|
@@ -104,6 +104,90 @@ const MemoryRegionOps pci_ide_data_le_ops = {
|
|
|
.endianness = DEVICE_LITTLE_ENDIAN,
|
|
|
};
|
|
|
|
|
|
+void pci_ide_update_mode(PCIIDEState *s)
|
|
|
+{
|
|
|
+ PCIDevice *d = PCI_DEVICE(s);
|
|
|
+ uint8_t mode = d->config[PCI_CLASS_PROG];
|
|
|
+
|
|
|
+ /*
|
|
|
+ * This function only configures the BARs/ioports for now: PCI IDE
|
|
|
+ * controllers must manage their own IRQ routing
|
|
|
+ */
|
|
|
+
|
|
|
+ switch (mode & 0xf) {
|
|
|
+ case 0xa:
|
|
|
+ /* Both channels legacy mode */
|
|
|
+
|
|
|
+ /*
|
|
|
+ * TODO: according to the PCI IDE specification the BARs should
|
|
|
+ * be completely disabled, however Linux for the pegasos2
|
|
|
+ * machine stil accesses the BAR addresses after switching to legacy
|
|
|
+ * mode. Hence we leave them active for now.
|
|
|
+ */
|
|
|
+
|
|
|
+ /* Clear interrupt pin */
|
|
|
+ pci_config_set_interrupt_pin(d->config, 0);
|
|
|
+
|
|
|
+ /* Add legacy IDE ports */
|
|
|
+ if (!s->bus[0].portio_list.owner) {
|
|
|
+ portio_list_init(&s->bus[0].portio_list, OBJECT(d),
|
|
|
+ ide_portio_list, &s->bus[0], "ide");
|
|
|
+ portio_list_add(&s->bus[0].portio_list,
|
|
|
+ pci_address_space_io(d), 0x1f0);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!s->bus[0].portio2_list.owner) {
|
|
|
+ portio_list_init(&s->bus[0].portio2_list, OBJECT(d),
|
|
|
+ ide_portio2_list, &s->bus[0], "ide");
|
|
|
+ portio_list_add(&s->bus[0].portio2_list,
|
|
|
+ pci_address_space_io(d), 0x3f6);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!s->bus[1].portio_list.owner) {
|
|
|
+ portio_list_init(&s->bus[1].portio_list, OBJECT(d),
|
|
|
+ ide_portio_list, &s->bus[1], "ide");
|
|
|
+ portio_list_add(&s->bus[1].portio_list,
|
|
|
+ pci_address_space_io(d), 0x170);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!s->bus[1].portio2_list.owner) {
|
|
|
+ portio_list_init(&s->bus[1].portio2_list, OBJECT(d),
|
|
|
+ ide_portio2_list, &s->bus[1], "ide");
|
|
|
+ portio_list_add(&s->bus[1].portio2_list,
|
|
|
+ pci_address_space_io(d), 0x376);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 0xf:
|
|
|
+ /* Both channels native mode */
|
|
|
+
|
|
|
+ /* Set interrupt pin */
|
|
|
+ pci_config_set_interrupt_pin(d->config, 1);
|
|
|
+
|
|
|
+ /* Remove legacy IDE ports */
|
|
|
+ if (s->bus[0].portio_list.owner) {
|
|
|
+ portio_list_del(&s->bus[0].portio_list);
|
|
|
+ portio_list_destroy(&s->bus[0].portio_list);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (s->bus[0].portio2_list.owner) {
|
|
|
+ portio_list_del(&s->bus[0].portio2_list);
|
|
|
+ portio_list_destroy(&s->bus[0].portio2_list);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (s->bus[1].portio_list.owner) {
|
|
|
+ portio_list_del(&s->bus[1].portio_list);
|
|
|
+ portio_list_destroy(&s->bus[1].portio_list);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (s->bus[1].portio2_list.owner) {
|
|
|
+ portio_list_del(&s->bus[1].portio2_list);
|
|
|
+ portio_list_destroy(&s->bus[1].portio2_list);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static IDEState *bmdma_active_if(BMDMAState *bmdma)
|
|
|
{
|
|
|
assert(bmdma->bus->retry_unit != (uint8_t)-1);
|