|
|
1.1 ! root 1: //////// ! 2: / ! 3: / I/O library for use with boot programs. Uses the BIOS. ! 4: / ! 5: / La Monte H. Yarroll <[email protected]>, September 1991 ! 6: / ! 7: //////// ! 8: ! 9: //////// ! 10: / ! 11: / Magic constants. ! 12: / ! 13: //////// ! 14: ! 15: RETF = 0xCB / Far return ! 16: VIDEO = 0x10 / video swi ! 17: DISK = 0x13 / disk io swi ! 18: KEYBD = 0x16 / keyboard swi ! 19: MON = 0x00 / Monitor swi ! 20: READ1 = 0x0201 / read 1 sector ! 21: ! 22: BUFSIZE = 0x200 / Size of a physical disk block. ! 23: ! 24: NTRK = 40 / Number of tracks on a floppy. ! 25: NSPT = 9 / Number of sectors per track on a floppy. ! 26: NHD = 1 / Number of heads per drive on a floppy. ! 27: ! 28: FIRST = 8 / Relative start of partition. ! 29: ! 30: .shri / Shared code segment, initialized. ! 31: //////// ! 32: / ! 33: / Read a block from disk, relative to the start of the boot partition, ! 34: / using the code in the IBM firmware. ! 35: / ! 36: / It takes two parameters: ! 37: / daddr_t blockno; /* 32 bit block number. */ ! 38: / char *buff; /* Must point to a 512 byte buffer. */ ! 39: / ! 40: / The buffer must not cross a 4K boundry. Disk input should generally ! 41: / be done through the C routine bread(), which calls bread() with an ! 42: / aligned buffer. ! 43: / ! 44: //////// ! 45: ! 46: .globl _bread_ ! 47: _bread_: ! 48: push es / Save registers ! 49: push si ! 50: push di ! 51: push bp ! 52: push dx ! 53: ! 54: push ds ! 55: pop es / Set es:bp to address of the buffer. ! 56: ! 57: mov bp, sp ! 58: mov ax, 12(bp) / Get low word of block number. ! 59: mov dx, 14(bp) / Get high word of block number. ! 60: mov bx, 16(bp) / Get a buffer to put it in. ! 61: mov bp, bx ! 62: ! 63: mov di, bp / Blast the buffer contents. ! 64: mov cx, $BUFSIZE / For block 0, this fills the buffer ! 65: rep / with zeros. ! 66: stosb ! 67: ! 68: / Block #0 is the sparse block--it means a block of all zeros. ! 69: test ax, ax / if block 0, return zeroed buffer ! 70: jnz 3f ! 71: test dx, dx ! 72: jnz 3f ! 73: movb al, $1 / Say that we read 1 block. ! 74: jmp 2f ! 75: / Translate block number into cylinder, head, and sector. ! 76: 3: add ax, first / add first block ! 77: adc dx, first+2 / add rest ! 78: ! 79: mov bx, ax / save block number ! 80: movb al, heads / get number of heads ! 81: movb cl, sects / get number of sectors ! 82: mulb cl / calculate sectors per cylinder ! 83: xchg bx,ax / swap block/sectors ! 84: div bx / calculate track ! 85: xchg dx, ax / put track in DX ! 86: divb cl / calculate head/sector ! 87: ! 88: movb cl, ah / set sector ! 89: inc cx / sectors start at 1 [incb cl] ! 90: ! 91: cmp dx, traks / check for second side ! 92: jb 0f ! 93: sub dx, traks / fold track ! 94: inc ax / next head [incb al] ! 95: ! 96: 0: rorb dh, $1 / rotate track(low) into ! 97: rorb dh, $1 / msbits of DX ! 98: orb cl, dh / set track(high) ! 99: movb ch, dl / set track(low) ! 100: movb dh, al / set head ! 101: movb dl, drive / set drive ! 102: mov bx, bp / set offset [bbuf] ! 103: ! 104: mov ax, $READ1 / Read, 1 sector. ! 105: int DISK / Disk I/O. ! 106: jnc 2f / Jump if no error. ! 107: mov ax, $READ1 / try again ! 108: int DISK ! 109: jc berror ! 110: ! 111: 2: ! 112: / al contains the number of blocks read (should be 1). ! 113: pop dx / restore registers. ! 114: pop bp ! 115: pop di ! 116: pop si ! 117: pop es ! 118: ret / return. ! 119: ! 120: berror: / error handling for _bread. ! 121: xorb al, al / ah contains an error code. ! 122: jmp 2b ! 123: ! 124: //////// ! 125: / ! 126: / Write the character in "al" out to ! 127: / the display, using routines in the ROM. ! 128: / Like most calls to the ROM, this routine spends ! 129: / most of its time saving and restoring the ! 130: / registers. ! 131: / ! 132: //////// ! 133: ! 134: .globl putchar_ ! 135: putchar_: push si / Save registers. ! 136: push di ! 137: push bp ! 138: ! 139: mov bp, sp ! 140: mov ax, 8(bp) / Fetch the single argument. ! 141: ! 142: mov bx, $0x0007 / Page 0, white on black ! 143: movb ah, $0x0E / Write TTY. ! 144: int VIDEO / Call video I/O in ROM. ! 145: ! 146: pop bp / Restore registers. ! 147: pop di ! 148: pop si ! 149: ret ! 150: ! 151: ! 152: //////// ! 153: / ! 154: / Fetch character from keyboard, using ! 155: / routines in the ROM. ! 156: / ! 157: //////// ! 158: ! 159: .globl getchar_ ! 160: getchar_: ! 161: push si / Save registers. ! 162: push di ! 163: push bp ! 164: ! 165: movb ah, $0x00 / Read keystroke. ! 166: int KEYBD ! 167: ! 168: movb ah, $0x00 ! 169: pop bp / Restore registers. ! 170: pop di ! 171: pop si ! 172: ret ! 173: ! 174: //////// ! 175: / ! 176: / Check for a pending keystroke using ! 177: / routines in the ROM. ! 178: / ! 179: //////// ! 180: ! 181: .globl iskey_ ! 182: iskey_: ! 183: push si / Save registers. ! 184: push di ! 185: push bp ! 186: ! 187: movb ah, $0x01 / Check for keystroke. ! 188: int KEYBD ! 189: jne 0f ! 190: xor ax, ax / Set false. ! 191: jmp 1f ! 192: 0: xor ax, ax ! 193: inc ax / Set true. ! 194: 1: pop bp / Restore registers. ! 195: pop di ! 196: pop si ! 197: ret ! 198: ! 199: ! 200: //////// ! 201: / ! 202: / Goto a far address ! 203: / Takes two integer arguments: an offset, and a segment, in that order. ! 204: / ! 205: //////// ! 206: ! 207: .globl gotofar_ ! 208: gotofar_: ! 209: add sp, $2 ! 210: .byte RETF ! 211: ! 212: ! 213: //////// ! 214: / ! 215: / Goto a kernel. ! 216: / Takes three integer arguments: an offset, a segment, and a new data segment ! 217: / in that order. ! 218: / ! 219: //////// ! 220: ! 221: .globl gotoker_ ! 222: gotoker_: ! 223: mov bp, sp ! 224: mov es, 6(bp) / Point es at the new data segment. ! 225: mov si, $seconddat / Point ds:si at useful data. ! 226: add sp, $2 ! 227: .byte RETF ! 228: ! 229: ! 230: //////// ! 231: / ! 232: / Initilize hard disk parameters ! 233: / ! 234: //////// ! 235: .globl hdinit_ ! 236: hdinit_: ! 237: push si / Save registers. ! 238: push di ! 239: push bp ! 240: ! 241: mov si, bp / set si to partition table ! 242: ! 243: movb dl, (si) / get drive number ! 244: movb ah, $8 / get drive parameters ! 245: int DISK ! 246: jc 1f / abort on error (just return) ! 247: ! 248: movb al, ch / fetch cyl(lo) ! 249: movb ah, cl / move cyl(hi), sects ! 250: rolb ah, $1 / shift cylinder high to ! 251: rolb ah, $1 / the least sig bits ! 252: andb ah, $3 / mask out cylinder bits ! 253: ! 254: mov di, $traks / point to drive ! 255: stosw / set number of tracks ! 256: ! 257: movb al, $0x3F / sector mask ! 258: andb al, cl / mask sector ! 259: stosb / set sector ! 260: ! 261: movb al, dh / get max head ! 262: inc ax / change to # of heads (incb al) ! 263: stosb / set number of heads ! 264: ! 265: movsb / set drive ! 266: add si, $FIRST-1 / point to first block ! 267: movsw / fetch first block ! 268: movsw ! 269: ! 270: 1: pop bp / Restore registers. ! 271: pop di ! 272: pop si ! 273: ! 274: ret ! 275: ! 276: //////// ! 277: / ! 278: / Invoke the native monitor. ! 279: / Useful for debugging. ! 280: / ! 281: //////// ! 282: ! 283: .globl intmon_ ! 284: intmon_: ! 285: int MON ! 286: ret ! 287: ! 288: //////// ! 289: / ! 290: / void _ffcopy(from_fp, to_fp, count) ! 291: / faddr_t from_fp, to_fp; ! 292: / int count; ! 293: / ! 294: / Copy count bytes from from_fp to to_fp. ! 295: / ! 296: / Here is the stack after initial "push bp": ! 297: / ! 298: / 12(bp) count ! 299: / 10(bp) FP_SEL(to_fp) ! 300: / 8(bp) FP_OFF(to_fp) ! 301: / 6(bp) FP_SEL(from_fp) ! 302: / 4(bp) FP_OFF(from_fp) ! 303: / 2(bp) return IP ! 304: / 0(bp) old bp ! 305: / ! 306: //////// ! 307: ! 308: .globl _ffcopy_ ! 309: _ffcopy_: ! 310: push bp ! 311: mov bp, sp ! 312: push es ! 313: push di ! 314: push ds ! 315: push si ! 316: ! 317: lds si, 4(bp) / from_fp to DS:SI ! 318: les di, 8(bp) / to_fp to ES:DI ! 319: mov cx, 12(bp) / rep count to CX ! 320: rep ! 321: movsb ! 322: ! 323: pop si ! 324: pop ds ! 325: pop di ! 326: pop es ! 327: pop bp ! 328: ret / return from _ffcopy() ! 329: ! 330: ! 331: ! 332: //////// ! 333: / ! 334: / Read a block from disk, relative to start of disk, ! 335: / using the code in the IBM firmware. ! 336: / ! 337: / It takes two parameters: ! 338: / daddr_t blockno; /* 32 bit block number. */ ! 339: / char *buff; /* Must point to a 512 byte buffer. */ ! 340: / ! 341: / The buffer must not cross a 4K boundry. Disk input should generally ! 342: / be done through the C routine bread(), which calls bread() with an ! 343: / aligned buffer. ! 344: / ! 345: //////// ! 346: ! 347: .globl _xbread_ ! 348: _xbread_: ! 349: push es / Save registers ! 350: push si ! 351: push di ! 352: push bp ! 353: push dx ! 354: ! 355: push ds ! 356: pop es / Set es:bp to address of the buffer. ! 357: ! 358: mov bp, sp ! 359: mov ax, 12(bp) / Get low word of block number. ! 360: mov dx, 14(bp) / Get high word of block number. ! 361: mov bx, 16(bp) / Get a buffer to put it in. ! 362: mov bp, bx ! 363: ! 364: / Translate block number into cylinder, head, and sector. ! 365: 3: ! 366: mov bx, ax / save block number ! 367: movb al, heads / get number of heads ! 368: movb cl, sects / get number of sectors ! 369: mulb cl / calculate sectors per cylinder ! 370: xchg bx,ax / swap block/sectors ! 371: div bx / calculate track ! 372: xchg dx, ax / put track in DX ! 373: divb cl / calculate head/sector ! 374: ! 375: movb cl, ah / set sector ! 376: inc cx / sectors start at 1 [incb cl] ! 377: ! 378: cmp dx, traks / check for second side ! 379: jb 0f ! 380: sub dx, traks / fold track ! 381: inc ax / next head [incb al] ! 382: ! 383: 0: rorb dh, $1 / rotate track(low) into ! 384: rorb dh, $1 / msbits of DX ! 385: orb cl, dh / set track(high) ! 386: movb ch, dl / set track(low) ! 387: movb dh, al / set head ! 388: movb dl, drive / set drive ! 389: mov bx, bp / set offset [bbuf] ! 390: ! 391: mov ax, $READ1 / Read, 1 sector. ! 392: int DISK / Disk I/O. ! 393: jnc 2f / Jump if no error. ! 394: mov ax, $READ1 / try again ! 395: int DISK ! 396: jc berror ! 397: ! 398: 2: ! 399: / al contains the number of blocks read (should be 1). ! 400: pop dx / restore registers. ! 401: pop bp ! 402: pop di ! 403: pop si ! 404: pop es ! 405: ret / return.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.