fix some wrong versions of the FSF's address (trivial)
[coreboot.git] / src / northbridge / via / vx800 / vgabios.c
1 #include <console/console.h>
2 #include <device/pci.h>
3 #include <device/pci_ids.h>
4 #include <device/pci_ops.h>
5 #undef __KERNEL__
6 #include <arch/io.h>
7 #include <string.h>
8 #include "vgachip.h"
9
10 /* vgabios.c. Derived from: */
11
12 /*------------------------------------------------------------ -*- C -*-
13  *  2 Kernel Monte a.k.a. Linux loading Linux on x86
14  *
15  *  Erik Arjan Hendriks <hendriks@lanl.gov>
16  *
17  *  This version is a derivative of the original two kernel monte
18  *  which is (C) 2000 Scyld.
19  *
20  *  Copyright (C) 2000 Scyld Computing Corporation
21  *
22  *  This program is free software; you can redistribute it and/or modify
23  *  it under the terms of the GNU General Public License as published by
24  *  the Free Software Foundation; version 2 of the License.
25  *
26  *  This program is distributed in the hope that it will be useful,
27  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
28  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29  *  GNU General Public License for more details.
30  *
31  *  You should have received a copy of the GNU General Public License
32  *  along with this program; if not, write to the Free Software
33  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
34  *
35  * Portions related to the alpha architecture are:
36  *
37  *  Copyright(C) 2001 University of California.  LA-CC Number 01-67.
38  *  This software has been authored by an employee or employees of the
39  *  University of California, operator of the Los Alamos National
40  *  Laboratory under Contract No.  W-7405-ENG-36 with the U.S.
41  *  Department of Energy.  The U.S. Government has rights to use,
42  *  reproduce, and distribute this software. If the software is
43  *  modified to produce derivative works, such modified software should
44  *  be clearly marked, so as not to confuse it with the version
45  *  available from LANL.
46  *
47  *  This software may be used and distributed according to the terms
48  *  of the GNU General Public License, incorporated herein by
49  *  reference to http://www.gnu.org/licenses/gpl.html.
50  *
51  *  This software is provided by the author(s) "as is" and any express
52  *  or implied warranties, including, but not limited to, the implied
53  *  warranties of merchantability and fitness for a particular purpose
54  *  are disclaimed.  In no event shall the author(s) be liable for any
55  *  direct, indirect, incidental, special, exemplary, or consequential
56  *  damages (including, but not limited to, procurement of substitute
57  *  goods or services; loss of use, data, or profits; or business
58  *  interruption) however caused and on any theory of liability,
59  *  whether in contract, strict liability, or tort (including
60  *  negligence or otherwise) arising in any way out of the use of this
61  *  software, even if advised of the possibility of such damage.
62  *
63  *  $Id: vgabios.c,v 1.5 2004/10/06 17:33:52 rminnich Exp $
64  *--------------------------------------------------------------------*/
65
66 /* Modified to be a self sufficient plug in so that it can be used 
67    without reliance on other parts of coreboot's core
68    (C) 2005 Nick.Barker9@btinternet.com
69
70   Used initially for epia-m where there are problems getting the bios
71   emulator to successfully run this bios.
72 */
73 /* Declare a temporary global descriptor table - necessary because the
74    Core part of the bios no longer sets up any 16 bit segments */
75 __asm__(
76                /* pointer to original gdt */
77                "gdtarg:                 \n"
78                "        .word   gdt_limit       \n"
79                "        .long   gdt             \n"
80                /* compute the table limit */
81                "__mygdt_limit = __mygdt_end - __mygdt - 1       \n"
82                "__mygdtaddr:                    \n"
83                "        .word   __mygdt_limit   \n"
84                "        .long   __mygdt         \n"
85                "__mygdt:                        \n"
86                /* selgdt 0, unused */
87                "        .word   0x0000, 0x0000  \n"
88                "        .byte   0x00, 0x00, 0x00, 0x00  \n"
89                /* selgdt 8, unused */
90                "        .word   0x0000, 0x0000          \n"
91                "        .byte   0x00, 0x00, 0x00, 0x00  \n"
92                /* selgdt 0x10, flat code segment */
93                "        .word   0xffff, 0x0000          \n"
94                "        .byte   0x00, 0x9b, 0xcf, 0x00  \n"
95                /* selgdt 0x18, flat data segment */
96                "        .word   0xffff, 0x0000          \n"
97                "        .byte   0x00, 0x93, 0xcf, 0x00  \n"
98                /* selgdt 0x20, unused */
99                "        .word   0x0000, 0x0000          \n"
100                "        .byte   0x00, 0x00, 0x00, 0x00  \n"
101                /* selgdt 0x28 16-bit 64k code at 0x00000000 */
102                "        .word   0xffff, 0x0000          \n"
103                "        .byte   0, 0x9a, 0, 0           \n"
104                /* selgdt 0x30 16-bit 64k data at 0x00000000 */
105                "        .word   0xffff, 0x0000          \n"
106                "        .byte   0, 0x92, 0, 0           \n"
107                "__mygdt_end:                            \n");
108
109 /* Declare a pointer to where our idt is going to be i.e. at mem zero */
110 __asm__("__myidt:               \n"
111         /* 16-bit limit */
112         "       .word 1023      \n"
113         /* 24-bit base */
114         "       .long 0         \n" "   .word 0         \n");
115
116 /* The address arguments to this function are PHYSICAL ADDRESSES */
117 extern u8 acpi_sleep_type;
118
119 static void real_mode_switch_call_vga(unsigned long devfn)
120 {
121         if ((acpi_sleep_type == 0)/* && (PAYLOAD_IS_SEABIOS == 1)*/)
122                 return;
123         __asm__ __volatile__(
124                                     // paranoia -- does ecx get saved? not sure. This is 
125                                     // the easiest safe thing to do.
126                                     "   pushal                  \n"
127                                     /* save the stack */
128                                     "   mov     %esp, __stack   \n"
129                                     "   jmp     1f              \n"
130                                     "__stack: .long 0           \n" "1:\n"
131                                     /* get devfn into %ecx */
132                                     "   movl    %esp, %ebp      \n"
133                                     "   movl    8(%ebp), %ecx   \n"
134                                     /* load 'our' gdt */
135                                     "   lgdt    %cs:__mygdtaddr \n"
136                                     /*  This configures CS properly for real mode. */
137                                     "   ljmp    $0x28, $__rms_16bit\n"
138                                     "__rms_16bit:                       \n"
139                                     "   .code16                 \n"
140                                     /* 16 bit code from here on... */
141                                     /* Load the segment registers w/ properly configured segment
142                                      * descriptors.  They will retain these configurations (limits,
143                                      * writability, etc.) once protected mode is turned off. */
144                                     "   mov     $0x30, %ax      \n"
145                                     "   mov     %ax, %ds        \n"
146                                     "   mov     %ax, %es        \n"
147                                     "   mov     %ax, %fs        \n"
148                                     "   mov     %ax, %gs        \n"
149                                     "   mov     %ax, %ss        \n"
150                                     /* Turn off protection (bit 0 in CR0) */
151                                     "   movl    %cr0, %eax      \n"
152                                     "   andl    $0xFFFFFFFE, %eax \n"
153                                     "   movl    %eax, %cr0      \n"
154                                     /* Now really going into real mode */
155                                     "   ljmp    $0,  $__rms_real\n"
156                                     "__rms_real:                        \n"
157                                     /* put the stack at the end of page zero. 
158                                      * that way we can easily share it between real and protected, 
159                                      * since the 16-bit ESP at segment 0 will work for any case. 
160                                      /* Setup a stack */
161                                     "   mov     $0x0, %ax       \n"
162                                     "   mov     %ax, %ss        \n"
163                                     "   movl    $0x1000, %eax   \n"
164                                     "   movl    %eax, %esp      \n"
165                                     /* Load our 16 it idt */
166                                     "   xor     %ax, %ax        \n"
167                                     "   mov     %ax, %ds        \n"
168                                     "   lidt    __myidt         \n"
169                                     /* Dump zeros in the other segregs */
170                                     "   mov     %ax, %es        \n"
171                                     "   mov     %ax, %fs        \n"
172                                     "   mov     %ax, %gs        \n"
173                                     "   mov     $0x40, %ax      \n"
174                                     "   mov     %ax, %ds        \n"
175                                     "   mov     %cx, %ax        \n"
176                                     /* run VGA BIOS at 0xc000:0003 */
177                                     "   lcall   $0xc000, $0x0003\n"
178                                     /* if we got here, just about done. 
179                                      * Need to get back to protected mode */
180                                     "   movl    %cr0, %eax      \n" "   orl     $0x0000001, %eax\n"     /* PE = 1 */
181                                     "   movl    %eax, %cr0      \n"
182                                     /* Now that we are in protected mode jump to a 32 bit code segment. */
183                                     "   data32  ljmp    $0x10, $vgarestart\n"
184                                     "vgarestart:\n"
185                                     "   .code32\n"
186                                     "   movw    $0x18, %ax      \n"
187                                     "   mov     %ax, %ds        \n"
188                                     "   mov     %ax, %es        \n"
189                                     "   mov     %ax, %fs        \n"
190                                     "   mov     %ax, %gs        \n"
191                                     "   mov     %ax, %ss        \n"
192                                     /* restore proper gdt and idt */
193                                     "   lgdt    %cs:gdtarg      \n"
194                                     "   lidt    idtarg          \n"
195                                     ".globl vga_exit            \n"
196                                     "vga_exit:                  \n"
197                                     "   mov     __stack, %esp   \n"
198                                     "   popal                   \n");
199 }
200
201 __asm__(".text\n" "real_mode_switch_end:\n");
202 extern char real_mode_switch_end[];
203
204 /* call vga bios int 10 function 0x4f14 to enable main console 
205    epia-m does not always autosence the main console so forcing it on is good !! */
206 void vga_enable_console()
207 {
208         if ((acpi_sleep_type == 0)/* && (PAYLOAD_IS_SEABIOS == 1)*/)
209                 return;
210         __asm__ __volatile__(
211                                     /* paranoia -- does ecx get saved? not sure. This is 
212                                      * the easiest safe thing to do. */
213                                     "   pushal                  \n"
214                                     /* save the stack */
215                                     "   mov     %esp, __stack   \n"
216                                     /* load 'our' gdt */
217                                     "   lgdt    %cs:__mygdtaddr \n"
218                                     /*  This configures CS properly for real mode. */
219                                     "   ljmp    $0x28, $__vga_ec_16bit\n"
220                                     "__vga_ec_16bit:            \n"
221                                     "   .code16                 \n"
222                                     /* 16 bit code from here on... */
223                                     /* Load the segment registers w/ properly configured segment
224                                      * descriptors.  They will retain these configurations (limits,
225                                      * writability, etc.) once protected mode is turned off. */
226                                     "   mov     $0x30, %ax      \n"
227                                     "   mov     %ax, %ds        \n"
228                                     "   mov     %ax, %es        \n"
229                                     "   mov     %ax, %fs        \n"
230                                     "   mov     %ax, %gs        \n"
231                                     "   mov     %ax, %ss        \n"
232                                     /* Turn off protection (bit 0 in CR0) */
233                                     "   movl    %cr0, %eax      \n"
234                                     "   andl    $0xFFFFFFFE, %eax\n"
235                                     "   movl    %eax, %cr0      \n"
236                                     /* Now really going into real mode */
237                                     "   ljmp    $0, $__vga_ec_real \n"
238                                     "__vga_ec_real:                  \n"
239                                     /* put the stack at the end of page zero. 
240                                      * that way we can easily share it between real and protected, 
241                                      * since the 16-bit ESP at segment 0 will work for any case. 
242                                      /* Setup a stack */
243                                     "   mov     $0x0, %ax       \n"
244                                     "   mov     %ax, %ss        \n"
245                                     "   movl    $0x1000, %eax   \n"
246                                     "   movl    %eax, %esp      \n"
247                                     /* debugging for RGM */
248                                     "   mov     $0x11, %al      \n"
249                                     "   outb    %al, $0x80      \n"
250                                     /* Load our 16 it idt */
251                                     "   xor     %ax, %ax        \n"
252                                     "   mov     %ax, %ds        \n"
253                                     "   lidt    __myidt         \n"
254                                     /* Dump zeros in the other segregs */
255                                     "   mov     %ax, %ds        \n"
256                                     "   mov     %ax, %es        \n"
257                                     "   mov     %ax, %fs        \n"
258                                     "   mov     %ax, %gs        \n"
259                                     /* ask bios to enable main console */
260                                     /* set up for int 10 call - values found from X server
261                                      * bios call routines */
262                                     "   movw    $0x4f14,%ax     \n"
263                                     "   movw    $0x8003,%bx     \n"
264                                     "   movw    $1, %cx         \n"
265                                     "   movw    $0, %dx         \n"
266                                     "   movw    $0, %di         \n"
267                                     "   int     $0x10           \n"
268                                     "   movb    $0x55, %al      \n"
269                                     "   outb    %al, $0x80      \n"
270                                     /* if we got here, just about done. 
271                                      * Need to get back to protected mode */
272                                     "   movl    %cr0, %eax      \n" "   orl     $0x0000001, %eax\n"     /* PE = 1 */
273                                     "   movl    %eax, %cr0      \n"
274                                     /* Now that we are in protected mode jump to a 32 bit code segment. */
275                                     "   data32  ljmp    $0x10, $vga_ec_restart\n"
276                                     "vga_ec_restart:\n"
277                                     "   .code32\n"
278                                     "   movw    $0x18, %ax      \n"
279                                     "   mov     %ax, %ds        \n"
280                                     "   mov     %ax, %es        \n"
281                                     "   mov     %ax, %fs        \n"
282                                     "   mov     %ax, %gs        \n"
283                                     "   mov     %ax, %ss        \n"
284                                     /* restore proper gdt and idt */
285                                     "   lgdt    %cs:gdtarg      \n"
286                                     "   lidt    idtarg          \n"
287                                     "   .globl  vga__ec_exit    \n"
288                                     "vga_ec_exit:\n"
289                                     "   mov     __stack, %esp   \n"
290                                     "   popal\n");
291 }
292
293 void do_vgabios(void)
294 {
295         device_t dev;
296         unsigned long busdevfn;
297         unsigned int rom = 0;
298         unsigned char *buf;
299         unsigned int size = 64 * 1024;
300         int i;
301         u16 tmp;
302         u8 tmp8;
303
304         printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
305
306         /* clear vga bios data area */
307         for (i = 0x400; i < 0x500; i++) {
308                 *(unsigned char *)i = 0;
309         }
310
311         dev = dev_find_class(PCI_CLASS_DISPLAY_VGA << 8, 0);
312
313         if (!dev) {
314                 printk_debug("NO VGA FOUND\n");
315                 return;
316         }
317         printk_debug("found VGA: vid=%x, did=%x\n", dev->vendor, dev->device);
318
319         /* declare rom address here - keep any config data out of the way
320          * of core LXB stuff */
321
322         rom = 0xffffffff - CONFIG_ROM_SIZE + 1;
323         pci_write_config32(dev, PCI_ROM_ADDRESS, rom | 1);
324         printk_debug("rom base: %x\n", rom);
325         buf = (unsigned char *)rom;
326         printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
327
328         if ((buf[0] == 0x55) && (buf[1] == 0xaa)) {
329                 memcpy((void *)0xc0000, buf, size);
330
331                 printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
332
333                 write_protect_vgabios();        // in northbridge
334
335                 // check signature again
336                 buf = (unsigned char *)0xc0000;
337                 if (buf[0] == 0x55 && buf[1] == 0xAA) {
338                         busdevfn =
339                             (dev->bus->secondary << 8) | dev->path.pci.devfn;
340                         printk_debug("bus/devfn = %#x\n", busdevfn);
341                         real_mode_switch_call_vga(busdevfn);
342                 } else
343                         printk_debug("Failed to copy VGA BIOS to 0xc0000\n");
344         } else
345                 printk_debug("BAD SIGNATURE 0x%x 0x%x\n", buf[0], buf[1]);
346
347         printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
348
349         pci_write_config32(dev, PCI_ROM_ADDRESS, 0);
350 }
351
352 // we had hoped to avoid this. 
353 // this is a stub IDT only. It's main purpose is to ignore calls 
354 // to the BIOS. 
355 // no longer. Dammit. We have to respond to these.
356 struct realidt {
357         unsigned short offset, cs;
358 };
359
360 // from a handy writeup that andrey found.
361
362 // handler. 
363 // There are some assumptions we can make here. 
364 // First, the Top Of Stack (TOS) is located on the top of page zero. 
365 // we can share this stack between real and protected mode. 
366 // that simplifies a lot of things ...
367 // we'll just push all the registers on the stack as longwords, 
368 // and pop to protected mode. 
369 // second, since this only ever runs as part of coreboot, 
370 // we know all the segment register values -- so we don't save any.
371 // keep the handler that calls things small. It can do a call to 
372 // more complex code in coreboot itself. This helps a lot as we don't
373 // have to do address fixup in this little stub, and calls are absolute
374 // so the handler is relocatable.
375 void handler(void)
376 {
377         __asm__ __volatile__("  .code16         \n"
378                              "idthandle:                \n"
379                              "  pushal          \n"
380                              "  movb    $0, %al \n"
381                              "  ljmp    $0, $callbiosint16\n"
382                              "end_idthandle:            \n"
383                              "  .code32         \n");
384 }
385
386 void debughandler(void)
387 {
388         __asm__ __volatile__("  .code16         \n"
389                              "debughandle:              \n"
390                              "  pushw   %cx     \n"
391                              "  movw    $250, %cx \n"
392                              "dbh1:                     \n"
393                              "  loop    dbh1    \n"
394                              "  popw    %cx     \n"
395                              "  iret            \n"
396                              "end_debughandle:  \n" ".code32            \n");
397 }
398
399 // Calling conventions. The first C function is called with this stuff
400 // on the stack. They look like value parameters, but note that if you
401 // modify them they will go back to the INTx function modified. 
402 // the C function will call the biosint function with these as
403 // REFERENCE parameters. In this way, we can easily get 
404 // returns back to the INTx caller (i.e. vgabios)
405 void callbiosint(void)
406 {
407         __asm__ __volatile__("  .code16         \n"
408                              "callbiosint16:            \n"
409                              "  push    %ds     \n"
410                              "  push    %es     \n"
411                              "  push    %fs     \n" "   push    %gs     \n"
412                              // clean up the int #. To save space we put it in the lower
413                              // byte. But the top 24 bits are junk. 
414                              "  andl    $0xff, %eax\n"
415                              // this push does two things:
416                              // - put the INT # on the stack as a parameter
417                              // - provides us with a temp for the %cr0 mods.
418                              "  pushl   %eax    \n" "   movl    %cr0, %eax\n" " orl     $0x00000001, %eax\n"    /* PE = 1 */
419                              "  movl    %eax, %cr0\n"
420                              /* Now that we are in protected mode jump to a 32 bit code segment. */
421                              "  data32  ljmp    $0x10, $biosprotect\n"
422                              "biosprotect:              \n"
423                              "  .code32         \n"
424                              "  movw    $0x18, %ax          \n"
425                              "  mov     %ax, %ds          \n"
426                              "  mov     %ax, %es          \n"
427                              "  mov     %ax, %fs          \n"
428                              "  mov     %ax, %gs          \n"
429                              "  mov     %ax, %ss          \n"
430                              "  lidt    idtarg         \n"
431                              "  call    biosint \n"
432                              // back to real mode ...
433                              "  ljmp    $0x28, $__rms_16bit2\n"
434                              "__rms_16bit2:                     \n"
435                              "  .code16                 \n"
436                              /* 16 bit code from here on... */
437                              /* Load the segment registers w/ properly configured segment
438                               * descriptors.  They will retain these configurations (limits,
439                               * writability, etc.) once protected mode is turned off. */
440                              "  mov     $0x30, %ax      \n"
441                              "  mov     %ax, %ds        \n"
442                              "  mov     %ax, %es        \n"
443                              "  mov     %ax, %fs        \n"
444                              "  mov     %ax, %gs        \n"
445                              "  mov     %ax, %ss        \n"
446                              /* Turn off protection (bit 0 in CR0) */
447                              "  movl    %cr0, %eax              \n"
448                              "  andl    $0xFFFFFFFE, %eax       \n"
449                              "  movl    %eax, %cr0              \n"
450                              /* Now really going into real mode */
451                              "  ljmp $0,  $__rms_real2  \n"
452                              "__rms_real2:                      \n"
453                              /* Setup a stack
454                               * FixME: where is esp? */
455                              "  mov     $0x0, %ax       \n"
456                              "  mov     %ax, %ss        \n"
457                              /* ebugging for RGM */
458                              "  mov     $0x11, %al      \n"
459                              "  outb    %al, $0x80      \n"
460                              /* Load our 16 it idt */
461                              "  xor     %ax, %ax        \n"
462                              "  mov     %ax, %ds        \n"
463                              "  lidt    __myidt         \n"
464                              /* Dump zeros in the other segregs */
465                              "  mov     %ax, %es        \n"
466                              "  mov     %ax, %fs        \n"
467                              "  mov     %ax, %gs        \n"
468                              "  mov     $0x40, %ax      \n"
469                              "  mov     %ax, %ds        \n"
470                              /* pop the INT # that you pushed earlier */
471                              "  popl    %eax            \n"
472                              "  pop     %gs             \n"
473                              "  pop     %fs             \n"
474                              "  pop     %es             \n"
475                              "  pop     %ds             \n"
476                              "  popal                   \n"
477                              "  iret                    \n"
478                              "  .code32                 \n");
479 }
480
481 enum {
482         PCIBIOS = 0x1a,
483         MEMSIZE = 0x12
484 };
485
486 int pcibios(unsigned long *pedi, unsigned long *pesi, unsigned long *pebp,
487             unsigned long *pesp, unsigned long *pebx, unsigned long *pedx,
488             unsigned long *pecx, unsigned long *peax, unsigned long *pflags);
489
490 int handleint21(unsigned long *pedi, unsigned long *pesi,
491                 unsigned long *pebp, unsigned long *pesp,
492                 unsigned long *pebx, unsigned long *pedx,
493                 unsigned long *pecx, unsigned long *peax,
494                 unsigned long *pflags);
495
496 extern void vga_exit(void);
497
498 int biosint(unsigned long intnumber,
499             unsigned long gsfs, unsigned long dses,
500             unsigned long edi, unsigned long esi,
501             unsigned long ebp, unsigned long esp,
502             unsigned long ebx, unsigned long edx,
503             unsigned long ecx, unsigned long eax,
504             unsigned long cs_ip, unsigned short stackflags)
505 {
506         unsigned long ip;
507         unsigned long cs;
508         unsigned long flags;
509         int ret = -1;
510
511         ip = cs_ip & 0xffff;
512         cs = cs_ip >> 16;
513         flags = stackflags;
514
515         printk_debug("biosint: INT# 0x%lx\n", intnumber);
516         printk_debug("biosint: eax 0x%lx ebx 0x%lx ecx 0x%lx edx 0x%lx\n",
517                      eax, ebx, ecx, edx);
518         printk_debug("biosint: ebp 0x%lx esp 0x%lx edi 0x%lx esi 0x%lx\n",
519                      ebp, esp, edi, esi);
520         printk_debug("biosint:  ip 0x%x   cs 0x%x  flags 0x%x\n",
521                      ip, cs, flags);
522
523         // cases in a good compiler are just as good as your own tables. 
524         switch (intnumber) {
525         case 0: case 1: case 2: case 3: case 4: case 5:
526         case 6: case 7: case 8: case 9: case 10:
527         case 11: case 12: case 13: case 14: case 15:
528                 // These are not BIOS service, but the CPU-generated exceptions
529                 printk_info("biosint: Oops, exception %u\n", intnumber);
530                 if (esp < 0x1000) {
531                         printk_debug("Stack contents: ");
532                         while (esp < 0x1000) {
533                                 printk_debug("0x%04x ", *(unsigned short *)esp);
534                                 esp += 2;
535                         }
536                         printk_debug("\n");
537                 }
538                 printk_debug("biosint: Bailing out\n");
539                 // "longjmp"
540                 if ((acpi_sleep_type == 3)/* || (PAYLOAD_IS_SEABIOS == 0)*/)    // add this to keep same with kevin's seabios patch in 2008-9-8
541                         vga_exit();
542                 break;
543
544         case PCIBIOS:
545                 ret = pcibios(&edi, &esi, &ebp, &esp,
546                               &ebx, &edx, &ecx, &eax, &flags);
547                 break;
548         case MEMSIZE:
549                 // who cares. 
550                 eax = 64 * 1024;
551                 ret = 0;
552                 break;
553         case 0x15:
554                 ret = handleint21(&edi, &esi, &ebp, &esp,
555                                   &ebx, &edx, &ecx, &eax, &flags);
556                 break;
557         default:
558                 printk_info("BIOSINT: Unsupport int #0x%x\n", intnumber);
559                 break;
560         }
561         if (ret)
562                 flags |= 1;     // carry flags
563         else
564                 flags &= ~1;
565         stackflags = flags;
566         return ret;
567 }
568
569 void setup_realmode_idt(void)
570 {
571         extern unsigned char idthandle, end_idthandle;
572         extern unsigned char debughandle, end_debughandle;
573
574         int i;
575         struct realidt *idts = (struct realidt *)0;
576         int codesize = &end_idthandle - &idthandle;
577         unsigned char *intbyte, *codeptr;
578
579         // for each int, we create a customized little handler
580         // that just pushes %ax, puts the int # in %al, 
581         // then calls the common interrupt handler. 
582         // this necessitated because intel didn't know much about 
583         // architecture when they did the 8086 (it shows)
584         // (hmm do they know anymore even now :-)
585         // obviously you can see I don't really care about memory 
586         // efficiency. If I did I would probe back through the stack
587         // and get it that way. But that's really disgusting.
588         for (i = 0; i < 256; i++) {
589                 idts[i].cs = 0;
590                 codeptr = (char *)4096 + i * codesize;
591                 idts[i].offset = (unsigned)codeptr;
592                 memcpy(codeptr, &idthandle, codesize);
593                 intbyte = codeptr + 3;
594                 *intbyte = i;
595         }
596
597         // fixed entry points
598
599         // VGA BIOSes tend to hardcode f000:f065 as the previous handler of
600         // int10. 
601         // calling convention here is the same as INTs, we can reuse
602         // the int entry code.
603         codeptr = (char *)0xff065;
604         memcpy(codeptr, &idthandle, codesize);
605         intbyte = codeptr + 3;
606         *intbyte = 0x42;        /* int42 is the relocated int10 */
607 /*
608  Fixed entry points
609   VBIOS will call f000:f859 instead of sending int15.
610  calling convertion here is the same as INTs, we can reuse the int entry code.
611 */
612         codeptr = (char *)0xff859;
613         memcpy(codeptr, &idthandle, codesize);
614         intbyte = codeptr + 3;
615         *intbyte = 0x15;
616
617         /* debug handler - useful to set a programmable delay between instructions if the
618            TF bit is set upon call to real mode */
619         idts[1].cs = 0;
620         idts[1].offset = 16384;
621         memcpy(16384, &debughandle, &end_debughandle - &debughandle);
622
623 }
624
625 enum {
626         CHECK = 0xb001,
627         FINDDEV = 0xb102,
628         READCONFBYTE = 0xb108,
629         READCONFWORD = 0xb109,
630         READCONFDWORD = 0xb10a,
631         WRITECONFBYTE = 0xb10b,
632         WRITECONFWORD = 0xb10c,
633         WRITECONFDWORD = 0xb10d
634 };
635
636 // errors go in AH. Just set these up so that word assigns
637 // will work. KISS. 
638 enum {
639         PCIBIOS_NODEV = 0x8600,
640         PCIBIOS_BADREG = 0x8700
641 };
642
643 int
644 pcibios(unsigned long *pedi, unsigned long *pesi, unsigned long *pebp,
645         unsigned long *pesp, unsigned long *pebx, unsigned long *pedx,
646         unsigned long *pecx, unsigned long *peax, unsigned long *pflags)
647 {
648         unsigned long edi = *pedi;
649         unsigned long esi = *pesi;
650         unsigned long ebp = *pebp;
651         unsigned long esp = *pesp;
652         unsigned long ebx = *pebx;
653         unsigned long edx = *pedx;
654         unsigned long ecx = *pecx;
655         unsigned long eax = *peax;
656         unsigned long flags = *pflags;
657         unsigned short func = (unsigned short)eax;
658         int retval = 0;
659         unsigned short devid, vendorid, devfn;
660         short devindex;         /* Use short to get rid of garbage in upper half of 32-bit register */
661         unsigned char bus;
662         device_t dev;
663
664         switch (func) {
665         case CHECK:
666                 *pedx = 0x4350;
667                 *pecx = 0x2049;
668                 retval = 0;
669                 break;
670         case FINDDEV:
671                 {
672                         devid = *pecx;
673                         vendorid = *pedx;
674                         devindex = *pesi;
675                         dev = 0;
676                         while ((dev = dev_find_device(vendorid, devid, dev))) {
677                                 if (devindex <= 0)
678                                         break;
679                                 devindex--;
680                         }
681                         if (dev) {
682                                 unsigned short busdevfn;
683                                 *peax = 0;
684                                 // busnum is an unsigned char;
685                                 // devfn is an int, so we mask it off. 
686                                 busdevfn = (dev->bus->secondary << 8)
687                                     | (dev->path.pci.devfn & 0xff);
688                                 printk_debug("0x%x: return 0x%x\n", func,
689                                              busdevfn);
690                                 *pebx = busdevfn;
691                                 retval = 0;
692                         } else {
693                                 *peax = PCIBIOS_NODEV;
694                                 retval = -1;
695                         }
696                 }
697                 break;
698         case READCONFDWORD:
699         case READCONFWORD:
700         case READCONFBYTE:
701         case WRITECONFDWORD:
702         case WRITECONFWORD:
703         case WRITECONFBYTE:
704                 {
705                         unsigned long dword;
706                         unsigned short word;
707                         unsigned char byte;
708                         unsigned char reg;
709
710                         devfn = *pebx & 0xff;
711                         bus = *pebx >> 8;
712                         reg = *pedi;
713                         dev = dev_find_slot(bus, devfn);
714                         if (!dev) {
715                                 printk_debug
716                                     ("0x%x: BAD DEVICE bus %d devfn 0x%x\n",
717                                      func, bus, devfn);
718                                 // idiots. the pcibios guys assumed you'd never pass a bad bus/devfn!
719                                 *peax = PCIBIOS_BADREG;
720                                 retval = -1;
721                         }
722                         switch (func) {
723                         case READCONFBYTE:
724                                 byte = pci_read_config8(dev, reg);
725                                 *pecx = byte;
726                                 break;
727                         case READCONFWORD:
728                                 word = pci_read_config16(dev, reg);
729                                 *pecx = word;
730                                 break;
731                         case READCONFDWORD:
732                                 dword = pci_read_config32(dev, reg);
733                                 *pecx = dword;
734                                 break;
735                         case WRITECONFBYTE:
736                                 byte = *pecx;
737                                 pci_write_config8(dev, reg, byte);
738                                 break;
739                         case WRITECONFWORD:
740                                 word = *pecx;
741                                 pci_write_config16(dev, reg, word);
742                                 break;
743                         case WRITECONFDWORD:
744                                 dword = *pecx;
745                                 pci_write_config32(dev, reg, dword);
746                                 break;
747                         }
748
749                         if (retval)
750                                 retval = PCIBIOS_BADREG;
751                         printk_debug
752                             ("0x%x: bus %d devfn 0x%x reg 0x%x val 0x%lx\n",
753                              func, bus, devfn, reg, *pecx);
754                         *peax = 0;
755                         retval = 0;
756                 }
757                 break;
758         default:
759                 printk_err("UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func);
760                 break;
761         }
762
763         return retval;
764 }
765
766 /* return value of int0x15(int21)
767 AH  AL                  Completion status 
768 ??  5Fh                 Function call supported 
769 ??  !=5Fh       Function not supported 
770 00  5Fh                 Function call successful 
771 01  5Fh                 Function call failed 
772 */
773 int handleint21(unsigned long *edi, unsigned long *esi, unsigned long *ebp,
774                 unsigned long *esp, unsigned long *ebx, unsigned long *edx,
775                 unsigned long *ecx, unsigned long *eax, unsigned long *flags)
776 {
777         int res = -1;
778         switch (*eax & 0xffff) {
779         case 0x5f19:
780                 *eax = 0x5f;
781                 *ecx = 0x3;
782                 res = 0;
783                 break;
784         case 0x5f18:
785                 {
786                         /*
787                            BL  
788                            Bit[7:4] 
789                            Memory Data Rate 
790                            0000: 66MHz 
791                            0001: 100MHz 
792                            0010: 133MHz 
793                            0011: 200MHz ( DDR200 ) 
794                            0100: 266MHz ( DDR266 ) 
795                            0101: 333MHz ( DDR333 ) 
796                            0110: 400MHz ( DDR400 ) 
797                            0111: 533MHz ( DDR I/II 533 
798                            1000: 667MHz ( DDR I/II 667)
799                            Bit[3:0]  
800                            N:  Frame Buffer Size 2^N  MB 
801                          */
802                         u8 i;
803                         device_t dev;
804                         dev = dev_find_slot(0, PCI_DEVFN(0, 3));
805                         i = pci_read_config8(dev, 0xa1);
806                         i = (i & 0x70);
807                         i = i >> 4;
808                         if (i == 0) {
809                                 *eax = 0x00;    //not support 5f18
810                                 break;
811                         }
812                         i = i + 2;
813                         *ebx = (u32) i;
814                         i = pci_read_config8(dev, 0x90);
815                         i = (i & 0x07);
816                         i = i + 3;
817                         i = i << 4;
818                         *ebx = (*ebx) + ((u32) i);
819                         *eax = 0x5f;
820                         res = 0;
821                         break;
822                 }
823         case 0x5f00:
824                 *eax = 0x005f;
825                 res = 0;
826                 break;
827         case 0x5f01:
828                 *eax = 0x5f;
829                 *ecx = (*ecx & 0xffffff00) | 2; // panel type =  2 = 1024 * 768
830                 res = 0;
831                 break;
832         case 0x5f02:
833                 *eax = 0x5f;
834                 *ebx = (*ebx & 0xffff0000) | 2;
835                 *ecx = (*ecx & 0xffff0000) | 0x401;     // PAL + crt only 
836                 *edx = (*edx & 0xffff0000) | 0; // TV Layout - default
837                 res = 0;
838                 break;
839         case 0x5f0f:
840                 *eax = 0x005f;
841                 res = 0;
842                 break;
843         default:
844                 *eax = 0;
845                 break;
846         }
847         return res;
848 }