1 /* 2 * QEMU Intel i82378 emulation (PCI to ISA bridge) 3 * 4 * Copyright (c) 2010-2011 Hervé Poussineau 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "hw/pci/pci.h" 21 #include "hw/i386/pc.h" 22 #include "hw/timer/i8254.h" 23 #include "hw/audio/pcspk.h" 24 25 //#define DEBUG_I82378 26 27 #ifdef DEBUG_I82378 28 #define DPRINTF(fmt, ...) \ 29 do { fprintf(stderr, "i82378: " fmt , ## __VA_ARGS__); } while (0) 30 #else 31 #define DPRINTF(fmt, ...) \ 32 do {} while (0) 33 #endif 34 35 #define BADF(fmt, ...) \ 36 do { fprintf(stderr, "i82378 ERROR: " fmt , ## __VA_ARGS__); } while (0) 37 38 typedef struct I82378State { 39 qemu_irq out[2]; 40 qemu_irq *i8259; 41 MemoryRegion io; 42 MemoryRegion mem; 43 } I82378State; 44 45 typedef struct PCIi82378State { 46 PCIDevice pci_dev; 47 uint32_t isa_io_base; 48 uint32_t isa_mem_base; 49 I82378State state; 50 } PCIi82378State; 51 52 static const VMStateDescription vmstate_pci_i82378 = { 53 .name = "pci-i82378", 54 .version_id = 0, 55 .minimum_version_id = 0, 56 .fields = (VMStateField[]) { 57 VMSTATE_PCI_DEVICE(pci_dev, PCIi82378State), 58 VMSTATE_END_OF_LIST() 59 }, 60 }; 61 62 static void i82378_io_write(void *opaque, hwaddr addr, 63 uint64_t value, unsigned int size) 64 { 65 switch (size) { 66 case 1: 67 DPRINTF("%s: " TARGET_FMT_plx "=%02" PRIx64 "\n", __func__, 68 addr, value); 69 cpu_outb(addr, value); 70 break; 71 case 2: 72 DPRINTF("%s: " TARGET_FMT_plx "=%04" PRIx64 "\n", __func__, 73 addr, value); 74 cpu_outw(addr, value); 75 break; 76 case 4: 77 DPRINTF("%s: " TARGET_FMT_plx "=%08" PRIx64 "\n", __func__, 78 addr, value); 79 cpu_outl(addr, value); 80 break; 81 default: 82 abort(); 83 } 84 } 85 86 static uint64_t i82378_io_read(void *opaque, hwaddr addr, 87 unsigned int size) 88 { 89 DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr); 90 switch (size) { 91 case 1: 92 return cpu_inb(addr); 93 case 2: 94 return cpu_inw(addr); 95 case 4: 96 return cpu_inl(addr); 97 default: 98 abort(); 99 } 100 } 101 102 static const MemoryRegionOps i82378_io_ops = { 103 .read = i82378_io_read, 104 .write = i82378_io_write, 105 .endianness = DEVICE_LITTLE_ENDIAN, 106 }; 107 108 static void i82378_mem_write(void *opaque, hwaddr addr, 109 uint64_t value, unsigned int size) 110 { 111 switch (size) { 112 case 1: 113 DPRINTF("%s: " TARGET_FMT_plx "=%02" PRIx64 "\n", __func__, 114 addr, value); 115 cpu_outb(addr, value); 116 break; 117 case 2: 118 DPRINTF("%s: " TARGET_FMT_plx "=%04" PRIx64 "\n", __func__, 119 addr, value); 120 cpu_outw(addr, value); 121 break; 122 case 4: 123 DPRINTF("%s: " TARGET_FMT_plx "=%08" PRIx64 "\n", __func__, 124 addr, value); 125 cpu_outl(addr, value); 126 break; 127 default: 128 abort(); 129 } 130 } 131 132 static uint64_t i82378_mem_read(void *opaque, hwaddr addr, 133 unsigned int size) 134 { 135 DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr); 136 switch (size) { 137 case 1: 138 return cpu_inb(addr); 139 case 2: 140 return cpu_inw(addr); 141 case 4: 142 return cpu_inl(addr); 143 default: 144 abort(); 145 } 146 } 147 148 static const MemoryRegionOps i82378_mem_ops = { 149 .read = i82378_mem_read, 150 .write = i82378_mem_write, 151 .endianness = DEVICE_LITTLE_ENDIAN, 152 }; 153 154 static void i82378_request_out0_irq(void *opaque, int irq, int level) 155 { 156 I82378State *s = opaque; 157 qemu_set_irq(s->out[0], level); 158 } 159 160 static void i82378_request_pic_irq(void *opaque, int irq, int level) 161 { 162 DeviceState *dev = opaque; 163 PCIDevice *pci = DO_UPCAST(PCIDevice, qdev, dev); 164 PCIi82378State *s = DO_UPCAST(PCIi82378State, pci_dev, pci); 165 166 qemu_set_irq(s->state.i8259[irq], level); 167 } 168 169 static void i82378_init(DeviceState *dev, I82378State *s) 170 { 171 ISABus *isabus = DO_UPCAST(ISABus, qbus, qdev_get_child_bus(dev, "isa.0")); 172 ISADevice *pit; 173 ISADevice *isa; 174 qemu_irq *out0_irq; 175 176 /* This device has: 177 2 82C59 (irq) 178 1 82C54 (pit) 179 2 82C37 (dma) 180 NMI 181 Utility Bus Support Registers 182 183 All devices accept byte access only, except timer 184 */ 185 186 qdev_init_gpio_out(dev, s->out, 2); 187 qdev_init_gpio_in(dev, i82378_request_pic_irq, 16); 188 189 /* Workaround the fact that i8259 is not qdev'ified... */ 190 out0_irq = qemu_allocate_irqs(i82378_request_out0_irq, s, 1); 191 192 /* 2 82C59 (irq) */ 193 s->i8259 = i8259_init(isabus, *out0_irq); 194 isa_bus_irqs(isabus, s->i8259); 195 196 /* 1 82C54 (pit) */ 197 pit = pit_init(isabus, 0x40, 0, NULL); 198 199 /* speaker */ 200 pcspk_init(isabus, pit); 201 202 /* 2 82C37 (dma) */ 203 isa = isa_create_simple(isabus, "i82374"); 204 qdev_connect_gpio_out(&isa->qdev, 0, s->out[1]); 205 206 /* timer */ 207 isa_create_simple(isabus, "mc146818rtc"); 208 } 209 210 static int pci_i82378_init(PCIDevice *dev) 211 { 212 PCIi82378State *pci = DO_UPCAST(PCIi82378State, pci_dev, dev); 213 I82378State *s = &pci->state; 214 uint8_t *pci_conf; 215 216 pci_conf = dev->config; 217 pci_set_word(pci_conf + PCI_COMMAND, 218 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); 219 pci_set_word(pci_conf + PCI_STATUS, 220 PCI_STATUS_DEVSEL_MEDIUM); 221 222 pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin 0 */ 223 224 memory_region_init_io(&s->io, &i82378_io_ops, s, "i82378-io", 0x00010000); 225 pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io); 226 227 memory_region_init_io(&s->mem, &i82378_mem_ops, s, "i82378-mem", 0x01000000); 228 pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem); 229 230 /* Make I/O address read only */ 231 pci_set_word(dev->wmask + PCI_COMMAND, PCI_COMMAND_SPECIAL); 232 pci_set_long(dev->wmask + PCI_BASE_ADDRESS_0, 0); 233 pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, pci->isa_io_base); 234 235 isa_mem_base = pci->isa_mem_base; 236 isa_bus_new(&dev->qdev, pci_address_space_io(dev)); 237 238 i82378_init(&dev->qdev, s); 239 240 return 0; 241 } 242 243 static Property i82378_properties[] = { 244 DEFINE_PROP_HEX32("iobase", PCIi82378State, isa_io_base, 0x80000000), 245 DEFINE_PROP_HEX32("membase", PCIi82378State, isa_mem_base, 0xc0000000), 246 DEFINE_PROP_END_OF_LIST() 247 }; 248 249 static void pci_i82378_class_init(ObjectClass *klass, void *data) 250 { 251 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 252 DeviceClass *dc = DEVICE_CLASS(klass); 253 254 k->init = pci_i82378_init; 255 k->vendor_id = PCI_VENDOR_ID_INTEL; 256 k->device_id = PCI_DEVICE_ID_INTEL_82378; 257 k->revision = 0x03; 258 k->class_id = PCI_CLASS_BRIDGE_ISA; 259 k->subsystem_vendor_id = 0x0; 260 k->subsystem_id = 0x0; 261 dc->vmsd = &vmstate_pci_i82378; 262 dc->props = i82378_properties; 263 } 264 265 static const TypeInfo pci_i82378_info = { 266 .name = "i82378", 267 .parent = TYPE_PCI_DEVICE, 268 .instance_size = sizeof(PCIi82378State), 269 .class_init = pci_i82378_class_init, 270 }; 271 272 static void i82378_register_types(void) 273 { 274 type_register_static(&pci_i82378_info); 275 } 276 277 type_init(i82378_register_types) 278