ide: convert to memory API

Reviewed-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Avi Kivity 2011-08-08 16:09:11 +03:00 committed by Anthony Liguori
parent e1a99dbd9c
commit a9deb8c69a
5 changed files with 260 additions and 119 deletions

View File

@ -44,35 +44,95 @@
static void cmd646_update_irq(PCIIDEState *d); static void cmd646_update_irq(PCIIDEState *d);
static void ide_map(PCIDevice *pci_dev, int region_num, static uint64_t cmd646_cmd_read(void *opaque, target_phys_addr_t addr,
pcibus_t addr, pcibus_t size, int type) unsigned size)
{ {
PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, pci_dev); CMD646BAR *cmd646bar = opaque;
IDEBus *bus;
if (region_num <= 3) { if (addr != 2 || size != 1) {
bus = &d->bus[(region_num >> 1)]; return ((uint64_t)1 << (size * 8)) - 1;
if (region_num & 1) { }
register_ioport_read(addr + 2, 1, 1, ide_status_read, bus); return ide_status_read(cmd646bar->bus, addr + 2);
register_ioport_write(addr + 2, 1, 1, ide_cmd_write, bus); }
static void cmd646_cmd_write(void *opaque, target_phys_addr_t addr,
uint64_t data, unsigned size)
{
CMD646BAR *cmd646bar = opaque;
if (addr != 2 || size != 1) {
return;
}
ide_cmd_write(cmd646bar->bus, addr + 2, data);
}
static MemoryRegionOps cmd646_cmd_ops = {
.read = cmd646_cmd_read,
.write = cmd646_cmd_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static uint64_t cmd646_data_read(void *opaque, target_phys_addr_t addr,
unsigned size)
{
CMD646BAR *cmd646bar = opaque;
if (size == 1) {
return ide_ioport_read(cmd646bar->bus, addr);
} else if (addr == 0) {
if (size == 2) {
return ide_data_readw(cmd646bar->bus, addr);
} else { } else {
register_ioport_write(addr, 8, 1, ide_ioport_write, bus); return ide_data_readl(cmd646bar->bus, addr);
register_ioport_read(addr, 8, 1, ide_ioport_read, bus); }
}
return ((uint64_t)1 << (size * 8)) - 1;
}
/* data ports */ static void cmd646_data_write(void *opaque, target_phys_addr_t addr,
register_ioport_write(addr, 2, 2, ide_data_writew, bus); uint64_t data, unsigned size)
register_ioport_read(addr, 2, 2, ide_data_readw, bus); {
register_ioport_write(addr, 4, 4, ide_data_writel, bus); CMD646BAR *cmd646bar = opaque;
register_ioport_read(addr, 4, 4, ide_data_readl, bus);
if (size == 1) {
return ide_ioport_write(cmd646bar->bus, addr, data);
} else if (addr == 0) {
if (size == 2) {
return ide_data_writew(cmd646bar->bus, addr, data);
} else {
return ide_data_writel(cmd646bar->bus, addr, data);
} }
} }
} }
static uint32_t bmdma_readb_common(PCIIDEState *pci_dev, BMDMAState *bm, static MemoryRegionOps cmd646_data_ops = {
uint32_t addr) .read = cmd646_data_read,
.write = cmd646_data_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static void setup_cmd646_bar(PCIIDEState *d, int bus_num)
{ {
IDEBus *bus = &d->bus[bus_num];
CMD646BAR *bar = &d->cmd646_bar[bus_num];
bar->bus = bus;
bar->pci_dev = d;
memory_region_init_io(&bar->cmd, &cmd646_cmd_ops, bar, "cmd646-cmd", 4);
memory_region_init_io(&bar->data, &cmd646_data_ops, bar, "cmd646-data", 8);
}
static uint64_t bmdma_read(void *opaque, target_phys_addr_t addr,
unsigned size)
{
BMDMAState *bm = opaque;
PCIIDEState *pci_dev = bm->pci_dev;
uint32_t val; uint32_t val;
if (size != 1) {
return ((uint64_t)1 << (size * 8)) - 1;
}
switch(addr & 3) { switch(addr & 3) {
case 0: case 0:
val = bm->cmd; val = bm->cmd;
@ -100,31 +160,22 @@ static uint32_t bmdma_readb_common(PCIIDEState *pci_dev, BMDMAState *bm,
return val; return val;
} }
static uint32_t bmdma_readb_0(void *opaque, uint32_t addr) static void bmdma_write(void *opaque, target_phys_addr_t addr,
uint64_t val, unsigned size)
{ {
PCIIDEState *pci_dev = opaque; BMDMAState *bm = opaque;
BMDMAState *bm = &pci_dev->bmdma[0]; PCIIDEState *pci_dev = bm->pci_dev;
return bmdma_readb_common(pci_dev, bm, addr); if (size != 1) {
} return;
}
static uint32_t bmdma_readb_1(void *opaque, uint32_t addr)
{
PCIIDEState *pci_dev = opaque;
BMDMAState *bm = &pci_dev->bmdma[1];
return bmdma_readb_common(pci_dev, bm, addr);
}
static void bmdma_writeb_common(PCIIDEState *pci_dev, BMDMAState *bm,
uint32_t addr, uint32_t val)
{
#ifdef DEBUG_IDE #ifdef DEBUG_IDE
printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val); printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val);
#endif #endif
switch(addr & 3) { switch(addr & 3) {
case 0: case 0:
bmdma_cmd_writeb(bm, addr, val); bmdma_cmd_writeb(bm, val);
break; break;
case 1: case 1:
pci_dev->dev.config[MRDMODE] = pci_dev->dev.config[MRDMODE] =
@ -143,42 +194,25 @@ static void bmdma_writeb_common(PCIIDEState *pci_dev, BMDMAState *bm,
} }
} }
static void bmdma_writeb_0(void *opaque, uint32_t addr, uint32_t val) static MemoryRegionOps cmd646_bmdma_ops = {
.read = bmdma_read,
.write = bmdma_write,
};
static void bmdma_setup_bar(PCIIDEState *d)
{ {
PCIIDEState *pci_dev = opaque; BMDMAState *bm;
BMDMAState *bm = &pci_dev->bmdma[0];
bmdma_writeb_common(pci_dev, bm, addr, val);
}
static void bmdma_writeb_1(void *opaque, uint32_t addr, uint32_t val)
{
PCIIDEState *pci_dev = opaque;
BMDMAState *bm = &pci_dev->bmdma[1];
bmdma_writeb_common(pci_dev, bm, addr, val);
}
static void bmdma_map(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, pci_dev);
int i; int i;
memory_region_init(&d->bmdma_bar, "cmd646-bmdma", 16);
for(i = 0;i < 2; i++) { for(i = 0;i < 2; i++) {
BMDMAState *bm = &d->bmdma[i]; bm = &d->bmdma[i];
memory_region_init_io(&bm->extra_io, &cmd646_bmdma_ops, bm,
if (i == 0) { "cmd646-bmdma-bus", 4);
register_ioport_write(addr, 4, 1, bmdma_writeb_0, d); memory_region_add_subregion(&d->bmdma_bar, i * 8, &bm->extra_io);
register_ioport_read(addr, 4, 1, bmdma_readb_0, d); memory_region_init_io(&bm->addr_ioport, &bmdma_addr_ioport_ops, bm,
} else { "cmd646-bmdma-ioport", 4);
register_ioport_write(addr, 4, 1, bmdma_writeb_1, d); memory_region_add_subregion(&d->bmdma_bar, i * 8 + 4, &bm->addr_ioport);
register_ioport_read(addr, 4, 1, bmdma_readb_1, d);
}
iorange_init(&bm->addr_ioport, &bmdma_addr_ioport_ops, addr + 4, 4);
ioport_register(&bm->addr_ioport);
addr += 8;
} }
} }
@ -234,11 +268,18 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev)
pci_conf[0x51] |= 0x08; /* enable IDE1 */ pci_conf[0x51] |= 0x08; /* enable IDE1 */
} }
pci_register_bar(dev, 0, 0x8, PCI_BASE_ADDRESS_SPACE_IO, ide_map); setup_cmd646_bar(d, 0);
pci_register_bar(dev, 1, 0x4, PCI_BASE_ADDRESS_SPACE_IO, ide_map); setup_cmd646_bar(d, 1);
pci_register_bar(dev, 2, 0x8, PCI_BASE_ADDRESS_SPACE_IO, ide_map); pci_register_bar_region(dev, 0, PCI_BASE_ADDRESS_SPACE_IO,
pci_register_bar(dev, 3, 0x4, PCI_BASE_ADDRESS_SPACE_IO, ide_map); &d->cmd646_bar[0].data);
pci_register_bar(dev, 4, 0x10, PCI_BASE_ADDRESS_SPACE_IO, bmdma_map); pci_register_bar_region(dev, 1, PCI_BASE_ADDRESS_SPACE_IO,
&d->cmd646_bar[0].cmd);
pci_register_bar_region(dev, 2, PCI_BASE_ADDRESS_SPACE_IO,
&d->cmd646_bar[1].data);
pci_register_bar_region(dev, 3, PCI_BASE_ADDRESS_SPACE_IO,
&d->cmd646_bar[1].cmd);
bmdma_setup_bar(d);
pci_register_bar_region(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &d->bmdma_bar);
/* TODO: RST# value should be 0 */ /* TODO: RST# value should be 0 */
pci_conf[PCI_INTERRUPT_PIN] = 0x01; // interrupt on pin 1 pci_conf[PCI_INTERRUPT_PIN] = 0x01; // interrupt on pin 1
@ -248,7 +289,7 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev)
ide_bus_new(&d->bus[i], &d->dev.qdev, i); ide_bus_new(&d->bus[i], &d->dev.qdev, i);
ide_init2(&d->bus[i], irq[i]); ide_init2(&d->bus[i], irq[i]);
bmdma_init(&d->bus[i], &d->bmdma[i]); bmdma_init(&d->bus[i], &d->bmdma[i], d);
d->bmdma[i].bus = &d->bus[i]; d->bmdma[i].bus = &d->bus[i];
qemu_add_vm_change_state_handler(d->bus[i].dma->ops->restart_cb, qemu_add_vm_change_state_handler(d->bus[i].dma->ops->restart_cb,
&d->bmdma[i].dma); &d->bmdma[i].dma);
@ -259,6 +300,24 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev)
return 0; return 0;
} }
static int pci_cmd646_ide_exitfn(PCIDevice *dev)
{
PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
unsigned i;
for (i = 0; i < 2; ++i) {
memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].extra_io);
memory_region_destroy(&d->bmdma[i].extra_io);
memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].addr_ioport);
memory_region_destroy(&d->bmdma[i].addr_ioport);
memory_region_destroy(&d->cmd646_bar[i].cmd);
memory_region_destroy(&d->cmd646_bar[i].data);
}
memory_region_destroy(&d->bmdma_bar);
return 0;
}
void pci_cmd646_ide_init(PCIBus *bus, DriveInfo **hd_table, void pci_cmd646_ide_init(PCIBus *bus, DriveInfo **hd_table,
int secondary_ide_enabled) int secondary_ide_enabled)
{ {
@ -276,6 +335,7 @@ static PCIDeviceInfo cmd646_ide_info[] = {
.qdev.name = "cmd646-ide", .qdev.name = "cmd646-ide",
.qdev.size = sizeof(PCIIDEState), .qdev.size = sizeof(PCIIDEState),
.init = pci_cmd646_ide_initfn, .init = pci_cmd646_ide_initfn,
.exit = pci_cmd646_ide_exitfn,
.vendor_id = PCI_VENDOR_ID_CMD, .vendor_id = PCI_VENDOR_ID_CMD,
.device_id = PCI_DEVICE_ID_CMD_646, .device_id = PCI_DEVICE_ID_CMD_646,
.revision = 0x07, // IDE controller revision .revision = 0x07, // IDE controller revision

View File

@ -287,9 +287,8 @@ static void bmdma_irq(void *opaque, int n, int level)
qemu_set_irq(bm->irq, level); qemu_set_irq(bm->irq, level);
} }
void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val) void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val)
{ {
BMDMAState *bm = opaque;
#ifdef DEBUG_IDE #ifdef DEBUG_IDE
printf("%s: 0x%08x\n", __func__, val); printf("%s: 0x%08x\n", __func__, val);
#endif #endif
@ -328,22 +327,24 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
bm->cmd = val & 0x09; bm->cmd = val & 0x09;
} }
static void bmdma_addr_read(IORange *ioport, uint64_t addr, static uint64_t bmdma_addr_read(void *opaque, target_phys_addr_t addr,
unsigned width, uint64_t *data) unsigned width)
{ {
BMDMAState *bm = container_of(ioport, BMDMAState, addr_ioport); BMDMAState *bm = opaque;
uint32_t mask = (1ULL << (width * 8)) - 1; uint32_t mask = (1ULL << (width * 8)) - 1;
uint64_t data;
*data = (bm->addr >> (addr * 8)) & mask; data = (bm->addr >> (addr * 8)) & mask;
#ifdef DEBUG_IDE #ifdef DEBUG_IDE
printf("%s: 0x%08x\n", __func__, (unsigned)*data); printf("%s: 0x%08x\n", __func__, (unsigned)*data);
#endif #endif
return data;
} }
static void bmdma_addr_write(IORange *ioport, uint64_t addr, static void bmdma_addr_write(void *opaque, target_phys_addr_t addr,
unsigned width, uint64_t data) uint64_t data, unsigned width)
{ {
BMDMAState *bm = container_of(ioport, BMDMAState, addr_ioport); BMDMAState *bm = opaque;
int shift = addr * 8; int shift = addr * 8;
uint32_t mask = (1ULL << (width * 8)) - 1; uint32_t mask = (1ULL << (width * 8)) - 1;
@ -354,9 +355,10 @@ static void bmdma_addr_write(IORange *ioport, uint64_t addr,
bm->addr |= ((data & mask) << shift) & ~3; bm->addr |= ((data & mask) << shift) & ~3;
} }
const IORangeOps bmdma_addr_ioport_ops = { MemoryRegionOps bmdma_addr_ioport_ops = {
.read = bmdma_addr_read, .read = bmdma_addr_read,
.write = bmdma_addr_write, .write = bmdma_addr_write,
.endianness = DEVICE_LITTLE_ENDIAN,
}; };
static bool ide_bmdma_current_needed(void *opaque) static bool ide_bmdma_current_needed(void *opaque)
@ -514,7 +516,7 @@ static const struct IDEDMAOps bmdma_ops = {
.reset = bmdma_reset, .reset = bmdma_reset,
}; };
void bmdma_init(IDEBus *bus, BMDMAState *bm) void bmdma_init(IDEBus *bus, BMDMAState *bm, PCIIDEState *d)
{ {
qemu_irq *irq; qemu_irq *irq;
@ -527,4 +529,5 @@ void bmdma_init(IDEBus *bus, BMDMAState *bm)
bm->irq = bus->irq; bm->irq = bus->irq;
irq = qemu_allocate_irqs(bmdma_irq, bm, 1); irq = qemu_allocate_irqs(bmdma_irq, bm, 1);
bus->irq = *irq; bus->irq = *irq;
bm->pci_dev = d;
} }

