summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-05-23 17:37:18 -0700
committerH. Peter Anvin <hpa@zytor.com>2009-05-23 17:37:18 -0700
commite1192a81bddbf803feb9445a9408a9feec6159aa (patch)
tree801c24f386e3654c3d8d72b5ce1c69bcc2449948
parent89ec5fa741f415296c6d6c83da5bad32710aaa38 (diff)
downloadsyslinux-e1192a81bddbf803feb9445a9408a9feec6159aa.tar.gz
core: add a proper interrupt handler for the serial console
If we enable interrupts for the serial console, add a proper interrupt handler. Since we don't know what vector we'll end up using, or if we are shared with other devices, simply hook *all* the interrupts and poll the serial port then. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--core/bcopy32.inc8
-rw-r--r--core/cleanup.inc5
-rw-r--r--core/conio.inc60
-rw-r--r--core/head.inc1
-rw-r--r--core/io.inc35
-rw-r--r--core/layout.inc4
-rw-r--r--core/parseconfig.inc39
7 files changed, 109 insertions, 43 deletions
diff --git a/core/bcopy32.inc b/core/bcopy32.inc
index c7155574..3df69f8f 100644
--- a/core/bcopy32.inc
+++ b/core/bcopy32.inc
@@ -189,14 +189,6 @@ simple_pm_call:
;
; We typically toggle A20 twice for every 64K transferred.
;
-%define IO_DELAY_PORT 80h ; Invalid port (we hope!)
-
-slow_out: out dx, al ; Fall through
-
-%macro io_delay 0
- out IO_DELAY_PORT,al
- out IO_DELAY_PORT,al
-%endmacro
section .data
alignz 2
diff --git a/core/cleanup.inc b/core/cleanup.inc
index 1b00e0b0..063ed73e 100644
--- a/core/cleanup.inc
+++ b/core/cleanup.inc
@@ -49,6 +49,7 @@ cleanup_hardware:
int 10h
.no_vmware:
%endif
-
popad
- ret
+
+ ; If we enabled serial port interrupts, clean them up now
+ jmp sirq_cleanup
diff --git a/core/conio.inc b/core/conio.inc
index 4488c94a..16c39c65 100644
--- a/core/conio.inc
+++ b/core/conio.inc
@@ -261,7 +261,7 @@ write_serial:
xchg dx,bx ; DX -> THR
pop ax
- call slow_out ; Send data
+ slow_out dx,al ; Send data
.noserial: popad
popfd
.end: ret
@@ -294,10 +294,14 @@ pollchar:
mov dx,[SerialPort]
and dx,dx
jz .done ; No serial port -> no input
- add dx,byte 5 ; DX -> LSR
+ mov ax,[SerialTail] ; Already-queued input?
+ cli
+ cmp ax,[SerialHead]
+ jne .done_sti ; If so, return ZF = 0
+ add dx,5 ; DX -> LSR
in al,dx
test al,1 ; ZF = 0 if data pending
- jz .done
+ jz .done_sti
inc dx ; DX -> MSR
mov ah,[FlowIgnore] ; Required status bits
in al,dx
@@ -305,12 +309,15 @@ pollchar:
cmp al,ah
setne al
dec al ; Set ZF = 0 if equal
+.done_sti: sti
.done: popad
ret
;
; getchar: Read a character from keyboard or serial port
;
+getchar.sti_again:
+ sti
getchar:
.again:
call do_idle
@@ -320,20 +327,38 @@ getchar:
mov bx,[SerialPort]
and bx,bx
jz .again
+ mov ax,[SerialTail]
+ cli
+ cmp ax,[SerialHead]
+ jne .serial_queued
lea dx,[bx+5] ; DX -> LSR
in al,dx
test al,1
- jz .again
+ jz .sti_again
inc dx ; DX -> MSR
mov ah,[FlowIgnore]
in al,dx
and al,ah
cmp al,ah
- jne .again
+ jne .sti_again
.serial: xor ah,ah ; Avoid confusion
mov dx,bx ; Data port
in al,dx ; Read data
- ret
+ sti
+ jmp .done
+.serial_queued:
+ sti ; We already know we'll consume data
+ xchg bx,ax
+ push ds
+ mov ax,aux_seg + (aux.serial >> 4)
+ mov ds,ax
+ mov al,[bx]
+ pop ds
+ inc bx
+ and bx,serial_buf_size-1
+ mov [SerialTail],bx
+ jmp .done
+
.kbd: mov ah,10h ; Get keyboard input
int 16h
cmp al,0E0h
@@ -345,8 +370,8 @@ getchar:
mov bx,KbdMap ; Convert character sets
xlatb
.func_key:
- call reset_idle ; Character received
- ret
+.done:
+ jmp reset_idle ; Character received
%ifdef DEBUG_TRACERS
;
@@ -387,13 +412,20 @@ ScreenSize equ $
VidCols resb 1 ; Columns on screen-1
VidRows resb 1 ; Rows on screen-1
-; Serial console stuff...
-BaudDivisor resw 1 ; Baud rate divisor
+; Serial console stuff; don't put this in .config becasue we don't want
+; loading a new config file to undo this setting.
+ section .data
+ alignz 4
+SerialPort dw 0 ; Serial port base (or 0 for no serial port)
+BaudDivisor dw 115200/9600 ; Baud rate divisor
FlowControl equ $
-FlowOutput resb 1 ; Outputs to assert for serial flow
-FlowInput resb 1 ; Input bits for serial flow
-FlowIgnore resb 1 ; Ignore input unless these bits set
-FlowDummy resb 1 ; Unused
+FlowOutput db 0 ; Outputs to assert for serial flow
+FlowInput db 0 ; Input bits for serial flow
+FlowIgnore db 0 ; Ignore input unless these bits set
+FlowDummy db 0 ; Unused
+ section .bss
TextAttribute resb 1 ; Text attribute for message file
DisplayMask resb 1 ; Display modes mask
+
+%include "serirq.inc"
diff --git a/core/head.inc b/core/head.inc
index 37f1b36f..7117b4ee 100644
--- a/core/head.inc
+++ b/core/head.inc
@@ -27,5 +27,6 @@
%include "bios.inc"
%include "tracers.inc"
%include "stack.inc"
+%include "io.inc"
%endif ; _HEAD_INC
diff --git a/core/io.inc b/core/io.inc
new file mode 100644
index 00000000..71613463
--- /dev/null
+++ b/core/io.inc
@@ -0,0 +1,35 @@
+;; -----------------------------------------------------------------------
+;;
+;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
+;; Copyright 2009 Intel Corporation; author: H. Peter Anvin
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+;; Boston MA 02111-1307, USA; either version 2 of the License, or
+;; (at your option) any later version; incorporated herein by reference.
+;;
+;; -----------------------------------------------------------------------
+
+;;
+;; io.inc
+;;
+;; I/O related macros
+;;
+
+%ifndef _IO_INC
+%define _IO_INC
+
+%define IO_DELAY_PORT 80h ; Invalid port (we hope!)
+
+%macro io_delay 0.nolist
+ out IO_DELAY_PORT,al
+ out IO_DELAY_PORT,al
+%endmacro
+
+%macro slow_out 2.nolist
+ out %1,%2
+ io_delay
+%endmacro
+
+%endif ; _IO_INC
diff --git a/core/layout.inc b/core/layout.inc
index 8d567455..8c2e2485 100644
--- a/core/layout.inc
+++ b/core/layout.inc
@@ -93,11 +93,15 @@ RBFG_brainfuck: resb 2048 ; Bigger than an Ethernet packet...
xfer_buf_seg equ 1000h
aux_seg equ 2000h
+serial_buf_size equ 4096 ; Should be a power of 2
+
;
; Contents of aux_seg
;
struc aux
.fontbuf resb 8192
+.serial resb serial_buf_size
+
alignb 4096 ; Align the next segment to 4K
endstruc
diff --git a/core/parseconfig.inc b/core/parseconfig.inc
index 61e7b330..efa41d17 100644
--- a/core/parseconfig.inc
+++ b/core/parseconfig.inc
@@ -224,46 +224,48 @@ pc_serial: call getint
;
; Begin code to actually set up the serial port
;
+ call sirq_cleanup ; Cleanup existing IRQ handler
+
lea dx,[di+3] ; DX -> LCR
mov al,83h ; Enable DLAB
- call slow_out
+ slow_out dx,al
pop ax ; Divisor
mov dx,di ; DX -> LS
- call slow_out
+ slow_out dx,al
inc dx ; DX -> MS
mov al,ah
- call slow_out
+ slow_out dx,al
mov al,03h ; Disable DLAB
inc dx ; DX -> LCR
inc dx
- call slow_out
-
- in al,dx ; Read back LCR (detect missing hw)
- cmp al,03h ; If nothing here we'll read 00 or FF
- jne .err ; Assume serial port busted
- dec dx
- dec dx ; DX -> IER
- test byte [FlowOutput],8
- setnz al ; Bit 0 -> input available IRQ
- call slow_out
-
- inc dx ; DX -> FCR/IIR
+ slow_out dx,al
+
+ in al,dx ; Read back LCR (detect missing hw)
+ cmp al,03h ; If nothing here we'll read 00 or FF
+ jne .err ; Assume serial port busted
+ dec dx ; DX -> IIR/FCR
mov al,01h
- call slow_out ; Enable FIFOs if present
+ slow_out dx,al ; Enable FIFOs if present
in al,dx
cmp al,0C0h ; FIFOs enabled and usable?
jae .fifo_ok
xor ax,ax ; Disable FIFO if unusable
- call slow_out
+ slow_out dx,al
.fifo_ok:
inc dx
inc dx ; DX -> MCR
mov al,[FlowOutput] ; Assert bits
- call slow_out
+ slow_out dx,al
+
+ ; Enable interrupts if requested
+ test al,8
+ jz .noirq
+ call sirq_install
+.noirq:
; Show some life
cmp byte [SerialNotice],0
@@ -461,7 +463,6 @@ AllowImplicit dw 1 ; Allow implicit kernels
AllowOptions dw 1 ; User-specified options allowed
IncludeLevel dw 1 ; Nesting level
DefaultLevel dw 0 ; The current level of default
-SerialPort dw 0 ; Serial port base (or 0 for no serial port)
VKernel db 0 ; Have we seen any "label" statements?
%if IS_PXELINUX