Commit 34e538ae5d87d263c024d1b803ccef4983807556
1 parent
9995c51f
added PIIX3 like IDE controller - PCI irq generation - SETFEATURES IDE command support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@852 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
76 additions
and
17 deletions
hw/ide.c
@@ -297,6 +297,7 @@ typedef struct IDEState { | @@ -297,6 +297,7 @@ typedef struct IDEState { | ||
297 | int64_t nb_sectors; | 297 | int64_t nb_sectors; |
298 | int mult_sectors; | 298 | int mult_sectors; |
299 | int irq; | 299 | int irq; |
300 | + PCIDevice *pci_dev; | ||
300 | int drive_serial; | 301 | int drive_serial; |
301 | /* ide regs */ | 302 | /* ide regs */ |
302 | uint8_t feature; | 303 | uint8_t feature; |
@@ -463,7 +464,10 @@ static inline void ide_abort_command(IDEState *s) | @@ -463,7 +464,10 @@ static inline void ide_abort_command(IDEState *s) | ||
463 | static inline void ide_set_irq(IDEState *s) | 464 | static inline void ide_set_irq(IDEState *s) |
464 | { | 465 | { |
465 | if (!(s->cmd & IDE_CMD_DISABLE_IRQ)) { | 466 | if (!(s->cmd & IDE_CMD_DISABLE_IRQ)) { |
466 | - pic_set_irq(s->irq, 1); | 467 | + if (s->irq == 16) |
468 | + pci_set_irq(s->pci_dev, 0, 1); | ||
469 | + else | ||
470 | + pic_set_irq(s->irq, 1); | ||
467 | } | 471 | } |
468 | } | 472 | } |
469 | 473 | ||
@@ -1169,7 +1173,22 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) | @@ -1169,7 +1173,22 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) | ||
1169 | s->status = READY_STAT; | 1173 | s->status = READY_STAT; |
1170 | ide_set_irq(s); | 1174 | ide_set_irq(s); |
1171 | break; | 1175 | break; |
1172 | - | 1176 | + case WIN_SETFEATURES: |
1177 | + if (!s->bs) | ||
1178 | + goto abort_cmd; | ||
1179 | + /* XXX: valid for CDROM ? */ | ||
1180 | + switch(s->feature) { | ||
1181 | + case 0x02: /* write cache enable */ | ||
1182 | + case 0x82: /* write cache disable */ | ||
1183 | + case 0xaa: /* read look-ahead enable */ | ||
1184 | + case 0x55: /* read look-ahead disable */ | ||
1185 | + s->status = READY_STAT; | ||
1186 | + ide_set_irq(s); | ||
1187 | + break; | ||
1188 | + default: | ||
1189 | + goto abort_cmd; | ||
1190 | + } | ||
1191 | + break; | ||
1173 | /* ATAPI commands */ | 1192 | /* ATAPI commands */ |
1174 | case WIN_PIDENTIFY: | 1193 | case WIN_PIDENTIFY: |
1175 | if (s->is_cdrom) { | 1194 | if (s->is_cdrom) { |
@@ -1262,7 +1281,10 @@ static uint32_t ide_ioport_read(void *opaque, uint32_t addr1) | @@ -1262,7 +1281,10 @@ static uint32_t ide_ioport_read(void *opaque, uint32_t addr1) | ||
1262 | ret = 0; | 1281 | ret = 0; |
1263 | else | 1282 | else |
1264 | ret = s->status; | 1283 | ret = s->status; |
1265 | - pic_set_irq(s->irq, 0); | 1284 | + if (s->irq == 16) |
1285 | + pci_set_irq(s->pci_dev, 0, 0); | ||
1286 | + else | ||
1287 | + pic_set_irq(s->irq, 0); | ||
1266 | break; | 1288 | break; |
1267 | } | 1289 | } |
1268 | #ifdef DEBUG_IDE | 1290 | #ifdef DEBUG_IDE |
@@ -1481,20 +1503,8 @@ static void ide_init2(IDEState *ide_state, int irq, | @@ -1481,20 +1503,8 @@ static void ide_init2(IDEState *ide_state, int irq, | ||
1481 | } | 1503 | } |
1482 | } | 1504 | } |
1483 | 1505 | ||
1484 | -/***********************************************************/ | ||
1485 | -/* ISA IDE definitions */ | ||
1486 | - | ||
1487 | -void isa_ide_init(int iobase, int iobase2, int irq, | ||
1488 | - BlockDriverState *hd0, BlockDriverState *hd1) | 1506 | +static void ide_init_ioport(IDEState *ide_state, int iobase, int iobase2) |
1489 | { | 1507 | { |
1490 | - IDEState *ide_state; | ||
1491 | - | ||
1492 | - ide_state = qemu_mallocz(sizeof(IDEState) * 2); | ||
1493 | - if (!ide_state) | ||
1494 | - return; | ||
1495 | - | ||
1496 | - ide_init2(ide_state, irq, hd0, hd1); | ||
1497 | - | ||
1498 | register_ioport_write(iobase, 8, 1, ide_ioport_write, ide_state); | 1508 | register_ioport_write(iobase, 8, 1, ide_ioport_write, ide_state); |
1499 | register_ioport_read(iobase, 8, 1, ide_ioport_read, ide_state); | 1509 | register_ioport_read(iobase, 8, 1, ide_ioport_read, ide_state); |
1500 | if (iobase2) { | 1510 | if (iobase2) { |
@@ -1510,6 +1520,22 @@ void isa_ide_init(int iobase, int iobase2, int irq, | @@ -1510,6 +1520,22 @@ void isa_ide_init(int iobase, int iobase2, int irq, | ||
1510 | } | 1520 | } |
1511 | 1521 | ||
1512 | /***********************************************************/ | 1522 | /***********************************************************/ |
1523 | +/* ISA IDE definitions */ | ||
1524 | + | ||
1525 | +void isa_ide_init(int iobase, int iobase2, int irq, | ||
1526 | + BlockDriverState *hd0, BlockDriverState *hd1) | ||
1527 | +{ | ||
1528 | + IDEState *ide_state; | ||
1529 | + | ||
1530 | + ide_state = qemu_mallocz(sizeof(IDEState) * 2); | ||
1531 | + if (!ide_state) | ||
1532 | + return; | ||
1533 | + | ||
1534 | + ide_init2(ide_state, irq, hd0, hd1); | ||
1535 | + ide_init_ioport(ide_state, iobase, iobase2); | ||
1536 | +} | ||
1537 | + | ||
1538 | +/***********************************************************/ | ||
1513 | /* PCI IDE definitions */ | 1539 | /* PCI IDE definitions */ |
1514 | 1540 | ||
1515 | typedef struct PCIIDEState { | 1541 | typedef struct PCIIDEState { |
@@ -1546,7 +1572,8 @@ void pci_ide_init(BlockDriverState **hd_table) | @@ -1546,7 +1572,8 @@ void pci_ide_init(BlockDriverState **hd_table) | ||
1546 | { | 1572 | { |
1547 | PCIIDEState *d; | 1573 | PCIIDEState *d; |
1548 | uint8_t *pci_conf; | 1574 | uint8_t *pci_conf; |
1549 | - | 1575 | + int i; |
1576 | + | ||
1550 | d = (PCIIDEState *)pci_register_device("IDE", sizeof(PCIIDEState), | 1577 | d = (PCIIDEState *)pci_register_device("IDE", sizeof(PCIIDEState), |
1551 | 0, -1, | 1578 | 0, -1, |
1552 | NULL, NULL); | 1579 | NULL, NULL); |
@@ -1573,6 +1600,38 @@ void pci_ide_init(BlockDriverState **hd_table) | @@ -1573,6 +1600,38 @@ void pci_ide_init(BlockDriverState **hd_table) | ||
1573 | pci_register_io_region((PCIDevice *)d, 3, 0x4, | 1600 | pci_register_io_region((PCIDevice *)d, 3, 0x4, |
1574 | PCI_ADDRESS_SPACE_IO, ide_map); | 1601 | PCI_ADDRESS_SPACE_IO, ide_map); |
1575 | 1602 | ||
1603 | + pci_conf[0x3d] = 0x01; // interrupt on pin 1 | ||
1604 | + | ||
1605 | + for(i = 0; i < 4; i++) | ||
1606 | + d->ide_if[i].pci_dev = (PCIDevice *)d; | ||
1607 | + ide_init2(&d->ide_if[0], 16, hd_table[0], hd_table[1]); | ||
1608 | + ide_init2(&d->ide_if[2], 16, hd_table[2], hd_table[3]); | ||
1609 | +} | ||
1610 | + | ||
1611 | +/* hd_table must contain 4 block drivers */ | ||
1612 | +/* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */ | ||
1613 | +void pci_piix3_ide_init(BlockDriverState **hd_table) | ||
1614 | +{ | ||
1615 | + PCIIDEState *d; | ||
1616 | + uint8_t *pci_conf; | ||
1617 | + | ||
1618 | + /* register a function 1 of PIIX3 */ | ||
1619 | + d = (PCIIDEState *)pci_register_device("PIIX3 IDE", sizeof(PCIIDEState), | ||
1620 | + 0, ((PCIDevice *)piix3_state)->devfn + 1, | ||
1621 | + NULL, NULL); | ||
1622 | + pci_conf = d->dev.config; | ||
1623 | + pci_conf[0x00] = 0x86; // Intel | ||
1624 | + pci_conf[0x01] = 0x80; | ||
1625 | + pci_conf[0x02] = 0x10; | ||
1626 | + pci_conf[0x03] = 0x70; | ||
1627 | + pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE | ||
1628 | + pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage | ||
1629 | + pci_conf[0x0e] = 0x00; // header_type | ||
1630 | + | ||
1631 | + /* XXX: must add BMDMA support to be fully compliant */ | ||
1632 | + | ||
1576 | ide_init2(&d->ide_if[0], 14, hd_table[0], hd_table[1]); | 1633 | ide_init2(&d->ide_if[0], 14, hd_table[0], hd_table[1]); |
1577 | ide_init2(&d->ide_if[2], 15, hd_table[2], hd_table[3]); | 1634 | ide_init2(&d->ide_if[2], 15, hd_table[2], hd_table[3]); |
1635 | + ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6); | ||
1636 | + ide_init_ioport(&d->ide_if[2], 0x170, 0x376); | ||
1578 | } | 1637 | } |