+video_newline:
+ movl $0, cursor_x
+ incl cursor_y
+ cmpl $25, cursor_y
+ jnz 0f
+ call scrollup
+ decl cursor_y
+0: ret
+
+scrollup:
+ pushal
+ # move 80 * 24 lines from b80a0 -> b8000
+ mov $0xb8000, %edi
+ mov $0xb80a0, %esi
+ mov $960, %ecx
+ addr32 rep movsl
+ # clear last line (b8f00)
+ mov $0xb8f00, %edi
+ xor %eax, %eax
+ mov $40, %ecx
+ addr32 rep stosl
+ popal
+ ret
+
+clearscr:
+ mov $0xb8000, %edi
+ xor %eax, %eax
+ mov $1000, %ecx
+ addr32 rep stosl
+ ret
+
+ .set UART_DATA, 0x3f8
+ .set UART_LSTAT, 0x3fd
+ .set LST_TREG_EMPTY, 0x20
+
+ser_putchar:
+ push %dx
+
+ cmp $10, %al
+ jnz 0f
+ push %ax
+ mov $13, %al
+ call ser_putchar
+ pop %ax
+
+0: mov %al, %ah
+ # wait until the transmit register is empty
+ mov $UART_LSTAT, %dx
+wait: in %dx, %al
+ and $LST_TREG_EMPTY, %al
+ jz wait
+ mov $UART_DATA, %dx
+ mov %ah, %al
+ out %al, %dx
+
+ pop %dx
+ ret
+
+
+
+ena20_msg: .asciz "A20 line enabled\n"
+
+enable_a20:
+ call test_a20
+ jnc a20done
+ call enable_a20_kbd
+ call test_a20
+ jnc a20done
+ call enable_a20_fast
+ call test_a20
+ jnc a20done
+ # keep trying ... we can't do anything useful without A20 anyway
+ jmp enable_a20
+a20done:
+ mov $ena20_msg, %esi
+ call putstr
+ ret
+
+ # CF = 1 if A20 test fails (not enabled)
+test_a20:
+ mov $0x07c000, %ebx
+ mov $0x17c000, %edx
+ movl $0xbaadf00d, (%ebx)
+ movl $0xaabbcc42, (%edx)
+ subl $0xbaadf00d, (%ebx)
+ ret
+
+ # enable A20 line through port 0x92 (fast A20)
+enable_a20_fast:
+ mov $ena20_fast_msg, %esi
+ call putstr
+
+ in $0x92, %al
+ or $2, %al
+ out %al, $0x92
+ ret
+
+ena20_fast_msg: .asciz "Attempting fast A20 enable\n"
+
+
+ # enable A20 line through the keyboard controller
+ .set KBC_DATA_PORT, 0x60
+ .set KBC_CMD_PORT, 0x64
+ .set KBC_STATUS_PORT, 0x64
+ .set KBC_CMD_RD_OUTPORT, 0xd0
+ .set KBC_CMD_WR_OUTPORT, 0xd1
+
+ .set KBC_STAT_OUT_RDY, 0x01
+ .set KBC_STAT_IN_FULL, 0x02
+
+enable_a20_kbd:
+ mov $ena20_kbd_msg, %esi
+ call putstr
+
+ call kbc_wait_write
+ mov $KBC_CMD_WR_OUTPORT, %al
+ out %al, $KBC_CMD_PORT
+ call kbc_wait_write
+ mov $0xdf, %al
+ out %al, $KBC_DATA_PORT
+ ret
+
+ena20_kbd_msg: .asciz "Attempting KBD A20 enable\n"
+
+ # wait until the keyboard controller is ready to accept another byte
+kbc_wait_write:
+ in $KBC_STATUS_PORT, %al
+ and $KBC_STAT_IN_FULL, %al
+ jnz kbc_wait_write
+ ret
+
+numbuf: .space 16