View File

@ -19,20 +19,31 @@ typedef struct BMDMAState {
BlockDriverCompletionFunc *dma_cb; BlockDriverCompletionFunc *dma_cb;
int64_t sector_num; int64_t sector_num;
uint32_t nsector; uint32_t nsector;
IORange addr_ioport; MemoryRegion addr_ioport;
MemoryRegion extra_io;
QEMUBH *bh; QEMUBH *bh;
qemu_irq irq; qemu_irq irq;
/* Bit 0-2 and 7: BM status register /* Bit 0-2 and 7: BM status register
* Bit 3-6: bus->error_status */ * Bit 3-6: bus->error_status */
uint8_t migration_compat_status; uint8_t migration_compat_status;
struct PCIIDEState *pci_dev;
} BMDMAState; } BMDMAState;
typedef struct CMD646BAR {
MemoryRegion cmd;
MemoryRegion data;
IDEBus *bus;
struct PCIIDEState *pci_dev;
} CMD646BAR;
typedef struct PCIIDEState { typedef struct PCIIDEState {
PCIDevice dev; PCIDevice dev;
IDEBus bus[2]; IDEBus bus[2];
BMDMAState bmdma[2]; BMDMAState bmdma[2];
uint32_t secondary; /* used only for cmd646 */ uint32_t secondary; /* used only for cmd646 */
MemoryRegion bmdma_bar;
CMD646BAR cmd646_bar[2]; /* used only for cmd646 */
} PCIIDEState; } PCIIDEState;
@ -43,9 +54,9 @@ static inline IDEState *bmdma_active_if(BMDMAState *bmdma)
} }
void bmdma_init(IDEBus *bus, BMDMAState *bm); void bmdma_init(IDEBus *bus, BMDMAState *bm, PCIIDEState *d);
void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val); void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val);
extern const IORangeOps bmdma_addr_ioport_ops; extern MemoryRegionOps bmdma_addr_ioport_ops;
void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table); void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table);
extern const VMStateDescription vmstate_ide_pci; extern const VMStateDescription vmstate_ide_pci;

