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