diff options
author | Marcelo Tosatti <mtosatti@redhat.com> | 2010-07-13 20:49:58 -0300 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2010-07-13 20:49:58 -0300 |
commit | f67f69139672068bf7f311ae1423d3a3fa97d007 (patch) | |
tree | a8415a1a65deff643f493093abcd7f03a3373cd4 /hw | |
parent | 496850369988be816680065e905edf74c7218b22 (diff) | |
parent | 498238687fd3a2bf3efb32694732f88ceac72e99 (diff) |
Merge commit '498238687fd3a2bf3efb32694732f88ceac72e99' into upstream-merge
* commit '498238687fd3a2bf3efb32694732f88ceac72e99': (28 commits)
pci: introduce multifunction property.
qdev: implement qdev_prop_set_bit().
pci: remove PCIDeviceInfo::header_type
pci: don't overwrite multi functio bit in pci header type.
pci: insert assert that auto-assigned-address function is single function device.
pci: use PCI_DEVFN() where appropriate.
target-mips: add loongson 2E & 2F integer instructions
Fix warning about uninitialized variable
sheepdog: fix compile error on systems without TCP_CORK
ramblocks: No more being lazy about duplicate names
pci: Free the space allocated for the option rom on removal
block: add sheepdog driver for distributed storage support
ide: Reject invalid CHS geometry
ide: Reject readonly drives unless CD-ROM
ide: Make ide_init_drive() return success
ide: Replace IDEState members is_cdrom, is_cf by drive_kind
ide: Improve error messages
scsi: Error locations for -drive if=scsi device initialization
error: New qemu_opts_loc_restore()
scsi: Reject unimplemented error actions
...
Conflicts:
hw/pci.c
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'hw')
40 files changed, 190 insertions, 91 deletions
@@ -1295,7 +1295,6 @@ static int ac97_initfn (PCIDevice *dev) c[PCI_REVISION_ID] = 0x01; /* rid revision ro */ c[PCI_CLASS_PROG] = 0x00; /* pi programming interface ro */ pci_config_set_class (c, PCI_CLASS_MULTIMEDIA_AUDIO); /* ro */ - c[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; /* headtyp header type ro */ /* TODO set when bar is registered. no need to override. */ /* nabmar native audio mixer base address rw */ diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 227aba8f2..882de96c1 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -376,7 +376,6 @@ static int piix4_pm_initfn(PCIDevice *dev) pci_conf[0x08] = 0x03; // revision number pci_conf[0x09] = 0x00; pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_OTHER); - pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type pci_conf[0x3d] = 0x01; // interrupt pin 1 pci_conf[0x40] = 0x01; /* PM io base read only bit */ diff --git a/hw/apb_pci.c b/hw/apb_pci.c index 31c8d705a..69a774d98 100644 --- a/hw/apb_pci.c +++ b/hw/apb_pci.c @@ -427,8 +427,6 @@ static int pbm_pci_host_init(PCIDevice *d) PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ | PCI_STATUS_DEVSEL_MEDIUM); pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST); - pci_set_byte(d->config + PCI_HEADER_TYPE, - PCI_HEADER_TYPE_NORMAL); return 0; } @@ -436,7 +434,7 @@ static PCIDeviceInfo pbm_pci_host_info = { .qdev.name = "pbm", .qdev.size = sizeof(PCIDevice), .init = pbm_pci_host_init, - .header_type = PCI_HEADER_TYPE_BRIDGE, + .is_bridge = 1, }; static SysBusDeviceInfo pbm_host_info = { diff --git a/hw/dec_pci.c b/hw/dec_pci.c index 024c67ce7..83ce4cd44 100644 --- a/hw/dec_pci.c +++ b/hw/dec_pci.c @@ -90,7 +90,7 @@ static PCIDeviceInfo dec_21154_pci_host_info = { .qdev.name = "dec-21154", .qdev.size = sizeof(PCIDevice), .init = dec_21154_pci_host_init, - .header_type = PCI_HEADER_TYPE_BRIDGE, + .is_bridge = 1, }; static void dec_register_devices(void) @@ -29,6 +29,7 @@ #include "hw.h" #include "fdc.h" +#include "qemu-error.h" #include "qemu-timer.h" #include "isa.h" #include "sysbus.h" @@ -1844,7 +1845,7 @@ static void fdctrl_result_timer(void *opaque) } /* Init functions */ -static void fdctrl_connect_drives(FDCtrl *fdctrl) +static int fdctrl_connect_drives(FDCtrl *fdctrl) { unsigned int i; FDrive *drive; @@ -1852,12 +1853,24 @@ static void fdctrl_connect_drives(FDCtrl *fdctrl) for (i = 0; i < MAX_FD; i++) { drive = &fdctrl->drives[i]; + if (drive->bs) { + if (bdrv_get_on_error(drive->bs, 0) != BLOCK_ERR_STOP_ENOSPC) { + error_report("fdc doesn't support drive option werror"); + return -1; + } + if (bdrv_get_on_error(drive->bs, 1) != BLOCK_ERR_REPORT) { + error_report("fdc doesn't support drive option rerror"); + return -1; + } + } + fd_init(drive); fd_revalidate(drive); if (drive->bs) { bdrv_set_removable(drive->bs, 1); } } + return 0; } FDCtrl *fdctrl_init_isa(DriveInfo **fds) @@ -1871,8 +1884,7 @@ FDCtrl *fdctrl_init_isa(DriveInfo **fds) if (fds[1]) { qdev_prop_set_drive_nofail(&dev->qdev, "driveB", fds[1]->bdrv); } - if (qdev_init(&dev->qdev) < 0) - return NULL; + qdev_init_nofail(&dev->qdev); return &(DO_UPCAST(FDCtrlISABus, busdev, dev)->state); } @@ -1950,9 +1962,7 @@ static int fdctrl_init_common(FDCtrl *fdctrl) if (fdctrl->dma_chann != -1) DMA_register_channel(fdctrl->dma_chann, &fdctrl_transfer_handler, fdctrl); - fdctrl_connect_drives(fdctrl); - - return 0; + return fdctrl_connect_drives(fdctrl); } static int isabus_fdc_init1(ISADevice *dev) diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c index 0cf29dc9d..91c755f4d 100644 --- a/hw/grackle_pci.c +++ b/hw/grackle_pci.c @@ -126,7 +126,6 @@ static int grackle_pci_host_init(PCIDevice *d) d->config[0x08] = 0x00; // revision d->config[0x09] = 0x01; pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST); - d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type return 0; } diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c index 313c08045..cabf7ea0b 100644 --- a/hw/gt64xxx.c +++ b/hw/gt64xxx.c @@ -1115,7 +1115,7 @@ PCIBus *pci_gt64120_init(qemu_irq *pic) s->pci->bus = pci_register_bus(NULL, "pci", pci_gt64120_set_irq, pci_gt64120_map_irq, - pic, 144, 4); + pic, PCI_DEVFN(18, 0), 4); s->ISD_handle = cpu_register_io_memory(gt64120_read, gt64120_write, s); d = pci_register_device(s->pci->bus, "GT64120 PCI Bus", sizeof(PCIDevice), 0, NULL, NULL); diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index 8b71a1315..ff80dd557 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -240,7 +240,6 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev) pci_conf[PCI_CLASS_PROG] = 0x8f; pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_IDE); - pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type pci_conf[0x51] = 0x04; // enable IDE0 if (d->secondary) { diff --git a/hw/ide/core.c b/hw/ide/core.c index ebdceb5fe..af52c2cb2 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -26,6 +26,7 @@ #include <hw/pc.h> #include <hw/pci.h> #include <hw/scsi.h> +#include "qemu-error.h" #include "qemu-timer.h" #include "sysemu.h" #include "dma.h" @@ -292,7 +293,7 @@ static void ide_set_signature(IDEState *s) /* put signature */ s->nsector = 1; s->sector = 1; - if (s->is_cdrom) { + if (s->drive_kind == IDE_CD) { s->lcyl = 0x14; s->hcyl = 0xeb; } else if (s->bs) { @@ -1827,15 +1828,15 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) switch(val) { case WIN_IDENTIFY: - if (s->bs && !s->is_cdrom) { - if (!s->is_cf) + if (s->bs && s->drive_kind != IDE_CD) { + if (s->drive_kind != IDE_CFATA) ide_identify(s); else ide_cfata_identify(s); s->status = READY_STAT | SEEK_STAT; ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop); } else { - if (s->is_cdrom) { + if (s->drive_kind == IDE_CD) { ide_set_signature(s); } ide_abort_command(s); @@ -1849,7 +1850,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) ide_set_irq(s->bus); break; case WIN_SETMULT: - if (s->is_cf && s->nsector == 0) { + if (s->drive_kind == IDE_CFATA && s->nsector == 0) { /* Disable Read and Write Multiple */ s->mult_sectors = 0; s->status = READY_STAT | SEEK_STAT; @@ -2033,7 +2034,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) ide_set_irq(s->bus); break; case WIN_SEEK: - if(s->is_cdrom) + if(s->drive_kind == IDE_CD) goto abort_cmd; /* XXX: Check that seek is within bounds */ s->status = READY_STAT | SEEK_STAT; @@ -2041,7 +2042,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) break; /* ATAPI commands */ case WIN_PIDENTIFY: - if (s->is_cdrom) { + if (s->drive_kind == IDE_CD) { ide_atapi_identify(s); s->status = READY_STAT | SEEK_STAT; ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop); @@ -2052,7 +2053,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) break; case WIN_DIAGNOSE: ide_set_signature(s); - if (s->is_cdrom) + if (s->drive_kind == IDE_CD) s->status = 0; /* ATAPI spec (v6) section 9.10 defines packet * devices to return a clear status register * with READY_STAT *not* set. */ @@ -2064,14 +2065,14 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) ide_set_irq(s->bus); break; case WIN_SRST: - if (!s->is_cdrom) + if (s->drive_kind != IDE_CD) goto abort_cmd; ide_set_signature(s); s->status = 0x00; /* NOTE: READY is _not_ set */ s->error = 0x01; break; case WIN_PACKETCMD: - if (!s->is_cdrom) + if (s->drive_kind != IDE_CD) goto abort_cmd; /* overlapping commands not supported */ if (s->feature & 0x02) @@ -2084,7 +2085,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) break; /* CF-ATA commands */ case CFA_REQ_EXT_ERROR_CODE: - if (!s->is_cf) + if (s->drive_kind != IDE_CFATA) goto abort_cmd; s->error = 0x09; /* miscellaneous error */ s->status = READY_STAT | SEEK_STAT; @@ -2092,7 +2093,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) break; case CFA_ERASE_SECTORS: case CFA_WEAR_LEVEL: - if (!s->is_cf) + if (s->drive_kind != IDE_CFATA) goto abort_cmd; if (val == CFA_WEAR_LEVEL) s->nsector = 0; @@ -2103,7 +2104,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) ide_set_irq(s->bus); break; case CFA_TRANSLATE_SECTOR: - if (!s->is_cf) + if (s->drive_kind != IDE_CFATA) goto abort_cmd; s->error = 0x00; s->status = READY_STAT | SEEK_STAT; @@ -2123,7 +2124,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) ide_set_irq(s->bus); break; case CFA_ACCESS_METADATA_STORAGE: - if (!s->is_cf) + if (s->drive_kind != IDE_CFATA) goto abort_cmd; switch (s->feature) { case 0x02: /* Inquiry Metadata Storage */ @@ -2143,7 +2144,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) ide_set_irq(s->bus); break; case IBM_SENSE_CONDITION: - if (!s->is_cf) + if (s->drive_kind != IDE_CFATA) goto abort_cmd; switch (s->feature) { case 0x01: /* sense temperature in device */ @@ -2157,7 +2158,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) break; case WIN_SMART: - if (s->is_cdrom) + if (s->drive_kind == IDE_CD) goto abort_cmd; if (s->hcyl != 0xc2 || s->lcyl != 0x4f) goto abort_cmd; @@ -2438,7 +2439,7 @@ void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val) /* high to low */ for(i = 0;i < 2; i++) { s = &bus->ifs[i]; - if (s->is_cdrom) + if (s->drive_kind == IDE_CD) s->status = 0x00; /* NOTE: READY is _not_ set */ else s->status = READY_STAT | SEEK_STAT; @@ -2540,7 +2541,7 @@ static void ide_reset(IDEState *s) #ifdef DEBUG_IDE printf("ide: reset\n"); #endif - if (s->is_cf) + if (s->drive_kind == IDE_CFATA) s->mult_sectors = 0; else s->mult_sectors = MAX_MULT_SECTORS; @@ -2594,8 +2595,8 @@ void ide_bus_reset(IDEBus *bus) ide_clear_hob(bus); } -void ide_init_drive(IDEState *s, BlockDriverState *bs, - const char *version, const char *serial) +int ide_init_drive(IDEState *s, BlockDriverState *bs, + const char *version, const char *serial) { int cylinders, heads, secs; uint64_t nb_sectors; @@ -2603,6 +2604,18 @@ void ide_init_drive(IDEState *s, BlockDriverState *bs, s->bs = bs; bdrv_get_geometry(bs, &nb_sectors); bdrv_guess_geometry(bs, &cylinders, &heads, &secs); + if (cylinders < 1 || cylinders > 16383) { + error_report("cyls must be between 1 and 16383"); + return -1; + } + if (heads < 1 || heads > 16) { + error_report("heads must be between 1 and 16"); + return -1; + } + if (secs < 1 || secs > 63) { + error_report("secs must be between 1 and 63"); + return -1; + } s->cylinders = cylinders; s->heads = heads; s->sectors = secs; @@ -2614,8 +2627,13 @@ void ide_init_drive(IDEState *s, BlockDriverState *bs, s->smart_errors = 0; s->smart_selftest_count = 0; if (bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM) { - s->is_cdrom = 1; + s->drive_kind = IDE_CD; bdrv_set_change_cb(bs, cdrom_change_cb, s); + } else { + if (bdrv_is_read_only(bs)) { + error_report("Can't use a read-only drive"); + return -1; + } } if (serial) { strncpy(s->drive_serial_str, serial, sizeof(s->drive_serial_str)); @@ -2629,7 +2647,8 @@ void ide_init_drive(IDEState *s, BlockDriverState *bs, pstrcpy(s->version, sizeof(s->version), QEMU_VERSION); } ide_reset(s); - bdrv_set_removable(bs, s->is_cdrom); + bdrv_set_removable(bs, s->drive_kind == IDE_CD); + return 0; } static void ide_init1(IDEBus *bus, int unit) @@ -2669,8 +2688,11 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, dinfo = i == 0 ? hd0 : hd1; ide_init1(bus, i); if (dinfo) { - ide_init_drive(&bus->ifs[i], dinfo->bdrv, NULL, - *dinfo->serial ? dinfo->serial : NULL); + if (ide_init_drive(&bus->ifs[i], dinfo->bdrv, NULL, + *dinfo->serial ? dinfo->serial : NULL) < 0) { + error_report("Can't set up IDE drive %s", dinfo->id); + exit(1); + } } else { ide_reset(&bus->ifs[i]); } diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 0125a9f0b..416554324 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -362,6 +362,8 @@ typedef struct BMDMAState BMDMAState; #define SMART_DISABLE 0xd9 #define SMART_STATUS 0xda +typedef enum { IDE_HD, IDE_CD, IDE_CFATA } IDEDriveKind; + typedef void EndTransferFunc(IDEState *); /* NOTE: IDEState represents in fact one drive */ @@ -369,8 +371,7 @@ struct IDEState { IDEBus *bus; uint8_t unit; /* ide config */ - int is_cdrom; - int is_cf; + IDEDriveKind drive_kind; int cylinders, heads, sectors; int64_t nb_sectors; int mult_sectors; @@ -555,8 +556,8 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr); void ide_data_writel(void *opaque, uint32_t addr, uint32_t val); uint32_t ide_data_readl(void *opaque, uint32_t addr); -void ide_init_drive(IDEState *s, BlockDriverState *bs, - const char *version, const char *serial); +int ide_init_drive(IDEState *s, BlockDriverState *bs, + const char *version, const char *serial); void ide_init2(IDEBus *bus, qemu_irq irq); void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1, qemu_irq irq); diff --git a/hw/ide/macio.c b/hw/ide/macio.c index fd4bdfd13..bd1c73e62 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -162,7 +162,7 @@ static void pmac_ide_transfer(DBDMA_io *io) IDEState *s = idebus_active_if(&m->bus); s->io_buffer_size = 0; - if (s->is_cdrom) { + if (s->drive_kind == IDE_CD) { pmac_ide_atapi_transfer_cb(io, 0); return; } diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c index 8e20e7467..2ceeb87c0 100644 --- a/hw/ide/microdrive.c +++ b/hw/ide/microdrive.c @@ -541,7 +541,7 @@ PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv) ide_init2_with_non_qdev_drives(&md->bus, bdrv, NULL, qemu_allocate_irqs(md_set_irq, md, 1)[0]); - md->bus.ifs[0].is_cf = 1; + md->bus.ifs[0].drive_kind = IDE_CFATA; md->bus.ifs[0].mdata_size = METADATA_SIZE; md->bus.ifs[0].mdata_storage = (uint8_t *) qemu_mallocz(METADATA_SIZE); diff --git a/hw/ide/piix.c b/hw/ide/piix.c index 9223834a6..07483e845 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -122,7 +122,6 @@ static int pci_piix_ide_initfn(PCIIDEState *d) pci_conf[PCI_CLASS_PROG] = 0x80; // legacy ATA mode pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_IDE); - pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type qemu_register_reset(piix3_reset, d); diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 2977a168e..53468edcb 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -18,7 +18,7 @@ */ #include <hw/hw.h> #include "dma.h" - +#include "qemu-error.h" #include <hw/ide/internal.h> /* --------------------------------- */ @@ -40,7 +40,7 @@ static int ide_qdev_init(DeviceState *qdev, DeviceInfo *base) IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus); if (!dev->conf.bs) { - fprintf(stderr, "%s: no drive specified\n", qdev->info->name); + error_report("No drive specified"); goto err; } if (dev->unit == -1) { @@ -49,19 +49,20 @@ static int ide_qdev_init(DeviceState *qdev, DeviceInfo *base) switch (dev->unit) { case 0: if (bus->master) { - fprintf(stderr, "ide: tried to assign master twice\n"); + error_report("IDE unit %d is in use", dev->unit); goto err; } bus->master = dev; break; case 1: if (bus->slave) { - fprintf(stderr, "ide: tried to assign slave twice\n"); + error_report("IDE unit %d is in use", dev->unit); goto err; } bus->slave = dev; break; default: + error_report("Invalid IDE unit %d", dev->unit); goto err; } return info->init(dev); @@ -117,7 +118,9 @@ static int ide_drive_initfn(IDEDevice *dev) } } - ide_init_drive(s, dev->conf.bs, dev->version, serial); + if (ide_init_drive(s, dev->conf.bs, dev->version, serial) < 0) { + return -1; + } if (!dev->version) { dev->version = qemu_strdup(s->version); diff --git a/hw/macio.c b/hw/macio.c index e92e82a73..789ca5529 100644 --- a/hw/macio.c +++ b/hw/macio.c @@ -110,7 +110,6 @@ void macio_init (PCIBus *bus, int device_id, int is_oldworld, int pic_mem_index, pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE); pci_config_set_device_id(d->config, device_id); pci_config_set_class(d->config, PCI_CLASS_OTHERS << 8); - d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type d->config[0x3d] = 0x01; // interrupt on pin 1 diff --git a/hw/ne2000.c b/hw/ne2000.c index 78fe14fe1..126e7cfea 100644 --- a/hw/ne2000.c +++ b/hw/ne2000.c @@ -723,7 +723,6 @@ static int pci_ne2000_init(PCIDevice *pci_dev) pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_REALTEK); pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_REALTEK_8029); pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET); - pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type /* TODO: RST# value should be 0. PCI spec 6.2.4 */ pci_conf[PCI_INTERRUPT_PIN] = 1; // interrupt pin 0 diff --git a/hw/openpic.c b/hw/openpic.c index 2b4cb0052..01bf15fc3 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -1194,7 +1194,6 @@ qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus, pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_IBM); pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_IBM_OPENPIC2); pci_config_set_class(pci_conf, PCI_CLASS_SYSTEM_OTHER); // FIXME? - pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type pci_conf[0x3d] = 0x00; // no interrupt pin /* Register I/O spaces */ @@ -72,6 +72,8 @@ static struct BusInfo pci_bus_info = { DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1), DEFINE_PROP_STRING("romfile", PCIDevice, romfile), DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1), + DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present, + QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false), DEFINE_PROP_END_OF_LIST() } }; @@ -79,6 +81,7 @@ static struct BusInfo pci_bus_info = { static void pci_update_mappings(PCIDevice *d); static void pci_set_irq(void *opaque, int irq_num, int level); static int pci_add_option_rom(PCIDevice *pdev); +static void pci_del_option_rom(PCIDevice *pdev); static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET; static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU; @@ -229,6 +232,7 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent, const char *name, int devfn_min) { qbus_create_inplace(&bus->qbus, &pci_bus_info, parent, name); + assert(PCI_FUNC(devfn_min) == 0); bus->devfn_min = devfn_min; /* host bridge */ @@ -684,11 +688,11 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, const char *name, int devfn, PCIConfigReadFunc *config_read, PCIConfigWriteFunc *config_write, - uint8_t header_type) + bool is_bridge) { if (devfn < 0) { for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices); - devfn += 8) { + devfn += PCI_FUNC_MAX) { if (!bus->devices[devfn]) goto found; } @@ -706,13 +710,12 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, pci_dev->irq_state = 0; pci_config_alloc(pci_dev); - header_type &= ~PCI_HEADER_TYPE_MULTI_FUNCTION; - if (header_type == PCI_HEADER_TYPE_NORMAL) { + if (!is_bridge) { pci_set_default_subsystem_id(pci_dev); } pci_init_cmask(pci_dev); pci_init_wmask(pci_dev); - if (header_type == PCI_HEADER_TYPE_BRIDGE) { + if (is_bridge) { pci_init_wmask_bridge(pci_dev); } @@ -790,6 +793,7 @@ static int pci_unregister_device(DeviceState *dev) return ret; pci_unregister_io_regions(pci_dev); + pci_del_option_rom(pci_dev); do_pci_unregister_device(pci_dev); return 0; } @@ -1705,7 +1709,9 @@ static int pci_bridge_initfn(PCIDevice *dev) pci_set_word(dev->config + PCI_STATUS, PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK); pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_PCI); - dev->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_BRIDGE; + dev->config[PCI_HEADER_TYPE] = + (dev->config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MULTI_FUNCTION) | + PCI_HEADER_TYPE_BRIDGE; pci_set_word(dev->config + PCI_SEC_STATUS, PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK); return 0; @@ -1756,7 +1762,7 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base) devfn = pci_dev->devfn; pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn, info->config_read, info->config_write, - info->header_type); + info->is_bridge); if (pci_dev == NULL) return -1; rc = info->init(pci_dev); @@ -1800,18 +1806,22 @@ void pci_qdev_register_many(PCIDeviceInfo *info) } } -PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name) +PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction, + const char *name) { DeviceState *dev; dev = qdev_create(&bus->qbus, name); qdev_prop_set_uint32(dev, "addr", devfn); + qdev_prop_set_bit(dev, "multifunction", multifunction); return DO_UPCAST(PCIDevice, qdev, dev); } -PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name) +PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn, + bool multifunction, + const char *name) { - PCIDevice *dev = pci_create(bus, devfn, name); + PCIDevice *dev = pci_create_multifunction(bus, devfn, multifunction, name); qdev_init_nofail(&dev->qdev); return dev; } @@ -1847,6 +1857,16 @@ int pci_enable_capability_support(PCIDevice *pci_dev, return config_init(pci_dev); } +PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name) +{ + return pci_create_multifunction(bus, devfn, false, name); +} + +PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name) +{ + return pci_create_simple_multifunction(bus, devfn, false, name); +} + static int pci_find_space(PCIDevice *pdev, uint8_t size) { int config_size = pci_config_size(pdev); @@ -1941,6 +1961,15 @@ static int pci_add_option_rom(PCIDevice *pdev) return 0; } +static void pci_del_option_rom(PCIDevice *pdev) +{ + if (!pdev->rom_offset) + return; + + qemu_ram_free(pdev->rom_offset); + pdev->rom_offset = 0; +} + /* Reserve space and add capability to the linked list in pci config space */ int pci_add_capability_at_offset(PCIDevice *pdev, uint8_t cap_id, uint8_t offset, uint8_t size) @@ -2054,7 +2083,7 @@ static PCIDeviceInfo bridge_info = { .init = pci_bridge_initfn, .exit = pci_bridge_exitfn, .config_write = pci_bridge_write_config, - .header_type = PCI_HEADER_TYPE_BRIDGE, + .is_bridge = 1, .qdev.props = (Property[]) { DEFINE_PROP_HEX32("vendorid", PCIBridge, vid, 0), DEFINE_PROP_HEX32("deviceid", PCIBridge, did, 0), @@ -16,6 +16,7 @@ struct kvm_irq_routing_entry; #define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) #define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) #define PCI_FUNC(devfn) ((devfn) & 0x07) +#define PCI_FUNC_MAX 8 /* Class, Vendor and Device IDs from Linux's pci_ids.h */ #include "pci_ids.h" @@ -118,6 +119,10 @@ typedef struct PCIIORegion { enum { QEMU_PCI_CAP_MSIX = 0x1, QEMU_PCI_CAP_EXPRESS = 0x2, + + /* multifunction capable device */ +#define QEMU_PCI_CAP_MULTIFUNCTION_BITNR 2 + QEMU_PCI_CAP_MULTIFUNCTION = (1 << QEMU_PCI_CAP_MULTIFUNCTION_BITNR), }; #define PCI_CAPABILITY_CONFIG_MAX_LENGTH 0x60 @@ -375,8 +380,12 @@ typedef struct { PCIConfigReadFunc *config_read; PCIConfigWriteFunc *config_write; - /* pci config header type */ - uint8_t header_type; + /* + * pci-to-pci bridge or normal device. + * This doesn't mean pci host switch. + * When card bus bridge is supported, this would be enhanced. + */ + int is_bridge; /* pcie stuff */ int is_express; /* is this device pci express? */ @@ -388,6 +397,11 @@ typedef struct { void pci_qdev_register(PCIDeviceInfo *info); void pci_qdev_register_many(PCIDeviceInfo *info); +PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction, + const char *name); +PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn, + bool multifunction, + const char *name); PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name); PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name); diff --git a/hw/pcnet.c b/hw/pcnet.c index 5e63eb5c0..5e7593050 100644 --- a/hw/pcnet.c +++ b/hw/pcnet.c @@ -1990,7 +1990,6 @@ static int pci_pcnet_init(PCIDevice *pci_dev) /* TODO: 0 is the default anyway, no need to set it. */ pci_conf[PCI_CLASS_PROG] = 0x00; pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET); - pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type /* TODO: not necessary, is set when BAR is registered. */ pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_SPACE_IO); diff --git a/hw/piix_pci.c b/hw/piix_pci.c index d01618f8c..ce977d04c 100644 --- a/hw/piix_pci.c +++ b/hw/piix_pci.c @@ -213,7 +213,6 @@ static int i440fx_initfn(PCIDevice *dev) pci_config_set_device_id(d->dev.config, PCI_DEVICE_ID_INTEL_82441); d->dev.config[0x08] = 0x02; // revision pci_config_set_class(d->dev.config, PCI_CLASS_BRIDGE_HOST); - d->dev.config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type d->dev.config[I440FX_SMRAM] = 0x02; diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index 5358f82b0..8ac99f281 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -279,7 +279,8 @@ PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers) controller->pci_state.bus = pci_register_bus(NULL, "pci", mpc85xx_pci_set_irq, mpc85xx_pci_map_irq, - pci_irqs, 0x88, 4); + pci_irqs, PCI_DEVFN(0x11, 0), + 4); d = pci_register_device(controller->pci_state.bus, "host bridge", sizeof(PCIDevice), 0, NULL, NULL); diff --git a/hw/prep_pci.c b/hw/prep_pci.c index 144fde03a..0c2afe9c8 100644 --- a/hw/prep_pci.c +++ b/hw/prep_pci.c @@ -137,7 +137,6 @@ PCIBus *pci_prep_init(qemu_irq *pic) pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST); d->config[0x0C] = 0x08; // cache_line_size d->config[0x0D] = 0x10; // latency_timer - d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type d->config[0x34] = 0x00; // capabilities_pointer return s->bus; diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 7e3e99efc..9219cd7a6 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -633,6 +633,11 @@ void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyT qdev_prop_cpy(dev, prop, src); } +void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value) +{ + qdev_prop_set(dev, name, &value, PROP_TYPE_BIT); +} + void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value) { qdev_prop_set(dev, name, &value, PROP_TYPE_UINT8); @@ -326,8 +326,10 @@ void qdev_init_nofail(DeviceState *dev) { DeviceInfo *info = dev->info; - if (qdev_init(dev) < 0) - hw_error("Initialization of device %s failed\n", info->name); + if (qdev_init(dev) < 0) { + error_report("Initialization of device %s failed\n", info->name); + exit(1); + } } /* Unlink device from bus and free the structure. */ @@ -269,6 +269,7 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop); int qdev_prop_exists(DeviceState *dev, const char *name); int qdev_prop_parse(DeviceState *dev, const char *name, const char *value); void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type); +void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value); void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value); void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value); void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value); diff --git a/hw/rtl8139.c b/hw/rtl8139.c index 72e224272..441f0a914 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -3361,7 +3361,6 @@ static int pci_rtl8139_init(PCIDevice *dev) pci_conf[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MASTER; pci_conf[PCI_REVISION_ID] = RTL8139_PCI_REVID; /* >=0x20 is for 8139C+ */ pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET); - pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; /* TODO: value should be 0 at RST# */ pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin 0 */ /* TODO: start of capability list, but no capability diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index b84b9b98b..d69c74c4e 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -102,19 +102,23 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, int int scsi_bus_legacy_handle_cmdline(SCSIBus *bus) { + Location loc; DriveInfo *dinfo; int res = 0, unit; + loc_push_none(&loc); for (unit = 0; unit < MAX_SCSI_DEVS; unit++) { dinfo = drive_get(IF_SCSI, bus->busnr, unit); if (dinfo == NULL) { continue; } + qemu_opts_loc_restore(dinfo->opts); if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit)) { res = -1; break; } } + loc_pop(&loc); return res; } diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 3e41011cc..c30709c55 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -1059,6 +1059,11 @@ static int scsi_disk_initfn(SCSIDevice *dev) s->bs = s->qdev.conf.bs; is_cd = bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM; + if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) { + error_report("Device doesn't support drive option rerror"); + return -1; + } + if (!s->serial) { /* try to fall back to value set with legacy -drive serial=... */ dinfo = drive_get_by_blockdev(s->bs); diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index 3915e7844..a8b4176d8 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -474,6 +474,15 @@ static int scsi_generic_initfn(SCSIDevice *dev) return -1; } + if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) { + error_report("Device doesn't support drive option werror"); + return -1; + } + if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) { + error_report("Device doesn't support drive option rerror"); + return -1; + } + /* check we are using a driver managing SG_IO (version 3 and after */ if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 || sg_version < 30000) { diff --git a/hw/sun4u.c b/hw/sun4u.c index 2234b4e92..31c0c4c48 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -562,7 +562,6 @@ pci_ebus_init1(PCIDevice *s) s->config[0x09] = 0x00; // programming i/f pci_config_set_class(s->config, PCI_CLASS_BRIDGE_OTHER); s->config[0x0D] = 0x0a; // latency_timer - s->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type pci_register_bar(s, 0, 0x1000000, PCI_BASE_ADDRESS_SPACE_MEMORY, ebus_mmio_mapfunc); diff --git a/hw/unin_pci.c b/hw/unin_pci.c index 362fb7762..1310211ae 100644 --- a/hw/unin_pci.c +++ b/hw/unin_pci.c @@ -230,10 +230,10 @@ PCIBus *pci_pmac_init(qemu_irq *pic) d = FROM_SYSBUS(UNINState, s); d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci", pci_unin_set_irq, pci_unin_map_irq, - pic, 11 << 3, 4); + pic, PCI_DEVFN(11, 0), 4); #if 0 - pci_create_simple(d->host_state.bus, 11 << 3, "uni-north"); + pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north"); #endif sysbus_mmio_map(s, 0, 0xf2800000); @@ -242,11 +242,11 @@ PCIBus *pci_pmac_init(qemu_irq *pic) /* DEC 21154 bridge */ #if 0 /* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */ - pci_create_simple(d->host_state.bus, 12 << 3, "dec-21154"); + pci_create_simple(d->host_state.bus, PCI_DEVFN(12, 0), "dec-21154"); #endif /* Uninorth AGP bus */ - pci_create_simple(d->host_state.bus, 11 << 3, "uni-north-agp"); + pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north-agp"); dev = qdev_create(NULL, "uni-north-agp"); qdev_init_nofail(dev); s = sysbus_from_qdev(dev); @@ -256,7 +256,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic) /* Uninorth internal bus */ #if 0 /* XXX: not needed for now */ - pci_create_simple(d->host_state.bus, 14 << 3, "uni-north-pci"); + pci_create_simple(d->host_state.bus, PCI_DEVFN(14, 0), "uni-north-pci"); dev = qdev_create(NULL, "uni-north-pci"); qdev_init_nofail(dev); s = sysbus_from_qdev(dev); @@ -282,7 +282,7 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic) d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci", pci_unin_set_irq, pci_unin_map_irq, - pic, 11 << 3, 4); + pic, PCI_DEVFN(11, 0), 4); sysbus_mmio_map(s, 0, 0xf0800000); sysbus_mmio_map(s, 1, 0xf0c00000); @@ -300,7 +300,6 @@ static int unin_main_pci_host_init(PCIDevice *d) pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST); d->config[0x0C] = 0x08; // cache_line_size d->config[0x0D] = 0x10; // latency_timer - d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type d->config[0x34] = 0x00; // capabilities_pointer return 0; } @@ -313,7 +312,6 @@ static int unin_agp_pci_host_init(PCIDevice *d) pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST); d->config[0x0C] = 0x08; // cache_line_size d->config[0x0D] = 0x10; // latency_timer - d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type // d->config[0x34] = 0x80; // capabilities_pointer return 0; } @@ -329,7 +327,6 @@ static int u3_agp_pci_host_init(PCIDevice *d) d->config[0x0C] = 0x08; /* latency timer */ d->config[0x0D] = 0x10; - d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; return 0; } @@ -341,7 +338,6 @@ static int unin_internal_pci_host_init(PCIDevice *d) pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST); d->config[0x0C] = 0x08; // cache_line_size d->config[0x0D] = 0x10; // latency_timer - d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type d->config[0x34] = 0x00; // capabilities_pointer return 0; } diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c index 4cdb55eb7..1d834004b 100644 --- a/hw/usb-uhci.c +++ b/hw/usb-uhci.c @@ -1109,7 +1109,6 @@ static int usb_uhci_common_initfn(UHCIState *s) pci_conf[PCI_REVISION_ID] = 0x01; // revision number pci_conf[PCI_CLASS_PROG] = 0x00; pci_config_set_class(pci_conf, PCI_CLASS_SERIAL_USB); - pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type /* TODO: reset value should be 0. */ pci_conf[PCI_INTERRUPT_PIN] = 4; // interrupt pin 3 pci_conf[0x60] = 0x10; // release number diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c index 199bc1936..a76bdfad6 100644 --- a/hw/versatile_pci.c +++ b/hw/versatile_pci.c @@ -127,7 +127,7 @@ static int pci_vpb_init(SysBusDevice *dev) } bus = pci_register_bus(&dev->qdev, "pci", pci_vpb_set_irq, pci_vpb_map_irq, s->irq, - 11 << 3, 4); + PCI_DEVFN(11, 0), 4); /* ??? Register memory space. */ diff --git a/hw/vga-pci.c b/hw/vga-pci.c index 9089c9f5d..390787111 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -92,7 +92,6 @@ static int pci_vga_initfn(PCIDevice *dev) pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_QEMU); pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_QEMU_VGA); pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA); - pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type /* XXX: VGA_RAM_SIZE must be a power of two */ pci_register_bar(&d->dev, 0, VGA_RAM_SIZE, diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index 1de424262..8747634fb 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -26,6 +26,7 @@ typedef struct VirtIOBlock QEMUBH *bh; BlockConf *conf; unsigned short sector_mask; + char sn[BLOCK_SERIAL_STRLEN]; } VirtIOBlock; static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev) @@ -324,6 +325,12 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req, virtio_blk_handle_flush(req, mrb); } else if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) { virtio_blk_handle_scsi(req); + } else if (req->out->type & VIRTIO_BLK_T_GET_ID) { + VirtIOBlock *s = req->dev; + + memcpy(req->elem.in_sg[0].iov_base, s->sn, + MIN(req->elem.in_sg[0].iov_len, sizeof(s->sn))); + virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); } else if (req->out->type & VIRTIO_BLK_T_OUT) { qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1], req->elem.out_num - 1); @@ -481,6 +488,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf) VirtIOBlock *s; int cylinders, heads, secs; static int virtio_blk_id; + DriveInfo *dinfo; s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK, sizeof(struct virtio_blk_config), @@ -495,6 +503,12 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf) s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1; bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs); + /* NB: per existing s/n string convention the string is terminated + * by '\0' only when less than sizeof (s->sn) + */ + dinfo = drive_get_by_blockdev(s->bs); + strncpy(s->sn, dinfo->serial, sizeof (s->sn)); + s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output); qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s); diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h index 7a7ece3d9..fff46da7d 100644 --- a/hw/virtio-blk.h +++ b/hw/virtio-blk.h @@ -59,6 +59,9 @@ struct virtio_blk_config /* Flush the volatile write cache */ #define VIRTIO_BLK_T_FLUSH 4 +/* return the device ID string */ +#define VIRTIO_BLK_T_GET_ID 8 + /* Barrier before this op. */ #define VIRTIO_BLK_T_BARRIER 0x80000000 diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index a55c9af8c..157d353b7 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -538,7 +538,6 @@ static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev, config[0x09] = pif; pci_config_set_class(config, class_code); - config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; config[0x2c] = vendor & 0xFF; config[0x2d] = (vendor >> 8) & 0xFF; diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index 9e72d2e9b..8c7224968 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -1246,7 +1246,6 @@ static int pci_vmsvga_initfn(PCIDevice *dev) pci_config_set_class(s->card.config, PCI_CLASS_DISPLAY_VGA); s->card.config[PCI_CACHE_LINE_SIZE] = 0x08; /* Cache line size */ s->card.config[PCI_LATENCY_TIMER] = 0x40; /* Latency timer */ - s->card.config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; s->card.config[PCI_SUBSYSTEM_VENDOR_ID] = PCI_VENDOR_ID_VMWARE & 0xff; s->card.config[PCI_SUBSYSTEM_VENDOR_ID + 1] = PCI_VENDOR_ID_VMWARE >> 8; s->card.config[PCI_SUBSYSTEM_ID] = SVGA_PCI_DEVICE_ID & 0xff; diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c index be0e89ed9..46e1df8b6 100644 --- a/hw/wdt_i6300esb.c +++ b/hw/wdt_i6300esb.c @@ -411,7 +411,6 @@ static int i6300esb_init(PCIDevice *dev) pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL); pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_ESB_9); pci_config_set_class(pci_conf, PCI_CLASS_SYSTEM_OTHER); - pci_conf[PCI_HEADER_TYPE] = 0x00; pci_register_bar(&d->dev, 0, 0x10, PCI_BASE_ADDRESS_SPACE_MEMORY, i6300esb_map); |