View File

@ -33,11 +33,15 @@
#include <hw/ide/pci.h> #include <hw/ide/pci.h>
static uint32_t bmdma_readb(void *opaque, uint32_t addr) static uint64_t bmdma_read(void *opaque, target_phys_addr_t addr, unsigned size)
{ {
BMDMAState *bm = opaque; BMDMAState *bm = opaque;
uint32_t val; uint32_t val;
if (size != 1) {
return ((uint64_t)1 << (size * 8)) - 1;
}
switch(addr & 3) { switch(addr & 3) {
case 0: case 0:
val = bm->cmd; val = bm->cmd;
@ -55,36 +59,46 @@ static uint32_t bmdma_readb(void *opaque, uint32_t addr)
return val; return val;
} }
static void bmdma_writeb(void *opaque, uint32_t addr, uint32_t val) static void bmdma_write(void *opaque, target_phys_addr_t addr,
uint64_t val, unsigned size)
{ {
BMDMAState *bm = opaque; BMDMAState *bm = opaque;
if (size != 1) {
return;
}
#ifdef DEBUG_IDE #ifdef DEBUG_IDE
printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val); printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val);
#endif #endif
switch(addr & 3) { switch(addr & 3) {
case 0:
return bmdma_cmd_writeb(bm, val);
case 2: case 2:
bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06); bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06);
break; break;
} }
} }
static void bmdma_map(PCIDevice *pci_dev, int region_num, static MemoryRegionOps piix_bmdma_ops = {
pcibus_t addr, pcibus_t size, int type) .read = bmdma_read,
.write = bmdma_write,
};
static void bmdma_setup_bar(PCIIDEState *d)
{ {
PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, pci_dev);
int i; int i;
memory_region_init(&d->bmdma_bar, "piix-bmdma-container", 16);
for(i = 0;i < 2; i++) { for(i = 0;i < 2; i++) {
BMDMAState *bm = &d->bmdma[i]; BMDMAState *bm = &d->bmdma[i];
register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm); memory_region_init_io(&bm->extra_io, &piix_bmdma_ops, bm,
"piix-bmdma", 4);
register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm); memory_region_add_subregion(&d->bmdma_bar, i * 8, &bm->extra_io);
register_ioport_read(addr, 4, 1, bmdma_readb, bm); memory_region_init_io(&bm->addr_ioport, &bmdma_addr_ioport_ops, bm,
"bmdma", 4);
iorange_init(&bm->addr_ioport, &bmdma_addr_ioport_ops, addr + 4, 4); memory_region_add_subregion(&d->bmdma_bar, i * 8 + 4, &bm->addr_ioport);
ioport_register(&bm->addr_ioport);
addr += 8;
} }
} }
@ -124,7 +138,7 @@ static void pci_piix_init_ports(PCIIDEState *d) {
ide_init_ioport(&d->bus[i], port_info[i].iobase, port_info[i].iobase2); ide_init_ioport(&d->bus[i], port_info[i].iobase, port_info[i].iobase2);
ide_init2(&d->bus[i], isa_get_irq(port_info[i].isairq)); ide_init2(&d->bus[i], isa_get_irq(port_info[i].isairq));
bmdma_init(&d->bus[i], &d->bmdma[i]); bmdma_init(&d->bus[i], &d->bmdma[i], d);
d->bmdma[i].bus = &d->bus[i]; d->bmdma[i].bus = &d->bus[i];
qemu_add_vm_change_state_handler(d->bus[i].dma->ops->restart_cb, qemu_add_vm_change_state_handler(d->bus[i].dma->ops->restart_cb,
&d->bmdma[i].dma); &d->bmdma[i].dma);
@ -140,7 +154,9 @@ static int pci_piix_ide_initfn(PCIDevice *dev)
qemu_register_reset(piix3_reset, d); qemu_register_reset(piix3_reset, d);
pci_register_bar(&d->dev, 4, 0x10, PCI_BASE_ADDRESS_SPACE_IO, bmdma_map); bmdma_setup_bar(d);
pci_register_bar_region(&d->dev, 4, PCI_BASE_ADDRESS_SPACE_IO,
&d->bmdma_bar);
vmstate_register(&d->dev.qdev, 0, &vmstate_ide_pci, d); vmstate_register(&d->dev.qdev, 0, &vmstate_ide_pci, d);
@ -185,6 +201,22 @@ PCIDevice *pci_piix3_xen_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
return dev; return dev;
} }
static int pci_piix_ide_exitfn(PCIDevice *dev)
{
PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
unsigned i;
for (i = 0; i < 2; ++i) {
memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].extra_io);
memory_region_destroy(&d->bmdma[i].extra_io);
memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].addr_ioport);
memory_region_destroy(&d->bmdma[i].addr_ioport);
}
memory_region_destroy(&d->bmdma_bar);
return 0;
}
/* hd_table must contain 4 block drivers */ /* hd_table must contain 4 block drivers */
/* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */ /* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
PCIDevice *pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn) PCIDevice *pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
@ -214,6 +246,7 @@ static PCIDeviceInfo piix_ide_info[] = {
.qdev.no_user = 1, .qdev.no_user = 1,
.no_hotplug = 1, .no_hotplug = 1,
.init = pci_piix_ide_initfn, .init = pci_piix_ide_initfn,
.exit = pci_piix_ide_exitfn,
.vendor_id = PCI_VENDOR_ID_INTEL, .vendor_id = PCI_VENDOR_ID_INTEL,
.device_id = PCI_DEVICE_ID_INTEL_82371SB_1, .device_id = PCI_DEVICE_ID_INTEL_82371SB_1,
.class_id = PCI_CLASS_STORAGE_IDE, .class_id = PCI_CLASS_STORAGE_IDE,
@ -231,6 +264,7 @@ static PCIDeviceInfo piix_ide_info[] = {
.qdev.no_user = 1, .qdev.no_user = 1,
.no_hotplug = 1, .no_hotplug = 1,
.init = pci_piix_ide_initfn, .init = pci_piix_ide_initfn,
.exit = pci_piix_ide_exitfn,
.vendor_id = PCI_VENDOR_ID_INTEL, .vendor_id = PCI_VENDOR_ID_INTEL,
.device_id = PCI_DEVICE_ID_INTEL_82371AB, .device_id = PCI_DEVICE_ID_INTEL_82371AB,
.class_id = PCI_CLASS_STORAGE_IDE, .class_id = PCI_CLASS_STORAGE_IDE,

View File

@ -34,11 +34,16 @@
#include <hw/ide/pci.h> #include <hw/ide/pci.h>
static uint32_t bmdma_readb(void *opaque, uint32_t addr) static uint64_t bmdma_read(void *opaque, target_phys_addr_t addr,
unsigned size)
{ {
BMDMAState *bm = opaque; BMDMAState *bm = opaque;
uint32_t val; uint32_t val;
if (size != 1) {
return ((uint64_t)1 << (size * 8)) - 1;
}
switch (addr & 3) { switch (addr & 3) {
case 0: case 0:
val = bm->cmd; val = bm->cmd;
@ -56,13 +61,21 @@ static uint32_t bmdma_readb(void *opaque, uint32_t addr)
return val; return val;
} }
static void bmdma_writeb(void *opaque, uint32_t addr, uint32_t val) static void bmdma_write(void *opaque, target_phys_addr_t addr,
uint64_t val, unsigned size)
{ {
BMDMAState *bm = opaque; BMDMAState *bm = opaque;
if (size != 1) {
return;
}
#ifdef DEBUG_IDE #ifdef DEBUG_IDE
printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val); printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val);
#endif #endif
switch (addr & 3) { switch (addr & 3) {
case 0:
return bmdma_cmd_writeb(bm, val);
case 2: case 2:
bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06); bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06);
break; break;
@ -70,23 +83,25 @@ static void bmdma_writeb(void *opaque, uint32_t addr, uint32_t val)
} }
} }
static void bmdma_map(PCIDevice *pci_dev, int region_num, static MemoryRegionOps via_bmdma_ops = {
pcibus_t addr, pcibus_t size, int type) .read = bmdma_read,
.write = bmdma_write,
};
static void bmdma_setup_bar(PCIIDEState *d)
{ {
PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, pci_dev);
int i; int i;
memory_region_init(&d->bmdma_bar, "via-bmdma-container", 16);
for(i = 0;i < 2; i++) { for(i = 0;i < 2; i++) {
BMDMAState *bm = &d->bmdma[i]; BMDMAState *bm = &d->bmdma[i];
register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm); memory_region_init_io(&bm->extra_io, &via_bmdma_ops, bm,
"via-bmdma", 4);
register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm); memory_region_add_subregion(&d->bmdma_bar, i * 8, &bm->extra_io);
register_ioport_read(addr, 4, 1, bmdma_readb, bm); memory_region_init_io(&bm->addr_ioport, &bmdma_addr_ioport_ops, bm,
"bmdma", 4);
iorange_init(&bm->addr_ioport, &bmdma_addr_ioport_ops, addr + 4, 4); memory_region_add_subregion(&d->bmdma_bar, i * 8 + 4, &bm->addr_ioport);
ioport_register(&bm->addr_ioport);
addr += 8;
} }
} }
@ -147,7 +162,7 @@ static void vt82c686b_init_ports(PCIIDEState *d) {
ide_init_ioport(&d->bus[i], port_info[i].iobase, port_info[i].iobase2); ide_init_ioport(&d->bus[i], port_info[i].iobase, port_info[i].iobase2);
ide_init2(&d->bus[i], isa_get_irq(port_info[i].isairq)); ide_init2(&d->bus[i], isa_get_irq(port_info[i].isairq));
bmdma_init(&d->bus[i], &d->bmdma[i]); bmdma_init(&d->bus[i], &d->bmdma[i], d);
d->bmdma[i].bus = &d->bus[i]; d->bmdma[i].bus = &d->bus[i];
qemu_add_vm_change_state_handler(d->bus[i].dma->ops->restart_cb, qemu_add_vm_change_state_handler(d->bus[i].dma->ops->restart_cb,
&d->bmdma[i].dma); &d->bmdma[i].dma);
@ -164,8 +179,9 @@ static int vt82c686b_ide_initfn(PCIDevice *dev)
pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x000000c0); pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x000000c0);
qemu_register_reset(via_reset, d); qemu_register_reset(via_reset, d);
pci_register_bar(&d->dev, 4, 0x10, bmdma_setup_bar(d);
PCI_BASE_ADDRESS_SPACE_IO, bmdma_map); pci_register_bar_region(&d->dev, 4, PCI_BASE_ADDRESS_SPACE_IO,
&d->bmdma_bar);
vmstate_register(&dev->qdev, 0, &vmstate_ide_pci, d); vmstate_register(&dev->qdev, 0, &vmstate_ide_pci, d);
@ -174,6 +190,22 @@ static int vt82c686b_ide_initfn(PCIDevice *dev)
return 0; return 0;
} }
static int vt82c686b_ide_exitfn(PCIDevice *dev)
{
PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
unsigned i;
for (i = 0; i < 2; ++i) {
memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].extra_io);
memory_region_destroy(&d->bmdma[i].extra_io);
memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].addr_ioport);
memory_region_destroy(&d->bmdma[i].addr_ioport);
}
memory_region_destroy(&d->bmdma_bar);
return 0;
}
void vt82c686b_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn) void vt82c686b_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
{ {
PCIDevice *dev; PCIDevice *dev;
@ -187,6 +219,7 @@ static PCIDeviceInfo via_ide_info = {
.qdev.size = sizeof(PCIIDEState), .qdev.size = sizeof(PCIIDEState),
.qdev.no_user = 1, .qdev.no_user = 1,
.init = vt82c686b_ide_initfn, .init = vt82c686b_ide_initfn,
.exit = vt82c686b_ide_exitfn,
.vendor_id = PCI_VENDOR_ID_VIA, .vendor_id = PCI_VENDOR_ID_VIA,
.device_id = PCI_DEVICE_ID_VIA_IDE, .device_id = PCI_DEVICE_ID_VIA_IDE,
.revision = 0x06, .revision = 0x06,