diff options
Diffstat (limited to 'contrib/syslinux-4.02/core/serirq.inc')
-rw-r--r-- | contrib/syslinux-4.02/core/serirq.inc | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/core/serirq.inc b/contrib/syslinux-4.02/core/serirq.inc new file mode 100644 index 0000000..47ccd50 --- /dev/null +++ b/contrib/syslinux-4.02/core/serirq.inc @@ -0,0 +1,219 @@ +;; ----------------------------------------------------------------------- +;; +;; 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. +;; +;; ----------------------------------------------------------------------- + +;; +;; serirq.inc +;; +;; Serial port IRQ code +;; +;; We don't know what IRQ, if any, we have, so map all of them... +;; + + section .text16 + bits 16 + align 8 + + section .bss16 + alignb 8 + +%assign n 0 +%rep 16 + section .text16 +serstub_irq %+ n : + push dword [cs:oldirq %+ n] + jmp short irq_common + + section .bss16 +oldirq %+ n resd 1 +%assign n n+1 +%endrep + + section .text16 +irq_common: + pushf + push ax + push dx + mov dx,[cs:SerialPort] + add dx,5 ; DX -> LSR + in al,dx + test al,1 ; Received data + jnz .data +.done: + pop dx + pop ax + popf + retf ; Chain to next handler +.data: + push es + push di + mov ax,aux_seg + (aux.serial >> 4) + mov es,ax + mov di,[cs:SerialHead] +.loop: + mov dx,[cs:SerialPort] ; DX -> RDR + in al,dx + stosb + mov ah,[cs:FlowIgnore] + add dx,5 ; DX -> LSR + in al,dx + push ax + and al,ah + cmp al,ah + jne .drop + and di,serial_buf_size-1 ; Wrap around if necessary + cmp di,[cs:SerialTail] ; Would this cause overflow? + je .drop ; If so, just drop the data + mov [cs:SerialHead],di +.drop: + pop ax + test al,1 ; More data? + jnz .loop +.full: + pop di + pop es + jmp .done + + section .bss16 +; +; SerialIRQPort will generally track SerialPort, but will be 0 when an +; IRQ service is not installed. +; +SerialIRQPort resw 1 ; Serial port w IRQ service +SerialHead resw 1 ; Head of serial port rx buffer +SerialTail resw 1 ; Tail of serial port rx buffer + + section .bss16 +IRQMask resw 1 ; PIC IRQ mask status + + section .text16 + +sirq_install: + pushad + + call sirq_cleanup + + ; Save the old interrupt vectors + mov si,4*08h + mov di,oldirq0 + mov cx,8 + rep movsd + mov si,4*70h + mov cx,8 + rep movsd + + ; Install new interrupt vectors + mov di,4*08h + mov cx,8 + mov eax,serstub_irq0 +.pic0: + stosd + add ax,serstub_irq1 - serstub_irq0 + loop .pic0 + mov di,4*70h + mov cx,8 +.pic1: + stosd + add ax,serstub_irq1 - serstub_irq0 + loop .pic1 + + mov bx,[SerialPort] + mov [SerialIRQPort],bx + + lea dx,[bx+5] ; DX -> LCR + mov al,03h ; Clear DLAB (should already be...) + slow_out dx,al + + lea dx,[bx+1] ; DX -> IER + mov al,1 ; Enable receive interrupt + slow_out dx,al + + ; + ; Enable all ther interupt lines at the PIC. Some BIOSes + ; only enable the timer interrupts and other interrupts + ; actively in use by the BIOS. + ; + in al,0xA1 ; Secondary PIC mask register + mov ah,al + in al,0x21 ; Primary PIC mask register + mov [IRQMask],ax + + io_delay + + xor ax,ax ; Remove all interrupt masks + out 0x21,al + out 0xA1,al + + popad + ret + +sirq_cleanup_nowipe: + pushad + push ds + push es + xor ax,ax + mov ds,ax + mov es,ax + + mov bx,[SerialIRQPort] + and bx,bx + jz .done + + lea dx,[bx+5] ; DX -> LCR + mov al,03h ; Clear DLAB (should already be...) + slow_out dx,al + + lea dx,[bx+1] ; DX -> IER + xor ax,ax + slow_out dx,al ; Clear IER + + ; Restore PIC masks + mov ax,[IRQMask] + out 0x21,al + mov al,ah + out 0xA1,al + + ; Restore the original interrupt vectors + mov si,oldirq0 + mov di,4*08h + mov cx,8 + rep movsd + mov di,4*70h + mov cx,8 + rep movsd + + xor ax,ax + mov [SerialIRQPort],ax ; No active interrupt system + +.done: + pop es + pop ds + popad + ret + +sirq_cleanup: + call sirq_cleanup_nowipe + pushad + push es + ; Just in case it might contain a password, erase the + ; serial port receive buffer... + mov ax,aux_seg + (aux.serial >> 4) + mov es,ax + xor eax,eax + mov [cs:SerialHead],eax + mov cx,serial_buf_size >> 2 + xor di,di + rep stosd + pop es + popad + ret + + section .text16 |