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