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

1.1     ! root        1: // PCI BIOS (int 1a/b1) calls
        !             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 "types.h" // u32
        !             9: #include "util.h" // handle_1ab1
        !            10: #include "pci.h" // pci_config_readl
        !            11: #include "bregs.h" // struct bregs
        !            12: #include "biosvar.h" // GET_EBDA
        !            13: #include "pci_regs.h" // PCI_VENDOR_ID
        !            14: 
        !            15: #define RET_FUNC_NOT_SUPPORTED 0x81
        !            16: #define RET_BAD_VENDOR_ID      0x83
        !            17: #define RET_DEVICE_NOT_FOUND   0x86
        !            18: #define RET_BUFFER_TOO_SMALL   0x89
        !            19: 
        !            20: // installation check
        !            21: static void
        !            22: handle_1ab101(struct bregs *regs)
        !            23: {
        !            24:     // Find max bus.
        !            25:     int bdf, max;
        !            26:     foreachpci(bdf, max) {
        !            27:     }
        !            28: 
        !            29:     regs->al = 0x01; // Flags - "Config Mechanism #1" supported.
        !            30:     regs->bx = 0x0210; // PCI version 2.10
        !            31:     regs->cl = pci_bdf_to_bus(max - 1);
        !            32:     regs->edx = 0x20494350; // "PCI "
        !            33:     // XXX - bochs bios code sets edi to point to 32bit code - but no
        !            34:     // reference to this in spec.
        !            35:     set_code_success(regs);
        !            36: }
        !            37: 
        !            38: // find pci device
        !            39: static void
        !            40: handle_1ab102(struct bregs *regs)
        !            41: {
        !            42:     u32 id = (regs->cx << 16) | regs->dx;
        !            43:     int count = regs->si;
        !            44:     int bdf, max;
        !            45:     foreachpci(bdf, max) {
        !            46:         u32 v = pci_config_readl(bdf, PCI_VENDOR_ID);
        !            47:         if (v != id)
        !            48:             continue;
        !            49:         if (count--)
        !            50:             continue;
        !            51:         regs->bx = bdf;
        !            52:         set_code_success(regs);
        !            53:         return;
        !            54:     }
        !            55:     set_code_invalid(regs, RET_DEVICE_NOT_FOUND);
        !            56: }
        !            57: 
        !            58: // find class code
        !            59: static void
        !            60: handle_1ab103(struct bregs *regs)
        !            61: {
        !            62:     int count = regs->si;
        !            63:     u32 classprog = regs->ecx;
        !            64:     int bdf, max;
        !            65:     foreachpci(bdf, max) {
        !            66:         u32 v = pci_config_readl(bdf, PCI_CLASS_REVISION);
        !            67:         if ((v>>8) != classprog)
        !            68:             continue;
        !            69:         if (count--)
        !            70:             continue;
        !            71:         regs->bx = bdf;
        !            72:         set_code_success(regs);
        !            73:         return;
        !            74:     }
        !            75:     set_code_invalid(regs, RET_DEVICE_NOT_FOUND);
        !            76: }
        !            77: 
        !            78: // read configuration byte
        !            79: static void
        !            80: handle_1ab108(struct bregs *regs)
        !            81: {
        !            82:     regs->cl = pci_config_readb(regs->bx, regs->di);
        !            83:     set_code_success(regs);
        !            84: }
        !            85: 
        !            86: // read configuration word
        !            87: static void
        !            88: handle_1ab109(struct bregs *regs)
        !            89: {
        !            90:     regs->cx = pci_config_readw(regs->bx, regs->di);
        !            91:     set_code_success(regs);
        !            92: }
        !            93: 
        !            94: // read configuration dword
        !            95: static void
        !            96: handle_1ab10a(struct bregs *regs)
        !            97: {
        !            98:     regs->ecx = pci_config_readl(regs->bx, regs->di);
        !            99:     set_code_success(regs);
        !           100: }
        !           101: 
        !           102: // write configuration byte
        !           103: static void
        !           104: handle_1ab10b(struct bregs *regs)
        !           105: {
        !           106:     pci_config_writeb(regs->bx, regs->di, regs->cl);
        !           107:     set_code_success(regs);
        !           108: }
        !           109: 
        !           110: // write configuration word
        !           111: static void
        !           112: handle_1ab10c(struct bregs *regs)
        !           113: {
        !           114:     pci_config_writew(regs->bx, regs->di, regs->cx);
        !           115:     set_code_success(regs);
        !           116: }
        !           117: 
        !           118: // write configuration dword
        !           119: static void
        !           120: handle_1ab10d(struct bregs *regs)
        !           121: {
        !           122:     pci_config_writel(regs->bx, regs->di, regs->ecx);
        !           123:     set_code_success(regs);
        !           124: }
        !           125: 
        !           126: // get irq routing options
        !           127: static void
        !           128: handle_1ab10e(struct bregs *regs)
        !           129: {
        !           130:     struct pir_header *pirtable_g = (void*)(GET_GLOBAL(PirOffset) + 0);
        !           131:     if (! pirtable_g) {
        !           132:         set_code_invalid(regs, RET_FUNC_NOT_SUPPORTED);
        !           133:         return;
        !           134:     }
        !           135: 
        !           136:     struct param_s {
        !           137:         u16 size;
        !           138:         u16 buf_off;
        !           139:         u16 buf_seg;
        !           140:     } *param_far = (void*)(regs->di+0);
        !           141: 
        !           142:     // Validate and update size.
        !           143:     u16 bufsize = GET_FARVAR(regs->es, param_far->size);
        !           144:     u16 pirsize = GET_GLOBAL(pirtable_g->size) - sizeof(struct pir_header);
        !           145:     SET_FARVAR(regs->es, param_far->size, pirsize);
        !           146:     if (bufsize < pirsize) {
        !           147:         set_code_invalid(regs, RET_BUFFER_TOO_SMALL);
        !           148:         return;
        !           149:     }
        !           150: 
        !           151:     // Get dest buffer.
        !           152:     void *buf_far = (void*)(GET_FARVAR(regs->es, param_far->buf_off)+0);
        !           153:     u16 buf_seg = GET_FARVAR(regs->es, param_far->buf_seg);
        !           154: 
        !           155:     // Memcpy pir table slots to dest buffer.
        !           156:     memcpy_far(buf_seg, buf_far
        !           157:                , get_global_seg(), pirtable_g->slots
        !           158:                , pirsize);
        !           159: 
        !           160:     // XXX - bochs bios sets bx to (1 << 9) | (1 << 11)
        !           161:     regs->bx = GET_GLOBAL(pirtable_g->exclusive_irqs);
        !           162:     set_code_success(regs);
        !           163: }
        !           164: 
        !           165: static void
        !           166: handle_1ab1XX(struct bregs *regs)
        !           167: {
        !           168:     set_code_unimplemented(regs, RET_FUNC_NOT_SUPPORTED);
        !           169: }
        !           170: 
        !           171: void
        !           172: handle_1ab1(struct bregs *regs)
        !           173: {
        !           174:     //debug_stub(regs);
        !           175: 
        !           176:     if (! CONFIG_PCIBIOS) {
        !           177:         set_invalid(regs);
        !           178:         return;
        !           179:     }
        !           180: 
        !           181:     switch (regs->al) {
        !           182:     case 0x01: handle_1ab101(regs); break;
        !           183:     case 0x02: handle_1ab102(regs); break;
        !           184:     case 0x03: handle_1ab103(regs); break;
        !           185:     case 0x08: handle_1ab108(regs); break;
        !           186:     case 0x09: handle_1ab109(regs); break;
        !           187:     case 0x0a: handle_1ab10a(regs); break;
        !           188:     case 0x0b: handle_1ab10b(regs); break;
        !           189:     case 0x0c: handle_1ab10c(regs); break;
        !           190:     case 0x0d: handle_1ab10d(regs); break;
        !           191:     case 0x0e: handle_1ab10e(regs); break;
        !           192:     default:   handle_1ab1XX(regs); break;
        !           193:     }
        !           194: }

unix.superglobalmegacorp.com

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