diff options
author | H. Peter Anvin <hpa@zytor.com> | 2009-05-23 17:37:18 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-05-23 17:37:18 -0700 |
commit | e1192a81bddbf803feb9445a9408a9feec6159aa (patch) | |
tree | 801c24f386e3654c3d8d72b5ce1c69bcc2449948 /core | |
parent | 89ec5fa741f415296c6d6c83da5bad32710aaa38 (diff) | |
download | syslinux-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>
Diffstat (limited to 'core')
-rw-r--r-- | core/bcopy32.inc | 8 | ||||
-rw-r--r-- | core/cleanup.inc | 5 | ||||
-rw-r--r-- | core/conio.inc | 60 | ||||
-rw-r--r-- | core/head.inc | 1 | ||||
-rw-r--r-- | core/io.inc | 35 | ||||
-rw-r--r-- | core/layout.inc | 4 | ||||
-rw-r--r-- | core/parseconfig.inc | 39 |
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 |