1 /* 2 * From Coreboot 3 * 4 * Copyright (C) 2001 Ronald G. Minnich 5 * Copyright (C) 2005 Nick.Barker9@btinternet.com 6 * Copyright (C) 2007-2009 coresystems GmbH 7 * 8 * SPDX-License-Identifier: GPL-2.0 9 */ 10 11 #include <common.h> 12 #include <asm/pci.h> 13 #include "bios_emul.h" 14 15 /* errors go in AH. Just set these up so that word assigns will work */ 16 enum { 17 PCIBIOS_SUCCESSFUL = 0x0000, 18 PCIBIOS_UNSUPPORTED = 0x8100, 19 PCIBIOS_BADVENDOR = 0x8300, 20 PCIBIOS_NODEV = 0x8600, 21 PCIBIOS_BADREG = 0x8700 22 }; 23 24 int int10_handler(void) 25 { 26 static u8 cursor_row, cursor_col; 27 int res = 0; 28 29 switch ((M.x86.R_EAX & 0xff00) >> 8) { 30 case 0x01: /* Set cursor shape */ 31 res = 1; 32 break; 33 case 0x02: /* Set cursor position */ 34 if (cursor_row != ((M.x86.R_EDX >> 8) & 0xff) || 35 cursor_col >= (M.x86.R_EDX & 0xff)) { 36 debug("\n"); 37 } 38 cursor_row = (M.x86.R_EDX >> 8) & 0xff; 39 cursor_col = M.x86.R_EDX & 0xff; 40 res = 1; 41 break; 42 case 0x03: /* Get cursor position */ 43 M.x86.R_EAX &= 0x00ff; 44 M.x86.R_ECX = 0x0607; 45 M.x86.R_EDX = (cursor_row << 8) | cursor_col; 46 res = 1; 47 break; 48 case 0x06: /* Scroll up */ 49 debug("\n"); 50 res = 1; 51 break; 52 case 0x08: /* Get Character and Mode at Cursor Position */ 53 M.x86.R_EAX = 0x0f00 | 'A'; /* White on black 'A' */ 54 res = 1; 55 break; 56 case 0x09: /* Write Character and attribute */ 57 case 0x0e: /* Write Character */ 58 debug("%c", M.x86.R_EAX & 0xff); 59 res = 1; 60 break; 61 case 0x0f: /* Get video mode */ 62 M.x86.R_EAX = 0x5002; /*80 x 25 */ 63 M.x86.R_EBX &= 0x00ff; 64 res = 1; 65 break; 66 default: 67 printf("Unknown INT10 function %04x\n", M.x86.R_EAX & 0xffff); 68 break; 69 } 70 return res; 71 } 72 73 int int12_handler(void) 74 { 75 M.x86.R_EAX = 64 * 1024; 76 return 1; 77 } 78 79 int int16_handler(void) 80 { 81 int res = 0; 82 83 switch ((M.x86.R_EAX & 0xff00) >> 8) { 84 case 0x00: /* Check for Keystroke */ 85 M.x86.R_EAX = 0x6120; /* Space Bar, Space */ 86 res = 1; 87 break; 88 case 0x01: /* Check for Keystroke */ 89 M.x86.R_EFLG |= 1 << 6; /* Zero Flag set (no key available) */ 90 res = 1; 91 break; 92 default: 93 printf("Unknown INT16 function %04x\n", M.x86.R_EAX & 0xffff); 94 95 break; 96 } 97 return res; 98 } 99 100 #define PCI_CONFIG_SPACE_TYPE1 (1 << 0) 101 #define PCI_SPECIAL_CYCLE_TYPE1 (1 << 4) 102 103 int int1a_handler(void) 104 { 105 unsigned short func = (unsigned short)M.x86.R_EAX; 106 int retval = 1; 107 unsigned short devid, vendorid, devfn; 108 /* Use short to get rid of gabage in upper half of 32-bit register */ 109 short devindex; 110 unsigned char bus; 111 pci_dev_t dev; 112 u32 dword; 113 u16 word; 114 u8 byte, reg; 115 116 switch (func) { 117 case 0xb101: /* PCIBIOS Check */ 118 M.x86.R_EDX = 0x20494350; /* ' ICP' */ 119 M.x86.R_EAX &= 0xffff0000; /* Clear AH / AL */ 120 M.x86.R_EAX |= PCI_CONFIG_SPACE_TYPE1 | 121 PCI_SPECIAL_CYCLE_TYPE1; 122 /* 123 * last bus in the system. Hard code to 255 for now. 124 * dev_enumerate() does not seem to tell us (publically) 125 */ 126 M.x86.R_ECX = 0xff; 127 M.x86.R_EDI = 0x00000000; /* protected mode entry */ 128 retval = 1; 129 break; 130 case 0xb102: /* Find Device */ 131 devid = M.x86.R_ECX; 132 vendorid = M.x86.R_EDX; 133 devindex = M.x86.R_ESI; 134 dev = pci_find_device(vendorid, devid, devindex); 135 if (dev != -1) { 136 unsigned short busdevfn; 137 M.x86.R_EAX &= 0xffff00ff; /* Clear AH */ 138 M.x86.R_EAX |= PCIBIOS_SUCCESSFUL; 139 /* 140 * busnum is an unsigned char; 141 * devfn is an int, so we mask it off. 142 */ 143 busdevfn = (PCI_BUS(dev) << 8) | PCI_DEV(dev) << 3 | 144 PCI_FUNC(dev); 145 debug("0x%x: return 0x%x\n", func, busdevfn); 146 M.x86.R_EBX = busdevfn; 147 retval = 1; 148 } else { 149 M.x86.R_EAX &= 0xffff00ff; /* Clear AH */ 150 M.x86.R_EAX |= PCIBIOS_NODEV; 151 retval = 0; 152 } 153 break; 154 case 0xb10a: /* Read Config Dword */ 155 case 0xb109: /* Read Config Word */ 156 case 0xb108: /* Read Config Byte */ 157 case 0xb10d: /* Write Config Dword */ 158 case 0xb10c: /* Write Config Word */ 159 case 0xb10b: /* Write Config Byte */ 160 devfn = M.x86.R_EBX & 0xff; 161 bus = M.x86.R_EBX >> 8; 162 reg = M.x86.R_EDI; 163 dev = PCI_BDF(bus, devfn >> 3, devfn & 7); 164 if (!dev) { 165 debug("0x%x: BAD DEVICE bus %d devfn 0x%x\n", func, 166 bus, devfn); 167 /* Or are we supposed to return PCIBIOS_NODEV? */ 168 M.x86.R_EAX &= 0xffff00ff; /* Clear AH */ 169 M.x86.R_EAX |= PCIBIOS_BADREG; 170 retval = 0; 171 return retval; 172 } 173 switch (func) { 174 case 0xb108: /* Read Config Byte */ 175 byte = pci_read_config8(dev, reg); 176 M.x86.R_ECX = byte; 177 break; 178 case 0xb109: /* Read Config Word */ 179 word = pci_read_config16(dev, reg); 180 M.x86.R_ECX = word; 181 break; 182 case 0xb10a: /* Read Config Dword */ 183 dword = pci_read_config32(dev, reg); 184 M.x86.R_ECX = dword; 185 break; 186 case 0xb10b: /* Write Config Byte */ 187 byte = M.x86.R_ECX; 188 pci_write_config8(dev, reg, byte); 189 break; 190 case 0xb10c: /* Write Config Word */ 191 word = M.x86.R_ECX; 192 pci_write_config16(dev, reg, word); 193 break; 194 case 0xb10d: /* Write Config Dword */ 195 dword = M.x86.R_ECX; 196 pci_write_config32(dev, reg, dword); 197 break; 198 } 199 200 #ifdef CONFIG_REALMODE_DEBUG 201 debug("0x%x: bus %d devfn 0x%x reg 0x%x val 0x%x\n", func, 202 bus, devfn, reg, M.x86.R_ECX); 203 #endif 204 M.x86.R_EAX &= 0xffff00ff; /* Clear AH */ 205 M.x86.R_EAX |= PCIBIOS_SUCCESSFUL; 206 retval = 1; 207 break; 208 default: 209 printf("UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func); 210 M.x86.R_EAX &= 0xffff00ff; /* Clear AH */ 211 M.x86.R_EAX |= PCIBIOS_UNSUPPORTED; 212 retval = 0; 213 break; 214 } 215 216 return retval; 217 } 218