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