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 mov al,#0x80 ! disable NMI for the bootup sequence
150 out #0x70,al
151
152 ! first we move the system to it's rightful place
153
154 mov ax,#0x0000
155 cld ! 'direction'=0, movs moves forward
156 do_move:
157 mov es,ax ! destination segment
158 add ax,#0x1000
159 cmp ax,#0x9000
160 jz end_move
161 mov ds,ax ! source segment
162 sub di,di
163 sub si,si
164 mov cx,#0x8000
165 rep
166 movsw
167 jmp do_move
168
169 ! then we load the segment descriptors
170
171 end_move:
172 mov ax,#SETUPSEG ! right, forgot this at first. didn't work :-)
173 mov ds,ax
174 lidt idt_48 ! load idt with 0,0
175 lgdt gdt_48 ! load gdt with whatever appropriate
176
177 ! that was painless, now we enable A20
178
179 call empty_8042
180 mov al,#0xD1 ! command write
181 out #0x64,al
182 call empty_8042
183 mov al,#0xDF ! A20 on
184 out #0x60,al
185 call empty_8042
186
187 ! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
188 ! we put them right after the intel-reserved hardware interrupts, at
189 ! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
190 ! messed this up with the original PC, and they haven't been able to
191 ! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
192 ! which is used for the internal hardware interrupts as well. We just
193 ! have to reprogram the 8259's, and it isn't fun.
194
195 mov al,#0x11 ! initialization sequence
196 out #0x20,al ! send it to 8259A-1
197 .word 0x00eb,0x00eb ! jmp $+2, jmp $+2
198 out #0xA0,al ! and to 8259A-2
199 .word 0x00eb,0x00eb
200 mov al,#0x20 ! start of hardware int's (0x20)
201 out #0x21,al
202 .word 0x00eb,0x00eb
203 mov al,#0x28 ! start of hardware int's 2 (0x28)
204 out #0xA1,al
205 .word 0x00eb,0x00eb
206 mov al,#0x04 ! 8259-1 is master
207 out #0x21,al
208 .word 0x00eb,0x00eb
209 mov al,#0x02 ! 8259-2 is slave
210 out #0xA1,al
211 .word 0x00eb,0x00eb
212 mov al,#0x01 ! 8086 mode for both
213 out #0x21,al
214 .word 0x00eb,0x00eb
215 out #0xA1,al
216 .word 0x00eb,0x00eb
217 mov al,#0xFF ! mask off all interrupts for now
218 out #0xA1,al
219 .word 0x00eb,0x00eb
220 mov al,#0xFB ! mask all irq's but irq2 which
221 out #0x21,al ! is cascaded
222
223 ! well, that certainly wasn't fun :-(. Hopefully it works, and we don't
224 ! need no steenking BIOS anyway (except for the initial loading :-).
225 ! The BIOS-routine wants lots of unnecessary data, and it's less
226 ! "interesting" anyway. This is how REAL programmers do it.
227 !
228 ! Well, now's the time to actually move into protected mode. To make
229 ! things as simple as possible, we do no register set-up or anything,
230 ! we let the gnu-compiled 32-bit programs do that. We just jump to
231 ! absolute address 0x00000, in 32-bit protected mode.
232 !
233 ! Note that the short jump isn't strictly needed, althought there are
234 ! reasons why it might be a good idea. It won't hurt in any case.
235 !
236 mov ax,#0x0001 ! protected mode (PE) bit
237 lmsw ax ! This is it!
238 jmp flush_instr
239 flush_instr:
240 jmpi 0,8 ! jmp offset 0 of segment 8 (cs)
241
242 ! This routine checks that the keyboard command queue is empty
243 ! (after emptying the output buffers)
244 !
245 ! No timeout is used - if this hangs there is something wrong with
246 ! the machine, and we probably couldn't proceed anyway.
247 empty_8042:
248 .word 0x00eb,0x00eb
249 in al,#0x64 ! 8042 status port
250 test al,#1 ! output buffer?
251 jz no_output
252 .word 0x00eb,0x00eb
253 in al,#0x60 ! read it
254 jmp empty_8042
255 no_output:
256 test al,#2 ! is input buffer full?
257 jnz empty_8042 ! yes - loop
258 ret
259
260 getkey:
261 in al,#0x60 ! Quick and dirty...
262 .word 0x00eb,0x00eb ! jmp $+2, jmp $+2
263 ret
264
265 !
266 ! Flush the keyboard buffer
267 !
268 flush: call getkey
269 cmp al,#0x82
270 jae flush
271 ret
272
273 ! Routine trying to recognize type of SVGA-board present (if any)
274 ! and if it recognize one gives the choices of resolution it offers.
275 ! If one is found the resolution chosen is given by al,ah (rows,cols).
276
277 chsvga: cld
278 push ds
279 push cs
280 mov ax,[0x01fa]
281 pop ds
282 mov modesave,ax
283 mov ax,#0xc000
284 mov es,ax
285 mov ax,modesave
286 cmp ax,#NORMAL_VGA
287 je defvga
288 cmp ax,#EXTENDED_VGA
289 je extvga
290 cmp ax,#ASK_VGA
291 jne svga
292 lea si,msg1
293 call prtstr
294 call flush
295 nokey: call getkey
296 cmp al,#0x9c ! enter ?
297 je svga ! yes - svga selection
298 cmp al,#0xb9 ! space ?
299 jne nokey ! no - repeat
300 defvga: mov ax,#0x5019
301 pop ds
302 ret
303
304 extvga:
305 mov ax,#0x1112
306 mov bl,#0
307 int 0x10 ! use 8x8 font set (50 lines on VGA)
308 mov ax,#0x1200
309 mov bl,#0x20
310 int 0x10 ! use alternate print screen
311 mov ax,#0x1201
312 mov bl,#0x34
313 int 0x10 ! turn off cursor emulation
314 mov ah,#0x01
315 mov cx,#0x0607
316 int 0x10 ! turn on cursor (scan lines 6 to 7)
317 pop ds
318 mov ax,#0x5032 ! return 80x50
319 ret
320
321 svga: cld
322 lea si,idf1280 ! Check for Orchid F1280 (dingbat@diku.dk)
323 mov di,#0x10a ! id string is at c000:010a
324 mov cx,#0x21 ! length
325 repe
326 cmpsb
327 jne nf1280
328 lea si,dscf1280
329 lea di,mof1280
330 br selmod
331 nf1280: cld
332 lea si,idati ! Check ATI 'clues'
333 mov di,#0x31
334 mov cx,#0x09
335 repe
336 cmpsb
337 jne noati
338 lea si,dscati
339 lea di,moati
340 br selmod
341 noati: mov ax,#0x200f ! Check Ahead 'clues'
342 mov dx,#0x3ce
343 out dx,ax
344 inc dx
345 in al,dx
346 cmp al,#0x20
347 je isahed
348 cmp al,#0x21
349 jne noahed
350 isahed: lea si,dscahead
351 lea di,moahead
352 br selmod
353 noahed: mov dx,#0x3c3 ! Check Chips & Tech. 'clues'
354 in al,dx
355 or al,#0x10
356 out dx,al
357 mov dx,#0x104
358 in al,dx
359 mov bl,al
360 mov dx,#0x3c3
361 in al,dx
362 and al,#0xef
363 out dx,al
364 cmp bl,[idcandt]
365 jne nocant
366 lea si,dsccandt
367 lea di,mocandt
368 br selmod
369 nocant: mov dx,#0x3d4 ! Check Cirrus 'clues'
370 mov al,#0x0c
371 out dx,al
372 inc dx
373 in al,dx
374 mov bl,al
375 xor al,al
376 out dx,al
377 dec dx
378 mov al,#0x1f
379 out dx,al
380 inc dx
381 in al,dx
382 mov bh,al
383 xor ah,ah
384 shl al,#4
385 mov cx,ax
386 mov al,bh
387 shr al,#4
388 add cx,ax
389 shl cx,#8
390 add cx,#6
391 mov ax,cx
392 mov dx,#0x3c4
393 out dx,ax
394 inc dx
395 in al,dx
396 and al,al
397 jnz nocirr
398 mov al,bh
399 out dx,al
400 in al,dx
401 cmp al,#0x01
402 jne nocirr
403 call rst3d4
404 lea si,dsccirrus
405 lea di,mocirrus
406 br selmod
407 rst3d4: mov dx,#0x3d4
408 mov al,bl
409 xor ah,ah
410 shl ax,#8
411 add ax,#0x0c
412 out dx,ax
413 ret
414 nocirr: call rst3d4 ! Check Everex 'clues'
415 mov ax,#0x7000
416 xor bx,bx
417 int 0x10
418 cmp al,#0x70
419 jne noevrx
420 shr dx,#4
421 cmp dx,#0x678
422 je istrid
423 cmp dx,#0x236
424 je istrid
425 lea si,dsceverex
426 lea di,moeverex
427 br selmod
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 test al,al
442 jz l2
443 seg es
444 cmp al,(di)
445 l2: loope l1
446 cmp cx,#0x00
447 jne nogen
448 lea si,dscgenoa
449 lea di,mogenoa
450 br selmod
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 br selmod
461 nooak: cld
462 lea si,idparadise ! Check Paradise 'clues'
463 mov di,#0x7d
464 mov cx,#0x04
465 repe
466 cmpsb
467 jne nopara
468 lea si,dscparadise
469 lea di,moparadise
470 br selmod
471 nopara: mov dx,#0x3c4 ! Check Trident 'clues'
472 mov al,#0x0e
473 out dx,al
474 inc dx
475 in al,dx
476 xchg ah,al
477 mov al,#0x00
478 out dx,al
479 in al,dx
480 xchg al,ah
481 mov bl,al ! Strange thing ... in the book this wasn't
482 and bl,#0x02 ! necessary but it worked on my card which
483 jz setb2 ! is a trident. Without it the screen goes
484 and al,#0xfd ! blurred ...
485 jmp clrb2 !
486 setb2: or al,#0x02 !
487 clrb2: out dx,al
488 and ah,#0x0f
489 cmp ah,#0x02
490 jne notrid
491 ev2tri: lea si,dsctrident
492 lea di,motrident
493 jmp selmod
494 notrid: mov dx,#0x3cd ! Check Tseng 'clues'
495 in al,dx ! Could things be this simple ! :-)
496 mov bl,al
497 mov al,#0x55
498 out dx,al
499 in al,dx
500 mov ah,al
501 mov al,bl
502 out dx,al
503 cmp ah,#0x55
504 jne notsen
505 lea si,dsctseng
506 lea di,motseng
507 jmp selmod
508 notsen: mov dx,#0x3cc ! Check Video7 'clues'
509 in al,dx
510 mov dx,#0x3b4
511 and al,#0x01
512 jz even7
513 mov dx,#0x3d4
514 even7: mov al,#0x0c
515 out dx,al
516 inc dx
517 in al,dx
518 mov bl,al
519 mov al,#0x55
520 out dx,al
521 in al,dx
522 dec dx
523 mov al,#0x1f
524 out dx,al
525 inc dx
526 in al,dx
527 mov bh,al
528 dec dx
529 mov al,#0x0c
530 out dx,al
531 inc dx
532 mov al,bl
533 out dx,al
534 mov al,#0x55
535 xor al,#0xea
536 cmp al,bh
537 jne novid7
538 lea si,dscvideo7
539 lea di,movideo7
540 selmod: push si
541 lea si,msg2
542 call prtstr
543 xor cx,cx
544 mov cl,(di)
545 pop si
546 push si
547 push cx
548 tbl: pop bx
549 push bx
550 mov al,bl
551 sub al,cl
552 call dprnt
553 call spcing
554 lodsw
555 xchg al,ah
556 call dprnt
557 xchg ah,al
558 push ax
559 mov al,#0x78
560 call prnt1
561 pop ax
562 call dprnt
563 call docr
564 loop tbl
565 pop cx
566 call docr
567 lea si,msg3
568 call prtstr
569 pop si
570 add cl,#0x80
571 mov ax,modesave
572 cmp ax,#ASK_VGA
573 je nonum
574 cmp ax,#NORMAL_VGA
575 jne gotmode
576 nonum: call getkey
577 cmp al,#0x82
578 jb nonum
579 cmp al,#0x8b
580 je zero
581 cmp al,cl
582 ja nonum
583 jmp nozero
584 zero: sub al,#0x0a
585 nozero: sub al,#0x80
586 dec al
587 gotmode: xor ah,ah
588 add di,ax
589 inc di
590 push ax
591 mov al,(di)
592 int 0x10
593 pop ax
594 shl ax,#1
595 add si,ax
596 lodsw
597 pop ds
598 ret
599 novid7:
600 br extvga
601
602 ! Routine that 'tabs' to next col.
603
604 spcing: mov al,#0x2e
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 mov al,#0x20
613 call prnt1
614 ret
615
616 ! Routine to print asciiz-string at DS:SI
617
618 prtstr: lodsb
619 and al,al
620 jz fin
621 call prnt1
622 jmp prtstr
623 fin: ret
624
625 ! Routine to print a decimal value on screen, the value to be
626 ! printed is put in al (i.e 0-255).
627
628 dprnt: push ax
629 push cx
630 mov ah,#0x00
631 mov cl,#0x0a
632 idiv cl
633 cmp al,#0x09
634 jbe lt100
635 call dprnt
636 jmp skip10
637 lt100: add al,#0x30
638 call prnt1
639 skip10: mov al,ah
640 add al,#0x30
641 call prnt1
642 pop cx
643 pop ax
644 ret
645
646 ! Part of above routine, this one just prints ascii al
647
648 prnt1: push ax
649 push cx
650 mov bh,#0x00
651 mov cx,#0x01
652 mov ah,#0x0e
653 int 0x10
654 pop cx
655 pop ax
656 ret
657
658 ! Prints <CR> + <LF>
659
660 docr: push ax
661 push cx
662 mov bh,#0x00
663 mov ah,#0x0e
664 mov al,#0x0a
665 mov cx,#0x01
666 int 0x10
667 mov al,#0x0d
668 int 0x10
669 pop cx
670 pop ax
671 ret
672
673 gdt:
674 .word 0,0,0,0 ! dummy
675
676 .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
677 .word 0x0000 ! base address=0
678 .word 0x9A00 ! code read/exec
679 .word 0x00C0 ! granularity=4096, 386
680
681 .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
682 .word 0x0000 ! base address=0
683 .word 0x9200 ! data read/write
684 .word 0x00C0 ! granularity=4096, 386
685
686 idt_48:
687 .word 0 ! idt limit=0
688 .word 0,0 ! idt base=0L
689
690 gdt_48:
691 .word 0x800 ! gdt limit=2048, 256 GDT entries
692 .word 512+gdt,0x9 ! gdt base = 0X9xxxx
693
694 msg1: .ascii "Press <RETURN> to see SVGA-modes available or <SPACE> to continue."
695 db 0x0d, 0x0a, 0x0a, 0x00
696 msg2: .ascii "Mode: COLSxROWS:"
697 db 0x0d, 0x0a, 0x0a, 0x00
698 msg3: .ascii "Choose mode by pressing the corresponding number."
699 db 0x0d, 0x0a, 0x00
700
701 idati: .ascii "761295520"
702 idcandt: .byte 0xa5
703 idgenoa: .byte 0x77, 0x00, 0x99, 0x66
704 idparadise: .ascii "VGA="
705 idoakvga: .ascii "OAK VGA "
706 idf1280: .ascii "Orchid Technology Fahrenheit 1280"
707
708 ! Manufacturer: Numofmodes: Mode:
709
710 moati: .byte 0x02, 0x23, 0x33
711 moahead: .byte 0x05, 0x22, 0x23, 0x24, 0x2f, 0x34
712 mocandt: .byte 0x02, 0x60, 0x61
713 mocirrus: .byte 0x04, 0x1f, 0x20, 0x22, 0x31
714 moeverex: .byte 0x0a, 0x03, 0x04, 0x07, 0x08, 0x0a, 0x0b, 0x16, 0x18, 0x21, 0x40
715 mogenoa: .byte 0x0a, 0x58, 0x5a, 0x60, 0x61, 0x62, 0x63, 0x64, 0x72, 0x74, 0x78
716 moparadise: .byte 0x02, 0x55, 0x54
717 motrident: .byte 0x07, 0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5a
718 motseng: .byte 0x05, 0x26, 0x2a, 0x23, 0x24, 0x22
719 movideo7: .byte 0x06, 0x40, 0x43, 0x44, 0x41, 0x42, 0x45
720 mooakvga: .byte 0x05, 0x00, 0x07, 0x4f, 0x50, 0x51
721 mof1280: .byte 0x02, 0x54, 0x55
722
723 ! msb = Cols lsb = Rows:
724
725 dscati: .word 0x8419, 0x842c
726 dscahead: .word 0x842c, 0x8419, 0x841c, 0xa032, 0x5042
727 dsccandt: .word 0x8419, 0x8432
728 dsccirrus: .word 0x8419, 0x842c, 0x841e, 0x6425
729 dsceverex: .word 0x5022, 0x503c, 0x642b, 0x644b, 0x8419, 0x842c, 0x501e, 0x641b, 0xa040, 0x841e
730 dscgenoa: .word 0x5020, 0x642a, 0x8419, 0x841d, 0x8420, 0x842c, 0x843c, 0x503c, 0x5042, 0x644b
731 dscparadise: .word 0x8419, 0x842b
732 dsctrident: .word 0x501e, 0x502b, 0x503c, 0x8419, 0x841e, 0x842b, 0x843c
733 dsctseng: .word 0x503c, 0x6428, 0x8419, 0x841c, 0x842c
734 dscvideo7: .word 0x502b, 0x503c, 0x643c, 0x8419, 0x842c, 0x841c
735 dscoakvga: .word 0x2819, 0x5019, 0x843c, 0x8419, 0x842C
736 dscf1280: .word 0x842b, 0x8419
737 modesave: .word SVGA_MODE
738
739 .text
740 endtext:
741 .data
742 enddata:
743 .bss
744 endbss: