Add uartctrl.rom: Control PC via COM1 attached terminal
This commit is contained in:
parent
b617709684
commit
963aebd948
3
Makefile
3
Makefile
@ -82,3 +82,6 @@ qemu-floppy5: fd360.img $(ROMS)
|
|||||||
|
|
||||||
qemu-hdd: hdd.img $(ROMS)
|
qemu-hdd: hdd.img $(ROMS)
|
||||||
$(QEMU) $(QEMU_ARGS) -boot c -hda hdd.img
|
$(QEMU) $(QEMU_ARGS) -boot c -hda hdd.img
|
||||||
|
|
||||||
|
qemu-uartctrl: uartctrl.rom
|
||||||
|
$(QEMU) $(QEMU_ARGS) -option-rom uartctrl.rom -serial stdio
|
||||||
|
325
rom/uartctrl.asm
Normal file
325
rom/uartctrl.asm
Normal file
@ -0,0 +1,325 @@
|
|||||||
|
cpu 8086
|
||||||
|
org 0x0000
|
||||||
|
|
||||||
|
; configuration for the uart chip for i/o
|
||||||
|
%define uart 0x3F8
|
||||||
|
%define irq 4
|
||||||
|
%define clock 115200
|
||||||
|
%define baud 9600
|
||||||
|
|
||||||
|
data equ (uart + 0) ; data register
|
||||||
|
ier equ (uart + 1)
|
||||||
|
fcr equ (uart + 2)
|
||||||
|
isr equ (uart + 2)
|
||||||
|
lcr equ (uart + 3)
|
||||||
|
mcr equ (uart + 4)
|
||||||
|
lsr equ (uart + 5) ; line status register
|
||||||
|
msr equ (uart + 6)
|
||||||
|
|
||||||
|
absolute 0xE0 ; data in bios data area
|
||||||
|
pstate resw 1 ; parser resume offset
|
||||||
|
parg resb 1 ; accumulator for numerical CSI arguments
|
||||||
|
section .text
|
||||||
|
|
||||||
|
db 0x55, 0xAA
|
||||||
|
db 0x00
|
||||||
|
jmp init
|
||||||
|
|
||||||
|
%defstr uart_s uart
|
||||||
|
%defstr baud_s baud
|
||||||
|
banner db "nero uartctrl: port ", uart_s, " irq ", irq + 0x30," baud ", baud_s, 0x0A, 0x0D, 0
|
||||||
|
|
||||||
|
init push ax
|
||||||
|
push dx
|
||||||
|
push bx
|
||||||
|
push si
|
||||||
|
push ds
|
||||||
|
|
||||||
|
; set dlab
|
||||||
|
mov dx, lcr
|
||||||
|
in al, dx
|
||||||
|
or al, 0x80
|
||||||
|
out dx, al
|
||||||
|
; set divisor
|
||||||
|
mov cx, (clock / baud)
|
||||||
|
; low byte
|
||||||
|
mov dx, (uart + 0)
|
||||||
|
mov al, cl
|
||||||
|
out dx, al
|
||||||
|
; high byte
|
||||||
|
mov dx, (uart + 1)
|
||||||
|
mov al, ch
|
||||||
|
out dx, al
|
||||||
|
; disable dlab
|
||||||
|
mov dx, lcr
|
||||||
|
in al, dx
|
||||||
|
and al, 0x7F
|
||||||
|
out dx, al
|
||||||
|
; disable fifo
|
||||||
|
mov dx, fcr
|
||||||
|
mov al, 0
|
||||||
|
out dx, al
|
||||||
|
; enable RX interrupt
|
||||||
|
mov dx, ier
|
||||||
|
mov al, 1
|
||||||
|
out dx, al
|
||||||
|
; set line modes (8 bits, no parity, 1 stopbit)
|
||||||
|
mov dx, lcr
|
||||||
|
mov al, 3
|
||||||
|
out dx, al
|
||||||
|
; set modem control lines (unused)
|
||||||
|
mov dx, mcr
|
||||||
|
mov al, 8
|
||||||
|
out dx, al
|
||||||
|
|
||||||
|
; hook boot interrupt
|
||||||
|
xor ax, ax
|
||||||
|
mov ds, ax
|
||||||
|
mov word [4*0x19], int19
|
||||||
|
mov word [4*0x19+2], cs
|
||||||
|
|
||||||
|
; hook video services
|
||||||
|
; keep original ptr in intvec 47h for chaining
|
||||||
|
mov ax, int10
|
||||||
|
mov bx, cs
|
||||||
|
xchg word [4*0x10], ax
|
||||||
|
xchg word [4*0x10+2], bx
|
||||||
|
mov word [4*0x47], ax
|
||||||
|
mov word [4*0x47+2], bx
|
||||||
|
|
||||||
|
; hook uart irq
|
||||||
|
mov word [4*(0x08+irq)], intu
|
||||||
|
mov word [4*(0x08+irq)+2], cs
|
||||||
|
|
||||||
|
; enable IRQ in PIC
|
||||||
|
mov dx, 0x21
|
||||||
|
in al, dx
|
||||||
|
and al, ~(1 << irq)
|
||||||
|
out dx, al
|
||||||
|
|
||||||
|
; reset parser state
|
||||||
|
mov word [0x400+pstate], parse.start
|
||||||
|
|
||||||
|
call greet
|
||||||
|
|
||||||
|
pop ds
|
||||||
|
pop si
|
||||||
|
pop bx
|
||||||
|
pop dx
|
||||||
|
pop ax
|
||||||
|
retf
|
||||||
|
|
||||||
|
greet mov si, banner
|
||||||
|
xor bx, bx
|
||||||
|
.loop mov al, [cs:si]
|
||||||
|
test al, al
|
||||||
|
jz .exit
|
||||||
|
mov ah, 0x0e
|
||||||
|
int 0x10
|
||||||
|
inc si
|
||||||
|
jmp .loop
|
||||||
|
.exit ret
|
||||||
|
|
||||||
|
putc mov ah, al
|
||||||
|
; check if transmit buffer empty
|
||||||
|
.l01 mov dx, lsr
|
||||||
|
in al, dx
|
||||||
|
test al, 0x20
|
||||||
|
jz .l01
|
||||||
|
mov al, ah
|
||||||
|
; send char to uart
|
||||||
|
mov dx, data
|
||||||
|
out dx, al
|
||||||
|
ret
|
||||||
|
|
||||||
|
pdx: ; this double-call is essentially a 4 times repeating loop
|
||||||
|
call .l1
|
||||||
|
.l1: call .l2
|
||||||
|
.l2: ; set up cl for bit shifts
|
||||||
|
mov cl, 4
|
||||||
|
; grab highest nibble from dx
|
||||||
|
mov al, dh
|
||||||
|
; remove highest nibble from dx
|
||||||
|
shl dx, cl
|
||||||
|
; shift away second-highest nibble that we accidentally copied
|
||||||
|
shr al, cl
|
||||||
|
; map 0-9 to ascii codes for '0' to '9'
|
||||||
|
add al, 0x30
|
||||||
|
; if result is larger than '9', ...
|
||||||
|
cmp al, 0x3a
|
||||||
|
jl pputc
|
||||||
|
; ... add 7 so we continue at 'A'
|
||||||
|
add al, 7
|
||||||
|
pputc mov ah, 0x0e
|
||||||
|
xor bx, bx
|
||||||
|
int 0x10
|
||||||
|
ret
|
||||||
|
|
||||||
|
; system bootstrap
|
||||||
|
int19 sti
|
||||||
|
xor ax, ax
|
||||||
|
int 0x16
|
||||||
|
mov dx, ax
|
||||||
|
call pdx
|
||||||
|
mov al, 0x0A
|
||||||
|
call pputc
|
||||||
|
mov al, 0x0D
|
||||||
|
call pputc
|
||||||
|
jmp int19
|
||||||
|
|
||||||
|
; video services
|
||||||
|
int10 cmp ah, 0x0e
|
||||||
|
jne .chain
|
||||||
|
|
||||||
|
push ax
|
||||||
|
push dx
|
||||||
|
|
||||||
|
call putc
|
||||||
|
|
||||||
|
pop dx
|
||||||
|
pop ax
|
||||||
|
|
||||||
|
.chain sub sp, 4
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
; stack: BP IP:CS IP:CS FL
|
||||||
|
|
||||||
|
push ax
|
||||||
|
push ds
|
||||||
|
|
||||||
|
xor ax, ax
|
||||||
|
mov ds, ax
|
||||||
|
; copy offset
|
||||||
|
mov ax, [4*0x47]
|
||||||
|
mov [bp+2], ax
|
||||||
|
; copy segment
|
||||||
|
mov ax, [4*0x47+2]
|
||||||
|
mov [bp+4], ax
|
||||||
|
|
||||||
|
pop ds
|
||||||
|
pop ax
|
||||||
|
|
||||||
|
pop bp
|
||||||
|
retf
|
||||||
|
|
||||||
|
|
||||||
|
; uart controller irq
|
||||||
|
intu push ax
|
||||||
|
push dx
|
||||||
|
; check if we controller has data ready
|
||||||
|
mov dx, isr
|
||||||
|
in al, dx
|
||||||
|
and al, 0xF
|
||||||
|
cmp al, 4
|
||||||
|
jne ugetc.ret
|
||||||
|
; set DS to bios data area
|
||||||
|
push bx
|
||||||
|
push ds
|
||||||
|
mov ax, 0x40
|
||||||
|
mov ds, ax
|
||||||
|
; receive data
|
||||||
|
mov dx, data
|
||||||
|
in al, dx
|
||||||
|
jmp near [pstate] ; load parser state
|
||||||
|
ugetc pop word [pstate] ; save parser state
|
||||||
|
pop ds
|
||||||
|
pop bx
|
||||||
|
; send non-specific EOI signal
|
||||||
|
.ret mov al, 0x20
|
||||||
|
out 0x20, al
|
||||||
|
pop dx
|
||||||
|
pop ax
|
||||||
|
iret
|
||||||
|
|
||||||
|
; parse loop
|
||||||
|
; this is called from inside the uart interrupt
|
||||||
|
; only call ugetc when nothing on stack, so no nested funcs
|
||||||
|
parse call ugetc
|
||||||
|
.start cmp al, 0x1B
|
||||||
|
je .esc
|
||||||
|
cmp al, 0x7F
|
||||||
|
je .bs
|
||||||
|
.ascii mov dl, al
|
||||||
|
mov bx, kmap
|
||||||
|
cs xlatb
|
||||||
|
mov dh, al
|
||||||
|
; insert key code into buffer in bios data area
|
||||||
|
.insert mov bx, [0x1C] ; get next empty slot
|
||||||
|
mov [bx], dx ; store key code
|
||||||
|
add bx, 2
|
||||||
|
cmp bx, 0x3E ; are we beyond last pos?
|
||||||
|
jc .nowrap
|
||||||
|
mov bx, 0x1E ; first position
|
||||||
|
.nowrap cmp bx, [0x1A] ; next to-read slot
|
||||||
|
je parse
|
||||||
|
mov [0x1C], bx ; commit if not full
|
||||||
|
jmp parse
|
||||||
|
.bs mov dx, 0x0E08
|
||||||
|
jmp .insert
|
||||||
|
.esc call ugetc
|
||||||
|
cmp al, 0x5B
|
||||||
|
je .csi
|
||||||
|
cmp al, 'O'
|
||||||
|
je .vt_o
|
||||||
|
jmp parse
|
||||||
|
.csi mov byte [parg], 0 ; reset argument
|
||||||
|
.csicon call ugetc
|
||||||
|
cmp al, 0x30
|
||||||
|
jc parse
|
||||||
|
cmp al, 0x3A
|
||||||
|
jnc .nonum
|
||||||
|
sub al, 0x30
|
||||||
|
mov dl, al
|
||||||
|
mov al, 0xA
|
||||||
|
mul byte [parg]
|
||||||
|
add al, dl
|
||||||
|
mov [parg], al
|
||||||
|
jmp .csicon
|
||||||
|
.nonum cmp al, '~'
|
||||||
|
jne .letter
|
||||||
|
mov al, [parg]
|
||||||
|
mov bx, fkeysn
|
||||||
|
jmp .lookup
|
||||||
|
.vt_o call ugetc ; VT100 \eO... sequences
|
||||||
|
.letter sub al, 0x40
|
||||||
|
mov bx, fkeysc
|
||||||
|
.lookup cs xlatb
|
||||||
|
cmp al, 0
|
||||||
|
je parse
|
||||||
|
mov dh, al
|
||||||
|
mov dl, 0
|
||||||
|
jmp .insert
|
||||||
|
|
||||||
|
align 128
|
||||||
|
|
||||||
|
; ascii -> XT scancode map
|
||||||
|
; this assumes US querty layout
|
||||||
|
kmap db 0x00,0x1E,0x30,0x2E, 0x20,0x12,0x21,0x22, 0x23,0x0F,0x24,0x25, 0x26,0x1C,0x31,0x18
|
||||||
|
db 0x19,0x10,0x13,0x1F, 0x14,0x16,0x2F,0x11, 0x2D,0x15,0x2C,0x01, 0x2B,0x1B,0x07,0x0C
|
||||||
|
|
||||||
|
db 0x39,0x02,0x03,0x04, 0x05,0x06,0x08,0x28, 0x0A,0x0B,0x09,0x0D, 0x33,0x0C,0x34,0x35
|
||||||
|
db 0x0B,0x02,0x03,0x04, 0x05,0x06,0x07,0x08, 0x09,0x0A,0x27,0x27, 0x33,0x0D,0x34,0x35
|
||||||
|
|
||||||
|
db 0x03,0x1E,0x30,0x2E, 0x20,0x12,0x21,0x22, 0x23,0x17,0x24,0x25, 0x26,0x32,0x31,0x18
|
||||||
|
db 0x19,0x10,0x13,0x1F, 0x14,0x16,0x2F,0x11, 0x2D,0x15,0x2C,0x1A, 0x2B,0x1B,0x07,0x0C
|
||||||
|
|
||||||
|
db 0x29,0x1E,0x30,0x2E, 0x20,0x12,0x21,0x22, 0x23,0x17,0x24,0x25, 0x26,0x32,0x31,0x18
|
||||||
|
db 0x19,0x10,0x13,0x1F, 0x14,0x16,0x2F,0x11, 0x2D,0x15,0x2C,0x1A, 0x2B,0x1B,0x29,0x70
|
||||||
|
|
||||||
|
; function keys by character
|
||||||
|
; \eO$c, looks up $c to XT scancode
|
||||||
|
; table is like ascii, except it starts at 0x40 '@'
|
||||||
|
fkeysc db 0,0x48,0x50,0x4D, 0x4B,0,0x4F,0, 0x47,0,0,0, 0,0,0,0
|
||||||
|
db 0x3B,0x3C,0x3D,0x3E, 0,0,0,0, 0,0,0,0, 0,0,0,0
|
||||||
|
db 0,0,0,0, 0,0,0,0, 0,0,0,0, 0x42,0,0,0
|
||||||
|
db 0,0,0,0, 0x3F,0x40,0x41,0x43, 0x44,0,0,0, 0,0,0,0
|
||||||
|
|
||||||
|
; function keys by numbers
|
||||||
|
; 10 entries per line
|
||||||
|
; \e[$n~, looks up $n to XT scancode
|
||||||
|
fkeysn db 0,0x47,0x52,0x53,0, 0x49,0x51,0x47,0x4F,0 ; 0-9
|
||||||
|
db 0,0x3B,0x3C,0x3D,0x3E, 0x3F,0,0x40,0x41,0x42 ; 10-19
|
||||||
|
db 0x43,0x44,0,0x85,0x86, 0,0,0,0,0 ; 20-29
|
||||||
|
db 0,0,0,0,0, 0,0,0,0,0 ; 30-39
|
||||||
|
|
||||||
|
align 512
|
Loading…
Reference in New Issue
Block a user