coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
x86_interrupts.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <arch/registers.h>
4 #include <console/console.h>
5 #include <device/pci.h>
6 #include <device/pci_ops.h>
7 
8 /* we use x86emu's register file representation */
9 #include <x86emu/regs.h>
10 
11 #include "x86.h"
12 
13 // errors go in AH. Just set these up so that word assigns
14 // will work. KISS.
15 enum {
19  PCIBIOS_NODEV = 0x8600,
20  PCIBIOS_BADREG = 0x8700
21 };
22 
23 int int10_handler(void)
24 {
25  int res=0;
26  static u8 cursor_row=0, cursor_col=0;
27  switch((X86_EAX & 0xff00)>>8) {
28  case 0x01: // Set cursor shape
29  res = 1;
30  break;
31  case 0x02: // Set cursor position
32  if (cursor_row != ((X86_EDX >> 8) & 0xff) ||
33  cursor_col >= (X86_EDX & 0xff)) {
34  printk(BIOS_INFO, "\n");
35  }
36  cursor_row = (X86_EDX >> 8) & 0xff;
37  cursor_col = X86_EDX & 0xff;
38  res = 1;
39  break;
40  case 0x03: // Get cursor position
41  X86_EAX &= 0x00ff;
42  X86_ECX = 0x0607;
43  X86_EDX = (cursor_row << 8) | cursor_col;
44  res = 1;
45  break;
46  case 0x06: // Scroll up
47  printk(BIOS_INFO, "\n");
48  res = 1;
49  break;
50  case 0x08: // Get Character and Mode at Cursor Position
51  X86_EAX = 0x0f00 | 'A'; // White on black 'A'
52  res = 1;
53  break;
54  case 0x09: // Write Character and attribute
55  case 0x0e: // Write Character
56  printk(BIOS_INFO, "%c", X86_EAX & 0xff);
57  res = 1;
58  break;
59  case 0x0f: // Get video mode
60  X86_EAX = 0x5002; //80x25
61  X86_EBX &= 0x00ff;
62  res = 1;
63  break;
64  default:
65  printk(BIOS_WARNING, "Unknown INT10 function %04x!\n",
66  X86_EAX & 0xffff);
67  break;
68  }
69  return res;
70 }
71 
72 int int12_handler(void)
73 {
74  X86_EAX = 64 * 1024;
75  return 1;
76 }
77 
78 int int16_handler(void)
79 {
80  int res=0;
81  switch((X86_EAX & 0xff00)>>8) {
82  case 0x00: // Check for Keystroke
83  X86_EAX = 0x6120; // Space Bar, Space
84  res = 1;
85  break;
86  case 0x01: // Check for Keystroke
87  X86_EFLAGS |= 1<<6; // Zero Flag set (no key available)
88  res = 1;
89  break;
90  default:
91  printk(BIOS_WARNING, "Unknown INT16 function %04x!\n",
92  X86_EAX & 0xffff);
93  break;
94  }
95  return res;
96 }
97 
98 #define PCI_CONFIG_SPACE_TYPE1 (1 << 0)
99 #define PCI_SPECIAL_CYCLE_TYPE1 (1 << 4)
100 
101 int int1a_handler(void)
102 {
103  unsigned short func = (unsigned short)X86_EAX;
104  int retval = 1;
105  unsigned short devid, vendorid, devfn;
106  /* Use short to get rid of garbage in upper half of 32-bit register */
107  short devindex;
108  unsigned char bus;
109  struct device *dev;
110  u32 dword;
111  u16 word;
112  u8 byte, reg;
113 
114  switch (func) {
115  case 0xb101: /* PCIBIOS Check */
116  X86_EDX = 0x20494350; /* ' ICP' */
117  X86_EAX &= 0xffff0000; /* Clear AH / AL */
119  // last bus in the system. Hard code to 255 for now.
120  // dev_enumerate() does not seem to tell us (publicly)
121  X86_ECX = 0xff;
122  X86_EDI = 0x00000000; /* protected mode entry */
123  retval = 1;
124  break;
125  case 0xb102: /* Find Device */
126  devid = X86_ECX;
127  vendorid = X86_EDX;
128  devindex = X86_ESI;
129  dev = 0;
130  while ((dev = dev_find_device(vendorid, devid, dev))) {
131  if (devindex <= 0)
132  break;
133  devindex--;
134  }
135  if (dev) {
136  unsigned short busdevfn;
137  X86_EAX &= 0xffff00ff; /* Clear AH */
139  // busnum is an unsigned char;
140  // devfn is an int, so we mask it off.
141  busdevfn = (dev->bus->secondary << 8)
142  | (dev->path.pci.devfn & 0xff);
143  printk(BIOS_DEBUG, "0x%x: return 0x%x\n", func, busdevfn);
144  X86_EBX = busdevfn;
145  retval = 1;
146  } else {
147  X86_EAX &= 0xffff00ff; /* Clear AH */
149  retval = 0;
150  }
151  break;
152  case 0xb10a: /* Read Config Dword */
153  case 0xb109: /* Read Config Word */
154  case 0xb108: /* Read Config Byte */
155  case 0xb10d: /* Write Config Dword */
156  case 0xb10c: /* Write Config Word */
157  case 0xb10b: /* Write Config Byte */
158  devfn = X86_EBX & 0xff;
159  bus = X86_EBX >> 8;
160  reg = X86_EDI;
161  dev = pcidev_path_on_bus(bus, devfn);
162  if (!dev) {
163  printk(BIOS_DEBUG, "0x%x: BAD DEVICE bus %d devfn 0x%x\n", func, bus, devfn);
164  // Or are we supposed to return PCIBIOS_NODEV?
165  X86_EAX &= 0xffff00ff; /* Clear AH */
167  retval = 0;
168  return retval;
169  }
170  switch (func) {
171  case 0xb108: /* Read Config Byte */
172  byte = pci_read_config8(dev, reg);
173  X86_ECX = byte;
174  break;
175  case 0xb109: /* Read Config Word */
176  word = pci_read_config16(dev, reg);
177  X86_ECX = word;
178  break;
179  case 0xb10a: /* Read Config Dword */
180  dword = pci_read_config32(dev, reg);
181  X86_ECX = dword;
182  break;
183  case 0xb10b: /* Write Config Byte */
184  byte = X86_ECX;
185  pci_write_config8(dev, reg, byte);
186  break;
187  case 0xb10c: /* Write Config Word */
188  word = X86_ECX;
189  pci_write_config16(dev, reg, word);
190  break;
191  case 0xb10d: /* Write Config Dword */
192  dword = X86_ECX;
193  pci_write_config32(dev, reg, dword);
194  break;
195  }
196 
197 #if CONFIG(REALMODE_DEBUG)
198  printk(BIOS_DEBUG, "0x%x: bus %d devfn 0x%x reg 0x%x val 0x%x\n",
199  func, bus, devfn, reg, X86_ECX);
200 #endif
201  X86_EAX &= 0xffff00ff; /* Clear AH */
203  retval = 1;
204  break;
205  default:
206  printk(BIOS_ERR, "UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func);
207  X86_EAX &= 0xffff00ff; /* Clear AH */
209  retval = 0;
210  break;
211  }
212 
213  return retval;
214 }
#define printk(level,...)
Definition: stdlib.h:16
DEVTREE_CONST struct device * pcidev_path_on_bus(unsigned int bus, pci_devfn_t devfn)
Definition: device_const.c:221
struct device * dev_find_device(u16 vendor, u16 device, struct device *from)
Find a device of a given vendor and type.
Definition: device_util.c:42
static __always_inline void pci_write_config32(const struct device *dev, u16 reg, u32 val)
Definition: pci_ops.h:76
static __always_inline u16 pci_read_config16(const struct device *dev, u16 reg)
Definition: pci_ops.h:52
static __always_inline u32 pci_read_config32(const struct device *dev, u16 reg)
Definition: pci_ops.h:58
static __always_inline u8 pci_read_config8(const struct device *dev, u16 reg)
Definition: pci_ops.h:46
static __always_inline void pci_write_config16(const struct device *dev, u16 reg, u16 val)
Definition: pci_ops.h:70
static __always_inline void pci_write_config8(const struct device *dev, u16 reg, u8 val)
Definition: pci_ops.h:64
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define BIOS_WARNING
BIOS_WARNING - Bad configuration.
Definition: loglevel.h:86
#define X86_ESI
Definition: regs.h:333
#define X86_EDI
Definition: regs.h:334
#define X86_ECX
Definition: regs.h:331
#define X86_EAX
Definition: regs.h:329
#define X86_EFLAGS
Definition: regs.h:338
#define X86_EBX
Definition: regs.h:330
#define X86_EDX
Definition: regs.h:332
static unsigned int word
Definition: uart.c:88
uint32_t u32
Definition: stdint.h:51
uint16_t u16
Definition: stdint.h:48
uint8_t u8
Definition: stdint.h:45
Definition: device.h:76
uint16_t secondary
Definition: device.h:84
struct pci_path pci
Definition: path.h:116
Definition: device.h:107
struct device_path path
Definition: device.h:115
DEVTREE_CONST struct bus * bus
Definition: device.h:108
unsigned int devfn
Definition: path.h:54
#define PCI_SPECIAL_CYCLE_TYPE1
int int1a_handler(void)
int int10_handler(void)
@ PCIBIOS_UNSUPPORTED
@ PCIBIOS_BADVENDOR
@ PCIBIOS_NODEV
@ PCIBIOS_SUCCESSFUL
@ PCIBIOS_BADREG
int int16_handler(void)
int int12_handler(void)
#define PCI_CONFIG_SPACE_TYPE1