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 15 ! NOTE! These had better be the same as in bootsect.s! 16 #include <linux/config.h> 17 #define NORMAL_VGA 0xffff 18 19 INITSEG = DEF_INITSEG ! we move boot here - out of the way 20 SYSSEG = DEF_SYSSEG ! system loaded at 0x10000 (65536). 21 SETUPSEG = DEF_SETUPSEG ! this is the current segment 22 23 .globl begtext, begdata, begbss, endtext, enddata, endbss 24 .text 25 begtext: 26 .data 27 begdata: 28 .bss 29 begbss: 30 .text 31 32 entry start 33 start: 34 35 ! ok, the read went well so we get current cursor position and save it for 36 ! posterity. 37 38 mov ax,#INITSEG ! this is done in bootsect already, but... 39 mov ds,ax 40 41 ! Get memory size (extended mem, kB) 42 43 mov ah,#0x88 44 int 0x15 45 mov [2],ax 46 47 ! set the keyboard repeat rate to the max 48 49 mov ax,#0x0305 50 mov bx,#0x0000 51 int 0x16 52 53 ! check for EGA/VGA and some config parameters 54 55 mov ah,#0x12 56 mov bl,#0x10 57 int 0x10 58 mov [8],ax 59 mov [10],bx 60 mov [12],cx 61 mov ax,#0x5019 62 cmp bl,#0x10 63 je novga 64 mov ax,#0x1a00 ! Added check for EGA/VGA discrimination 65 int 0x10 66 mov bx,ax 67 mov ax,#0x5019 68 cmp bl,#0x1a ! 1a means VGA, anything else EGA or lower 69 jne novga 70 call chsvga 71 novga: mov [14],ax 72 mov ah,#0x03 ! read cursor pos 73 xor bh,bh 74 int 0x10 ! save it in known place, con_init fetches 75 mov [0],dx ! it from 0x90000. 76 77 ! Get video-card data: 78 79 mov ah,#0x0f 80 int 0x10 81 mov [4],bx ! bh = display page 82 mov [6],ax ! al = video mode, ah = window width 83 84 ! Get hd0 data 85 86 mov ax,#0x0000 87 mov ds,ax 88 lds si,[4*0x41] 89 mov ax,#INITSEG 90 mov es,ax 91 mov di,#0x0080 92 mov cx,#0x10 93 cld 94 rep 95 movsb 96 97 ! Get hd1 data 98 99 mov ax,#0x0000 100 mov ds,ax 101 lds si,[4*0x46] 102 mov ax,#INITSEG 103 mov es,ax 104 mov di,#0x0090 105 mov cx,#0x10 106 cld 107 rep 108 movsb 109 110 ! Check that there IS a hd1 :-) 111 112 mov ax,#0x01500 113 mov dl,#0x81 114 int 0x13 115 jc no_disk1 116 cmp ah,#3 117 je is_disk1 118 no_disk1: 119 mov ax,#INITSEG 120 mov es,ax 121 mov di,#0x0090 122 mov cx,#0x10 123 mov ax,#0x00 124 cld 125 rep 126 stosb 127 is_disk1: 128 129 ! check for PS/2 pointing device 130 131 mov ax,#INITSEG 132 mov ds,ax 133 mov [0x1ff],#0 ! default is no pointing device 134 int 0x11 ! int 0x11: equipment determination 135 test al,#0x04 ! check if pointing device installed 136 jz no_psmouse 137 mov ax,#0xc201 ! reset pointing device 138 int 0x15 139 jc no_psmouse 140 mov bh,#0x03 ! 3 bytes/packet 141 mov ax,#0xc205 ! initialize pointing device 142 int 0x15 143 jc no_psmouse 144 mov ax,#0xc203 ! set resolution 145 mov bh,#0x03 ! 8 counts/mm 146 int 0x15 147 jc no_psmouse 148 mov ax,#0xc206 ! set scaling 149 mov bh,0x02 ! 2:1 scaling 150 int 0x15 151 jc no_psmouse 152 mov ax,#0xc202 ! set sample rate 153 mov bh,#0x05 ! 100 reports per second 154 int 0x15 155 jc no_psmouse 156 mov bh,#0x01 157 mov ax,#0xc200 ! enable pointing device 158 int 0x15 159 jc no_psmouse 160 mov [0x1ff],#0xaa ! device present 161 no_psmouse: 162 163 ! now we want to move to protected mode ... 164 165 cli ! no interrupts allowed ! 166 167 ! first we move the system to it's rightful place 168 169 mov ax,#0x0000 170 cld ! 'direction'=0, movs moves forward 171 do_move: 172 mov es,ax ! destination segment 173 add ax,#0x1000 174 cmp ax,#0x9000 175 jz end_move 176 mov ds,ax ! source segment 177 sub di,di 178 sub si,si 179 mov cx,#0x8000 180 rep 181 movsw 182 jmp do_move 183 184 ! then we load the segment descriptors 185 186 end_move: 187 mov ax,#SETUPSEG ! right, forgot this at first. didn't work :-) 188 mov ds,ax 189 lidt idt_48 ! load idt with 0,0 190 lgdt gdt_48 ! load gdt with whatever appropriate 191 192 ! that was painless, now we enable A20 193 194 call empty_8042 195 mov al,#0xD1 ! command write 196 out #0x64,al 197 call empty_8042 198 mov al,#0xDF ! A20 on 199 out #0x60,al 200 call empty_8042 201 202 ! well, that went ok, I hope. Now we have to reprogram the interrupts :-( 203 ! we put them right after the intel-reserved hardware interrupts, at 204 ! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really 205 ! messed this up with the original PC, and they haven't been able to 206 ! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f, 207 ! which is used for the internal hardware interrupts as well. We just 208 ! have to reprogram the 8259's, and it isn't fun. 209 210 mov al,#0x11 ! initialization sequence 211 out #0x20,al ! send it to 8259A-1 212 .word 0x00eb,0x00eb ! jmp $+2, jmp $+2 213 out #0xA0,al ! and to 8259A-2 214 .word 0x00eb,0x00eb 215 mov al,#0x20 ! start of hardware int's (0x20) 216 out #0x21,al 217 .word 0x00eb,0x00eb 218 mov al,#0x28 ! start of hardware int's 2 (0x28) 219 out #0xA1,al 220 .word 0x00eb,0x00eb 221 mov al,#0x04 ! 8259-1 is master 222 out #0x21,al 223 .word 0x00eb,0x00eb 224 mov al,#0x02 ! 8259-2 is slave 225 out #0xA1,al 226 .word 0x00eb,0x00eb 227 mov al,#0x01 ! 8086 mode for both 228 out #0x21,al 229 .word 0x00eb,0x00eb 230 out #0xA1,al 231 .word 0x00eb,0x00eb 232 mov al,#0xFF ! mask off all interrupts for now 233 out #0xA1,al 234 .word 0x00eb,0x00eb 235 mov al,#0xFB ! mask all irq's but irq2 which 236 out #0x21,al ! is cascaded 237 238 ! well, that certainly wasn't fun :-(. Hopefully it works, and we don't 239 ! need no steenking BIOS anyway (except for the initial loading :-). 240 ! The BIOS-routine wants lots of unnecessary data, and it's less 241 ! "interesting" anyway. This is how REAL programmers do it. 242 ! 243 ! Well, now's the time to actually move into protected mode. To make 244 ! things as simple as possible, we do no register set-up or anything, 245 ! we let the gnu-compiled 32-bit programs do that. We just jump to 246 ! absolute address 0x00000, in 32-bit protected mode. 247 248 mov ax,#0x0001 ! protected mode (PE) bit 249 lmsw ax ! This is it! 250 jmpi 0,8 ! jmp offset 0 of segment 8 (cs) 251 252 ! This routine checks that the keyboard command queue is empty 253 ! No timeout is used - if this hangs there is something wrong with 254 ! the machine, and we probably couldn't proceed anyway. 255 empty_8042: 256 .word 0x00eb,0x00eb 257 in al,#0x64 ! 8042 status port 258 test al,#2 ! is input buffer full? 259 jnz empty_8042 ! yes - loop 260 ret 261 262 getkey: 263 in al,#0x60 ! Quick and dirty... 264 .word 0x00eb,0x00eb ! jmp $+2, jmp $+2 265 mov bl,al 266 in al,#0x61 267 .word 0x00eb,0x00eb 268 mov ah,al 269 or al,#0x80 270 out #0x61,al 271 .word 0x00eb,0x00eb 272 mov al,ah 273 out #0x61,al 274 .word 0x00eb,0x00eb 275 mov al,bl 276 ret 277 278 ! Routine trying to recognize type of SVGA-board present (if any) 279 ! and if it recognize one gives the choices of resolution it offers. 280 ! If one is found the resolution chosen is given by al,ah (rows,cols). 281 282 chsvga: cld 283 push ds 284 push cs 285 pop ds 286 mov ax,#0xc000 287 mov es,ax 288 lea si,msg1 289 #ifndef SVGA_MODE 290 call prtstr 291 flush: in al,#0x60 ! Flush the keyboard buffer 292 cmp al,#0x82 293 jb nokey 294 jmp flush 295 nokey: call getkey 296 cmp al,#0x82 297 jb nokey 298 cmp al,#0xe0 299 ja nokey 300 cmp al,#0x9c 301 je svga 302 #endif 303 #if !defined(SVGA_MODE) || SVGA_MODE == NORMAL_VGA 304 mov ax,#0x5019 305 pop ds 306 ret 307 #endif 308 svga: cld 309 lea si,idati ! Check ATI 'clues' 310 mov di,#0x31 311 mov cx,#0x09 312 repe 313 cmpsb 314 jne noati 315 lea si,dscati 316 lea di,moati 317 lea cx,selmod 318 jmp cx 319 noati: mov ax,#0x200f ! Check Ahead 'clues' 320 mov dx,#0x3ce 321 out dx,ax 322 inc dx 323 in al,dx 324 cmp al,#0x20 325 je isahed 326 cmp al,#0x21 327 jne noahed 328 isahed: lea si,dscahead 329 lea di,moahead 330 lea cx,selmod 331 jmp cx 332 noahed: mov dx,#0x3c3 ! Check Chips & Tech. 'clues' 333 in al,dx 334 or al,#0x10 335 out dx,al 336 mov dx,#0x104 337 in al,dx 338 mov bl,al 339 mov dx,#0x3c3 340 in al,dx 341 and al,#0xef 342 out dx,al 343 cmp bl,[idcandt] 344 jne nocant 345 lea si,dsccandt 346 lea di,mocandt 347 lea cx,selmod 348 jmp cx 349 nocant: mov dx,#0x3d4 ! Check Cirrus 'clues' 350 mov al,#0x0c 351 out dx,al 352 inc dx 353 in al,dx 354 mov bl,al 355 xor al,al 356 out dx,al 357 dec dx 358 mov al,#0x1f 359 out dx,al 360 inc dx 361 in al,dx 362 mov bh,al 363 xor ah,ah 364 shl al,#4 365 mov cx,ax 366 mov al,bh 367 shr al,#4 368 add cx,ax 369 shl cx,#8 370 add cx,#6 371 mov ax,cx 372 mov dx,#0x3c4 373 out dx,ax 374 inc dx 375 in al,dx 376 and al,al 377 jnz nocirr 378 mov al,bh 379 out dx,al 380 in al,dx 381 cmp al,#0x01 382 jne nocirr 383 call rst3d4 384 lea si,dsccirrus 385 lea di,mocirrus 386 lea cx,selmod 387 jmp cx 388 rst3d4: mov dx,#0x3d4 389 mov al,bl 390 xor ah,ah 391 shl ax,#8 392 add ax,#0x0c 393 out dx,ax 394 ret 395 nocirr: call rst3d4 ! Check Everex 'clues' 396 mov ax,#0x7000 397 xor bx,bx 398 int 0x10 399 cmp al,#0x70 400 jne noevrx 401 shr dx,#4 402 cmp dx,#0x678 403 je istrid 404 cmp dx,#0x236 405 je istrid 406 lea si,dsceverex 407 lea di,moeverex 408 lea cx,selmod 409 jmp cx 410 istrid: lea cx,ev2tri 411 jmp cx 412 noevrx: lea si,idgenoa ! Check Genoa 'clues' 413 xor ax,ax 414 seg es 415 mov al,[0x37] 416 mov di,ax 417 mov cx,#0x04 418 dec si 419 dec di 420 l1: inc si 421 inc di 422 mov al,(si) 423 seg es 424 and al,(di) 425 cmp al,(si) 426 loope l1 427 cmp cx,#0x00 428 jne nogen 429 lea si,dscgenoa 430 lea di,mogenoa 431 lea cx,selmod 432 jmp cx 433 nogen: cld 434 lea si,idoakvga 435 mov di,#0x08 436 mov cx,#0x08 437 repe 438 cmpsb 439 jne nooak 440 lea si,dscoakvga 441 lea di,mooakvga 442 lea cx,selmod 443 jmp cx 444 nooak: cld 445 lea si,idparadise ! Check Paradise 'clues' 446 mov di,#0x7d 447 mov cx,#0x04 448 repe 449 cmpsb 450 jne nopara 451 lea si,dscparadise 452 lea di,moparadise 453 lea cx,selmod 454 jmp cx 455 nopara: mov dx,#0x3c4 ! Check Trident 'clues' 456 mov al,#0x0e 457 out dx,al 458 inc dx 459 in al,dx 460 xchg ah,al 461 mov al,#0x00 462 out dx,al 463 in al,dx 464 xchg al,ah 465 mov bl,al ! Strange thing ... in the book this wasn't 466 and bl,#0x02 ! necessary but it worked on my card which 467 jz setb2 ! is a trident. Without it the screen goes 468 and al,#0xfd ! blurred ... 469 jmp clrb2 ! 470 setb2: or al,#0x02 ! 471 clrb2: out dx,al 472 and ah,#0x0f 473 cmp ah,#0x02 474 jne notrid 475 ev2tri: lea si,dsctrident 476 lea di,motrident 477 lea cx,selmod 478 jmp cx 479 notrid: mov dx,#0x3cd ! Check Tseng 'clues' 480 in al,dx ! Could things be this simple ! :-) 481 mov bl,al 482 mov al,#0x55 483 out dx,al 484 in al,dx 485 mov ah,al 486 mov al,bl 487 out dx,al 488 cmp ah,#0x55 489 jne notsen 490 lea si,dsctseng 491 lea di,motseng 492 lea cx,selmod 493 jmp cx 494 notsen: mov dx,#0x3cc ! Check Video7 'clues' 495 in al,dx 496 mov dx,#0x3b4 497 and al,#0x01 498 jz even7 499 mov dx,#0x3d4 500 even7: mov al,#0x0c 501 out dx,al 502 inc dx 503 in al,dx 504 mov bl,al 505 mov al,#0x55 506 out dx,al 507 in al,dx 508 dec dx 509 mov al,#0x1f 510 out dx,al 511 inc dx 512 in al,dx 513 mov bh,al 514 dec dx 515 mov al,#0x0c 516 out dx,al 517 inc dx 518 mov al,bl 519 out dx,al 520 mov al,#0x55 521 xor al,#0xea 522 cmp al,bh 523 jne novid7 524 lea si,dscvideo7 525 lea di,movideo7 526 selmod: push si 527 lea si,msg2 528 call prtstr 529 xor cx,cx 530 mov cl,(di) 531 pop si 532 push si 533 push cx 534 tbl: pop bx 535 push bx 536 mov al,bl 537 sub al,cl 538 call dprnt 539 call spcing 540 lodsw 541 xchg al,ah 542 call dprnt 543 xchg ah,al 544 push ax 545 mov al,#0x78 546 call prnt1 547 pop ax 548 call dprnt 549 call docr 550 loop tbl 551 pop cx 552 call docr 553 lea si,msg3 554 call prtstr 555 pop si 556 add cl,#0x80 557 #if defined(SVGA_MODE) && SVGA_MODE != NORMAL_VGA 558 mov al,#SVGA_MODE ! Preset SVGA mode 559 #else 560 nonum: call getkey 561 cmp al,#0x82 562 jb nonum 563 cmp al,#0x8b 564 je zero 565 cmp al,cl 566 ja nonum 567 jmp nozero 568 zero: sub al,#0x0a 569 nozero: sub al,#0x80 570 dec al 571 #endif 572 xor ah,ah 573 add di,ax 574 inc di 575 push ax 576 mov al,(di) 577 int 0x10 578 pop ax 579 shl ax,#1 580 add si,ax 581 lodsw 582 pop ds 583 ret 584 novid7: 585 mov ax,#0x1112 586 mov bl,#0 587 int 0x10 ! use 8x8 font set (50 lines on VGA) 588 589 mov ax,#0x1200 590 mov bl,#0x20 591 int 0x10 ! use alternate print screen 592 593 mov ax,#0x1201 594 mov bl,#0x34 595 int 0x10 ! turn off cursor emulation 596 597 mov ah,#0x01 598 mov cx,#0x0607 599 int 0x10 ! turn on cursor (scan lines 6 to 7) 600 601 pop ds 602 mov ax,#0x5032 ! return 80x50 603 ret 604 605 ! Routine that 'tabs' to next col. 606 607 spcing: mov al,#0x2e 608 call prnt1 609 mov al,#0x20 610 call prnt1 611 mov al,#0x20 612 call prnt1 613 mov al,#0x20 614 call prnt1 615 mov al,#0x20 616 call prnt1 617 ret 618 619 ! Routine to print asciiz-string at DS:SI 620 621 prtstr: lodsb 622 and al,al 623 jz fin 624 call prnt1 625 jmp prtstr 626 fin: ret 627 628 ! Routine to print a decimal value on screen, the value to be 629 ! printed is put in al (i.e 0-255). 630 631 dprnt: push ax 632 push cx 633 mov ah,#0x00 634 mov cl,#0x0a 635 idiv cl 636 cmp al,#0x09 637 jbe lt100 638 call dprnt 639 jmp skip10 640 lt100: add al,#0x30 641 call prnt1 642 skip10: mov al,ah 643 add al,#0x30 644 call prnt1 645 pop cx 646 pop ax 647 ret 648 649 ! Part of above routine, this one just prints ascii al 650 651 prnt1: push ax 652 push cx 653 mov bh,#0x00 654 mov cx,#0x01 655 mov ah,#0x0e 656 int 0x10 657 pop cx 658 pop ax 659 ret 660 661 ! Prints <CR> + <LF> 662 663 docr: push ax 664 push cx 665 mov bh,#0x00 666 mov ah,#0x0e 667 mov al,#0x0a 668 mov cx,#0x01 669 int 0x10 670 mov al,#0x0d 671 int 0x10 672 pop cx 673 pop ax 674 ret 675 676 gdt: 677 .word 0,0,0,0 ! dummy 678 679 .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb) 680 .word 0x0000 ! base address=0 681 .word 0x9A00 ! code read/exec 682 .word 0x00C0 ! granularity=4096, 386 683 684 .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb) 685 .word 0x0000 ! base address=0 686 .word 0x9200 ! data read/write 687 .word 0x00C0 ! granularity=4096, 386 688 689 idt_48: 690 .word 0 ! idt limit=0 691 .word 0,0 ! idt base=0L 692 693 gdt_48: 694 .word 0x800 ! gdt limit=2048, 256 GDT entries 695 .word 512+gdt,0x9 ! gdt base = 0X9xxxx 696 697 msg1: .ascii "Press <RETURN> to see SVGA-modes available or any other key to continue." 698 db 0x0d, 0x0a, 0x0a, 0x00 699 msg2: .ascii "Mode: COLSxROWS:" 700 db 0x0d, 0x0a, 0x0a, 0x00 701 msg3: .ascii "Choose mode by pressing the corresponding number." 702 db 0x0d, 0x0a, 0x00 703 704 idati: .ascii "761295520" 705 idcandt: .byte 0xa5 706 idgenoa: .byte 0x77, 0x00, 0x66, 0x99 707 idparadise: .ascii "VGA=" 708 idoakvga: .ascii "OAK VGA " 709 710 ! Manufacturer: Numofmodes: Mode: 711 712 moati: .byte 0x02, 0x23, 0x33 713 moahead: .byte 0x05, 0x22, 0x23, 0x24, 0x2f, 0x34 714 mocandt: .byte 0x02, 0x60, 0x61 715 mocirrus: .byte 0x04, 0x1f, 0x20, 0x22, 0x31 716 moeverex: .byte 0x0a, 0x03, 0x04, 0x07, 0x08, 0x0a, 0x0b, 0x16, 0x18, 0x21, 0x40 717 mogenoa: .byte 0x0a, 0x58, 0x5a, 0x60, 0x61, 0x62, 0x63, 0x64, 0x72, 0x74, 0x78 718 moparadise: .byte 0x02, 0x55, 0x54 719 motrident: .byte 0x07, 0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5a 720 motseng: .byte 0x05, 0x26, 0x2a, 0x23, 0x24, 0x22 721 movideo7: .byte 0x06, 0x40, 0x43, 0x44, 0x41, 0x42, 0x45 722 mooakvga: .byte 0x05, 0x00, 0x07, 0x4f, 0x50, 0x51 723 724 ! msb = Cols lsb = Rows: 725 726 dscati: .word 0x8419, 0x842c 727 dscahead: .word 0x842c, 0x8419, 0x841c, 0xa032, 0x5042 728 dsccandt: .word 0x8419, 0x8432 729 dsccirrus: .word 0x8419, 0x842c, 0x841e, 0x6425 730 dsceverex: .word 0x5022, 0x503c, 0x642b, 0x644b, 0x8419, 0x842c, 0x501e, 0x641b, 0xa040, 0x841e 731 dscgenoa: .word 0x5020, 0x642a, 0x8419, 0x841d, 0x8420, 0x842c, 0x843c, 0x503c, 0x5042, 0x644b 732 dscparadise: .word 0x8419, 0x842b 733 dsctrident: .word 0x501e, 0x502b, 0x503c, 0x8419, 0x841e, 0x842b, 0x843c 734 dsctseng: .word 0x503c, 0x6428, 0x8419, 0x841c, 0x842c 735 dscvideo7: .word 0x502b, 0x503c, 0x643c, 0x8419, 0x842c, 0x841c 736 dscoakvga: .word 0x2819, 0x5019, 0x843c, 0x8419, 0x842C 737 738 .text 739 endtext: 740 .data 741 enddata: 742 .bss 743 endbss: