172ea60e4SPhilippe Mathieu-Daudé /*
272ea60e4SPhilippe Mathieu-Daudé * QEMU Floppy disk emulator (Intel 82078)
372ea60e4SPhilippe Mathieu-Daudé *
472ea60e4SPhilippe Mathieu-Daudé * Copyright (c) 2003, 2007 Jocelyn Mayer
572ea60e4SPhilippe Mathieu-Daudé * Copyright (c) 2008 Hervé Poussineau
672ea60e4SPhilippe Mathieu-Daudé *
772ea60e4SPhilippe Mathieu-Daudé * Permission is hereby granted, free of charge, to any person obtaining a copy
872ea60e4SPhilippe Mathieu-Daudé * of this software and associated documentation files (the "Software"), to deal
972ea60e4SPhilippe Mathieu-Daudé * in the Software without restriction, including without limitation the rights
1072ea60e4SPhilippe Mathieu-Daudé * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1172ea60e4SPhilippe Mathieu-Daudé * copies of the Software, and to permit persons to whom the Software is
1272ea60e4SPhilippe Mathieu-Daudé * furnished to do so, subject to the following conditions:
1372ea60e4SPhilippe Mathieu-Daudé *
1472ea60e4SPhilippe Mathieu-Daudé * The above copyright notice and this permission notice shall be included in
1572ea60e4SPhilippe Mathieu-Daudé * all copies or substantial portions of the Software.
1672ea60e4SPhilippe Mathieu-Daudé *
1772ea60e4SPhilippe Mathieu-Daudé * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1872ea60e4SPhilippe Mathieu-Daudé * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1972ea60e4SPhilippe Mathieu-Daudé * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2072ea60e4SPhilippe Mathieu-Daudé * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2172ea60e4SPhilippe Mathieu-Daudé * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2272ea60e4SPhilippe Mathieu-Daudé * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2372ea60e4SPhilippe Mathieu-Daudé * THE SOFTWARE.
2472ea60e4SPhilippe Mathieu-Daudé */
2572ea60e4SPhilippe Mathieu-Daudé /*
2672ea60e4SPhilippe Mathieu-Daudé * The controller is used in Sun4m systems in a slightly different
2772ea60e4SPhilippe Mathieu-Daudé * way. There are changes in DOR register and DMA is not available.
2872ea60e4SPhilippe Mathieu-Daudé */
2972ea60e4SPhilippe Mathieu-Daudé
3072ea60e4SPhilippe Mathieu-Daudé #include "qemu/osdep.h"
3172ea60e4SPhilippe Mathieu-Daudé #include "hw/block/fdc.h"
3272ea60e4SPhilippe Mathieu-Daudé #include "qapi/error.h"
3372ea60e4SPhilippe Mathieu-Daudé #include "qemu/error-report.h"
3472ea60e4SPhilippe Mathieu-Daudé #include "qemu/timer.h"
35e7c72a67SIgor Mammedov #include "hw/acpi/acpi_aml_interface.h"
3672ea60e4SPhilippe Mathieu-Daudé #include "hw/irq.h"
3772ea60e4SPhilippe Mathieu-Daudé #include "hw/isa/isa.h"
3872ea60e4SPhilippe Mathieu-Daudé #include "hw/qdev-properties.h"
3972ea60e4SPhilippe Mathieu-Daudé #include "hw/qdev-properties-system.h"
4072ea60e4SPhilippe Mathieu-Daudé #include "migration/vmstate.h"
4172ea60e4SPhilippe Mathieu-Daudé #include "hw/block/block.h"
4272ea60e4SPhilippe Mathieu-Daudé #include "sysemu/block-backend.h"
4372ea60e4SPhilippe Mathieu-Daudé #include "sysemu/blockdev.h"
4472ea60e4SPhilippe Mathieu-Daudé #include "sysemu/sysemu.h"
45271c5bb3SBernhard Beschow #include "exec/ioport.h"
4672ea60e4SPhilippe Mathieu-Daudé #include "qemu/log.h"
4772ea60e4SPhilippe Mathieu-Daudé #include "qemu/main-loop.h"
4872ea60e4SPhilippe Mathieu-Daudé #include "qemu/module.h"
4972ea60e4SPhilippe Mathieu-Daudé #include "trace.h"
5072ea60e4SPhilippe Mathieu-Daudé #include "qom/object.h"
5172ea60e4SPhilippe Mathieu-Daudé #include "fdc-internal.h"
5272ea60e4SPhilippe Mathieu-Daudé
5372ea60e4SPhilippe Mathieu-Daudé OBJECT_DECLARE_SIMPLE_TYPE(FDCtrlISABus, ISA_FDC)
5472ea60e4SPhilippe Mathieu-Daudé
5572ea60e4SPhilippe Mathieu-Daudé struct FDCtrlISABus {
5672ea60e4SPhilippe Mathieu-Daudé /*< private >*/
5772ea60e4SPhilippe Mathieu-Daudé ISADevice parent_obj;
5872ea60e4SPhilippe Mathieu-Daudé /*< public >*/
5972ea60e4SPhilippe Mathieu-Daudé
6072ea60e4SPhilippe Mathieu-Daudé uint32_t iobase;
6172ea60e4SPhilippe Mathieu-Daudé uint32_t irq;
6272ea60e4SPhilippe Mathieu-Daudé uint32_t dma;
6372ea60e4SPhilippe Mathieu-Daudé struct FDCtrl state;
64271c5bb3SBernhard Beschow PortioList portio_list;
6572ea60e4SPhilippe Mathieu-Daudé int32_t bootindexA;
6672ea60e4SPhilippe Mathieu-Daudé int32_t bootindexB;
6772ea60e4SPhilippe Mathieu-Daudé };
6872ea60e4SPhilippe Mathieu-Daudé
fdctrl_external_reset_isa(DeviceState * d)6972ea60e4SPhilippe Mathieu-Daudé static void fdctrl_external_reset_isa(DeviceState *d)
7072ea60e4SPhilippe Mathieu-Daudé {
7172ea60e4SPhilippe Mathieu-Daudé FDCtrlISABus *isa = ISA_FDC(d);
7272ea60e4SPhilippe Mathieu-Daudé FDCtrl *s = &isa->state;
7372ea60e4SPhilippe Mathieu-Daudé
7472ea60e4SPhilippe Mathieu-Daudé fdctrl_reset(s, 0);
7572ea60e4SPhilippe Mathieu-Daudé }
7672ea60e4SPhilippe Mathieu-Daudé
isa_fdc_init_drives(ISADevice * fdc,DriveInfo ** fds)7772ea60e4SPhilippe Mathieu-Daudé void isa_fdc_init_drives(ISADevice *fdc, DriveInfo **fds)
7872ea60e4SPhilippe Mathieu-Daudé {
7972ea60e4SPhilippe Mathieu-Daudé fdctrl_init_drives(&ISA_FDC(fdc)->state.bus, fds);
8072ea60e4SPhilippe Mathieu-Daudé }
8172ea60e4SPhilippe Mathieu-Daudé
8272ea60e4SPhilippe Mathieu-Daudé static const MemoryRegionPortio fdc_portio_list[] = {
8372ea60e4SPhilippe Mathieu-Daudé { 1, 5, 1, .read = fdctrl_read, .write = fdctrl_write },
8472ea60e4SPhilippe Mathieu-Daudé { 7, 1, 1, .read = fdctrl_read, .write = fdctrl_write },
8572ea60e4SPhilippe Mathieu-Daudé PORTIO_END_OF_LIST(),
8672ea60e4SPhilippe Mathieu-Daudé };
8772ea60e4SPhilippe Mathieu-Daudé
isabus_fdc_realize(DeviceState * dev,Error ** errp)8872ea60e4SPhilippe Mathieu-Daudé static void isabus_fdc_realize(DeviceState *dev, Error **errp)
8972ea60e4SPhilippe Mathieu-Daudé {
9072ea60e4SPhilippe Mathieu-Daudé ISADevice *isadev = ISA_DEVICE(dev);
918e7db8abSPhilippe Mathieu-Daudé ISABus *bus = isa_bus_from_device(isadev);
9272ea60e4SPhilippe Mathieu-Daudé FDCtrlISABus *isa = ISA_FDC(dev);
9372ea60e4SPhilippe Mathieu-Daudé FDCtrl *fdctrl = &isa->state;
9472ea60e4SPhilippe Mathieu-Daudé Error *err = NULL;
9572ea60e4SPhilippe Mathieu-Daudé
96271c5bb3SBernhard Beschow isa_register_portio_list(isadev, &isa->portio_list,
9772ea60e4SPhilippe Mathieu-Daudé isa->iobase, fdc_portio_list, fdctrl,
9872ea60e4SPhilippe Mathieu-Daudé "fdc");
9972ea60e4SPhilippe Mathieu-Daudé
1008e7db8abSPhilippe Mathieu-Daudé fdctrl->irq = isa_bus_get_irq(bus, isa->irq);
10172ea60e4SPhilippe Mathieu-Daudé fdctrl->dma_chann = isa->dma;
10272ea60e4SPhilippe Mathieu-Daudé if (fdctrl->dma_chann != -1) {
10372ea60e4SPhilippe Mathieu-Daudé IsaDmaClass *k;
1048e7db8abSPhilippe Mathieu-Daudé fdctrl->dma = isa_bus_get_dma(bus, isa->dma);
10572ea60e4SPhilippe Mathieu-Daudé if (!fdctrl->dma) {
10672ea60e4SPhilippe Mathieu-Daudé error_setg(errp, "ISA controller does not support DMA");
10772ea60e4SPhilippe Mathieu-Daudé return;
10872ea60e4SPhilippe Mathieu-Daudé }
10972ea60e4SPhilippe Mathieu-Daudé k = ISADMA_GET_CLASS(fdctrl->dma);
11072ea60e4SPhilippe Mathieu-Daudé k->register_channel(fdctrl->dma, fdctrl->dma_chann,
11172ea60e4SPhilippe Mathieu-Daudé &fdctrl_transfer_handler, fdctrl);
11272ea60e4SPhilippe Mathieu-Daudé }
11372ea60e4SPhilippe Mathieu-Daudé
11472ea60e4SPhilippe Mathieu-Daudé qdev_set_legacy_instance_id(dev, isa->iobase, 2);
11572ea60e4SPhilippe Mathieu-Daudé
11672ea60e4SPhilippe Mathieu-Daudé fdctrl_realize_common(dev, fdctrl, &err);
11772ea60e4SPhilippe Mathieu-Daudé if (err != NULL) {
11872ea60e4SPhilippe Mathieu-Daudé error_propagate(errp, err);
11972ea60e4SPhilippe Mathieu-Daudé return;
12072ea60e4SPhilippe Mathieu-Daudé }
12172ea60e4SPhilippe Mathieu-Daudé }
12272ea60e4SPhilippe Mathieu-Daudé
isa_fdc_get_drive_type(ISADevice * fdc,int i)12372ea60e4SPhilippe Mathieu-Daudé FloppyDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i)
12472ea60e4SPhilippe Mathieu-Daudé {
12572ea60e4SPhilippe Mathieu-Daudé FDCtrlISABus *isa = ISA_FDC(fdc);
12672ea60e4SPhilippe Mathieu-Daudé
12772ea60e4SPhilippe Mathieu-Daudé return isa->state.drives[i].drive;
12872ea60e4SPhilippe Mathieu-Daudé }
12972ea60e4SPhilippe Mathieu-Daudé
isa_fdc_get_drive_max_chs(FloppyDriveType type,uint8_t * maxc,uint8_t * maxh,uint8_t * maxs)13072ea60e4SPhilippe Mathieu-Daudé static void isa_fdc_get_drive_max_chs(FloppyDriveType type, uint8_t *maxc,
13172ea60e4SPhilippe Mathieu-Daudé uint8_t *maxh, uint8_t *maxs)
13272ea60e4SPhilippe Mathieu-Daudé {
13372ea60e4SPhilippe Mathieu-Daudé const FDFormat *fdf;
13472ea60e4SPhilippe Mathieu-Daudé
13572ea60e4SPhilippe Mathieu-Daudé *maxc = *maxh = *maxs = 0;
13672ea60e4SPhilippe Mathieu-Daudé for (fdf = fd_formats; fdf->drive != FLOPPY_DRIVE_TYPE_NONE; fdf++) {
13772ea60e4SPhilippe Mathieu-Daudé if (fdf->drive != type) {
13872ea60e4SPhilippe Mathieu-Daudé continue;
13972ea60e4SPhilippe Mathieu-Daudé }
14072ea60e4SPhilippe Mathieu-Daudé if (*maxc < fdf->max_track) {
14172ea60e4SPhilippe Mathieu-Daudé *maxc = fdf->max_track;
14272ea60e4SPhilippe Mathieu-Daudé }
14372ea60e4SPhilippe Mathieu-Daudé if (*maxh < fdf->max_head) {
14472ea60e4SPhilippe Mathieu-Daudé *maxh = fdf->max_head;
14572ea60e4SPhilippe Mathieu-Daudé }
14672ea60e4SPhilippe Mathieu-Daudé if (*maxs < fdf->last_sect) {
14772ea60e4SPhilippe Mathieu-Daudé *maxs = fdf->last_sect;
14872ea60e4SPhilippe Mathieu-Daudé }
14972ea60e4SPhilippe Mathieu-Daudé }
15011b46661SPeter Maydell /* fd_formats must contain at least one entry per FloppyDriveType */
15111b46661SPeter Maydell assert(*maxc);
15272ea60e4SPhilippe Mathieu-Daudé (*maxc)--;
15372ea60e4SPhilippe Mathieu-Daudé }
15472ea60e4SPhilippe Mathieu-Daudé
build_fdinfo_aml(int idx,FloppyDriveType type)15572ea60e4SPhilippe Mathieu-Daudé static Aml *build_fdinfo_aml(int idx, FloppyDriveType type)
15672ea60e4SPhilippe Mathieu-Daudé {
15772ea60e4SPhilippe Mathieu-Daudé Aml *dev, *fdi;
15872ea60e4SPhilippe Mathieu-Daudé uint8_t maxc, maxh, maxs;
15972ea60e4SPhilippe Mathieu-Daudé
16072ea60e4SPhilippe Mathieu-Daudé isa_fdc_get_drive_max_chs(type, &maxc, &maxh, &maxs);
16172ea60e4SPhilippe Mathieu-Daudé
16272ea60e4SPhilippe Mathieu-Daudé dev = aml_device("FLP%c", 'A' + idx);
16372ea60e4SPhilippe Mathieu-Daudé
16472ea60e4SPhilippe Mathieu-Daudé aml_append(dev, aml_name_decl("_ADR", aml_int(idx)));
16572ea60e4SPhilippe Mathieu-Daudé
16672ea60e4SPhilippe Mathieu-Daudé fdi = aml_package(16);
16772ea60e4SPhilippe Mathieu-Daudé aml_append(fdi, aml_int(idx)); /* Drive Number */
16872ea60e4SPhilippe Mathieu-Daudé aml_append(fdi,
16972ea60e4SPhilippe Mathieu-Daudé aml_int(cmos_get_fd_drive_type(type))); /* Device Type */
17072ea60e4SPhilippe Mathieu-Daudé /*
17172ea60e4SPhilippe Mathieu-Daudé * the values below are the limits of the drive, and are thus independent
17272ea60e4SPhilippe Mathieu-Daudé * of the inserted media
17372ea60e4SPhilippe Mathieu-Daudé */
17472ea60e4SPhilippe Mathieu-Daudé aml_append(fdi, aml_int(maxc)); /* Maximum Cylinder Number */
17572ea60e4SPhilippe Mathieu-Daudé aml_append(fdi, aml_int(maxs)); /* Maximum Sector Number */
17672ea60e4SPhilippe Mathieu-Daudé aml_append(fdi, aml_int(maxh)); /* Maximum Head Number */
17772ea60e4SPhilippe Mathieu-Daudé /*
17872ea60e4SPhilippe Mathieu-Daudé * SeaBIOS returns the below values for int 0x13 func 0x08 regardless of
17972ea60e4SPhilippe Mathieu-Daudé * the drive type, so shall we
18072ea60e4SPhilippe Mathieu-Daudé */
18172ea60e4SPhilippe Mathieu-Daudé aml_append(fdi, aml_int(0xAF)); /* disk_specify_1 */
18272ea60e4SPhilippe Mathieu-Daudé aml_append(fdi, aml_int(0x02)); /* disk_specify_2 */
18372ea60e4SPhilippe Mathieu-Daudé aml_append(fdi, aml_int(0x25)); /* disk_motor_wait */
18472ea60e4SPhilippe Mathieu-Daudé aml_append(fdi, aml_int(0x02)); /* disk_sector_siz */
18572ea60e4SPhilippe Mathieu-Daudé aml_append(fdi, aml_int(0x12)); /* disk_eot */
18672ea60e4SPhilippe Mathieu-Daudé aml_append(fdi, aml_int(0x1B)); /* disk_rw_gap */
18772ea60e4SPhilippe Mathieu-Daudé aml_append(fdi, aml_int(0xFF)); /* disk_dtl */
18872ea60e4SPhilippe Mathieu-Daudé aml_append(fdi, aml_int(0x6C)); /* disk_formt_gap */
18972ea60e4SPhilippe Mathieu-Daudé aml_append(fdi, aml_int(0xF6)); /* disk_fill */
19072ea60e4SPhilippe Mathieu-Daudé aml_append(fdi, aml_int(0x0F)); /* disk_head_sttl */
19172ea60e4SPhilippe Mathieu-Daudé aml_append(fdi, aml_int(0x08)); /* disk_motor_strt */
19272ea60e4SPhilippe Mathieu-Daudé
19372ea60e4SPhilippe Mathieu-Daudé aml_append(dev, aml_name_decl("_FDI", fdi));
19472ea60e4SPhilippe Mathieu-Daudé return dev;
19572ea60e4SPhilippe Mathieu-Daudé }
19672ea60e4SPhilippe Mathieu-Daudé
isa_fdc_set_iobase(ISADevice * fdc,hwaddr iobase)1978c4d2391SBernhard Beschow void isa_fdc_set_iobase(ISADevice *fdc, hwaddr iobase)
1988c4d2391SBernhard Beschow {
1998c4d2391SBernhard Beschow FDCtrlISABus *isa = ISA_FDC(fdc);
2008c4d2391SBernhard Beschow
2018c4d2391SBernhard Beschow fdc->ioport_id = iobase;
2028c4d2391SBernhard Beschow isa->iobase = iobase;
2038c4d2391SBernhard Beschow portio_list_set_address(&isa->portio_list, isa->iobase);
2048c4d2391SBernhard Beschow }
2058c4d2391SBernhard Beschow
isa_fdc_set_enabled(ISADevice * fdc,bool enabled)2068c4d2391SBernhard Beschow void isa_fdc_set_enabled(ISADevice *fdc, bool enabled)
2078c4d2391SBernhard Beschow {
2088c4d2391SBernhard Beschow portio_list_set_enabled(&ISA_FDC(fdc)->portio_list, enabled);
2098c4d2391SBernhard Beschow }
2108c4d2391SBernhard Beschow
cmos_get_fd_drive_type(FloppyDriveType fd0)21172ea60e4SPhilippe Mathieu-Daudé int cmos_get_fd_drive_type(FloppyDriveType fd0)
21272ea60e4SPhilippe Mathieu-Daudé {
21372ea60e4SPhilippe Mathieu-Daudé int val;
21472ea60e4SPhilippe Mathieu-Daudé
21572ea60e4SPhilippe Mathieu-Daudé switch (fd0) {
21672ea60e4SPhilippe Mathieu-Daudé case FLOPPY_DRIVE_TYPE_144:
21772ea60e4SPhilippe Mathieu-Daudé /* 1.44 Mb 3"5 drive */
21872ea60e4SPhilippe Mathieu-Daudé val = 4;
21972ea60e4SPhilippe Mathieu-Daudé break;
22072ea60e4SPhilippe Mathieu-Daudé case FLOPPY_DRIVE_TYPE_288:
22172ea60e4SPhilippe Mathieu-Daudé /* 2.88 Mb 3"5 drive */
22272ea60e4SPhilippe Mathieu-Daudé val = 5;
22372ea60e4SPhilippe Mathieu-Daudé break;
22472ea60e4SPhilippe Mathieu-Daudé case FLOPPY_DRIVE_TYPE_120:
22572ea60e4SPhilippe Mathieu-Daudé /* 1.2 Mb 5"5 drive */
22672ea60e4SPhilippe Mathieu-Daudé val = 2;
22772ea60e4SPhilippe Mathieu-Daudé break;
22872ea60e4SPhilippe Mathieu-Daudé case FLOPPY_DRIVE_TYPE_NONE:
22972ea60e4SPhilippe Mathieu-Daudé default:
23072ea60e4SPhilippe Mathieu-Daudé val = 0;
23172ea60e4SPhilippe Mathieu-Daudé break;
23272ea60e4SPhilippe Mathieu-Daudé }
23372ea60e4SPhilippe Mathieu-Daudé return val;
23472ea60e4SPhilippe Mathieu-Daudé }
23572ea60e4SPhilippe Mathieu-Daudé
build_fdc_aml(AcpiDevAmlIf * adev,Aml * scope)236e7c72a67SIgor Mammedov static void build_fdc_aml(AcpiDevAmlIf *adev, Aml *scope)
23772ea60e4SPhilippe Mathieu-Daudé {
238e7c72a67SIgor Mammedov FDCtrlISABus *isa = ISA_FDC(adev);
23972ea60e4SPhilippe Mathieu-Daudé Aml *dev;
24072ea60e4SPhilippe Mathieu-Daudé Aml *crs;
24172ea60e4SPhilippe Mathieu-Daudé int i;
24272ea60e4SPhilippe Mathieu-Daudé
24372ea60e4SPhilippe Mathieu-Daudé #define ACPI_FDE_MAX_FD 4
24472ea60e4SPhilippe Mathieu-Daudé uint32_t fde_buf[5] = {
24572ea60e4SPhilippe Mathieu-Daudé 0, 0, 0, 0, /* presence of floppy drives #0 - #3 */
24672ea60e4SPhilippe Mathieu-Daudé cpu_to_le32(2) /* tape presence (2 == never present) */
24772ea60e4SPhilippe Mathieu-Daudé };
24872ea60e4SPhilippe Mathieu-Daudé
24972ea60e4SPhilippe Mathieu-Daudé crs = aml_resource_template();
25072ea60e4SPhilippe Mathieu-Daudé aml_append(crs,
251fdb8541bSBernhard Beschow aml_io(AML_DECODE16, isa->iobase + 2, isa->iobase + 2, 0x00, 0x04));
252fdb8541bSBernhard Beschow aml_append(crs,
253fdb8541bSBernhard Beschow aml_io(AML_DECODE16, isa->iobase + 7, isa->iobase + 7, 0x00, 0x01));
254fdb8541bSBernhard Beschow aml_append(crs, aml_irq_no_flags(isa->irq));
255fdb8541bSBernhard Beschow aml_append(crs,
256fdb8541bSBernhard Beschow aml_dma(AML_COMPATIBILITY, AML_NOTBUSMASTER, AML_TRANSFER8, isa->dma));
25772ea60e4SPhilippe Mathieu-Daudé
25872ea60e4SPhilippe Mathieu-Daudé dev = aml_device("FDC0");
25972ea60e4SPhilippe Mathieu-Daudé aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0700")));
26072ea60e4SPhilippe Mathieu-Daudé aml_append(dev, aml_name_decl("_CRS", crs));
26172ea60e4SPhilippe Mathieu-Daudé
26272ea60e4SPhilippe Mathieu-Daudé for (i = 0; i < MIN(MAX_FD, ACPI_FDE_MAX_FD); i++) {
263e7c72a67SIgor Mammedov FloppyDriveType type = isa_fdc_get_drive_type(ISA_DEVICE(adev), i);
26472ea60e4SPhilippe Mathieu-Daudé
26572ea60e4SPhilippe Mathieu-Daudé if (type < FLOPPY_DRIVE_TYPE_NONE) {
26672ea60e4SPhilippe Mathieu-Daudé fde_buf[i] = cpu_to_le32(1); /* drive present */
26772ea60e4SPhilippe Mathieu-Daudé aml_append(dev, build_fdinfo_aml(i, type));
26872ea60e4SPhilippe Mathieu-Daudé }
26972ea60e4SPhilippe Mathieu-Daudé }
27072ea60e4SPhilippe Mathieu-Daudé aml_append(dev, aml_name_decl("_FDE",
27172ea60e4SPhilippe Mathieu-Daudé aml_buffer(sizeof(fde_buf), (uint8_t *)fde_buf)));
27272ea60e4SPhilippe Mathieu-Daudé
27372ea60e4SPhilippe Mathieu-Daudé aml_append(scope, dev);
27472ea60e4SPhilippe Mathieu-Daudé }
27572ea60e4SPhilippe Mathieu-Daudé
27672ea60e4SPhilippe Mathieu-Daudé static const VMStateDescription vmstate_isa_fdc = {
27772ea60e4SPhilippe Mathieu-Daudé .name = "fdc",
27872ea60e4SPhilippe Mathieu-Daudé .version_id = 2,
27972ea60e4SPhilippe Mathieu-Daudé .minimum_version_id = 2,
2807d5dc0a3SRichard Henderson .fields = (const VMStateField[]) {
28172ea60e4SPhilippe Mathieu-Daudé VMSTATE_STRUCT(state, FDCtrlISABus, 0, vmstate_fdc, FDCtrl),
28272ea60e4SPhilippe Mathieu-Daudé VMSTATE_END_OF_LIST()
28372ea60e4SPhilippe Mathieu-Daudé }
28472ea60e4SPhilippe Mathieu-Daudé };
28572ea60e4SPhilippe Mathieu-Daudé
28672ea60e4SPhilippe Mathieu-Daudé static Property isa_fdc_properties[] = {
28772ea60e4SPhilippe Mathieu-Daudé DEFINE_PROP_UINT32("iobase", FDCtrlISABus, iobase, 0x3f0),
28872ea60e4SPhilippe Mathieu-Daudé DEFINE_PROP_UINT32("irq", FDCtrlISABus, irq, 6),
28972ea60e4SPhilippe Mathieu-Daudé DEFINE_PROP_UINT32("dma", FDCtrlISABus, dma, 2),
29072ea60e4SPhilippe Mathieu-Daudé DEFINE_PROP_SIGNED("fdtypeA", FDCtrlISABus, state.qdev_for_drives[0].type,
29172ea60e4SPhilippe Mathieu-Daudé FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
29272ea60e4SPhilippe Mathieu-Daudé FloppyDriveType),
29372ea60e4SPhilippe Mathieu-Daudé DEFINE_PROP_SIGNED("fdtypeB", FDCtrlISABus, state.qdev_for_drives[1].type,
29472ea60e4SPhilippe Mathieu-Daudé FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
29572ea60e4SPhilippe Mathieu-Daudé FloppyDriveType),
29672ea60e4SPhilippe Mathieu-Daudé DEFINE_PROP_SIGNED("fallback", FDCtrlISABus, state.fallback,
29772ea60e4SPhilippe Mathieu-Daudé FLOPPY_DRIVE_TYPE_288, qdev_prop_fdc_drive_type,
29872ea60e4SPhilippe Mathieu-Daudé FloppyDriveType),
29972ea60e4SPhilippe Mathieu-Daudé DEFINE_PROP_END_OF_LIST(),
30072ea60e4SPhilippe Mathieu-Daudé };
30172ea60e4SPhilippe Mathieu-Daudé
isabus_fdc_class_init(ObjectClass * klass,void * data)30272ea60e4SPhilippe Mathieu-Daudé static void isabus_fdc_class_init(ObjectClass *klass, void *data)
30372ea60e4SPhilippe Mathieu-Daudé {
30472ea60e4SPhilippe Mathieu-Daudé DeviceClass *dc = DEVICE_CLASS(klass);
305e7c72a67SIgor Mammedov AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
30672ea60e4SPhilippe Mathieu-Daudé
3079362984fSPhilippe Mathieu-Daudé dc->desc = "virtual floppy controller";
30872ea60e4SPhilippe Mathieu-Daudé dc->realize = isabus_fdc_realize;
30972ea60e4SPhilippe Mathieu-Daudé dc->fw_name = "fdc";
310*e3d08143SPeter Maydell device_class_set_legacy_reset(dc, fdctrl_external_reset_isa);
31172ea60e4SPhilippe Mathieu-Daudé dc->vmsd = &vmstate_isa_fdc;
312e7c72a67SIgor Mammedov adevc->build_dev_aml = build_fdc_aml;
31372ea60e4SPhilippe Mathieu-Daudé device_class_set_props(dc, isa_fdc_properties);
31472ea60e4SPhilippe Mathieu-Daudé set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
31572ea60e4SPhilippe Mathieu-Daudé }
31672ea60e4SPhilippe Mathieu-Daudé
isabus_fdc_instance_init(Object * obj)31772ea60e4SPhilippe Mathieu-Daudé static void isabus_fdc_instance_init(Object *obj)
31872ea60e4SPhilippe Mathieu-Daudé {
31972ea60e4SPhilippe Mathieu-Daudé FDCtrlISABus *isa = ISA_FDC(obj);
32072ea60e4SPhilippe Mathieu-Daudé
32172ea60e4SPhilippe Mathieu-Daudé device_add_bootindex_property(obj, &isa->bootindexA,
32272ea60e4SPhilippe Mathieu-Daudé "bootindexA", "/floppy@0",
32372ea60e4SPhilippe Mathieu-Daudé DEVICE(obj));
32472ea60e4SPhilippe Mathieu-Daudé device_add_bootindex_property(obj, &isa->bootindexB,
32572ea60e4SPhilippe Mathieu-Daudé "bootindexB", "/floppy@1",
32672ea60e4SPhilippe Mathieu-Daudé DEVICE(obj));
32772ea60e4SPhilippe Mathieu-Daudé }
32872ea60e4SPhilippe Mathieu-Daudé
32972ea60e4SPhilippe Mathieu-Daudé static const TypeInfo isa_fdc_info = {
33072ea60e4SPhilippe Mathieu-Daudé .name = TYPE_ISA_FDC,
33172ea60e4SPhilippe Mathieu-Daudé .parent = TYPE_ISA_DEVICE,
33272ea60e4SPhilippe Mathieu-Daudé .instance_size = sizeof(FDCtrlISABus),
33372ea60e4SPhilippe Mathieu-Daudé .class_init = isabus_fdc_class_init,
33472ea60e4SPhilippe Mathieu-Daudé .instance_init = isabus_fdc_instance_init,
335e7c72a67SIgor Mammedov .interfaces = (InterfaceInfo[]) {
336e7c72a67SIgor Mammedov { TYPE_ACPI_DEV_AML_IF },
337e7c72a67SIgor Mammedov { },
338e7c72a67SIgor Mammedov },
33972ea60e4SPhilippe Mathieu-Daudé };
34072ea60e4SPhilippe Mathieu-Daudé
isa_fdc_register_types(void)34172ea60e4SPhilippe Mathieu-Daudé static void isa_fdc_register_types(void)
34272ea60e4SPhilippe Mathieu-Daudé {
34372ea60e4SPhilippe Mathieu-Daudé type_register_static(&isa_fdc_info);
34472ea60e4SPhilippe Mathieu-Daudé }
34572ea60e4SPhilippe Mathieu-Daudé
34672ea60e4SPhilippe Mathieu-Daudé type_init(isa_fdc_register_types)
347