Revision b41a2cd1 hw/serial.c
b/hw/serial.c | ||
---|---|---|
90 | 90 |
#define UART_LSR_OE 0x02 /* Overrun error indicator */ |
91 | 91 |
#define UART_LSR_DR 0x01 /* Receiver data ready */ |
92 | 92 |
|
93 |
typedef struct SerialState {
|
|
93 |
struct SerialState { |
|
94 | 94 |
uint8_t divider; |
95 | 95 |
uint8_t rbr; /* receive register */ |
96 | 96 |
uint8_t ier; |
... | ... | |
104 | 104 |
it can be reset while reading iir */ |
105 | 105 |
int thr_ipending; |
106 | 106 |
int irq; |
107 |
} SerialState; |
|
107 |
int out_fd; |
|
108 |
}; |
|
108 | 109 |
|
109 |
SerialState serial_ports[1]; |
|
110 |
|
|
111 |
void serial_update_irq(void) |
|
110 |
static void serial_update_irq(SerialState *s) |
|
112 | 111 |
{ |
113 |
SerialState *s = &serial_ports[0]; |
|
114 |
|
|
115 | 112 |
if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI)) { |
116 | 113 |
s->iir = UART_IIR_RDI; |
117 | 114 |
} else if (s->thr_ipending && (s->ier & UART_IER_THRI)) { |
... | ... | |
126 | 123 |
} |
127 | 124 |
} |
128 | 125 |
|
129 |
void serial_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
|
|
126 |
static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
|
130 | 127 |
{ |
131 |
SerialState *s = &serial_ports[0];
|
|
128 |
SerialState *s = opaque;
|
|
132 | 129 |
unsigned char ch; |
133 | 130 |
int ret; |
134 | 131 |
|
... | ... | |
144 | 141 |
} else { |
145 | 142 |
s->thr_ipending = 0; |
146 | 143 |
s->lsr &= ~UART_LSR_THRE; |
147 |
serial_update_irq(); |
|
144 |
serial_update_irq(s);
|
|
148 | 145 |
|
149 | 146 |
ch = val; |
150 | 147 |
do { |
151 |
ret = write(1, &ch, 1);
|
|
148 |
ret = write(s->out_fd, &ch, 1);
|
|
152 | 149 |
} while (ret != 1); |
153 | 150 |
s->thr_ipending = 1; |
154 | 151 |
s->lsr |= UART_LSR_THRE; |
155 | 152 |
s->lsr |= UART_LSR_TEMT; |
156 |
serial_update_irq(); |
|
153 |
serial_update_irq(s);
|
|
157 | 154 |
} |
158 | 155 |
break; |
159 | 156 |
case 1: |
... | ... | |
161 | 158 |
s->divider = (s->divider & 0x00ff) | (val << 8); |
162 | 159 |
} else { |
163 | 160 |
s->ier = val; |
164 |
serial_update_irq(); |
|
161 |
serial_update_irq(s);
|
|
165 | 162 |
} |
166 | 163 |
break; |
167 | 164 |
case 2: |
... | ... | |
183 | 180 |
} |
184 | 181 |
} |
185 | 182 |
|
186 |
uint32_t serial_ioport_read(CPUState *env, uint32_t addr)
|
|
183 |
static uint32_t serial_ioport_read(void *opaque, uint32_t addr)
|
|
187 | 184 |
{ |
188 |
SerialState *s = &serial_ports[0];
|
|
185 |
SerialState *s = opaque;
|
|
189 | 186 |
uint32_t ret; |
190 | 187 |
|
191 | 188 |
addr &= 7; |
... | ... | |
197 | 194 |
} else { |
198 | 195 |
ret = s->rbr; |
199 | 196 |
s->lsr &= ~(UART_LSR_DR | UART_LSR_BI); |
200 |
serial_update_irq(); |
|
197 |
serial_update_irq(s);
|
|
201 | 198 |
} |
202 | 199 |
break; |
203 | 200 |
case 1: |
... | ... | |
212 | 209 |
/* reset THR pending bit */ |
213 | 210 |
if ((ret & 0x7) == UART_IIR_THRI) |
214 | 211 |
s->thr_ipending = 0; |
215 |
serial_update_irq(); |
|
212 |
serial_update_irq(s);
|
|
216 | 213 |
break; |
217 | 214 |
case 3: |
218 | 215 |
ret = s->lcr; |
... | ... | |
244 | 241 |
return ret; |
245 | 242 |
} |
246 | 243 |
|
247 |
int serial_can_receive(void)
|
|
244 |
int serial_can_receive(SerialState *s)
|
|
248 | 245 |
{ |
249 |
SerialState *s = &serial_ports[0]; |
|
250 | 246 |
return !(s->lsr & UART_LSR_DR); |
251 | 247 |
} |
252 | 248 |
|
253 |
void serial_receive_byte(int ch) |
|
249 |
void serial_receive_byte(SerialState *s, int ch)
|
|
254 | 250 |
{ |
255 |
SerialState *s = &serial_ports[0]; |
|
256 |
|
|
257 | 251 |
s->rbr = ch; |
258 | 252 |
s->lsr |= UART_LSR_DR; |
259 |
serial_update_irq(); |
|
253 |
serial_update_irq(s);
|
|
260 | 254 |
} |
261 | 255 |
|
262 |
void serial_receive_break(void)
|
|
256 |
void serial_receive_break(SerialState *s)
|
|
263 | 257 |
{ |
264 |
SerialState *s = &serial_ports[0]; |
|
265 |
|
|
266 | 258 |
s->rbr = 0; |
267 | 259 |
s->lsr |= UART_LSR_BI | UART_LSR_DR; |
268 |
serial_update_irq(); |
|
260 |
serial_update_irq(s);
|
|
269 | 261 |
} |
270 | 262 |
|
271 |
void serial_init(int base, int irq)
|
|
263 |
static int serial_can_receive1(void *opaque)
|
|
272 | 264 |
{ |
273 |
SerialState *s = &serial_ports[0]; |
|
265 |
SerialState *s = opaque; |
|
266 |
return serial_can_receive(s); |
|
267 |
} |
|
268 |
|
|
269 |
static void serial_receive1(void *opaque, const uint8_t *buf, int size) |
|
270 |
{ |
|
271 |
SerialState *s = opaque; |
|
272 |
serial_receive_byte(s, buf[0]); |
|
273 |
} |
|
274 | 274 |
|
275 |
/* If fd is zero, it means that the serial device uses the console */ |
|
276 |
SerialState *serial_init(int base, int irq, int fd) |
|
277 |
{ |
|
278 |
SerialState *s; |
|
279 |
|
|
280 |
s = qemu_mallocz(sizeof(SerialState)); |
|
281 |
if (!s) |
|
282 |
return NULL; |
|
275 | 283 |
s->irq = irq; |
276 | 284 |
s->lsr = UART_LSR_TEMT | UART_LSR_THRE; |
277 | 285 |
s->iir = UART_IIR_NO_INT; |
278 |
|
|
279 |
register_ioport_write(base, 8, serial_ioport_write, 1); |
|
280 |
register_ioport_read(base, 8, serial_ioport_read, 1); |
|
286 |
|
|
287 |
register_ioport_write(base, 8, 1, serial_ioport_write, s); |
|
288 |
register_ioport_read(base, 8, 1, serial_ioport_read, s); |
|
289 |
|
|
290 |
if (fd != 0) { |
|
291 |
add_fd_read_handler(fd, serial_can_receive1, serial_receive1, s); |
|
292 |
s->out_fd = fd; |
|
293 |
} else { |
|
294 |
serial_console = s; |
|
295 |
s->out_fd = 1; |
|
296 |
} |
|
297 |
return s; |
|
281 | 298 |
} |
Also available in: Unified diff