--- /dev/null
+#!/usr/bin/env bash
+set -ev
+
+# runtime.asm must come first to place the ISR entry at address zero
+./as.py -o writer.bin -m writer.map runtime.asm vga_console.asm host.asm ps2_keyboard.asm uart_console.asm timers.asm entry.asm
--- /dev/null
+start:
+ ( Send greetz to the l33tz )
+ #32 greetz_uart call uart_puts
+ #32 greetz_vga call vga_console_puts
+
+ #8 0xa5i8 call host_seg_upper_set
+ #8 0xc3i8 call host_seg_lower_set
+ #8 0x02i8 call host_seg_dp_set
+
+halt:
+ #8 0xc0i8 #32 host_swled !8 drop
+_halt:
+ jmp _halt
+
+
+greetz_uart:
+ "Hellorld," 0x20i8 "through" 0x20i8 "the" 0x20i8 "UART!" 0x0ai8 0x0di8 0x00i8
+
+greetz_vga:
+ "Hellorld," 0x20i8 "through" 0x20i8 "VGA!" 0x0ai8 0x0di8 0x00i8
--- /dev/null
+( Initialize host controller with reasonable defaults )
+( -- )
+host_reset:
+ ( Clear LEDs )
+ #8 0x00i8 #32 host_swled !8 drop
+ #8 0xffi8 #32 host_sseg0 !8 drop
+ #8 0xffi8 #32 host_sseg1 !8 drop
+ #8 0xffi8 #32 host_sseg2 !8 drop
+ #8 0xffi8 #32 host_sseg3 !8 drop
+ ;
+
+
+( Host flag interrupt )
+( -- )
+host_int:
+ ( Just acknowledge the interrupt and move on )
+ #32 host_flags @8
+ #32 host_flags !8 drop
+ ;
+
+
+( Print a byte to the seven-segment display upper byte )
+( b -- )
+host_seg_upper_set:
+ dup #8 0x0fi8 & ( Extract lower nibble )
+ #32 host_seg_lut + @8 ( Look up segment value )
+ #32 host_sseg2 @8 ( Read existing value )
+ #8 0x80i8 & | ( Mask out only the decimal point and combine )
+ #32 host_sseg2 !8 drop ( Write back to segment register )
+
+ lsr lsr lsr lsr ( Extract upper nibble )
+ #32 host_seg_lut + @8 ( Look up segment value )
+ #32 host_sseg3 @8 ( Read existing value )
+ #8 0x80i8 & | ( Mask out only decimal point and combine )
+ #32 host_sseg3 !8 drop ( Write back to segment register )
+
+ ;
+
+
+( Print a byte to the seven-segment display lower byte )
+( b -- )
+host_seg_lower_set:
+ dup #8 0x0fi8 & ( Extract lower nibble )
+ #32 host_seg_lut + @8 ( Look up segment value )
+ #32 host_sseg0 @8 ( Read existing value )
+ #8 0x80i8 & | ( Mask out only the decimal point and combine )
+ #32 host_sseg0 !8 drop ( Write back to segment register )
+
+ lsr lsr lsr lsr ( Extract upper nibble )
+ #32 host_seg_lut + @8 ( Look up segment value )
+ #32 host_sseg1 @8 ( Read existing value )
+ #8 0x80i8 & | ( Mask out only decimal point and combine )
+ #32 host_sseg1 !8 drop ( Write back to segment register )
+
+ ;
+
+
+( Clear the seven-segment display upper byte )
+( -- )
+seg_upper_clr:
+ #32 host_sseg2 @8 #8 0x7fi8 | ( Read original value and clear all segments except point )
+ #32 host_sseg2 !8 drop ( Write back into segment register )
+ #32 host_sseg3 @8 #8 0x7fi8 | ( Read original value and clear all segments except point )
+ #32 host_sseg3 !8 drop ( Write back into segment register )
+ ;
+
+
+( Clear the seven-segment display lower byte )
+( -- )
+seg_upper_clr:
+ #32 host_sseg0 @8 #8 0x7fi8 | ( Read original value and clear all segments except point )
+ #32 host_sseg0 !8 drop ( Write back into segment register )
+ #32 host_sseg1 @8 #8 0x7fi8 | ( Read original value and clear all segments except point )
+ #32 host_sseg1 !8 drop ( Write back into segment register )
+ ;
+
+
+( Turn on a decimal point on the seven-segment display )
+( n -- )
+host_seg_dp_set:
+ dup #8 0x03i8 - jn _host_seg_dp_set_x
+ #32 host_sseg0 +
+ dup @8 #8 0x7fi8 &
+ swap !8
+_host_seg_dp_set_x:
+ drop ;
+
+
+( Turn off a decimal point on the seven-segment display )
+( n -- )
+host_seg_dp_clr:
+ dup #8 0x03i8 - jn _host_seg_dp_clr_x
+ #32 host_sseg0 +
+ dup @8 #8 0x80i8 |
+ swap !8
+_host_seg_dp_clr_x:
+ drop ;
+
+
+( Look up table for seven-segment values for hex characters )
+host_seg_lut:
+ 0x40i8 0x79i8 0x24i8 0x30i8
+ 0x19i8 0x12i8 0x02i8 0x78i8
+ 0x00i8 0x10i8 0x08i8 0x03i8
+ 0x46i8 0x21i8 0x06i8 0x0ei8
--- /dev/null
+( Reset the PS2 controller with reasonable defaults )
+( -- )
+ps2_reset:
+ ( Enable PS2 block and Rx interrupt )
+ #8 0x41i8 #32 ps2_ctrl !8 drop
+ #8 0x01i8 #32 ps2_imask !8 drop
+ ;
+
+
+( PS2 interface interrupt )
+( -- )
+ps2_int:
+ ;
--- /dev/null
+( ---------------------------------------------------------------------------- )
+( Global address definitions )
+
+
+( VGA region bases )
+vga_scr=0x02000000
+vga_tile=0x02004000
+vga_pal=0x02006000
+
+( host registers )
+host_ctrl=0x02008000
+host_flags=0x02008001
+host_mbox=0x02008002
+host_swled=0x02008003
+host_sseg0=0x02008004
+host_sseg1=0x02008005
+host_sseg2=0x02008006
+host_sseg3=0x02008007
+
+( ps2 registers )
+ps2_ctrl=0x02008008
+ps2_imask=0x02008009
+ps2_iflag=0x0200800a
+ps2_error=0x0200800b
+ps2_data=0x0200800c
+
+( rs232 registers )
+uart_ctrl=0x02008010
+uart_baudl=0x02008011
+uart_baudh=0x02008012
+uart_imask=0x02008013
+uart_iflag=0x02008014
+uart_data=0x02008015
+
+( timer registers )
+timer0_ctrl=0x02008018
+timer0_count_l=0x02008019
+timer0_count_m=0x0200801a
+timer0_count_h=0x0200801b
+timer1_ctrl=0x0200801c
+timer1_count_l=0x0200801d
+timer1_count_m=0x0200801e
+timer1_count_h=0x0200801f
+
+
+( ---------------------------------------------------------------------------- )
+( Interrupt service routines )
+
+
+( ISR common entry point )
+( ivec -- )
+isr:
+ dup #8 5i8 - jn isr_unknown
+ dup + dup + #32 isr_jumptable + @32 >r ;
+
+ align
+isr_jumptable:
+ isr_reset
+ isr_host
+ isr_ps2
+ isr_uart
+ isr_timer0
+ isr_timer1
+
+
+( Reset )
+( -- )
+isr_reset:
+ ( Perform device-specific reset/init )
+ call vga_reset
+ call host_reset
+ call ps2_reset
+ call uart_reset
+ call timer_reset
+
+ ( enable interrupts and start )
+ ien jmp start
+
+
+( Host controller flags )
+( -- )
+isr_host:
+ call host_int
+ ien ;
+
+
+( PS2 host interface )
+( -- )
+isr_ps2:
+ call ps2_int
+ ien ;
+
+
+( RS232 UART )
+( -- )
+isr_uart:
+ call uart_int
+ ien ;
+
+
+( Timer 0 )
+( -- )
+isr_timer0:
+ call timer0_int
+ ien ;
+
+
+( Timer 1 )
+( -- )
+isr_timer1:
+ call timer1_int
+ ien ;
+
+
+( Unknown source )
+( ivec -- )
+isr_unknown:
+ #32 host_swled !8 drop idis
+_isr_unknown_halt:
+ jmp _isr_unknown_halt
+
+
+( ---------------------------------------------------------------------------- )
+( Utility subroutines )
+
+
+( Copy block of bytes, allowing for overlap )
+( dest src count -- )
+mem_move:
+ >r swap
+ >r dup r> swap
+ >r dup r> swap
+ - ( dest-src )
+ dup jz _mem_move_none
+ jp _mem_move_back
+
+ ( Copy the block front-to-back )
+_mem_move_front_loop:
+ r@ jz _mem_move_done
+ >r dup @8 r@ !8 drop
+ #8 1i8 + r> #8 1i8 +
+ #8 1i8 r> - >r
+ jmp _mem_move_front_loop
+
+_mem_move_back:
+ ( Copy the block back-to-front )
+ r@ swap >r +
+ r> r@ +
+_mem_move_back_loop:
+ r@ jz _mem_move_done
+ #8 1i8 swap -
+ >r #8 1i8 swap -
+ dup @8 r@ !8 drop r>
+ #8 1i8 r> - >r
+ jmp _mem_move_back_loop
+
+_mem_move_none:
+ drop
+_mem_move_done:
+ r> drop drop drop ;
+
+
+( Fill a block of memory with an 8-bit value )
+( dest value count -- )
+mem_set_8:
+ >r
+_mem_set_8_loop:
+ r@ jz _mem_set_8_done
+ >r dup r> swap !8
+ >r #8 1i8 + r>
+ #8 1i8 r> - >r
+ jmp _mem_set_8_loop
+_mem_set_8_done:
+ r> drop drop drop ;
+
+
+( Fill a block of memory with a 16-bit value, little-endian )
+( dest value count -- )
+mem_set_16:
+ >r
+_mem_set_16_loop:
+ r@ jz _mem_set_16_done
+ >r dup r@ swap !8 drop
+ #8 1i8 + dup r@ lsr lsr lsr lsr lsr lsr lsr lsr swap !8 drop
+ #8 1i8 + r>
+ #8 1i8 r> - >r
+ jmp _mem_set_16_loop
+_mem_set_16_done:
+ r> drop drop drop ;
--- /dev/null
+( Reset the timer blocks with reasonable defaults )
+( -- )
+timer_reset:
+ ( Enable timer 0 with 1s period, auto-restart )
+ ( #8 0x02i8 #32 timer0_count_h !8 drop )
+ ( #8 0xfai8 #32 timer0_count_m !8 drop )
+ ( #8 0xf0i8 #32 timer0_count_l !8 drop )
+ ( #8 0x0fi8 #32 timer0_ctrl !8 drop )
+ ;
+
+
+( Timer 0 interrupt )
+( -- )
+timer0_int:
+ ;
+
+
+( Timer 1 interrupt )
+( -- )
+timer1_int:
+ ;
--- /dev/null
+( Reset the UART with reasonable defaults )
+( -- )
+uart_reset:
+ ( 9600 baud, enable Tx/Rx )
+ #8 0x01i8 #32 uart_baudh !8 drop
+ #8 0x46i8 #32 uart_baudl !8 drop
+ ( #8 0x01i8 #32 uart_imask !8 drop )
+ #8 0x13i8 #32 uart_ctrl !8 drop
+ ;
+
+
+( UART interrupt )
+( -- )
+uart_int:
+ ;
+
+
+( Print a byte out the UART )
+( c -- )
+uart_putc:
+ ( Wait for available space in the Tx FIFO )
+_uart_putc_wait:
+ #32 uart_iflag @8
+ #8 0x04i8 & jz _uart_putc_wait
+
+ ( Write byte to UART data register )
+ #32 uart_data !8 drop ;
+
+
+( Print an ASCIIZ string out the UART )
+( &s -- )
+uart_puts:
+_uart_puts_loop:
+ dup @8 dup jz _uart_puts_done
+ call uart_putc
+ #8 0x01i8 + jmp _uart_puts_loop
+_uart_puts_done:
+ drop drop ;
+
+
+( Print a hex byte )
+( b -- )
+uart_put_hex8:
+ dup #8 0xf0i8 & lsr lsr lsr lsr
+ #32 uart_xdigit_lut + @8 call uart_putc
+ #8 0x0fi8 &
+ #32 uart_xdigit_lut + @8 call uart_putc
+ ;
+
+
+uart_xdigit_lut: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "a" "b" "c" "d" "e" "f"
--- /dev/null
+( Initialize VGA hardware to some reasonable defaults )
+vga_reset:
+ ( Write palette to VGA controller )
+ #8 0x00i8 #32 vga_pal #8 0x00i8 + !8 drop ( black )
+ #8 0x60i8 #32 vga_pal #8 0x01i8 + !8 drop
+ #8 0x03i8 #32 vga_pal #8 0x02i8 + !8 drop
+ #8 0x01i8 #32 vga_pal #8 0x03i8 + !8 drop ( dark blue )
+ #8 0x6ci8 #32 vga_pal #8 0x04i8 + !8 drop
+ #8 0x0di8 #32 vga_pal #8 0x05i8 + !8 drop
+ #8 0x61i8 #32 vga_pal #8 0x06i8 + !8 drop
+ #8 0x6di8 #32 vga_pal #8 0x07i8 + !8 drop ( light gray )
+ #8 0x92i8 #32 vga_pal #8 0x08i8 + !8 drop ( dark gray )
+ #8 0xe0i8 #32 vga_pal #8 0x09i8 + !8 drop
+ #8 0x1ci8 #32 vga_pal #8 0x0ai8 + !8 drop
+ #8 0x13i8 #32 vga_pal #8 0x0bi8 + !8 drop ( light blue )
+ #8 0xfci8 #32 vga_pal #8 0x0ci8 + !8 drop
+ #8 0x1fi8 #32 vga_pal #8 0x0di8 + !8 drop
+ #8 0xe3i8 #32 vga_pal #8 0x0ei8 + !8 drop
+ #8 0xffi8 #32 vga_pal #8 0x0fi8 + !8 drop ( white )
+
+ ( TODO: Reload tile memory? )
+
+ ( Initialize console )
+ #8 0x00i8 #32 vga_cursor_loc !32 drop ( Set the cursor to the beginning of the screen )
+ #8 0x3bi8 #32 vga_cursor_col !8 drop ( Set the cursor color to light blue on dark blue )
+
+ ( Clear screen )
+ #32 vga_scr #32 0x00003b20i32 #32 4800i32 call mem_set_16
+
+ ;
+
+
+( Print a character to the VGA display )
+( c -- )
+vga_console_putc:
+ #32 vga_scr #32 vga_cursor_loc @32 + dup >r
+ !8 drop
+ #32 vga_cursor_col @8 r> #8 1i8 + !8 drop
+ #32 vga_cursor_loc dup @32 #8 0x02i8 + swap !32 drop
+ ;
+
+
+( Print an ASCIIZ string out the VGA display )
+( &s -- )
+vga_console_puts:
+_vga_console_puts_loop:
+ dup @8 dup jz _vga_console_puts_done
+ call vga_console_putc
+ #8 0x01i8 + jmp _vga_console_puts_loop
+_vga_console_puts_done:
+ drop drop ;
+
+
+( ---------------------------------------------------------------------------- )
+( RAM variables )
+
+
+vga_cursor_loc=0x01000000
+vga_cursor_col=0x01000004