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