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,6 +74,8 @@ typedef enum { | ||
74 | chn_a, chn_b, | 74 | chn_a, chn_b, |
75 | } chn_id_t; | 75 | } chn_id_t; |
76 | 76 | ||
77 | +#define CHN_C(s) ((s)->chn == chn_b? 'b' : 'a') | ||
78 | + | ||
77 | typedef enum { | 79 | typedef enum { |
78 | ser, kbd, mouse, | 80 | ser, kbd, mouse, |
79 | } chn_type_t; | 81 | } chn_type_t; |
@@ -113,7 +115,7 @@ static void put_queue(void *opaque, int b) | @@ -113,7 +115,7 @@ static void put_queue(void *opaque, int b) | ||
113 | ChannelState *s = opaque; | 115 | ChannelState *s = opaque; |
114 | SERIOQueue *q = &s->queue; | 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 | if (q->count >= SERIO_QUEUE_SIZE) | 119 | if (q->count >= SERIO_QUEUE_SIZE) |
118 | return; | 120 | return; |
119 | q->data[q->wptr] = b; | 121 | q->data[q->wptr] = b; |
@@ -137,7 +139,7 @@ static uint32_t get_queue(void *opaque) | @@ -137,7 +139,7 @@ static uint32_t get_queue(void *opaque) | ||
137 | q->rptr = 0; | 139 | q->rptr = 0; |
138 | q->count--; | 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 | if (q->count > 0) | 143 | if (q->count > 0) |
142 | serial_receive_byte(s, 0); | 144 | serial_receive_byte(s, 0); |
143 | return val; | 145 | return val; |
@@ -198,11 +200,10 @@ static inline void clr_rxint(ChannelState *s) | @@ -198,11 +200,10 @@ static inline void clr_rxint(ChannelState *s) | ||
198 | { | 200 | { |
199 | s->rxint = 0; | 201 | s->rxint = 0; |
200 | s->rxint_under_svc = 0; | 202 | s->rxint_under_svc = 0; |
201 | - if (s->chn == 0) | 203 | + if (s->chn == chn_a) |
202 | s->rregs[3] &= ~0x20; | 204 | s->rregs[3] &= ~0x20; |
203 | - else { | 205 | + else |
204 | s->otherchn->rregs[3] &= ~4; | 206 | s->otherchn->rregs[3] &= ~4; |
205 | - } | ||
206 | if (s->txint) | 207 | if (s->txint) |
207 | set_txint(s); | 208 | set_txint(s); |
208 | else | 209 | else |
@@ -215,11 +216,10 @@ static inline void set_rxint(ChannelState *s) | @@ -215,11 +216,10 @@ static inline void set_rxint(ChannelState *s) | ||
215 | s->rxint = 1; | 216 | s->rxint = 1; |
216 | if (!s->txint_under_svc) { | 217 | if (!s->txint_under_svc) { |
217 | s->rxint_under_svc = 1; | 218 | s->rxint_under_svc = 1; |
218 | - if (s->chn == 0) | 219 | + if (s->chn == chn_a) |
219 | s->rregs[3] |= 0x20; | 220 | s->rregs[3] |= 0x20; |
220 | - else { | 221 | + else |
221 | s->otherchn->rregs[3] |= 4; | 222 | s->otherchn->rregs[3] |= 4; |
222 | - } | ||
223 | s->rregs[2] = 4; | 223 | s->rregs[2] = 4; |
224 | slavio_serial_update_irq(s); | 224 | slavio_serial_update_irq(s); |
225 | } | 225 | } |
@@ -229,11 +229,10 @@ static inline void clr_txint(ChannelState *s) | @@ -229,11 +229,10 @@ static inline void clr_txint(ChannelState *s) | ||
229 | { | 229 | { |
230 | s->txint = 0; | 230 | s->txint = 0; |
231 | s->txint_under_svc = 0; | 231 | s->txint_under_svc = 0; |
232 | - if (s->chn == 0) | 232 | + if (s->chn == chn_a) |
233 | s->rregs[3] &= ~0x10; | 233 | s->rregs[3] &= ~0x10; |
234 | - else { | 234 | + else |
235 | s->otherchn->rregs[3] &= ~2; | 235 | s->otherchn->rregs[3] &= ~2; |
236 | - } | ||
237 | if (s->rxint) | 236 | if (s->rxint) |
238 | set_rxint(s); | 237 | set_rxint(s); |
239 | else | 238 | else |
@@ -246,16 +245,74 @@ static inline void set_txint(ChannelState *s) | @@ -246,16 +245,74 @@ static inline void set_txint(ChannelState *s) | ||
246 | s->txint = 1; | 245 | s->txint = 1; |
247 | if (!s->rxint_under_svc) { | 246 | if (!s->rxint_under_svc) { |
248 | s->txint_under_svc = 1; | 247 | s->txint_under_svc = 1; |
249 | - if (s->chn == 0) | 248 | + if (s->chn == chn_a) |
250 | s->rregs[3] |= 0x10; | 249 | s->rregs[3] |= 0x10; |
251 | - else { | 250 | + else |
252 | s->otherchn->rregs[3] |= 2; | 251 | s->otherchn->rregs[3] |= 2; |
253 | - } | ||
254 | s->rregs[2] = 0; | 252 | s->rregs[2] = 0; |
255 | slavio_serial_update_irq(s); | 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 | static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) | 316 | static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) |
260 | { | 317 | { |
261 | SerialState *ser = opaque; | 318 | SerialState *ser = opaque; |
@@ -269,7 +326,7 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint | @@ -269,7 +326,7 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint | ||
269 | s = &ser->chn[channel]; | 326 | s = &ser->chn[channel]; |
270 | switch (saddr) { | 327 | switch (saddr) { |
271 | case 0: | 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 | newreg = 0; | 330 | newreg = 0; |
274 | switch (s->reg) { | 331 | switch (s->reg) { |
275 | case 0: | 332 | case 0: |
@@ -292,9 +349,18 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint | @@ -292,9 +349,18 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint | ||
292 | break; | 349 | break; |
293 | } | 350 | } |
294 | break; | 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 | s->wregs[s->reg] = val; | 362 | s->wregs[s->reg] = val; |
363 | + slavio_serial_update_parameters(s); | ||
298 | break; | 364 | break; |
299 | case 9: | 365 | case 9: |
300 | switch (val & 0xc0) { | 366 | switch (val & 0xc0) { |
@@ -321,7 +387,7 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint | @@ -321,7 +387,7 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint | ||
321 | s->reg = 0; | 387 | s->reg = 0; |
322 | break; | 388 | break; |
323 | case 1: | 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 | if (s->wregs[5] & 8) { // tx enabled | 391 | if (s->wregs[5] & 8) { // tx enabled |
326 | s->tx = val; | 392 | s->tx = val; |
327 | if (s->chr) | 393 | if (s->chr) |
@@ -352,7 +418,7 @@ static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr) | @@ -352,7 +418,7 @@ static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr) | ||
352 | s = &ser->chn[channel]; | 418 | s = &ser->chn[channel]; |
353 | switch (saddr) { | 419 | switch (saddr) { |
354 | case 0: | 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 | ret = s->rregs[s->reg]; | 422 | ret = s->rregs[s->reg]; |
357 | s->reg = 0; | 423 | s->reg = 0; |
358 | return ret; | 424 | return ret; |
@@ -363,7 +429,7 @@ static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr) | @@ -363,7 +429,7 @@ static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr) | ||
363 | ret = get_queue(s); | 429 | ret = get_queue(s); |
364 | else | 430 | else |
365 | ret = s->rx; | 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 | return ret; | 433 | return ret; |
368 | default: | 434 | default: |
369 | break; | 435 | break; |
@@ -381,13 +447,13 @@ static int serial_can_receive(void *opaque) | @@ -381,13 +447,13 @@ static int serial_can_receive(void *opaque) | ||
381 | ret = 0; | 447 | ret = 0; |
382 | else | 448 | else |
383 | ret = 1; | 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 | return ret; | 451 | return ret; |
386 | } | 452 | } |
387 | 453 | ||
388 | static void serial_receive_byte(ChannelState *s, int ch) | 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 | s->rregs[0] |= 1; | 457 | s->rregs[0] |= 1; |
392 | s->rx = ch; | 458 | s->rx = ch; |
393 | set_rxint(s); | 459 | set_rxint(s); |