coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
interrupt.c
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright (c) 2004, 2008 IBM Corporation
3  * Copyright (c) 2008, 2009 Pattrick Hueper <phueper@hueper.net>
4  *
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are
9  * met:
10  *
11  * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer
16  * in the documentation and/or other materials provided with the
17  * distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * Contributors:
32  * IBM Corporation - initial implementation
33  *****************************************************************************/
34 
35 #include <types.h>
36 #include "compat/rtas.h"
37 
38 #include "biosemu.h"
39 #include "mem.h"
40 #include "device.h"
41 #include "debug.h"
42 #include "pmm.h"
43 #include "interrupt.h"
44 
45 #include <x86emu/x86emu.h>
46 #include "../x86emu/prim_ops.h"
47 
48 #include <device/pci.h>
49 #include <device/pci_ops.h>
50 
51 //setup to run the code at the address, that the Interrupt Vector points to...
52 static void
53 setupInt(int intNum)
54 {
55  DEBUG_PRINTF_INTR("%s(%x): executing interrupt handler @%08x\n",
56  __func__, intNum, my_rdl(intNum * 4));
57  // push current R_FLG... will be popped by IRET
58  push_word((u16) M.x86.R_FLG);
61  // push current CS:IP to the stack, will be popped by IRET
62  push_word(M.x86.R_CS);
63  push_word(M.x86.R_IP);
64  // set CS:IP to the interrupt handler address... so the next executed instruction will
65  // be the interrupt handler
66  M.x86.R_CS = my_rdw(intNum * 4 + 2);
67  M.x86.R_IP = my_rdw(intNum * 4);
68 }
69 
70 // handle int10 (VGA BIOS Interrupt)
71 static void
73 {
74  // the data for INT10 is stored in BDA (0000:0400h) offset 49h-66h
75  // function number in AH
76  //DEBUG_PRINTF_CS_IP("%s:\n", __func__);
77  //x86emu_dump_xregs();
78  //if ((M.x86.R_IP == 0x32c2) && (M.x86.R_SI == 0x1ce2)){
79  //X86EMU_trace_on();
80  //M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
81  //}
82  switch (M.x86.R_AH) {
83  case 0x00:
84  // set video mode
85  // BDA offset 49h is current video mode
86  my_wrb(0x449, M.x86.R_AL);
87  if (M.x86.R_AL > 7)
88  M.x86.R_AL = 0x20;
89  else if (M.x86.R_AL == 6)
90  M.x86.R_AL = 0x3f;
91  else
92  M.x86.R_AL = 0x30;
93  break;
94  case 0x01:
95  // set cursor shape
96  // ignore
97  break;
98  case 0x02:
99  // set cursor position
100  // BH: pagenumber, DX: cursor_pos (DH:row, DL:col)
101  // BDA offset 50h-60h are 8 cursor position words for
102  // eight possible video pages
103  my_wrw(0x450 + (M.x86.R_BH * 2), M.x86.R_DX);
104  break;
105  case 0x03:
106  //get cursor position
107  // BH: pagenumber
108  // BDA offset 50h-60h are 8 cursor position words for
109  // eight possible video pages
110  M.x86.R_AX = 0;
111  M.x86.R_CH = 0; // start scan line ???
112  M.x86.R_CL = 0; // end scan line ???
113  M.x86.R_DX = my_rdw(0x450 + (M.x86.R_BH * 2));
114  break;
115  case 0x05:
116  // set active page
117  // BDA offset 62h is current page number
118  my_wrb(0x462, M.x86.R_AL);
119  break;
120  case 0x06:
121  //scroll up windows
122  break;
123  case 0x07:
124  //scroll down windows
125  break;
126  case 0x08:
127  //read character and attribute at position
128  M.x86.R_AH = 0x07; // white-on-black
129  M.x86.R_AL = 0x20; // a space...
130  break;
131  case 0x09:
132  // write character and attribute
133  //AL: char, BH: page number, BL: attribute, CX: number of times to write
134  //BDA offset 62h is current page number
136  u32 i = 0;
137  if (M.x86.R_BH == my_rdb(0x462)) {
138  for (i = 0; i < M.x86.R_CX; i++)
139  printf("%c", M.x86.R_AL);
140  }
141  }
142  break;
143  case 0x0a:
144  // write character
145  //AL: char, BH: page number, BL: attribute, CX: number of times to write
146  //BDA offset 62h is current page number
148  u32 i = 0;
149  if (M.x86.R_BH == my_rdb(0x462)) {
150  for (i = 0; i < M.x86.R_CX; i++)
151  printf("%c", M.x86.R_AL);
152  }
153  }
154  break;
155  case 0x0e:
156  // teletype output: write character and advance cursor...
157  //AL: char, BH: page number, BL: attribute
158  //BDA offset 62h is current page number
160  // we ignore the pagenumber on this call...
161  //if (M.x86.R_BH == my_rdb(0x462))
162  {
163  printf("%c", M.x86.R_AL);
164  // for debugging, to read all lines
165  //if (M.x86.R_AL == 0xd) // carriage return
166  // printf("\n");
167  }
168  }
169  break;
170  case 0x0f:
171  // get video mode
172  // BDA offset 49h is current video mode
173  // BDA offset 62h is current page number
174  // BDA offset 4ah is columns on screen
175  M.x86.R_AH = 80; //number of character columns... we hardcode it to 80
176  M.x86.R_AL = my_rdb(0x449);
177  M.x86.R_BH = my_rdb(0x462);
178  break;
179  default:
180  printf("%s(): unknown function (%x) for int10 handler.\n",
181  __func__, M.x86.R_AH);
182  DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
183  M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
184  M.x86.R_DX);
185  HALT_SYS();
186  break;
187  }
188 }
189 
190 // this table translates ASCII chars into their XT scan codes:
191 static u8 keycode_table[256] = {
192  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0 - 7
193  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 8 - 15
194  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 16 - 23
195  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 24 - 31
196  0x39, 0x02, 0x28, 0x04, 0x05, 0x06, 0x08, 0x28, // 32 - 39
197  0x0a, 0x0b, 0x09, 0x2b, 0x33, 0x0d, 0x34, 0x35, // 40 - 47
198  0x0b, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // 48 - 55
199  0x09, 0x0a, 0x27, 0x27, 0x33, 0x2b, 0x34, 0x35, // 56 - 63
200  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 64 - 71
201  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 72 - 79
202  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 80 - 87
203  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 88 - 95
204  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 96 - 103
205  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 104 - 111
206  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 112 - 119
207  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 120 - 127
208  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ...
209  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
213  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
216  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
221  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
222  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
223  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224 }
225 
226 ;
227 
228 static void
230 {
231  u8 scan_code = 0;
232  u8 char_code = 0;
233  if (*keycode < 256) {
234  scan_code = keycode_table[*keycode];
235  char_code = (u8) * keycode & 0xff;
236  } else {
237  switch (*keycode) {
238  case 0x1b50:
239  // F1
240  scan_code = 0x3b;
241  char_code = 0x0;
242  break;
243  default:
244  printf("%s(): unknown multibyte keycode: %llx\n",
245  __func__, *keycode);
246  break;
247  }
248  }
249  //assemble scan/char code in keycode
250  *keycode = (u64) ((((u16) scan_code) << 8) | char_code);
251 }
252 
253 // handle int16 (Keyboard BIOS Interrupt)
254 static void
256 {
257  // keyboard buffer is in BIOS Memory Area:
258  // offset 0x1a (WORD) pointer to next char in keybuffer
259  // offset 0x1c (WORD) pointer to next insert slot in keybuffer
260  // offset 0x1e-0x3e: 16 WORD Ring Buffer
261  // since we currently always read the char from the FW buffer,
262  // we misuse the ring buffer, we use it as pointer to a u64 that stores
263  // multi-byte keys (e.g. special keys in VT100 terminal)
264  // and as long as a key is available (not 0) we don't read further keys
265  u64 *keycode = (u64 *) (M.mem_base + 0x41e);
266  s8 c;
267  // function number in AH
268  DEBUG_PRINTF_INTR("%s(): Keyboard Interrupt: function: %x.\n",
269  __func__, M.x86.R_AH);
270  DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n", M.x86.R_AX,
271  M.x86.R_BX, M.x86.R_CX, M.x86.R_DX);
272  switch (M.x86.R_AH) {
273  case 0x00:
274  // get keystroke
275  if (*keycode) {
276  M.x86.R_AX = (u16) * keycode;
277  // clear keycode
278  *keycode = 0;
279  } else {
280  M.x86.R_AH = 0x61; // scancode for space key
281  M.x86.R_AL = 0x20; // a space
282  }
283  break;
284  case 0x01:
285  // check keystroke
286  // ZF set = no keystroke
287  // read first byte of key code
288  if (*keycode) {
289  // already read, but not yet taken
290  CLEAR_FLAG(F_ZF);
291  M.x86.R_AX = (u16) * keycode;
292  } else {
293  /* TODO: we need getchar... */
294  c = -1; //getchar();
295  if (c == -1) {
296  // no key available
297  SET_FLAG(F_ZF);
298  } else {
299  *keycode = c;
300 
301  // since after an ESC it may take a while to receive the next char,
302  // we send something that is not shown on the screen, and then try to get
303  // the next char
304  // TODO: only after ESC?? what about other multibyte keys
305  printf("tt%c%c", 0x08, 0x08); // 0x08 == Backspace
306 
307  /* TODO: we need getchar... */
308  while ((c = -1 /*getchar()*/) != -1) {
309  *keycode = (*keycode << 8) | c;
310  DEBUG_PRINTF(" key read: %0llx\n",
311  *keycode);
312  }
313  translate_keycode(keycode);
314  DEBUG_PRINTF(" translated key: %0llx\n",
315  *keycode);
316  if (*keycode == 0) {
317  //not found
318  SET_FLAG(F_ZF);
319  } else {
320  CLEAR_FLAG(F_ZF);
321  M.x86.R_AX = (u16) * keycode;
322  //X86EMU_trace_on();
323  //M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
324  }
325  }
326  }
327  break;
328  default:
329  printf("%s(): unknown function (%x) for int16 handler.\n",
330  __func__, M.x86.R_AH);
331  DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
332  M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
333  M.x86.R_DX);
334  HALT_SYS();
335  break;
336  }
337 }
338 
339 // handle int1a (PCI BIOS Interrupt)
340 static void
342 {
343  // function number in AX
344  u8 bus, devfn, offs;
345  struct device *dev = NULL;
346 
347  switch (M.x86.R_AX) {
348  case 0xb101:
349  // Installation check
350  CLEAR_FLAG(F_CF); // clear CF
351  M.x86.R_EDX = 0x20494350; // " ICP" endian swapped "PCI "
352  M.x86.R_AL = 0x1; // Config Space Mechanism 1 supported
353  M.x86.R_BX = 0x0210; // PCI Interface Level Version 2.10
354  M.x86.R_CL = 0xff; // number of last PCI Bus in system TODO: check!
355  break;
356  case 0xb102:
357  // Find PCI Device
358  // device_id in CX, vendor_id in DX
359  // device index in SI (i.e. if multiple devices with same vendor/device id
360  // are connected). We currently only support device index 0
361  //
362  DEBUG_PRINTF_INTR("%s(): function: %x: PCI Find Device\n",
363  __func__, M.x86.R_AX);
364 
365  /* FixME: support SI != 0 */
366 
367  // only allow the device to find itself...
368  if ((M.x86.R_CX == bios_device.pci_device_id)
369  && (M.x86.R_DX == bios_device.pci_vendor_id)
370  // device index must be 0
371  && (M.x86.R_SI == 0)) {
372  dev = bios_device.dev;
373  M.x86.R_BH = bios_device.bus;
374  M.x86.R_BL = bios_device.devfn;
375  } else if (CONFIG(YABEL_PCI_ACCESS_OTHER_DEVICES)) {
376  dev = dev_find_device(M.x86.R_DX, M.x86.R_CX, 0);
377  if (dev != NULL) {
378  M.x86.R_BH = dev->bus->secondary;
379  M.x86.R_BL = dev->path.pci.devfn;
381  ("%s(): function %x: PCI Find Device --> 0x%04x\n",
382  __func__, M.x86.R_AX, M.x86.R_BX);
383  }
384  }
385  if (dev == NULL) {
387  ("%s(): function %x: invalid device/vendor/device index! (%04x/%04x/%02x expected: %04x/%04x/00)\n",
388  __func__, M.x86.R_AX, M.x86.R_CX, M.x86.R_DX,
389  M.x86.R_SI, bios_device.pci_device_id,
391 
392  SET_FLAG(F_CF);
393  M.x86.R_AH = 0x86; // return code: device not found
394  return;
395  }
396  CLEAR_FLAG(F_CF);
397  M.x86.R_AH = 0x00; // return code: success
398  break;
399  case 0xb108: //read configuration byte
400  case 0xb109: //read configuration word
401  case 0xb10a: //read configuration dword
402  bus = M.x86.R_BH;
403  devfn = M.x86.R_BL;
404  offs = M.x86.R_DI;
405  DEBUG_PRINTF_INTR("%s(): function: %x: PCI Config Read from device: bus: %02x, devfn: %02x, offset: %02x\n",
406  __func__, M.x86.R_AX, bus, devfn, offs);
407 
408  if ((bus == bios_device.bus) && (devfn == bios_device.devfn)) {
409  dev = bios_device.dev;
410  } else if (CONFIG(YABEL_PCI_ACCESS_OTHER_DEVICES)) {
411  dev = pcidev_path_on_bus(bus, devfn);
412  DEBUG_PRINTF_INTR("%s(): function: %x: pcidev_path_on_bus() returned: %s\n",
413  __func__, M.x86.R_AX, dev_path(dev));
414  }
415 
416  if (dev == NULL) {
417  printf
418  ("%s(): Config read access invalid device! bus: %02x (%02x), devfn: %02x (%02x), offs: %02x\n",
419  __func__, bus, bios_device.bus, devfn,
420  bios_device.devfn, offs);
421  SET_FLAG(F_CF);
422  M.x86.R_AH = 0x87; //return code: bad pci register
423  HALT_SYS();
424  return;
425  }
426 
427  switch (M.x86.R_AX) {
428  case 0xb108:
429  M.x86.R_CL =
430 #if CONFIG(PCI_OPTION_ROM_RUN_YABEL)
431  pci_read_config8(dev, offs);
432 #else
434  bus, devfn,
435  offs);
436 #endif
438  ("%s(): function %x: PCI Config Read @%02x --> 0x%02x\n",
439  __func__, M.x86.R_AX, offs,
440  M.x86.R_CL);
441  break;
442  case 0xb109:
443  M.x86.R_CX =
444 #if CONFIG(PCI_OPTION_ROM_RUN_YABEL)
445  pci_read_config16(dev, offs);
446 #else
448  bus, devfn,
449  offs);
450 #endif
452  ("%s(): function %x: PCI Config Read @%02x --> 0x%04x\n",
453  __func__, M.x86.R_AX, offs,
454  M.x86.R_CX);
455  break;
456  case 0xb10a:
457  M.x86.R_ECX =
458 #if CONFIG(PCI_OPTION_ROM_RUN_YABEL)
459  pci_read_config32(dev, offs);
460 #else
462  bus, devfn,
463  offs);
464 #endif
466  ("%s(): function %x: PCI Config Read @%02x --> 0x%08x\n",
467  __func__, M.x86.R_AX, offs,
468  M.x86.R_ECX);
469  break;
470  }
471  CLEAR_FLAG(F_CF);
472  M.x86.R_AH = 0x0; // return code: success
473  break;
474  case 0xb10b: //write configuration byte
475  case 0xb10c: //write configuration word
476  case 0xb10d: //write configuration dword
477  bus = M.x86.R_BH;
478  devfn = M.x86.R_BL;
479  offs = M.x86.R_DI;
480 
481  if ((bus == bios_device.bus) && (devfn == bios_device.devfn)) {
482  dev = bios_device.dev;
483  }
484 
485  if (dev == NULL) {
486  printf
487  ("%s(): Config read access invalid! bus: %x (%x), devfn: %x (%x), offs: %x\n",
488  __func__, bus, bios_device.bus, devfn,
489  bios_device.devfn, offs);
490  SET_FLAG(F_CF);
491  M.x86.R_AH = 0x87; //return code: bad pci register
492  HALT_SYS();
493  return;
494  }
495 
496  switch (M.x86.R_AX) {
497  case 0xb10b:
498 #if CONFIG(PCI_OPTION_ROM_RUN_YABEL)
499  pci_write_config8(dev, offs, M.x86.R_CL);
500 #else
502  devfn, offs, M.x86.R_CL);
503 #endif
505  ("%s(): function %x: PCI Config Write @%02x <-- 0x%02x\n",
506  __func__, M.x86.R_AX, offs,
507  M.x86.R_CL);
508  break;
509  case 0xb10c:
510 #if CONFIG(PCI_OPTION_ROM_RUN_YABEL)
511  pci_write_config16(dev, offs, M.x86.R_CX);
512 #else
514  devfn, offs, M.x86.R_CX);
515 #endif
517  ("%s(): function %x: PCI Config Write @%02x <-- 0x%04x\n",
518  __func__, M.x86.R_AX, offs,
519  M.x86.R_CX);
520  break;
521  case 0xb10d:
522 #if CONFIG(PCI_OPTION_ROM_RUN_YABEL)
523  pci_write_config32(dev, offs, M.x86.R_ECX);
524 #else
526  devfn, offs, M.x86.R_ECX);
527 #endif
529  ("%s(): function %x: PCI Config Write @%02x <-- 0x%08x\n",
530  __func__, M.x86.R_AX, offs,
531  M.x86.R_ECX);
532  break;
533  }
534  CLEAR_FLAG(F_CF);
535  M.x86.R_AH = 0x0; // return code: success
536  break;
537  default:
538  printf("%s(): unknown function (%x) for int1a handler.\n",
539  __func__, M.x86.R_AX);
540  DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
541  M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
542  M.x86.R_DX);
543  HALT_SYS();
544  break;
545  }
546 }
547 
548 // main Interrupt Handler routine, should be registered as x86emu interrupt handler
549 void
550 handleInterrupt(int intNum)
551 {
552  u8 int_handled = 0;
553 #ifndef DEBUG_PRINT_INT10
554  // this printf makes output by int 10 unreadable...
555  // so we only enable it, if int10 print is disabled
556  DEBUG_PRINTF_INTR("%s(%x)\n", __func__, intNum);
557 #endif
558 
559  /* check whether this interrupt has a function pointer set in yabel_intFuncArray and run that */
560  if (yabel_intFuncArray[intNum]) {
561  DEBUG_PRINTF_INTR("%s(%x) intHandler overridden, calling it...\n", __func__, intNum);
562  int_handled = (*yabel_intFuncArray[intNum])();
563  } else {
564  switch (intNum) {
565  case 0x10: //BIOS video interrupt
566  case 0x42: // INT 10h relocated by EGA/VGA BIOS
567  case 0x6d: // INT 10h relocated by VGA BIOS
568  // get interrupt vector from IDT (4 bytes per Interrupt starting at address 0
569  if ((my_rdl(intNum * 4) == 0xF000F065) || //F000:F065 is default BIOS interrupt handler address
570  (my_rdl(intNum * 4) == 0xF4F4F4F4)) //invalid
571  {
572 #if 0
573  // ignore interrupt...
575  ("%s(%x): invalid interrupt Vector (%08x) found, interrupt ignored...\n",
576  __func__, intNum, my_rdl(intNum * 4));
577  DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
578  M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
579  M.x86.R_DX);
580  //HALT_SYS();
581 #endif
582  handleInt10();
583  int_handled = 1;
584  }
585  break;
586  case 0x16:
587  // Keyboard BIOS Interrupt
588  handleInt16();
589  int_handled = 1;
590  break;
591  case 0x1a:
592  // PCI BIOS Interrupt
593  handleInt1a();
594  int_handled = 1;
595  break;
596  case PMM_INT_NUM:
597  /* The self-defined PMM INT number, this is called by
598  * the code in PMM struct, and it is handled by
599  * pmm_handleInt()
600  */
601  pmm_handleInt();
602  int_handled = 1;
603  break;
604  default:
605  printf("Interrupt %#x (Vector: %x) not implemented\n", intNum,
606  my_rdl(intNum * 4));
607  DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
608  M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
609  M.x86.R_DX);
610  int_handled = 1;
611  HALT_SYS();
612  break;
613  }
614  }
615  // if we did not handle the interrupt, jump to the interrupt vector...
616  if (!int_handled) {
617  setupInt(intNum);
618  }
619 }
620 
621 // prepare and execute Interrupt 10 (VGA Interrupt)
622 void
623 runInt10(void)
624 {
625  // Initialize stack and data segment
626  M.x86.R_SS = STACK_SEGMENT;
627  M.x86.R_DS = DATA_SEGMENT;
628  M.x86.R_SP = STACK_START_OFFSET;
629 
630  // push a HLT instruction and a pointer to it onto the stack
631  // any return will pop the pointer and jump to the HLT, thus
632  // exiting (more or less) cleanly
633  push_word(0xf4f4); //F4=HLT
634  //push_word(M.x86.R_SS);
635  //push_word(M.x86.R_SP + 2);
636 
637  // setupInt will push the current CS and IP to the stack to return to it,
638  // but we want to halt, so set CS:IP to the HLT instruction we just pushed
639  // to the stack
640  M.x86.R_CS = M.x86.R_SS;
641  M.x86.R_IP = M.x86.R_SP; // + 4;
642 
644  X86EMU_trace_on();
645  }
647  M.x86.debug |= DEBUG_TRACEJMP_REGS_F;
648  M.x86.debug |= DEBUG_TRACEJMP_REGS_F;
649  M.x86.debug |= DEBUG_TRACECALL_F;
650  M.x86.debug |= DEBUG_TRACECALL_REGS_F;
651  }
652  setupInt(0x10);
653  DEBUG_PRINTF_INTR("%s(): starting execution of INT10...\n",
654  __func__);
655  X86EMU_exec();
656  DEBUG_PRINTF_INTR("%s(): execution finished\n", __func__);
657 }
658 
659 // prepare and execute Interrupt 13 (Disk Interrupt)
660 void
661 runInt13(void)
662 {
663  // Initialize stack and data segment
664  M.x86.R_SS = STACK_SEGMENT;
665  M.x86.R_DS = DATA_SEGMENT;
666  M.x86.R_SP = STACK_START_OFFSET;
667 
668  // push a HLT instruction and a pointer to it onto the stack
669  // any return will pop the pointer and jump to the HLT, thus
670  // exiting (more or less) cleanly
671  push_word(0xf4f4); //F4=HLT
672  //push_word(M.x86.R_SS);
673  //push_word(M.x86.R_SP + 2);
674 
675  // setupInt will push the current CS and IP to the stack to return to it,
676  // but we want to halt, so set CS:IP to the HLT instruction we just pushed
677  // to the stack
678  M.x86.R_CS = M.x86.R_SS;
679  M.x86.R_IP = M.x86.R_SP;
680 
682  X86EMU_trace_on();
683  }
685  M.x86.debug |= DEBUG_TRACEJMP_REGS_F;
686  M.x86.debug |= DEBUG_TRACEJMP_REGS_F;
687  M.x86.debug |= DEBUG_TRACECALL_F;
688  M.x86.debug |= DEBUG_TRACECALL_REGS_F;
689  }
690 
691  setupInt(0x13);
692  DEBUG_PRINTF_INTR("%s(): starting execution of INT13...\n",
693  __func__);
694  X86EMU_exec();
695  DEBUG_PRINTF_INTR("%s(): execution finished\n", __func__);
696 }
yabel_handleIntFunc yabel_intFuncArray[256]
Definition: biosemu.c:71
#define STACK_SEGMENT
Definition: biosemu.h:41
#define DATA_SEGMENT
Definition: biosemu.h:44
#define STACK_START_OFFSET
Definition: biosemu.h:42
#define PMM_INT_NUM
Definition: biosemu.h:58
#define printf(x...)
Definition: debug.h:47
#define DEBUG_JMP
Definition: debug.h:92
#define DEBUG_PRINT_INT10
Definition: debug.h:84
#define DEBUG_PRINTF_INTR(_x...)
Definition: debug.h:125
#define DEBUG_PRINTF(_x...)
Definition: debug.h:120
#define DEBUG_TRACE_X86EMU
Definition: debug.h:90
#define CHECK_DBG(_flag)
Definition: debug.h:118
biosemu_device_t bios_device
Definition: device.c:46
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
const char * dev_path(const struct device *dev)
Definition: device_util.c:149
@ CONFIG
Definition: dsi_common.h:201
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
static void handleInt10(void)
Definition: interrupt.c:72
static void translate_keycode(u64 *keycode)
Definition: interrupt.c:229
void handleInterrupt(int intNum)
Definition: interrupt.c:550
static void handleInt16(void)
Definition: interrupt.c:255
static u8 keycode_table[256]
Definition: interrupt.c:191
void runInt10(void)
Definition: interrupt.c:623
static void setupInt(int intNum)
Definition: interrupt.c:53
void runInt13(void)
Definition: interrupt.c:661
static void handleInt1a(void)
Definition: interrupt.c:341
void my_wrb(u32 addr, u8 val)
Definition: mem.c:363
u16 my_rdw(u32 addr)
Definition: mem.c:249
u32 my_rdl(u32 addr)
Definition: mem.c:300
void my_wrw(u32 addr, u16 val)
Definition: mem.c:388
u8 my_rdb(u32 addr)
Definition: mem.c:217
void pmm_handleInt(void)
Definition: pmm.c:107
void push_word(u16 w)
Definition: prim_ops.c:2394
#define F_TF
Definition: regs.h:198
#define M
Definition: regs.h:327
#define F_IF
Definition: regs.h:199
#define SET_FLAG(flag)
Definition: regs.h:204
#define F_CF
Definition: regs.h:193
#define CLEAR_FLAG(flag)
Definition: regs.h:205
#define F_ZF
Definition: regs.h:196
int rtas_pci_config_read(long long, int, int, int, int)
int rtas_pci_config_write(long long, int, int, int, int, int)
#define NULL
Definition: stddef.h:19
uint64_t u64
Definition: stdint.h:54
uint32_t u32
Definition: stdint.h:51
uint16_t u16
Definition: stdint.h:48
int8_t s8
Definition: stdint.h:44
uint8_t u8
Definition: stdint.h:45
u16 pci_vendor_id
Definition: device.h:101
u16 pci_device_id
Definition: device.h:102
void * dev
Definition: device.h:89
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 c(value, pmcreg, dst_bits)
#define DEBUG_TRACECALL_REGS_F
Definition: x86emu.h:178
#define HALT_SYS()
Definition: x86emu.h:160
#define DEBUG_TRACECALL_F
Definition: x86emu.h:174
int X86EMU_trace_on(void)
void X86EMU_exec(void)
Definition: decode.c:92
#define DEBUG_TRACEJMP_REGS_F
Definition: x86emu.h:182