Commit 35db099ddb95c9761f665782b2f2cbe73f44e336
1 parent
6bcb76c3
allow host serial port usage (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2153 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
88 additions
and
22 deletions
hw/slavio_serial.c
... | ... | @@ -74,6 +74,8 @@ typedef enum { |
74 | 74 | chn_a, chn_b, |
75 | 75 | } chn_id_t; |
76 | 76 | |
77 | +#define CHN_C(s) ((s)->chn == chn_b? 'b' : 'a') | |
78 | + | |
77 | 79 | typedef enum { |
78 | 80 | ser, kbd, mouse, |
79 | 81 | } chn_type_t; |
... | ... | @@ -113,7 +115,7 @@ static void put_queue(void *opaque, int b) |
113 | 115 | ChannelState *s = opaque; |
114 | 116 | SERIOQueue *q = &s->queue; |
115 | 117 | |
116 | - SER_DPRINTF("put: 0x%02x\n", b); | |
118 | + SER_DPRINTF("channel %c put: 0x%02x\n", CHN_C(s), b); | |
117 | 119 | if (q->count >= SERIO_QUEUE_SIZE) |
118 | 120 | return; |
119 | 121 | q->data[q->wptr] = b; |
... | ... | @@ -137,7 +139,7 @@ static uint32_t get_queue(void *opaque) |
137 | 139 | q->rptr = 0; |
138 | 140 | q->count--; |
139 | 141 | } |
140 | - KBD_DPRINTF("get 0x%02x\n", val); | |
142 | + KBD_DPRINTF("channel %c get 0x%02x\n", CHN_C(s), val); | |
141 | 143 | if (q->count > 0) |
142 | 144 | serial_receive_byte(s, 0); |
143 | 145 | return val; |
... | ... | @@ -198,11 +200,10 @@ static inline void clr_rxint(ChannelState *s) |
198 | 200 | { |
199 | 201 | s->rxint = 0; |
200 | 202 | s->rxint_under_svc = 0; |
201 | - if (s->chn == 0) | |
203 | + if (s->chn == chn_a) | |
202 | 204 | s->rregs[3] &= ~0x20; |
203 | - else { | |
205 | + else | |
204 | 206 | s->otherchn->rregs[3] &= ~4; |
205 | - } | |
206 | 207 | if (s->txint) |
207 | 208 | set_txint(s); |
208 | 209 | else |
... | ... | @@ -215,11 +216,10 @@ static inline void set_rxint(ChannelState *s) |
215 | 216 | s->rxint = 1; |
216 | 217 | if (!s->txint_under_svc) { |
217 | 218 | s->rxint_under_svc = 1; |
218 | - if (s->chn == 0) | |
219 | + if (s->chn == chn_a) | |
219 | 220 | s->rregs[3] |= 0x20; |
220 | - else { | |
221 | + else | |
221 | 222 | s->otherchn->rregs[3] |= 4; |
222 | - } | |
223 | 223 | s->rregs[2] = 4; |
224 | 224 | slavio_serial_update_irq(s); |
225 | 225 | } |
... | ... | @@ -229,11 +229,10 @@ static inline void clr_txint(ChannelState *s) |
229 | 229 | { |
230 | 230 | s->txint = 0; |
231 | 231 | s->txint_under_svc = 0; |
232 | - if (s->chn == 0) | |
232 | + if (s->chn == chn_a) | |
233 | 233 | s->rregs[3] &= ~0x10; |
234 | - else { | |
234 | + else | |
235 | 235 | s->otherchn->rregs[3] &= ~2; |
236 | - } | |
237 | 236 | if (s->rxint) |
238 | 237 | set_rxint(s); |
239 | 238 | else |
... | ... | @@ -246,16 +245,74 @@ static inline void set_txint(ChannelState *s) |
246 | 245 | s->txint = 1; |
247 | 246 | if (!s->rxint_under_svc) { |
248 | 247 | s->txint_under_svc = 1; |
249 | - if (s->chn == 0) | |
248 | + if (s->chn == chn_a) | |
250 | 249 | s->rregs[3] |= 0x10; |
251 | - else { | |
250 | + else | |
252 | 251 | s->otherchn->rregs[3] |= 2; |
253 | - } | |
254 | 252 | s->rregs[2] = 0; |
255 | 253 | slavio_serial_update_irq(s); |
256 | 254 | } |
257 | 255 | } |
258 | 256 | |
257 | +static void slavio_serial_update_parameters(ChannelState *s) | |
258 | +{ | |
259 | + int speed, parity, data_bits, stop_bits; | |
260 | + QEMUSerialSetParams ssp; | |
261 | + | |
262 | + if (!s->chr || s->type != ser) | |
263 | + return; | |
264 | + | |
265 | + if (s->wregs[4] & 1) { | |
266 | + if (s->wregs[4] & 2) | |
267 | + parity = 'E'; | |
268 | + else | |
269 | + parity = 'O'; | |
270 | + } else { | |
271 | + parity = 'N'; | |
272 | + } | |
273 | + if ((s->wregs[4] & 0x0c) == 0x0c) | |
274 | + stop_bits = 2; | |
275 | + else | |
276 | + stop_bits = 1; | |
277 | + switch (s->wregs[5] & 0x60) { | |
278 | + case 0x00: | |
279 | + data_bits = 5; | |
280 | + break; | |
281 | + case 0x20: | |
282 | + data_bits = 7; | |
283 | + break; | |
284 | + case 0x40: | |
285 | + data_bits = 6; | |
286 | + break; | |
287 | + default: | |
288 | + case 0x60: | |
289 | + data_bits = 8; | |
290 | + break; | |
291 | + } | |
292 | + speed = 2457600 / ((s->wregs[12] | (s->wregs[13] << 8)) + 2); | |
293 | + switch (s->wregs[4] & 0xc0) { | |
294 | + case 0x00: | |
295 | + break; | |
296 | + case 0x40: | |
297 | + speed /= 16; | |
298 | + break; | |
299 | + case 0x80: | |
300 | + speed /= 32; | |
301 | + break; | |
302 | + default: | |
303 | + case 0xc0: | |
304 | + speed /= 64; | |
305 | + break; | |
306 | + } | |
307 | + ssp.speed = speed; | |
308 | + ssp.parity = parity; | |
309 | + ssp.data_bits = data_bits; | |
310 | + ssp.stop_bits = stop_bits; | |
311 | + SER_DPRINTF("channel %c: speed=%d parity=%c data=%d stop=%d\n", CHN_C(s), | |
312 | + speed, parity, data_bits, stop_bits); | |
313 | + qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp); | |
314 | +} | |
315 | + | |
259 | 316 | static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) |
260 | 317 | { |
261 | 318 | SerialState *ser = opaque; |
... | ... | @@ -269,7 +326,7 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint |
269 | 326 | s = &ser->chn[channel]; |
270 | 327 | switch (saddr) { |
271 | 328 | case 0: |
272 | - SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", channel? 'b' : 'a', s->reg, val & 0xff); | |
329 | + SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, val & 0xff); | |
273 | 330 | newreg = 0; |
274 | 331 | switch (s->reg) { |
275 | 332 | case 0: |
... | ... | @@ -292,9 +349,18 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint |
292 | 349 | break; |
293 | 350 | } |
294 | 351 | break; |
295 | - case 1 ... 8: | |
296 | - case 10 ... 15: | |
352 | + case 1 ... 3: | |
353 | + case 6 ... 8: | |
354 | + case 10 ... 11: | |
355 | + case 14 ... 15: | |
356 | + s->wregs[s->reg] = val; | |
357 | + break; | |
358 | + case 4: | |
359 | + case 5: | |
360 | + case 12: | |
361 | + case 13: | |
297 | 362 | s->wregs[s->reg] = val; |
363 | + slavio_serial_update_parameters(s); | |
298 | 364 | break; |
299 | 365 | case 9: |
300 | 366 | switch (val & 0xc0) { |
... | ... | @@ -321,7 +387,7 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint |
321 | 387 | s->reg = 0; |
322 | 388 | break; |
323 | 389 | case 1: |
324 | - SER_DPRINTF("Write channel %c, ch %d\n", channel? 'b' : 'a', val); | |
390 | + SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val); | |
325 | 391 | if (s->wregs[5] & 8) { // tx enabled |
326 | 392 | s->tx = val; |
327 | 393 | if (s->chr) |
... | ... | @@ -352,7 +418,7 @@ static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr) |
352 | 418 | s = &ser->chn[channel]; |
353 | 419 | switch (saddr) { |
354 | 420 | case 0: |
355 | - SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", channel? 'b' : 'a', s->reg, s->rregs[s->reg]); | |
421 | + SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, s->rregs[s->reg]); | |
356 | 422 | ret = s->rregs[s->reg]; |
357 | 423 | s->reg = 0; |
358 | 424 | return ret; |
... | ... | @@ -363,7 +429,7 @@ static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr) |
363 | 429 | ret = get_queue(s); |
364 | 430 | else |
365 | 431 | ret = s->rx; |
366 | - SER_DPRINTF("Read channel %c, ch %d\n", channel? 'b' : 'a', ret); | |
432 | + SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret); | |
367 | 433 | return ret; |
368 | 434 | default: |
369 | 435 | break; |
... | ... | @@ -381,13 +447,13 @@ static int serial_can_receive(void *opaque) |
381 | 447 | ret = 0; |
382 | 448 | else |
383 | 449 | ret = 1; |
384 | - SER_DPRINTF("can receive %d\n", ret); | |
450 | + //SER_DPRINTF("channel %c can receive %d\n", CHN_C(s), ret); | |
385 | 451 | return ret; |
386 | 452 | } |
387 | 453 | |
388 | 454 | static void serial_receive_byte(ChannelState *s, int ch) |
389 | 455 | { |
390 | - SER_DPRINTF("put ch %d\n", ch); | |
456 | + SER_DPRINTF("channel %c put ch %d\n", CHN_C(s), ch); | |
391 | 457 | s->rregs[0] |= 1; |
392 | 458 | s->rx = ch; |
393 | 459 | set_rxint(s); | ... | ... |