Annotation of qemu/hw/piix_pci.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * QEMU i440FX/PIIX3 PCI Bridge Emulation
                      3:  *
                      4:  * Copyright (c) 2006 Fabrice Bellard
                      5:  * 
                      6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      7:  * of this software and associated documentation files (the "Software"), to deal
                      8:  * in the Software without restriction, including without limitation the rights
                      9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     10:  * copies of the Software, and to permit persons to whom the Software is
                     11:  * furnished to do so, subject to the following conditions:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included in
                     14:  * all copies or substantial portions of the Software.
                     15:  *
                     16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     22:  * THE SOFTWARE.
                     23:  */
                     24: 
                     25: #include "vl.h"
                     26: typedef uint32_t pci_addr_t;
                     27: #include "pci_host.h"
                     28: 
                     29: typedef PCIHostState I440FXState;
                     30: 
                     31: static void i440fx_addr_writel(void* opaque, uint32_t addr, uint32_t val)
                     32: {
                     33:     I440FXState *s = opaque;
                     34:     s->config_reg = val;
                     35: }
                     36: 
                     37: static uint32_t i440fx_addr_readl(void* opaque, uint32_t addr)
                     38: {
                     39:     I440FXState *s = opaque;
                     40:     return s->config_reg;
                     41: }
                     42: 
                     43: static void piix3_set_irq(PCIDevice *pci_dev, void *pic, int irq_num, int level);
                     44: 
                     45: PCIBus *i440fx_init(void)
                     46: {
                     47:     PCIBus *b;
                     48:     PCIDevice *d;
                     49:     I440FXState *s;
                     50: 
                     51:     s = qemu_mallocz(sizeof(I440FXState));
                     52:     b = pci_register_bus(piix3_set_irq, NULL, 0);
                     53:     s->bus = b;
                     54: 
                     55:     register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
                     56:     register_ioport_read(0xcf8, 4, 4, i440fx_addr_readl, s);
                     57: 
                     58:     register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb, s);
                     59:     register_ioport_write(0xcfc, 4, 2, pci_host_data_writew, s);
                     60:     register_ioport_write(0xcfc, 4, 4, pci_host_data_writel, s);
                     61:     register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s);
                     62:     register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
                     63:     register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
                     64: 
                     65:     d = pci_register_device(b, "i440FX", sizeof(PCIDevice), 0, 
                     66:                             NULL, NULL);
                     67: 
                     68:     d->config[0x00] = 0x86; // vendor_id
                     69:     d->config[0x01] = 0x80;
                     70:     d->config[0x02] = 0x37; // device_id
                     71:     d->config[0x03] = 0x12;
                     72:     d->config[0x08] = 0x02; // revision
                     73:     d->config[0x0a] = 0x00; // class_sub = host2pci
                     74:     d->config[0x0b] = 0x06; // class_base = PCI_bridge
                     75:     d->config[0x0e] = 0x00; // header_type
                     76:     return b;
                     77: }
                     78: 
                     79: /* PIIX3 PCI to ISA bridge */
                     80: 
                     81: static PCIDevice *piix3_dev;
                     82: 
                     83: /* just used for simpler irq handling. */
                     84: #define PCI_IRQ_WORDS   ((PCI_DEVICES_MAX + 31) / 32)
                     85: 
                     86: static uint32_t pci_irq_levels[4][PCI_IRQ_WORDS];
                     87: 
                     88: /* return the global irq number corresponding to a given device irq
                     89:    pin. We could also use the bus number to have a more precise
                     90:    mapping. */
                     91: static inline int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
                     92: {
                     93:     int slot_addend;
                     94:     slot_addend = (pci_dev->devfn >> 3) - 1;
                     95:     return (irq_num + slot_addend) & 3;
                     96: }
                     97: 
                     98: static inline int get_pci_irq_level(int irq_num)
                     99: {
                    100:     int pic_level;
                    101: #if (PCI_IRQ_WORDS == 2)
                    102:     pic_level = ((pci_irq_levels[irq_num][0] | 
                    103:                   pci_irq_levels[irq_num][1]) != 0);
                    104: #else
                    105:     {
                    106:         int i;
                    107:         pic_level = 0;
                    108:         for(i = 0; i < PCI_IRQ_WORDS; i++) {
                    109:             if (pci_irq_levels[irq_num][i]) {
                    110:                 pic_level = 1;
                    111:                 break;
                    112:             }
                    113:         }
                    114:     }
                    115: #endif
                    116:     return pic_level;
                    117: }
                    118: 
                    119: static void piix3_set_irq(PCIDevice *pci_dev, void *pic, int irq_num, int level)
                    120: {
                    121:     int irq_index, shift, pic_irq, pic_level;
                    122:     uint32_t *p;
                    123: 
                    124:     irq_num = pci_slot_get_pirq(pci_dev, irq_num);
                    125:     irq_index = pci_dev->irq_index;
                    126:     p = &pci_irq_levels[irq_num][irq_index >> 5];
                    127:     shift = (irq_index & 0x1f);
                    128:     *p = (*p & ~(1 << shift)) | (level << shift);
                    129: 
                    130:     /* now we change the pic irq level according to the piix irq mappings */
                    131:     /* XXX: optimize */
                    132:     pic_irq = piix3_dev->config[0x60 + irq_num];
                    133:     if (pic_irq < 16) {
                    134:         /* the pic level is the logical OR of all the PCI irqs mapped
                    135:            to it */
                    136:         pic_level = 0;
                    137:         if (pic_irq == piix3_dev->config[0x60])
                    138:             pic_level |= get_pci_irq_level(0);
                    139:         if (pic_irq == piix3_dev->config[0x61])
                    140:             pic_level |= get_pci_irq_level(1);
                    141:         if (pic_irq == piix3_dev->config[0x62])
                    142:             pic_level |= get_pci_irq_level(2);
                    143:         if (pic_irq == piix3_dev->config[0x63])
                    144:             pic_level |= get_pci_irq_level(3);
                    145:         pic_set_irq(pic_irq, pic_level);
                    146:     }
                    147: }
                    148: 
                    149: static void piix3_reset(PCIDevice *d)
                    150: {
                    151:     uint8_t *pci_conf = d->config;
                    152: 
                    153:     pci_conf[0x04] = 0x07; // master, memory and I/O
                    154:     pci_conf[0x05] = 0x00;
                    155:     pci_conf[0x06] = 0x00;
                    156:     pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
                    157:     pci_conf[0x4c] = 0x4d;
                    158:     pci_conf[0x4e] = 0x03;
                    159:     pci_conf[0x4f] = 0x00;
                    160:     pci_conf[0x60] = 0x80;
                    161:     pci_conf[0x69] = 0x02;
                    162:     pci_conf[0x70] = 0x80;
                    163:     pci_conf[0x76] = 0x0c;
                    164:     pci_conf[0x77] = 0x0c;
                    165:     pci_conf[0x78] = 0x02;
                    166:     pci_conf[0x79] = 0x00;
                    167:     pci_conf[0x80] = 0x00;
                    168:     pci_conf[0x82] = 0x00;
                    169:     pci_conf[0xa0] = 0x08;
                    170:     pci_conf[0xa0] = 0x08;
                    171:     pci_conf[0xa2] = 0x00;
                    172:     pci_conf[0xa3] = 0x00;
                    173:     pci_conf[0xa4] = 0x00;
                    174:     pci_conf[0xa5] = 0x00;
                    175:     pci_conf[0xa6] = 0x00;
                    176:     pci_conf[0xa7] = 0x00;
                    177:     pci_conf[0xa8] = 0x0f;
                    178:     pci_conf[0xaa] = 0x00;
                    179:     pci_conf[0xab] = 0x00;
                    180:     pci_conf[0xac] = 0x00;
                    181:     pci_conf[0xae] = 0x00;
                    182: }
                    183: 
                    184: int piix3_init(PCIBus *bus)
                    185: {
                    186:     PCIDevice *d;
                    187:     uint8_t *pci_conf;
                    188: 
                    189:     d = pci_register_device(bus, "PIIX3", sizeof(PCIDevice),
                    190:                                     -1, NULL, NULL);
                    191:     register_savevm("PIIX3", 0, 1, generic_pci_save, generic_pci_load, d);
                    192: 
                    193:     piix3_dev = d;
                    194:     pci_conf = d->config;
                    195: 
                    196:     pci_conf[0x00] = 0x86; // Intel
                    197:     pci_conf[0x01] = 0x80;
                    198:     pci_conf[0x02] = 0x00; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
                    199:     pci_conf[0x03] = 0x70;
                    200:     pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
                    201:     pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
                    202:     pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
                    203: 
                    204:     piix3_reset(d);
                    205:     return d->devfn;
                    206: }
                    207: 
                    208: /***********************************************************/
                    209: /* XXX: the following should be moved to the PC BIOS */
                    210: 
                    211: static __attribute__((unused)) uint32_t isa_inb(uint32_t addr)
                    212: {
                    213:     return cpu_inb(NULL, addr);
                    214: }
                    215: 
                    216: static void isa_outb(uint32_t val, uint32_t addr)
                    217: {
                    218:     cpu_outb(NULL, addr, val);
                    219: }
                    220: 
                    221: static __attribute__((unused)) uint32_t isa_inw(uint32_t addr)
                    222: {
                    223:     return cpu_inw(NULL, addr);
                    224: }
                    225: 
                    226: static __attribute__((unused)) void isa_outw(uint32_t val, uint32_t addr)
                    227: {
                    228:     cpu_outw(NULL, addr, val);
                    229: }
                    230: 
                    231: static __attribute__((unused)) uint32_t isa_inl(uint32_t addr)
                    232: {
                    233:     return cpu_inl(NULL, addr);
                    234: }
                    235: 
                    236: static __attribute__((unused)) void isa_outl(uint32_t val, uint32_t addr)
                    237: {
                    238:     cpu_outl(NULL, addr, val);
                    239: }
                    240: 
                    241: static uint32_t pci_bios_io_addr;
                    242: static uint32_t pci_bios_mem_addr;
                    243: /* host irqs corresponding to PCI irqs A-D */
                    244: static uint8_t pci_irqs[4] = { 11, 9, 11, 9 };
                    245: 
                    246: static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)
                    247: {
                    248:     PCIBus *s = d->bus;
                    249:     addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
                    250:     pci_data_write(s, addr, val, 4);
                    251: }
                    252: 
                    253: static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val)
                    254: {
                    255:     PCIBus *s = d->bus;
                    256:     addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
                    257:     pci_data_write(s, addr, val, 2);
                    258: }
                    259: 
                    260: static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val)
                    261: {
                    262:     PCIBus *s = d->bus;
                    263:     addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
                    264:     pci_data_write(s, addr, val, 1);
                    265: }
                    266: 
                    267: static __attribute__((unused)) uint32_t pci_config_readl(PCIDevice *d, uint32_t addr)
                    268: {
                    269:     PCIBus *s = d->bus;
                    270:     addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
                    271:     return pci_data_read(s, addr, 4);
                    272: }
                    273: 
                    274: static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr)
                    275: {
                    276:     PCIBus *s = d->bus;
                    277:     addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
                    278:     return pci_data_read(s, addr, 2);
                    279: }
                    280: 
                    281: static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr)
                    282: {
                    283:     PCIBus *s = d->bus;
                    284:     addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
                    285:     return pci_data_read(s, addr, 1);
                    286: }
                    287: 
                    288: static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr)
                    289: {
                    290:     PCIIORegion *r;
                    291:     uint16_t cmd;
                    292:     uint32_t ofs;
                    293: 
                    294:     if ( region_num == PCI_ROM_SLOT ) {
                    295:         ofs = 0x30;
                    296:     }else{
                    297:         ofs = 0x10 + region_num * 4;
                    298:     }
                    299: 
                    300:     pci_config_writel(d, ofs, addr);
                    301:     r = &d->io_regions[region_num];
                    302: 
                    303:     /* enable memory mappings */
                    304:     cmd = pci_config_readw(d, PCI_COMMAND);
                    305:     if ( region_num == PCI_ROM_SLOT )
                    306:         cmd |= 2;
                    307:     else if (r->type & PCI_ADDRESS_SPACE_IO)
                    308:         cmd |= 1;
                    309:     else
                    310:         cmd |= 2;
                    311:     pci_config_writew(d, PCI_COMMAND, cmd);
                    312: }
                    313: 
                    314: static void pci_bios_init_device(PCIDevice *d)
                    315: {
                    316:     int class;
                    317:     PCIIORegion *r;
                    318:     uint32_t *paddr;
                    319:     int i, pin, pic_irq, vendor_id, device_id;
                    320: 
                    321:     class = pci_config_readw(d, PCI_CLASS_DEVICE);
                    322:     vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
                    323:     device_id = pci_config_readw(d, PCI_DEVICE_ID);
                    324:     switch(class) {
                    325:     case 0x0101:
                    326:         if (vendor_id == 0x8086 && device_id == 0x7010) {
                    327:             /* PIIX3 IDE */
                    328:             pci_config_writew(d, 0x40, 0x8000); // enable IDE0
                    329:             pci_config_writew(d, 0x42, 0x8000); // enable IDE1
                    330:             goto default_map;
                    331:         } else {
                    332:             /* IDE: we map it as in ISA mode */
                    333:             pci_set_io_region_addr(d, 0, 0x1f0);
                    334:             pci_set_io_region_addr(d, 1, 0x3f4);
                    335:             pci_set_io_region_addr(d, 2, 0x170);
                    336:             pci_set_io_region_addr(d, 3, 0x374);
                    337:         }
                    338:         break;
                    339:     case 0x0300:
                    340:         if (vendor_id != 0x1234)
                    341:             goto default_map;
                    342:         /* VGA: map frame buffer to default Bochs VBE address */
                    343:         pci_set_io_region_addr(d, 0, 0xE0000000);
                    344:         break;
                    345:     case 0x0800:
                    346:         /* PIC */
                    347:         vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
                    348:         device_id = pci_config_readw(d, PCI_DEVICE_ID);
                    349:         if (vendor_id == 0x1014) {
                    350:             /* IBM */
                    351:             if (device_id == 0x0046 || device_id == 0xFFFF) {
                    352:                 /* MPIC & MPIC2 */
                    353:                 pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000);
                    354:             }
                    355:         }
                    356:         break;
                    357:     case 0xff00:
                    358:         if (vendor_id == 0x0106b &&
                    359:             (device_id == 0x0017 || device_id == 0x0022)) {
                    360:             /* macio bridge */
                    361:             pci_set_io_region_addr(d, 0, 0x80800000);
                    362:         }
                    363:         break;
                    364:     default:
                    365:     default_map:
                    366:         /* default memory mappings */
                    367:         for(i = 0; i < PCI_NUM_REGIONS; i++) {
                    368:             r = &d->io_regions[i];
                    369:             if (r->size) {
                    370:                 if (r->type & PCI_ADDRESS_SPACE_IO)
                    371:                     paddr = &pci_bios_io_addr;
                    372:                 else
                    373:                     paddr = &pci_bios_mem_addr;
                    374:                 *paddr = (*paddr + r->size - 1) & ~(r->size - 1);
                    375:                 pci_set_io_region_addr(d, i, *paddr);
                    376:                 *paddr += r->size;
                    377:             }
                    378:         }
                    379:         break;
                    380:     }
                    381: 
                    382:     /* map the interrupt */
                    383:     pin = pci_config_readb(d, PCI_INTERRUPT_PIN);
                    384:     if (pin != 0) {
                    385:         pin = pci_slot_get_pirq(d, pin - 1);
                    386:         pic_irq = pci_irqs[pin];
                    387:         pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);
                    388:     }
                    389: }
                    390: 
                    391: /*
                    392:  * This function initializes the PCI devices as a normal PCI BIOS
                    393:  * would do. It is provided just in case the BIOS has no support for
                    394:  * PCI.
                    395:  */
                    396: void pci_bios_init(void)
                    397: {
                    398:     int i, irq;
                    399:     uint8_t elcr[2];
                    400: 
                    401:     pci_bios_io_addr = 0xc000;
                    402:     pci_bios_mem_addr = 0xf0000000;
                    403: 
                    404:     /* activate IRQ mappings */
                    405:     elcr[0] = 0x00;
                    406:     elcr[1] = 0x00;
                    407:     for(i = 0; i < 4; i++) {
                    408:         irq = pci_irqs[i];
                    409:         /* set to trigger level */
                    410:         elcr[irq >> 3] |= (1 << (irq & 7));
                    411:         /* activate irq remapping in PIIX */
                    412:         pci_config_writeb(piix3_dev, 0x60 + i, irq);
                    413:     }
                    414:     isa_outb(elcr[0], 0x4d0);
                    415:     isa_outb(elcr[1], 0x4d1);
                    416: 
                    417:     pci_for_each_device(pci_bios_init_device);
                    418: }
                    419: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.