1 !
2 ! setup.S Copyright (C) 1991, 1992 Linus Torvalds
3 !
4 ! setup.s is responsible for getting the system data from the BIOS,
5 ! and putting them into the appropriate places in system memory.
6 ! both setup.s and system has been loaded by the bootblock.
7 !
8 ! This code asks the bios for memory/disk/other parameters, and
9 ! puts them in a "safe" place: 0x90000-0x901FF, ie where the
10 ! boot-block used to be. It is then up to the protected mode
11 ! system to read them from there before the area is overwritten
12 ! for buffer-blocks.
13 !
14 ! Move PS/2 aux init code to psaux.c
15 ! (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
16 !
17
18 ! NOTE! These had better be the same as in bootsect.s!
19 #include <linux/config.h>
20
21 #ifndef SVGA_MODE
22 #define SVGA_MODE ASK_VGA
23 #endif
24
25 INITSEG = DEF_INITSEG ! we move boot here - out of the way
26 SYSSEG = DEF_SYSSEG ! system loaded at 0x10000 (65536).
27 SETUPSEG = DEF_SETUPSEG ! this is the current segment
28
29 .globl begtext, begdata, begbss, endtext, enddata, endbss
30 .text
31 begtext:
32 .data
33 begdata:
34 .bss
35 begbss:
36 .text
37
38 entry start
39 start:
40
41 ! ok, the read went well so we get current cursor position and save it for
42 ! posterity.
43
44 mov ax,#INITSEG ! this is done in bootsect already, but...
45 mov ds,ax
46
47 ! Get memory size (extended mem, kB)
48
49 mov ah,#0x88
50 int 0x15
51 mov [2],ax
52
53 ! set the keyboard repeat rate to the max
54
55 mov ax,#0x0305
56 mov bx,#0x0000
57 int 0x16
58
59 ! check for EGA/VGA and some config parameters
60
61 mov ah,#0x12
62 mov bl,#0x10
63 int 0x10
64 mov [8],ax
65 mov [10],bx
66 mov [12],cx
67 mov ax,#0x5019
68 cmp bl,#0x10
69 je novga
70 mov ax,#0x1a00 ! Added check for EGA/VGA discrimination
71 int 0x10
72 mov bx,ax
73 mov ax,#0x5019
74 cmp bl,#0x1a ! 1a means VGA, anything else EGA or lower
75 jne novga
76 call chsvga
77 novga: mov [14],ax
78 mov ah,#0x03 ! read cursor pos
79 xor bh,bh
80 int 0x10 ! save it in known place, con_init fetches
81 mov [0],dx ! it from 0x90000.
82
83 ! Get video-card data:
84
85 mov ah,#0x0f
86 int 0x10
87 mov [4],bx ! bh = display page
88 mov [6],ax ! al = video mode, ah = window width
89
90 ! Get hd0 data
91
92 mov ax,#0x0000
93 mov ds,ax
94 lds si,[4*0x41]
95 mov ax,#INITSEG
96 mov es,ax
97 mov di,#0x0080
98 mov cx,#0x10
99 cld
100 rep
101 movsb
102
103 ! Get hd1 data
104
105 mov ax,#0x0000
106 mov ds,ax
107 lds si,[4*0x46]
108 mov ax,#INITSEG
109 mov es,ax
110 mov di,#0x0090
111 mov cx,#0x10
112 cld
113 rep
114 movsb
115
116 ! Check that there IS a hd1 :-)
117
118 mov ax,#0x01500
119 mov dl,#0x81
120 int 0x13
121 jc no_disk1
122 cmp ah,#3
123 je is_disk1
124 no_disk1:
125 mov ax,#INITSEG
126 mov es,ax
127 mov di,#0x0090
128 mov cx,#0x10
129 mov ax,#0x00
130 cld
131 rep
132 stosb
133 is_disk1:
134
135 ! check for PS/2 pointing device
136
137 mov ax,#INITSEG
138 mov ds,ax
139 mov [0x1ff],#0 ! default is no pointing device
140 int 0x11 ! int 0x11: equipment determination
141 test al,#0x04 ! check if pointing device installed
142 jz no_psmouse
143 mov [0x1ff],#0xaa ! device present
144 no_psmouse:
145
146 ! now we want to move to protected mode ...
147
148 cli ! no interrupts allowed !
149
150 ! first we move the system to it's rightful place
151
152 mov ax,#0x0000
153 cld ! 'direction'=0, movs moves forward
154 do_move:
155 mov es,ax ! destination segment
156 add ax,#0x1000
157 cmp ax,#0x9000
158 jz end_move
159 mov ds,ax ! source segment
160 sub di,di
161 sub si,si
162 mov cx,#0x8000
163 rep
164 movsw
165 jmp do_move
166
167 ! then we load the segment descriptors
168
169 end_move:
170 mov ax,#SETUPSEG ! right, forgot this at first. didn't work :-)
171 mov ds,ax
172 lidt idt_48 ! load idt with 0,0
173 lgdt gdt_48 ! load gdt with whatever appropriate
174
175 ! that was painless, now we enable A20
176
177 call empty_8042
178 mov al,#0xD1 ! command write
179 out #0x64,al
180 call empty_8042
181 mov al,#0xDF ! A20 on
182 out #0x60,al
183 call empty_8042
184
185 ! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
186 ! we put them right after the intel-reserved hardware interrupts, at
187 ! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
188 ! messed this up with the original PC, and they haven't been able to
189 ! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
190 ! which is used for the internal hardware interrupts as well. We just
191 ! have to reprogram the 8259's, and it isn't fun.
192
193 mov al,#0x11 ! initialization sequence
194 out #0x20,al ! send it to 8259A-1
195 .word 0x00eb,0x00eb ! jmp $+2, jmp $+2
196 out #0xA0,al ! and to 8259A-2
197 .word 0x00eb,0x00eb
198 mov al,#0x20 ! start of hardware int's (0x20)
199 out #0x21,al
200 .word 0x00eb,0x00eb
201 mov al,#0x28 ! start of hardware int's 2 (0x28)
202 out #0xA1,al
203 .word 0x00eb,0x00eb
204 mov al,#0x04 ! 8259-1 is master
205 out #0x21,al
206 .word 0x00eb,0x00eb
207 mov al,#0x02 ! 8259-2 is slave
208 out #0xA1,al
209 .word 0x00eb,0x00eb
210 mov al,#0x01 ! 8086 mode for both
211 out #0x21,al
212 .word 0x00eb,0x00eb
213 out #0xA1,al
214 .word 0x00eb,0x00eb
215 mov al,#0xFF ! mask off all interrupts for now
216 out #0xA1,al
217 .word 0x00eb,0x00eb
218 mov al,#0xFB ! mask all irq's but irq2 which
219 out #0x21,al ! is cascaded
220
221 ! well, that certainly wasn't fun :-(. Hopefully it works, and we don't
222 ! need no steenking BIOS anyway (except for the initial loading :-).
223 ! The BIOS-routine wants lots of unnecessary data, and it's less
224 ! "interesting" anyway. This is how REAL programmers do it.
225 !
226 ! Well, now's the time to actually move into protected mode. To make
227 ! things as simple as possible, we do no register set-up or anything,
228 ! we let the gnu-compiled 32-bit programs do that. We just jump to
229 ! absolute address 0x00000, in 32-bit protected mode.
230
231 mov ax,#0x0001 ! protected mode (PE) bit
232 lmsw ax ! This is it!
233 jmpi 0,8 ! jmp offset 0 of segment 8 (cs)
234
235 ! This routine checks that the keyboard command queue is empty
236 ! (after emptying the output buffers)
237 !
238 ! No timeout is used - if this hangs there is something wrong with
239 ! the machine, and we probably couldn't proceed anyway.
240 empty_8042:
241 .word 0x00eb,0x00eb
242 in al,#0x64 ! 8042 status port
243 test al,#1 ! output buffer?
244 jz no_output
245 .word 0x00eb,0x00eb
246 in al,#0x60 ! read it
247 jmp empty_8042
248 no_output:
249 test al,#2 ! is input buffer full?
250 jnz empty_8042 ! yes - loop
251 ret
252
253 getkey:
254 in al,#0x60 ! Quick and dirty...
255 .word 0x00eb,0x00eb ! jmp $+2, jmp $+2
256 ret
257
258 !
259 ! Flush the keyboard buffer
260 !
261 flush: in al,#0x60
262 .word 0x00eb,0x00eb
263 cmp al,#0x82
264 jae flush
265 ret
266
267 ! Routine trying to recognize type of SVGA-board present (if any)
268 ! and if it recognize one gives the choices of resolution it offers.
269 ! If one is found the resolution chosen is given by al,ah (rows,cols).
270
271 chsvga: cld
272 push ds
273 push cs
274 mov ax,[0x01fa]
275 pop ds
276 mov modesave,ax
277 mov ax,#0xc000
278 mov es,ax
279 mov ax,modesave
280 cmp ax,#NORMAL_VGA
281 je defvga
282 cmp ax,#EXTENDED_VGA
283 je extvga
284 cmp ax,#ASK_VGA
285 jne svga
286 lea si,msg1
287 call prtstr
288 call flush
289 nokey: call getkey
290 cmp al,#0x9c ! enter ?
291 je svga ! yes - svga selection
292 cmp al,#0xb9 ! space ?
293 jne nokey ! no - repeat
294 defvga: mov ax,#0x5019
295 pop ds
296 ret
297
298 extvga:
299 mov ax,#0x1112
300 mov bl,#0
301 int 0x10 ! use 8x8 font set (50 lines on VGA)
302 mov ax,#0x1200
303 mov bl,#0x20
304 int 0x10 ! use alternate print screen
305 mov ax,#0x1201
306 mov bl,#0x34
307 int 0x10 ! turn off cursor emulation
308 mov ah,#0x01
309 mov cx,#0x0607
310 int 0x10 ! turn on cursor (scan lines 6 to 7)
311 pop ds
312 mov ax,#0x5032 ! return 80x50
313 ret
314
315 svga: cld
316 lea si,idf1280 ! Check for Orchid F1280 (dingbat@diku.dk)
317 mov di,#0x10a ! id string is at c000:010a
318 mov cx,#0x21 ! length
319 repe
320 cmpsb
321 jne nf1280
322 lea si,dscf1280
323 lea di,mof1280
324 lea cx,selmod
325 jmp cx
326 nf1280: cld
327 lea si,idati ! Check ATI 'clues'
328 mov di,#0x31
329 mov cx,#0x09
330 repe
331 cmpsb
332 jne noati
333 lea si,dscati
334 lea di,moati
335 lea cx,selmod
336 jmp cx
337 noati: mov ax,#0x200f ! Check Ahead 'clues'
338 mov dx,#0x3ce
339 out dx,ax
340 inc dx
341 in al,dx
342 cmp al,#0x20
343 je isahed
344 cmp al,#0x21
345 jne noahed
346 isahed: lea si,dscahead
347 lea di,moahead
348 lea cx,selmod
349 jmp cx
350 noahed: mov dx,#0x3c3 ! Check Chips & Tech. 'clues'
351 in al,dx
352 or al,#0x10
353 out dx,al
354 mov dx,#0x104
355 in al,dx
356 mov bl,al
357 mov dx,#0x3c3
358 in al,dx
359 and al,#0xef
360 out dx,al
361 cmp bl,[idcandt]
362 jne nocant
363 lea si,dsccandt
364 lea di,mocandt
365 lea cx,selmod
366 jmp cx
367 nocant: mov dx,#0x3d4 ! Check Cirrus 'clues'
368 mov al,#0x0c
369 out dx,al
370 inc dx
371 in al,dx
372 mov bl,al
373 xor al,al
374 out dx,al
375 dec dx
376 mov al,#0x1f
377 out dx,al
378 inc dx
379 in al,dx
380 mov bh,al
381 xor ah,ah
382 shl al,#4
383 mov cx,ax
384 mov al,bh
385 shr al,#4
386 add cx,ax
387 shl cx,#8
388 add cx,#6
389 mov ax,cx
390 mov dx,#0x3c4
391 out dx,ax
392 inc dx
393 in al,dx
394 and al,al
395 jnz nocirr
396 mov al,bh
397 out dx,al
398 in al,dx
399 cmp al,#0x01
400 jne nocirr
401 call rst3d4
402 lea si,dsccirrus
403 lea di,mocirrus
404 lea cx,selmod
405 jmp cx
406 rst3d4: mov dx,#0x3d4
407 mov al,bl
408 xor ah,ah
409 shl ax,#8
410 add ax,#0x0c
411 out dx,ax
412 ret
413 nocirr: call rst3d4 ! Check Everex 'clues'
414 mov ax,#0x7000
415 xor bx,bx
416 int 0x10
417 cmp al,#0x70
418 jne noevrx
419 shr dx,#4
420 cmp dx,#0x678
421 je istrid
422 cmp dx,#0x236
423 je istrid
424 lea si,dsceverex
425 lea di,moeverex
426 lea cx,selmod
427 jmp cx
428 istrid: lea cx,ev2tri
429 jmp cx
430 noevrx: lea si,idgenoa ! Check Genoa 'clues'
431 xor ax,ax
432 seg es
433 mov al,[0x37]
434 mov di,ax
435 mov cx,#0x04
436 dec si
437 dec di
438 l1: inc si
439 inc di
440 mov al,(si)
441 seg es
442 and al,(di)
443 cmp al,(si)
444 loope l1
445 cmp cx,#0x00
446 jne nogen
447 lea si,dscgenoa
448 lea di,mogenoa
449 lea cx,selmod
450 jmp cx
451 nogen: cld
452 lea si,idoakvga
453 mov di,#0x08
454 mov cx,#0x08
455 repe
456 cmpsb
457 jne nooak
458 lea si,dscoakvga
459 lea di,mooakvga
460 lea cx,selmod
461 jmp cx
462 nooak: cld
463 lea si,idparadise ! Check Paradise 'clues'
464 mov di,#0x7d
465 mov cx,#0x04
466 repe
467 cmpsb
468 jne nopara
469 lea si,dscparadise
470 lea di,moparadise
471 lea cx,selmod
472 jmp cx
473 nopara: mov dx,#0x3c4 ! Check Trident 'clues'
474 mov al,#0x0e
475 out dx,al
476 inc dx
477 in al,dx
478 xchg ah,al
479 mov al,#0x00
480 out dx,al
481 in al,dx
482 xchg al,ah
483 mov bl,al ! Strange thing ... in the book this wasn't
484 and bl,#0x02 ! necessary but it worked on my card which
485 jz setb2 ! is a trident. Without it the screen goes
486 and al,#0xfd ! blurred ...
487 jmp clrb2 !
488 setb2: or al,#0x02 !
489 clrb2: out dx,al
490 and ah,#0x0f
491 cmp ah,#0x02
492 jne notrid
493 ev2tri: lea si,dsctrident
494 lea di,motrident
495 lea cx,selmod
496 jmp cx
497 notrid: mov dx,#0x3cd ! Check Tseng 'clues'
498 in al,dx ! Could things be this simple ! :-)
499 mov bl,al
500 mov al,#0x55
501 out dx,al
502 in al,dx
503 mov ah,al
504 mov al,bl
505 out dx,al
506 cmp ah,#0x55
507 jne notsen
508 lea si,dsctseng
509 lea di,motseng
510 lea cx,selmod
511 jmp cx
512 notsen: mov dx,#0x3cc ! Check Video7 'clues'
513 in al,dx
514 mov dx,#0x3b4
515 and al,#0x01
516 jz even7
517 mov dx,#0x3d4
518 even7: mov al,#0x0c
519 out dx,al
520 inc dx
521 in al,dx
522 mov bl,al
523 mov al,#0x55
524 out dx,al
525 in al,dx
526 dec dx
527 mov al,#0x1f
528 out dx,al
529 inc dx
530 in al,dx
531 mov bh,al
532 dec dx
533 mov al,#0x0c
534 out dx,al
535 inc dx
536 mov al,bl
537 out dx,al
538 mov al,#0x55
539 xor al,#0xea
540 cmp al,bh
541 jne novid7
542 lea si,dscvideo7
543 lea di,movideo7
544 selmod: push si
545 lea si,msg2
546 call prtstr
547 xor cx,cx
548 mov cl,(di)
549 pop si
550 push si
551 push cx
552 tbl: pop bx
553 push bx
554 mov al,bl
555 sub al,cl
556 call dprnt
557 call spcing
558 lodsw
559 xchg al,ah
560 call dprnt
561 xchg ah,al
562 push ax
563 mov al,#0x78
564 call prnt1
565 pop ax
566 call dprnt
567 call docr
568 loop tbl
569 pop cx
570 call docr
571 lea si,msg3
572 call prtstr
573 pop si
574 add cl,#0x80
575 mov ax,modesave
576 cmp ax,#ASK_VGA
577 je nonum
578 cmp ax,#NORMAL_VGA
579 jne gotmode
580 nonum: call getkey
581 cmp al,#0x82
582 jb nonum
583 cmp al,#0x8b
584 je zero
585 cmp al,cl
586 ja nonum
587 jmp nozero
588 zero: sub al,#0x0a
589 nozero: sub al,#0x80
590 dec al
591 gotmode: xor ah,ah
592 add di,ax
593 inc di
594 push ax
595 mov al,(di)
596 int 0x10
597 pop ax
598 shl ax,#1
599 add si,ax
600 lodsw
601 pop ds
602 ret
603 novid7:
604 br extvga
605
606 ! Routine that 'tabs' to next col.
607
608 spcing: mov al,#0x2e
609 call prnt1
610 mov al,#0x20
611 call prnt1
612 mov al,#0x20
613 call prnt1
614 mov al,#0x20
615 call prnt1
616 mov al,#0x20
617 call prnt1
618 ret
619
620 ! Routine to print asciiz-string at DS:SI
621
622 prtstr: lodsb
623 and al,al
624 jz fin
625 call prnt1
626 jmp prtstr
627 fin: ret
628
629 ! Routine to print a decimal value on screen, the value to be
630 ! printed is put in al (i.e 0-255).
631
632 dprnt: push ax
633 push cx
634 mov ah,#0x00
635 mov cl,#0x0a
636 idiv cl
637 cmp al,#0x09
638 jbe lt100
639 call dprnt
640 jmp skip10
641 lt100: add al,#0x30
642 call prnt1
643 skip10: mov al,ah
644 add al,#0x30
645 call prnt1
646 pop cx
647 pop ax
648 ret
649
650 ! Part of above routine, this one just prints ascii al
651
652 prnt1: push ax
653 push cx
654 mov bh,#0x00
655 mov cx,#0x01
656 mov ah,#0x0e
657 int 0x10
658 pop cx
659 pop ax
660 ret
661
662 ! Prints <CR> + <LF>
663
664 docr: push ax
665 push cx
666 mov bh,#0x00
667 mov ah,#0x0e
668 mov al,#0x0a
669 mov cx,#0x01
670 int 0x10
671 mov al,#0x0d
672 int 0x10
673 pop cx
674 pop ax
675 ret
676
677 gdt:
678 .word 0,0,0,0 ! dummy
679
680 .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
681 .word 0x0000 ! base address=0
682 .word 0x9A00 ! code read/exec
683 .word 0x00C0 ! granularity=4096, 386
684
685 .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
686 .word 0x0000 ! base address=0
687 .word 0x9200 ! data read/write
688 .word 0x00C0 ! granularity=4096, 386
689
690 idt_48:
691 .word 0 ! idt limit=0
692 .word 0,0 ! idt base=0L
693
694 gdt_48:
695 .word 0x800 ! gdt limit=2048, 256 GDT entries
696 .word 512+gdt,0x9 ! gdt base = 0X9xxxx
697
698 msg1: .ascii "Press <RETURN> to see SVGA-modes available or <SPACE> to continue."
699 db 0x0d, 0x0a, 0x0a, 0x00
700 msg2: .ascii "Mode: COLSxROWS:"
701 db 0x0d, 0x0a, 0x0a, 0x00
702 msg3: .ascii "Choose mode by pressing the corresponding number."
703 db 0x0d, 0x0a, 0x00
704
705 idati: .ascii "761295520"
706 idcandt: .byte 0xa5
707 idgenoa: .byte 0x77, 0x00, 0x66, 0x99
708 idparadise: .ascii "VGA="
709 idoakvga: .ascii "OAK VGA "
710 idf1280: .ascii "Orchid Technology Fahrenheit 1280"
711
712 ! Manufacturer: Numofmodes: Mode:
713
714 moati: .byte 0x02, 0x23, 0x33
715 moahead: .byte 0x05, 0x22, 0x23, 0x24, 0x2f, 0x34
716 mocandt: .byte 0x02, 0x60, 0x61
717 mocirrus: .byte 0x04, 0x1f, 0x20, 0x22, 0x31
718 moeverex: .byte 0x0a, 0x03, 0x04, 0x07, 0x08, 0x0a, 0x0b, 0x16, 0x18, 0x21, 0x40
719 mogenoa: .byte 0x0a, 0x58, 0x5a, 0x60, 0x61, 0x62, 0x63, 0x64, 0x72, 0x74, 0x78
720 moparadise: .byte 0x02, 0x55, 0x54
721 motrident: .byte 0x07, 0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5a
722 motseng: .byte 0x05, 0x26, 0x2a, 0x23, 0x24, 0x22
723 movideo7: .byte 0x06, 0x40, 0x43, 0x44, 0x41, 0x42, 0x45
724 mooakvga: .byte 0x05, 0x00, 0x07, 0x4f, 0x50, 0x51
725 mof1280: .byte 0x02, 0x54, 0x55
726
727 ! msb = Cols lsb = Rows:
728
729 dscati: .word 0x8419, 0x842c
730 dscahead: .word 0x842c, 0x8419, 0x841c, 0xa032, 0x5042
731 dsccandt: .word 0x8419, 0x8432
732 dsccirrus: .word 0x8419, 0x842c, 0x841e, 0x6425
733 dsceverex: .word 0x5022, 0x503c, 0x642b, 0x644b, 0x8419, 0x842c, 0x501e, 0x641b, 0xa040, 0x841e
734 dscgenoa: .word 0x5020, 0x642a, 0x8419, 0x841d, 0x8420, 0x842c, 0x843c, 0x503c, 0x5042, 0x644b
735 dscparadise: .word 0x8419, 0x842b
736 dsctrident: .word 0x501e, 0x502b, 0x503c, 0x8419, 0x841e, 0x842b, 0x843c
737 dsctseng: .word 0x503c, 0x6428, 0x8419, 0x841c, 0x842c
738 dscvideo7: .word 0x502b, 0x503c, 0x643c, 0x8419, 0x842c, 0x841c
739 dscoakvga: .word 0x2819, 0x5019, 0x843c, 0x8419, 0x842C
740 dscf1280: .word 0x842b, 0x8419
741 modesave: .word SVGA_MODE
742
743 .text
744 endtext:
745 .data
746 enddata:
747 .bss
748 endbss: