|
|
1.1 ! root 1: /* ! 2: * Copyright 2010 Google Inc. ! 3: * ! 4: * Licensed under the Apache License, Version 2.0 (the "License"); ! 5: * you may not use this file except in compliance with the License. ! 6: * You may obtain a copy of the License at ! 7: * ! 8: * http://www.apache.org/licenses/LICENSE-2.0 ! 9: * ! 10: * Unless required by applicable law or agreed to in writing, software ! 11: * distributed under the License is distributed on an "AS IS" BASIS, ! 12: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ! 13: * See the License for the specific language governing permissions and ! 14: * limitations under the License. ! 15: */ ! 16: ! 17: #include "sgabios.h" ! 18: #define BUILD_CL "$Id$" ! 19: ! 20: .code16 ! 21: .text ! 22: .section ".init","ax" ! 23: .globl _start ! 24: .type _start,@object ! 25: _start: ! 26: /* option rom header */ ! 27: .byte 0x55 ! 28: .byte 0xaa ! 29: .byte _rom_size_byte ! 30: .size _start, .-_start ! 31: ! 32: .globl legacy_entry ! 33: .type legacy_entry,@function ! 34: legacy_entry: ! 35: jmp sga_init ! 36: /* pnp entry here to avoid changing PnP table as code moves */ ! 37: pnp_init: ! 38: jmp pnp_sga_init ! 39: ! 40: /* ! 41: * do_old_int10h ! 42: * ! 43: * Patched at option rom init to be a far jump to old int 10h isr ! 44: * ! 45: */ ! 46: do_old_int10h: ! 47: .byte 0xea /* jmp absolute segment:offset */ ! 48: old_int10h: /* store what was at offset 0x40 */ ! 49: .word 0xf065 /* placeholder for chained ISR offset */ ! 50: /* if the chained segment is detected as 0xc000, use 80 cols only */ ! 51: /* since it's assumed that a vga card is attached and 80 cols max */ ! 52: old_int10h_seg: ! 53: .word 0xf000 /* placeholder for chained ISR segment */ ! 54: /* ! 55: * do_old_int16h ! 56: * ! 57: * Patched at option rom init to be a far jump to old int 16h isr ! 58: * ! 59: */ ! 60: do_old_int16h: ! 61: .byte 0xea /* jmp absolute segment:offset */ ! 62: old_int16h: /* store what was at offset 0x58 */ ! 63: .word 0xe82e /* placeholder for chained ISR offset */ ! 64: .word 0xf000 /* placeholder for chained ISR segment */ ! 65: .org 0x18 ! 66: .word 0 /* offset to PCI data, 0 = none */ ! 67: .word pnp_table /* offset to PnP expansion header */ ! 68: .org 0x20 ! 69: pnp_table: ! 70: /* FIXME: **** PnP header currently disabled by PoO **** */ ! 71: /* legacy entry only called once, PnP entry called multiple times */ ! 72: /* The code isn't yet written to deal with multiple inits properly */ ! 73: .ascii "$PoO" /* PnP expansion header signature */ ! 74: .byte 1 /* structure revision */ ! 75: .byte 2 /* length in 16-byte increments */ ! 76: .word 0 /* offset of next header, 0 if none */ ! 77: .byte 0 /* reserved */ ! 78: .byte 0x52 /* checksum - update manually! FIXME */ ! 79: .long 0 /* device identifier */ ! 80: .word mfg_string /* pointer to manufacturer string */ ! 81: .word prod_string /* pointer to product name string */ ! 82: .byte 3, 0x80, 0x80 /* device type code = other display */ ! 83: .byte 0xe3 /* device indicators, kbd/display dev */ ! 84: .word 0 /* boot connection vector, 0 if none */ ! 85: .word 0 /* disconnect vector, 0 if none */ ! 86: .word pnp_init /* bootstrap entry vector */ ! 87: .word 0 /* reserved */ ! 88: .word 0 /* static resource information vector */ ! 89: ! 90: /* WARNING: changing mfg_string / prod_string locations will */ ! 91: /* affect pnp table above -- recalculate checksum manually! */ ! 92: mfg_string: ! 93: .asciz "Google, Inc." ! 94: prod_string: ! 95: .ascii "Serial Graphics Adapter " ! 96: build_date: ! 97: .asciz BUILD_SHORT_DATE ! 98: long_version: ! 99: .ascii "SGABIOS " ! 100: .ascii BUILD_CL ! 101: .ascii " (" ! 102: .ascii BUILD_USER ! 103: .ascii "@" ! 104: .ascii BUILD_HOST ! 105: .ascii ") " ! 106: .asciz BUILD_DATE ! 107: term_cols: ! 108: .byte 80 /* overwritten at rom init with detected value */ ! 109: term_rows: ! 110: .byte 24 /* overwritten at rom init with detected value */ ! 111: term_init_string: /* terminal reply: \033[n;mR n=row, m=col */ ! 112: .asciz "\033[1;256r\033[256;256H\033[6n" ! 113: /* reset the scroll, move to col 256, row 256, ask current position */ ! 114: /* bios cursor positions >255 rows or cols can't be used anyway */ ! 115: term_info: ! 116: .asciz "Term: " ! 117: ebda_info: ! 118: .asciz "EBDA: " ! 119: ! 120: /* ! 121: * do_old_irq3 - exception 0x0b, int 0x0a ! 122: * ! 123: * Patched at option rom init to be a far jump to old irq 3 isr ! 124: * ! 125: */ ! 126: do_old_irq3: ! 127: .byte 0xea /* jmp absolute segment:offset */ ! 128: old_irq3: /* store what was at offset 0x28 */ ! 129: .word 0xeef3 /* placeholder for chained ISR offset */ ! 130: .word 0xf000 /* placeholder for chained ISR segment */ ! 131: ! 132: /* ! 133: * do_old_irq4 - exception 0x0c, int 0x0b ! 134: * ! 135: * Patched at option rom init to be a far jump to old irq 4 isr ! 136: * ! 137: */ ! 138: do_old_irq4: ! 139: .byte 0xea /* jmp absolute segment:offset */ ! 140: old_irq4: /* store what was at offset 0x2c */ ! 141: .word 0xeef3 /* placeholder for chained ISR offset */ ! 142: .word 0xf000 /* placeholder for chained ISR segment */ ! 143: ! 144: /* ! 145: * do_old_int14h ! 146: * ! 147: * Patched at option rom init to be a far jump to old int 14h isr ! 148: * ! 149: */ ! 150: do_old_int14h: ! 151: .byte 0xea /* jmp absolute segment:offset */ ! 152: old_int14h: /* store what was at offset 0x50 */ ! 153: .word 0xe739 /* placeholder for chained ISR offset */ ! 154: .word 0xf000 /* placeholder for chained ISR segment */ ! 155: ! 156: .align 16, 0xff /* aligning this table only makes hexdump prettier */ ! 157: /* ascii -> scancode, bit 7=shifted, char < 32 = +ctrl */ ! 158: /* except chars 8, 9, 13, 27 (bs, tab, enter, esc) */ ! 159: /* most int16h consumers will probably never use */ ! 160: ascii2scan: ! 161: /*00*/ .byte 0x00, 0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22 ! 162: /*08*/ .byte 0x0e, 0x17, 0x24, 0x25, 0x26, 0x1c, 0x31, 0x18 ! 163: /*10*/ .byte 0x19, 0x0f, 0x13, 0x1f, 0x14, 0x16, 0x2f, 0x11 ! 164: /*18*/ .byte 0x2d, 0x15, 0x2c, 0x01, 0x2b, 0x1b, 0x87, 0x8c ! 165: /*20*/ .byte 0x39, 0x82, 0xa8, 0x84, 0x85, 0x86, 0x88, 0x28 ! 166: /*28*/ .byte 0x8a, 0x8b, 0x89, 0x8d, 0x33, 0x0c, 0x34, 0x35 ! 167: /*30*/ .byte 0x0b, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 ! 168: /*38*/ .byte 0x09, 0x0a, 0xa7, 0x27, 0xb3, 0x0d, 0x34, 0xb5 ! 169: /*40*/ .byte 0x83, 0x9e, 0xb0, 0xae, 0xa0, 0x92, 0xa1, 0xa2 ! 170: /*48*/ .byte 0xa3, 0x97, 0xa4, 0xa5, 0xa6, 0xb2, 0xb1, 0x98 ! 171: /*50*/ .byte 0x99, 0x90, 0x93, 0x9f, 0x94, 0x96, 0xaf, 0x91 ! 172: /*58*/ .byte 0xad, 0x95, 0xac, 0x1a, 0x2b, 0x1b, 0x87, 0x8c ! 173: /*60*/ .byte 0x29, 0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22 ! 174: /*68*/ .byte 0x23, 0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18 ! 175: /*70*/ .byte 0x19, 0x10, 0x13, 0x1f, 0x14, 0x16, 0x2f, 0x11 ! 176: /*78*/ .byte 0x2d, 0x15, 0x2c, 0x9a, 0xab, 0x9b, 0xa9, 0x0e ! 177: ! 178: /* TABLES FOR NON-ASCII VGA CHARACTERS (CP437) TO ASCII */ ! 179: /* Unicode at: http://en.wikipedia.org/wiki/Code_page_437 */ ! 180: ! 181: ctrl2ascii: ! 182: /* translate vga (CP437) first 32 characters to ascii */ ! 183: /* for char 0, update the cursor position, but output nothing */ ! 184: /* lilo uses this "trick" for a background attribute update */ ! 185: .ascii "\0@@v***........*><|!PS-|^v><L-^v" ! 186: high2ascii: ! 187: /* translate vga (CP437) chars 0x80 to 0xff to ascii */ ! 188: /* these characters are mostly to visually approximate */ ! 189: /* line art characters will probably need tweaking */ ! 190: /*80*/ .ascii "CueaaaaceeeiiiAAEaAooouuyOUcLYPf" ! 191: /*a0*/ .ascii "aiounNao?--24!<>###||||++||+++++" ! 192: /*c0*/ .ascii "+--|-+||++--|-+----++++++++#-||-" ! 193: /*e0*/ .ascii "abgpesut00osiye^=+><||-=...vn2* " ! 194: ! 195: colortable: ! 196: /* vga text color is IRGB, ansi color is BGR */ ! 197: /* this table is effectively a nibble bit-reverse */ ! 198: .byte 0, 4, 2, 6, 1, 5, 3, 7 ! 199: ! 200: serial_port_base_address: ! 201: .word COM_BASE_ADDR ! 202: ! 203: /* in-memory console log ! 204: * ! 205: * It's expected that the EBDA contains a magic signature ! 206: * like 0xdeadbabe, followed by a byte of flags, followed ! 207: * by a 32-bit buffer pointer, followed by a 16-bit start ! 208: * index, followed by a 16-bit end index, followed by 16- ! 209: * bit logged character count, followed by an 8-bit flag. ! 210: */ ! 211: ! 212: #define MEMCONSOLE_BUFFER_SIZE 32768 ! 213: #define MEMCONSOLE_SIGNATURE 0xdeadbabe ! 214: #define MEMCONSOLE_ENDINDEX_OFF 0x0b ! 215: #define SGABIOS_EBDA_SIGNATURE 0x00414753 ! 216: ! 217: memconsole_buffer_start: /* pulled from ebda struct */ ! 218: .long 0x00000000 /* 0 = not found/no logging */ ! 219: memconsole_ebda_deadbabe_offset: /* bytes from start of ebda */ ! 220: .word 0x0000 /* 40:0e contains ebda seg */ ! 221: sgabios_ebda_logbuf_offset: /* bytes from start of ebda */ ! 222: .word 0x0000 /* 40:0e contains ebda seg */ ! 223: ! 224: /* ! 225: * setup_memconsole ! 226: * ! 227: * Initialize the option rom variables associated with logging ! 228: * of the legacy console output ! 229: * ! 230: * If these variables are left at zero, no logging will occur ! 231: * ! 232: * There are no parameters ! 233: * All registers except flags should be preserved ! 234: */ ! 235: ! 236: setup_memconsole: ! 237: pushaw ! 238: pushw %ds ! 239: pushw %es ! 240: pushw $BDA_SEG ! 241: popw %ds /* ds = 0x40 */ ! 242: pushw BDA_EBDA /* push word at 0x0e */ ! 243: popw %es /* es = EBDA_SEG */ ! 244: /* search for memconsole signature in ebda */ ! 245: movl $MEMCONSOLE_SIGNATURE, %eax ! 246: xorw %di, %di /* start at zero */ ! 247: movzbw %es:(%di), %cx /* cx = size of EBDA in KB */ ! 248: shlw $8, %cx /* cx = (cx * 1024) / 4 */ ! 249: cld ! 250: repnz ! 251: scasl /* search until sig found */ ! 252: subw $4, %di /* scasl always increments di, undo */ ! 253: cmpl %eax, %es:(%di) /* is signature here? */ ! 254: jnz setup_memconsole_end /* bail if so */ ! 255: movw %di, %cs:memconsole_ebda_deadbabe_offset /* save offset */ ! 256: movl %es:5(%di), %eax /* get 32-bit buffer base address */ ! 257: movl %eax, %cs:memconsole_buffer_start ! 258: setup_memconsole_end: ! 259: popw %es ! 260: popw %ds ! 261: popaw ! 262: ret ! 263: ! 264: /* ! 265: * memconsole_log_char ! 266: * ! 267: * Log the character passed in %al to the next available memory ! 268: * console log position, if any. ! 269: * ! 270: * If memconsole_buffer_start is zero, no logging will occur ! 271: * ! 272: * %al = character to be logged ! 273: * All registers except flags should be preserved ! 274: */ ! 275: ! 276: memconsole_log_char: ! 277: pushaw ! 278: pushw %ds ! 279: pushw %es ! 280: pushw %fs ! 281: pushw $BDA_SEG ! 282: popw %ds /* ds = 0x40 */ ! 283: pushw BDA_EBDA /* push word at 0x0e */ ! 284: popw %es /* es = EBDA_SEG */ ! 285: movw %ax, %si /* %si = %al = byte to write */ ! 286: movl %cs:memconsole_buffer_start, %ebp ! 287: movw %cs:memconsole_ebda_deadbabe_offset, %di ! 288: addw $MEMCONSOLE_ENDINDEX_OFF, %di /* %di points to char pos */ ! 289: orl %ebp, %ebp ! 290: jz memconsole_log_tail /* bufptr==0, no logging */ ! 291: movw %es:(%di), %bx /* bx = current position in buffer */ ! 292: cmpw $MEMCONSOLE_BUFFER_SIZE, %bx /* at end of buffer? */ ! 293: jnc memconsole_log_tail /* don't log any more if so */ ! 294: cmpb $0xd, %al /* is the char CR? */ ! 295: jz memconsole_log_tail /* if so, ignore it */ ! 296: cmpb $0x8, %al /* is the char backspace? */ ! 297: jnz memconsole_update_fsbase /* if not, log char as usual... */ ! 298: orw %bx, %bx /* make sure ptr isn't already zero */ ! 299: jz memconsole_log_tail /* if so, bail */ ! 300: decw %bx /* else point to previous character */ ! 301: jmp memconsole_update_end_ptr /* and go directly to save it */ ! 302: memconsole_update_fsbase: ! 303: movl $0xc0000100, %ecx /* ecx = IA32_FS_BASE (AMD64+) */ ! 304: rdmsr /* read what was there before */ ! 305: pushl %eax /* save away previous FS_BASE eax */ ! 306: pushl %edx /* save away previous FS_BASE edx */ ! 307: xorl %edx, %edx /* clear high 32 bits */ ! 308: movl %ebp, %eax /* eax = memconsole buffer start */ ! 309: wrmsr /* fs_base = memconsole buffer start */ ! 310: movw %si, %ax /* %ax = saved value on entry */ ! 311: movb %al, %fs:(%bx) /* log character */ ! 312: popl %edx /* restore previous FS_BASE edx */ ! 313: popl %eax /* restore previous FS_BASE eax */ ! 314: wrmsr /* write what was there before */ ! 315: incw %bx /* update character count */ ! 316: memconsole_update_end_ptr: ! 317: movw %bx, %es:(%di) /* save new end pointer */ ! 318: addw $2, %di /* numchars stored at next word */ ! 319: movw %bx, %es:(%di) /* save new numchar value */ ! 320: memconsole_log_tail: ! 321: popw %fs ! 322: popw %es ! 323: popw %ds ! 324: popaw ! 325: ret ! 326: ! 327: /* sgabioslog_setup_ebda ! 328: * ! 329: * SGABIOS makes its own 1KB EBDA allocation to save non- ! 330: * translated characters with associated cursor positions ! 331: * for the last 256 characters output. This is organized ! 332: * with 256 bytes reserved for houskeeping, 256 bytes for ! 333: * the raw character codes, and 512 bytes of 16bit cursor ! 334: * positions to record the associated position for each. ! 335: * ! 336: * The first 4 bytes contain "SGA\0" followed by a 16-bit ! 337: * size of the allocation in bytes, followed by a 16-bit ! 338: * index indicating the next spot to be overwritten. ! 339: * ! 340: * There are no parameters ! 341: * All registers should be preserved ! 342: */ ! 343: ! 344: sgabioslog_setup_ebda: ! 345: pushf ! 346: pushaw ! 347: pushw %ds ! 348: pushw %es ! 349: pushw $BDA_SEG ! 350: popw %ds /* ds = 0x40 */ ! 351: movw BDA_EBDA, %ax /* ax = old ebda segment from 0x0e */ ! 352: subw $SGABIOS_EBDA_DELTA, %ax ! 353: movw %ax, %es /* es = new EBDA segment start */ ! 354: cmpw $EBDA_MIN_SEG, %ax /* is there room for the allocation? */ ! 355: jc sgabioslog_setup_ebda_tail /* if not, don't change anything */ ! 356: cli /* paranoid in case irq uses EBDA */ ! 357: movw %ax, BDA_EBDA /* save new EBDA segment start */ ! 358: subw $SGABIOS_EBDA_KB, BDA_MEM_SIZE /* subtract extra allocation */ ! 359: movw %ax, %ds /* ds = new EBDA segment start */ ! 360: movw $SGABIOS_EBDA_BYTES, %si /* si = offset of first byte to move */ ! 361: movzbw (%si), %cx /* cx = number of KB in EBDA */ ! 362: addb $SGABIOS_EBDA_KB, (%si) /* update EBDA size in kb */ ! 363: shlw $10, %cx /* cx = KB * 1024 = bytes in EBDA */ ! 364: movw %cx, %cs:sgabios_ebda_logbuf_offset /* new ebda space */ ! 365: xorw %di, %di /* di = new EBDA start */ ! 366: cld ! 367: rep ! 368: movsb /* move ebda by SGABIOS_EBDA_BYTES */ ! 369: movw %cs:sgabios_ebda_logbuf_offset, %bx /* bx = new buffer */ ! 370: movl $SGABIOS_EBDA_SIGNATURE, (%bx) /* setup signature */ ! 371: movw $SGABIOS_EBDA_BYTES, 4(%bx) /* bytes in new ebda buffer */ ! 372: movw $0, 6(%bx) /* next log index, new ebda buffer */ ! 373: sgabioslog_setup_ebda_tail: ! 374: popw %es ! 375: popw %ds ! 376: popaw ! 377: popf ! 378: ret ! 379: ! 380: /* ! 381: * sgabioslog_save_char ! 382: * ! 383: * Like memconsole_log_char, except the original, untranslated ! 384: * character is expected to be given in the %al register. ! 385: * ! 386: * The original character and its corresponding cursor position ! 387: * are logged to the sgabios ebda memory allocation. ! 388: * ! 389: * %al = character to be logged ! 390: * All registers except flags should be preserved ! 391: */ ! 392: ! 393: sgabioslog_save_char: ! 394: pushaw ! 395: pushw %ds ! 396: pushw %es ! 397: pushw $BDA_SEG ! 398: popw %ds /* ds = 0x40 */ ! 399: pushw BDA_EBDA /* push word at 0x0e */ ! 400: popw %es /* es = EBDA_SEG */ ! 401: movw %cs:sgabios_ebda_logbuf_offset, %di ! 402: orw %di, %di /* is offset zero? */ ! 403: jz sgabioslog_save_tail /* if so, bail */ ! 404: cmpl $SGABIOS_EBDA_SIGNATURE, %es:(%di) ! 405: jnz sgabioslog_save_tail /* bail if magic not found */ ! 406: movw %es:6(%di), %bx /* bx = index of next char output */ ! 407: movb %al, %es:SGABIOS_EBDA_LOG_START(%bx,%di) /* store character */ ! 408: movzbw %bl, %ax /* %ax = next cursor buffer index */ ! 409: shlw $1, %ax /* %ax = offset to cursor storage */ ! 410: call get_current_cursor /* %dh = row, %dl = column */ ! 411: addw $SGABIOS_EBDA_POS_START, %di /* cursor storage */ ! 412: addw %ax, %di /* %di = next cursor storage offset */ ! 413: movw %dx, %es:(%di) /* save position for logged char */ ! 414: incw %bx /* point to next char to log */ ! 415: cmpw $SGABIOS_EBDA_LOG_SIZE, %bx ! 416: jnz sgabioslog_save_index ! 417: xorw %bx, %bx /* wrap around to start */ ! 418: sgabioslog_save_index: ! 419: movw %cs:sgabios_ebda_logbuf_offset, %di ! 420: movw %bx, %es:6(%di) /* save new index */ ! 421: sgabioslog_save_tail: ! 422: popw %es ! 423: popw %ds ! 424: popaw ! 425: ret ! 426: ! 427: /* ! 428: * sgabioslog_get_char ! 429: * ! 430: * Return the character at current cursor position, last recorded ! 431: * to sgabios ebda allocation, if available. ! 432: * ! 433: * If the current cursor postition contains one of the last 256 characters ! 434: * written to the ebda buffer, return that character, else return 0. ! 435: * ! 436: * If sgabios_ebdda_logbuf_offset is zero, %al will be 0 and zf set ! 437: * ! 438: * All registers except flags and %al should be preserved ! 439: */ ! 440: ! 441: sgabioslog_get_char: ! 442: pushaw ! 443: movw %sp, %bp ! 444: movb $0, 14(%bp) /* %al on stack = 0 */ ! 445: pushw %ds ! 446: pushw %es ! 447: pushw $BDA_SEG ! 448: popw %ds /* ds = 0x40 */ ! 449: pushw BDA_EBDA /* push word at 0x0e */ ! 450: popw %es /* es = EBDA_SEG */ ! 451: movw %cs:sgabios_ebda_logbuf_offset, %di ! 452: orw %di, %di ! 453: jz sgabioslog_get_tail /* offset==0, no logging */ ! 454: cmpl $SGABIOS_EBDA_SIGNATURE, %es:(%di) ! 455: jnz sgabioslog_get_tail /* bail if magic not found */ ! 456: call get_current_cursor /* dh = row, dl = col */ ! 457: std /* scan backwards in mem */ ! 458: movw %es:6(%di), %bx /* bx = index of next char output */ ! 459: decw %bx /* %bx = offset of last char in buf */ ! 460: jnc sgabioslog_got_pos ! 461: addw $SGABIOS_EBDA_LOG_SIZE, %bx /* bx position wrap around */ ! 462: sgabioslog_got_pos: ! 463: movw %bx, %ax /* %ax = last cursor pos written */ ! 464: shlw $1, %ax /* %ax = offset of last cursor pos */ ! 465: addw $SGABIOS_EBDA_POS_START, %di /* %di = first cursor position */ ! 466: addw %ax, %di /* %di = offset in ebda */ ! 467: movw %dx, %ax /* %ax = cursor pos to compare */ ! 468: movw %bx, %cx /* %cx = positions before wrap */ ! 469: jcxz sgabioslog_cmp_wrap /* if zero, try from end next */ ! 470: repnz ! 471: scasw /* search until position match */ ! 472: addw $2, %di /* scasd always decrements di, undo */ ! 473: cmpw %ax, %es:(%di) /* did it really match? */ ! 474: jz sgabioslog_cursor_match /* if so, do something */ ! 475: sgabioslog_cmp_wrap: ! 476: movw %cs:sgabios_ebda_logbuf_offset, %di ! 477: addw $SGABIOS_EBDA_POS_LAST, %di /* %di = last cursor storage */ ! 478: movw $SGABIOS_EBDA_LOG_SIZE, %cx /* %cx = compare all positions */ ! 479: repnz ! 480: scasw /* search until position match */ ! 481: addw $2, %di /* scasd always decrements di, undo */ ! 482: cmpw %ax, %es:(%di) /* did it really match? */ ! 483: jnz sgabioslog_get_tail /* if not, bail */ ! 484: sgabioslog_cursor_match: ! 485: /* %di contains the EBDA offset of the matching position */ ! 486: /* convert this into a memconsole offset */ ! 487: subw $512, %di /* take off the storage offset */ ! 488: subw %cs:sgabios_ebda_logbuf_offset, %di /* and ebda offset */ ! 489: shrw $1, %di /* %di = char position index */ ! 490: addw %cs:sgabios_ebda_logbuf_offset, %di /* add back ebda offset */ ! 491: addw $SGABIOS_EBDA_LOG_START, %di /* and add back log offset */ ! 492: movb %es:(%di), %al /* get related saved character */ ! 493: movb %al, 14(%bp) /* %al on stack = logged char */ ! 494: sgabioslog_get_tail: ! 495: popw %es ! 496: popw %ds ! 497: popaw ! 498: ret ! 499: ! 500: /* ! 501: * multibyteinput ! 502: * ! 503: * When an escape key is detected, the input routines will attempt to ! 504: * capture as many characters as arrive up until a timeout, or six, ! 505: * whichever is less. ! 506: * ! 507: * This table is intended to decide what the characters after the ! 508: * initial escape key translate to in terms of high and low bytes ! 509: * that go into the keyboard buffer the high byte is the scancode, ! 510: * the low byte is ascii, but for special keys this is usually 0xe0 ! 511: * or 0x00. ! 512: * ! 513: * This table is formatted so that the first word is a scancode + ! 514: * ascii pair (as returned by int 16h, ah = 10h or 11h). Immediately ! 515: * following is a nul-terminated ascii string to match in order to ! 516: * use the corresponding scancode+ascii word. ! 517: * ! 518: * The search through this table is terminated by a match or finding ! 519: * a 0 scancode+ascii word. ! 520: * ! 521: * FIXME: all the low bytes are now zero, get rid of them? ! 522: */ ! 523: multibyteinput: ! 524: .byte 0x3b /* F1 */ ! 525: .asciz "[[A" /* F1/screen */ ! 526: ! 527: .byte 0x3b /* F1 */ ! 528: .asciz "OP" /* F1/xterm/ansi */ ! 529: ! 530: .byte 0x3b /* F1 */ ! 531: .asciz "[11~" /* F1/vt400 */ ! 532: ! 533: .byte 0x3c /* F2 */ ! 534: .asciz "[[B" /* F2/screen */ ! 535: ! 536: .byte 0x3c /* F2 */ ! 537: .asciz "OQ" /* F2/xterm/ansi */ ! 538: ! 539: .byte 0x3c /* F2 */ ! 540: .asciz "[12~" /* F2/vt400 */ ! 541: ! 542: .byte 0x3d /* F3 */ ! 543: .asciz "[[C" /* F3/screen */ ! 544: ! 545: .byte 0x3d /* F3 */ ! 546: .asciz "OR" /* F3/xterm/ansi */ ! 547: ! 548: .byte 0x3d /* F3 */ ! 549: .asciz "[13~" /* F3/vt400 */ ! 550: ! 551: .byte 0x3e /* F4 */ ! 552: .asciz "[[D" /* F4/screen */ ! 553: ! 554: .byte 0x3e /* F4 */ ! 555: .asciz "OS" /* F4/xterm/ansi */ ! 556: ! 557: .byte 0x3e /* F4 */ ! 558: .asciz "[14~" /* F4/vt400 */ ! 559: ! 560: .byte 0x3f /* F5 */ ! 561: .asciz "[[E" /* F5/screen */ ! 562: ! 563: .byte 0x3f /* F5 */ ! 564: .asciz "[15~" /* F5/xterm */ ! 565: ! 566: .byte 0x3f /* F5 */ ! 567: .asciz "OT" /* F5/ansi */ ! 568: ! 569: .byte 0x40 /* F6 */ ! 570: .asciz "[17~" /* F6/screen/vt220/xterm/vt400 */ ! 571: ! 572: .byte 0x40 /* F6 */ ! 573: .asciz "OU" /* F6/ansi */ ! 574: ! 575: .byte 0x41 /* F7 */ ! 576: .asciz "[18~" /* F7/screen/vt220/xterm/vt400 */ ! 577: ! 578: .byte 0x41 /* F7 */ ! 579: .asciz "OV" /* F7/ansi */ ! 580: ! 581: .byte 0x42 /* F8 */ ! 582: .asciz "[19~" /* F8/screen/vt220/xterm/vt400 */ ! 583: ! 584: .byte 0x42 /* F8 */ ! 585: .asciz "OW" /* F8/ansi */ ! 586: ! 587: .byte 0x43 /* F9 */ ! 588: .asciz "[20~" /* F9/screen/vt220/xterm/vt400 */ ! 589: ! 590: .byte 0x43 /* F9 */ ! 591: .asciz "OX" /* F9/ansi */ ! 592: ! 593: .byte 0x44 /* F10 */ ! 594: .asciz "[21~" /* F10/screen/vt220/xterm/vt400 */ ! 595: ! 596: .byte 0x44 /* F10 */ ! 597: .asciz "OY" /* F10/ansi */ ! 598: ! 599: .byte 0x85 /* F11 */ ! 600: .asciz "[23~" /* F11/screen/xterm/vt400 */ ! 601: ! 602: .byte 0x85 /* F11 */ ! 603: .asciz "OZ" /* F11/ansi */ ! 604: ! 605: .byte 0x86 /* F12 */ ! 606: .asciz "[24~" /* F12/screen/xterm/vt400 */ ! 607: ! 608: .byte 0x52 /* Insert */ ! 609: .asciz "[2~" /* Insert/screen/vt102/xterm */ ! 610: ! 611: .byte 0x53 /* Delete */ ! 612: .asciz "[3~" /* Delete/screen/vt102/xterm */ ! 613: ! 614: .byte 0x4b /* Left */ ! 615: .asciz "OD" /* Left/screen/vt102 */ ! 616: ! 617: .byte 0x4b /* Left */ ! 618: .asciz "[D" /* Left/xterm */ ! 619: ! 620: .byte 0x47 /* Home */ ! 621: .asciz "[1~" /* Home/screen/vt102 */ ! 622: ! 623: .byte 0x47 /* Home */ ! 624: .asciz "[H" /* Home/xterm */ ! 625: ! 626: .byte 0x4f /* End */ ! 627: .asciz "[4~" /* End/screen/vt102 */ ! 628: ! 629: .byte 0x4f /* End */ ! 630: .asciz "[F" /* End/xterm */ ! 631: ! 632: .byte 0x48 /* Up */ ! 633: .asciz "OA" /* Up/screen/vt102 app */ ! 634: ! 635: .byte 0x48 /* Up */ ! 636: .asciz "[A" /* Up/xterm/vt102 ansi */ ! 637: ! 638: .byte 0x50 /* Down */ ! 639: .asciz "OB" /* Down/screen/vt102 app */ ! 640: ! 641: .byte 0x50 /* Down */ ! 642: .asciz "[B" /* Down/xterm/vt102 ansi */ ! 643: ! 644: .byte 0x49 /* PageUp */ ! 645: .asciz "[5~" /* PageUp/screen/vt102/xterm */ ! 646: ! 647: .byte 0x51 /* PageDown */ ! 648: .asciz "[6~" /* PageDown/screen/vt102/xterm */ ! 649: ! 650: .byte 0x4d /* Right */ ! 651: .asciz "OC" /* Right/screen/vt102 app */ ! 652: ! 653: .byte 0x4d /* Right */ ! 654: .asciz "[C" /* Right/xterm/vt102 ansi */ ! 655: ! 656: .byte 0 /* end of table marker */ ! 657: ! 658: /* init_serial_port ! 659: * ! 660: * Initialize serial port to 115200,8n1 ! 661: * Serial interrupts disabled ! 662: * ! 663: * All registers except flags preserved ! 664: */ ! 665: ! 666: init_serial_port: ! 667: pushw %ax ! 668: pushw %dx ! 669: pushw %bx ! 670: movw %cs:serial_port_base_address, %dx ! 671: addw $IER_OFFSET, %dx ! 672: xorb %al, %al ! 673: outb %al, %dx /* disable all serial interrupts */ ! 674: addw $(LCR_OFFSET - IER_OFFSET), %dx /* LCR */ ! 675: movb $(LCR_VALUE|LCR_DLAB), %al ! 676: outb %al, %dx /* enable divisor access */ ! 677: movw %cs:serial_port_base_address, %dx ! 678: movw $(PORT_DIVISOR/PORT_SPEED), %bx ! 679: movb %bl, %al /* al = lsb of divisor */ ! 680: outb %al, %dx /* set divisor latch lsb */ ! 681: movb %bh, %al /* al = msb of divisor */ ! 682: incw %dx ! 683: outb %al, %dx /* set divisor latch msb */ ! 684: movw %cs:serial_port_base_address, %dx ! 685: addw $LCR_OFFSET, %dx ! 686: movb $LCR_VALUE, %al ! 687: outb %al, %dx /* disable divisor access */ ! 688: addw $(MCR_OFFSET - LCR_OFFSET), %dx /* MCR */ ! 689: movb $MCR_DTRRTS, %al ! 690: outb %al, %dx /* enable DTR + RTS */ ! 691: movw %cs:serial_port_base_address, %dx ! 692: addw $FCR_OFFSET, %dx ! 693: movb $FCR_FIFO_ENABLE, %al ! 694: outb %al, %dx /* enable FIFOs */ ! 695: popw %bx ! 696: popw %dx ! 697: popw %ax ! 698: ret ! 699: ! 700: ! 701: /* get_serial_lsr ! 702: * ! 703: * return serial line status register in %al ! 704: * return offset to serial port line status register io port in %dx ! 705: * all other registers except flags unchanged ! 706: * ! 707: * if status == 0xff return ZF=1, else return ZF=0 ! 708: */ ! 709: ! 710: get_serial_lsr: ! 711: movw %cs:serial_port_base_address, %dx ! 712: addw $LSR_OFFSET, %dx ! 713: inb %dx, %al ! 714: cmpb $0xff, %al ! 715: ret ! 716: ! 717: /* ! 718: * get_byte ! 719: * ! 720: * get serial byte in %al, scancode in %ah [FIXME: EFI console input] ! 721: * ! 722: * all registers except %ax preserved ! 723: * ! 724: */ ! 725: ! 726: get_byte: ! 727: pushw %dx ! 728: pushw %bx ! 729: next_serial_char: ! 730: call get_serial_lsr /* get serial lsr in %al */ ! 731: jz get_byte_tail /* no port present... */ ! 732: testb $1, %al /* bit 0 of LSR = 1 = data available */ ! 733: jz get_byte_tail /* no input waiting */ ! 734: /* new character found on serial port */ ! 735: /* convert it to a scancode */ ! 736: movw %cs:serial_port_base_address, %dx ! 737: inb %dx, %al /* al = serial input char */ ! 738: testb $0x80, %al /* non-ascii char received? */ ! 739: jnz next_serial_char /* throw char away */ ! 740: movb %al, %dl /* dl = character read */ ! 741: pushw %ds ! 742: pushw %cs ! 743: popw %ds /* ds = cs */ ! 744: movw $ascii2scan, %bx /* table to translate ascii->scan */ ! 745: xlatb /* translate char to scancode */ ! 746: popw %ds ! 747: /* shift status is ignored at this point, may be used later */ ! 748: andb $0x7f, %al /* strip shift status from table */ ! 749: movb %al, %ah /* scancode goes in high byte */ ! 750: movb %dl, %al /* "translated" ascii in lower byte */ ! 751: cmpb $0x7f, %al /* Did the user transmit ascii DEL? */ ! 752: jnz get_byte_not_del /* if not, don't do anything to al */ ! 753: movb $0x08, %al /* else delete becomes backspace */ ! 754: get_byte_not_del: ! 755: testw %ax, %ax /* clear zero flag */ ! 756: get_byte_tail: ! 757: popw %bx ! 758: popw %dx ! 759: ret ! 760: ! 761: /* ! 762: * poll_byte ! 763: * ! 764: * get serial byte in %al, scancode in %ah [FIXME: EFI console input] ! 765: * retry up to 65536 times for an expected input byte ! 766: * ! 767: * all registers except %ax preserved ! 768: * ! 769: */ ! 770: ! 771: poll_byte: ! 772: pushw %cx ! 773: xorw %cx, %cx ! 774: poll_byte_retry: ! 775: inb $0xed, %al ! 776: call get_byte ! 777: loopz poll_byte_retry /* repeat while zf set or cx != 0 */ ! 778: popw %cx ! 779: ret ! 780: ! 781: /* ! 782: * get_multibyte ! 783: * ! 784: * after an escape character, poll for terminal keys that generate ! 785: * an escape code plus multiple bytes (up to four). ! 786: * ! 787: * if no byte is waiting, all registers preserved except flags ! 788: * if more bytes are waiting, all registers preserved except %ax and flags ! 789: * ! 790: */ ! 791: get_multibyte: ! 792: pushw %bp /* bp points to temp buffer on stack */ ! 793: pushw %bx /* bx points to multibyteinput table */ ! 794: pushw %cx /* cx will count chars */ ! 795: pushw %ax /* ax will receive chars */ ! 796: pushl $0 /* make space on stack for 4 chars */ ! 797: xorw %cx, %cx /* cx = 0 */ ! 798: movw %sp, %bp /* point bp at temp data */ ! 799: call poll_byte /* is a character waiting? */ ! 800: jz get_multibyte_tail /* if not, bail */ ! 801: get_multibyte_store: ! 802: movb %al, (%bp) /* store char received */ ! 803: incb %cl /* mark one char received */ ! 804: incw %bp /* point to next char */ ! 805: cmpb $4, %cl /* got enough chars? */ ! 806: jz got_multibyte /* no strings longer than 4 chars */ ! 807: call poll_byte /* is another char waiting? */ ! 808: jnz get_multibyte_store /* store a new one if it's there */ ! 809: got_multibyte: ! 810: movw $multibyteinput, %bx /* point to first scancode */ ! 811: got_multibyte_findkey: ! 812: movw %sp, %bp /* bp = start of buffer */ ! 813: movb %cs:(%bx), %ah /* ah = scancode */ ! 814: incw %bx /* bx = start of test string */ ! 815: orb %ah, %ah /* is it zero? */ ! 816: jz get_multibyte_tail /* if so, bail, key not found */ ! 817: got_multibyte_nextchar: ! 818: movb %cs:(%bx), %ch /* ch = test char to compare */ ! 819: incw %bx /* point to next char */ ! 820: orb %ch, %ch /* is char to compare NUL? */ ! 821: jz got_multibyte_key /* matched to end of a string! */ ! 822: cmpb %ch, (%bp) /* input tmp buf equal to test char? */ ! 823: jnz got_multibyte_try_next_key ! 824: /* note: expected that test string will be nul before input string */ ! 825: /* no attempt is made to ensure no more than 4 bytes stack read */ ! 826: incw %bp /* point to next input */ ! 827: jmp got_multibyte_nextchar ! 828: got_multibyte_try_next_key: /* align to next scancode/ascii pair */ ! 829: movb %cs:(%bx), %ch /* ch = test char to compare */ ! 830: incw %bx /* point to next char */ ! 831: orb %ch, %ch /* is char to compare NUL? */ ! 832: jnz got_multibyte_try_next_key ! 833: jmp got_multibyte_findkey ! 834: got_multibyte_key: ! 835: xorb %al, %al /* ascii value = 0 for special keys */ ! 836: movw %sp, %bp ! 837: movw %ax, 4(%bp) /* overwrite old %ax value with key */ ! 838: get_multibyte_tail: ! 839: addw $4, %sp /* pop temp space */ ! 840: popw %ax ! 841: popw %cx ! 842: popw %bx ! 843: popw %bp ! 844: ret ! 845: ! 846: /* ! 847: * send_byte ! 848: * ! 849: * send character in %al to serial port [FIXME: EFI console out] ! 850: * ! 851: * all registers preserved except flags ! 852: * ! 853: */ ! 854: ! 855: send_byte: ! 856: pushw %ax ! 857: pushw %dx ! 858: pushw %cx ! 859: testb $0x80, %al /* don't send non-ascii chars */ ! 860: jnz send_tail /* these should be translated earlier */ ! 861: movb %al, %ah /* save char to output in %ah */ ! 862: movw $0xFFF0, %cx /* only retry 65520 times */ ! 863: serial_ready_test: ! 864: call get_serial_lsr /* get serial lsr in %al */ ! 865: testb $TRANSMIT_READY_BIT, %al ! 866: loopz serial_ready_test /* if !tx ready, loop while cx!=0 */ ! 867: movb %ah, %al ! 868: movw %cs:serial_port_base_address, %dx ! 869: outb %al, %dx ! 870: send_tail: ! 871: popw %cx ! 872: popw %dx ! 873: popw %ax ! 874: ret ! 875: ! 876: /* ! 877: * translate_char ! 878: * ! 879: * translate vga character in %al to ascii ! 880: * ! 881: * returns: ! 882: * al = translated character ! 883: * ! 884: * all registers except %al preserved ! 885: * ! 886: */ ! 887: ! 888: translate_char: ! 889: pushw %bx ! 890: pushw %ds ! 891: pushw %cs ! 892: popw %ds /* ds = cs */ ! 893: testb $0x80, %al ! 894: jz translate_char_ctrl ! 895: andb $0x7f, %al ! 896: movw $high2ascii, %bx ! 897: xlatb ! 898: translate_char_ctrl: ! 899: cmpb $0x20, %al ! 900: jnc translate_char_tail ! 901: movw $ctrl2ascii, %bx ! 902: xlatb ! 903: translate_char_tail: ! 904: popw %ds ! 905: popw %bx ! 906: ret ! 907: ! 908: /* ! 909: * translate_char_tty ! 910: * ! 911: * translate vga character in %al to ascii ! 912: * unless %al == 7, 8, 10, or 13 (bell, bs, lf, cr) ! 913: * ! 914: * returns: ! 915: * al = translated character ! 916: * ! 917: * all registers except %al preserved ! 918: * ! 919: */ ! 920: ! 921: translate_char_tty: ! 922: cmpb $0x07, %al /* bell */ ! 923: jz translate_char_tty_tail ! 924: cmpb $0x08, %al /* backspace */ ! 925: jz translate_char_tty_tail ! 926: cmpb $0x0a, %al /* LF */ ! 927: jz translate_char_tty_tail ! 928: cmpb $0x0d, %al /* CR */ ! 929: jz translate_char_tty_tail ! 930: call translate_char ! 931: translate_char_tty_tail: ! 932: ret ! 933: ! 934: /* ! 935: * send_char ! 936: * ! 937: * send character 0 - 255 in %al out through serial port ! 938: * increment cursor position without control processing ! 939: * ! 940: * send_byte is used for data that isn't tracked ! 941: * ! 942: * send_char is used for text that should be tracked ! 943: * send_char outputs all characters as non-control chars ! 944: * ! 945: * returns: ! 946: * al = translated character ! 947: * ! 948: * all registers except %al preserved ! 949: * ! 950: */ ! 951: ! 952: send_char: ! 953: call sgabioslog_save_char /* save original char+pos */ ! 954: call translate_char ! 955: jmp send_char_tty_out ! 956: /* after ctrl translation, same as send_char_tty */ ! 957: ! 958: /* ! 959: * send_char_tty ! 960: * ! 961: * send character 0 - 255 in %al out through serial port ! 962: * increment cursor position *with* control processing ! 963: * for bell, linefeed, cr, and backspace (others all printable) ! 964: * ! 965: * send_byte is used for data that isn't tracked ! 966: * ! 967: * send_char_tty is used for text that should be tracked ! 968: * ! 969: * returns: ! 970: * al = translated character ! 971: * ! 972: * all registers except %al preserved ! 973: * ! 974: */ ! 975: ! 976: ! 977: /* send character 0 - 255 in %al out through serial port */ ! 978: /* increment cursor position with CR/LF/Backspace processing */ ! 979: send_char_tty: ! 980: call sgabioslog_save_char /* save original char+pos */ ! 981: call translate_char_tty ! 982: send_char_tty_out: ! 983: pushw %dx ! 984: call update_serial_cursor ! 985: call get_current_cursor /* vga cursor in %dx */ ! 986: cmpb $0x0d, %al /* CR */ ! 987: jnz send_char_tty_nul /* if not CR, check for NUL */ ! 988: orb %dl, %dl /* already at col 0? */ ! 989: jz send_char_tty_tail /* no need to re-send CR */ ! 990: send_char_tty_nul: ! 991: orb %al, %al /* %al == 0 ? (nul) */ ! 992: /* more than likely, we have NUL at this point because the caller */ ! 993: /* tried to read a char using int $0x10, %ah=8, and is trying */ ! 994: /* to re-output it with different attributes - for now send nothing */ ! 995: jz send_char_tty_tail ! 996: send_char_tty_write: ! 997: call memconsole_log_char /* log character sent */ ! 998: call send_byte ! 999: cmpb $0x07, %al /* bell */ ! 1000: jz send_char_tty_tail /* no cursor update for bell */ ! 1001: cmpb $0x08, %al /* backspace */ ! 1002: jz send_char_tty_backspace ! 1003: cmpb $0x0a, %al /* LF */ ! 1004: jz send_char_tty_lf ! 1005: cmpb $0x0d, %al /* CR */ ! 1006: jz send_char_tty_cr ! 1007: incb %dl ! 1008: jmp send_char_tty_tail ! 1009: send_char_tty_backspace: ! 1010: orb %dl, %dl ! 1011: jz send_char_tty_tail ! 1012: decb %dl ! 1013: jmp send_char_tty_tail ! 1014: send_char_tty_lf: ! 1015: incb %dh ! 1016: jmp send_char_tty_tail ! 1017: send_char_tty_cr: ! 1018: xorb %dl, %dl ! 1019: send_char_tty_tail: ! 1020: cmpb %cs:term_cols, %dl ! 1021: jc send_char_tty_check_rows ! 1022: movb %cs:term_cols, %dl ! 1023: decb %dl /* dl = cols - 1 */ ! 1024: send_char_tty_check_rows: ! 1025: cmpb %cs:term_rows, %dh ! 1026: jc send_char_tty_save_cursor ! 1027: movb %cs:term_rows, %dh ! 1028: decb %dh /* dh = rows - 1 */ ! 1029: send_char_tty_save_cursor: ! 1030: call set_current_cursor ! 1031: pushw %ds ! 1032: pushw $BDA_SEG ! 1033: popw %ds ! 1034: /* save current position as the serial terminal position */ ! 1035: /* since a character was just output at that position */ ! 1036: movw %dx, BDA_SERIAL_POS ! 1037: popw %ds ! 1038: popw %dx ! 1039: ret ! 1040: ! 1041: /* ! 1042: * send_asciz_out ! 1043: * ! 1044: * send nul terminated string pointed to by %ds:%si ! 1045: * to serial port without text tracking ! 1046: * ! 1047: * indended to be used for multi-byte send_byte ! 1048: * ! 1049: * all registers preserved except flags ! 1050: */ ! 1051: ! 1052: send_asciz_out: ! 1053: pushw %ax ! 1054: pushw %si ! 1055: cld ! 1056: send_asciz_loop: ! 1057: lodsb ! 1058: test %al,%al ! 1059: jz send_asciz_end ! 1060: call send_byte ! 1061: jmp send_asciz_loop ! 1062: send_asciz_end: ! 1063: popw %si ! 1064: popw %ax ! 1065: ret ! 1066: ! 1067: /* ! 1068: * send_string ! 1069: * ! 1070: * send cx chars in string pointed to by %ds:%si ! 1071: * to serial port with tty tracking ! 1072: * ! 1073: * indended to be used for multi-byte send_char_tty ! 1074: * ! 1075: * all registers preserved except flags ! 1076: */ ! 1077: ! 1078: send_string: ! 1079: pushw %ax ! 1080: pushw %si ! 1081: cld ! 1082: send_string_loop: ! 1083: lodsb ! 1084: call send_char_tty ! 1085: loop send_string_loop ! 1086: popw %si ! 1087: popw %ax ! 1088: ret ! 1089: ! 1090: /* ! 1091: * send_string ! 1092: * ! 1093: * send cx chars in string pointed to by %ds:%si ! 1094: * with interleaved attribute data ! 1095: * ! 1096: * indended to be used for multi-byte send_char_tty ! 1097: * with interleaved vga attribute updates ! 1098: * ! 1099: * all registers preserved except flags ! 1100: */ ! 1101: ! 1102: send_attr_string: ! 1103: pushw %ax ! 1104: pushw %bx ! 1105: pushw %si ! 1106: cld ! 1107: send_attr_string_loop: ! 1108: lodsb ! 1109: call send_char_tty ! 1110: lodsb ! 1111: movb %al, %bl ! 1112: call send_attribute /* send attribute in %bl */ ! 1113: loop send_attr_string_loop ! 1114: popw %si ! 1115: popw %bx ! 1116: popw %ax ! 1117: ret ! 1118: ! 1119: /* ! 1120: * send_number ! 1121: * ! 1122: * send ascii version of number in %al to serial port ! 1123: * ! 1124: * intended for ansi cursor positions and attributes, ! 1125: * so cursor position is not tracked/updated ! 1126: * ! 1127: * all registers preserved except flags ! 1128: */ ! 1129: ! 1130: send_number: ! 1131: pushw %ax ! 1132: pushw %bx ! 1133: aam /* ah = al/10, al = al mod 10 */ ! 1134: movw %ax, %bx /* bh = al/10, bl = al mod 10 */ ! 1135: movb %bh, %al ! 1136: aam /* ah = bh/10, al = bh mod 10 */ ! 1137: movb %al, %bh /* bh = 10s digit, bl = 1s digit */ ! 1138: movb %ah, %al /* ah = al = 100s digit */ ! 1139: testb %al, %al /* is there a 100s digit? */ ! 1140: jz send_tens /* move to tens if not */ ! 1141: orb $0x30, %al /* al = ascii value of digit */ ! 1142: call send_byte ! 1143: send_tens: ! 1144: orb %bh, %ah /* bh = 10s, ah = 100s digits */ ! 1145: jz send_ones /* non-zero = must send tens */ ! 1146: movb %bh, %al /* al = bh = 10s digit */ ! 1147: orb $0x30, %al /* al = ascii value of digit */ ! 1148: call send_byte ! 1149: send_ones: ! 1150: movb %bl, %al /* al = bl = 1s digit */ ! 1151: orb $0x30, %al /* al = ascii value of digit */ ! 1152: call send_byte ! 1153: popw %bx ! 1154: popw %ax ! 1155: ret ! 1156: ! 1157: /* ! 1158: * send_crlf ! 1159: * ! 1160: * send CRLF to serial port ! 1161: * ! 1162: * FIXME: used at vga init and for scrolling terminal ! 1163: * so position is not tracked. Callers of this routine ! 1164: * predate the code that does smart tty/cursor output. ! 1165: * ! 1166: * Callers should probably be changed to use those ! 1167: * routines or send_crlf changed to use them and ! 1168: * terminal scrolling fixed to use linefeed only. ! 1169: * ! 1170: * all registers preserved except flags ! 1171: */ ! 1172: ! 1173: send_crlf: ! 1174: pushw %ax ! 1175: movb $0x0d, %al ! 1176: call send_byte ! 1177: movb $0x0a, %al ! 1178: call send_byte ! 1179: popw %ax ! 1180: ret ! 1181: /* ! 1182: * send_ansi_csi ! 1183: * ! 1184: * send ESCAPE [ to serial port ! 1185: * ! 1186: * output is not tracked since these are control sequences ! 1187: * ! 1188: * all registers preserved except flags ! 1189: */ ! 1190: ! 1191: send_ansi_csi: /* transmit ESC [ */ ! 1192: pushw %ax ! 1193: movb $0x1b, %al /* escape */ ! 1194: call send_byte ! 1195: movb $0x5b, %al /* [ */ ! 1196: call send_byte ! 1197: popw %ax ! 1198: ret ! 1199: /* ! 1200: * send_ansi_csi_2num ! 1201: * ! 1202: * send ESC [ %dh ; %dl to serial port ! 1203: * ! 1204: * since both position and attribute updates generally have ! 1205: * two parameters, this function converts values in dx to ! 1206: * two ascii numbers. It's expected that the caller will ! 1207: * output the final trailing H or m or whatever is required. ! 1208: * ! 1209: * output is not tracked since these are control sequences ! 1210: * ! 1211: * all registers preserved except flags ! 1212: */ ! 1213: ! 1214: send_ansi_csi_2num: ! 1215: /* send ESC [ %dh ; %dl */ ! 1216: pushw %ax ! 1217: call send_ansi_csi /* esc [ */ ! 1218: movb %dh, %al ! 1219: call send_number ! 1220: movb $0x3b, %al /* semicolon */ ! 1221: call send_byte ! 1222: movb %dl, %al ! 1223: call send_number ! 1224: popw %ax ! 1225: ret ! 1226: ! 1227: /* ! 1228: * send_ansi_cursor_pos ! 1229: * ! 1230: * send ESC [ %dh+1 ; %dl+1 to serial port to position ! 1231: * cursor ! 1232: * ! 1233: * since both position and attribute updates generally have ! 1234: * two parameters, this function converts values in dx to ! 1235: * two ascii numbers, after adding 1 to both dh and dl. ! 1236: * ! 1237: * output is not tracked since this is a control sequence ! 1238: * ! 1239: * all registers preserved except flags ! 1240: */ ! 1241: ! 1242: send_ansi_cursor_pos: ! 1243: pushw %ax ! 1244: pushw %dx ! 1245: addw $0x0101, %dx /* dh += 1, dl += 1 */ ! 1246: call send_ansi_csi_2num /* send esc [ %dh+1;%dl+1 */ ! 1247: movb $0x48, %al /* H */ ! 1248: call send_byte ! 1249: popw %dx ! 1250: popw %ax ! 1251: ret ! 1252: ! 1253: /* ! 1254: * send_attribute ! 1255: * ! 1256: * send ansi attribute change ESC [ 4x ; 3y ; (1|22)m ! 1257: * if the attribute has changed since last sent (stored in bda) ! 1258: * ! 1259: * output is not tracked since this is a control sequence ! 1260: * ! 1261: * all registers preserved except flags ! 1262: */ ! 1263: ! 1264: send_attribute: ! 1265: andb $0x7f, %bl /* ansi has no bright bg */ ! 1266: pushw %ds ! 1267: pushw %es ! 1268: pushw %ax ! 1269: pushw %bx ! 1270: pushw %dx ! 1271: pushw $BDA_SEG ! 1272: popw %es /* es = 0x40 */ ! 1273: pushw %cs ! 1274: popw %ds /* ds = cs */ ! 1275: cmpb %es:BDA_COLOR_VAL, %bl ! 1276: jz send_attribute_tail ! 1277: cmpb $0x07, %bl /* is it white on black? */ ! 1278: jnz send_attribute_color ! 1279: /* for white on black, send esc [ m */ ! 1280: call send_ansi_csi ! 1281: jmp send_attribute_m /* send the m, return */ ! 1282: send_attribute_color: ! 1283: movb %bl, %ah /* ah = attribute */ ! 1284: movw $colortable, %bx ! 1285: movb %ah, %al ! 1286: andb $7, %al /* al = fg attr */ ! 1287: xlatb /* al = fg ansi num */ ! 1288: movb %al, %dl /* dl = fg ansi num */ ! 1289: movb %ah, %al ! 1290: shrb $4, %al /* al = bg attr */ ! 1291: xlatb /* al = bg ansi num */ ! 1292: movb %al, %dh /* dh = bg ansi num */ ! 1293: addw $0x281e, %dx /* 3x=setfg, 4x=setbg */ ! 1294: call send_ansi_csi_2num ! 1295: movb $0x3b, %al /* semicolon */ ! 1296: call send_byte ! 1297: shlb $4, %ah /* bright text? */ ! 1298: sets %al /* if bit 7, al = 1 */ ! 1299: js send_attribute_intensity ! 1300: movb $22, %al /* 22 = normal intensity */ ! 1301: send_attribute_intensity: ! 1302: call send_number /* either 22 or 1 */ ! 1303: send_attribute_m: ! 1304: movb $0x6d, %al /* m */ ! 1305: call send_byte ! 1306: send_attribute_tail: ! 1307: popw %dx ! 1308: popw %bx ! 1309: /* mark attribute in %bl the current one */ ! 1310: movb %bl, %es:BDA_COLOR_VAL ! 1311: popw %ax ! 1312: popw %es ! 1313: popw %ds ! 1314: ret ! 1315: ! 1316: /* ! 1317: * serial_get_input ! 1318: * ! 1319: * common code for both interrupt-driven and non-interrupt ! 1320: * driven serial input. Called only when LSR bit 1 is set. ! 1321: * ! 1322: * No parameters, no return values ! 1323: * ! 1324: * Preserves all registers ! 1325: */ ! 1326: ! 1327: serial_get_input: ! 1328: pushf ! 1329: /* be paranoid about int 9h happening during update */ ! 1330: cli ! 1331: pushaw ! 1332: pushw %ds ! 1333: /* next char input buffer is at 0x40:0x1c */ ! 1334: pushw $BDA_SEG ! 1335: popw %ds /* es = 0x40 */ ! 1336: call get_byte /* next scancode/byte in %ax */ ! 1337: cmpb $0x1b, %al /* look for escape */ ! 1338: jnz serial_gotkey /* not escape, don't look for more bytes */ ! 1339: call get_multibyte /* look for any chars after escape */ ! 1340: serial_gotkey: ! 1341: movw KBD_TAIL, %bx /* bx = keyboard tail pointer */ ! 1342: movw %ax, (%bx) /* store key in buffer */ ! 1343: addw $2, %bx /* point to next location */ ! 1344: cmpw $KBD_BUF_END, %bx /* did the buffer wrap? */ ! 1345: jb kbd_buf_no_wrap ! 1346: movw $KBD_BUF_START, %bx ! 1347: kbd_buf_no_wrap: ! 1348: movw %bx, KBD_TAIL /* update tail pointer to show key */ ! 1349: popw %ds ! 1350: popaw ! 1351: popf ! 1352: ret ! 1353: ! 1354: /* ! 1355: * irq3_isr ! 1356: * ! 1357: * entry point for irq 3 / int 0x0b / exception 11 ! 1358: * ! 1359: * Called when COM2 or COM4 have characters pending ! 1360: * ! 1361: * The segment not present exception should never happen ! 1362: * in real mode 16-bit code like this, but just to be safe, ! 1363: * if this interrupt is invoked and no characters are ! 1364: * pending on the port found in serial_port_base_address, ! 1365: * this routine will chain to the original handler. ! 1366: * ! 1367: * If characters are found pending, they will be processed ! 1368: * and control returned via iret. ! 1369: */ ! 1370: ! 1371: irq3_isr: ! 1372: #if 0 ! 1373: pushw %ax ! 1374: pushw %dx ! 1375: /* placeholder, this shouldn't ever happen */ ! 1376: /* no interrupts are configured outside COM1 */ ! 1377: call get_serial_lsr /* get serial lsr in %al */ ! 1378: jz chain_irq3 /* no port present... */ ! 1379: testb $1, %al /* bit 0 of LSR = 1 = data available */ ! 1380: jz chain_irq3 /* no input waiting */ ! 1381: call serial_get_input /* get input and stuff kbd buffer */ ! 1382: movb $0x20, %al ! 1383: outb %al, $0x20 /* send non-specific EOI */ ! 1384: popw %dx ! 1385: popw %ax ! 1386: iret ! 1387: chain_irq3: ! 1388: popw %dx ! 1389: popw %ax ! 1390: #endif ! 1391: jmp do_old_irq3 ! 1392: ! 1393: /* ! 1394: * irq4_isr ! 1395: * ! 1396: * entry point for irq 4 / int 0x0c / exception 12 ! 1397: * ! 1398: * Called when COM1 or COM3 have characters pending ! 1399: * ! 1400: * The stack fault exception may occur if code attempts to ! 1401: * read from sp:0xffff, so if this interrupt is invoked and ! 1402: * no characters are pending on the port found in ! 1403: * serial_port_base_address, this routine will chain to the ! 1404: * original handler. ! 1405: * ! 1406: * If characters are found pending, they will be processed ! 1407: * and control returned via iret. ! 1408: */ ! 1409: ! 1410: irq4_isr: ! 1411: #if 0 ! 1412: pushw %ax ! 1413: pushw %dx ! 1414: call get_serial_lsr /* get serial lsr in %al */ ! 1415: jz chain_irq4 /* no port present... */ ! 1416: testb $1, %al /* bit 0 of LSR = 1 = data available */ ! 1417: jz chain_irq4 /* no input waiting */ ! 1418: call serial_get_input /* get input and stuff kbd buffer */ ! 1419: movb $0x20, %al ! 1420: outb %al, $0x20 /* send non-specific EOI */ ! 1421: popw %dx ! 1422: popw %ax ! 1423: iret ! 1424: chain_irq4: ! 1425: popw %dx ! 1426: popw %ax ! 1427: #endif ! 1428: jmp do_old_irq4 ! 1429: ! 1430: /* ! 1431: * int14h_isr ! 1432: * ! 1433: * entry point for int 14h ! 1434: * ! 1435: */ ! 1436: int14h_isr: ! 1437: pushaw ! 1438: movw %sp, %bp ! 1439: addw $16, %bp /* bp points to return address */ ! 1440: orb %ah, %ah /* fn 0x00, initialize port */ ! 1441: jz int14h_init_port ! 1442: cmpb $0x04, %ah /* fn 0x04, extended intialize */ ! 1443: jnz chain_isr14h ! 1444: int14h_init_port: ! 1445: /* check for init port = current port */ ! 1446: pushw %ds ! 1447: pushw $BDA_SEG ! 1448: popw %ds /* ds = 0x40 */ ! 1449: movw %dx, %bx /* bx = port number */ ! 1450: shlw $1, %bx /* bx = port number * 2 */ ! 1451: andw $7, %bx /* bx = bda offset of serial io addr */ ! 1452: movw (%bx), %cx /* cx = io address of port to init */ ! 1453: popw %ds /* restore original ds */ ! 1454: cmpw %cx, %cs:serial_port_base_address ! 1455: jnz chain_isr14h /* if different, don't get in the way */ ! 1456: /* init port == current port */ ! 1457: pushw %ds ! 1458: /* LILO 22.6 HACK STARTS HERE */ ! 1459: movw (%bp), %bx /* return address for int 14h call */ ! 1460: movw 2(%bp), %ds /* return segment for int 14h call */ ! 1461: cmpl $0x4f4c494c, 0x06 /* does segment have lilo signature? */ ! 1462: jnz int14h_init_tail /* not lilo, bail on hack */ ! 1463: cmpw $0x0616, 0x0a /* does version match lilo 22.6? */ ! 1464: jnz int14h_init_tail /* unknown lilo release, bail on hack */ ! 1465: movb $0, 0x12 /* set lilo com port = 0 */ ! 1466: movl $0x90c3585a, (%bx) /* return code= pop dx;pop ax;ret;nop */ ! 1467: /* now lilo 22.6's own serial out is permanently disabled */ ! 1468: /* this prevents double-character output from int10h + serial */ ! 1469: /* this also prevents lilo from stealing serial input chars */ ! 1470: /* END LILO 22.6 HACK */ ! 1471: int14h_init_tail: ! 1472: popw %ds ! 1473: popaw ! 1474: pushw %dx /* get_serial_lsr trashes %dx */ ! 1475: call get_serial_lsr /* return serial status in %al */ ! 1476: xorb %ah, %ah /* return serial status in %ax */ ! 1477: popw %dx /* restore %dx */ ! 1478: iret ! 1479: chain_isr14h: ! 1480: popaw ! 1481: jmp do_old_int14h ! 1482: ! 1483: /* ! 1484: * int16h_isr ! 1485: * ! 1486: * entry point for int 16h ! 1487: * ! 1488: * keyboard characters are usually retrieved by calling ! 1489: * int 16h, generally placed in the keyboard buffer by ! 1490: * irq 1 (int 9h). Poll serial port for new data before ! 1491: * chaining to int 16h to fake irq 1 behavior ! 1492: * ! 1493: * all registers preserved except flags (later iret will restore) ! 1494: * bda updated with a new keypress if available ! 1495: * ! 1496: * FIXME: handle multi-byte keypresses like cursor up/down ! 1497: * to send proper scancodes for navigating lilo menus ! 1498: */ ! 1499: ! 1500: int16h_isr: ! 1501: pushw %ax ! 1502: pushw %dx ! 1503: /* each time int 16h is invoked, fake an int 9h */ ! 1504: /* except read the serial input buffer */ ! 1505: /* then chain to the original int 16h for processing */ ! 1506: call get_serial_lsr ! 1507: jz chain_isr16h /* no port present... */ ! 1508: testb $1, %al /* bit 0 of LSR = 1 = data available */ ! 1509: jz chain_isr16h /* no input waiting */ ! 1510: call serial_get_input /* get input and stuff kbd buffer */ ! 1511: /* for now, leave remaining chars pending in serial fifo */ ! 1512: /* int 16h callers only get one char at a time anyway */ ! 1513: chain_isr16h: ! 1514: popw %dx ! 1515: popw %ax ! 1516: jmp do_old_int16h ! 1517: ! 1518: /* ! 1519: * update serial_cursor ! 1520: * ! 1521: * figure out where the cursor was, and where it's going ! 1522: * use the minimal amount of serial output to get it there ! 1523: * input: vga cursor and serial cursor positions stored in BDA ! 1524: * ! 1525: * all registers preserved except flags ! 1526: * bda updated with new position for serial console cursor ! 1527: */ ! 1528: update_serial_cursor: ! 1529: pushw %ax ! 1530: pushw %bx ! 1531: pushw %dx ! 1532: pushw %ds ! 1533: pushw $BDA_SEG ! 1534: popw %ds /* ds = 0x40 */ ! 1535: call get_current_cursor /* dh = row, dl = col */ ! 1536: movw BDA_SERIAL_POS, %bx /* bh = row, bl = col */ ! 1537: subb %dl, %bl /* -col update */ ! 1538: negb %bl /* col update */ ! 1539: subb %dh, %bh /* -row update */ ! 1540: negb %bh /* row update */ ! 1541: /* handle a few special movement cases */ ! 1542: /* cr, lf, bs, bs+bs, space, else send full ansi position */ ! 1543: orb %dl, %dl /* column zero? */ ! 1544: jnz update_serial_cursor_lf ! 1545: movb $0x0d, %al /* CR */ ! 1546: call send_byte ! 1547: xorb %bl, %bl /* mark no diff in col */ ! 1548: update_serial_cursor_lf: ! 1549: cmpb $1, %bh /* +1 row? */ ! 1550: jnz update_serial_cursor_bs ! 1551: movb $0x0a, %al /* LF */ ! 1552: call send_byte ! 1553: xorb %bh, %bh /* mark no diff in row */ ! 1554: update_serial_cursor_bs: ! 1555: cmpb $-1, %bl /* one char back */ ! 1556: jz update_serial_cursor_one_bs ! 1557: cmpb $-2, %bl /* two chars back */ ! 1558: jnz update_serial_cursor_space /* check for space */ ! 1559: movb $0x08, %al /* BS */ ! 1560: call send_byte ! 1561: update_serial_cursor_one_bs: ! 1562: movb $0x08, %al /* BS */ ! 1563: call send_byte ! 1564: xorb %bl, %bl /* mark no diff in col */ ! 1565: update_serial_cursor_space: ! 1566: cmpb $1, %bl /* one char forward */ ! 1567: jnz update_serial_cursor_up ! 1568: movb $0x20, %al /* space */ ! 1569: call send_byte ! 1570: xorb %bl, %bl /* mark no diff in col */ ! 1571: update_serial_cursor_up: ! 1572: cmpb $-1, %bh /* -1 row? */ ! 1573: jnz update_serial_cursor_full /* do full ansi pos update */ ! 1574: call send_ansi_csi /* send ESC [ A (cursor up) */ ! 1575: movb $0x41, %al /* A */ ! 1576: call send_byte ! 1577: xorb %bh, %bh /* mark no diff in row */ ! 1578: update_serial_cursor_full: ! 1579: orw %bx, %bx /* diff = 0? */ ! 1580: jz update_serial_cursor_done ! 1581: call send_ansi_cursor_pos /* set cursor pos from dh,dl */ ! 1582: update_serial_cursor_done: ! 1583: movw %dx, BDA_SERIAL_POS ! 1584: popw %ds ! 1585: popw %dx ! 1586: popw %bx ! 1587: popw %ax ! 1588: ret ! 1589: ! 1590: /* ! 1591: * write_teletype ! 1592: * ! 1593: * handle int 10h, function 0eh ! 1594: * ! 1595: * ah = 0x0e write teletype character ! 1596: * al = character ascii code ! 1597: * bh = display page number ! 1598: * ! 1599: * all registers except %al preserved ! 1600: * caller will restore all registers ! 1601: */ ! 1602: ! 1603: write_teletype: ! 1604: pushw %bx ! 1605: movb $0x07, %bl /* black bg, white fg */ ! 1606: call send_attribute ! 1607: popw %bx ! 1608: call send_char_tty ! 1609: ret ! 1610: ! 1611: /* ! 1612: * write_attr_char ! 1613: * ! 1614: * handle int 10h, function 09h ! 1615: * ! 1616: * ah = 0x09 write attribute/character at current cursor position ! 1617: * al = character ascii code ! 1618: * bh = display page number ! 1619: * bl = character attribute ! 1620: * cx = repetition count ! 1621: * ! 1622: * does not update cursor position ! 1623: * all registers except %cx and %al preserved ! 1624: * caller will restore all registers ! 1625: */ ! 1626: ! 1627: write_attr_char: ! 1628: call send_attribute /* send attribute in %bl */ ! 1629: jmp write_char_common ! 1630: ! 1631: /* ! 1632: * write_char ! 1633: * ! 1634: * handle int 10h, function 0ah ! 1635: * ! 1636: * ah = 0x0a write character at current cursor position ! 1637: * al = character ascii code ! 1638: * bh = display page number ! 1639: * cx = repetition count ! 1640: * ! 1641: * does not update cursor position ! 1642: * all registers except %cx and %al preserved ! 1643: * caller will restore all registers ! 1644: */ ! 1645: ! 1646: write_char: ! 1647: pushw %bx ! 1648: movb $0x07, %bl /* black bg, white fg */ ! 1649: call send_attribute ! 1650: popw %bx ! 1651: write_char_common: ! 1652: call get_current_cursor ! 1653: call send_char ! 1654: /* make cx=0 and cx=1 only output one char */ ! 1655: cmpw $1, %cx ! 1656: jbe write_char_tail ! 1657: decw %cx ! 1658: jmp write_char ! 1659: write_char_tail: ! 1660: /* put cursor back where it was on entry */ ! 1661: call set_current_cursor ! 1662: ret ! 1663: ! 1664: /* ! 1665: * write_string ! 1666: * ! 1667: * handle int 10h, function 13h ! 1668: * ! 1669: * ah = 0x13 write character at current cursor position ! 1670: * al = 0, data = char, ..., no cursor update ! 1671: * al = 1, data = char, ..., cursor at end of string ! 1672: * al = 2, data = char+attr, ..., no cursor update ! 1673: * al = 3, data = char+attr, ..., cursor at end of string ! 1674: * bh = display page number ! 1675: * bl = character attribute for all chars (if al = 0 or 1) ! 1676: * cx = characters in string (attributes don't count) ! 1677: * dh = cursor row start ! 1678: * dl = cursor column start ! 1679: * es:bp = pointer to source text string in memory ! 1680: * ! 1681: * all registers preserved except flags ! 1682: * caller will restore all registers ! 1683: */ ! 1684: write_string: ! 1685: call set_cursor_position ! 1686: pushw %ds ! 1687: pushw %es ! 1688: pushw %es ! 1689: popw %ds /* ds = es */ ! 1690: movw %bp, %si /* si = bp */ ! 1691: testb $2, %al ! 1692: jnz write_attr_string ! 1693: call send_attribute /* send attribute in %bl */ ! 1694: test %cx, %cx ! 1695: jz write_string_empty ! 1696: call send_string /* plaintext out */ ! 1697: write_string_empty: ! 1698: jmp write_string_update_cursor ! 1699: write_attr_string: ! 1700: call send_attr_string /* text+attrib out */ ! 1701: write_string_update_cursor: ! 1702: testb $1, %al /* cursor update? */ ! 1703: jnz write_string_tail /* yes? already happened */ ! 1704: /* restore entry cursor position if no update */ ! 1705: call set_cursor_position ! 1706: write_string_tail: ! 1707: popw %es ! 1708: popw %ds ! 1709: ret ! 1710: ! 1711: /* ! 1712: * set_cursor_position ! 1713: * ! 1714: * handle int 10h, function 02h ! 1715: * ! 1716: * ah = 0x02 set cursor position ! 1717: * bh = display page number ! 1718: * dh = cursor row ! 1719: * dl = cursor column ! 1720: * ! 1721: * update bda cursor position with value in %dx ! 1722: * serial console cursor only updated on text output ! 1723: * this routine also called by set_current_cursor ! 1724: * which won't bother setting ah = 2 ! 1725: * ! 1726: * all registers preserved except flags ! 1727: */ ! 1728: ! 1729: set_cursor_position: ! 1730: pushw %ax ! 1731: pushw %ds ! 1732: pushw $BDA_SEG ! 1733: popw %ds /* ds = 0x40 */ ! 1734: movzbw %bh, %ax /* ax = page number */ ! 1735: andb $0x07, %al /* prevent invalid page number */ ! 1736: shlb $1, %al /* calculate word offset */ ! 1737: addb $BDA_CURSOR_BUF, %al /* ax = cursor save offset */ ! 1738: movw %ax, %bx /* bx = cursor save offset */ ! 1739: movw %dx, (%bx) /* save new cursor value */ ! 1740: popw %ds ! 1741: popw %ax ! 1742: ret ! 1743: ! 1744: /* ! 1745: * set_current_cursor ! 1746: * ! 1747: * get current display page number and call set_cursor_positon ! 1748: * to store the row/column value in dx to the bda ! 1749: * ! 1750: * all registers preserved except flags ! 1751: */ ! 1752: ! 1753: set_current_cursor: ! 1754: pushw %ds ! 1755: pushw %bx ! 1756: pushw $BDA_SEG ! 1757: popw %ds /* ds = 0x40 */ ! 1758: movb BDA_ACTIVE_PAGE, %bh ! 1759: call set_cursor_position ! 1760: popw %bx ! 1761: popw %ds ! 1762: ret ! 1763: ! 1764: /* ! 1765: * get_cursor_common ! 1766: * ! 1767: * read cursor position for page %bh from bda into %dx ! 1768: * ! 1769: * returns: ! 1770: * dh = cursor row ! 1771: * dl = cursor column ! 1772: * ch = cursor start scanline ! 1773: * cl = cursor end scanline ! 1774: * ! 1775: * all registers except %dx, %cx preserved ! 1776: */ ! 1777: get_cursor_common: ! 1778: pushw %bx ! 1779: pushw %ds ! 1780: pushw $BDA_SEG ! 1781: popw %ds /* ds = 0x40 */ ! 1782: movzbw %bh, %bx /* dx = current page */ ! 1783: andb $7, %bl ! 1784: shlb $1, %bl ! 1785: addb $BDA_CURSOR_BUF, %bl ! 1786: movw (%bx), %dx /* get cursor pos */ ! 1787: movw BDA_CURSOR_SCAN, %cx ! 1788: popw %ds ! 1789: popw %bx ! 1790: ret ! 1791: ! 1792: /* ! 1793: * get_current_cursor ! 1794: * ! 1795: * read cursor position for current page from bda into %dx ! 1796: * ! 1797: * returns: ! 1798: * dh = cursor row ! 1799: * dl = cursor column ! 1800: * ! 1801: * all registers except %dx preserved ! 1802: */ ! 1803: ! 1804: get_current_cursor: ! 1805: pushw %ds ! 1806: pushw %bx ! 1807: pushw %cx ! 1808: pushw $BDA_SEG ! 1809: popw %ds /* ds = 0x40 */ ! 1810: movb BDA_ACTIVE_PAGE, %bh ! 1811: call get_cursor_common ! 1812: popw %cx ! 1813: popw %bx ! 1814: popw %ds ! 1815: ret ! 1816: ! 1817: /* ! 1818: * get_cursor_position ! 1819: * ! 1820: * handle int 10h, function 03h ! 1821: * ! 1822: * ah = 0x02 get cursor position ! 1823: * bh = display page number ! 1824: * ! 1825: * returns: ! 1826: * ax = 0 ! 1827: * ch = cursor start scanline ! 1828: * ch = cursor end scanline ! 1829: * dh = cursor row ! 1830: * dl = cursor column ! 1831: * ! 1832: * all registers except %ax, %cx, %dx preserved ! 1833: */ ! 1834: ! 1835: get_cursor_position: ! 1836: call bail_if_vga_attached /* does not return if vga attached */ ! 1837: popw %ax /* not chaining, pop fake return address */ ! 1838: popw %dx /* not chaining, pop saved cursor position */ ! 1839: popaw /* not chaining to old int 10h, pop saved state */ ! 1840: call get_cursor_common ! 1841: xorw %ax, %ax ! 1842: iret ! 1843: ! 1844: /* ! 1845: * return_current_video_state ! 1846: * ! 1847: * handle int 10h, function 0fh ! 1848: * ! 1849: * ah = 0x0f return current video state ! 1850: * ! 1851: * returns: ! 1852: * ah = number of columns on screen (from 40:4a) ! 1853: * al = current video mode setting (from 40:49) ! 1854: * bh = active display page number (from 40:62) ! 1855: * ! 1856: * all registers except %ax and %bh preserved ! 1857: */ ! 1858: ! 1859: read_current_video_state: ! 1860: call bail_if_vga_attached /* does not return if vga attached */ ! 1861: popw %ax /* not chaining, pop fake return address */ ! 1862: popw %dx /* not chaining, pop saved cursor position */ ! 1863: popaw /* not chaining to old int 10h, pop saved state */ ! 1864: pushw %ds ! 1865: pushw $BDA_SEG ! 1866: popw %ds /* ds = 0x40 */ ! 1867: movb BDA_COLS, %ah ! 1868: movb BDA_MODE_NUM, %al ! 1869: movb BDA_ACTIVE_PAGE, %bh ! 1870: popw %ds ! 1871: iret ! 1872: ! 1873: /* ! 1874: * read_attr_char ! 1875: * ! 1876: * handle int 10h, function 08h ! 1877: * ! 1878: * ah = 0x08 read character/attribute from screen ! 1879: * ! 1880: * returns: ! 1881: * ah = attribute at current cursor position ! 1882: * al = character read from current cursor position ! 1883: * ! 1884: * all registers preserved except %ax and flags ! 1885: */ ! 1886: ! 1887: read_attr_char: ! 1888: call bail_if_vga_attached /* does not return if vga attached */ ! 1889: popw %ax /* not chaining, pop fake return address */ ! 1890: popw %dx /* not chaining, pop saved cursor position */ ! 1891: popaw /* not chaining to old int 10h, pop saved state */ ! 1892: pushw %ds ! 1893: pushw $BDA_SEG ! 1894: popw %ds /* ds = 0x40 */ ! 1895: movb BDA_COLOR_VAL, %ah /* return last color value */ ! 1896: call sgabioslog_get_char ! 1897: popw %ds ! 1898: iret ! 1899: ! 1900: /* ! 1901: * set_video_mode ! 1902: * ! 1903: * handle int 10h, function 00h ! 1904: * ! 1905: * ah = 0x00 set video mode ! 1906: * al = video mode ! 1907: * ! 1908: * unless bit 7 of al = 1, setting mode clears screen ! 1909: * ! 1910: * all registers preserved except %bh, %dx, flags ! 1911: */ ! 1912: ! 1913: set_video_mode: ! 1914: testb $0x80, %al /* preserve screen flag? */ ! 1915: jnz set_video_mode_tail ! 1916: call send_ansi_csi ! 1917: movb $0x32, %al /* 2 */ ! 1918: call send_byte ! 1919: movb $0x4a, %al /* J */ ! 1920: call send_byte ! 1921: set_video_mode_tail: ! 1922: movb $0x07, %bl /* white on black text */ ! 1923: call send_attribute /* send attribute in %bl */ ! 1924: /* set cursor position to 0,0 */ ! 1925: xorb %bh, %bh /* page 0 */ ! 1926: xorw %dx, %dx ! 1927: jmp set_cursor_position ! 1928: ! 1929: /* ! 1930: * scroll_page_up ! 1931: * ! 1932: * handle int 10h, function 06h ! 1933: * ! 1934: * ah = 0x06 scroll current page up ! 1935: * al = scroll distance in character rows (0 blanks entire area) ! 1936: * bh = attribute to used on blanked lines ! 1937: * ch = top row (upper left corner) of window ! 1938: * cl = left-most column (upper left corner) of window ! 1939: * dh = bottom row (lower right corner) of window ! 1940: * dl = right-most column (lower right corner) of window ! 1941: * ! 1942: * all registers preserved except flags ! 1943: */ ! 1944: ! 1945: scroll_page_up: ! 1946: pushw %si ! 1947: pushw %dx ! 1948: call get_current_cursor /* save current cursor */ ! 1949: movw %dx, %si /* si = vga cursor pos */ ! 1950: popw %dx ! 1951: cmpb $0, %al /* al = 0 = clear window */ ! 1952: jz scroll_common_clear ! 1953: pushw %ax ! 1954: call send_ansi_csi /* CSI [ %al S */ ! 1955: call send_number ! 1956: movb $0x53, %al /* S */ ! 1957: call send_byte ! 1958: popw %dx ! 1959: popw %si ! 1960: ret ! 1961: ! 1962: /* ! 1963: * scroll_common_clear ! 1964: * ! 1965: * common tail for up/down scrolls to clear window specified ! 1966: * in %cx and %dx. ! 1967: * ! 1968: * stack should contain saved copy of si ! 1969: * si = original vga cursor position on service entry ! 1970: * ! 1971: * bh = attribute to used on blanked lines ! 1972: * ch = top row (upper left corner) of window ! 1973: * cl = left-most column (upper left corner) of window ! 1974: * dh = bottom row (lower right corner) of window ! 1975: * dl = right-most column (lower right corner) of window ! 1976: */ ! 1977: scroll_common_clear: ! 1978: pushw %ax ! 1979: xchgb %bl, %bh /* bl = attribute, bh = old bl */ ! 1980: call send_attribute /* send attribute in %bl */ ! 1981: xchgb %bl, %bh /* restore bx */ ! 1982: pushw %ds ! 1983: pushw $BDA_SEG ! 1984: popw %ds /* ds = 0x40 */ ! 1985: /* check to see if region is full screen, and attribute default */ ! 1986: orw %cx, %cx /* is top left 0,0? */ ! 1987: jnz scroll_common_window /* no, handle window */ ! 1988: cmpb $0x07, %bh /* is attribute white on black? */ ! 1989: jnz scroll_common_window /* no, must write spaces */ ! 1990: #ifdef LILO_CLEAR_WORKAROUND_NOT_REQUIRED ! 1991: cmpb %cs:term_cols, %dl /* is right less than cols ? */ ! 1992: jc scroll_common_window /* if so, handle window */ ! 1993: cmpb %cs:term_rows, %dh /* is bottom less than rows ? */ ! 1994: jc scroll_common_window /* if so, handle window */ ! 1995: #endif ! 1996: /* safe to send standard clear screen sequence */ ! 1997: call send_ansi_csi /* send ESC [ */ ! 1998: movb $0x32, %al /* 2 */ ! 1999: call send_byte ! 2000: movb $0x4a, %al /* J */ ! 2001: call send_byte ! 2002: jmp scroll_common_tail ! 2003: scroll_common_window: ! 2004: pushw %dx ! 2005: movw %cx, %dx /* dx = upper right */ ! 2006: call set_current_cursor ! 2007: popw %dx ! 2008: pushw %cx ! 2009: /* setup cx with count of chars to clear per row */ ! 2010: xorb %ch, %ch ! 2011: negb %cl ! 2012: addb %dl, %cl /* cl = dl - cl */ ! 2013: incb %cl /* start = end col = clear 1 col */ ! 2014: cmpb %cs:term_cols, %cl /* is count < cols? */ ! 2015: jc scroll_common_row_ok /* if so then skip limit */ ! 2016: movb %cs:term_cols, %cl /* limit count to cols */ ! 2017: scroll_common_row_ok: ! 2018: jz scroll_common_row_done /* count == 0 ? */ ! 2019: movb $0x20, %al /* space */ ! 2020: scroll_common_space_loop: ! 2021: call send_char ! 2022: loop scroll_common_space_loop /* send cx spaces */ ! 2023: scroll_common_row_done: ! 2024: popw %cx ! 2025: incb %ch /* top left now next row */ ! 2026: cmpb %dh, %ch ! 2027: jbe scroll_common_window /* do next row */ ! 2028: scroll_common_tail: ! 2029: popw %ds ! 2030: popw %ax ! 2031: pushw %dx ! 2032: movw %si, %dx /* dx = saved vga cursor pos */ ! 2033: call set_current_cursor /* restore saved cursor */ ! 2034: popw %dx ! 2035: popw %si ! 2036: ret ! 2037: ! 2038: /* ! 2039: * scroll_page_down ! 2040: * ! 2041: * handle int 10h, function 07h ! 2042: * ! 2043: * ah = 0x07 scroll current page down ! 2044: * al = scroll distance in character rows (0 blanks entire area) ! 2045: * bh = attribute to used on blanked lines ! 2046: * ch = top row (upper left corner) of window ! 2047: * cl = left-most column (upper left corner) of window ! 2048: * dh = bottom row (lower right corner) of window ! 2049: * dl = right-most column (lower right corner) of window ! 2050: * ! 2051: * FIXME: this routine doesn't handle windowing, it currently ! 2052: * only handles one line screen scrolls and erasing entire screen ! 2053: * ! 2054: * all registers preserved except flags ! 2055: */ ! 2056: ! 2057: scroll_page_down: ! 2058: pushw %si ! 2059: pushw %dx ! 2060: call get_current_cursor /* save current cursor */ ! 2061: movw %dx, %si /* si = vga cursor pos */ ! 2062: popw %dx ! 2063: cmpb $0, %al /* al = 0 = clear window */ ! 2064: jz scroll_common_clear ! 2065: pushw %ax ! 2066: call send_ansi_csi /* CSI [ %al T */ ! 2067: call send_number ! 2068: movb $0x54, %al /* T */ ! 2069: call send_byte ! 2070: popw %dx ! 2071: popw %si ! 2072: ret ! 2073: ! 2074: /* ! 2075: * bail_if_vga_attached ! 2076: * ! 2077: * Check for vga installed, if not, return to caller. ! 2078: * If so, pop return address, return to chain_isr_10h ! 2079: * ! 2080: * expected that routine calling this one has chain_isr_10h ! 2081: * as the next item on the stack ! 2082: * ! 2083: * all registers except flags and sp preserved ! 2084: */ ! 2085: ! 2086: bail_if_vga_attached: ! 2087: cmpw $0xc000, %cs:old_int10h_seg /* vga attached? */ ! 2088: jnz bail_tail /* if not, don't modify stack */ ! 2089: addw $2, %sp /* else drop first return address */ ! 2090: bail_tail: ! 2091: ret /* return to caller or chain_isr_10h */ ! 2092: ! 2093: /* ! 2094: * int10h_isr ! 2095: * ! 2096: * entry point for int 10h ! 2097: * ! 2098: * save all registers, force return to chain to previous int10h isr ! 2099: * decide which function in ah needs to be dispatched ! 2100: * ! 2101: * ah = 0x00 set mode ! 2102: * ah = 0x01 set cursor type ! 2103: * ah = 0x02 set cursor position ! 2104: * ah = 0x03 read cursor position ! 2105: * ah = 0x04 read light pen position ! 2106: * ah = 0x05 set active display page ! 2107: * ah = 0x06 scroll active page up ! 2108: * ah = 0x07 scroll active page down ! 2109: * ah = 0x08 read attribute/character at cursor ! 2110: * ah = 0x09 write attribute/character at cursor ! 2111: * ah = 0x0a write character at cursor position ! 2112: * ah = 0x0b set color palette ! 2113: * ah = 0x0c write pixel ! 2114: * ah = 0x0d read pixel ! 2115: * ah = 0x0e write teletype ! 2116: * ah = 0x0f read current video state ! 2117: * ah = 0x10 set individual palette registers ! 2118: * ah = 0x11 character generation (font control/info) ! 2119: * ah = 0x12 alternate select (video control/info) ! 2120: * ah = 0x13 write string ! 2121: * ah = 0x1a read/write display combination code ! 2122: * ah = 0x1b return functionality/state information ! 2123: * ah = 0x1c save/restore video state ! 2124: * ah = 0x4f vesa bios calls ! 2125: * all registers preserved except flags (later iret will restore) ! 2126: */ ! 2127: ! 2128: int10h_isr: ! 2129: pushaw ! 2130: call get_current_cursor ! 2131: pushw %dx /* save current cursor */ ! 2132: pushw %bp /* need bp for indexing off stack */ ! 2133: movw %sp, %bp /* bp = sp */ ! 2134: movw 14(%bp), %dx /* restore dx from earlier pushaw */ ! 2135: popw %bp /* restore old bp */ ! 2136: pushw $chain_isr10h /* force return to chain_isr10h */ ! 2137: testb %ah, %ah ! 2138: jnz int10h_02 ! 2139: jmp set_video_mode ! 2140: int10h_02: ! 2141: cmpb $0x02, %ah ! 2142: jnz int10h_03 ! 2143: jmp set_cursor_position ! 2144: int10h_03: ! 2145: cmpb $0x03, %ah ! 2146: jnz int10h_06 ! 2147: jmp get_cursor_position ! 2148: int10h_06: ! 2149: cmpb $0x06, %ah ! 2150: jnz int10h_07 ! 2151: jmp scroll_page_up ! 2152: int10h_07: ! 2153: cmpb $0x07, %ah ! 2154: jnz int10h_08 ! 2155: jmp scroll_page_down ! 2156: int10h_08: ! 2157: cmpb $0x08, %ah ! 2158: jnz int10h_09 ! 2159: jmp read_attr_char ! 2160: int10h_09: ! 2161: cmpb $0x09, %ah ! 2162: jnz int10h_0a ! 2163: jmp write_attr_char ! 2164: int10h_0a: ! 2165: cmpb $0x0a, %ah ! 2166: jnz int10h_0e ! 2167: jmp write_char ! 2168: int10h_0e: ! 2169: cmpb $0x0e, %ah ! 2170: jnz int10h_0f ! 2171: jmp write_teletype ! 2172: int10h_0f: ! 2173: cmpb $0x0f, %ah ! 2174: jnz int10h_13 ! 2175: jmp read_current_video_state ! 2176: int10h_13: ! 2177: cmpb $0x13, %ah ! 2178: jnz int10h_default ! 2179: jmp write_string ! 2180: int10h_default: ! 2181: popw %ax /* pop chain_isr10h return address */ ! 2182: chain_isr10h: ! 2183: popw %dx /* pop saved cursor */ ! 2184: cmpw $0xc000, %cs:old_int10h_seg /* vga attached? */ ! 2185: jnz chain_post_cursor /* if not, don't restore the cursor */ ! 2186: call set_current_cursor /* restore cursor if vga attached */ ! 2187: chain_post_cursor: ! 2188: popaw ! 2189: jmp do_old_int10h ! 2190: ! 2191: /* ! 2192: * pnp_sga_init ! 2193: * ! 2194: * handle PnP initialization of option rom ! 2195: * ! 2196: * es:di = pointer to PnP structure ! 2197: * ax = indication as to which vectors should be hooked ! 2198: * by specifying th type of boot device this has ! 2199: * been selected as ! 2200: * bit 7..3= reserved(0) ! 2201: * bit 2 = 1 = connect as IPL (int 13h) ! 2202: * bit 1 = 1 = connect as primary video (int 10h) ! 2203: * bit 0 = 1 = connect as primary input (int 9h) ! 2204: * bx = card select number (probably 0xffff) ! 2205: * dx = read data port address (probably 0xffff) ! 2206: * ! 2207: * return: ! 2208: * ax = initialization status ! 2209: * bit 8 = 1 = IPL device supports int 13h block dev format ! 2210: * bit 7 = 1 = Output device supports int 10h char output ! 2211: * bit 6 = 1 = Input device supports int 9h char input ! 2212: * bit 5..4 = 00 = no IPL device attached ! 2213: * 01 = unknown whether or not IPL device attached ! 2214: * 10 = IPL device attached (RPL devices have connection) ! 2215: * 11 = reserved ! 2216: * bit 3..2 = 00 = no display device attached ! 2217: * 01 = unknown whether or not display device attached ! 2218: * 10 = display device attached ! 2219: * 11 = reserved ! 2220: * bit 1..0 = 00 = no input device attached ! 2221: * 01 = unknown whether or not input device attached ! 2222: * 10 = input device attached ! 2223: * 11 = reserved ! 2224: * ! 2225: * all registers preserved except %ax ! 2226: */ ! 2227: ! 2228: pnp_sga_init: ! 2229: /* FIXME: this is *wrong* -- init only what bios says to init */ ! 2230: movw $0xca, %ax /* 0xca = attached int 10h, 9h display, input */ ! 2231: ! 2232: /* ! 2233: * sga_init ! 2234: * ! 2235: * legacy option rom entry point ! 2236: * ! 2237: * all registers preserved ! 2238: */ ! 2239: ! 2240: sga_init: ! 2241: /* this is probably paranoid about register preservation */ ! 2242: pushfw ! 2243: cli /* more paranoia */ ! 2244: pushaw ! 2245: pushw %ds ! 2246: pushw %es ! 2247: pushw $0 ! 2248: popw %es /* es = 0 */ ! 2249: pushw %cs ! 2250: popw %ds /* ds = cs */ ! 2251: /* get original ISR */ ! 2252: movl %es:0x28, %eax /* eax = old irq 3/int 0bh */ ! 2253: movl %eax, old_irq3 /* save away old irq 4/int 0bh */ ! 2254: movl %es:0x2c, %eax /* eax = old irq 4/int 0ch */ ! 2255: movl %eax, old_irq4 /* save away old irq 4/int 0ch */ ! 2256: movl %es:0x40, %eax /* eax = old int 10h */ ! 2257: movl %eax, old_int10h /* save away old int 10h */ ! 2258: movl %es:0x50, %eax /* eax = old int 14h */ ! 2259: movl %eax, old_int14h /* save away old int 14h */ ! 2260: movl %es:0x58, %eax /* eax = old int 16h */ ! 2261: movl %eax, old_int16h /* save away old int 16h */ ! 2262: movw $irq3_isr, %es:0x28 /* new irq 3 offset */ ! 2263: movw %cs, %es:0x2a /* write new irq 3 seg */ ! 2264: movw $irq4_isr, %es:0x2c /* new irq 4 offset */ ! 2265: movw %cs, %es:0x2e /* write new irq 4 seg */ ! 2266: movw $int10h_isr, %es:0x40 /* new int 10h offset */ ! 2267: movw %cs, %es:0x42 /* write new int10h seg */ ! 2268: movw $int14h_isr, %es:0x50 /* new int 14h offset */ ! 2269: movw %cs, %es:0x52 /* write new int14h seg */ ! 2270: movw $int16h_isr, %es:0x58 /* new int 16h offset */ ! 2271: movw %cs, %es:0x5a /* write new int16h seg */ ! 2272: /* empty input buffer to prepare for terminal sizing */ ! 2273: call init_serial_port ! 2274: input_clear_loop: ! 2275: call get_byte ! 2276: jnz input_clear_loop ! 2277: movw $term_init_string, %si ! 2278: call send_asciz_out ! 2279: push $BDA_SEG ! 2280: push $BDA_SEG ! 2281: popw %ds /* ds = 0x40 */ ! 2282: popw %es /* es = 0x40 */ ! 2283: movw $BDA_CURSOR_BUF, %di ! 2284: input_timeout_loop: ! 2285: /* get input from terminal until timeout found */ ! 2286: /* store input at 40:50 - 40:5e (cursor pos) */ ! 2287: call poll_byte ! 2288: jz input_timeout ! 2289: stosb /* es:di */ ! 2290: cmpw $0x5f, %di /* 14 characters max */ ! 2291: jnz input_timeout_loop /* good for more data */ ! 2292: input_timeout: ! 2293: xorb %al, %al /* nul terminate input */ ! 2294: stosb ! 2295: cmpw $0x58, %di /* less than 8 chars? */ ! 2296: jc resize_end /* too small to have valid data */ ! 2297: movw $BDA_CURSOR_BUF, %si /* point to start */ ! 2298: lodsw /* ax = first 2 chars */ ! 2299: cmpw $0x5b1b, %ax /* was it "ESC[" ? */ ! 2300: jnz resize_end /* reply starts ESC[row;colR */ ! 2301: xorb %bl, %bl /* bl = ascii->int conversion */ ! 2302: input_first_number: ! 2303: lodsb /* al = next char */ ! 2304: cmpb $0x30, %al ! 2305: jc resize_end /* char < 0x30 invalid */ ! 2306: cmpb $0x3a, %al /* is char < 0x3a */ ! 2307: jnc input_semicolon ! 2308: andb $0x0f, %al /* al = 0 - 9 */ ! 2309: movb %bl, %ah /* ah = last conversion */ ! 2310: aad /* ax = (al + ah * 10) & 0xff */ ! 2311: movb %al, %bl /* bl = row ascii->int conversion */ ! 2312: jmp input_first_number ! 2313: input_semicolon: ! 2314: /* at this point bl should contain rows, al = ; */ ! 2315: /* sanity check, bail if invalid */ ! 2316: cmpb $0x3b, %al ! 2317: jnz resize_end /* invalid input found */ ! 2318: cmpb $0x0a, %bl /* less than 10 rows? */ ! 2319: jc suspect_loopback /* consider input invalid */ ! 2320: xorb %bh, %bh /* bh = col ascii->int conversion */ ! 2321: input_second_number: ! 2322: lodsb /* al = next char */ ! 2323: cmpb $0x30, %al ! 2324: jc resize_end /* char < 0x30 invalid */ ! 2325: cmpb $0x3a, %al /* is char < 0x3a */ ! 2326: jnc input_final_r ! 2327: andb $0x0f, %al /* al = 0 - 9 */ ! 2328: movb %bh, %ah /* ah = last conversion */ ! 2329: aad /* ax = (al + ah * 10) & 0xff */ ! 2330: movb %al, %bh /* bh = ascii->int conversion */ ! 2331: jmp input_second_number ! 2332: input_final_r: ! 2333: cmpb $0x52, %al /* is al = 'R' ? */ ! 2334: jnz suspect_loopback /* invalid input found */ ! 2335: movb %bl, %cs:term_rows /* save away bl rows value */ ! 2336: cmpw $0xc000, %cs:old_int10h_seg /* vga attached? */ ! 2337: jz resize_end /* if so, leave term_cols at 80 */ ! 2338: movb %bh, %cs:term_cols /* save away bh cols value */ ! 2339: jmp resize_end ! 2340: suspect_loopback: ! 2341: /* ! 2342: * characters were received that look like what we sent out ! 2343: * at this point, assume that a loopback device was plugged in ! 2344: * and disable any future serial port reads or writes, by pointing ! 2345: * output to port 0x2e8 (COM4) instead of 0x3f8 -- it's expected ! 2346: * that this is safe since a real port responds correctly and a ! 2347: * missing port will respond with 0xff which will terminate the ! 2348: * loop that waits for the "right" status on the port. ! 2349: */ ! 2350: movw $0x2e8, %cs:serial_port_base_address ! 2351: resize_end: ! 2352: /* clear (hopefully) overwritten cursor position buffer */ ! 2353: xorb %al, %al ! 2354: movw $BDA_CURSOR_BUF, %di ! 2355: movw $0x10, %cx ! 2356: cld ! 2357: rep ! 2358: stosb /* fill 40:50 - 40:5f with 0 */ ! 2359: pushw %cs ! 2360: popw %ds /* ds = cs */ ! 2361: call get_byte /* flush any remaining "wrong" input */ ! 2362: jnz resize_end ! 2363: call send_crlf /* place cursor on start of last line */ ! 2364: movw $mfg_string, %si ! 2365: call send_asciz_out ! 2366: call send_crlf ! 2367: movw $prod_string, %si ! 2368: call send_asciz_out ! 2369: call send_crlf ! 2370: movw $long_version, %si ! 2371: call send_asciz_out ! 2372: call send_crlf ! 2373: /* if vga attached, skip terminal message and bda setup... */ ! 2374: cmpw $0xc000, %cs:old_int10h_seg /* vga attached? */ ! 2375: jz post_bda_init_tail /* if so, don't modify BDA */ ! 2376: /* show detected terminal size, or default if none detected */ ! 2377: movw $term_info, %si ! 2378: call send_asciz_out ! 2379: pushw $BDA_SEG ! 2380: popw %ds /* ds = 0x40 */ ! 2381: movb %cs:term_cols, %al ! 2382: movb %al, BDA_COLS /* 40:4a = number of character cols */ ! 2383: movb $0, BDA_CURSOR_COL /* 40:51 = cursor0 col */ ! 2384: call send_number ! 2385: movb $0x78, %al /* x */ ! 2386: call send_byte ! 2387: movb %cs:term_rows, %al ! 2388: movb %al, %ah ! 2389: decb %ah /* ah = rows-1 */ ! 2390: movb %ah, BDA_ROWS /* 40:84 = num character rows - 1 */ ! 2391: movb %ah, BDA_CURSOR_ROW /* 40:50 = cursor0 row */ ! 2392: call send_number ! 2393: call send_crlf ! 2394: movb $3, BDA_MODE_NUM ! 2395: movb $0x29, BDA_MODE_SEL ! 2396: movw $VGA_IO_BASE, BDA_6845_ADDR ! 2397: movw $0x4000, BDA_PAGE_SIZE /* 16KB per video page */ ! 2398: /* to avoid ansi colors every character, store last attribute */ ! 2399: movb $0x07, BDA_COLOR_VAL /* 07 = black bg, white fg */ ! 2400: movw %cs, %ax ! 2401: movw $_start, BDA_ROM_OFF ! 2402: movw %ax, BDA_ROM_SEG ! 2403: post_bda_init_tail: ! 2404: /* copy BDA rows/cols to sgabios location... */ ! 2405: /* if vga card is installed, reuse those values... */ ! 2406: /* if no vga card is installed, this shouldn't change anything */ ! 2407: pushw $BDA_SEG ! 2408: popw %ds /* ds = 0x40 */ ! 2409: movb BDA_ROWS, %al ! 2410: incb %al /* bda holds rows-1 */ ! 2411: movb %al, %cs:term_rows /* sgabios rows */ ! 2412: movb BDA_COLS, %ah ! 2413: movb %ah, %cs:term_cols /* sgabios cols */ ! 2414: /* setup in-memory logging of console if desired... */ ! 2415: call setup_memconsole ! 2416: /* setup logging of last 256 characters output, if ebda has room */ ! 2417: call sgabioslog_setup_ebda ! 2418: movw $ebda_info, %si ! 2419: call send_asciz_out ! 2420: movw %cs:sgabios_ebda_logbuf_offset, %ax ! 2421: xchgb %ah, %al ! 2422: call send_number ! 2423: movb $0x20, %al ! 2424: call send_byte ! 2425: movb %ah, %al ! 2426: call send_number ! 2427: call send_crlf ! 2428: popw %es ! 2429: popw %ds ! 2430: popaw ! 2431: popf ! 2432: lret ! 2433: ! 2434: _end_sgabios:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.