Commit 35db099ddb95c9761f665782b2f2cbe73f44e336

Authored by bellard
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);
... ...