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#include <cbfs.h>
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76__asm__(
77
78 "gdtarg: \n"
79 " .word gdt_limit \n"
80 " .long gdt \n"
81
82 "__mygdt_limit = __mygdt_end - __mygdt - 1 \n"
83 "__mygdtaddr: \n"
84 " .word __mygdt_limit \n"
85 " .long __mygdt \n"
86 "__mygdt: \n"
87
88 " .word 0x0000, 0x0000 \n"
89 " .byte 0x00, 0x00, 0x00, 0x00 \n"
90
91 " .word 0x0000, 0x0000 \n"
92 " .byte 0x00, 0x00, 0x00, 0x00 \n"
93
94 " .word 0xffff, 0x0000 \n"
95 " .byte 0x00, 0x9b, 0xcf, 0x00 \n"
96
97 " .word 0xffff, 0x0000 \n"
98 " .byte 0x00, 0x93, 0xcf, 0x00 \n"
99
100 " .word 0x0000, 0x0000 \n"
101 " .byte 0x00, 0x00, 0x00, 0x00 \n"
102
103 " .word 0xffff, 0x0000 \n"
104 " .byte 0, 0x9a, 0, 0 \n"
105
106 " .word 0xffff, 0x0000 \n"
107 " .byte 0, 0x92, 0, 0 \n"
108 "__mygdt_end: \n");
109
110
111__asm__("__myidt: \n"
112
113 " .word 1023 \n"
114
115 " .long 0 \n" " .word 0 \n");
116
117
118extern u8 acpi_sleep_type;
119
120static void real_mode_switch_call_vga(unsigned long devfn)
121{
122 if ((acpi_sleep_type == 0))
123 return;
124 __asm__ __volatile__(
125
126
127 " pushal \n"
128
129 " mov %esp, __stack \n"
130 " jmp 1f \n"
131 "__stack: .long 0 \n" "1:\n"
132
133 " movl %esp, %ebp \n"
134 " movl 8(%ebp), %ecx \n"
135
136 " lgdt %cs:__mygdtaddr \n"
137
138 " ljmp $0x28, $__rms_16bit\n"
139 "__rms_16bit: \n"
140 " .code16 \n"
141
142
143
144
145 " mov $0x30, %ax \n"
146 " mov %ax, %ds \n"
147 " mov %ax, %es \n"
148 " mov %ax, %fs \n"
149 " mov %ax, %gs \n"
150 " mov %ax, %ss \n"
151
152 " movl %cr0, %eax \n"
153 " andl $0xFFFFFFFE, %eax \n"
154 " movl %eax, %cr0 \n"
155
156 " ljmp $0, $__rms_real\n"
157 "__rms_real: \n"
158
159
160
161
162 " mov $0x0, %ax \n"
163 " mov %ax, %ss \n"
164 " movl $0x1000, %eax \n"
165 " movl %eax, %esp \n"
166
167 " xor %ax, %ax \n"
168 " mov %ax, %ds \n"
169 " lidt __myidt \n"
170
171 " mov %ax, %es \n"
172 " mov %ax, %fs \n"
173 " mov %ax, %gs \n"
174 " mov $0x40, %ax \n"
175 " mov %ax, %ds \n"
176 " mov %cx, %ax \n"
177
178 " lcall $0xc000, $0x0003\n"
179
180
181 " movl %cr0, %eax \n" " orl $0x0000001, %eax\n"
182 " movl %eax, %cr0 \n"
183
184 " data32 ljmp $0x10, $vgarestart\n"
185 "vgarestart:\n"
186 " .code32\n"
187 " movw $0x18, %ax \n"
188 " mov %ax, %ds \n"
189 " mov %ax, %es \n"
190 " mov %ax, %fs \n"
191 " mov %ax, %gs \n"
192 " mov %ax, %ss \n"
193
194 " lgdt %cs:gdtarg \n"
195 " lidt idtarg \n"
196 ".globl vga_exit \n"
197 "vga_exit: \n"
198 " mov __stack, %esp \n"
199 " popal \n");
200}
201
202__asm__(".text\n" "real_mode_switch_end:\n");
203extern char real_mode_switch_end[];
204
205
206
207void vga_enable_console()
208{
209 if ((acpi_sleep_type == 0))
210 return;
211 __asm__ __volatile__(
212
213
214 " pushal \n"
215
216 " mov %esp, __stack \n"
217
218 " lgdt %cs:__mygdtaddr \n"
219
220 " ljmp $0x28, $__vga_ec_16bit\n"
221 "__vga_ec_16bit: \n"
222 " .code16 \n"
223
224
225
226
227 " mov $0x30, %ax \n"
228 " mov %ax, %ds \n"
229 " mov %ax, %es \n"
230 " mov %ax, %fs \n"
231 " mov %ax, %gs \n"
232 " mov %ax, %ss \n"
233
234 " movl %cr0, %eax \n"
235 " andl $0xFFFFFFFE, %eax\n"
236 " movl %eax, %cr0 \n"
237
238 " ljmp $0, $__vga_ec_real \n"
239 "__vga_ec_real: \n"
240
241
242
243
244 " mov $0x0, %ax \n"
245 " mov %ax, %ss \n"
246 " movl $0x1000, %eax \n"
247 " movl %eax, %esp \n"
248
249 " mov $0x11, %al \n"
250 " outb %al, $0x80 \n"
251
252 " xor %ax, %ax \n"
253 " mov %ax, %ds \n"
254 " lidt __myidt \n"
255
256 " mov %ax, %ds \n"
257 " mov %ax, %es \n"
258 " mov %ax, %fs \n"
259 " mov %ax, %gs \n"
260
261
262
263 " movw $0x4f14,%ax \n"
264 " movw $0x8003,%bx \n"
265 " movw $1, %cx \n"
266 " movw $0, %dx \n"
267 " movw $0, %di \n"
268 " int $0x10 \n"
269 " movb $0x55, %al \n"
270 " outb %al, $0x80 \n"
271
272
273 " movl %cr0, %eax \n" " orl $0x0000001, %eax\n"
274 " movl %eax, %cr0 \n"
275
276 " data32 ljmp $0x10, $vga_ec_restart\n"
277 "vga_ec_restart:\n"
278 " .code32\n"
279 " movw $0x18, %ax \n"
280 " mov %ax, %ds \n"
281 " mov %ax, %es \n"
282 " mov %ax, %fs \n"
283 " mov %ax, %gs \n"
284 " mov %ax, %ss \n"
285
286 " lgdt %cs:gdtarg \n"
287 " lidt idtarg \n"
288 " .globl vga__ec_exit \n"
289 "vga_ec_exit:\n"
290 " mov __stack, %esp \n"
291 " popal\n");
292}
293
294void do_vgabios(void)
295{
296 device_t dev;
297 unsigned long busdevfn;
298 unsigned int rom = 0;
299 unsigned char *buf;
300 unsigned int size = 64 * 1024;
301 int i;
302 u16 tmp;
303 u8 tmp8;
304
305 printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
306
307
308 for (i = 0x400; i < 0x500; i++) {
309 *(unsigned char *)i = 0;
310 }
311
312 dev = dev_find_class(PCI_CLASS_DISPLAY_VGA << 8, 0);
313
314 if (!dev) {
315 printk_debug("NO VGA FOUND\n");
316 return;
317 }
318 printk_debug("found VGA: vid=%x, did=%x\n", dev->vendor, dev->device);
319
320
321
322
323 rom = cbfs_load_optionrom(dev->vendor, dev->device, 0);
324 pci_write_config32(dev, PCI_ROM_ADDRESS, rom | 1);
325 printk_debug("rom base: %x\n", rom);
326 buf = (unsigned char *)rom;
327 printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
328
329 if ((buf[0] == 0x55) && (buf[1] == 0xaa)) {
330 memcpy((void *)0xc0000, buf, size);
331
332 printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
333
334 write_protect_vgabios();
335
336
337 buf = (unsigned char *)0xc0000;
338 if (buf[0] == 0x55 && buf[1] == 0xAA) {
339 busdevfn =
340 (dev->bus->secondary << 8) | dev->path.pci.devfn;
341 printk_debug("bus/devfn = %#x\n", busdevfn);
342 real_mode_switch_call_vga(busdevfn);
343 } else
344 printk_debug("Failed to copy VGA BIOS to 0xc0000\n");
345 } else
346 printk_debug("BAD SIGNATURE 0x%x 0x%x\n", buf[0], buf[1]);
347
348 printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
349
350 pci_write_config32(dev, PCI_ROM_ADDRESS, 0);
351}
352
353
354
355
356
357struct realidt {
358 unsigned short offset, cs;
359};
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376void handler(void)
377{
378 __asm__ __volatile__(" .code16 \n"
379 "idthandle: \n"
380 " pushal \n"
381 " movb $0, %al \n"
382 " ljmp $0, $callbiosint16\n"
383 "end_idthandle: \n"
384 " .code32 \n");
385}
386
387void debughandler(void)
388{
389 __asm__ __volatile__(" .code16 \n"
390 "debughandle: \n"
391 " pushw %cx \n"
392 " movw $250, %cx \n"
393 "dbh1: \n"
394 " loop dbh1 \n"
395 " popw %cx \n"
396 " iret \n"
397 "end_debughandle: \n" ".code32 \n");
398}
399
400
401
402
403
404
405
406void callbiosint(void)
407{
408 __asm__ __volatile__(" .code16 \n"
409 "callbiosint16: \n"
410 " push %ds \n"
411 " push %es \n"
412 " push %fs \n" " push %gs \n"
413
414
415 " andl $0xff, %eax\n"
416
417
418
419 " pushl %eax \n" " movl %cr0, %eax\n" " orl $0x00000001, %eax\n"
420 " movl %eax, %cr0\n"
421
422 " data32 ljmp $0x10, $biosprotect\n"
423 "biosprotect: \n"
424 " .code32 \n"
425 " movw $0x18, %ax \n"
426 " mov %ax, %ds \n"
427 " mov %ax, %es \n"
428 " mov %ax, %fs \n"
429 " mov %ax, %gs \n"
430 " mov %ax, %ss \n"
431 " lidt idtarg \n"
432 " call biosint \n"
433
434 " ljmp $0x28, $__rms_16bit2\n"
435 "__rms_16bit2: \n"
436 " .code16 \n"
437
438
439
440
441 " mov $0x30, %ax \n"
442 " mov %ax, %ds \n"
443 " mov %ax, %es \n"
444 " mov %ax, %fs \n"
445 " mov %ax, %gs \n"
446 " mov %ax, %ss \n"
447
448 " movl %cr0, %eax \n"
449 " andl $0xFFFFFFFE, %eax \n"
450 " movl %eax, %cr0 \n"
451
452 " ljmp $0, $__rms_real2 \n"
453 "__rms_real2: \n"
454
455
456 " mov $0x0, %ax \n"
457 " mov %ax, %ss \n"
458
459 " mov $0x11, %al \n"
460 " outb %al, $0x80 \n"
461
462 " xor %ax, %ax \n"
463 " mov %ax, %ds \n"
464 " lidt __myidt \n"
465
466 " mov %ax, %es \n"
467 " mov %ax, %fs \n"
468 " mov %ax, %gs \n"
469 " mov $0x40, %ax \n"
470 " mov %ax, %ds \n"
471
472 " popl %eax \n"
473 " pop %gs \n"
474 " pop %fs \n"
475 " pop %es \n"
476 " pop %ds \n"
477 " popal \n"
478 " iret \n"
479 " .code32 \n");
480}
481
482enum {
483 PCIBIOS = 0x1a,
484 MEMSIZE = 0x12
485};
486
487int pcibios(unsigned long *pedi, unsigned long *pesi, unsigned long *pebp,
488 unsigned long *pesp, unsigned long *pebx, unsigned long *pedx,
489 unsigned long *pecx, unsigned long *peax, unsigned long *pflags);
490
491int handleint21(unsigned long *pedi, unsigned long *pesi,
492 unsigned long *pebp, unsigned long *pesp,
493 unsigned long *pebx, unsigned long *pedx,
494 unsigned long *pecx, unsigned long *peax,
495 unsigned long *pflags);
496
497extern void vga_exit(void);
498
499int biosint(unsigned long intnumber,
500 unsigned long gsfs, unsigned long dses,
501 unsigned long edi, unsigned long esi,
502 unsigned long ebp, unsigned long esp,
503 unsigned long ebx, unsigned long edx,
504 unsigned long ecx, unsigned long eax,
505 unsigned long cs_ip, unsigned short stackflags)
506{
507 unsigned long ip;
508 unsigned long cs;
509 unsigned long flags;
510 int ret = -1;
511
512 ip = cs_ip & 0xffff;
513 cs = cs_ip >> 16;
514 flags = stackflags;
515
516 printk_debug("biosint: INT# 0x%lx\n", intnumber);
517 printk_debug("biosint: eax 0x%lx ebx 0x%lx ecx 0x%lx edx 0x%lx\n",
518 eax, ebx, ecx, edx);
519 printk_debug("biosint: ebp 0x%lx esp 0x%lx edi 0x%lx esi 0x%lx\n",
520 ebp, esp, edi, esi);
521 printk_debug("biosint: ip 0x%x cs 0x%x flags 0x%x\n",
522 ip, cs, flags);
523
524
525 switch (intnumber) {
526 case 0: case 1: case 2: case 3: case 4: case 5:
527 case 6: case 7: case 8: case 9: case 10:
528 case 11: case 12: case 13: case 14: case 15:
529
530 printk_info("biosint: Oops, exception %u\n", intnumber);
531 if (esp < 0x1000) {
532 printk_debug("Stack contents: ");
533 while (esp < 0x1000) {
534 printk_debug("0x%04x ", *(unsigned short *)esp);
535 esp += 2;
536 }
537 printk_debug("\n");
538 }
539 printk_debug("biosint: Bailing out\n");
540
541 if ((acpi_sleep_type == 3))
542 vga_exit();
543 break;
544
545 case PCIBIOS:
546 ret = pcibios(&edi, &esi, &ebp, &esp,
547 &ebx, &edx, &ecx, &eax, &flags);
548 break;
549 case MEMSIZE:
550
551 eax = 64 * 1024;
552 ret = 0;
553 break;
554 case 0x15:
555 ret = handleint21(&edi, &esi, &ebp, &esp,
556 &ebx, &edx, &ecx, &eax, &flags);
557 break;
558 default:
559 printk_info("BIOSINT: Unsupport int #0x%x\n", intnumber);
560 break;
561 }
562 if (ret)
563 flags |= 1;
564 else
565 flags &= ~1;
566 stackflags = flags;
567 return ret;
568}
569
570void setup_realmode_idt(void)
571{
572 extern unsigned char idthandle, end_idthandle;
573 extern unsigned char debughandle, end_debughandle;
574
575 int i;
576 struct realidt *idts = (struct realidt *)0;
577 int codesize = &end_idthandle - &idthandle;
578 unsigned char *intbyte, *codeptr;
579
580
581
582
583
584
585
586
587
588
589 for (i = 0; i < 256; i++) {
590 idts[i].cs = 0;
591 codeptr = (char *)4096 + i * codesize;
592 idts[i].offset = (unsigned)codeptr;
593 memcpy(codeptr, &idthandle, codesize);
594 intbyte = codeptr + 3;
595 *intbyte = i;
596 }
597
598
599
600
601
602
603
604 codeptr = (char *)0xff065;
605 memcpy(codeptr, &idthandle, codesize);
606 intbyte = codeptr + 3;
607 *intbyte = 0x42;
608
609
610
611
612
613 codeptr = (char *)0xff859;
614 memcpy(codeptr, &idthandle, codesize);
615 intbyte = codeptr + 3;
616 *intbyte = 0x15;
617
618
619
620 idts[1].cs = 0;
621 idts[1].offset = 16384;
622 memcpy(16384, &debughandle, &end_debughandle - &debughandle);
623
624}
625
626enum {
627 CHECK = 0xb001,
628 FINDDEV = 0xb102,
629 READCONFBYTE = 0xb108,
630 READCONFWORD = 0xb109,
631 READCONFDWORD = 0xb10a,
632 WRITECONFBYTE = 0xb10b,
633 WRITECONFWORD = 0xb10c,
634 WRITECONFDWORD = 0xb10d
635};
636
637
638
639enum {
640 PCIBIOS_NODEV = 0x8600,
641 PCIBIOS_BADREG = 0x8700
642};
643
644int
645pcibios(unsigned long *pedi, unsigned long *pesi, unsigned long *pebp,
646 unsigned long *pesp, unsigned long *pebx, unsigned long *pedx,
647 unsigned long *pecx, unsigned long *peax, unsigned long *pflags)
648{
649 unsigned long edi = *pedi;
650 unsigned long esi = *pesi;
651 unsigned long ebp = *pebp;
652 unsigned long esp = *pesp;
653 unsigned long ebx = *pebx;
654 unsigned long edx = *pedx;
655 unsigned long ecx = *pecx;
656 unsigned long eax = *peax;
657 unsigned long flags = *pflags;
658 unsigned short func = (unsigned short)eax;
659 int retval = 0;
660 unsigned short devid, vendorid, devfn;
661 short devindex;
662 unsigned char bus;
663 device_t dev;
664
665 switch (func) {
666 case CHECK:
667 *pedx = 0x4350;
668 *pecx = 0x2049;
669 retval = 0;
670 break;
671 case FINDDEV:
672 {
673 devid = *pecx;
674 vendorid = *pedx;
675 devindex = *pesi;
676 dev = 0;
677 while ((dev = dev_find_device(vendorid, devid, dev))) {
678 if (devindex <= 0)
679 break;
680 devindex--;
681 }
682 if (dev) {
683 unsigned short busdevfn;
684 *peax = 0;
685
686
687 busdevfn = (dev->bus->secondary << 8)
688 | (dev->path.pci.devfn & 0xff);
689 printk_debug("0x%x: return 0x%x\n", func,
690 busdevfn);
691 *pebx = busdevfn;
692 retval = 0;
693 } else {
694 *peax = PCIBIOS_NODEV;
695 retval = -1;
696 }
697 }
698 break;
699 case READCONFDWORD:
700 case READCONFWORD:
701 case READCONFBYTE:
702 case WRITECONFDWORD:
703 case WRITECONFWORD:
704 case WRITECONFBYTE:
705 {
706 unsigned long dword;
707 unsigned short word;
708 unsigned char byte;
709 unsigned char reg;
710
711 devfn = *pebx & 0xff;
712 bus = *pebx >> 8;
713 reg = *pedi;
714 dev = dev_find_slot(bus, devfn);
715 if (!dev) {
716 printk_debug
717 ("0x%x: BAD DEVICE bus %d devfn 0x%x\n",
718 func, bus, devfn);
719
720 *peax = PCIBIOS_BADREG;
721 retval = -1;
722 }
723 switch (func) {
724 case READCONFBYTE:
725 byte = pci_read_config8(dev, reg);
726 *pecx = byte;
727 break;
728 case READCONFWORD:
729 word = pci_read_config16(dev, reg);
730 *pecx = word;
731 break;
732 case READCONFDWORD:
733 dword = pci_read_config32(dev, reg);
734 *pecx = dword;
735 break;
736 case WRITECONFBYTE:
737 byte = *pecx;
738 pci_write_config8(dev, reg, byte);
739 break;
740 case WRITECONFWORD:
741 word = *pecx;
742 pci_write_config16(dev, reg, word);
743 break;
744 case WRITECONFDWORD:
745 dword = *pecx;
746 pci_write_config32(dev, reg, dword);
747 break;
748 }
749
750 if (retval)
751 retval = PCIBIOS_BADREG;
752 printk_debug
753 ("0x%x: bus %d devfn 0x%x reg 0x%x val 0x%lx\n",
754 func, bus, devfn, reg, *pecx);
755 *peax = 0;
756 retval = 0;
757 }
758 break;
759 default:
760 printk_err("UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func);
761 break;
762 }
763
764 return retval;
765}
766
767
768
769
770
771
772
773
774int handleint21(unsigned long *edi, unsigned long *esi, unsigned long *ebp,
775 unsigned long *esp, unsigned long *ebx, unsigned long *edx,
776 unsigned long *ecx, unsigned long *eax, unsigned long *flags)
777{
778 int res = -1;
779 switch (*eax & 0xffff) {
780 case 0x5f19:
781 *eax = 0x5f;
782 *ecx = 0x3;
783 res = 0;
784 break;
785 case 0x5f18:
786 {
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803 u8 i;
804 device_t dev;
805 dev = dev_find_slot(0, PCI_DEVFN(0, 3));
806 i = pci_read_config8(dev, 0xa1);
807 i = (i & 0x70);
808 i = i >> 4;
809 if (i == 0) {
810 *eax = 0x00;
811 break;
812 }
813 i = i + 2;
814 *ebx = (u32) i;
815 i = pci_read_config8(dev, 0x90);
816 i = (i & 0x07);
817 i = i + 3;
818 i = i << 4;
819 *ebx = (*ebx) + ((u32) i);
820 *eax = 0x5f;
821 res = 0;
822 break;
823 }
824 case 0x5f00:
825 *eax = 0x005f;
826 res = 0;
827 break;
828 case 0x5f01:
829 *eax = 0x5f;
830 *ecx = (*ecx & 0xffffff00) | 2;
831 res = 0;
832 break;
833 case 0x5f02:
834 *eax = 0x5f;
835 *ebx = (*ebx & 0xffff0000) | 2;
836 *ecx = (*ecx & 0xffff0000) | 0x401;
837 *edx = (*edx & 0xffff0000) | 0;
838 res = 0;
839 break;
840 case 0x5f0f:
841 *eax = 0x005f;
842 res = 0;
843 break;
844 default:
845 *eax = 0;
846 break;
847 }
848 return res;
849}
850