X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=hw%2Fslavio_serial.c;h=7112bec840b94dfe592c97789d0d19deac1c283a;hb=e4a89056df2c6fc38f860db172460f4df37cd2ca;hp=b13e7c46f9a2a00648c20bc26d34497b503057fb;hpb=ffcdb539debe426e75290cb76f73e5c7b4fc645d;p=qemu diff --git a/hw/slavio_serial.c b/hw/slavio_serial.c index b13e7c4..7112bec 100644 --- a/hw/slavio_serial.c +++ b/hw/slavio_serial.c @@ -42,6 +42,13 @@ * */ +/* + * Modifications: + * 2006-Aug-10 Igor Kovalenko : Renamed KBDQueue to SERIOQueue, implemented + * serial mouse queue. + * Implemented serial mouse protocol. + */ + #ifdef DEBUG_SERIAL #define SER_DPRINTF(fmt, args...) \ do { printf("SER: " fmt , ##args); } while (0) @@ -58,7 +65,7 @@ do { printf("KBD: " fmt , ##args); } while (0) #endif #ifdef DEBUG_MOUSE #define MS_DPRINTF(fmt, args...) \ -do { printf("SER: " fmt , ##args); } while (0) +do { printf("MSC: " fmt , ##args); } while (0) #else #define MS_DPRINTF(fmt, args...) #endif @@ -71,22 +78,22 @@ typedef enum { ser, kbd, mouse, } chn_type_t; -#define KBD_QUEUE_SIZE 256 +#define SERIO_QUEUE_SIZE 256 typedef struct { - uint8_t data[KBD_QUEUE_SIZE]; + uint8_t data[SERIO_QUEUE_SIZE]; int rptr, wptr, count; -} KBDQueue; +} SERIOQueue; typedef struct ChannelState { int irq; int reg; - int rxint, txint; + int rxint, txint, rxint_under_svc, txint_under_svc; chn_id_t chn; // this channel, A (base+4) or B (base+0) chn_type_t type; struct ChannelState *otherchn; uint8_t rx, tx, wregs[16], rregs[16]; - KBDQueue queue; + SERIOQueue queue; CharDriverState *chr; } ChannelState; @@ -99,17 +106,18 @@ struct SerialState { static void handle_kbd_command(ChannelState *s, int val); static int serial_can_receive(void *opaque); static void serial_receive_byte(ChannelState *s, int ch); +static inline void set_txint(ChannelState *s); static void put_queue(void *opaque, int b) { ChannelState *s = opaque; - KBDQueue *q = &s->queue; + SERIOQueue *q = &s->queue; - KBD_DPRINTF("put: 0x%02x\n", b); - if (q->count >= KBD_QUEUE_SIZE) + SER_DPRINTF("put: 0x%02x\n", b); + if (q->count >= SERIO_QUEUE_SIZE) return; q->data[q->wptr] = b; - if (++q->wptr == KBD_QUEUE_SIZE) + if (++q->wptr == SERIO_QUEUE_SIZE) q->wptr = 0; q->count++; serial_receive_byte(s, 0); @@ -118,14 +126,14 @@ static void put_queue(void *opaque, int b) static uint32_t get_queue(void *opaque) { ChannelState *s = opaque; - KBDQueue *q = &s->queue; + SERIOQueue *q = &s->queue; int val; if (q->count == 0) { return 0; } else { val = q->data[q->rptr]; - if (++q->rptr == KBD_QUEUE_SIZE) + if (++q->rptr == SERIO_QUEUE_SIZE) q->rptr = 0; q->count--; } @@ -135,17 +143,26 @@ static uint32_t get_queue(void *opaque) return val; } -static void slavio_serial_update_irq(ChannelState *s) +static int slavio_serial_update_irq_chn(ChannelState *s) { if ((s->wregs[1] & 1) && // interrupts enabled (((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending ((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) && s->rxint == 1) || // rx ints enabled, pending ((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p - pic_set_irq(s->irq, 1); - } else { - pic_set_irq(s->irq, 0); + return 1; } + return 0; +} + +static void slavio_serial_update_irq(ChannelState *s) +{ + int irq; + + irq = slavio_serial_update_irq_chn(s); + irq |= slavio_serial_update_irq_chn(s->otherchn); + + pic_set_irq(s->irq, irq); } static void slavio_serial_reset_chn(ChannelState *s) @@ -167,6 +184,7 @@ static void slavio_serial_reset_chn(ChannelState *s) s->rx = s->tx = 0; s->rxint = s->txint = 0; + s->rxint_under_svc = s->txint_under_svc = 0; } static void slavio_serial_reset(void *opaque) @@ -179,45 +197,63 @@ static void slavio_serial_reset(void *opaque) static inline void clr_rxint(ChannelState *s) { s->rxint = 0; + s->rxint_under_svc = 0; if (s->chn == 0) s->rregs[3] &= ~0x20; else { s->otherchn->rregs[3] &= ~4; } + if (s->txint) + set_txint(s); + else + s->rregs[2] = 6; slavio_serial_update_irq(s); } static inline void set_rxint(ChannelState *s) { s->rxint = 1; - if (s->chn == 0) - s->rregs[3] |= 0x20; - else { - s->otherchn->rregs[3] |= 4; + if (!s->txint_under_svc) { + s->rxint_under_svc = 1; + if (s->chn == 0) + s->rregs[3] |= 0x20; + else { + s->otherchn->rregs[3] |= 4; + } + s->rregs[2] = 4; + slavio_serial_update_irq(s); } - slavio_serial_update_irq(s); } static inline void clr_txint(ChannelState *s) { s->txint = 0; + s->txint_under_svc = 0; if (s->chn == 0) s->rregs[3] &= ~0x10; else { s->otherchn->rregs[3] &= ~2; } + if (s->rxint) + set_rxint(s); + else + s->rregs[2] = 6; slavio_serial_update_irq(s); } static inline void set_txint(ChannelState *s) { s->txint = 1; - if (s->chn == 0) - s->rregs[3] |= 0x10; - else { - s->otherchn->rregs[3] |= 2; + if (!s->rxint_under_svc) { + s->txint_under_svc = 1; + if (s->chn == 0) + s->rregs[3] |= 0x10; + else { + s->otherchn->rregs[3] |= 2; + } + s->rregs[2] = 0; + slavio_serial_update_irq(s); } - slavio_serial_update_irq(s); } static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) @@ -243,15 +279,14 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint case 8: newreg |= 0x8; break; - case 0x20: - clr_rxint(s); - break; case 0x28: clr_txint(s); break; case 0x38: - clr_rxint(s); - clr_txint(s); + if (s->rxint_under_svc) + clr_rxint(s); + else if (s->txint_under_svc) + clr_txint(s); break; default: break; @@ -294,11 +329,9 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint else if (s->type == kbd) { handle_kbd_command(s, val); } - s->txint = 1; s->rregs[0] |= 4; // Tx buffer empty s->rregs[1] |= 1; // All sent set_txint(s); - slavio_serial_update_irq(s); } break; default: @@ -326,7 +359,7 @@ static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr) case 1: s->rregs[0] &= ~1; clr_rxint(s); - if (s->type == kbd) + if (s->type == kbd || s->type == mouse) ret = get_queue(s); else ret = s->rx; @@ -341,11 +374,15 @@ static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr) static int serial_can_receive(void *opaque) { ChannelState *s = opaque; + int ret; + if (((s->wregs[3] & 1) == 0) // Rx not enabled || ((s->rregs[0] & 1) == 1)) // char already available - return 0; + ret = 0; else - return 1; + ret = 1; + SER_DPRINTF("can receive %d\n", ret); + return ret; } static void serial_receive_byte(ChannelState *s, int ch) @@ -393,6 +430,8 @@ static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s) qemu_put_be32s(f, &s->reg); qemu_put_be32s(f, &s->rxint); qemu_put_be32s(f, &s->txint); + qemu_put_be32s(f, &s->rxint_under_svc); + qemu_put_be32s(f, &s->txint_under_svc); qemu_put_8s(f, &s->rx); qemu_put_8s(f, &s->tx); qemu_put_buffer(f, s->wregs, 16); @@ -409,13 +448,17 @@ static void slavio_serial_save(QEMUFile *f, void *opaque) static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id) { - if (version_id != 1) + if (version_id > 2) return -EINVAL; qemu_get_be32s(f, &s->irq); qemu_get_be32s(f, &s->reg); qemu_get_be32s(f, &s->rxint); qemu_get_be32s(f, &s->txint); + if (version_id >= 2) { + qemu_get_be32s(f, &s->rxint_under_svc); + qemu_get_be32s(f, &s->txint_under_svc); + } qemu_get_8s(f, &s->rx); qemu_get_8s(f, &s->tx); qemu_get_buffer(f, s->wregs, 16); @@ -462,7 +505,7 @@ SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDr } s->chn[0].otherchn = &s->chn[1]; s->chn[1].otherchn = &s->chn[0]; - register_savevm("slavio_serial", base, 1, slavio_serial_save, slavio_serial_load, s); + register_savevm("slavio_serial", base, 2, slavio_serial_save, slavio_serial_load, s); qemu_register_reset(slavio_serial_reset, s); slavio_serial_reset(s); return s; @@ -512,9 +555,44 @@ static void sunmouse_event(void *opaque, ChannelState *s = opaque; int ch; - // XXX - ch = 0x42; - serial_receive_byte(s, ch); + /* XXX: SDL sometimes generates nul events: we delete them */ + if (dx == 0 && dy == 0 && dz == 0 && buttons_state == 0) + return; + MS_DPRINTF("dx=%d dy=%d buttons=%01x\n", dx, dy, buttons_state); + + ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */ + + if (buttons_state & MOUSE_EVENT_LBUTTON) + ch ^= 0x4; + if (buttons_state & MOUSE_EVENT_MBUTTON) + ch ^= 0x2; + if (buttons_state & MOUSE_EVENT_RBUTTON) + ch ^= 0x1; + + put_queue(s, ch); + + ch = dx; + + if (ch > 127) + ch=127; + else if (ch < -127) + ch=-127; + + put_queue(s, ch & 0xff); + + ch = -dy; + + if (ch > 127) + ch=127; + else if (ch < -127) + ch=-127; + + put_queue(s, ch & 0xff); + + // MSC protocol specify two extra motion bytes + + put_queue(s, 0); + put_queue(s, 0); } void slavio_serial_ms_kbd_init(int base, int irq)