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); |