-----BEGIN PGP SIGNATURE-----
iQIcBAABAgAGBQJZwGCAAAoJEH3vgQaq/DkOnk4QAMDP/WST80HUEWeDV+Rm3uk5 FSM6hZzFGIweutCphSYCtwgT5E1xpeh+oDPzpEmevmxSi03hEG9yndiUqqhjmygc jwd1xfEPAywUQ1i7nZ+ymh4wxzT5RnIxtCMaj3NwtNqsOM8V/5Ffd2XkXcKdvxjD KJQe1f61ghhDOUr2Buk0btKXpdzxOhtvw7/czovZjN20D5POof9UGM5I4iRqjmEy rD5xCC4jotLn6L9A9cafqPD6PBRXWRfU2fIHZXHm568LlbnKomyVwgvCjRsk+BU8 zUYjH2ymIg86RajiTAIzrjGNTwR3KXpefV+8DKde/WcxWZIfW8yskA9rB1ITj+ID VBjkbTQRkhZdOD9lkSHragfghqV34NevncMf4lQEbtKImosU0XQb38rGkqGACNs9 7fNsniK8YH1tnpaVNYmzeK7B/9APCk0GNxxORdWe55TdTXRUmclzWCWxmEF6bW3C 7TxXTwP2Ee+ZXv+ncmIp8YZ7tXxfvFC/N6dDMT6PcFThtZE97fDK+Hiw/Shz18OE 5FLB+cwoPKVLYmJ5osnjEz5Ckq9Fc0byYrpCL5KeUUV72aIfSKhTUf032hcz1cfv 9SSQAKXzGhm1KzJL60dawlLtI2+H+wbBX4ek6iINb/MGy44shA+SuuWYuYwRe03t GBLremn7qcH8iGXPksox =WGrh -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/jnsnow/tags/ide-pull-request' into staging # gpg: Signature made Tue 19 Sep 2017 01:10:40 BST # gpg: using RSA key 0x7DEF8106AAFC390E # gpg: Good signature from "John Snow (John Huston) <jsnow@redhat.com>" # Primary key fingerprint: FAEB 9711 A12C F475 812F 18F2 88A9 064D 1835 61EB # Subkey fingerprint: F9B7 ABDB BCAC DF95 BE76 CBD0 7DEF 8106 AAFC 390E * remotes/jnsnow/tags/ide-pull-request: hw/block/fdc: Convert to realize hw/ide: Convert DeviceClass init to realize AHCI: remove DPRINTF macro AHCI: pretty-print FIS to buffer instead of stderr AHCI: Rework IRQ constants AHCI: Replace DPRINTF with trace-events IDE: replace DEBUG_AIO with trace events ATAPI: Replace DEBUG_IDE_ATAPI with tracing events IDE: add tracing for data ports IDE: Add register hints to tracing IDE: replace DEBUG_IDE with tracing system hw/ide/microdrive: Mark the dscm1xxxx device with user_creatable = false ide: ahci: unparent children buses before freeing their memory Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
11e06ce1ed
|
@ -155,6 +155,7 @@ trace-events-subdirs += hw/acpi
|
|||
trace-events-subdirs += hw/arm
|
||||
trace-events-subdirs += hw/alpha
|
||||
trace-events-subdirs += hw/xen
|
||||
trace-events-subdirs += hw/ide
|
||||
trace-events-subdirs += ui
|
||||
trace-events-subdirs += audio
|
||||
trace-events-subdirs += net
|
||||
|
|
|
@ -517,7 +517,7 @@ static Property floppy_drive_properties[] = {
|
|||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static int floppy_drive_init(DeviceState *qdev)
|
||||
static void floppy_drive_realize(DeviceState *qdev, Error **errp)
|
||||
{
|
||||
FloppyDrive *dev = FLOPPY_DRIVE(qdev);
|
||||
FloppyBus *bus = FLOPPY_BUS(qdev->parent_bus);
|
||||
|
@ -535,15 +535,15 @@ static int floppy_drive_init(DeviceState *qdev)
|
|||
}
|
||||
|
||||
if (dev->unit >= MAX_FD) {
|
||||
error_report("Can't create floppy unit %d, bus supports only %d units",
|
||||
dev->unit, MAX_FD);
|
||||
return -1;
|
||||
error_setg(errp, "Can't create floppy unit %d, bus supports "
|
||||
"only %d units", dev->unit, MAX_FD);
|
||||
return;
|
||||
}
|
||||
|
||||
drive = get_drv(bus->fdc, dev->unit);
|
||||
if (drive->blk) {
|
||||
error_report("Floppy unit %d is in use", dev->unit);
|
||||
return -1;
|
||||
error_setg(errp, "Floppy unit %d is in use", dev->unit);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dev->conf.blk) {
|
||||
|
@ -557,8 +557,9 @@ static int floppy_drive_init(DeviceState *qdev)
|
|||
if (dev->conf.logical_block_size != 512 ||
|
||||
dev->conf.physical_block_size != 512)
|
||||
{
|
||||
error_report("Physical and logical block size must be 512 for floppy");
|
||||
return -1;
|
||||
error_setg(errp, "Physical and logical block size must "
|
||||
"be 512 for floppy");
|
||||
return;
|
||||
}
|
||||
|
||||
/* rerror/werror aren't supported by fdc and therefore not even registered
|
||||
|
@ -570,20 +571,20 @@ static int floppy_drive_init(DeviceState *qdev)
|
|||
blkconf_apply_backend_options(&dev->conf, blk_is_read_only(dev->conf.blk),
|
||||
false, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
return -1;
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 'enospc' is the default for -drive, 'report' is what blk_new() gives us
|
||||
* for empty drives. */
|
||||
if (blk_get_on_error(dev->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC &&
|
||||
blk_get_on_error(dev->conf.blk, 0) != BLOCKDEV_ON_ERROR_REPORT) {
|
||||
error_report("fdc doesn't support drive option werror");
|
||||
return -1;
|
||||
error_setg(errp, "fdc doesn't support drive option werror");
|
||||
return;
|
||||
}
|
||||
if (blk_get_on_error(dev->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) {
|
||||
error_report("fdc doesn't support drive option rerror");
|
||||
return -1;
|
||||
error_setg(errp, "fdc doesn't support drive option rerror");
|
||||
return;
|
||||
}
|
||||
|
||||
drive->conf = &dev->conf;
|
||||
|
@ -599,14 +600,12 @@ static int floppy_drive_init(DeviceState *qdev)
|
|||
dev->type = drive->drive;
|
||||
|
||||
fd_revalidate(drive);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void floppy_drive_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *k = DEVICE_CLASS(klass);
|
||||
k->init = floppy_drive_init;
|
||||
k->realize = floppy_drive_realize;
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, k->categories);
|
||||
k->bus_type = TYPE_FLOPPY_BUS;
|
||||
k->props = floppy_drive_properties;
|
||||
|
|
244
hw/ide/ahci.c
244
hw/ide/ahci.c
|
@ -34,15 +34,7 @@
|
|||
#include "hw/ide/pci.h"
|
||||
#include "hw/ide/ahci_internal.h"
|
||||
|
||||
#define DEBUG_AHCI 0
|
||||
|
||||
#define DPRINTF(port, fmt, ...) \
|
||||
do { \
|
||||
if (DEBUG_AHCI) { \
|
||||
fprintf(stderr, "ahci: %s: [%d] ", __func__, port); \
|
||||
fprintf(stderr, fmt, ## __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#include "trace.h"
|
||||
|
||||
static void check_cmd(AHCIState *s, int port);
|
||||
static int handle_cmd(AHCIState *s, int port, uint8_t slot);
|
||||
|
@ -55,6 +47,27 @@ static bool ahci_map_fis_address(AHCIDevice *ad);
|
|||
static void ahci_unmap_clb_address(AHCIDevice *ad);
|
||||
static void ahci_unmap_fis_address(AHCIDevice *ad);
|
||||
|
||||
static const char *AHCIPortIRQ_lookup[AHCI_PORT_IRQ__COUNT] = {
|
||||
[AHCI_PORT_IRQ_BIT_DHRS] = "DHRS",
|
||||
[AHCI_PORT_IRQ_BIT_PSS] = "PSS",
|
||||
[AHCI_PORT_IRQ_BIT_DSS] = "DSS",
|
||||
[AHCI_PORT_IRQ_BIT_SDBS] = "SDBS",
|
||||
[AHCI_PORT_IRQ_BIT_UFS] = "UFS",
|
||||
[AHCI_PORT_IRQ_BIT_DPS] = "DPS",
|
||||
[AHCI_PORT_IRQ_BIT_PCS] = "PCS",
|
||||
[AHCI_PORT_IRQ_BIT_DMPS] = "DMPS",
|
||||
[8 ... 21] = "RESERVED",
|
||||
[AHCI_PORT_IRQ_BIT_PRCS] = "PRCS",
|
||||
[AHCI_PORT_IRQ_BIT_IPMS] = "IPMS",
|
||||
[AHCI_PORT_IRQ_BIT_OFS] = "OFS",
|
||||
[25] = "RESERVED",
|
||||
[AHCI_PORT_IRQ_BIT_INFS] = "INFS",
|
||||
[AHCI_PORT_IRQ_BIT_IFS] = "IFS",
|
||||
[AHCI_PORT_IRQ_BIT_HBDS] = "HBDS",
|
||||
[AHCI_PORT_IRQ_BIT_HBFS] = "HBFS",
|
||||
[AHCI_PORT_IRQ_BIT_TFES] = "TFES",
|
||||
[AHCI_PORT_IRQ_BIT_CPDS] = "CPDS"
|
||||
};
|
||||
|
||||
static uint32_t ahci_port_read(AHCIState *s, int port, int offset)
|
||||
{
|
||||
|
@ -114,9 +127,9 @@ static uint32_t ahci_port_read(AHCIState *s, int port, int offset)
|
|||
default:
|
||||
val = 0;
|
||||
}
|
||||
DPRINTF(port, "offset: 0x%x val: 0x%x\n", offset, val);
|
||||
return val;
|
||||
|
||||
trace_ahci_port_read(s, port, offset, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
static void ahci_irq_raise(AHCIState *s, AHCIDevice *dev)
|
||||
|
@ -125,7 +138,7 @@ static void ahci_irq_raise(AHCIState *s, AHCIDevice *dev)
|
|||
PCIDevice *pci_dev = (PCIDevice *) object_dynamic_cast(OBJECT(dev_state),
|
||||
TYPE_PCI_DEVICE);
|
||||
|
||||
DPRINTF(0, "raise irq\n");
|
||||
trace_ahci_irq_raise(s);
|
||||
|
||||
if (pci_dev && msi_enabled(pci_dev)) {
|
||||
msi_notify(pci_dev, 0);
|
||||
|
@ -140,7 +153,7 @@ static void ahci_irq_lower(AHCIState *s, AHCIDevice *dev)
|
|||
PCIDevice *pci_dev = (PCIDevice *) object_dynamic_cast(OBJECT(dev_state),
|
||||
TYPE_PCI_DEVICE);
|
||||
|
||||
DPRINTF(0, "lower irq\n");
|
||||
trace_ahci_irq_lower(s);
|
||||
|
||||
if (!pci_dev || !msi_enabled(pci_dev)) {
|
||||
qemu_irq_lower(s->irq);
|
||||
|
@ -150,8 +163,7 @@ static void ahci_irq_lower(AHCIState *s, AHCIDevice *dev)
|
|||
static void ahci_check_irq(AHCIState *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
DPRINTF(-1, "check irq %#x\n", s->control_regs.irqstatus);
|
||||
uint32_t old_irq = s->control_regs.irqstatus;
|
||||
|
||||
s->control_regs.irqstatus = 0;
|
||||
for (i = 0; i < s->ports; i++) {
|
||||
|
@ -160,7 +172,7 @@ static void ahci_check_irq(AHCIState *s)
|
|||
s->control_regs.irqstatus |= (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
trace_ahci_check_irq(s, old_irq, s->control_regs.irqstatus);
|
||||
if (s->control_regs.irqstatus &&
|
||||
(s->control_regs.ghc & HOST_CTL_IRQ_EN)) {
|
||||
ahci_irq_raise(s, NULL);
|
||||
|
@ -170,12 +182,18 @@ static void ahci_check_irq(AHCIState *s)
|
|||
}
|
||||
|
||||
static void ahci_trigger_irq(AHCIState *s, AHCIDevice *d,
|
||||
int irq_type)
|
||||
enum AHCIPortIRQ irqbit)
|
||||
{
|
||||
DPRINTF(d->port_no, "trigger irq %#x -> %x\n",
|
||||
irq_type, d->port_regs.irq_mask & irq_type);
|
||||
g_assert(irqbit >= 0 && irqbit < 32);
|
||||
uint32_t irq = 1U << irqbit;
|
||||
uint32_t irqstat = d->port_regs.irq_stat | irq;
|
||||
|
||||
d->port_regs.irq_stat |= irq_type;
|
||||
trace_ahci_trigger_irq(s, d->port_no,
|
||||
AHCIPortIRQ_lookup[irqbit], irq,
|
||||
d->port_regs.irq_stat, irqstat,
|
||||
irqstat & d->port_regs.irq_mask);
|
||||
|
||||
d->port_regs.irq_stat = irqstat;
|
||||
ahci_check_irq(s);
|
||||
}
|
||||
|
||||
|
@ -240,7 +258,7 @@ static void ahci_port_write(AHCIState *s, int port, int offset, uint32_t val)
|
|||
{
|
||||
AHCIPortRegs *pr = &s->dev[port].port_regs;
|
||||
|
||||
DPRINTF(port, "offset: 0x%x val: 0x%x\n", offset, val);
|
||||
trace_ahci_port_write(s, port, offset, val);
|
||||
switch (offset) {
|
||||
case PORT_LST_ADDR:
|
||||
pr->lst_addr = val;
|
||||
|
@ -341,8 +359,6 @@ static uint64_t ahci_mem_read_32(void *opaque, hwaddr addr)
|
|||
val = s->control_regs.version;
|
||||
break;
|
||||
}
|
||||
|
||||
DPRINTF(-1, "(addr 0x%08X), val 0x%08X\n", (unsigned) addr, val);
|
||||
} else if ((addr >= AHCI_PORT_REGS_START_ADDR) &&
|
||||
(addr < (AHCI_PORT_REGS_START_ADDR +
|
||||
(s->ports * AHCI_PORT_ADDR_OFFSET_LEN)))) {
|
||||
|
@ -350,6 +366,7 @@ static uint64_t ahci_mem_read_32(void *opaque, hwaddr addr)
|
|||
addr & AHCI_PORT_ADDR_OFFSET_MASK);
|
||||
}
|
||||
|
||||
trace_ahci_mem_read_32(s, addr, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
@ -379,8 +396,7 @@ static uint64_t ahci_mem_read(void *opaque, hwaddr addr, unsigned size)
|
|||
val = (hi << 32 | lo) >> (ofst * 8);
|
||||
}
|
||||
|
||||
DPRINTF(-1, "addr=0x%" HWADDR_PRIx " val=0x%" PRIx64 ", size=%d\n",
|
||||
addr, val, size);
|
||||
trace_ahci_mem_read(opaque, size, addr, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
@ -390,8 +406,7 @@ static void ahci_mem_write(void *opaque, hwaddr addr,
|
|||
{
|
||||
AHCIState *s = opaque;
|
||||
|
||||
DPRINTF(-1, "addr=0x%" HWADDR_PRIx " val=0x%" PRIx64 ", size=%d\n",
|
||||
addr, val, size);
|
||||
trace_ahci_mem_write(s, size, addr, val);
|
||||
|
||||
/* Only aligned reads are allowed on AHCI */
|
||||
if (addr & 3) {
|
||||
|
@ -401,15 +416,12 @@ static void ahci_mem_write(void *opaque, hwaddr addr,
|
|||
}
|
||||
|
||||
if (addr < AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR) {
|
||||
DPRINTF(-1, "(addr 0x%08X), val 0x%08"PRIX64"\n", (unsigned) addr, val);
|
||||
|
||||
switch (addr) {
|
||||
case HOST_CAP: /* R/WO, RO */
|
||||
/* FIXME handle R/WO */
|
||||
break;
|
||||
case HOST_CTL: /* R/W */
|
||||
if (val & HOST_CTL_RESET) {
|
||||
DPRINTF(-1, "HBA Reset\n");
|
||||
ahci_reset(s);
|
||||
} else {
|
||||
s->control_regs.ghc = (val & 0x3) | HOST_CTL_AHCI_EN;
|
||||
|
@ -427,7 +439,7 @@ static void ahci_mem_write(void *opaque, hwaddr addr,
|
|||
/* FIXME report write? */
|
||||
break;
|
||||
default:
|
||||
DPRINTF(-1, "write to unknown register 0x%x\n", (unsigned)addr);
|
||||
trace_ahci_mem_write_unknown(s, size, addr, val);
|
||||
}
|
||||
} else if ((addr >= AHCI_PORT_REGS_START_ADDR) &&
|
||||
(addr < (AHCI_PORT_REGS_START_ADDR +
|
||||
|
@ -559,7 +571,8 @@ static void ahci_set_signature(AHCIDevice *ad, uint32_t sig)
|
|||
s->sector = sig >> 8 & 0xFF;
|
||||
s->nsector = sig & 0xFF;
|
||||
|
||||
DPRINTF(ad->port_no, "set hcyl:lcyl:sect:nsect = 0x%08x\n", sig);
|
||||
trace_ahci_set_signature(ad->hba, ad->port_no, s->nsector, s->sector,
|
||||
s->lcyl, s->hcyl, sig);
|
||||
}
|
||||
|
||||
static void ahci_reset_port(AHCIState *s, int port)
|
||||
|
@ -569,7 +582,7 @@ static void ahci_reset_port(AHCIState *s, int port)
|
|||
IDEState *ide_state = &d->port.ifs[0];
|
||||
int i;
|
||||
|
||||
DPRINTF(port, "reset port\n");
|
||||
trace_ahci_reset_port(s, port);
|
||||
|
||||
ide_bus_reset(&d->port);
|
||||
ide_state->ncq_queues = AHCI_MAX_CMDS;
|
||||
|
@ -622,20 +635,21 @@ static void ahci_reset_port(AHCIState *s, int port)
|
|||
ahci_init_d2h(d);
|
||||
}
|
||||
|
||||
static void debug_print_fis(uint8_t *fis, int cmd_len)
|
||||
/* Buffer pretty output based on a raw FIS structure. */
|
||||
static char *ahci_pretty_buffer_fis(uint8_t *fis, int cmd_len)
|
||||
{
|
||||
#if DEBUG_AHCI
|
||||
int i;
|
||||
GString *s = g_string_new("FIS:");
|
||||
|
||||
fprintf(stderr, "fis:");
|
||||
for (i = 0; i < cmd_len; i++) {
|
||||
if ((i & 0xf) == 0) {
|
||||
fprintf(stderr, "\n%02x:",i);
|
||||
g_string_append_printf(s, "\n0x%02x: ", i);
|
||||
}
|
||||
fprintf(stderr, "%02x ",fis[i]);
|
||||
g_string_append_printf(s, "%02x ", fis[i]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
g_string_append_c(s, '\n');
|
||||
|
||||
return g_string_free(s, FALSE);
|
||||
}
|
||||
|
||||
static bool ahci_map_fis_address(AHCIDevice *ad)
|
||||
|
@ -655,7 +669,7 @@ static bool ahci_map_fis_address(AHCIDevice *ad)
|
|||
static void ahci_unmap_fis_address(AHCIDevice *ad)
|
||||
{
|
||||
if (ad->res_fis == NULL) {
|
||||
DPRINTF(ad->port_no, "Attempt to unmap NULL FIS address\n");
|
||||
trace_ahci_unmap_fis_address_null(ad->hba, ad->port_no);
|
||||
return;
|
||||
}
|
||||
ad->port_regs.cmd &= ~PORT_CMD_FIS_ON;
|
||||
|
@ -682,7 +696,7 @@ static bool ahci_map_clb_address(AHCIDevice *ad)
|
|||
static void ahci_unmap_clb_address(AHCIDevice *ad)
|
||||
{
|
||||
if (ad->lst == NULL) {
|
||||
DPRINTF(ad->port_no, "Attempt to unmap NULL CLB address\n");
|
||||
trace_ahci_unmap_clb_address_null(ad->hba, ad->port_no);
|
||||
return;
|
||||
}
|
||||
ad->port_regs.cmd &= ~PORT_CMD_LIST_ON;
|
||||
|
@ -723,7 +737,7 @@ static void ahci_write_fis_sdb(AHCIState *s, NCQTransferState *ncq_tfs)
|
|||
|
||||
/* Trigger IRQ if interrupt bit is set (which currently, it always is) */
|
||||
if (sdb_fis->flags & 0x40) {
|
||||
ahci_trigger_irq(s, ad, PORT_IRQ_SDB_FIS);
|
||||
ahci_trigger_irq(s, ad, AHCI_PORT_IRQ_BIT_SDBS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -766,10 +780,10 @@ static void ahci_write_fis_pio(AHCIDevice *ad, uint16_t len)
|
|||
ad->port.ifs[0].status;
|
||||
|
||||
if (pio_fis[2] & ERR_STAT) {
|
||||
ahci_trigger_irq(ad->hba, ad, PORT_IRQ_TF_ERR);
|
||||
ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_TFES);
|
||||
}
|
||||
|
||||
ahci_trigger_irq(ad->hba, ad, PORT_IRQ_PIOS_FIS);
|
||||
ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_PSS);
|
||||
}
|
||||
|
||||
static bool ahci_write_fis_d2h(AHCIDevice *ad)
|
||||
|
@ -809,10 +823,10 @@ static bool ahci_write_fis_d2h(AHCIDevice *ad)
|
|||
ad->port.ifs[0].status;
|
||||
|
||||
if (d2h_fis[2] & ERR_STAT) {
|
||||
ahci_trigger_irq(ad->hba, ad, PORT_IRQ_TF_ERR);
|
||||
ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_TFES);
|
||||
}
|
||||
|
||||
ahci_trigger_irq(ad->hba, ad, PORT_IRQ_D2H_REG_FIS);
|
||||
ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_DHRS);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -854,20 +868,22 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist,
|
|||
IDEBus *bus = &ad->port;
|
||||
BusState *qbus = BUS(bus);
|
||||
|
||||
trace_ahci_populate_sglist(ad->hba, ad->port_no);
|
||||
|
||||
if (!prdtl) {
|
||||
DPRINTF(ad->port_no, "no sg list given by guest: 0x%08x\n", opts);
|
||||
trace_ahci_populate_sglist_no_prdtl(ad->hba, ad->port_no, opts);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* map PRDT */
|
||||
if (!(prdt = dma_memory_map(ad->hba->as, prdt_addr, &prdt_len,
|
||||
DMA_DIRECTION_TO_DEVICE))){
|
||||
DPRINTF(ad->port_no, "map failed\n");
|
||||
trace_ahci_populate_sglist_no_map(ad->hba, ad->port_no);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (prdt_len < real_prdt_len) {
|
||||
DPRINTF(ad->port_no, "mapped less than expected\n");
|
||||
trace_ahci_populate_sglist_short_map(ad->hba, ad->port_no);
|
||||
r = -1;
|
||||
goto out;
|
||||
}
|
||||
|
@ -886,9 +902,8 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist,
|
|||
sum += tbl_entry_size;
|
||||
}
|
||||
if ((off_idx == -1) || (off_pos < 0) || (off_pos > tbl_entry_size)) {
|
||||
DPRINTF(ad->port_no, "%s: Incorrect offset! "
|
||||
"off_idx: %d, off_pos: %"PRId64"\n",
|
||||
__func__, off_idx, off_pos);
|
||||
trace_ahci_populate_sglist_bad_offset(ad->hba, ad->port_no,
|
||||
off_idx, off_pos);
|
||||
r = -1;
|
||||
goto out;
|
||||
}
|
||||
|
@ -934,8 +949,8 @@ static void ncq_finish(NCQTransferState *ncq_tfs)
|
|||
|
||||
ahci_write_fis_sdb(ncq_tfs->drive->hba, ncq_tfs);
|
||||
|
||||
DPRINTF(ncq_tfs->drive->port_no, "NCQ transfer tag %d finished\n",
|
||||
ncq_tfs->tag);
|
||||
trace_ncq_finish(ncq_tfs->drive->hba, ncq_tfs->drive->port_no,
|
||||
ncq_tfs->tag);
|
||||
|
||||
block_acct_done(blk_get_stats(ncq_tfs->drive->port.ifs[0].blk),
|
||||
&ncq_tfs->acct);
|
||||
|
@ -999,12 +1014,8 @@ static void execute_ncq_command(NCQTransferState *ncq_tfs)
|
|||
|
||||
switch (ncq_tfs->cmd) {
|
||||
case READ_FPDMA_QUEUED:
|
||||
DPRINTF(port, "NCQ reading %d sectors from LBA %"PRId64", tag %d\n",
|
||||
ncq_tfs->sector_count, ncq_tfs->lba, ncq_tfs->tag);
|
||||
|
||||
DPRINTF(port, "tag %d aio read %"PRId64"\n",
|
||||
ncq_tfs->tag, ncq_tfs->lba);
|
||||
|
||||
trace_execute_ncq_command_read(ad->hba, port, ncq_tfs->tag,
|
||||
ncq_tfs->sector_count, ncq_tfs->lba);
|
||||
dma_acct_start(ide_state->blk, &ncq_tfs->acct,
|
||||
&ncq_tfs->sglist, BLOCK_ACCT_READ);
|
||||
ncq_tfs->aiocb = dma_blk_read(ide_state->blk, &ncq_tfs->sglist,
|
||||
|
@ -1013,12 +1024,8 @@ static void execute_ncq_command(NCQTransferState *ncq_tfs)
|
|||
ncq_cb, ncq_tfs);
|
||||
break;
|
||||
case WRITE_FPDMA_QUEUED:
|
||||
DPRINTF(port, "NCQ writing %d sectors to LBA %"PRId64", tag %d\n",
|
||||
ncq_tfs->sector_count, ncq_tfs->lba, ncq_tfs->tag);
|
||||
|
||||
DPRINTF(port, "tag %d aio write %"PRId64"\n",
|
||||
ncq_tfs->tag, ncq_tfs->lba);
|
||||
|
||||
trace_execute_ncq_command_read(ad->hba, port, ncq_tfs->tag,
|
||||
ncq_tfs->sector_count, ncq_tfs->lba);
|
||||
dma_acct_start(ide_state->blk, &ncq_tfs->acct,
|
||||
&ncq_tfs->sglist, BLOCK_ACCT_WRITE);
|
||||
ncq_tfs->aiocb = dma_blk_write(ide_state->blk, &ncq_tfs->sglist,
|
||||
|
@ -1027,8 +1034,8 @@ static void execute_ncq_command(NCQTransferState *ncq_tfs)
|
|||
ncq_cb, ncq_tfs);
|
||||
break;
|
||||
default:
|
||||
DPRINTF(port, "error: unsupported NCQ command (0x%02x) received\n",
|
||||
ncq_tfs->cmd);
|
||||
trace_execute_ncq_command_unsup(ad->hba, port,
|
||||
ncq_tfs->tag, ncq_tfs->cmd);
|
||||
ncq_err(ncq_tfs);
|
||||
}
|
||||
}
|
||||
|
@ -1038,7 +1045,6 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis,
|
|||
uint8_t slot)
|
||||
{
|
||||
AHCIDevice *ad = &s->dev[port];
|
||||
IDEState *ide_state = &ad->port.ifs[0];
|
||||
NCQFrame *ncq_fis = (NCQFrame*)cmd_fis;
|
||||
uint8_t tag = ncq_fis->tag >> 3;
|
||||
NCQTransferState *ncq_tfs = &ad->ncq_tfs[tag];
|
||||
|
@ -1066,21 +1072,20 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis,
|
|||
|
||||
/* Sanity-check the NCQ packet */
|
||||
if (tag != slot) {
|
||||
DPRINTF(port, "Warn: NCQ slot (%d) did not match the given tag (%d)\n",
|
||||
slot, tag);
|
||||
trace_process_ncq_command_mismatch(s, port, tag, slot);
|
||||
}
|
||||
|
||||
if (ncq_fis->aux0 || ncq_fis->aux1 || ncq_fis->aux2 || ncq_fis->aux3) {
|
||||
DPRINTF(port, "Warn: Attempt to use NCQ auxiliary fields.\n");
|
||||
trace_process_ncq_command_aux(s, port, tag);
|
||||
}
|
||||
if (ncq_fis->prio || ncq_fis->icc) {
|
||||
DPRINTF(port, "Warn: Unsupported attempt to use PRIO/ICC fields\n");
|
||||
trace_process_ncq_command_prioicc(s, port, tag);
|
||||
}
|
||||
if (ncq_fis->fua & NCQ_FIS_FUA_MASK) {
|
||||
DPRINTF(port, "Warn: Unsupported attempt to use Force Unit Access\n");
|
||||
trace_process_ncq_command_fua(s, port, tag);
|
||||
}
|
||||
if (ncq_fis->tag & NCQ_FIS_RARC_MASK) {
|
||||
DPRINTF(port, "Warn: Unsupported attempt to use Rebuild Assist\n");
|
||||
trace_process_ncq_command_rarc(s, port, tag);
|
||||
}
|
||||
|
||||
ncq_tfs->sector_count = ((ncq_fis->sector_count_high << 8) |
|
||||
|
@ -1096,19 +1101,17 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis,
|
|||
"is smaller than the requested size (0x%zx)",
|
||||
ncq_tfs->sglist.size, size);
|
||||
ncq_err(ncq_tfs);
|
||||
ahci_trigger_irq(ad->hba, ad, PORT_IRQ_OVERFLOW);
|
||||
ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_OFS);
|
||||
return;
|
||||
} else if (ncq_tfs->sglist.size != size) {
|
||||
DPRINTF(port, "Warn: PRDTL (0x%zx)"
|
||||
" does not match requested size (0x%zx)",
|
||||
ncq_tfs->sglist.size, size);
|
||||
trace_process_ncq_command_large(s, port, tag,
|
||||
ncq_tfs->sglist.size, size);
|
||||
}
|
||||
|
||||
DPRINTF(port, "NCQ transfer LBA from %"PRId64" to %"PRId64", "
|
||||
"drive max %"PRId64"\n",
|
||||
ncq_tfs->lba, ncq_tfs->lba + ncq_tfs->sector_count - 1,
|
||||
ide_state->nb_sectors - 1);
|
||||
|
||||
trace_process_ncq_command(s, port, tag,
|
||||
ncq_fis->command,
|
||||
ncq_tfs->lba,
|
||||
ncq_tfs->lba + ncq_tfs->sector_count - 1);
|
||||
execute_ncq_command(ncq_tfs);
|
||||
}
|
||||
|
||||
|
@ -1129,16 +1132,14 @@ static void handle_reg_h2d_fis(AHCIState *s, int port,
|
|||
uint16_t opts = le16_to_cpu(cmd->opts);
|
||||
|
||||
if (cmd_fis[1] & 0x0F) {
|
||||
DPRINTF(port, "Port Multiplier not supported."
|
||||
" cmd_fis[0]=%02x cmd_fis[1]=%02x cmd_fis[2]=%02x\n",
|
||||
cmd_fis[0], cmd_fis[1], cmd_fis[2]);
|
||||
trace_handle_reg_h2d_fis_pmp(s, port, cmd_fis[1],
|
||||
cmd_fis[2], cmd_fis[3]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd_fis[1] & 0x70) {
|
||||
DPRINTF(port, "Reserved flags set in H2D Register FIS."
|
||||
" cmd_fis[0]=%02x cmd_fis[1]=%02x cmd_fis[2]=%02x\n",
|
||||
cmd_fis[0], cmd_fis[1], cmd_fis[2]);
|
||||
trace_handle_reg_h2d_fis_res(s, port, cmd_fis[1],
|
||||
cmd_fis[2], cmd_fis[3]);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1192,7 +1193,11 @@ static void handle_reg_h2d_fis(AHCIState *s, int port,
|
|||
* table to ide_state->io_buffer */
|
||||
if (opts & AHCI_CMD_ATAPI) {
|
||||
memcpy(ide_state->io_buffer, &cmd_fis[AHCI_COMMAND_TABLE_ACMD], 0x10);
|
||||
debug_print_fis(ide_state->io_buffer, 0x10);
|
||||
if (trace_event_get_state_backends(TRACE_HANDLE_REG_H2D_FIS_DUMP)) {
|
||||
char *pretty_fis = ahci_pretty_buffer_fis(ide_state->io_buffer, 0x10);
|
||||
trace_handle_reg_h2d_fis_dump(s, port, pretty_fis);
|
||||
g_free(pretty_fis);
|
||||
}
|
||||
s->dev[port].done_atapi_packet = false;
|
||||
/* XXX send PIO setup FIS */
|
||||
}
|
||||
|
@ -1216,12 +1221,12 @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot)
|
|||
|
||||
if (s->dev[port].port.ifs[0].status & (BUSY_STAT|DRQ_STAT)) {
|
||||
/* Engine currently busy, try again later */
|
||||
DPRINTF(port, "engine busy\n");
|
||||
trace_handle_cmd_busy(s, port);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!s->dev[port].lst) {
|
||||
DPRINTF(port, "error: lst not given but cmd handled");
|
||||
trace_handle_cmd_nolist(s, port);
|
||||
return -1;
|
||||
}
|
||||
cmd = get_cmd_header(s, port, slot);
|
||||
|
@ -1231,7 +1236,7 @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot)
|
|||
/* The device we are working for */
|
||||
ide_state = &s->dev[port].port.ifs[0];
|
||||
if (!ide_state->blk) {
|
||||
DPRINTF(port, "error: guest accessed unused port");
|
||||
trace_handle_cmd_badport(s, port);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1240,25 +1245,25 @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot)
|
|||
cmd_fis = dma_memory_map(s->as, tbl_addr, &cmd_len,
|
||||
DMA_DIRECTION_FROM_DEVICE);
|
||||
if (!cmd_fis) {
|
||||
DPRINTF(port, "error: guest passed us an invalid cmd fis\n");
|
||||
trace_handle_cmd_badfis(s, port);
|
||||
return -1;
|
||||
} else if (cmd_len != 0x80) {
|
||||
ahci_trigger_irq(s, &s->dev[port], PORT_IRQ_HBUS_ERR);
|
||||
DPRINTF(port, "error: dma_memory_map failed: "
|
||||
"(len(%02"PRIx64") != 0x80)\n",
|
||||
cmd_len);
|
||||
ahci_trigger_irq(s, &s->dev[port], AHCI_PORT_IRQ_BIT_HBFS);
|
||||
trace_handle_cmd_badmap(s, port, cmd_len);
|
||||
goto out;
|
||||
}
|
||||
debug_print_fis(cmd_fis, 0x80);
|
||||
|
||||
if (trace_event_get_state_backends(TRACE_HANDLE_CMD_FIS_DUMP)) {
|
||||
char *pretty_fis = ahci_pretty_buffer_fis(cmd_fis, 0x80);
|
||||
trace_handle_cmd_fis_dump(s, port, pretty_fis);
|
||||
g_free(pretty_fis);
|
||||
}
|
||||
switch (cmd_fis[0]) {
|
||||
case SATA_FIS_TYPE_REGISTER_H2D:
|
||||
handle_reg_h2d_fis(s, port, slot, cmd_fis);
|
||||
break;
|
||||
default:
|
||||
DPRINTF(port, "unknown command cmd_fis[0]=%02x cmd_fis[1]=%02x "
|
||||
"cmd_fis[2]=%02x\n", cmd_fis[0], cmd_fis[1],
|
||||
cmd_fis[2]);
|
||||
trace_handle_cmd_unhandled_fis(s, port,
|
||||
cmd_fis[0], cmd_fis[1], cmd_fis[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1299,9 +1304,9 @@ static void ahci_start_transfer(IDEDMA *dma)
|
|||
has_sglist = 1;
|
||||
}
|
||||
|
||||
DPRINTF(ad->port_no, "%sing %d bytes on %s w/%s sglist\n",
|
||||
is_write ? "writ" : "read", size, is_atapi ? "atapi" : "ata",
|
||||
has_sglist ? "" : "o");
|
||||
trace_ahci_start_transfer(ad->hba, ad->port_no, is_write ? "writ" : "read",
|
||||
size, is_atapi ? "atapi" : "ata",
|
||||
has_sglist ? "" : "o");
|
||||
|
||||
if (has_sglist && size) {
|
||||
if (is_write) {
|
||||
|
@ -1330,7 +1335,7 @@ static void ahci_start_dma(IDEDMA *dma, IDEState *s,
|
|||
BlockCompletionFunc *dma_cb)
|
||||
{
|
||||
AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
|
||||
DPRINTF(ad->port_no, "\n");
|
||||
trace_ahci_start_dma(ad->hba, ad->port_no);
|
||||
s->io_buffer_offset = 0;
|
||||
dma_cb(s, 0);
|
||||
}
|
||||
|
@ -1368,12 +1373,12 @@ static int32_t ahci_dma_prepare_buf(IDEDMA *dma, int32_t limit)
|
|||
|
||||
if (ahci_populate_sglist(ad, &s->sg, ad->cur_cmd,
|
||||
limit, s->io_buffer_offset) == -1) {
|
||||
DPRINTF(ad->port_no, "ahci_dma_prepare_buf failed.\n");
|
||||
trace_ahci_dma_prepare_buf_fail(ad->hba, ad->port_no);
|
||||
return -1;
|
||||
}
|
||||
s->io_buffer_size = s->sg.size;
|
||||
|
||||
DPRINTF(ad->port_no, "len=%#x\n", s->io_buffer_size);
|
||||
trace_ahci_dma_prepare_buf(ad->hba, ad->port_no, limit, s->io_buffer_size);
|
||||
return s->io_buffer_size;
|
||||
}
|
||||
|
||||
|
@ -1409,11 +1414,9 @@ static int ahci_dma_rw_buf(IDEDMA *dma, int is_write)
|
|||
|
||||
/* free sglist, update byte count */
|
||||
dma_buf_commit(s, l);
|
||||
|
||||
s->io_buffer_index += l;
|
||||
|
||||
DPRINTF(ad->port_no, "len=%#x\n", l);
|
||||
|
||||
trace_ahci_dma_rw_buf(ad->hba, ad->port_no, l);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1421,7 +1424,7 @@ static void ahci_cmd_done(IDEDMA *dma)
|
|||
{
|
||||
AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
|
||||
|
||||
DPRINTF(ad->port_no, "cmd done\n");
|
||||
trace_ahci_cmd_done(ad->hba, ad->port_no);
|
||||
|
||||
/* update d2h status */
|
||||
ahci_write_fis_d2h(ad);
|
||||
|
@ -1495,6 +1498,7 @@ void ahci_uninit(AHCIState *s)
|
|||
|
||||
ide_exit(s);
|
||||
}
|
||||
object_unparent(OBJECT(&ad->port));
|
||||
}
|
||||
|
||||
g_free(s->dev);
|
||||
|
@ -1505,6 +1509,8 @@ void ahci_reset(AHCIState *s)
|
|||
AHCIPortRegs *pr;
|
||||
int i;
|
||||
|
||||
trace_ahci_reset(s);
|
||||
|
||||
s->control_regs.irqstatus = 0;
|
||||
/* AHCI Enable (AE)
|
||||
* The implementation of this bit is dependent upon the value of the
|
||||
|
@ -1755,6 +1761,7 @@ static uint64_t allwinner_ahci_mem_read(void *opaque, hwaddr addr,
|
|||
unsigned size)
|
||||
{
|
||||
AllwinnerAHCIState *a = opaque;
|
||||
AHCIState *s = &(SYSBUS_AHCI(a)->ahci);
|
||||
uint64_t val = a->regs[addr/4];
|
||||
|
||||
switch (addr / 4) {
|
||||
|
@ -1765,8 +1772,7 @@ static uint64_t allwinner_ahci_mem_read(void *opaque, hwaddr addr,
|
|||
val &= ~(0x1 << 24);
|
||||
break;
|
||||
}
|
||||
DPRINTF(-1, "addr=0x%" HWADDR_PRIx " val=0x%" PRIx64 ", size=%d\n",
|
||||
addr, val, size);
|
||||
trace_allwinner_ahci_mem_read(s, a, addr, val, size);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
@ -1774,9 +1780,9 @@ static void allwinner_ahci_mem_write(void *opaque, hwaddr addr,
|
|||
uint64_t val, unsigned size)
|
||||
{
|
||||
AllwinnerAHCIState *a = opaque;
|
||||
AHCIState *s = &(SYSBUS_AHCI(a)->ahci);
|
||||
|
||||
DPRINTF(-1, "addr=0x%" HWADDR_PRIx " val=0x%" PRIx64 ", size=%d\n",
|
||||
addr, val, size);
|
||||
trace_allwinner_ahci_mem_write(s, a, addr, val, size);
|
||||
a->regs[addr/4] = val;
|
||||
}
|
||||
|
||||
|
|
|
@ -91,6 +91,31 @@
|
|||
#define PORT_CMD_ISSUE 0x38 /* command issue */
|
||||
#define PORT_RESERVED 0x3c /* reserved */
|
||||
|
||||
/* Port interrupt bit descriptors */
|
||||
enum AHCIPortIRQ {
|
||||
AHCI_PORT_IRQ_BIT_DHRS = 0,
|
||||
AHCI_PORT_IRQ_BIT_PSS = 1,
|
||||
AHCI_PORT_IRQ_BIT_DSS = 2,
|
||||
AHCI_PORT_IRQ_BIT_SDBS = 3,
|
||||
AHCI_PORT_IRQ_BIT_UFS = 4,
|
||||
AHCI_PORT_IRQ_BIT_DPS = 5,
|
||||
AHCI_PORT_IRQ_BIT_PCS = 6,
|
||||
AHCI_PORT_IRQ_BIT_DMPS = 7,
|
||||
/* RESERVED */
|
||||
AHCI_PORT_IRQ_BIT_PRCS = 22,
|
||||
AHCI_PORT_IRQ_BIT_IPMS = 23,
|
||||
AHCI_PORT_IRQ_BIT_OFS = 24,
|
||||
/* RESERVED */
|
||||
AHCI_PORT_IRQ_BIT_INFS = 26,
|
||||
AHCI_PORT_IRQ_BIT_IFS = 27,
|
||||
AHCI_PORT_IRQ_BIT_HBDS = 28,
|
||||
AHCI_PORT_IRQ_BIT_HBFS = 29,
|
||||
AHCI_PORT_IRQ_BIT_TFES = 30,
|
||||
AHCI_PORT_IRQ_BIT_CPDS = 31,
|
||||
AHCI_PORT_IRQ__COUNT = 32
|
||||
};
|
||||
|
||||
|
||||
/* PORT_IRQ_{STAT,MASK} bits */
|
||||
#define PORT_IRQ_COLD_PRES (1U << 31) /* cold presence detect */
|
||||
#define PORT_IRQ_TF_ERR (1 << 30) /* task file error */
|
||||
|
@ -98,18 +123,19 @@
|
|||
#define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */
|
||||
#define PORT_IRQ_IF_ERR (1 << 27) /* interface fatal error */
|
||||
#define PORT_IRQ_IF_NONFATAL (1 << 26) /* interface non-fatal error */
|
||||
/* reserved */
|
||||
#define PORT_IRQ_OVERFLOW (1 << 24) /* xfer exhausted available S/G */
|
||||
#define PORT_IRQ_BAD_PMP (1 << 23) /* incorrect port multiplier */
|
||||
|
||||
#define PORT_IRQ_PHYRDY (1 << 22) /* PhyRdy changed */
|
||||
#define PORT_IRQ_DEV_ILCK (1 << 7) /* device interlock */
|
||||
#define PORT_IRQ_CONNECT (1 << 6) /* port connect change status */
|
||||
#define PORT_IRQ_SG_DONE (1 << 5) /* descriptor processed */
|
||||
#define PORT_IRQ_UNK_FIS (1 << 4) /* unknown FIS rx'd */
|
||||
#define PORT_IRQ_SDB_FIS (1 << 3) /* Set Device Bits FIS rx'd */
|
||||
#define PORT_IRQ_DMAS_FIS (1 << 2) /* DMA Setup FIS rx'd */
|
||||
#define PORT_IRQ_PIOS_FIS (1 << 1) /* PIO Setup FIS rx'd */
|
||||
#define PORT_IRQ_D2H_REG_FIS (1 << 0) /* D2H Register FIS rx'd */
|
||||
/* reserved */
|
||||
#define PORT_IRQ_DEV_ILCK (1 << 7) /* device interlock */
|
||||
#define PORT_IRQ_CONNECT (1 << 6) /* port connect change status */
|
||||
#define PORT_IRQ_SG_DONE (1 << 5) /* descriptor processed */
|
||||
#define PORT_IRQ_UNK_FIS (1 << 4) /* unknown FIS rx'd */
|
||||
#define PORT_IRQ_SDB_FIS (1 << 3) /* Set Device Bits FIS rx'd */
|
||||
#define PORT_IRQ_DMAS_FIS (1 << 2) /* DMA Setup FIS rx'd */
|
||||
#define PORT_IRQ_PIOS_FIS (1 << 1) /* PIO Setup FIS rx'd */
|
||||
#define PORT_IRQ_D2H_REG_FIS (1 << 0) /* D2H Register FIS rx'd */
|
||||
|
||||
#define PORT_IRQ_FREEZE (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR | \
|
||||
PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY | \
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "hw/ide/internal.h"
|
||||
#include "hw/scsi/scsi.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define ATAPI_SECTOR_BITS (2 + BDRV_SECTOR_BITS)
|
||||
#define ATAPI_SECTOR_SIZE (1 << ATAPI_SECTOR_BITS)
|
||||
|
@ -116,9 +117,7 @@ cd_read_sector_sync(IDEState *s)
|
|||
block_acct_start(blk_get_stats(s->blk), &s->acct,
|
||||
ATAPI_SECTOR_SIZE, BLOCK_ACCT_READ);
|
||||
|
||||
#ifdef DEBUG_IDE_ATAPI
|
||||
printf("cd_read_sector_sync: lba=%d\n", s->lba);
|
||||
#endif
|
||||
trace_cd_read_sector_sync(s->lba);
|
||||
|
||||
switch (s->cd_sector_size) {
|
||||
case 2048:
|
||||
|
@ -152,9 +151,7 @@ static void cd_read_sector_cb(void *opaque, int ret)
|
|||
{
|
||||
IDEState *s = opaque;
|
||||
|
||||
#ifdef DEBUG_IDE_ATAPI
|
||||
printf("cd_read_sector_cb: lba=%d ret=%d\n", s->lba, ret);
|
||||
#endif
|
||||
trace_cd_read_sector_cb(s->lba, ret);
|
||||
|
||||
if (ret < 0) {
|
||||
block_acct_failed(blk_get_stats(s->blk), &s->acct);
|
||||
|
@ -188,9 +185,7 @@ static int cd_read_sector(IDEState *s)
|
|||
s->iov.iov_len = ATAPI_SECTOR_SIZE;
|
||||
qemu_iovec_init_external(&s->qiov, &s->iov, 1);
|
||||
|
||||
#ifdef DEBUG_IDE_ATAPI
|
||||
printf("cd_read_sector: lba=%d\n", s->lba);
|
||||
#endif
|
||||
trace_cd_read_sector(s->lba);
|
||||
|
||||
block_acct_start(blk_get_stats(s->blk), &s->acct,
|
||||
ATAPI_SECTOR_SIZE, BLOCK_ACCT_READ);
|
||||
|
@ -213,9 +208,7 @@ void ide_atapi_cmd_ok(IDEState *s)
|
|||
|
||||
void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc)
|
||||
{
|
||||
#ifdef DEBUG_IDE_ATAPI
|
||||
printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc);
|
||||
#endif
|
||||
trace_ide_atapi_cmd_error(s, sense_key, asc);
|
||||
s->error = sense_key << 4;
|
||||
s->status = READY_STAT | ERR_STAT;
|
||||
s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
|
||||
|
@ -252,19 +245,14 @@ static uint16_t atapi_byte_count_limit(IDEState *s)
|
|||
void ide_atapi_cmd_reply_end(IDEState *s)
|
||||
{
|
||||
int byte_count_limit, size, ret;
|
||||
#ifdef DEBUG_IDE_ATAPI
|
||||
printf("reply: tx_size=%d elem_tx_size=%d index=%d\n",
|
||||
s->packet_transfer_size,
|
||||
s->elementary_transfer_size,
|
||||
s->io_buffer_index);
|
||||
#endif
|
||||
trace_ide_atapi_cmd_reply_end(s, s->packet_transfer_size,
|
||||
s->elementary_transfer_size,
|
||||
s->io_buffer_index);
|
||||
if (s->packet_transfer_size <= 0) {
|
||||
/* end of transfer */
|
||||
ide_atapi_cmd_ok(s);
|
||||
ide_set_irq(s->bus);
|
||||
#ifdef DEBUG_IDE_ATAPI
|
||||
printf("end of transfer, status=0x%x\n", s->status);
|
||||
#endif
|
||||
trace_ide_atapi_cmd_reply_end_eot(s, s->status);
|
||||
} else {
|
||||
/* see if a new sector must be read */
|
||||
if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) {
|
||||
|
@ -300,9 +288,7 @@ void ide_atapi_cmd_reply_end(IDEState *s)
|
|||
/* a new transfer is needed */
|
||||
s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO;
|
||||
byte_count_limit = atapi_byte_count_limit(s);
|
||||
#ifdef DEBUG_IDE_ATAPI
|
||||
printf("byte_count_limit=%d\n", byte_count_limit);
|
||||
#endif
|
||||
trace_ide_atapi_cmd_reply_end_bcl(s, byte_count_limit);
|
||||
size = s->packet_transfer_size;
|
||||
if (size > byte_count_limit) {
|
||||
/* byte count limit must be even if this case */
|
||||
|
@ -324,9 +310,7 @@ void ide_atapi_cmd_reply_end(IDEState *s)
|
|||
ide_transfer_start(s, s->io_buffer + s->io_buffer_index - size,
|
||||
size, ide_atapi_cmd_reply_end);
|
||||
ide_set_irq(s->bus);
|
||||
#ifdef DEBUG_IDE_ATAPI
|
||||
printf("status=0x%x\n", s->status);
|
||||
#endif
|
||||
trace_ide_atapi_cmd_reply_end_new(s, s->status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -368,9 +352,7 @@ static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors,
|
|||
|
||||
static void ide_atapi_cmd_check_status(IDEState *s)
|
||||
{
|
||||
#ifdef DEBUG_IDE_ATAPI
|
||||
printf("atapi_cmd_check_status\n");
|
||||
#endif
|
||||
trace_ide_atapi_cmd_check_status(s);
|
||||
s->error = MC_ERR | (UNIT_ATTENTION << 4);
|
||||
s->status = ERR_STAT;
|
||||
s->nsector = 0;
|
||||
|
@ -434,10 +416,7 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret)
|
|||
s->io_buffer_size = n * 2048;
|
||||
data_offset = 0;
|
||||
}
|
||||
#ifdef DEBUG_AIO
|
||||
printf("aio_read_cd: lba=%u n=%d\n", s->lba, n);
|
||||
#endif
|
||||
|
||||
trace_ide_atapi_cmd_read_dma_cb_aio(s, s->lba, n);
|
||||
s->bus->dma->iov.iov_base = (void *)(s->io_buffer + data_offset);
|
||||
s->bus->dma->iov.iov_len = n * ATAPI_SECTOR_SIZE;
|
||||
qemu_iovec_init_external(&s->bus->dma->qiov, &s->bus->dma->iov, 1);
|
||||
|
@ -477,10 +456,8 @@ static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors,
|
|||
static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors,
|
||||
int sector_size)
|
||||
{
|
||||
#ifdef DEBUG_IDE_ATAPI
|
||||
printf("read %s: LBA=%d nb_sectors=%d\n", s->atapi_dma ? "dma" : "pio",
|
||||
lba, nb_sectors);
|
||||
#endif
|
||||
trace_ide_atapi_cmd_read(s, s->atapi_dma ? "dma" : "pio",
|
||||
lba, nb_sectors);
|
||||
if (s->atapi_dma) {
|
||||
ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size);
|
||||
} else {
|
||||
|
@ -1330,16 +1307,18 @@ void ide_atapi_cmd(IDEState *s)
|
|||
uint8_t *buf = s->io_buffer;
|
||||
const struct AtapiCmd *cmd = &atapi_cmd_table[s->io_buffer[0]];
|
||||
|
||||
#ifdef DEBUG_IDE_ATAPI
|
||||
{
|
||||
trace_ide_atapi_cmd(s, s->io_buffer[0]);
|
||||
|
||||
if (trace_event_get_state_backends(TRACE_IDE_ATAPI_CMD_PACKET)) {
|
||||
/* Each pretty-printed byte needs two bytes and a space; */
|
||||
char *ppacket = g_malloc(ATAPI_PACKET_SIZE * 3 + 1);
|
||||
int i;
|
||||
printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8));
|
||||
for(i = 0; i < ATAPI_PACKET_SIZE; i++) {
|
||||
printf(" %02x", buf[i]);
|
||||
for (i = 0; i < ATAPI_PACKET_SIZE; i++) {
|
||||
sprintf(ppacket + (i * 3), "%02x ", buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
trace_ide_atapi_cmd_packet(s, s->lcyl | (s->hcyl << 8), ppacket);
|
||||
g_free(ppacket);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If there's a UNIT_ATTENTION condition pending, only command flagged with
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "sysemu/dma.h"
|
||||
|
||||
#include "hw/ide/pci.h"
|
||||
#include "trace.h"
|
||||
|
||||
/* CMD646 specific */
|
||||
#define CFR 0x50
|
||||
|
@ -195,9 +196,8 @@ static uint64_t bmdma_read(void *opaque, hwaddr addr,
|
|||
val = 0xff;
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG_IDE
|
||||
printf("bmdma: readb " TARGET_FMT_plx " : 0x%02x\n", addr, val);
|
||||
#endif
|
||||
|
||||
trace_bmdma_read_cmd646(addr, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
@ -211,9 +211,7 @@ static void bmdma_write(void *opaque, hwaddr addr,
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_IDE
|
||||
printf("bmdma: writeb " TARGET_FMT_plx " : 0x%" PRIx64 "\n", addr, val);
|
||||
#endif
|
||||
trace_bmdma_write_cmd646(addr, val);
|
||||
switch(addr & 3) {
|
||||
case 0:
|
||||
bmdma_cmd_writeb(bm, val);
|
||||
|
|
192
hw/ide/core.c
192
hw/ide/core.c
|
@ -34,8 +34,10 @@
|
|||
#include "hw/block/block.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
#include "hw/ide/internal.h"
|
||||
#include "trace.h"
|
||||
|
||||
/* These values were based on a Seagate ST3500418AS but have been modified
|
||||
to make more sense in QEMU */
|
||||
|
@ -57,6 +59,21 @@ static const int smart_attributes[][12] = {
|
|||
{ 190, 0x03, 0x00, 0x45, 0x45, 0x1f, 0x00, 0x1f, 0x1f, 0x00, 0x00, 0x32},
|
||||
};
|
||||
|
||||
const char *IDE_DMA_CMD_lookup[IDE_DMA__COUNT] = {
|
||||
[IDE_DMA_READ] = "DMA READ",
|
||||
[IDE_DMA_WRITE] = "DMA WRITE",
|
||||
[IDE_DMA_TRIM] = "DMA TRIM",
|
||||
[IDE_DMA_ATAPI] = "DMA ATAPI"
|
||||
};
|
||||
|
||||
static const char *IDE_DMA_CMD_str(enum ide_dma_cmd enval)
|
||||
{
|
||||
if (enval >= IDE_DMA__BEGIN && enval < IDE_DMA__COUNT) {
|
||||
return IDE_DMA_CMD_lookup[enval];
|
||||
}
|
||||
return "DMA UNKNOWN CMD";
|
||||
}
|
||||
|
||||
static void ide_dummy_transfer_stop(IDEState *s);
|
||||
|
||||
static void padstr(char *str, const char *src, int len)
|
||||
|
@ -656,10 +673,7 @@ void ide_cancel_dma_sync(IDEState *s)
|
|||
* write requests) pending and we can avoid to drain. */
|
||||
QLIST_FOREACH(req, &s->buffered_requests, list) {
|
||||
if (!req->orphaned) {
|
||||
#ifdef DEBUG_IDE
|
||||
printf("%s: invoking cb %p of buffered request %p with"
|
||||
" -ECANCELED\n", __func__, req->original_cb, req);
|
||||
#endif
|
||||
trace_ide_cancel_dma_sync_buffered(req->original_cb, req);
|
||||
req->original_cb(req->original_opaque, -ECANCELED);
|
||||
}
|
||||
req->orphaned = true;
|
||||
|
@ -678,9 +692,7 @@ void ide_cancel_dma_sync(IDEState *s)
|
|||
* aio operation with preadv/pwritev.
|
||||
*/
|
||||
if (s->bus->dma->aiocb) {
|
||||
#ifdef DEBUG_IDE
|
||||
printf("%s: draining all remaining requests", __func__);
|
||||
#endif
|
||||
trace_ide_cancel_dma_sync_remaining();
|
||||
blk_drain(s->blk);
|
||||
assert(s->bus->dma->aiocb == NULL);
|
||||
}
|
||||
|
@ -741,9 +753,7 @@ static void ide_sector_read(IDEState *s)
|
|||
n = s->req_nb_sectors;
|
||||
}
|
||||
|
||||
#if defined(DEBUG_IDE)
|
||||
printf("sector=%" PRId64 "\n", sector_num);
|
||||
#endif
|
||||
trace_ide_sector_read(sector_num, n);
|
||||
|
||||
if (!ide_sect_range_ok(s, sector_num, n)) {
|
||||
ide_rw_error(s);
|
||||
|
@ -866,10 +876,7 @@ static void ide_dma_cb(void *opaque, int ret)
|
|||
goto eot;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_AIO
|
||||
printf("ide_dma_cb: sector_num=%" PRId64 " n=%d, cmd_cmd=%d\n",
|
||||
sector_num, n, s->dma_cmd);
|
||||
#endif
|
||||
trace_ide_dma_cb(s, sector_num, n, IDE_DMA_CMD_str(s->dma_cmd));
|
||||
|
||||
if ((s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) &&
|
||||
!ide_sect_range_ok(s, sector_num, n)) {
|
||||
|
@ -1005,14 +1012,14 @@ static void ide_sector_write(IDEState *s)
|
|||
|
||||
s->status = READY_STAT | SEEK_STAT | BUSY_STAT;
|
||||
sector_num = ide_get_sector(s);
|
||||
#if defined(DEBUG_IDE)
|
||||
printf("sector=%" PRId64 "\n", sector_num);
|
||||
#endif
|
||||
|
||||
n = s->nsector;
|
||||
if (n > s->req_nb_sectors) {
|
||||
n = s->req_nb_sectors;
|
||||
}
|
||||
|
||||
trace_ide_sector_write(sector_num, n);
|
||||
|
||||
if (!ide_sect_range_ok(s, sector_num, n)) {
|
||||
ide_rw_error(s);
|
||||
block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_WRITE);
|
||||
|
@ -1191,60 +1198,83 @@ static void ide_clear_hob(IDEBus *bus)
|
|||
bus->ifs[1].select &= ~(1 << 7);
|
||||
}
|
||||
|
||||
/* IOport [W]rite [R]egisters */
|
||||
enum ATA_IOPORT_WR {
|
||||
ATA_IOPORT_WR_DATA = 0,
|
||||
ATA_IOPORT_WR_FEATURES = 1,
|
||||
ATA_IOPORT_WR_SECTOR_COUNT = 2,
|
||||
ATA_IOPORT_WR_SECTOR_NUMBER = 3,
|
||||
ATA_IOPORT_WR_CYLINDER_LOW = 4,
|
||||
ATA_IOPORT_WR_CYLINDER_HIGH = 5,
|
||||
ATA_IOPORT_WR_DEVICE_HEAD = 6,
|
||||
ATA_IOPORT_WR_COMMAND = 7,
|
||||
ATA_IOPORT_WR_NUM_REGISTERS,
|
||||
};
|
||||
|
||||
const char *ATA_IOPORT_WR_lookup[ATA_IOPORT_WR_NUM_REGISTERS] = {
|
||||
[ATA_IOPORT_WR_DATA] = "Data",
|
||||
[ATA_IOPORT_WR_FEATURES] = "Features",
|
||||
[ATA_IOPORT_WR_SECTOR_COUNT] = "Sector Count",
|
||||
[ATA_IOPORT_WR_SECTOR_NUMBER] = "Sector Number",
|
||||
[ATA_IOPORT_WR_CYLINDER_LOW] = "Cylinder Low",
|
||||
[ATA_IOPORT_WR_CYLINDER_HIGH] = "Cylinder High",
|
||||
[ATA_IOPORT_WR_DEVICE_HEAD] = "Device/Head",
|
||||
[ATA_IOPORT_WR_COMMAND] = "Command"
|
||||
};
|
||||
|
||||
void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
||||
{
|
||||
IDEBus *bus = opaque;
|
||||
IDEState *s = idebus_active_if(bus);
|
||||
int reg_num = addr & 7;
|
||||
|
||||
#ifdef DEBUG_IDE
|
||||
printf("IDE: write addr=0x%x val=0x%02x\n", addr, val);
|
||||
#endif
|
||||
|
||||
addr &= 7;
|
||||
trace_ide_ioport_write(addr, ATA_IOPORT_WR_lookup[reg_num], val, bus, s);
|
||||
|
||||
/* ignore writes to command block while busy with previous command */
|
||||
if (addr != 7 && (idebus_active_if(bus)->status & (BUSY_STAT|DRQ_STAT)))
|
||||
if (reg_num != 7 && (s->status & (BUSY_STAT|DRQ_STAT))) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(addr) {
|
||||
switch (reg_num) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
ide_clear_hob(bus);
|
||||
case ATA_IOPORT_WR_FEATURES:
|
||||
ide_clear_hob(bus);
|
||||
/* NOTE: data is written to the two drives */
|
||||
bus->ifs[0].hob_feature = bus->ifs[0].feature;
|
||||
bus->ifs[1].hob_feature = bus->ifs[1].feature;
|
||||
bus->ifs[0].hob_feature = bus->ifs[0].feature;
|
||||
bus->ifs[1].hob_feature = bus->ifs[1].feature;
|
||||
bus->ifs[0].feature = val;
|
||||
bus->ifs[1].feature = val;
|
||||
break;
|
||||
case 2:
|
||||
case ATA_IOPORT_WR_SECTOR_COUNT:
|
||||
ide_clear_hob(bus);
|
||||
bus->ifs[0].hob_nsector = bus->ifs[0].nsector;
|
||||
bus->ifs[1].hob_nsector = bus->ifs[1].nsector;
|
||||
bus->ifs[0].nsector = val;
|
||||
bus->ifs[1].nsector = val;
|
||||
break;
|
||||
case 3:
|
||||
case ATA_IOPORT_WR_SECTOR_NUMBER:
|
||||
ide_clear_hob(bus);
|
||||
bus->ifs[0].hob_sector = bus->ifs[0].sector;
|
||||
bus->ifs[1].hob_sector = bus->ifs[1].sector;
|
||||
bus->ifs[0].sector = val;
|
||||
bus->ifs[1].sector = val;
|
||||
break;
|
||||
case 4:
|
||||
case ATA_IOPORT_WR_CYLINDER_LOW:
|
||||
ide_clear_hob(bus);
|
||||
bus->ifs[0].hob_lcyl = bus->ifs[0].lcyl;
|
||||
bus->ifs[1].hob_lcyl = bus->ifs[1].lcyl;
|
||||
bus->ifs[0].lcyl = val;
|
||||
bus->ifs[1].lcyl = val;
|
||||
break;
|
||||
case 5:
|
||||
case ATA_IOPORT_WR_CYLINDER_HIGH:
|
||||
ide_clear_hob(bus);
|
||||
bus->ifs[0].hob_hcyl = bus->ifs[0].hcyl;
|
||||
bus->ifs[1].hob_hcyl = bus->ifs[1].hcyl;
|
||||
bus->ifs[0].hcyl = val;
|
||||
bus->ifs[1].hcyl = val;
|
||||
break;
|
||||
case 6:
|
||||
case ATA_IOPORT_WR_DEVICE_HEAD:
|
||||
/* FIXME: HOB readback uses bit 7 */
|
||||
bus->ifs[0].select = (val & ~0x10) | 0xa0;
|
||||
bus->ifs[1].select = (val | 0x10) | 0xa0;
|
||||
|
@ -1252,7 +1282,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
|||
bus->unit = (val >> 4) & 1;
|
||||
break;
|
||||
default:
|
||||
case 7:
|
||||
case ATA_IOPORT_WR_COMMAND:
|
||||
/* command */
|
||||
ide_exec_cmd(bus, val);
|
||||
break;
|
||||
|
@ -1261,9 +1291,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
|||
|
||||
static void ide_reset(IDEState *s)
|
||||
{
|
||||
#ifdef DEBUG_IDE
|
||||
printf("ide: reset\n");
|
||||
#endif
|
||||
trace_ide_reset(s);
|
||||
|
||||
if (s->pio_aiocb) {
|
||||
blk_aio_cancel(s->pio_aiocb);
|
||||
|
@ -2021,10 +2049,9 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
|
|||
IDEState *s;
|
||||
bool complete;
|
||||
|
||||
#if defined(DEBUG_IDE)
|
||||
printf("ide: CMD=%02x\n", val);
|
||||
#endif
|
||||
s = idebus_active_if(bus);
|
||||
trace_ide_exec_cmd(bus, s, val);
|
||||
|
||||
/* ignore commands to non existent slave */
|
||||
if (s != bus->ifs && !s->blk) {
|
||||
return;
|
||||
|
@ -2062,22 +2089,46 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
|
||||
/* IOport [R]ead [R]egisters */
|
||||
enum ATA_IOPORT_RR {
|
||||
ATA_IOPORT_RR_DATA = 0,
|
||||
ATA_IOPORT_RR_ERROR = 1,
|
||||
ATA_IOPORT_RR_SECTOR_COUNT = 2,
|
||||
ATA_IOPORT_RR_SECTOR_NUMBER = 3,
|
||||
ATA_IOPORT_RR_CYLINDER_LOW = 4,
|
||||
ATA_IOPORT_RR_CYLINDER_HIGH = 5,
|
||||
ATA_IOPORT_RR_DEVICE_HEAD = 6,
|
||||
ATA_IOPORT_RR_STATUS = 7,
|
||||
ATA_IOPORT_RR_NUM_REGISTERS,
|
||||
};
|
||||
|
||||
const char *ATA_IOPORT_RR_lookup[ATA_IOPORT_RR_NUM_REGISTERS] = {
|
||||
[ATA_IOPORT_RR_DATA] = "Data",
|
||||
[ATA_IOPORT_RR_ERROR] = "Error",
|
||||
[ATA_IOPORT_RR_SECTOR_COUNT] = "Sector Count",
|
||||
[ATA_IOPORT_RR_SECTOR_NUMBER] = "Sector Number",
|
||||
[ATA_IOPORT_RR_CYLINDER_LOW] = "Cylinder Low",
|
||||
[ATA_IOPORT_RR_CYLINDER_HIGH] = "Cylinder High",
|
||||
[ATA_IOPORT_RR_DEVICE_HEAD] = "Device/Head",
|
||||
[ATA_IOPORT_RR_STATUS] = "Status"
|
||||
};
|
||||
|
||||
uint32_t ide_ioport_read(void *opaque, uint32_t addr)
|
||||
{
|
||||
IDEBus *bus = opaque;
|
||||
IDEState *s = idebus_active_if(bus);
|
||||
uint32_t addr;
|
||||
uint32_t reg_num;
|
||||
int ret, hob;
|
||||
|
||||
addr = addr1 & 7;
|
||||
reg_num = addr & 7;
|
||||
/* FIXME: HOB readback uses bit 7, but it's always set right now */
|
||||
//hob = s->select & (1 << 7);
|
||||
hob = 0;
|
||||
switch(addr) {
|
||||
case 0:
|
||||
switch (reg_num) {
|
||||
case ATA_IOPORT_RR_DATA:
|
||||
ret = 0xff;
|
||||
break;
|
||||
case 1:
|
||||
case ATA_IOPORT_RR_ERROR:
|
||||
if ((!bus->ifs[0].blk && !bus->ifs[1].blk) ||
|
||||
(s != bus->ifs && !s->blk)) {
|
||||
ret = 0;
|
||||
|
@ -2087,7 +2138,7 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
|
|||
ret = s->hob_feature;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
case ATA_IOPORT_RR_SECTOR_COUNT:
|
||||
if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
|
||||
ret = 0;
|
||||
} else if (!hob) {
|
||||
|
@ -2096,7 +2147,7 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
|
|||
ret = s->hob_nsector;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case ATA_IOPORT_RR_SECTOR_NUMBER:
|
||||
if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
|
||||
ret = 0;
|
||||
} else if (!hob) {
|
||||
|
@ -2105,7 +2156,7 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
|
|||
ret = s->hob_sector;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
case ATA_IOPORT_RR_CYLINDER_LOW:
|
||||
if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
|
||||
ret = 0;
|
||||
} else if (!hob) {
|
||||
|
@ -2114,7 +2165,7 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
|
|||
ret = s->hob_lcyl;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
case ATA_IOPORT_RR_CYLINDER_HIGH:
|
||||
if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
|
||||
ret = 0;
|
||||
} else if (!hob) {
|
||||
|
@ -2123,7 +2174,7 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
|
|||
ret = s->hob_hcyl;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
case ATA_IOPORT_RR_DEVICE_HEAD:
|
||||
if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
|
||||
ret = 0;
|
||||
} else {
|
||||
|
@ -2131,7 +2182,7 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
|
|||
}
|
||||
break;
|
||||
default:
|
||||
case 7:
|
||||
case ATA_IOPORT_RR_STATUS:
|
||||
if ((!bus->ifs[0].blk && !bus->ifs[1].blk) ||
|
||||
(s != bus->ifs && !s->blk)) {
|
||||
ret = 0;
|
||||
|
@ -2141,9 +2192,8 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
|
|||
qemu_irq_lower(bus->irq);
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG_IDE
|
||||
printf("ide: read addr=0x%x val=%02x\n", addr1, ret);
|
||||
#endif
|
||||
|
||||
trace_ide_ioport_read(addr, ATA_IOPORT_RR_lookup[reg_num], ret, bus, s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2159,9 +2209,8 @@ uint32_t ide_status_read(void *opaque, uint32_t addr)
|
|||
} else {
|
||||
ret = s->status;
|
||||
}
|
||||
#ifdef DEBUG_IDE
|
||||
printf("ide: read status addr=0x%x val=%02x\n", addr, ret);
|
||||
#endif
|
||||
|
||||
trace_ide_status_read(addr, ret, bus, s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2171,9 +2220,8 @@ void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val)
|
|||
IDEState *s;
|
||||
int i;
|
||||
|
||||
#ifdef DEBUG_IDE
|
||||
printf("ide: write control addr=0x%x val=%02x\n", addr, val);
|
||||
#endif
|
||||
trace_ide_cmd_write(addr, val, bus);
|
||||
|
||||
/* common for both drives */
|
||||
if (!(bus->cmd & IDE_CMD_RESET) &&
|
||||
(val & IDE_CMD_RESET)) {
|
||||
|
@ -2224,6 +2272,8 @@ void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
|
|||
IDEState *s = idebus_active_if(bus);
|
||||
uint8_t *p;
|
||||
|
||||
trace_ide_data_writew(addr, val, bus, s);
|
||||
|
||||
/* PIO data access allowed only when DRQ bit is set. The result of a write
|
||||
* during PIO out is indeterminate, just ignore it. */
|
||||
if (!(s->status & DRQ_STAT) || ide_is_pio_out(s)) {
|
||||
|
@ -2269,6 +2319,8 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr)
|
|||
s->status &= ~DRQ_STAT;
|
||||
s->end_transfer_func(s);
|
||||
}
|
||||
|
||||
trace_ide_data_readw(addr, ret, bus, s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2278,6 +2330,8 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
|
|||
IDEState *s = idebus_active_if(bus);
|
||||
uint8_t *p;
|
||||
|
||||
trace_ide_data_writel(addr, val, bus, s);
|
||||
|
||||
/* PIO data access allowed only when DRQ bit is set. The result of a write
|
||||
* during PIO out is indeterminate, just ignore it. */
|
||||
if (!(s->status & DRQ_STAT) || ide_is_pio_out(s)) {
|
||||
|
@ -2308,7 +2362,8 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr)
|
|||
/* PIO data access allowed only when DRQ bit is set. The result of a read
|
||||
* during PIO in is indeterminate, return 0 and don't move forward. */
|
||||
if (!(s->status & DRQ_STAT) || !ide_is_pio_out(s)) {
|
||||
return 0;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
p = s->data_ptr;
|
||||
|
@ -2323,6 +2378,9 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr)
|
|||
s->status &= ~DRQ_STAT;
|
||||
s->end_transfer_func(s);
|
||||
}
|
||||
|
||||
out:
|
||||
trace_ide_data_readl(addr, ret, bus, s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2346,9 +2404,7 @@ void ide_bus_reset(IDEBus *bus)
|
|||
|
||||
/* pending async DMA */
|
||||
if (bus->dma->aiocb) {
|
||||
#ifdef DEBUG_AIO
|
||||
printf("aio_cancel\n");
|
||||
#endif
|
||||
trace_ide_bus_reset_aio();
|
||||
blk_aio_cancel(bus->dma->aiocb);
|
||||
bus->dma->aiocb = NULL;
|
||||
}
|
||||
|
@ -2406,7 +2462,7 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind,
|
|||
const char *version, const char *serial, const char *model,
|
||||
uint64_t wwn,
|
||||
uint32_t cylinders, uint32_t heads, uint32_t secs,
|
||||
int chs_trans)
|
||||
int chs_trans, Error **errp)
|
||||
{
|
||||
uint64_t nb_sectors;
|
||||
|
||||
|
@ -2431,11 +2487,11 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind,
|
|||
blk_set_guest_block_size(blk, 2048);
|
||||
} else {
|
||||
if (!blk_is_inserted(s->blk)) {
|
||||
error_report("Device needs media, but drive is empty");
|
||||
error_setg(errp, "Device needs media, but drive is empty");
|
||||
return -1;
|
||||
}
|
||||
if (blk_is_read_only(blk)) {
|
||||
error_report("Can't use a read-only drive");
|
||||
error_setg(errp, "Can't use a read-only drive");
|
||||
return -1;
|
||||
}
|
||||
blk_set_dev_ops(blk, &ide_hd_block_ops, s);
|
||||
|
|
|
@ -575,12 +575,15 @@ PCMCIACardState *dscm1xxxx_init(DriveInfo *dinfo)
|
|||
static void dscm1xxxx_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
PCMCIACardClass *pcc = PCMCIA_CARD_CLASS(oc);
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
pcc->cis = dscm1xxxx_cis;
|
||||
pcc->cis_len = sizeof(dscm1xxxx_cis);
|
||||
|
||||
pcc->attach = dscm1xxxx_attach;
|
||||
pcc->detach = dscm1xxxx_detach;
|
||||
/* Reason: Needs to be wired-up in code, see dscm1xxxx_init() */
|
||||
dc->user_creatable = false;
|
||||
}
|
||||
|
||||
static const TypeInfo dscm1xxxx_type_info = {
|
||||
|
|
17
hw/ide/pci.c
17
hw/ide/pci.c
|
@ -31,6 +31,7 @@
|
|||
#include "sysemu/dma.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/ide/pci.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define BMDMA_PAGE_SIZE 4096
|
||||
|
||||
|
@ -196,9 +197,7 @@ static void bmdma_reset(IDEDMA *dma)
|
|||
{
|
||||
BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
|
||||
|
||||
#ifdef DEBUG_IDE
|
||||
printf("ide: dma_reset\n");
|
||||
#endif
|
||||
trace_bmdma_reset();
|
||||
bmdma_cancel(bm);
|
||||
bm->cmd = 0;
|
||||
bm->status = 0;
|
||||
|
@ -227,9 +226,7 @@ static void bmdma_irq(void *opaque, int n, int level)
|
|||
|
||||
void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val)
|
||||
{
|
||||
#ifdef DEBUG_IDE
|
||||
printf("%s: 0x%08x\n", __func__, val);
|
||||
#endif
|
||||
trace_bmdma_cmd_writeb(val);
|
||||
|
||||
/* Ignore writes to SSBM if it keeps the old value */
|
||||
if ((val & BM_CMD_START) != (bm->cmd & BM_CMD_START)) {
|
||||
|
@ -258,9 +255,7 @@ static uint64_t bmdma_addr_read(void *opaque, hwaddr addr,
|
|||
uint64_t data;
|
||||
|
||||
data = (bm->addr >> (addr * 8)) & mask;
|
||||
#ifdef DEBUG_IDE
|
||||
printf("%s: 0x%08x\n", __func__, (unsigned)data);
|
||||
#endif
|
||||
trace_bmdma_addr_read(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -271,9 +266,7 @@ static void bmdma_addr_write(void *opaque, hwaddr addr,
|
|||
int shift = addr * 8;
|
||||
uint32_t mask = (1ULL << (width * 8)) - 1;
|
||||
|
||||
#ifdef DEBUG_IDE
|
||||
printf("%s: 0x%08x\n", __func__, (unsigned)data);
|
||||
#endif
|
||||
trace_bmdma_addr_write(data);
|
||||
bm->addr &= ~(mask << shift);
|
||||
bm->addr |= ((data & mask) << shift) & ~3;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "sysemu/dma.h"
|
||||
|
||||
#include "hw/ide/pci.h"
|
||||
#include "trace.h"
|
||||
|
||||
static uint64_t bmdma_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
|
@ -54,9 +55,8 @@ static uint64_t bmdma_read(void *opaque, hwaddr addr, unsigned size)
|
|||
val = 0xff;
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG_IDE
|
||||
printf("bmdma: readb 0x%02x : 0x%02x\n", (uint8_t)addr, val);
|
||||
#endif
|
||||
|
||||
trace_bmdma_read(addr, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
@ -69,9 +69,8 @@ static void bmdma_write(void *opaque, hwaddr addr,
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_IDE
|
||||
printf("bmdma: writeb 0x%02x : 0x%02x\n", (uint8_t)addr, (uint8_t)val);
|
||||
#endif
|
||||
trace_bmdma_write(addr, val);
|
||||
|
||||
switch(addr & 3) {
|
||||
case 0:
|
||||
bmdma_cmd_writeb(bm, val);
|
||||
|
|
|
@ -80,7 +80,7 @@ static char *idebus_get_fw_dev_path(DeviceState *dev)
|
|||
return g_strdup(path);
|
||||
}
|
||||
|
||||
static int ide_qdev_init(DeviceState *qdev)
|
||||
static void ide_qdev_realize(DeviceState *qdev, Error **errp)
|
||||
{
|
||||
IDEDevice *dev = IDE_DEVICE(qdev);
|
||||
IDEDeviceClass *dc = IDE_DEVICE_GET_CLASS(dev);
|
||||
|
@ -91,34 +91,31 @@ static int ide_qdev_init(DeviceState *qdev)
|
|||
}
|
||||
|
||||
if (dev->unit >= bus->max_units) {
|
||||
error_report("Can't create IDE unit %d, bus supports only %d units",
|
||||
error_setg(errp, "Can't create IDE unit %d, bus supports only %d units",
|
||||
dev->unit, bus->max_units);
|
||||
goto err;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (dev->unit) {
|
||||
case 0:
|
||||
if (bus->master) {
|
||||
error_report("IDE unit %d is in use", dev->unit);
|
||||
goto err;
|
||||
error_setg(errp, "IDE unit %d is in use", dev->unit);
|
||||
return;
|
||||
}
|
||||
bus->master = dev;
|
||||
break;
|
||||
case 1:
|
||||
if (bus->slave) {
|
||||
error_report("IDE unit %d is in use", dev->unit);
|
||||
goto err;
|
||||
error_setg(errp, "IDE unit %d is in use", dev->unit);
|
||||
return;
|
||||
}
|
||||
bus->slave = dev;
|
||||
break;
|
||||
default:
|
||||
error_report("Invalid IDE unit %d", dev->unit);
|
||||
goto err;
|
||||
error_setg(errp, "Invalid IDE unit %d", dev->unit);
|
||||
return;
|
||||
}
|
||||
return dc->init(dev);
|
||||
|
||||
err:
|
||||
return -1;
|
||||
dc->realize(dev, errp);
|
||||
}
|
||||
|
||||
IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive)
|
||||
|
@ -159,7 +156,7 @@ typedef struct IDEDrive {
|
|||
IDEDevice dev;
|
||||
} IDEDrive;
|
||||
|
||||
static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
|
||||
static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp)
|
||||
{
|
||||
IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
|
||||
IDEState *s = bus->ifs + dev->unit;
|
||||
|
@ -168,8 +165,8 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
|
|||
|
||||
if (!dev->conf.blk) {
|
||||
if (kind != IDE_CD) {
|
||||
error_report("No drive specified");
|
||||
return -1;
|
||||
error_setg(errp, "No drive specified");
|
||||
return;
|
||||
} else {
|
||||
/* Anonymous BlockBackend for an empty drive */
|
||||
dev->conf.blk = blk_new(0, BLK_PERM_ALL);
|
||||
|
@ -182,36 +179,36 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
|
|||
dev->conf.discard_granularity = 512;
|
||||
} else if (dev->conf.discard_granularity &&
|
||||
dev->conf.discard_granularity != 512) {
|
||||
error_report("discard_granularity must be 512 for ide");
|
||||
return -1;
|
||||
error_setg(errp, "discard_granularity must be 512 for ide");
|
||||
return;
|
||||
}
|
||||
|
||||
blkconf_blocksizes(&dev->conf);
|
||||
if (dev->conf.logical_block_size != 512) {
|
||||
error_report("logical_block_size must be 512 for IDE");
|
||||
return -1;
|
||||
error_setg(errp, "logical_block_size must be 512 for IDE");
|
||||
return;
|
||||
}
|
||||
|
||||
blkconf_serial(&dev->conf, &dev->serial);
|
||||
if (kind != IDE_CD) {
|
||||
blkconf_geometry(&dev->conf, &dev->chs_trans, 65535, 16, 255, &err);
|
||||
if (err) {
|
||||
error_report_err(err);
|
||||
return -1;
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
blkconf_apply_backend_options(&dev->conf, kind == IDE_CD, kind != IDE_CD,
|
||||
&err);
|
||||
if (err) {
|
||||
error_report_err(err);
|
||||
return -1;
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ide_init_drive(s, dev->conf.blk, kind,
|
||||
dev->version, dev->serial, dev->model, dev->wwn,
|
||||
dev->conf.cyls, dev->conf.heads, dev->conf.secs,
|
||||
dev->chs_trans) < 0) {
|
||||
return -1;
|
||||
dev->chs_trans, errp) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dev->version) {
|
||||
|
@ -223,8 +220,6 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
|
|||
|
||||
add_boot_device_path(dev->conf.bootindex, &dev->qdev,
|
||||
dev->unit ? "/disk@1" : "/disk@0");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ide_dev_get_bootindex(Object *obj, Visitor *v, const char *name,
|
||||
|
@ -270,17 +265,17 @@ static void ide_dev_instance_init(Object *obj)
|
|||
object_property_set_int(obj, -1, "bootindex", NULL);
|
||||
}
|
||||
|
||||
static int ide_hd_initfn(IDEDevice *dev)
|
||||
static void ide_hd_realize(IDEDevice *dev, Error **errp)
|
||||
{
|
||||
return ide_dev_initfn(dev, IDE_HD);
|
||||
ide_dev_initfn(dev, IDE_HD, errp);
|
||||
}
|
||||
|
||||
static int ide_cd_initfn(IDEDevice *dev)
|
||||
static void ide_cd_realize(IDEDevice *dev, Error **errp)
|
||||
{
|
||||
return ide_dev_initfn(dev, IDE_CD);
|
||||
ide_dev_initfn(dev, IDE_CD, errp);
|
||||
}
|
||||
|
||||
static int ide_drive_initfn(IDEDevice *dev)
|
||||
static void ide_drive_realize(IDEDevice *dev, Error **errp)
|
||||
{
|
||||
DriveInfo *dinfo = NULL;
|
||||
|
||||
|
@ -288,7 +283,7 @@ static int ide_drive_initfn(IDEDevice *dev)
|
|||
dinfo = blk_legacy_dinfo(dev->conf.blk);
|
||||
}
|
||||
|
||||
return ide_dev_initfn(dev, dinfo && dinfo->media_cd ? IDE_CD : IDE_HD);
|
||||
ide_dev_initfn(dev, dinfo && dinfo->media_cd ? IDE_CD : IDE_HD, errp);
|
||||
}
|
||||
|
||||
#define DEFINE_IDE_DEV_PROPERTIES() \
|
||||
|
@ -311,10 +306,11 @@ static void ide_hd_class_init(ObjectClass *klass, void *data)
|
|||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
IDEDeviceClass *k = IDE_DEVICE_CLASS(klass);
|
||||
k->init = ide_hd_initfn;
|
||||
|
||||
k->realize = ide_hd_realize;
|
||||
dc->fw_name = "drive";
|
||||
dc->desc = "virtual IDE disk";
|
||||
dc->props = ide_hd_properties;
|
||||
dc->desc = "virtual IDE disk";
|
||||
dc->props = ide_hd_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo ide_hd_info = {
|
||||
|
@ -333,10 +329,11 @@ static void ide_cd_class_init(ObjectClass *klass, void *data)
|
|||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
IDEDeviceClass *k = IDE_DEVICE_CLASS(klass);
|
||||
k->init = ide_cd_initfn;
|
||||
|
||||
k->realize = ide_cd_realize;
|
||||
dc->fw_name = "drive";
|
||||
dc->desc = "virtual IDE CD-ROM";
|
||||
dc->props = ide_cd_properties;
|
||||
dc->desc = "virtual IDE CD-ROM";
|
||||
dc->props = ide_cd_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo ide_cd_info = {
|
||||
|
@ -355,10 +352,11 @@ static void ide_drive_class_init(ObjectClass *klass, void *data)
|
|||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
IDEDeviceClass *k = IDE_DEVICE_CLASS(klass);
|
||||
k->init = ide_drive_initfn;
|
||||
|
||||
k->realize = ide_drive_realize;
|
||||
dc->fw_name = "drive";
|
||||
dc->desc = "virtual IDE disk or CD-ROM (legacy)";
|
||||
dc->props = ide_drive_properties;
|
||||
dc->desc = "virtual IDE disk or CD-ROM (legacy)";
|
||||
dc->props = ide_drive_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo ide_drive_info = {
|
||||
|
@ -371,7 +369,7 @@ static const TypeInfo ide_drive_info = {
|
|||
static void ide_device_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *k = DEVICE_CLASS(klass);
|
||||
k->init = ide_qdev_init;
|
||||
k->realize = ide_qdev_realize;
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, k->categories);
|
||||
k->bus_type = TYPE_IDE_BUS;
|
||||
k->props = ide_props;
|
||||
|
|
111
hw/ide/trace-events
Normal file
111
hw/ide/trace-events
Normal file
|
@ -0,0 +1,111 @@
|
|||
# See docs/devel/tracing.txt for syntax documentation.
|
||||
|
||||
# hw/ide/core.c
|
||||
# portio
|
||||
ide_ioport_read(uint32_t addr, const char *reg, uint32_t val, void *bus, void *s) "IDE PIO rd @ 0x%"PRIx32" (%s); val 0x%02"PRIx32"; bus %p IDEState %p"
|
||||
ide_ioport_write(uint32_t addr, const char *reg, uint32_t val, void *bus, void *s) "IDE PIO wr @ 0x%"PRIx32" (%s); val 0x%02"PRIx32"; bus %p IDEState %p"
|
||||
ide_status_read(uint32_t addr, uint32_t val, void *bus, void *s) "IDE PIO rd @ 0x%"PRIx32" (Alt Status); val 0x%02"PRIx32"; bus %p; IDEState %p"
|
||||
ide_cmd_write(uint32_t addr, uint32_t val, void *bus) "IDE PIO wr @ 0x%"PRIx32" (Device Control); val 0x%02"PRIx32"; bus %p"
|
||||
# Warning: verbose
|
||||
ide_data_readw(uint32_t addr, uint32_t val, void *bus, void *s) "IDE PIO rd @ 0x%"PRIx32" (Data: Word); val 0x%04"PRIx32"; bus %p; IDEState %p"
|
||||
ide_data_writew(uint32_t addr, uint32_t val, void *bus, void *s) "IDE PIO wr @ 0x%"PRIx32" (Data: Word); val 0x%04"PRIx32"; bus %p; IDEState %p"
|
||||
ide_data_readl(uint32_t addr, uint32_t val, void *bus, void *s) "IDE PIO rd @ 0x%"PRIx32" (Data: Long); val 0x%08"PRIx32"; bus %p; IDEState %p"
|
||||
ide_data_writel(uint32_t addr, uint32_t val, void *bus, void *s) "IDE PIO wr @ 0x%"PRIx32" (Data: Long); val 0x%08"PRIx32"; bus %p; IDEState %p"
|
||||
# misc
|
||||
ide_exec_cmd(void *bus, void *state, uint32_t cmd) "IDE exec cmd: bus %p; state %p; cmd 0x%02x"
|
||||
ide_cancel_dma_sync_buffered(void *fn, void *req) "invoking cb %p of buffered request %p with -ECANCELED"
|
||||
ide_cancel_dma_sync_remaining(void) "draining all remaining requests"
|
||||
ide_sector_read(int64_t sector_num, int nsectors) "sector=%"PRId64" nsectors=%d"
|
||||
ide_sector_write(int64_t sector_num, int nsectors) "sector=%"PRId64" nsectors=%d"
|
||||
ide_reset(void *s) "IDEstate %p"
|
||||
ide_bus_reset_aio(void) "aio_cancel"
|
||||
ide_dma_cb(void *s, int64_t sector_num, int n, const char *dma) "IDEState %p; sector_num=%"PRId64" n=%d cmd=%s"
|
||||
|
||||
# BMDMA HBAs:
|
||||
|
||||
# hw/ide/cmd646.c
|
||||
bmdma_read_cmd646(uint64_t addr, uint32_t val) "bmdma: readb 0x%"PRIx64" : 0x%02x"
|
||||
bmdma_write_cmd646(uint64_t addr, uint64_t val) "bmdma: writeb 0x%"PRIx64" : 0x%02"PRIx64
|
||||
|
||||
# hw/ide/pci.c
|
||||
bmdma_reset(void) ""
|
||||
bmdma_cmd_writeb(uint32_t val) "val: 0x%08x"
|
||||
bmdma_addr_read(uint64_t data) "data: 0x%016"PRIx64
|
||||
bmdma_addr_write(uint64_t data) "data: 0x%016"PRIx64
|
||||
|
||||
# hw/ide/piix.c
|
||||
bmdma_read(uint64_t addr, uint8_t val) "bmdma: readb 0x%"PRIx64" : 0x%02x"
|
||||
bmdma_write(uint64_t addr, uint64_t val) "bmdma: writeb 0x%"PRIx64" : 0x%02"PRIx64
|
||||
|
||||
# hw/ide/via.c
|
||||
bmdma_read_via(uint64_t addr, uint32_t val) "bmdma: readb 0x%"PRIx64" : 0x%02x"
|
||||
bmdma_write_via(uint64_t addr, uint64_t val) "bmdma: writeb 0x%"PRIx64" : 0x%02"PRIx64
|
||||
|
||||
# hw/ide/atapi.c
|
||||
cd_read_sector_sync(int lba) "lba=%d"
|
||||
cd_read_sector_cb(int lba, int ret) "lba=%d ret=%d"
|
||||
cd_read_sector(int lba) "lba=%d"
|
||||
ide_atapi_cmd_error(void *s, int sense_key, int asc) "IDEState: %p; sense=0x%x asc=0x%x"
|
||||
ide_atapi_cmd_reply_end(void *s, int tx_size, int elem_tx_size, int32_t index) "IDEState %p; reply: tx_size=%d elem_tx_size=%d index=%"PRId32
|
||||
ide_atapi_cmd_reply_end_eot(void *s, int status) "IDEState: %p; end of transfer, status=0x%x"
|
||||
ide_atapi_cmd_reply_end_bcl(void *s, int bcl) "IDEState: %p; byte_count_limit=%d"
|
||||
ide_atapi_cmd_reply_end_new(void *s, int status) "IDEState: %p; new transfer started, status=0x%x"
|
||||
ide_atapi_cmd_check_status(void *s) "IDEState: %p"
|
||||
ide_atapi_cmd_read(void *s, const char *method, int lba, int nb_sectors) "IDEState: %p; read %s: LBA=%d nb_sectors=%d"
|
||||
ide_atapi_cmd(void *s, uint8_t cmd) "IDEState: %p; cmd: 0x%02x"
|
||||
ide_atapi_cmd_read_dma_cb_aio(void *s, int lba, int n) "IDEState: %p; aio read: lba=%d n=%d"
|
||||
# Warning: Verbose
|
||||
ide_atapi_cmd_packet(void *s, uint16_t limit, const char *packet) "IDEState: %p; limit=0x%x packet: %s"
|
||||
|
||||
# hw/ide/ahci.c
|
||||
ahci_port_read(void *s, int port, int offset, uint32_t ret) "ahci(%p)[%d]: port read @ 0x%x: 0x%08x"
|
||||
ahci_irq_raise(void *s) "ahci(%p): raise irq"
|
||||
ahci_irq_lower(void *s) "ahci(%p): lower irq"
|
||||
ahci_check_irq(void *s, uint32_t old, uint32_t new) "ahci(%p): check irq 0x%08x --> 0x%08x"
|
||||
ahci_trigger_irq(void *s, int port, const char *name, uint32_t val, uint32_t old, uint32_t new, uint32_t effective) "ahci(%p)[%d]: trigger irq +%s (0x%08x); irqstat: 0x%08x --> 0x%08x; effective: 0x%08x"
|
||||
ahci_port_write(void *s, int port, int offset, uint32_t val) "ahci(%p)[%d]: port write @ 0x%x: 0x%08x"
|
||||
ahci_mem_read_32(void *s, uint64_t addr, uint32_t val) "ahci(%p): mem read @ 0x%"PRIx64": 0x%08x"
|
||||
ahci_mem_read(void *s, unsigned size, uint64_t addr, uint64_t val) "ahci(%p): read%u @ 0x%"PRIx64": 0x%016"PRIx64
|
||||
ahci_mem_write(void *s, unsigned size, uint64_t addr, uint64_t val) "ahci(%p): write%u @ 0x%"PRIx64": 0x%016"PRIx64
|
||||
ahci_mem_write_unknown(void *s, unsigned size, uint64_t addr, uint64_t val) "ahci(%p): write%u to unknown register 0x%"PRIx64": 0x%016"PRIx64
|
||||
ahci_set_signature(void *s, int port, uint8_t nsector, uint8_t sector, uint8_t lcyl, uint8_t hcyl, uint32_t sig) "ahci(%p)[%d]: set signature sector:0x%02x nsector:0x%02x lcyl:0x%02x hcyl:0x%02x (cumulatively: 0x%08x)"
|
||||
ahci_reset_port(void *s, int port) "ahci(%p)[%d]: reset port"
|
||||
ahci_unmap_fis_address_null(void *s, int port) "ahci(%p)[%d]: Attempt to unmap NULL FIS address"
|
||||
ahci_unmap_clb_address_null(void *s, int port) "ahci(%p)[%d]: Attempt to unmap NULL CLB address"
|
||||
ahci_populate_sglist(void *s, int port) "ahci(%p)[%d]"
|
||||
ahci_populate_sglist_no_prdtl(void *s, int port, uint16_t opts) "ahci(%p)[%d]: no sg list given by guest: 0x%04x"
|
||||
ahci_populate_sglist_no_map(void *s, int port) "ahci(%p)[%d]: DMA mapping failed"
|
||||
ahci_populate_sglist_short_map(void *s, int port) "ahci(%p)[%d]: mapped less than expected"
|
||||
ahci_populate_sglist_bad_offset(void *s, int port, int off_idx, int64_t off_pos) "ahci(%p)[%d]: Incorrect offset! off_idx: %d, off_pos: %"PRId64
|
||||
ncq_finish(void *s, int port, uint8_t tag) "ahci(%p)[%d][tag:%d]: NCQ transfer finished"
|
||||
execute_ncq_command_read(void *s, int port, uint8_t tag, int count, int64_t lba) "ahci(%p)[%d][tag:%d]: NCQ reading %d sectors from LBA %"PRId64
|
||||
execute_ncq_command_write(void *s, int port, uint8_t tag, int count, int64_t lba) "ahci(%p)[%d][tag:%d]: NCQ writing %d sectors to LBA %"PRId64
|
||||
execute_ncq_command_unsup(void *s, int port, uint8_t tag, uint8_t cmd) "ahci(%p)[%d][tag:%d]: error: unsupported NCQ command (0x%02x) received"
|
||||
process_ncq_command_mismatch(void *s, int port, uint8_t tag, uint8_t slot) "ahci(%p)[%d][tag:%d]: Warning: NCQ slot (%d) did not match the given tag"
|
||||
process_ncq_command_aux(void *s, int port, uint8_t tag) "ahci(%p)[%d][tag:%d]: Warn: Attempt to use NCQ auxiliary fields"
|
||||
process_ncq_command_prioicc(void *s, int port, uint8_t tag) "ahci(%p)[%d][tag:%d]: Warn: Unsupported attempt to use PRIO/ICC fields"
|
||||
process_ncq_command_fua(void *s, int port, uint8_t tag) "ahci(%p)[%d][tag:%d]: Warn: Unsupported attempt to use Force Unit Access"
|
||||
process_ncq_command_rarc(void *s, int port, uint8_t tag) "ahci(%p)[%d][tag:%d]: Warn: Unsupported attempt to use Rebuild Assist"
|
||||
process_ncq_command_large(void *s, int port, uint8_t tag, size_t prdtl, size_t size) "ahci(%p)[%d][tag:%d]: Warn: PRDTL (0x%zx) does not match requested size (0x%zx)"
|
||||
process_ncq_command(void *s, int port, uint8_t tag, uint8_t cmd, uint64_t lba, uint64_t end) "ahci(%p)[%d][tag:%d]: NCQ op 0x%02x on sectors [%"PRId64",%"PRId64"]"
|
||||
handle_reg_h2d_fis_pmp(void *s, int port, char b0, char b1, char b2) "ahci(%p)[%d]: Port Multiplier not supported, FIS: 0x%02x-%02x-%02x"
|
||||
handle_reg_h2d_fis_res(void *s, int port, char b0, char b1, char b2) "ahci(%p)[%d]: Reserved flags set in H2D Register FIS, FIS: 0x%02x-%02x-%02x"
|
||||
handle_cmd_busy(void *s, int port) "ahci(%p)[%d]: engine busy"
|
||||
handle_cmd_nolist(void *s, int port) "ahci(%p)[%d]: handle_cmd called without s->dev[port].lst"
|
||||
handle_cmd_badport(void *s, int port) "ahci(%p)[%d]: guest accessed unused port"
|
||||
handle_cmd_badfis(void *s, int port) "ahci(%p)[%d]: guest provided an invalid cmd FIS"
|
||||
handle_cmd_badmap(void *s, int port, uint64_t len) "ahci(%p)[%d]: dma_memory_map failed, 0x%02"PRIx64" != 0x80"
|
||||
handle_cmd_unhandled_fis(void *s, int port, uint8_t b0, uint8_t b1, uint8_t b2) "ahci(%p)[%d]: unhandled FIS type. cmd_fis: 0x%02x-%02x-%02x"
|
||||
ahci_start_transfer(void *s, int port, const char *rw, uint32_t size, const char *tgt, const char *sgl) "ahci(%p)[%d]: %sing %d bytes on %s w/%s sglist"
|
||||
ahci_start_dma(void *s, int port) "ahci(%p)[%d]: start dma"
|
||||
ahci_dma_prepare_buf(void *s, int port, int32_t io_buffer_size, int32_t limit) "ahci(%p)[%d]: prepare buf limit=%"PRId32" prepared=%"PRId32
|
||||
ahci_dma_prepare_buf_fail(void *s, int port) "ahci(%p)[%d]: sglist population failed"
|
||||
ahci_dma_rw_buf(void *s, int port, int l) "ahci(%p)[%d] len=0x%x"
|
||||
ahci_cmd_done(void *s, int port) "ahci(%p)[%d]: cmd done"
|
||||
ahci_reset(void *s) "ahci(%p): HBA reset"
|
||||
allwinner_ahci_mem_read(void *s, void *a, uint64_t addr, uint64_t val, unsigned size) "ahci(%p): read a=%p addr=0x%"HWADDR_PRIx" val=0x%"PRIx64", size=%d"
|
||||
allwinner_ahci_mem_write(void *s, void *a, uint64_t addr, uint64_t val, unsigned size) "ahci(%p): write a=%p addr=0x%"HWADDR_PRIx" val=0x%"PRIx64", size=%d"
|
||||
|
||||
# Warning: Verbose
|
||||
handle_reg_h2d_fis_dump(void *s, int port, const char *fis) "ahci(%p)[%d]: %s"
|
||||
handle_cmd_fis_dump(void *s, int port, const char *fis) "ahci(%p)[%d]: %s"
|
10
hw/ide/via.c
10
hw/ide/via.c
|
@ -33,6 +33,7 @@
|
|||
#include "sysemu/dma.h"
|
||||
|
||||
#include "hw/ide/pci.h"
|
||||
#include "trace.h"
|
||||
|
||||
static uint64_t bmdma_read(void *opaque, hwaddr addr,
|
||||
unsigned size)
|
||||
|
@ -55,9 +56,8 @@ static uint64_t bmdma_read(void *opaque, hwaddr addr,
|
|||
val = 0xff;
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG_IDE
|
||||
printf("bmdma: readb 0x%02x : 0x%02x\n", addr, val);
|
||||
#endif
|
||||
|
||||
trace_bmdma_read_via(addr, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
@ -70,9 +70,7 @@ static void bmdma_write(void *opaque, hwaddr addr,
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_IDE
|
||||
printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val);
|
||||
#endif
|
||||
trace_bmdma_write_via(addr, val);
|
||||
switch (addr & 3) {
|
||||
case 0:
|
||||
bmdma_cmd_writeb(bm, val);
|
||||
|
|
|
@ -12,11 +12,9 @@
|
|||
#include "sysemu/sysemu.h"
|
||||
#include "hw/block/block.h"
|
||||
#include "block/scsi.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
/* debug IDE devices */
|
||||
//#define DEBUG_IDE
|
||||
//#define DEBUG_IDE_ATAPI
|
||||
//#define DEBUG_AIO
|
||||
#define USE_DMA_CDROM
|
||||
|
||||
typedef struct IDEBus IDEBus;
|
||||
|
@ -335,12 +333,16 @@ struct unreported_events {
|
|||
};
|
||||
|
||||
enum ide_dma_cmd {
|
||||
IDE_DMA_READ,
|
||||
IDE_DMA__BEGIN = 0,
|
||||
IDE_DMA_READ = IDE_DMA__BEGIN,
|
||||
IDE_DMA_WRITE,
|
||||
IDE_DMA_TRIM,
|
||||
IDE_DMA_ATAPI,
|
||||
IDE_DMA__COUNT
|
||||
};
|
||||
|
||||
extern const char *IDE_DMA_CMD_lookup[IDE_DMA__COUNT];
|
||||
|
||||
#define ide_cmd_is_read(s) \
|
||||
((s)->dma_cmd == IDE_DMA_READ)
|
||||
|
||||
|
@ -495,7 +497,7 @@ struct IDEBus {
|
|||
|
||||
typedef struct IDEDeviceClass {
|
||||
DeviceClass parent_class;
|
||||
int (*init)(IDEDevice *dev);
|
||||
void (*realize)(IDEDevice *dev, Error **errp);
|
||||
} IDEDeviceClass;
|
||||
|
||||
struct IDEDevice {
|
||||
|
@ -605,7 +607,7 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind,
|
|||
const char *version, const char *serial, const char *model,
|
||||
uint64_t wwn,
|
||||
uint32_t cylinders, uint32_t heads, uint32_t secs,
|
||||
int chs_trans);
|
||||
int chs_trans, Error **errp);
|
||||
void ide_init2(IDEBus *bus, qemu_irq irq);
|
||||
void ide_exit(IDEState *s);
|
||||
void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2);
|
||||
|
|
|
@ -123,8 +123,7 @@ quit
|
|||
|
||||
Testing: -drive if=ide
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) QEMU_PROG: Device needs media, but drive is empty
|
||||
QEMU_PROG: Initialization of device ide-hd failed: Device initialization failed.
|
||||
(qemu) QEMU_PROG: Initialization of device ide-hd failed: Device needs media, but drive is empty
|
||||
|
||||
Testing: -drive if=scsi
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
|
@ -146,12 +145,10 @@ QEMU X.Y.Z monitor - type 'help' for more information
|
|||
Testing: -drive if=none,id=disk -device ide-drive,drive=disk
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty
|
||||
QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed.
|
||||
|
||||
Testing: -drive if=none,id=disk -device ide-hd,drive=disk
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) QEMU_PROG: -device ide-hd,drive=disk: Device needs media, but drive is empty
|
||||
QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed.
|
||||
|
||||
Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
|
@ -179,8 +176,7 @@ quit
|
|||
|
||||
Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) QEMU_PROG: Block node is read-only
|
||||
QEMU_PROG: Initialization of device ide-hd failed: Device initialization failed.
|
||||
(qemu) QEMU_PROG: Initialization of device ide-hd failed: Block node is read-only
|
||||
|
||||
Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
|
@ -202,12 +198,10 @@ QEMU X.Y.Z monitor - type 'help' for more information
|
|||
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-drive,drive=disk
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) QEMU_PROG: -device ide-drive,drive=disk: Block node is read-only
|
||||
QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed.
|
||||
|
||||
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-hd,drive=disk
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) QEMU_PROG: -device ide-hd,drive=disk: Block node is read-only
|
||||
QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed.
|
||||
|
||||
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
|
|
|
@ -725,11 +725,9 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
|
|||
|
||||
Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0,unit=0
|
||||
QEMU_PROG: -device floppy,drive=none0,unit=0: Floppy unit 0 is in use
|
||||
QEMU_PROG: -device floppy,drive=none0,unit=0: Device initialization failed.
|
||||
|
||||
Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0,unit=1
|
||||
QEMU_PROG: -device floppy,drive=none0,unit=1: Floppy unit 1 is in use
|
||||
QEMU_PROG: -device floppy,drive=none0,unit=1: Device initialization failed.
|
||||
|
||||
|
||||
=== Mixing -drive and -device ===
|
||||
|
@ -812,7 +810,6 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
|
|||
|
||||
Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0,unit=0
|
||||
QEMU_PROG: -device floppy,drive=none0,unit=0: Floppy unit 0 is in use
|
||||
QEMU_PROG: -device floppy,drive=none0,unit=0: Device initialization failed.
|
||||
|
||||
|
||||
=== Mixing -global and -device ===
|
||||
|
@ -971,18 +968,15 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco
|
|||
|
||||
Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0 -device floppy,drive=none1,unit=0
|
||||
QEMU_PROG: -device floppy,drive=none1,unit=0: Floppy unit 0 is in use
|
||||
QEMU_PROG: -device floppy,drive=none1,unit=0: Device initialization failed.
|
||||
|
||||
Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveB=none0 -device floppy,drive=none1,unit=1
|
||||
QEMU_PROG: -device floppy,drive=none1,unit=1: Floppy unit 1 is in use
|
||||
QEMU_PROG: -device floppy,drive=none1,unit=1: Device initialization failed.
|
||||
|
||||
|
||||
=== Too many floppy drives ===
|
||||
|
||||
Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -drive if=none,file=TEST_DIR/t.qcow2.3 -global isa-fdc.driveB=none0 -device floppy,drive=none1
|
||||
QEMU_PROG: -device floppy,drive=none1: Can't create floppy unit 2, bus supports only 2 units
|
||||
QEMU_PROG: -device floppy,drive=none1: Device initialization failed.
|
||||
|
||||
|
||||
=== Creating an empty drive with anonymous BB ===
|
||||
|
@ -1211,11 +1205,9 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,physica
|
|||
|
||||
Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,logical_block_size=4096
|
||||
QEMU_PROG: -device floppy,drive=none0,logical_block_size=4096: Physical and logical block size must be 512 for floppy
|
||||
QEMU_PROG: -device floppy,drive=none0,logical_block_size=4096: Device initialization failed.
|
||||
|
||||
Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,physical_block_size=1024
|
||||
QEMU_PROG: -device floppy,drive=none0,physical_block_size=1024: Physical and logical block size must be 512 for floppy
|
||||
QEMU_PROG: -device floppy,drive=none0,physical_block_size=1024: Device initialization failed.
|
||||
|
||||
|
||||
=== Writethrough caching ===
|
||||
|
|
Loading…
Reference in a new issue