|
|
1.1 ! root 1: /* ! 2: * QEMU IDE Emulation: PCI PIIX3/4 support. ! 3: * ! 4: * Copyright (c) 2003 Fabrice Bellard ! 5: * Copyright (c) 2006 Openedhand Ltd. ! 6: * ! 7: * Permission is hereby granted, free of charge, to any person obtaining a copy ! 8: * of this software and associated documentation files (the "Software"), to deal ! 9: * in the Software without restriction, including without limitation the rights ! 10: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ! 11: * copies of the Software, and to permit persons to whom the Software is ! 12: * furnished to do so, subject to the following conditions: ! 13: * ! 14: * The above copyright notice and this permission notice shall be included in ! 15: * all copies or substantial portions of the Software. ! 16: * ! 17: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ! 18: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ! 19: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ! 20: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ! 21: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ! 22: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ! 23: * THE SOFTWARE. ! 24: */ ! 25: #include <hw/hw.h> ! 26: #include <hw/pc.h> ! 27: #include <hw/pci.h> ! 28: #include <hw/isa.h> ! 29: #include "block.h" ! 30: #include "block_int.h" ! 31: #include "sysemu.h" ! 32: #include "dma.h" ! 33: ! 34: #include <hw/ide/pci.h> ! 35: ! 36: static uint32_t bmdma_readb(void *opaque, uint32_t addr) ! 37: { ! 38: BMDMAState *bm = opaque; ! 39: uint32_t val; ! 40: ! 41: switch(addr & 3) { ! 42: case 0: ! 43: val = bm->cmd; ! 44: break; ! 45: case 2: ! 46: val = bm->status; ! 47: break; ! 48: default: ! 49: val = 0xff; ! 50: break; ! 51: } ! 52: #ifdef DEBUG_IDE ! 53: printf("bmdma: readb 0x%02x : 0x%02x\n", addr, val); ! 54: #endif ! 55: return val; ! 56: } ! 57: ! 58: static void bmdma_writeb(void *opaque, uint32_t addr, uint32_t val) ! 59: { ! 60: BMDMAState *bm = opaque; ! 61: #ifdef DEBUG_IDE ! 62: printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val); ! 63: #endif ! 64: switch(addr & 3) { ! 65: case 2: ! 66: bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06); ! 67: break; ! 68: } ! 69: } ! 70: ! 71: static void bmdma_map(PCIDevice *pci_dev, int region_num, ! 72: pcibus_t addr, pcibus_t size, int type) ! 73: { ! 74: PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, pci_dev); ! 75: int i; ! 76: ! 77: for(i = 0;i < 2; i++) { ! 78: BMDMAState *bm = &d->bmdma[i]; ! 79: d->bus[i].bmdma = bm; ! 80: bm->bus = d->bus+i; ! 81: qemu_add_vm_change_state_handler(ide_dma_restart_cb, bm); ! 82: ! 83: register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm); ! 84: ! 85: register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm); ! 86: register_ioport_read(addr, 4, 1, bmdma_readb, bm); ! 87: ! 88: register_ioport_write(addr + 4, 4, 1, bmdma_addr_writeb, bm); ! 89: register_ioport_read(addr + 4, 4, 1, bmdma_addr_readb, bm); ! 90: register_ioport_write(addr + 4, 4, 2, bmdma_addr_writew, bm); ! 91: register_ioport_read(addr + 4, 4, 2, bmdma_addr_readw, bm); ! 92: register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm); ! 93: register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm); ! 94: addr += 8; ! 95: } ! 96: } ! 97: ! 98: static void piix3_reset(void *opaque) ! 99: { ! 100: PCIIDEState *d = opaque; ! 101: uint8_t *pci_conf = d->dev.config; ! 102: int i; ! 103: ! 104: for (i = 0; i < 2; i++) { ! 105: ide_bus_reset(&d->bus[i]); ! 106: ide_dma_reset(&d->bmdma[i]); ! 107: } ! 108: ! 109: pci_conf[0x04] = 0x00; ! 110: pci_conf[0x05] = 0x00; ! 111: pci_conf[0x06] = 0x80; /* FBC */ ! 112: pci_conf[0x07] = 0x02; // PCI_status_devsel_medium ! 113: pci_conf[0x20] = 0x01; /* BMIBA: 20-23h */ ! 114: } ! 115: ! 116: static int pci_piix_ide_initfn(PCIIDEState *d) ! 117: { ! 118: uint8_t *pci_conf = d->dev.config; ! 119: ! 120: pci_conf[0x09] = 0x80; // legacy ATA mode ! 121: pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_IDE); ! 122: pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type ! 123: ! 124: qemu_register_reset(piix3_reset, d); ! 125: ! 126: pci_register_bar(&d->dev, 4, 0x10, PCI_BASE_ADDRESS_SPACE_IO, bmdma_map); ! 127: ! 128: vmstate_register(0, &vmstate_ide_pci, d); ! 129: ! 130: ide_bus_new(&d->bus[0], &d->dev.qdev); ! 131: ide_bus_new(&d->bus[1], &d->dev.qdev); ! 132: ide_init_ioport(&d->bus[0], 0x1f0, 0x3f6); ! 133: ide_init_ioport(&d->bus[1], 0x170, 0x376); ! 134: ! 135: ide_init2(&d->bus[0], NULL, NULL, isa_reserve_irq(14)); ! 136: ide_init2(&d->bus[1], NULL, NULL, isa_reserve_irq(15)); ! 137: return 0; ! 138: } ! 139: ! 140: static int pci_piix3_ide_initfn(PCIDevice *dev) ! 141: { ! 142: PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev); ! 143: ! 144: pci_config_set_vendor_id(d->dev.config, PCI_VENDOR_ID_INTEL); ! 145: pci_config_set_device_id(d->dev.config, PCI_DEVICE_ID_INTEL_82371SB_1); ! 146: return pci_piix_ide_initfn(d); ! 147: } ! 148: ! 149: static int pci_piix4_ide_initfn(PCIDevice *dev) ! 150: { ! 151: PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev); ! 152: ! 153: pci_config_set_vendor_id(d->dev.config, PCI_VENDOR_ID_INTEL); ! 154: pci_config_set_device_id(d->dev.config, PCI_DEVICE_ID_INTEL_82371AB); ! 155: return pci_piix_ide_initfn(d); ! 156: } ! 157: ! 158: /* hd_table must contain 4 block drivers */ ! 159: /* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */ ! 160: void pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn) ! 161: { ! 162: PCIDevice *dev; ! 163: ! 164: dev = pci_create_simple(bus, devfn, "piix3-ide"); ! 165: pci_ide_create_devs(dev, hd_table); ! 166: } ! 167: ! 168: /* hd_table must contain 4 block drivers */ ! 169: /* NOTE: for the PIIX4, the IRQs and IOports are hardcoded */ ! 170: void pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn) ! 171: { ! 172: PCIDevice *dev; ! 173: ! 174: dev = pci_create_simple(bus, devfn, "piix4-ide"); ! 175: pci_ide_create_devs(dev, hd_table); ! 176: } ! 177: ! 178: static PCIDeviceInfo piix_ide_info[] = { ! 179: { ! 180: .qdev.name = "piix3-ide", ! 181: .qdev.size = sizeof(PCIIDEState), ! 182: .qdev.no_user = 1, ! 183: .init = pci_piix3_ide_initfn, ! 184: },{ ! 185: .qdev.name = "piix4-ide", ! 186: .qdev.size = sizeof(PCIIDEState), ! 187: .qdev.no_user = 1, ! 188: .init = pci_piix4_ide_initfn, ! 189: },{ ! 190: /* end of list */ ! 191: } ! 192: }; ! 193: ! 194: static void piix_ide_register(void) ! 195: { ! 196: pci_qdev_register_many(piix_ide_info); ! 197: } ! 198: device_init(piix_ide_register);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.