2 * -----------------------------------------------------------------------
4 * Copyright 2009 Intel Corporation; author: H. Peter Anvin
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
9 * Boston MA 02111-1307, USA; either version 2 of the License, or
10 * (at your option) any later version; incorporated herein by reference.
12 * -----------------------------------------------------------------------
16 * Serial port IRQ code
18 * We don't know what IRQ, if any, we have, so map all of them...
26 static char serial_buf
[serial_buf_size
];
28 static unsigned short SerialIRQPort
; /* Serial port w IRQ service */
29 char *SerialHead
= serial_buf
; /* Head of serial port rx buffer */
30 char *SerialTail
= serial_buf
; /* Tail of serial port rx buffer */
32 static unsigned char IRQMask
[2]; /* PIC IRQ mask status */
34 static unsigned int oldirq
[16];
36 typedef void (*irqhandler_t
)(void);
38 void sirq_cleanup(void);
40 static void irq_common(unsigned short old_irq
)
47 next
= (irqhandler_t
)oldirq
[old_irq
];
50 val
= inb(SerialPort
+ 5);
55 *dst
++ = inb(SerialPort
);
57 val
= inb(SerialPort
+ 5);
58 if ((val
& FlowIgnore
) == FlowIgnore
) {
59 /* Wrap around if necessary */
60 dst
= (char *)((unsigned long)dst
& (serial_buf_size
- 1));
62 /* Would this cause overflow? */
63 if (dst
!= SerialTail
)
68 /* Chain to next handler */
72 #define SERIAL_IRQ_HANDLER(n) \
73 static void serstub_irq##n(void) \
78 SERIAL_IRQ_HANDLER(0);
79 SERIAL_IRQ_HANDLER(1);
80 SERIAL_IRQ_HANDLER(2);
81 SERIAL_IRQ_HANDLER(3);
82 SERIAL_IRQ_HANDLER(4);
83 SERIAL_IRQ_HANDLER(5);
84 SERIAL_IRQ_HANDLER(6);
85 SERIAL_IRQ_HANDLER(7);
86 SERIAL_IRQ_HANDLER(8);
87 SERIAL_IRQ_HANDLER(9);
88 SERIAL_IRQ_HANDLER(10);
89 SERIAL_IRQ_HANDLER(11);
90 SERIAL_IRQ_HANDLER(12);
91 SERIAL_IRQ_HANDLER(13);
92 SERIAL_IRQ_HANDLER(14);
93 SERIAL_IRQ_HANDLER(15);
95 static inline void save_irq_vectors(uint32_t *src
, uint32_t *dst
)
99 for (i
= 0; i
< 8; i
++)
103 static inline void install_irq_vectors(uint32_t *dst
, int first
)
106 *dst
++ = (uint32_t)serstub_irq0
;
107 *dst
++ = (uint32_t)serstub_irq1
;
108 *dst
++ = (uint32_t)serstub_irq2
;
109 *dst
++ = (uint32_t)serstub_irq3
;
110 *dst
++ = (uint32_t)serstub_irq4
;
111 *dst
++ = (uint32_t)serstub_irq5
;
112 *dst
++ = (uint32_t)serstub_irq6
;
113 *dst
++ = (uint32_t)serstub_irq7
;
115 *dst
++ = (uint32_t)serstub_irq8
;
116 *dst
++ = (uint32_t)serstub_irq9
;
117 *dst
++ = (uint32_t)serstub_irq10
;
118 *dst
++ = (uint32_t)serstub_irq11
;
119 *dst
++ = (uint32_t)serstub_irq12
;
120 *dst
++ = (uint32_t)serstub_irq13
;
121 *dst
++ = (uint32_t)serstub_irq14
;
122 *dst
++ = (uint32_t)serstub_irq15
;
126 __export
void sirq_install(void)
132 save_irq_vectors((uint32_t *)(4 * 0x8), oldirq
);
133 save_irq_vectors((uint32_t *)(4 * 0x70), &oldirq
[8]);
135 install_irq_vectors((uint32_t *)(4 * 0x8), 1);
136 install_irq_vectors((uint32_t *)(4 * 0x70), 0);
138 SerialIRQPort
= SerialPort
;
140 /* Clear DLAB (should already be...) */
141 outb(0x3, SerialIRQPort
+ 5);
144 /* Enable receive interrupt */
145 outb(0x1, SerialIRQPort
+ 1);
149 * Enable all the interrupt lines at the PIC. Some BIOSes only
150 * enable the timer interrupts and other interrupts actively
151 * in use by the BIOS.
154 /* Secondary PIC mask register */
162 /* Remove all interrupt masks */
167 __export
void sirq_cleanup_nowipe(void)
176 outb(0x3, SerialIRQPort
+ 5);
180 outb(0x0, SerialIRQPort
+ 1);
183 /* Restore PIC masks */
184 outb(IRQMask
[0], 0x21);
185 outb(IRQMask
[1], 0xA1);
187 /* Restore the original interrupt vectors */
188 dst
= (uint32_t *)(4 * 0x8);
189 for (i
= 0; i
< 8; i
++)
192 dst
= (uint32_t *)(4 * 0x70);
193 for (i
= 8; i
< 16; i
++)
196 /* No active interrupt system */
200 void sirq_cleanup(void)
202 sirq_cleanup_nowipe();
203 memset(SerialHead
, 0x0, serial_buf_size
);