26 #define UART1_BASE 0x3f8
27 #define UART2_BASE 0x2f8
42 /* interrupt enable register bits */
48 /* fifo control register bits */
49 #define FIFO_ENABLE 0x01
50 #define FIFO_RECV_CLEAR 0x02
51 #define FIFO_SEND_CLEAR 0x04
53 #define FIFO_TRIG_4 0x40
54 #define FIFO_TRIG_8 0x80
55 #define FIFO_TRIG_14 0xc0
57 /* interrupt id register bits */
58 #define IID_PENDING 0x01
62 #define IID_FIFO_EN 0xc0
64 #define IID_SOURCE 0xe
70 #define IID_STATUS 0x6
72 /* line control register bits */
73 #define LCTL_BITS_8 0x03
74 #define LCTL_STOP_2 0x04
75 #define LCTL_DLAB 0x80
76 #define LCTL_8N1 LCTL_BITS_8
77 #define LCTL_8N2 (LCTL_BITS_8 | LCTL_STOP_2)
79 /* modem control register bits */
82 #define MCTL_OUT1 0x04
83 #define MCTL_OUT2 0x08
84 #define MCTL_LOOP 0x10
86 /* line status register bits */
88 #define LST_ERR_OVER 0x02
89 #define LST_ERR_PARITY 0x04
90 #define LST_ERR_FRAME 0x08
91 #define LST_ERR_BRK 0x10
92 #define LST_TREG_EMPTY 0x20
93 #define LST_TIDLE 0x40
94 #define LST_ERROR 0x80
96 /* modem status register bits */
97 #define MST_DELTA_CTS 0x01
98 #define MST_DELTA_DSR 0x02
100 #define MST_DELTA_DCD 0x08
103 #define MST_RING 0x40
106 /* interrupt controller stuff */
107 #define PIC1_CMD_PORT 0x20
108 #define PIC1_DATA_PORT 0x21
109 #define PIC2_CMD_PORT 0xa0
110 #define PIC2_DATA_PORT 0xa1
111 #define OCW2_EOI 0x20
118 static int init_smouse(void);
119 static void read_motion(int *m, const char *s);
120 static void read_keystate(unsigned int *stptr, const char *s);
121 static void procpkt(struct packet *p);
122 static void enqueue_event(sball_event *ev);
124 #define COM_FMT_8N1 LCTL_8N1
125 #define COM_FMT_8N2 LCTL_8N2
126 static void com_setup(int port, int baud, unsigned int fmt);
127 static void com_close(void);
129 static void com_putc(char c);
130 static void com_puts(const char *s);
131 static int com_getc(void);
132 static char *com_gets(char *buf, int sz);
134 static int com_have_recv(void);
135 static int com_can_send(void);
138 #define INTERRUPT __interrupt __far
139 static void (INTERRUPT *prev_recv_intr)(void);
145 static _go32_dpmi_seginfo intr, prev_intr;
148 static void INTERRUPT recv_intr(void);
150 static int uart_base, uart_intr_num;
152 static struct packet pktbuf[16];
153 static int pktbuf_ridx, pktbuf_widx;
154 #define BNEXT(x) (((x) + 1) & 0xf)
155 #define BEMPTY(b) (b##_ridx == b##_widx)
157 static sball_event evbuf[16];
158 static int evbuf_ridx, evbuf_widx;
163 com_setup(0, 9600, COM_FMT_8N2);
168 void sball_shutdown(void)
173 int sball_getdev(void)
178 int sball_pending(void)
181 while(!BEMPTY(pktbuf)) {
182 procpkt(pktbuf + pktbuf_ridx);
183 pktbuf_ridx = BNEXT(pktbuf_ridx);
186 return !BEMPTY(evbuf);
189 int sball_getevent(sball_event *ev)
192 while(!BEMPTY(pktbuf)) {
193 procpkt(pktbuf + pktbuf_ridx);
194 pktbuf_ridx = BNEXT(pktbuf_ridx);
201 *ev = evbuf[evbuf_ridx];
202 evbuf_ridx = BNEXT(evbuf_ridx);
206 static int init_smouse(void)
208 /* try repeatedly zeroing the device until we get a response */
212 } while(BEMPTY(pktbuf));
214 /* then ask for id string and request motion updates */
220 static void procpkt(struct packet *p)
222 static unsigned int bnstate;
224 unsigned int st, delta, prev;
229 ev = evbuf + evbuf_widx;
230 read_motion(ev->motion.motion, p->data);
231 ev->type = SBALL_EV_MOTION;
236 read_keystate(&st, p->data);
238 delta = st ^ bnstate;
242 for(i=0; i<32; i++) {
244 ev = evbuf + evbuf_widx;
245 ev->type = SBALL_EV_BUTTON;
247 ev->button.pressed = st & 1;
248 ev->button.state = prev ^ (1 << i);
257 printf("Device: %s\n", p->data);
261 printf("DBG %c -> %s\n", (char)p->id, p->data);
266 static void enqueue_event(sball_event *ev)
268 if(ev != evbuf + evbuf_widx) {
269 evbuf[evbuf_widx] = *ev;
272 evbuf_widx = BNEXT(evbuf_widx);
273 if(evbuf_widx == evbuf_ridx) {
274 fprintf(stderr, "enqueue_event: overflow, dropping oldest\n");
275 evbuf_ridx = BNEXT(evbuf_ridx);
279 static void com_setup(int port, int baud, unsigned int fmt)
282 unsigned short div = 115200 / baud;
283 static int base[] = {UART1_BASE, UART2_BASE};
284 static int irq[] = {UART1_IRQ, UART2_IRQ};
286 uart_base = base[port];
287 uart_intr_num = irq[port] | 8;
291 prev_recv_intr = _dos_getvect(uart_intr_num);
292 _dos_setvect(uart_intr_num, recv_intr);
295 _go32_dpmi_get_protected_mode_interrupt_vector(uart_intr_num, &prev_intr);
296 intr.pm_offset = (intptr_t)recv_intr;
297 intr.pm_selector = _go32_my_cs();
298 _go32_dpmi_allocate_iret_wrapper(&intr);
299 _go32_dpmi_set_protected_mode_interrupt_vector(uart_intr_num, &intr);
301 /* unmask the appropriate interrupt */
302 outp(PIC1_DATA_PORT, inp(PIC1_DATA_PORT) & ~(1 << irq[port]));
304 outp(uart_base + UART_LCTL, LCTL_DLAB);
305 outp(uart_base + UART_DIVLO, div & 0xff);
306 outp(uart_base + UART_DIVHI, (div >> 8) & 0xff);
307 outp(uart_base + UART_LCTL, fmt); /* fmt should be LCTL_8N1, LCTL_8N2 etc */
308 outp(uart_base + UART_FIFO, FIFO_ENABLE | FIFO_SEND_CLEAR | FIFO_RECV_CLEAR);
309 outp(uart_base + UART_MCTL, MCTL_DTR | MCTL_RTS | MCTL_OUT2);
310 outp(uart_base + UART_INTR, INTR_RECV);
315 static void com_close(void)
318 outp(uart_base + UART_INTR, 0);
319 outp(uart_base + UART_MCTL, 0);
321 _dos_setvect(uart_intr_num, prev_recv_intr);
324 _go32_dpmi_set_protected_mode_interrupt_vector(uart_intr_num, &prev_intr);
325 _go32_dpmi_free_iret_wrapper(&intr);
330 static void com_putc(char c)
332 while(!com_can_send());
333 while((inp(uart_base + UART_MSTAT) & MST_CTS) == 0);
334 outp(uart_base + UART_DATA, c);
337 static void com_puts(const char *s)
344 static int com_getc(void)
347 while(!(have = com_have_recv()));
348 return inp(uart_base + UART_DATA);
351 static char *com_gets(char *buf, int sz)
356 while(sz-- > 1 && (c = com_getc()) != -1) {
370 static int com_have_recv(void)
372 unsigned short stat = inp(uart_base + UART_LSTAT);
373 if(stat & LST_ERROR) {
374 fprintf(stderr, "receive error\n");
377 return stat & LST_DRDY;
380 static int com_can_send(void)
382 return inp(uart_base + UART_LSTAT) & LST_TREG_EMPTY;
385 static void INTERRUPT recv_intr()
387 static char buf[128];
388 static char *bptr = buf;
390 int idreg, c, datasz;
392 while(((idreg = inp(uart_base + UART_IID)) & IID_PENDING) == 0) {
393 while(com_have_recv()) {
394 if((c = inp(uart_base + UART_DATA)) == '\r') {
399 pkt = pktbuf + pktbuf_widx;
400 pktbuf_widx = BNEXT(pktbuf_widx);
402 if(pktbuf_widx == pktbuf_ridx) {
403 /* we overflowed, drop the oldest packet */
404 pktbuf_ridx = BNEXT(pktbuf_ridx);
407 if(datasz > sizeof pkt->data) {
408 datasz = sizeof pkt->data; /* truncate */
411 memcpy(pkt->data, buf + 1, datasz);
413 } else if(bptr - buf < sizeof buf - 1) {
419 outp(PIC1_CMD_PORT, OCW2_EOI);
422 static void read_motion(int *m, const char *s)
427 long val = ((((long)s[0] & 0xf) << 12) |
428 (((long)s[1] & 0xf) << 8) |
429 (((long)s[2] & 0xf) << 4) |
430 ((long)s[3] & 0xf)) - 32768;
436 static void read_keystate(unsigned int *stptr, const char *s)
442 st |= ((unsigned int)*s++ & 0xf) << bit;