|
|
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: mov bx, bp ! 229: add bx, $2 ! 230: xcall (bx) ! 231: ret ! 232: ! 233: ! 234: //////// ! 235: / ! 236: / Initilize hard disk parameters ! 237: / ! 238: //////// ! 239: .globl hdinit_ ! 240: hdinit_: ! 241: push si / Save registers. ! 242: push di ! 243: push bp ! 244: ! 245: mov si, bp / set si to partition table ! 246: ! 247: movb dl, (si) / get drive number ! 248: movb ah, $8 / get drive parameters ! 249: int DISK ! 250: jc 1f / abort on error (just return) ! 251: ! 252: movb al, ch / fetch cyl(lo) ! 253: movb ah, cl / move cyl(hi), sects ! 254: rolb ah, $1 / shift cylinder high to ! 255: rolb ah, $1 / the least sig bits ! 256: andb ah, $3 / mask out cylinder bits ! 257: ! 258: mov di, $traks / point to drive ! 259: stosw / set number of tracks ! 260: ! 261: movb al, $0x3F / sector mask ! 262: andb al, cl / mask sector ! 263: stosb / set sector ! 264: ! 265: movb al, dh / get max head ! 266: inc ax / change to # of heads (incb al) ! 267: stosb / set number of heads ! 268: ! 269: movsb / set drive ! 270: add si, $FIRST-1 / point to first block ! 271: movsw / fetch first block ! 272: movsw ! 273: ! 274: 1: pop bp / Restore registers. ! 275: pop di ! 276: pop si ! 277: ! 278: ret ! 279: ! 280: //////// ! 281: / ! 282: / Invoke the native monitor. ! 283: / Useful for debugging. ! 284: / ! 285: //////// ! 286: ! 287: .globl intmon_ ! 288: intmon_: ! 289: int MON ! 290: ret ! 291: ! 292: //////// ! 293: / ! 294: / void _ffcopy(from_fp, to_fp, count) ! 295: / faddr_t from_fp, to_fp; ! 296: / int count; ! 297: / ! 298: / Copy count bytes from from_fp to to_fp. ! 299: / ! 300: / Here is the stack after initial "push bp": ! 301: / ! 302: / 12(bp) count ! 303: / 10(bp) FP_SEL(to_fp) ! 304: / 8(bp) FP_OFF(to_fp) ! 305: / 6(bp) FP_SEL(from_fp) ! 306: / 4(bp) FP_OFF(from_fp) ! 307: / 2(bp) return IP ! 308: / 0(bp) old bp ! 309: / ! 310: //////// ! 311: ! 312: .globl _ffcopy_ ! 313: _ffcopy_: ! 314: push bp ! 315: mov bp, sp ! 316: push es ! 317: push di ! 318: push ds ! 319: push si ! 320: ! 321: lds si, 4(bp) / from_fp to DS:SI ! 322: les di, 8(bp) / to_fp to ES:DI ! 323: mov cx, 12(bp) / rep count to CX ! 324: rep ! 325: movsb ! 326: ! 327: pop si ! 328: pop ds ! 329: pop di ! 330: pop es ! 331: pop bp ! 332: ret / return from _ffcopy() ! 333: ! 334: ! 335: ! 336: //////// ! 337: / ! 338: / Read a block from disk, relative to start of disk, ! 339: / using the code in the IBM firmware. ! 340: / ! 341: / It takes two parameters: ! 342: / daddr_t blockno; /* 32 bit block number. */ ! 343: / char *buff; /* Must point to a 512 byte buffer. */ ! 344: / ! 345: / The buffer must not cross a 4K boundry. Disk input should generally ! 346: / be done through the C routine xbread(), which calls _xbread() with an ! 347: / aligned buffer. ! 348: / ! 349: //////// ! 350: ! 351: .globl _xbread_ ! 352: _xbread_: ! 353: push es / Save registers ! 354: push si ! 355: push di ! 356: push bp ! 357: push dx ! 358: ! 359: push ds ! 360: pop es / Set es:bp to address of the buffer. ! 361: ! 362: mov bp, sp ! 363: mov ax, 12(bp) / Get low word of block number. ! 364: mov dx, 14(bp) / Get high word of block number. ! 365: mov bx, 16(bp) / Get a buffer to put it in. ! 366: mov bp, bx ! 367: ! 368: / Translate block number into cylinder, head, and sector. ! 369: 3: ! 370: mov bx, ax / save block number ! 371: movb al, heads / get number of heads ! 372: movb cl, sects / get number of sectors ! 373: mulb cl / calculate sectors per cylinder ! 374: xchg bx,ax / swap block/sectors ! 375: div bx / calculate track ! 376: xchg dx, ax / put track in DX ! 377: divb cl / calculate head/sector ! 378: ! 379: movb cl, ah / set sector ! 380: inc cx / sectors start at 1 [incb cl] ! 381: ! 382: cmp dx, traks / check for second side ! 383: jb 0f ! 384: sub dx, traks / fold track ! 385: inc ax / next head [incb al] ! 386: ! 387: 0: rorb dh, $1 / rotate track(low) into ! 388: rorb dh, $1 / msbits of DX ! 389: orb cl, dh / set track(high) ! 390: movb ch, dl / set track(low) ! 391: movb dh, al / set head ! 392: movb dl, drive / set drive ! 393: mov bx, bp / set offset [bbuf] ! 394: ! 395: mov ax, $READ1 / Read, 1 sector. ! 396: int DISK / Disk I/O. ! 397: jnc 2f / Jump if no error. ! 398: mov ax, $READ1 / try again ! 399: int DISK ! 400: jc berror ! 401: ! 402: 2: ! 403: / al contains the number of blocks read (should be 1). ! 404: pop dx / restore registers. ! 405: pop bp ! 406: pop di ! 407: pop si ! 408: pop es ! 409: ret / return.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.