cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

fdc-isa.c (10114B)


      1/*
      2 * QEMU Floppy disk emulator (Intel 82078)
      3 *
      4 * Copyright (c) 2003, 2007 Jocelyn Mayer
      5 * Copyright (c) 2008 Hervé Poussineau
      6 *
      7 * Permission is hereby granted, free of charge, to any person obtaining a copy
      8 * of this software and associated documentation files (the "Software"), to deal
      9 * in the Software without restriction, including without limitation the rights
     10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     11 * copies of the Software, and to permit persons to whom the Software is
     12 * furnished to do so, subject to the following conditions:
     13 *
     14 * The above copyright notice and this permission notice shall be included in
     15 * all copies or substantial portions of the Software.
     16 *
     17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     23 * THE SOFTWARE.
     24 */
     25/*
     26 * The controller is used in Sun4m systems in a slightly different
     27 * way. There are changes in DOR register and DMA is not available.
     28 */
     29
     30#include "qemu/osdep.h"
     31#include "hw/block/fdc.h"
     32#include "qapi/error.h"
     33#include "qemu/error-report.h"
     34#include "qemu/timer.h"
     35#include "hw/acpi/aml-build.h"
     36#include "hw/irq.h"
     37#include "hw/isa/isa.h"
     38#include "hw/qdev-properties.h"
     39#include "hw/qdev-properties-system.h"
     40#include "migration/vmstate.h"
     41#include "hw/block/block.h"
     42#include "sysemu/block-backend.h"
     43#include "sysemu/blockdev.h"
     44#include "sysemu/sysemu.h"
     45#include "qemu/log.h"
     46#include "qemu/main-loop.h"
     47#include "qemu/module.h"
     48#include "trace.h"
     49#include "qom/object.h"
     50#include "fdc-internal.h"
     51
     52OBJECT_DECLARE_SIMPLE_TYPE(FDCtrlISABus, ISA_FDC)
     53
     54struct FDCtrlISABus {
     55    /*< private >*/
     56    ISADevice parent_obj;
     57    /*< public >*/
     58
     59    uint32_t iobase;
     60    uint32_t irq;
     61    uint32_t dma;
     62    struct FDCtrl state;
     63    int32_t bootindexA;
     64    int32_t bootindexB;
     65};
     66
     67static void fdctrl_external_reset_isa(DeviceState *d)
     68{
     69    FDCtrlISABus *isa = ISA_FDC(d);
     70    FDCtrl *s = &isa->state;
     71
     72    fdctrl_reset(s, 0);
     73}
     74
     75void isa_fdc_init_drives(ISADevice *fdc, DriveInfo **fds)
     76{
     77    fdctrl_init_drives(&ISA_FDC(fdc)->state.bus, fds);
     78}
     79
     80static const MemoryRegionPortio fdc_portio_list[] = {
     81    { 1, 5, 1, .read = fdctrl_read, .write = fdctrl_write },
     82    { 7, 1, 1, .read = fdctrl_read, .write = fdctrl_write },
     83    PORTIO_END_OF_LIST(),
     84};
     85
     86static void isabus_fdc_realize(DeviceState *dev, Error **errp)
     87{
     88    ISADevice *isadev = ISA_DEVICE(dev);
     89    FDCtrlISABus *isa = ISA_FDC(dev);
     90    FDCtrl *fdctrl = &isa->state;
     91    Error *err = NULL;
     92
     93    isa_register_portio_list(isadev, &fdctrl->portio_list,
     94                             isa->iobase, fdc_portio_list, fdctrl,
     95                             "fdc");
     96
     97    isa_init_irq(isadev, &fdctrl->irq, isa->irq);
     98    fdctrl->dma_chann = isa->dma;
     99    if (fdctrl->dma_chann != -1) {
    100        IsaDmaClass *k;
    101        fdctrl->dma = isa_get_dma(isa_bus_from_device(isadev), isa->dma);
    102        if (!fdctrl->dma) {
    103            error_setg(errp, "ISA controller does not support DMA");
    104            return;
    105        }
    106        k = ISADMA_GET_CLASS(fdctrl->dma);
    107        k->register_channel(fdctrl->dma, fdctrl->dma_chann,
    108                            &fdctrl_transfer_handler, fdctrl);
    109    }
    110
    111    qdev_set_legacy_instance_id(dev, isa->iobase, 2);
    112
    113    fdctrl_realize_common(dev, fdctrl, &err);
    114    if (err != NULL) {
    115        error_propagate(errp, err);
    116        return;
    117    }
    118}
    119
    120FloppyDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i)
    121{
    122    FDCtrlISABus *isa = ISA_FDC(fdc);
    123
    124    return isa->state.drives[i].drive;
    125}
    126
    127static void isa_fdc_get_drive_max_chs(FloppyDriveType type, uint8_t *maxc,
    128                                      uint8_t *maxh, uint8_t *maxs)
    129{
    130    const FDFormat *fdf;
    131
    132    *maxc = *maxh = *maxs = 0;
    133    for (fdf = fd_formats; fdf->drive != FLOPPY_DRIVE_TYPE_NONE; fdf++) {
    134        if (fdf->drive != type) {
    135            continue;
    136        }
    137        if (*maxc < fdf->max_track) {
    138            *maxc = fdf->max_track;
    139        }
    140        if (*maxh < fdf->max_head) {
    141            *maxh = fdf->max_head;
    142        }
    143        if (*maxs < fdf->last_sect) {
    144            *maxs = fdf->last_sect;
    145        }
    146    }
    147    (*maxc)--;
    148}
    149
    150static Aml *build_fdinfo_aml(int idx, FloppyDriveType type)
    151{
    152    Aml *dev, *fdi;
    153    uint8_t maxc, maxh, maxs;
    154
    155    isa_fdc_get_drive_max_chs(type, &maxc, &maxh, &maxs);
    156
    157    dev = aml_device("FLP%c", 'A' + idx);
    158
    159    aml_append(dev, aml_name_decl("_ADR", aml_int(idx)));
    160
    161    fdi = aml_package(16);
    162    aml_append(fdi, aml_int(idx));  /* Drive Number */
    163    aml_append(fdi,
    164        aml_int(cmos_get_fd_drive_type(type)));  /* Device Type */
    165    /*
    166     * the values below are the limits of the drive, and are thus independent
    167     * of the inserted media
    168     */
    169    aml_append(fdi, aml_int(maxc));  /* Maximum Cylinder Number */
    170    aml_append(fdi, aml_int(maxs));  /* Maximum Sector Number */
    171    aml_append(fdi, aml_int(maxh));  /* Maximum Head Number */
    172    /*
    173     * SeaBIOS returns the below values for int 0x13 func 0x08 regardless of
    174     * the drive type, so shall we
    175     */
    176    aml_append(fdi, aml_int(0xAF));  /* disk_specify_1 */
    177    aml_append(fdi, aml_int(0x02));  /* disk_specify_2 */
    178    aml_append(fdi, aml_int(0x25));  /* disk_motor_wait */
    179    aml_append(fdi, aml_int(0x02));  /* disk_sector_siz */
    180    aml_append(fdi, aml_int(0x12));  /* disk_eot */
    181    aml_append(fdi, aml_int(0x1B));  /* disk_rw_gap */
    182    aml_append(fdi, aml_int(0xFF));  /* disk_dtl */
    183    aml_append(fdi, aml_int(0x6C));  /* disk_formt_gap */
    184    aml_append(fdi, aml_int(0xF6));  /* disk_fill */
    185    aml_append(fdi, aml_int(0x0F));  /* disk_head_sttl */
    186    aml_append(fdi, aml_int(0x08));  /* disk_motor_strt */
    187
    188    aml_append(dev, aml_name_decl("_FDI", fdi));
    189    return dev;
    190}
    191
    192int cmos_get_fd_drive_type(FloppyDriveType fd0)
    193{
    194    int val;
    195
    196    switch (fd0) {
    197    case FLOPPY_DRIVE_TYPE_144:
    198        /* 1.44 Mb 3"5 drive */
    199        val = 4;
    200        break;
    201    case FLOPPY_DRIVE_TYPE_288:
    202        /* 2.88 Mb 3"5 drive */
    203        val = 5;
    204        break;
    205    case FLOPPY_DRIVE_TYPE_120:
    206        /* 1.2 Mb 5"5 drive */
    207        val = 2;
    208        break;
    209    case FLOPPY_DRIVE_TYPE_NONE:
    210    default:
    211        val = 0;
    212        break;
    213    }
    214    return val;
    215}
    216
    217static void fdc_isa_build_aml(ISADevice *isadev, Aml *scope)
    218{
    219    Aml *dev;
    220    Aml *crs;
    221    int i;
    222
    223#define ACPI_FDE_MAX_FD 4
    224    uint32_t fde_buf[5] = {
    225        0, 0, 0, 0,     /* presence of floppy drives #0 - #3 */
    226        cpu_to_le32(2)  /* tape presence (2 == never present) */
    227    };
    228
    229    crs = aml_resource_template();
    230    aml_append(crs, aml_io(AML_DECODE16, 0x03F2, 0x03F2, 0x00, 0x04));
    231    aml_append(crs, aml_io(AML_DECODE16, 0x03F7, 0x03F7, 0x00, 0x01));
    232    aml_append(crs, aml_irq_no_flags(6));
    233    aml_append(crs,
    234        aml_dma(AML_COMPATIBILITY, AML_NOTBUSMASTER, AML_TRANSFER8, 2));
    235
    236    dev = aml_device("FDC0");
    237    aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0700")));
    238    aml_append(dev, aml_name_decl("_CRS", crs));
    239
    240    for (i = 0; i < MIN(MAX_FD, ACPI_FDE_MAX_FD); i++) {
    241        FloppyDriveType type = isa_fdc_get_drive_type(isadev, i);
    242
    243        if (type < FLOPPY_DRIVE_TYPE_NONE) {
    244            fde_buf[i] = cpu_to_le32(1);  /* drive present */
    245            aml_append(dev, build_fdinfo_aml(i, type));
    246        }
    247    }
    248    aml_append(dev, aml_name_decl("_FDE",
    249               aml_buffer(sizeof(fde_buf), (uint8_t *)fde_buf)));
    250
    251    aml_append(scope, dev);
    252}
    253
    254static const VMStateDescription vmstate_isa_fdc = {
    255    .name = "fdc",
    256    .version_id = 2,
    257    .minimum_version_id = 2,
    258    .fields = (VMStateField[]) {
    259        VMSTATE_STRUCT(state, FDCtrlISABus, 0, vmstate_fdc, FDCtrl),
    260        VMSTATE_END_OF_LIST()
    261    }
    262};
    263
    264static Property isa_fdc_properties[] = {
    265    DEFINE_PROP_UINT32("iobase", FDCtrlISABus, iobase, 0x3f0),
    266    DEFINE_PROP_UINT32("irq", FDCtrlISABus, irq, 6),
    267    DEFINE_PROP_UINT32("dma", FDCtrlISABus, dma, 2),
    268    DEFINE_PROP_SIGNED("fdtypeA", FDCtrlISABus, state.qdev_for_drives[0].type,
    269                        FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
    270                        FloppyDriveType),
    271    DEFINE_PROP_SIGNED("fdtypeB", FDCtrlISABus, state.qdev_for_drives[1].type,
    272                        FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
    273                        FloppyDriveType),
    274    DEFINE_PROP_SIGNED("fallback", FDCtrlISABus, state.fallback,
    275                        FLOPPY_DRIVE_TYPE_288, qdev_prop_fdc_drive_type,
    276                        FloppyDriveType),
    277    DEFINE_PROP_END_OF_LIST(),
    278};
    279
    280static void isabus_fdc_class_init(ObjectClass *klass, void *data)
    281{
    282    DeviceClass *dc = DEVICE_CLASS(klass);
    283    ISADeviceClass *isa = ISA_DEVICE_CLASS(klass);
    284
    285    dc->desc = "virtual floppy controller";
    286    dc->realize = isabus_fdc_realize;
    287    dc->fw_name = "fdc";
    288    dc->reset = fdctrl_external_reset_isa;
    289    dc->vmsd = &vmstate_isa_fdc;
    290    isa->build_aml = fdc_isa_build_aml;
    291    device_class_set_props(dc, isa_fdc_properties);
    292    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
    293}
    294
    295static void isabus_fdc_instance_init(Object *obj)
    296{
    297    FDCtrlISABus *isa = ISA_FDC(obj);
    298
    299    device_add_bootindex_property(obj, &isa->bootindexA,
    300                                  "bootindexA", "/floppy@0",
    301                                  DEVICE(obj));
    302    device_add_bootindex_property(obj, &isa->bootindexB,
    303                                  "bootindexB", "/floppy@1",
    304                                  DEVICE(obj));
    305}
    306
    307static const TypeInfo isa_fdc_info = {
    308    .name          = TYPE_ISA_FDC,
    309    .parent        = TYPE_ISA_DEVICE,
    310    .instance_size = sizeof(FDCtrlISABus),
    311    .class_init    = isabus_fdc_class_init,
    312    .instance_init = isabus_fdc_instance_init,
    313};
    314
    315static void isa_fdc_register_types(void)
    316{
    317    type_register_static(&isa_fdc_info);
    318}
    319
    320type_init(isa_fdc_register_types)