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 struct udevice *dev; 109 /* Use short to get rid of gabage in upper half of 32-bit register */ 110 short devindex; 111 unsigned char bus; 112 pci_dev_t bdf; 113 u32 dword; 114 u16 word; 115 u8 byte, reg; 116 int ret; 117 118 switch (func) { 119 case 0xb101: /* PCIBIOS Check */ 120 M.x86.R_EDX = 0x20494350; /* ' ICP' */ 121 M.x86.R_EAX &= 0xffff0000; /* Clear AH / AL */ 122 M.x86.R_EAX |= PCI_CONFIG_SPACE_TYPE1 | 123 PCI_SPECIAL_CYCLE_TYPE1; 124 /* 125 * last bus in the system. Hard code to 255 for now. 126 * dev_enumerate() does not seem to tell us (publically) 127 */ 128 M.x86.R_ECX = 0xff; 129 M.x86.R_EDI = 0x00000000; /* protected mode entry */ 130 retval = 1; 131 break; 132 case 0xb102: /* Find Device */ 133 devid = M.x86.R_ECX; 134 vendorid = M.x86.R_EDX; 135 devindex = M.x86.R_ESI; 136 bdf = -1; 137 ret = dm_pci_find_device(vendorid, devid, devindex, &dev); 138 if (!ret) { 139 unsigned short busdevfn; 140 141 bdf = dm_pci_get_bdf(dev); 142 M.x86.R_EAX &= 0xffff00ff; /* Clear AH */ 143 M.x86.R_EAX |= PCIBIOS_SUCCESSFUL; 144 /* 145 * busnum is an unsigned char; 146 * devfn is an int, so we mask it off. 147 */ 148 busdevfn = (PCI_BUS(bdf) << 8) | PCI_DEV(bdf) << 3 | 149 PCI_FUNC(bdf); 150 debug("0x%x: return 0x%x\n", func, busdevfn); 151 M.x86.R_EBX = busdevfn; 152 retval = 1; 153 } else { 154 M.x86.R_EAX &= 0xffff00ff; /* Clear AH */ 155 M.x86.R_EAX |= PCIBIOS_NODEV; 156 retval = 0; 157 } 158 break; 159 case 0xb10a: /* Read Config Dword */ 160 case 0xb109: /* Read Config Word */ 161 case 0xb108: /* Read Config Byte */ 162 case 0xb10d: /* Write Config Dword */ 163 case 0xb10c: /* Write Config Word */ 164 case 0xb10b: /* Write Config Byte */ 165 devfn = M.x86.R_EBX & 0xff; 166 bus = M.x86.R_EBX >> 8; 167 reg = M.x86.R_EDI; 168 bdf = PCI_BDF(bus, devfn >> 3, devfn & 7); 169 170 ret = dm_pci_bus_find_bdf(bdf, &dev); 171 if (ret) { 172 debug("%s: Device %x not found\n", __func__, bdf); 173 break; 174 } 175 176 switch (func) { 177 case 0xb108: /* Read Config Byte */ 178 dm_pci_read_config8(dev, reg, &byte); 179 M.x86.R_ECX = byte; 180 break; 181 case 0xb109: /* Read Config Word */ 182 dm_pci_read_config16(dev, reg, &word); 183 M.x86.R_ECX = word; 184 break; 185 case 0xb10a: /* Read Config Dword */ 186 dm_pci_read_config32(dev, reg, &dword); 187 M.x86.R_ECX = dword; 188 break; 189 case 0xb10b: /* Write Config Byte */ 190 byte = M.x86.R_ECX; 191 dm_pci_write_config8(dev, reg, byte); 192 break; 193 case 0xb10c: /* Write Config Word */ 194 word = M.x86.R_ECX; 195 dm_pci_write_config16(dev, reg, word); 196 break; 197 case 0xb10d: /* Write Config Dword */ 198 dword = M.x86.R_ECX; 199 dm_pci_write_config32(dev, reg, dword); 200 break; 201 } 202 #ifdef CONFIG_REALMODE_DEBUG 203 debug("0x%x: bus %d devfn 0x%x reg 0x%x val 0x%x\n", func, 204 bus, devfn, reg, M.x86.R_ECX); 205 #endif 206 M.x86.R_EAX &= 0xffff00ff; /* Clear AH */ 207 M.x86.R_EAX |= PCIBIOS_SUCCESSFUL; 208 retval = 1; 209 break; 210 default: 211 printf("UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func); 212 M.x86.R_EAX &= 0xffff00ff; /* Clear AH */ 213 M.x86.R_EAX |= PCIBIOS_UNSUPPORTED; 214 retval = 0; 215 break; 216 } 217 218 return retval; 219 } 220