Annotation of qemu/roms/seabios/src/pci.c, revision 1.1

1.1     ! root        1: // PCI config space access functions.
        !             2: //
        !             3: // Copyright (C) 2008  Kevin O'Connor <[email protected]>
        !             4: // Copyright (C) 2002  MandrakeSoft S.A.
        !             5: //
        !             6: // This file may be distributed under the terms of the GNU LGPLv3 license.
        !             7: 
        !             8: #include "pci.h" // pci_config_writel
        !             9: #include "ioport.h" // outl
        !            10: #include "util.h" // dprintf
        !            11: #include "config.h" // CONFIG_*
        !            12: #include "pci_regs.h" // PCI_VENDOR_ID
        !            13: #include "pci_ids.h" // PCI_CLASS_DISPLAY_VGA
        !            14: 
        !            15: void pci_config_writel(u16 bdf, u32 addr, u32 val)
        !            16: {
        !            17:     outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
        !            18:     outl(val, PORT_PCI_DATA);
        !            19: }
        !            20: 
        !            21: void pci_config_writew(u16 bdf, u32 addr, u16 val)
        !            22: {
        !            23:     outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
        !            24:     outw(val, PORT_PCI_DATA + (addr & 2));
        !            25: }
        !            26: 
        !            27: void pci_config_writeb(u16 bdf, u32 addr, u8 val)
        !            28: {
        !            29:     outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
        !            30:     outb(val, PORT_PCI_DATA + (addr & 3));
        !            31: }
        !            32: 
        !            33: u32 pci_config_readl(u16 bdf, u32 addr)
        !            34: {
        !            35:     outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
        !            36:     return inl(PORT_PCI_DATA);
        !            37: }
        !            38: 
        !            39: u16 pci_config_readw(u16 bdf, u32 addr)
        !            40: {
        !            41:     outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
        !            42:     return inw(PORT_PCI_DATA + (addr & 2));
        !            43: }
        !            44: 
        !            45: u8 pci_config_readb(u16 bdf, u32 addr)
        !            46: {
        !            47:     outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
        !            48:     return inb(PORT_PCI_DATA + (addr & 3));
        !            49: }
        !            50: 
        !            51: void
        !            52: pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on)
        !            53: {
        !            54:     u16 val = pci_config_readw(bdf, addr);
        !            55:     val = (val & ~off) | on;
        !            56:     pci_config_writew(bdf, addr, val);
        !            57: }
        !            58: 
        !            59: // Helper function for foreachpci() macro - return next device
        !            60: int
        !            61: pci_next(int bdf, int *pmax)
        !            62: {
        !            63:     if (pci_bdf_to_fn(bdf) == 1
        !            64:         && (pci_config_readb(bdf-1, PCI_HEADER_TYPE) & 0x80) == 0)
        !            65:         // Last found device wasn't a multi-function device - skip to
        !            66:         // the next device.
        !            67:         bdf += 7;
        !            68: 
        !            69:     int max = *pmax;
        !            70:     for (;;) {
        !            71:         if (bdf >= max) {
        !            72:             if (CONFIG_PCI_ROOT1 && bdf <= (CONFIG_PCI_ROOT1 << 8))
        !            73:                 bdf = CONFIG_PCI_ROOT1 << 8;
        !            74:             else if (CONFIG_PCI_ROOT2 && bdf <= (CONFIG_PCI_ROOT2 << 8))
        !            75:                 bdf = CONFIG_PCI_ROOT2 << 8;
        !            76:             else
        !            77:                return -1;
        !            78:             *pmax = max = bdf + 0x0100;
        !            79:         }
        !            80: 
        !            81:         u16 v = pci_config_readw(bdf, PCI_VENDOR_ID);
        !            82:         if (v != 0x0000 && v != 0xffff)
        !            83:             // Device is present.
        !            84:             break;
        !            85: 
        !            86:         if (pci_bdf_to_fn(bdf) == 0)
        !            87:             bdf += 8;
        !            88:         else
        !            89:             bdf += 1;
        !            90:     }
        !            91: 
        !            92:     // Check if found device is a bridge.
        !            93:     u32 v = pci_config_readb(bdf, PCI_HEADER_TYPE);
        !            94:     v &= 0x7f;
        !            95:     if (v == PCI_HEADER_TYPE_BRIDGE || v == PCI_HEADER_TYPE_CARDBUS) {
        !            96:         v = pci_config_readl(bdf, PCI_PRIMARY_BUS);
        !            97:         int newmax = (v & 0xff00) + 0x0100;
        !            98:         if (newmax > max)
        !            99:             *pmax = newmax;
        !           100:     }
        !           101: 
        !           102:     return bdf;
        !           103: }
        !           104: 
        !           105: // Find a vga device with legacy address decoding enabled.
        !           106: int
        !           107: pci_find_vga()
        !           108: {
        !           109:     int bdf = 0x0000, max = 0x0100;
        !           110:     for (;;) {
        !           111:         if (bdf >= max) {
        !           112:             if (CONFIG_PCI_ROOT1 && bdf <= (CONFIG_PCI_ROOT1 << 8))
        !           113:                 bdf = CONFIG_PCI_ROOT1 << 8;
        !           114:             else if (CONFIG_PCI_ROOT2 && bdf <= (CONFIG_PCI_ROOT2 << 8))
        !           115:                 bdf = CONFIG_PCI_ROOT2 << 8;
        !           116:             else
        !           117:                return -1;
        !           118:             max = bdf + 0x0100;
        !           119:         }
        !           120: 
        !           121:         u16 cls = pci_config_readw(bdf, PCI_CLASS_DEVICE);
        !           122:         if (cls == 0x0000 || cls == 0xffff) {
        !           123:             // Device not present.
        !           124:             if (pci_bdf_to_fn(bdf) == 0)
        !           125:                 bdf += 8;
        !           126:             else
        !           127:                 bdf += 1;
        !           128:             continue;
        !           129:         }
        !           130:         if (cls == PCI_CLASS_DISPLAY_VGA) {
        !           131:             u16 cmd = pci_config_readw(bdf, PCI_COMMAND);
        !           132:             if (cmd & PCI_COMMAND_IO && cmd & PCI_COMMAND_MEMORY)
        !           133:                 // Found active vga card
        !           134:                 return bdf;
        !           135:         }
        !           136: 
        !           137:         // Check if device is a bridge.
        !           138:         u8 hdr = pci_config_readb(bdf, PCI_HEADER_TYPE);
        !           139:         u8 ht = hdr & 0x7f;
        !           140:         if (ht == PCI_HEADER_TYPE_BRIDGE || ht == PCI_HEADER_TYPE_CARDBUS) {
        !           141:             u32 ctrl = pci_config_readb(bdf, PCI_BRIDGE_CONTROL);
        !           142:             if (ctrl & PCI_BRIDGE_CTL_VGA) {
        !           143:                 // Found a VGA enabled bridge.
        !           144:                 u32 pbus = pci_config_readl(bdf, PCI_PRIMARY_BUS);
        !           145:                 bdf = (pbus & 0xff00);
        !           146:                 max = bdf + 0x100;
        !           147:                 continue;
        !           148:             }
        !           149:         }
        !           150: 
        !           151:         if (pci_bdf_to_fn(bdf) == 0 && (hdr & 0x80) == 0)
        !           152:             // Last found device wasn't a multi-function device - skip to
        !           153:             // the next device.
        !           154:             bdf += 8;
        !           155:         else
        !           156:             bdf += 1;
        !           157:     }
        !           158: }
        !           159: 
        !           160: // Search for a device with the specified vendor and device ids.
        !           161: int
        !           162: pci_find_device(u16 vendid, u16 devid)
        !           163: {
        !           164:     u32 id = (devid << 16) | vendid;
        !           165:     int bdf, max;
        !           166:     foreachpci(bdf, max) {
        !           167:         u32 v = pci_config_readl(bdf, PCI_VENDOR_ID);
        !           168:         if (v == id)
        !           169:             return bdf;
        !           170:     }
        !           171:     return -1;
        !           172: }
        !           173: 
        !           174: // Search for a device with the specified class id.
        !           175: int
        !           176: pci_find_class(u16 classid)
        !           177: {
        !           178:     int bdf, max;
        !           179:     foreachpci(bdf, max) {
        !           180:         u16 v = pci_config_readw(bdf, PCI_CLASS_DEVICE);
        !           181:         if (v == classid)
        !           182:             return bdf;
        !           183:     }
        !           184:     return -1;
        !           185: }

unix.superglobalmegacorp.com

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