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 ! some changes and additional features by Christoph Niemann,
18 ! March 1993/June 1994 (Christoph.Niemann@linux.org)
19 !
20 ! add APM BIOS checking by Stephen Rothwell, May 1994
21 ! (Stephen.Rothwell@pd.necisa.oz.au)
22 !
23
24 ! NOTE! These had better be the same as in bootsect.s!
25 #define __ASSEMBLY__
26 #include <linux/config.h>
27 #include <asm/segment.h>
28
29 #ifndef SVGA_MODE
30 #define SVGA_MODE ASK_VGA
31 #endif
32
33 ! Signature words to ensure LILO loaded us right
34 #define SIG1 0xAA55
35 #define SIG2 0x5A5A
36
37 INITSEG = DEF_INITSEG ! we move boot here - out of the way
38 SYSSEG = DEF_SYSSEG ! system loaded at 0x10000 (65536).
39 SETUPSEG = DEF_SETUPSEG ! this is the current segment
40
41 .globl begtext, begdata, begbss, endtext, enddata, endbss
42 .text
43 begtext:
44 .data
45 begdata:
46 .bss
47 begbss:
48 .text
49
50 entry start
51 start:
52 ! Bootlin depends on this being done early
53 mov ax,#0x01500
54 mov dl,#0x81
55 int 0x13
56
57 ! Check signature at end of setup
58 mov ax,#SETUPSEG
59 mov ds,ax
60 cmp setup_sig1,#SIG1
61 jne bad_sig
62 cmp setup_sig2,#SIG2
63 jne bad_sig
64 jmp good_sig1
65
66 ! Routine to print asciiz-string at DS:SI
67
68 prtstr: lodsb
69 and al,al
70 jz fin
71 call prnt1
72 jmp prtstr
73 fin: ret
74
75 ! Part of above routine, this one just prints ascii al
76
77 prnt1: push ax
78 push cx
79 xor bh,bh
80 mov cx,#0x01
81 mov ah,#0x0e
82 int 0x10
83 pop cx
84 pop ax
85 ret
86
87 beep: mov al,#0x07
88 jmp prnt1
89
90 no_sig_mess: .ascii "No setup signature found ..."
91 db 0x00
92 start_sys_seg: .word SYSSEG
93
94 good_sig1:
95 jmp good_sig
96
97 ! We now have to find the rest of the setup code/data
98 bad_sig:
99 mov ax,#INITSEG
100 mov ds,ax
101 xor bh,bh
102 mov bl,[497] ! get setup sects from boot sector
103 sub bx,#4 ! LILO loads 4 sectors of setup
104 shl bx,#8 ! convert to words
105 mov cx,bx
106 shr bx,#3 ! convert to segment
107 add bx,#SYSSEG
108 seg cs
109 mov start_sys_seg,bx
110
111 ! Move rest of setup code/data to here
112 mov di,#2048 ! four sectors loaded by LILO
113 sub si,si
114 mov ax,#SETUPSEG
115 mov es,ax
116 mov ax,#SYSSEG
117 mov ds,ax
118 rep
119 movsw
120
121 mov ax,#SETUPSEG
122 mov ds,ax
123 cmp setup_sig1,#SIG1
124 jne no_sig
125 cmp setup_sig2,#SIG2
126 jne no_sig
127 jmp good_sig
128
129 no_sig:
130 lea si,no_sig_mess
131 call prtstr
132 no_sig_loop:
133 jmp no_sig_loop
134
135 good_sig:
136 mov ax,#INITSEG
137 mov ds,ax
138
139 ! Get memory size (extended mem, kB)
140
141 mov ah,#0x88
142 int 0x15
143 mov [2],ax
144
145 ! set the keyboard repeat rate to the max
146
147 mov ax,#0x0305
148 xor bx,bx ! clear bx
149 int 0x16
150
151 ! check for EGA/VGA and some config parameters
152
153 mov ah,#0x12
154 mov bl,#0x10
155 int 0x10
156 mov [8],ax
157 mov [10],bx
158 mov [12],cx
159 mov ax,#0x5019
160 cmp bl,#0x10
161 je novga
162 mov ax,#0x1a00 ! Added check for EGA/VGA discrimination
163 int 0x10
164 mov bx,ax
165 mov ax,#0x5019
166 movb [15],#0 ! by default, no VGA
167 cmp bl,#0x1a ! 1a means VGA, anything else EGA or lower
168 jne novga
169 movb [15],#1 ! we've detected a VGA
170 call chsvga
171 novga: mov [14],al
172 mov ah,#0x03 ! read cursor pos
173 xor bh,bh ! clear bh
174 int 0x10 ! save it in known place, con_init fetches
175 mov [0],dx ! it from 0x90000.
176
177 ! Get video-card data:
178
179 mov ah,#0x0f
180 int 0x10
181 mov [4],bx ! bh = display page
182 mov [6],ax ! al = video mode, ah = window width
183 xor ax,ax
184 mov es,ax ! Access low memory
185 seg es
186 mov ax,[0x485] ! POINTS - Height of character matrix
187 mov [16],ax
188
189 ! Get hd0 data
190
191 xor ax,ax ! clear ax
192 mov ds,ax
193 lds si,[4*0x41]
194 mov ax,#INITSEG
195 push ax
196 mov es,ax
197 mov di,#0x0080
198 mov cx,#0x10
199 push cx
200 cld
201 rep
202 movsb
203
204 ! Get hd1 data
205
206 xor ax,ax ! clear ax
207 mov ds,ax
208 lds si,[4*0x46]
209 pop cx
210 pop es
211 mov di,#0x0090
212 rep
213 movsb
214
215 ! Check that there IS a hd1 :-)
216
217 mov ax,#0x01500
218 mov dl,#0x81
219 int 0x13
220 jc no_disk1
221 cmp ah,#3
222 je is_disk1
223 no_disk1:
224 mov ax,#INITSEG
225 mov es,ax
226 mov di,#0x0090
227 mov cx,#0x10
228 xor ax,ax ! clear ax
229 cld
230 rep
231 stosb
232 is_disk1:
233
234 ! check for PS/2 pointing device
235
236 mov ax,#INITSEG
237 mov ds,ax
238 mov [0x1ff],#0 ! default is no pointing device
239 int 0x11 ! int 0x11: equipment determination
240 test al,#0x04 ! check if pointing device installed
241 jz no_psmouse
242 mov [0x1ff],#0xaa ! device present
243 no_psmouse:
244
245 #ifdef CONFIG_APM
246 ! check for APM BIOS
247
248 mov [64],#0 ! version == 0 means no APM BIOS
249
250 mov ax,#0x05300 ! APM BIOS installation check
251 xor bx,bx
252 int 0x15
253 jc done_apm_bios ! error -> no APM BIOS
254
255 cmp bx,#0x0504d ! check for "PM" signature
256 jne done_apm_bios ! no signature -> no APM BIOS
257
258 mov [64],ax ! record the APM BIOS version
259 mov [76],cx ! and flags
260 and cx,#0x02 ! Is 32 bit supported?
261 je done_apm_bios ! no ...
262
263 mov ax,#0x05304 ! Disconnect first just in case
264 xor bx,bx
265 int 0x15 ! ignore return code
266
267 mov ax,#0x05303 ! 32 bit connect
268 xor bx,bx
269 int 0x15
270 jc no_32_apm_bios ! error
271
272 mov [66],ax ! BIOS code segment
273 mov [68],ebx ! BIOS entry point offset
274 mov [72],cx ! BIOS 16 bit code segment
275 mov [74],dx ! BIOS data segment
276 mov [78],si ! BIOS code segment length
277 mov [80],di ! BIOS data segment length
278 jmp done_apm_bios
279
280 no_32_apm_bios:
281 and [76], #0xfffd ! remove 32 bit support bit
282
283 done_apm_bios:
284 #endif
285
286 ! now we want to move to protected mode ...
287
288 cli ! no interrupts allowed !
289 mov al,#0x80 ! disable NMI for the bootup sequence
290 out #0x70,al
291
292 ! first we move the system to its rightful place
293
294 mov ax,#0x100 ! start of destination segment
295 seg cs
296 mov bx,start_sys_seg ! start of source segment
297 cld ! 'direction'=0, movs moves forward
298 do_move:
299 mov es,ax ! destination segment
300 inc ah ! instead of add ax,#0x100
301 cmp ax,#0x9000
302 jz end_move
303 mov ds,bx ! source segment
304 add bx,#0x100
305 sub di,di
306 sub si,si
307 mov cx,#0x800
308 rep
309 movsw
310 jmp do_move
311
312 ! then we load the segment descriptors
313
314 end_move:
315 mov ax,#SETUPSEG ! right, forgot this at first. didn't work :-)
316 mov ds,ax
317 lidt idt_48 ! load idt with 0,0
318 lgdt gdt_48 ! load gdt with whatever appropriate
319
320 ! that was painless, now we enable A20
321
322 call empty_8042
323 mov al,#0xD1 ! command write
324 out #0x64,al
325 call empty_8042
326 mov al,#0xDF ! A20 on
327 out #0x60,al
328 call empty_8042
329
330 ! make sure any possible coprocessor is properly reset..
331
332 xor ax,ax
333 out #0xf0,al
334 call delay
335 out #0xf1,al
336 call delay
337
338 ! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
339 ! we put them right after the intel-reserved hardware interrupts, at
340 ! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
341 ! messed this up with the original PC, and they haven't been able to
342 ! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
343 ! which is used for the internal hardware interrupts as well. We just
344 ! have to reprogram the 8259's, and it isn't fun.
345
346 mov al,#0x11 ! initialization sequence
347 out #0x20,al ! send it to 8259A-1
348 call delay
349 out #0xA0,al ! and to 8259A-2
350 call delay
351 mov al,#0x20 ! start of hardware int's (0x20)
352 out #0x21,al
353 call delay
354 mov al,#0x28 ! start of hardware int's 2 (0x28)
355 out #0xA1,al
356 call delay
357 mov al,#0x04 ! 8259-1 is master
358 out #0x21,al
359 call delay
360 mov al,#0x02 ! 8259-2 is slave
361 out #0xA1,al
362 call delay
363 mov al,#0x01 ! 8086 mode for both
364 out #0x21,al
365 call delay
366 out #0xA1,al
367 call delay
368 mov al,#0xFF ! mask off all interrupts for now
369 out #0xA1,al
370 call delay
371 mov al,#0xFB ! mask all irq's but irq2 which
372 out #0x21,al ! is cascaded
373
374 ! well, that certainly wasn't fun :-(. Hopefully it works, and we don't
375 ! need no steenking BIOS anyway (except for the initial loading :-).
376 ! The BIOS-routine wants lots of unnecessary data, and it's less
377 ! "interesting" anyway. This is how REAL programmers do it.
378 !
379 ! Well, now's the time to actually move into protected mode. To make
380 ! things as simple as possible, we do no register set-up or anything,
381 ! we let the gnu-compiled 32-bit programs do that. We just jump to
382 ! absolute address 0x00000, in 32-bit protected mode.
383 !
384 ! Note that the short jump isn't strictly needed, although there are
385 ! reasons why it might be a good idea. It won't hurt in any case.
386 !
387 xor ax,ax
388 inc ax ! protected mode (PE) bit
389 lmsw ax ! This is it!
390 jmp flush_instr
391 flush_instr:
392 mov bx,#0 ! Flag to indicate a boot
393 jmpi 0x1000,KERNEL_CS ! jmp offset 1000 of segment 0x10 (cs)
394
395 ! This routine checks that the keyboard command queue is empty
396 ! (after emptying the output buffers)
397 !
398 ! No timeout is used - if this hangs there is something wrong with
399 ! the machine, and we probably couldn't proceed anyway.
400 empty_8042:
401 call delay
402 in al,#0x64 ! 8042 status port
403 test al,#1 ! output buffer?
404 jz no_output
405 call delay
406 in al,#0x60 ! read it
407 jmp empty_8042
408 no_output:
409 test al,#2 ! is input buffer full?
410 jnz empty_8042 ! yes - loop
411 ret
412 !
413 ! Read a key and return the (US-)ascii code in al, scan code in ah
414 !
415 getkey:
416 xor ah,ah
417 int 0x16
418 ret
419
420 !
421 ! Read a key with a timeout of 30 seconds. The cmos clock is used to get
422 ! the time.
423 !
424 getkt:
425 call gettime
426 add al,#30 ! wait 30 seconds
427 cmp al,#60
428 jl lminute
429 sub al,#60
430 lminute:
431 mov cl,al
432 again: mov ah,#0x01
433 int 0x16
434 jnz getkey ! key pressed, so get it
435 call gettime
436 cmp al,cl
437 jne again
438 mov al,#0x20 ! timeout, return default char `space'
439 ret
440
441 !
442 ! Flush the keyboard buffer
443 !
444 flush: mov ah,#0x01
445 int 0x16
446 jz empty
447 xor ah,ah
448 int 0x16
449 jmp flush
450 empty: ret
451
452 !
453 ! Read the cmos clock. Return the seconds in al
454 !
455 gettime:
456 push cx
457 mov ah,#0x02
458 int 0x1a
459 mov al,dh ! dh contains the seconds
460 and al,#0x0f
461 mov ah,dh
462 mov cl,#0x04
463 shr ah,cl
464 aad
465 pop cx
466 ret
467
468 !
469 ! Delay is needed after doing i/o
470 !
471 delay:
472 .word 0x00eb ! jmp $+2
473 ret
474
475 ! Routine trying to recognize type of SVGA-board present (if any)
476 ! and if it recognize one gives the choices of resolution it offers.
477 ! If one is found the resolution chosen is given by al,ah (rows,cols).
478
479 chsvga: cld
480 push ds
481 push cs
482 mov ax,[0x01fa]
483 pop ds
484 mov modesave,ax
485 mov ax,#0xc000
486 mov es,ax
487 mov ax,modesave
488 cmp ax,#NORMAL_VGA
489 je defvga
490 cmp ax,#EXTENDED_VGA
491 je vga50
492 cmp ax,#ASK_VGA
493 jne svga
494 lea si,msg1
495 call prtstr
496 call flush
497 nokey: call getkt
498 cmp al,#0x0d ! enter ?
499 je svga ! yes - svga selection
500 cmp al,#0x20 ! space ?
501 je defvga ! no - repeat
502 call beep
503 jmp nokey
504 defvga: mov ax,#0x5019
505 pop ds
506 ret
507
508 vga50:
509 mov ax,#0x1112
510 xor bl,bl
511 int 0x10 ! use 8x8 font set (50 lines on VGA)
512 mov ax,#0x1200
513 mov bl,#0x20
514 int 0x10 ! use alternate print screen
515 mov ax,#0x1201
516 mov bl,#0x34
517 int 0x10 ! turn off cursor emulation
518 mov ah,#0x01
519 mov cx,#0x0607
520 int 0x10 ! turn on cursor (scan lines 6 to 7)
521 pop ds
522 mov ax,#0x5032 ! return 80x50
523 ret
524
525 vga28:
526 pop ax ! clean the stack
527 mov ax,#0x1111
528 xor bl,bl
529 int 0x10 ! use 9x14 fontset (28 lines on VGA)
530 mov ah, #0x01
531 mov cx,#0x0b0c
532 int 0x10 ! turn on cursor (scan lines 11 to 12)
533 pop ds
534 mov ax,#0x501c ! return 80x28
535 ret
536
537 !
538 ! test for presence of an S3 VGA chip. The algorithm was taken
539 ! from the SuperProbe package of XFree86 1.2.1
540 ! report bugs to Christoph.Niemann@linux.org
541 !
542 svga: cld
543 mov cx,#0x0f35 ! we store some constants in cl/ch
544 mov dx,#0x03d4
545 movb al,#0x38
546 call inidx
547 mov bh,al ! store current value of CRT-register 0x38
548 mov ax,#0x0038
549 call outidx ! disable writing to special regs
550 movb al,cl ! check whether we can write special reg 0x35
551 call inidx
552 movb bl,al ! save the current value of CRT reg 0x35
553 andb al,#0xf0 ! clear bits 0-3
554 movb ah,al
555 movb al,cl ! and write it to CRT reg 0x35
556 call outidx
557 call inidx ! now read it back
558 andb al,ch ! clear the upper 4 bits
559 jz s3_2 ! the first test failed. But we have a
560 movb ah,bl ! second chance
561 mov al,cl
562 call outidx
563 jmp s3_1 ! do the other tests
564 s3_2: mov ax,cx ! load ah with 0xf and al with 0x35
565 orb ah,bl ! set the upper 4 bits of ah with the orig value
566 call outidx ! write ...
567 call inidx ! ... and reread
568 andb al,cl ! turn off the upper 4 bits
569 push ax
570 movb ah,bl ! restore old value in register 0x35
571 movb al,cl
572 call outidx
573 pop ax
574 cmp al,ch ! setting lower 4 bits was successful => bad
575 je no_s3 ! writing is allowed => this is not an S3
576 s3_1: mov ax,#0x4838 ! allow writing to special regs by putting
577 call outidx ! magic number into CRT-register 0x38
578 movb al,cl ! check whether we can write special reg 0x35
579 call inidx
580 movb bl,al
581 andb al,#0xf0
582 movb ah,al
583 movb al,cl
584 call outidx
585 call inidx
586 andb al,ch
587 jnz no_s3 ! no, we can't write => no S3
588 mov ax,cx
589 orb ah,bl
590 call outidx
591 call inidx
592 andb al,ch
593 push ax
594 movb ah,bl ! restore old value in register 0x35
595 movb al,cl
596 call outidx
597 pop ax
598 cmp al,ch
599 jne no_s31 ! writing not possible => no S3
600 movb al,#0x30
601 call inidx ! now get the S3 id ...
602 lea di,idS3
603 mov cx,#0x10
604 repne
605 scasb
606 je no_s31
607 lea si,dsc_S3 ! table of descriptions of video modes for BIOS
608 lea di,mo_S3 ! table of sizes of video modes for my BIOS
609 movb ah,bh
610 movb al,#0x38
611 call outidx ! restore old value of CRT register 0x38
612 br selmod ! go ask for video mode
613 no_s3: movb al,#0x35 ! restore CRT register 0x35
614 movb ah,bl
615 call outidx
616 no_s31: movb ah,bh
617 movb al,#0x38
618 call outidx ! restore old value of CRT register 0x38
619
620 lea si,idati ! Check ATI 'clues'
621 mov di,#0x31
622 mov cx,#0x09
623 repe
624 cmpsb
625 jne noati
626 lea si,dscati
627 lea di,moati
628 br selmod
629 noati: mov ax,#0x200f ! Check Ahead 'clues'
630 mov dx,#0x3ce
631 out dx,ax
632 inc dx
633 in al,dx
634 cmp al,#0x20
635 je isahed
636 cmp al,#0x21
637 jne noahed
638 isahed: lea si,dscahead
639 lea di,moahead
640 br selmod
641 noahed: mov dx,#0x3c3 ! Check Chips & Tech. 'clues'
642 in al,dx
643 or al,#0x10
644 out dx,al
645 mov dx,#0x104
646 in al,dx
647 mov bl,al
648 mov dx,#0x3c3
649 in al,dx
650 and al,#0xef
651 out dx,al
652 cmp bl,[idcandt]
653 jne nocant
654 lea si,dsccandt
655 lea di,mocandt
656 br selmod
657 nocant: mov dx,#0x3d4 ! Check Cirrus 'clues'
658 mov al,#0x0c
659 out dx,al
660 inc dx
661 in al,dx
662 mov bl,al
663 xor al,al
664 out dx,al
665 dec dx
666 mov al,#0x1f
667 out dx,al
668 inc dx
669 in al,dx
670 mov bh,al
671 xor ah,ah
672 shl al,#4
673 mov cx,ax
674 mov al,bh
675 shr al,#4
676 add cx,ax
677 shl cx,#8
678 add cx,#6
679 mov ax,cx
680 mov dx,#0x3c4
681 out dx,ax
682 inc dx
683 in al,dx
684 and al,al
685 jnz nocirr
686 mov al,bh
687 out dx,al
688 in al,dx
689 cmp al,#0x01
690 jne nocirr
691 call rst3d4
692 lea si,dsccirrus
693 lea di,mocirrus
694 br selmod
695 rst3d4: mov dx,#0x3d4
696 mov al,bl
697 xor ah,ah
698 shl ax,#8
699 add ax,#0x0c
700 out dx,ax
701 ret
702 nocirr: call rst3d4 ! Check Everex 'clues'
703 mov ax,#0x7000
704 xor bx,bx
705 int 0x10
706 cmp al,#0x70
707 jne noevrx
708 shr dx,#4
709 cmp dx,#0x678
710 je istrid
711 cmp dx,#0x236
712 je istrid
713 lea si,dsceverex
714 lea di,moeverex
715 br selmod
716 istrid: lea cx,ev2tri
717 jmp cx
718 noevrx: lea si,idgenoa ! Check Genoa 'clues'
719 xor ax,ax
720 seg es
721 mov al,[0x37]
722 mov di,ax
723 mov cx,#0x04
724 dec si
725 dec di
726 l1: inc si
727 inc di
728 mov al,(si)
729 test al,al
730 jz l2
731 seg es
732 cmp al,(di)
733 l2: loope l1
734 cmp cx,#0x00
735 jne nogen
736 lea si,dscgenoa
737 lea di,mogenoa
738 br selmod
739 nogen: cld
740 lea si,idoakvga
741 mov di,#0x08
742 mov cx,#0x08
743 repe
744 cmpsb
745 jne nooak
746 lea si,dscoakvga
747 lea di,mooakvga
748 br selmod
749 nooak: cld
750 lea si,idparadise ! Check Paradise 'clues'
751 mov di,#0x7d
752 mov cx,#0x04
753 repe
754 cmpsb
755 jne nopara
756 lea si,dscparadise
757 lea di,moparadise
758 br selmod
759 nopara: mov dx,#0x3c4 ! Check Trident 'clues'
760 mov al,#0x0e
761 out dx,al
762 inc dx
763 in al,dx
764 xchg ah,al
765 xor al,al
766 out dx,al
767 in al,dx
768 xchg al,ah
769 mov bl,al ! Strange thing ... in the book this wasn't
770 and bl,#0x02 ! necessary but it worked on my card which
771 jz setb2 ! is a trident. Without it the screen goes
772 and al,#0xfd ! blurred ...
773 jmp clrb2 !
774 setb2: or al,#0x02 !
775 clrb2: out dx,al
776 and ah,#0x0f
777 cmp ah,#0x02
778 jne notrid
779 ev2tri: lea si,dsctrident
780 lea di,motrident
781 jmp selmod
782 notrid: mov dx,#0x3cd ! Check Tseng 'clues'
783 in al,dx ! Could things be this simple ! :-)
784 mov bl,al
785 mov al,#0x55
786 out dx,al
787 in al,dx
788 mov ah,al
789 mov al,bl
790 out dx,al
791 cmp ah,#0x55
792 jne notsen
793 lea si,dsctseng
794 lea di,motseng
795 jmp selmod
796 notsen: mov dx,#0x3cc ! Check Video7 'clues'
797 in al,dx
798 mov dx,#0x3b4
799 and al,#0x01
800 jz even7
801 mov dx,#0x3d4
802 even7: mov al,#0x0c
803 out dx,al
804 inc dx
805 in al,dx
806 mov bl,al
807 mov al,#0x55
808 out dx,al
809 in al,dx
810 dec dx
811 mov al,#0x1f
812 out dx,al
813 inc dx
814 in al,dx
815 mov bh,al
816 dec dx
817 mov al,#0x0c
818 out dx,al
819 inc dx
820 mov al,bl
821 out dx,al
822 mov al,#0x55
823 xor al,#0xea
824 cmp al,bh
825 jne novid7
826 lea si,dscvideo7
827 lea di,movideo7
828 jmp selmod
829 novid7: lea si,dsunknown
830 lea di,mounknown
831 selmod: xor cx,cx
832 mov cl,(di)
833 mov ax,modesave
834 cmp ax,#ASK_VGA
835 je askmod
836 cmp ax,#NORMAL_VGA
837 je askmod
838 cmp al,cl
839 jl gotmode
840 push si
841 lea si,msg4
842 call prtstr
843 pop si
844 askmod: push si
845 lea si,msg2
846 call prtstr
847 pop si
848 push si
849 push cx
850 tbl: pop bx
851 push bx
852 mov al,bl
853 sub al,cl
854 call modepr
855 lodsw
856 xchg al,ah
857 call dprnt
858 xchg ah,al
859 push ax
860 mov al,#0x78
861 call prnt1
862 pop ax
863 call dprnt
864 push si
865 lea si,crlf ! print CR+LF
866 call prtstr
867 pop si
868 loop tbl
869 pop cx
870 lea si,msg3
871 call prtstr
872 pop si
873 add cl,#0x30
874 jmp nonum
875 nonumb: call beep
876 nonum: call getkey
877 cmp al,#0x30 ! ascii `0'
878 jb nonumb
879 cmp al,#0x3a ! ascii `9'
880 jbe number
881 cmp al,#0x61 ! ascii `a'
882 jb nonumb
883 cmp al,#0x7a ! ascii `z'
884 ja nonumb
885 sub al,#0x27
886 cmp al,cl
887 jae nonumb
888 sub al,#0x30
889 jmp gotmode
890 number: cmp al,cl
891 jae nonumb
892 sub al,#0x30
893 gotmode: xor ah,ah
894 or al,al
895 beq vga50
896 push ax
897 dec ax
898 beq vga28
899 add di,ax
900 mov al,(di)
901 int 0x10
902 pop ax
903 shl ax,#1
904 add si,ax
905 lodsw
906 pop ds
907 ret
908
909 ! Routine to write al into a VGA-register that is
910 ! accessed via an index register
911 !
912 ! dx contains the address of the index register
913 ! al contains the index
914 ! ah contains the value to write to the data register (dx + 1)
915 !
916 ! no registers are changed
917
918 outidx: out dx,al
919 push ax
920 mov al,ah
921 inc dx
922 out dx,al
923 dec dx
924 pop ax
925 ret
926 inidx: out dx,al
927 inc dx
928 in al,dx
929 dec dx
930 ret
931
932 ! Routine to print a decimal value on screen, the value to be
933 ! printed is put in al (i.e 0-255).
934
935 dprnt: push ax
936 push cx
937 xor ah,ah ! Clear ah
938 mov cl,#0x0a
939 idiv cl
940 cmp al,#0x09
941 jbe lt100
942 call dprnt
943 jmp skip10
944 lt100: add al,#0x30
945 call prnt1
946 skip10: mov al,ah
947 add al,#0x30
948 call prnt1
949 pop cx
950 pop ax
951 ret
952
953 !
954 ! Routine to print the mode number key on screen. Mode numbers
955 ! 0-9 print the ascii values `0' to '9', 10-35 are represented by
956 ! the letters `a' to `z'. This routine prints some spaces around the
957 ! mode no.
958 !
959
960 modepr: push ax
961 cmp al,#0x0a
962 jb digit ! Here is no check for number > 35
963 add al,#0x27
964 digit: add al,#0x30
965 mov modenr, al
966 push si
967 lea si, modestring
968 call prtstr
969 pop si
970 pop ax
971 ret
972
973 gdt:
974 .word 0,0,0,0 ! dummy
975
976 .word 0,0,0,0 ! unused
977
978 .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
979 .word 0x0000 ! base address=0
980 .word 0x9A00 ! code read/exec
981 .word 0x00C0 ! granularity=4096, 386
982
983 .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
984 .word 0x0000 ! base address=0
985 .word 0x9200 ! data read/write
986 .word 0x00C0 ! granularity=4096, 386
987
988 idt_48:
989 .word 0 ! idt limit=0
990 .word 0,0 ! idt base=0L
991
992 gdt_48:
993 .word 0x800 ! gdt limit=2048, 256 GDT entries
994 .word 512+gdt,0x9 ! gdt base = 0X9xxxx
995
996 msg1: .ascii "Press <RETURN> to see SVGA-modes available, <SPACE> to continue or wait 30 secs."
997 db 0x0d, 0x0a, 0x0a, 0x00
998 msg2: .ascii "Mode: COLSxROWS:"
999 db 0x0d, 0x0a, 0x0a, 0x00
1000 msg3: db 0x0d, 0x0a
1001 .ascii "Choose mode by pressing the corresponding number or letter."
1002 crlf: db 0x0d, 0x0a, 0x00
1003 msg4: .ascii "You passed an undefined mode number to setup. Please choose a new mode."
1004 db 0x0d, 0x0a, 0x0a, 0x07, 0x00
1005 modestring: .ascii " "
1006 modenr: db 0x00 ! mode number
1007 .ascii ": "
1008 db 0x00
1009
1010 idati: .ascii "761295520"
1011 idcandt: .byte 0xa5
1012 idgenoa: .byte 0x77, 0x00, 0x99, 0x66
1013 idparadise: .ascii "VGA="
1014 idoakvga: .ascii "OAK VGA "
1015 idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
1016 .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
1017
1018 ! Manufacturer: Numofmodes+2: Mode:
1019 ! Number of modes is the number of chip-specific svga modes plus the extended
1020 ! modes available on any vga (currently 2)
1021
1022 moati: .byte 0x06, 0x23, 0x33, 0x22, 0x21
1023 moahead: .byte 0x07, 0x22, 0x23, 0x24, 0x2f, 0x34
1024 mocandt: .byte 0x04, 0x60, 0x61
1025 mocirrus: .byte 0x06, 0x1f, 0x20, 0x22, 0x31
1026 moeverex: .byte 0x0c, 0x03, 0x04, 0x07, 0x08, 0x0a, 0x0b, 0x16, 0x18, 0x21, 0x40
1027 mogenoa: .byte 0x0c, 0x58, 0x5a, 0x60, 0x61, 0x62, 0x63, 0x64, 0x72, 0x74, 0x78
1028 moparadise: .byte 0x04, 0x55, 0x54
1029 motrident: .byte 0x09, 0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5a
1030 motseng: .byte 0x07, 0x26, 0x2a, 0x23, 0x24, 0x22
1031 movideo7: .byte 0x08, 0x40, 0x43, 0x44, 0x41, 0x42, 0x45
1032 mooakvga: .byte 0x08, 0x00, 0x07, 0x4e, 0x4f, 0x50, 0x51
1033 mo_S3: .byte 0x04, 0x54, 0x55
1034 mounknown: .byte 0x02
1035
1036 ! msb = Cols lsb = Rows:
1037 ! The first two modes are standard vga modes available on any vga.
1038 ! mode 0 is 80x50 and mode 1 is 80x28
1039
1040 dscati: .word 0x5032, 0x501c, 0x8419, 0x842c, 0x641e, 0x6419
1041 dscahead: .word 0x5032, 0x501c, 0x842c, 0x8419, 0x841c, 0xa032, 0x5042
1042 dsccandt: .word 0x5032, 0x501c, 0x8419, 0x8432
1043 dsccirrus: .word 0x5032, 0x501c, 0x8419, 0x842c, 0x841e, 0x6425
1044 dsceverex: .word 0x5032, 0x501c, 0x5022, 0x503c, 0x642b, 0x644b, 0x8419, 0x842c, 0x501e, 0x641b, 0xa040, 0x841e
1045 dscgenoa: .word 0x5032, 0x501c, 0x5020, 0x642a, 0x8419, 0x841d, 0x8420, 0x842c, 0x843c, 0x503c, 0x5042, 0x644b
1046 dscparadise: .word 0x5032, 0x501c, 0x8419, 0x842c
1047 dsctrident: .word 0x5032, 0x501c, 0x501e, 0x502b, 0x503c, 0x8419, 0x841e, 0x842b, 0x843c
1048 dsctseng: .word 0x5032, 0x501c, 0x503c, 0x6428, 0x8419, 0x841c, 0x842c
1049 dscvideo7: .word 0x5032, 0x501c, 0x502b, 0x503c, 0x643c, 0x8419, 0x842c, 0x841c
1050 dscoakvga: .word 0x5032, 0x501c, 0x2819, 0x5019, 0x503c, 0x843c, 0x8419, 0x842b
1051 dsc_S3: .word 0x5032, 0x501c, 0x842b, 0x8419
1052 dsunknown: .word 0x5032, 0x501c
1053 modesave: .word SVGA_MODE
1054
1055 ! This must be last
1056 setup_sig1: .word SIG1
1057 setup_sig2: .word SIG2
1058
1059 .text
1060 endtext:
1061 .data
1062 enddata:
1063 .bss
1064 endbss: