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 ! No timeout is used - if this hangs there is something wrong with
237 ! the machine, and we probably couldn't proceed anyway.
238 empty_8042:
239 .word 0x00eb,0x00eb
240 in al,#0x64 ! 8042 status port
241 test al,#2 ! is input buffer full?
242 jnz empty_8042 ! yes - loop
243 ret
244
245 getkey:
246 in al,#0x60 ! Quick and dirty...
247 .word 0x00eb,0x00eb ! jmp $+2, jmp $+2
248 mov bl,al
249 in al,#0x61
250 .word 0x00eb,0x00eb
251 mov ah,al
252 or al,#0x80
253 out #0x61,al
254 .word 0x00eb,0x00eb
255 mov al,ah
256 out #0x61,al
257 .word 0x00eb,0x00eb
258 mov al,bl
259 ret
260
261 ! Routine trying to recognize type of SVGA-board present (if any)
262 ! and if it recognize one gives the choices of resolution it offers.
263 ! If one is found the resolution chosen is given by al,ah (rows,cols).
264
265 chsvga: cld
266 push ds
267 push cs
268 mov ax,[0x01fa]
269 pop ds
270 mov modesave,ax
271 mov ax,#0xc000
272 mov es,ax
273 mov ax,modesave
274 cmp ax,#NORMAL_VGA
275 je defvga
276 cmp ax,#EXTENDED_VGA
277 je extvga
278 cmp ax,#ASK_VGA
279 jne svga
280 lea si,msg1
281 call prtstr
282 flush: in al,#0x60 ! Flush the keyboard buffer
283 cmp al,#0x82
284 jb nokey
285 jmp flush
286 nokey: call getkey
287 cmp al,#0x9c ! enter ?
288 je svga ! yes - svga selection
289 cmp al,#0xb9 ! space ?
290 jne nokey ! no - repeat
291 defvga: mov ax,#0x5019
292 pop ds
293 ret
294
295 extvga:
296 mov ax,#0x1112
297 mov bl,#0
298 int 0x10 ! use 8x8 font set (50 lines on VGA)
299 mov ax,#0x1200
300 mov bl,#0x20
301 int 0x10 ! use alternate print screen
302 mov ax,#0x1201
303 mov bl,#0x34
304 int 0x10 ! turn off cursor emulation
305 mov ah,#0x01
306 mov cx,#0x0607
307 int 0x10 ! turn on cursor (scan lines 6 to 7)
308 pop ds
309 mov ax,#0x5032 ! return 80x50
310 ret
311
312 svga: cld
313 lea si,idati ! Check ATI 'clues'
314 mov di,#0x31
315 mov cx,#0x09
316 repe
317 cmpsb
318 jne noati
319 lea si,dscati
320 lea di,moati
321 lea cx,selmod
322 jmp cx
323 noati: mov ax,#0x200f ! Check Ahead 'clues'
324 mov dx,#0x3ce
325 out dx,ax
326 inc dx
327 in al,dx
328 cmp al,#0x20
329 je isahed
330 cmp al,#0x21
331 jne noahed
332 isahed: lea si,dscahead
333 lea di,moahead
334 lea cx,selmod
335 jmp cx
336 noahed: mov dx,#0x3c3 ! Check Chips & Tech. 'clues'
337 in al,dx
338 or al,#0x10
339 out dx,al
340 mov dx,#0x104
341 in al,dx
342 mov bl,al
343 mov dx,#0x3c3
344 in al,dx
345 and al,#0xef
346 out dx,al
347 cmp bl,[idcandt]
348 jne nocant
349 lea si,dsccandt
350 lea di,mocandt
351 lea cx,selmod
352 jmp cx
353 nocant: mov dx,#0x3d4 ! Check Cirrus 'clues'
354 mov al,#0x0c
355 out dx,al
356 inc dx
357 in al,dx
358 mov bl,al
359 xor al,al
360 out dx,al
361 dec dx
362 mov al,#0x1f
363 out dx,al
364 inc dx
365 in al,dx
366 mov bh,al
367 xor ah,ah
368 shl al,#4
369 mov cx,ax
370 mov al,bh
371 shr al,#4
372 add cx,ax
373 shl cx,#8
374 add cx,#6
375 mov ax,cx
376 mov dx,#0x3c4
377 out dx,ax
378 inc dx
379 in al,dx
380 and al,al
381 jnz nocirr
382 mov al,bh
383 out dx,al
384 in al,dx
385 cmp al,#0x01
386 jne nocirr
387 call rst3d4
388 lea si,dsccirrus
389 lea di,mocirrus
390 lea cx,selmod
391 jmp cx
392 rst3d4: mov dx,#0x3d4
393 mov al,bl
394 xor ah,ah
395 shl ax,#8
396 add ax,#0x0c
397 out dx,ax
398 ret
399 nocirr: call rst3d4 ! Check Everex 'clues'
400 mov ax,#0x7000
401 xor bx,bx
402 int 0x10
403 cmp al,#0x70
404 jne noevrx
405 shr dx,#4
406 cmp dx,#0x678
407 je istrid
408 cmp dx,#0x236
409 je istrid
410 lea si,dsceverex
411 lea di,moeverex
412 lea cx,selmod
413 jmp cx
414 istrid: lea cx,ev2tri
415 jmp cx
416 noevrx: lea si,idgenoa ! Check Genoa 'clues'
417 xor ax,ax
418 seg es
419 mov al,[0x37]
420 mov di,ax
421 mov cx,#0x04
422 dec si
423 dec di
424 l1: inc si
425 inc di
426 mov al,(si)
427 seg es
428 and al,(di)
429 cmp al,(si)
430 loope l1
431 cmp cx,#0x00
432 jne nogen
433 lea si,dscgenoa
434 lea di,mogenoa
435 lea cx,selmod
436 jmp cx
437 nogen: cld
438 lea si,idoakvga
439 mov di,#0x08
440 mov cx,#0x08
441 repe
442 cmpsb
443 jne nooak
444 lea si,dscoakvga
445 lea di,mooakvga
446 lea cx,selmod
447 jmp cx
448 nooak: cld
449 lea si,idparadise ! Check Paradise 'clues'
450 mov di,#0x7d
451 mov cx,#0x04
452 repe
453 cmpsb
454 jne nopara
455 lea si,dscparadise
456 lea di,moparadise
457 lea cx,selmod
458 jmp cx
459 nopara: mov dx,#0x3c4 ! Check Trident 'clues'
460 mov al,#0x0e
461 out dx,al
462 inc dx
463 in al,dx
464 xchg ah,al
465 mov al,#0x00
466 out dx,al
467 in al,dx
468 xchg al,ah
469 mov bl,al ! Strange thing ... in the book this wasn't
470 and bl,#0x02 ! necessary but it worked on my card which
471 jz setb2 ! is a trident. Without it the screen goes
472 and al,#0xfd ! blurred ...
473 jmp clrb2 !
474 setb2: or al,#0x02 !
475 clrb2: out dx,al
476 and ah,#0x0f
477 cmp ah,#0x02
478 jne notrid
479 ev2tri: lea si,dsctrident
480 lea di,motrident
481 lea cx,selmod
482 jmp cx
483 notrid: mov dx,#0x3cd ! Check Tseng 'clues'
484 in al,dx ! Could things be this simple ! :-)
485 mov bl,al
486 mov al,#0x55
487 out dx,al
488 in al,dx
489 mov ah,al
490 mov al,bl
491 out dx,al
492 cmp ah,#0x55
493 jne notsen
494 lea si,dsctseng
495 lea di,motseng
496 lea cx,selmod
497 jmp cx
498 notsen: mov dx,#0x3cc ! Check Video7 'clues'
499 in al,dx
500 mov dx,#0x3b4
501 and al,#0x01
502 jz even7
503 mov dx,#0x3d4
504 even7: mov al,#0x0c
505 out dx,al
506 inc dx
507 in al,dx
508 mov bl,al
509 mov al,#0x55
510 out dx,al
511 in al,dx
512 dec dx
513 mov al,#0x1f
514 out dx,al
515 inc dx
516 in al,dx
517 mov bh,al
518 dec dx
519 mov al,#0x0c
520 out dx,al
521 inc dx
522 mov al,bl
523 out dx,al
524 mov al,#0x55
525 xor al,#0xea
526 cmp al,bh
527 jne novid7
528 lea si,dscvideo7
529 lea di,movideo7
530 selmod: push si
531 lea si,msg2
532 call prtstr
533 xor cx,cx
534 mov cl,(di)
535 pop si
536 push si
537 push cx
538 tbl: pop bx
539 push bx
540 mov al,bl
541 sub al,cl
542 call dprnt
543 call spcing
544 lodsw
545 xchg al,ah
546 call dprnt
547 xchg ah,al
548 push ax
549 mov al,#0x78
550 call prnt1
551 pop ax
552 call dprnt
553 call docr
554 loop tbl
555 pop cx
556 call docr
557 lea si,msg3
558 call prtstr
559 pop si
560 add cl,#0x80
561 mov ax,modesave
562 cmp ax,#ASK_VGA
563 je nonum
564 cmp ax,#NORMAL_VGA
565 jne gotmode
566 nonum: call getkey
567 cmp al,#0x82
568 jb nonum
569 cmp al,#0x8b
570 je zero
571 cmp al,cl
572 ja nonum
573 jmp nozero
574 zero: sub al,#0x0a
575 nozero: sub al,#0x80
576 dec al
577 gotmode: xor ah,ah
578 add di,ax
579 inc di
580 push ax
581 mov al,(di)
582 int 0x10
583 pop ax
584 shl ax,#1
585 add si,ax
586 lodsw
587 pop ds
588 ret
589 novid7:
590 br extvga
591
592 ! Routine that 'tabs' to next col.
593
594 spcing: mov al,#0x2e
595 call prnt1
596 mov al,#0x20
597 call prnt1
598 mov al,#0x20
599 call prnt1
600 mov al,#0x20
601 call prnt1
602 mov al,#0x20
603 call prnt1
604 ret
605
606 ! Routine to print asciiz-string at DS:SI
607
608 prtstr: lodsb
609 and al,al
610 jz fin
611 call prnt1
612 jmp prtstr
613 fin: ret
614
615 ! Routine to print a decimal value on screen, the value to be
616 ! printed is put in al (i.e 0-255).
617
618 dprnt: push ax
619 push cx
620 mov ah,#0x00
621 mov cl,#0x0a
622 idiv cl
623 cmp al,#0x09
624 jbe lt100
625 call dprnt
626 jmp skip10
627 lt100: add al,#0x30
628 call prnt1
629 skip10: mov al,ah
630 add al,#0x30
631 call prnt1
632 pop cx
633 pop ax
634 ret
635
636 ! Part of above routine, this one just prints ascii al
637
638 prnt1: push ax
639 push cx
640 mov bh,#0x00
641 mov cx,#0x01
642 mov ah,#0x0e
643 int 0x10
644 pop cx
645 pop ax
646 ret
647
648 ! Prints <CR> + <LF>
649
650 docr: push ax
651 push cx
652 mov bh,#0x00
653 mov ah,#0x0e
654 mov al,#0x0a
655 mov cx,#0x01
656 int 0x10
657 mov al,#0x0d
658 int 0x10
659 pop cx
660 pop ax
661 ret
662
663 gdt:
664 .word 0,0,0,0 ! dummy
665
666 .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
667 .word 0x0000 ! base address=0
668 .word 0x9A00 ! code read/exec
669 .word 0x00C0 ! granularity=4096, 386
670
671 .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
672 .word 0x0000 ! base address=0
673 .word 0x9200 ! data read/write
674 .word 0x00C0 ! granularity=4096, 386
675
676 idt_48:
677 .word 0 ! idt limit=0
678 .word 0,0 ! idt base=0L
679
680 gdt_48:
681 .word 0x800 ! gdt limit=2048, 256 GDT entries
682 .word 512+gdt,0x9 ! gdt base = 0X9xxxx
683
684 msg1: .ascii "Press <RETURN> to see SVGA-modes available or <SPACE> to continue."
685 db 0x0d, 0x0a, 0x0a, 0x00
686 msg2: .ascii "Mode: COLSxROWS:"
687 db 0x0d, 0x0a, 0x0a, 0x00
688 msg3: .ascii "Choose mode by pressing the corresponding number."
689 db 0x0d, 0x0a, 0x00
690
691 idati: .ascii "761295520"
692 idcandt: .byte 0xa5
693 idgenoa: .byte 0x77, 0x00, 0x66, 0x99
694 idparadise: .ascii "VGA="
695 idoakvga: .ascii "OAK VGA "
696
697 ! Manufacturer: Numofmodes: Mode:
698
699 moati: .byte 0x02, 0x23, 0x33
700 moahead: .byte 0x05, 0x22, 0x23, 0x24, 0x2f, 0x34
701 mocandt: .byte 0x02, 0x60, 0x61
702 mocirrus: .byte 0x04, 0x1f, 0x20, 0x22, 0x31
703 moeverex: .byte 0x0a, 0x03, 0x04, 0x07, 0x08, 0x0a, 0x0b, 0x16, 0x18, 0x21, 0x40
704 mogenoa: .byte 0x0a, 0x58, 0x5a, 0x60, 0x61, 0x62, 0x63, 0x64, 0x72, 0x74, 0x78
705 moparadise: .byte 0x02, 0x55, 0x54
706 motrident: .byte 0x07, 0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5a
707 motseng: .byte 0x05, 0x26, 0x2a, 0x23, 0x24, 0x22
708 movideo7: .byte 0x06, 0x40, 0x43, 0x44, 0x41, 0x42, 0x45
709 mooakvga: .byte 0x05, 0x00, 0x07, 0x4f, 0x50, 0x51
710
711 ! msb = Cols lsb = Rows:
712
713 dscati: .word 0x8419, 0x842c
714 dscahead: .word 0x842c, 0x8419, 0x841c, 0xa032, 0x5042
715 dsccandt: .word 0x8419, 0x8432
716 dsccirrus: .word 0x8419, 0x842c, 0x841e, 0x6425
717 dsceverex: .word 0x5022, 0x503c, 0x642b, 0x644b, 0x8419, 0x842c, 0x501e, 0x641b, 0xa040, 0x841e
718 dscgenoa: .word 0x5020, 0x642a, 0x8419, 0x841d, 0x8420, 0x842c, 0x843c, 0x503c, 0x5042, 0x644b
719 dscparadise: .word 0x8419, 0x842b
720 dsctrident: .word 0x501e, 0x502b, 0x503c, 0x8419, 0x841e, 0x842b, 0x843c
721 dsctseng: .word 0x503c, 0x6428, 0x8419, 0x841c, 0x842c
722 dscvideo7: .word 0x502b, 0x503c, 0x643c, 0x8419, 0x842c, 0x841c
723 dscoakvga: .word 0x2819, 0x5019, 0x843c, 0x8419, 0x842C
724 modesave: .word SVGA_MODE
725
726 .text
727 endtext:
728 .data
729 enddata:
730 .bss
731 endbss: