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