com32/chain: make raw handover use total sectors info
[syslinux.git] / core / serirq.inc
blob47ccd50fd3d8bbd6655a5fb4b8f844fe972660c2
1 ;; -----------------------------------------------------------------------
2 ;;
3 ;;   Copyright 2009 Intel Corporation; author: H. Peter Anvin
4 ;;
5 ;;   This program is free software; you can redistribute it and/or modify
6 ;;   it under the terms of the GNU General Public License as published by
7 ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
8 ;;   Boston MA 02111-1307, USA; either version 2 of the License, or
9 ;;   (at your option) any later version; incorporated herein by reference.
11 ;; -----------------------------------------------------------------------
14 ;; serirq.inc
16 ;; Serial port IRQ code
18 ;; We don't know what IRQ, if any, we have, so map all of them...
21                 section .text16
22                 bits 16
23                 align 8
25                 section .bss16
26                 alignb 8
28 %assign n 0
29 %rep 16
30                 section .text16
31 serstub_irq %+ n :
32                 push dword [cs:oldirq %+ n]
33                 jmp short irq_common
35                 section .bss16
36 oldirq %+ n     resd 1
37 %assign n n+1
38 %endrep
40                 section .text16
41 irq_common:
42                 pushf
43                 push ax
44                 push dx
45                 mov dx,[cs:SerialPort]
46                 add dx,5                        ; DX -> LSR
47                 in al,dx
48                 test al,1                       ; Received data
49                 jnz .data
50 .done:
51                 pop dx
52                 pop ax
53                 popf
54                 retf                            ; Chain to next handler
55 .data:
56                 push es
57                 push di
58                 mov ax,aux_seg + (aux.serial >> 4)
59                 mov es,ax
60                 mov di,[cs:SerialHead]
61 .loop:
62                 mov dx,[cs:SerialPort]          ; DX -> RDR
63                 in al,dx
64                 stosb
65                 mov ah,[cs:FlowIgnore]
66                 add dx,5                        ; DX -> LSR
67                 in al,dx
68                 push ax
69                 and al,ah
70                 cmp al,ah
71                 jne .drop
72                 and di,serial_buf_size-1        ; Wrap around if necessary
73                 cmp di,[cs:SerialTail]          ; Would this cause overflow?
74                 je .drop                        ; If so, just drop the data
75                 mov [cs:SerialHead],di
76 .drop:
77                 pop ax
78                 test al,1                       ; More data?
79                 jnz .loop
80 .full:
81                 pop di
82                 pop es
83                 jmp .done
85                 section .bss16
87 ; SerialIRQPort will generally track SerialPort, but will be 0 when an
88 ; IRQ service is not installed.
90 SerialIRQPort   resw 1                  ; Serial port w IRQ service
91 SerialHead      resw 1                  ; Head of serial port rx buffer
92 SerialTail      resw 1                  ; Tail of serial port rx buffer
94                 section .bss16
95 IRQMask         resw 1                  ; PIC IRQ mask status
97                 section .text16
99 sirq_install:
100                 pushad
102                 call sirq_cleanup
104                 ; Save the old interrupt vectors
105                 mov si,4*08h
106                 mov di,oldirq0
107                 mov cx,8
108                 rep movsd
109                 mov si,4*70h
110                 mov cx,8
111                 rep movsd
113                 ; Install new interrupt vectors
114                 mov di,4*08h
115                 mov cx,8
116                 mov eax,serstub_irq0
117 .pic0:
118                 stosd
119                 add ax,serstub_irq1 - serstub_irq0
120                 loop .pic0
121                 mov di,4*70h
122                 mov cx,8
123 .pic1:
124                 stosd
125                 add ax,serstub_irq1 - serstub_irq0
126                 loop .pic1
128                 mov bx,[SerialPort]
129                 mov [SerialIRQPort],bx
131                 lea dx,[bx+5]           ; DX -> LCR
132                 mov al,03h              ; Clear DLAB (should already be...)
133                 slow_out dx,al
135                 lea dx,[bx+1]           ; DX -> IER
136                 mov al,1                ; Enable receive interrupt
137                 slow_out dx,al
139                 ;
140                 ; Enable all ther interupt lines at the PIC.  Some BIOSes
141                 ; only enable the timer interrupts and other interrupts
142                 ; actively in use by the BIOS.
143                 ;
144                 in al,0xA1              ; Secondary PIC mask register
145                 mov ah,al
146                 in al,0x21              ; Primary PIC mask register
147                 mov [IRQMask],ax
149                 io_delay
151                 xor ax,ax               ; Remove all interrupt masks
152                 out 0x21,al
153                 out 0xA1,al
155                 popad
156                 ret
158 sirq_cleanup_nowipe:
159                 pushad
160                 push ds
161                 push es
162                 xor ax,ax
163                 mov ds,ax
164                 mov es,ax
166                 mov bx,[SerialIRQPort]
167                 and bx,bx
168                 jz .done
170                 lea dx,[bx+5]           ; DX -> LCR
171                 mov al,03h              ; Clear DLAB (should already be...)
172                 slow_out dx,al
174                 lea dx,[bx+1]           ; DX -> IER
175                 xor ax,ax
176                 slow_out dx,al          ; Clear IER
178                 ; Restore PIC masks
179                 mov ax,[IRQMask]
180                 out 0x21,al
181                 mov al,ah
182                 out 0xA1,al
184                 ; Restore the original interrupt vectors
185                 mov si,oldirq0
186                 mov di,4*08h
187                 mov cx,8
188                 rep movsd
189                 mov di,4*70h
190                 mov cx,8
191                 rep movsd
193                 xor ax,ax
194                 mov [SerialIRQPort],ax          ; No active interrupt system
196 .done:
197                 pop es
198                 pop ds
199                 popad
200                 ret
202 sirq_cleanup:
203                 call sirq_cleanup_nowipe
204                 pushad
205                 push es
206                 ; Just in case it might contain a password, erase the
207                 ; serial port receive buffer...
208                 mov ax,aux_seg + (aux.serial >> 4)
209                 mov es,ax
210                 xor eax,eax
211                 mov [cs:SerialHead],eax
212                 mov cx,serial_buf_size >> 2
213                 xor di,di
214                 rep stosd
215                 pop es
216                 popad
217                 ret
219                 section .text16