|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.