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