ia64/xen-unstable

view tools/ioemu/hw/serial.c @ 6946:e703abaf6e3d

Add behaviour to the remove methods to remove the transaction's path itself. This allows us to write Remove(path) to remove the specified path rather than having to slice the path ourselves.
author emellor@ewan
date Sun Sep 18 14:42:13 2005 +0100 (2005-09-18)
parents 8e5fc5fe636c
children 58d1ef215706
line source
1 /*
2 * QEMU 16450 UART emulation
3 *
4 * Copyright (c) 2003-2004 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 #include "vl.h"
26 //#define DEBUG_SERIAL
28 #define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
30 #define UART_IER_MSI 0x08 /* Enable Modem status interrupt */
31 #define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
32 #define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
33 #define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
35 #define UART_IIR_NO_INT 0x01 /* No interrupts pending */
36 #define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
38 #define UART_IIR_MSI 0x00 /* Modem status interrupt */
39 #define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
40 #define UART_IIR_RDI 0x04 /* Receiver data interrupt */
41 #define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
43 /*
44 * These are the definitions for the Modem Control Register
45 */
46 #define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
47 #define UART_MCR_OUT2 0x08 /* Out2 complement */
48 #define UART_MCR_OUT1 0x04 /* Out1 complement */
49 #define UART_MCR_RTS 0x02 /* RTS complement */
50 #define UART_MCR_DTR 0x01 /* DTR complement */
52 /*
53 * These are the definitions for the Modem Status Register
54 */
55 #define UART_MSR_DCD 0x80 /* Data Carrier Detect */
56 #define UART_MSR_RI 0x40 /* Ring Indicator */
57 #define UART_MSR_DSR 0x20 /* Data Set Ready */
58 #define UART_MSR_CTS 0x10 /* Clear to Send */
59 #define UART_MSR_DDCD 0x08 /* Delta DCD */
60 #define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */
61 #define UART_MSR_DDSR 0x02 /* Delta DSR */
62 #define UART_MSR_DCTS 0x01 /* Delta CTS */
63 #define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */
65 #define UART_LSR_TEMT 0x40 /* Transmitter empty */
66 #define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
67 #define UART_LSR_BI 0x10 /* Break interrupt indicator */
68 #define UART_LSR_FE 0x08 /* Frame error indicator */
69 #define UART_LSR_PE 0x04 /* Parity error indicator */
70 #define UART_LSR_OE 0x02 /* Overrun error indicator */
71 #define UART_LSR_DR 0x01 /* Receiver data ready */
73 struct SerialState {
74 uint8_t divider;
75 uint8_t rbr; /* receive register */
76 uint8_t ier;
77 uint8_t iir; /* read only */
78 uint8_t lcr;
79 uint8_t mcr;
80 uint8_t lsr; /* read only */
81 uint8_t msr;
82 uint8_t scr;
83 /* NOTE: this hidden state is necessary for tx irq generation as
84 it can be reset while reading iir */
85 int thr_ipending;
86 int irq;
87 CharDriverState *chr;
88 };
90 static void serial_update_irq(SerialState *s)
91 {
92 if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI)) {
93 s->iir = UART_IIR_RDI;
94 } else if (s->thr_ipending && (s->ier & UART_IER_THRI)) {
95 s->iir = UART_IIR_THRI;
96 } else {
97 s->iir = UART_IIR_NO_INT;
98 }
99 if (s->iir != UART_IIR_NO_INT) {
100 pic_set_irq(s->irq, 1);
101 } else {
102 pic_set_irq(s->irq, 0);
103 }
104 }
106 static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
107 {
108 SerialState *s = opaque;
109 unsigned char ch;
111 addr &= 7;
112 #ifdef DEBUG_SERIAL
113 printf("serial: write addr=0x%02x val=0x%02x\n", addr, val);
114 #endif
115 switch(addr) {
116 default:
117 case 0:
118 if (s->lcr & UART_LCR_DLAB) {
119 s->divider = (s->divider & 0xff00) | val;
120 } else {
121 s->thr_ipending = 0;
122 s->lsr &= ~UART_LSR_THRE;
123 serial_update_irq(s);
124 ch = val;
125 qemu_chr_write(s->chr, &ch, 1);
126 s->thr_ipending = 1;
127 s->lsr |= UART_LSR_THRE;
128 s->lsr |= UART_LSR_TEMT;
129 serial_update_irq(s);
130 }
131 break;
132 case 1:
133 if (s->lcr & UART_LCR_DLAB) {
134 s->divider = (s->divider & 0x00ff) | (val << 8);
135 } else {
136 s->ier = val & 0x0f;
137 if (s->lsr & UART_LSR_THRE) {
138 s->thr_ipending = 1;
139 }
140 serial_update_irq(s);
141 }
142 break;
143 case 2:
144 break;
145 case 3:
146 s->lcr = val;
147 break;
148 case 4:
149 s->mcr = val & 0x1f;
150 break;
151 case 5:
152 break;
153 case 6:
154 s->msr = val;
155 break;
156 case 7:
157 s->scr = val;
158 break;
159 }
160 }
162 static uint32_t serial_ioport_read(void *opaque, uint32_t addr)
163 {
164 SerialState *s = opaque;
165 uint32_t ret;
167 addr &= 7;
168 switch(addr) {
169 default:
170 case 0:
171 if (s->lcr & UART_LCR_DLAB) {
172 ret = s->divider & 0xff;
173 } else {
174 ret = s->rbr;
175 s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
176 serial_update_irq(s);
177 }
178 break;
179 case 1:
180 if (s->lcr & UART_LCR_DLAB) {
181 ret = (s->divider >> 8) & 0xff;
182 } else {
183 ret = s->ier;
184 }
185 break;
186 case 2:
187 ret = s->iir;
188 /* reset THR pending bit */
189 if ((ret & 0x7) == UART_IIR_THRI)
190 s->thr_ipending = 0;
191 serial_update_irq(s);
192 break;
193 case 3:
194 ret = s->lcr;
195 break;
196 case 4:
197 ret = s->mcr;
198 break;
199 case 5:
200 ret = s->lsr;
201 break;
202 case 6:
203 if (s->mcr & UART_MCR_LOOP) {
204 /* in loopback, the modem output pins are connected to the
205 inputs */
206 ret = (s->mcr & 0x0c) << 4;
207 ret |= (s->mcr & 0x02) << 3;
208 ret |= (s->mcr & 0x01) << 5;
209 } else {
210 ret = s->msr;
211 }
212 break;
213 case 7:
214 ret = s->scr;
215 break;
216 }
217 #ifdef DEBUG_SERIAL
218 printf("serial: read addr=0x%02x val=0x%02x\n", addr, ret);
219 #endif
220 return ret;
221 }
223 static int serial_can_receive(SerialState *s)
224 {
225 return !(s->lsr & UART_LSR_DR);
226 }
228 static void serial_receive_byte(SerialState *s, int ch)
229 {
230 s->rbr = ch;
231 s->lsr |= UART_LSR_DR;
232 serial_update_irq(s);
233 }
235 static void serial_receive_break(SerialState *s)
236 {
237 s->rbr = 0;
238 s->lsr |= UART_LSR_BI | UART_LSR_DR;
239 serial_update_irq(s);
240 }
242 static int serial_can_receive1(void *opaque)
243 {
244 SerialState *s = opaque;
245 return serial_can_receive(s);
246 }
248 static void serial_receive1(void *opaque, const uint8_t *buf, int size)
249 {
250 SerialState *s = opaque;
251 serial_receive_byte(s, buf[0]);
252 }
254 static void serial_event(void *opaque, int event)
255 {
256 SerialState *s = opaque;
257 if (event == CHR_EVENT_BREAK)
258 serial_receive_break(s);
259 }
261 /* If fd is zero, it means that the serial device uses the console */
262 SerialState *serial_init(int base, int irq, CharDriverState *chr)
263 {
264 SerialState *s;
266 s = qemu_mallocz(sizeof(SerialState));
267 if (!s)
268 return NULL;
269 s->irq = irq;
270 s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
271 s->iir = UART_IIR_NO_INT;
273 register_ioport_write(base, 8, 1, serial_ioport_write, s);
274 register_ioport_read(base, 8, 1, serial_ioport_read, s);
275 s->chr = chr;
276 qemu_chr_add_read_handler(chr, serial_can_receive1, serial_receive1, s);
277 qemu_chr_add_event_handler(chr, serial_event);
278 return s;
279 }