12 #define UART1_BASE 0x3f8
13 #define UART2_BASE 0x2f8
28 /* interrupt enable register bits */
34 /* fifo control register bits */
35 #define FIFO_ENABLE 0x01
36 #define FIFO_RECV_CLEAR 0x02
37 #define FIFO_SEND_CLEAR 0x04
39 #define FIFO_TRIG_4 0x40
40 #define FIFO_TRIG_8 0x80
41 #define FIFO_TRIG_14 0xc0
43 /* interrupt id register bits */
44 #define IID_PENDING 0x01
48 #define IID_FIFO_EN 0xc0
50 #define IID_SOURCE 0xe
56 #define IID_STATUS 0x6
58 /* line control register bits */
59 #define LCTL_BITS_8 0x03
60 #define LCTL_STOP_2 0x04
61 #define LCTL_DLAB 0x80
62 #define LCTL_8N1 LCTL_BITS_8
63 #define LCTL_8N2 (LCTL_BITS_8 | LCTL_STOP_2)
65 /* modem control register bits */
68 #define MCTL_OUT1 0x04
69 #define MCTL_OUT2 0x08
70 #define MCTL_LOOP 0x10
72 /* line status register bits */
74 #define LST_ERR_OVER 0x02
75 #define LST_ERR_PARITY 0x04
76 #define LST_ERR_FRAME 0x08
77 #define LST_ERR_BRK 0x10
78 #define LST_TREG_EMPTY 0x20
79 #define LST_TIDLE 0x40
80 #define LST_ERROR 0x80
82 /* modem status register bits */
83 #define MST_DELTA_CTS 0x01
84 #define MST_DELTA_DSR 0x02
86 #define MST_DELTA_DCD 0x08
92 /* interrupt controller stuff */
93 #define PIC1_CMD_PORT 0x20
94 #define PIC1_DATA_PORT 0x21
95 #define PIC2_CMD_PORT 0xa0
96 #define PIC2_DATA_PORT 0xa1
99 static int init_smouse(void);
100 static void read_motion(int *m, const char *s);
101 static void read_keystate(unsigned int *stptr, const char *s);
102 static void procpkt(struct packet *p);
103 static void enqueue_event(sball_event *ev);
105 #define COM_FMT_8N1 LCTL_8N1
106 #define COM_FMT_8N2 LCTL_8N2
107 static void com_setup(int port, int baud, unsigned int fmt);
109 static void com_putc(char c);
110 static void com_puts(const char *s);
111 static int com_getc(void);
112 static char *com_gets(char *buf, int sz);
114 static int com_have_recv(void);
115 static int com_can_send(void);
117 static void __interrupt __far recv_intr(void);
119 static int uart_base, uart_intr_num;
120 static void (__interrupt __far *prev_recv_intr)(void);
122 static struct packet {
126 static int pktbuf_ridx, pktbuf_widx;
127 #define BNEXT(x) (((x) + 1) & 0xf)
128 #define BEMPTY(b) (b##_ridx == b##_widx)
130 static sball_event evbuf[16];
131 static int evbuf_ridx, evbuf_widx;
136 com_setup(0, 9600, COM_FMT_8N2);
141 void sball_shutdown(void)
146 int sball_getdev(void)
151 int sball_pending(void)
154 while(!BEMPTY(pktbuf)) {
155 procpkt(pktbuf + pktbuf_ridx);
156 pktbuf_ridx = BNEXT(pktbuf_ridx);
159 return !BEMPTY(evbuf);
162 int sball_getevent(sball_event *ev)
165 while(!BEMPTY(pktbuf)) {
166 procpkt(pktbuf + pktbuf_ridx);
167 pktbuf_ridx = BNEXT(pktbuf_ridx);
174 *ev = evbuf[evbuf_ridx];
175 evbuf_ridx = BNEXT(evbuf_ridx);
179 static int init_smouse(void)
181 /* try repeatedly zeroing the device until we get a response */
185 } while(BEMPTY(pktbuf));
187 /* then ask for id string and request motion updates */
193 static void procpkt(struct packet *p)
195 static unsigned int bnstate;
197 unsigned int st, delta, prev;
202 ev = evbuf + evbuf_widx;
203 read_motion(ev->motion.motion, p->data);
204 ev->type = SBALL_EV_MOTION;
209 read_keystate(&st, p->data);
211 delta = st ^ bnstate;
215 for(i=0; i<32; i++) {
217 ev = evbuf + evbuf_widx;
218 ev->type = SBALL_EV_BUTTON;
220 ev->button.pressed = st & 1;
221 ev->button.state = prev ^ (1 << i);
230 printf("Device: %s\n", p->data);
234 printf("DBG %c -> %s\n", (char)p->id, p->data);
239 static void enqueue_event(sball_event *ev)
241 if(ev != evbuf + evbuf_widx) {
242 evbuf[evbuf_widx] = *ev;
245 evbuf_widx = BNEXT(evbuf_widx);
246 if(evbuf_widx == evbuf_ridx) {
247 fprintf(stderr, "enqueue_event: overflow, dropping oldest\n");
248 evbuf_ridx = BNEXT(evbuf_ridx);
252 static void com_setup(int port, int baud, unsigned int fmt)
255 unsigned short div = 115200 / baud;
256 static int base[] = {UART1_BASE, UART2_BASE};
257 static int irq[] = {UART1_IRQ, UART2_IRQ};
259 uart_base = base[port];
260 uart_intr_num = irq[port] | 8;
263 prev_recv_intr = _dos_getvect(uart_intr_num);
264 _dos_setvect(uart_intr_num, recv_intr);
265 /* unmask the appropriate interrupt */
266 outp(PIC1_DATA_PORT, inp(PIC1_DATA_PORT) & ~(1 << irq[port]));
268 outp(uart_base + UART_LCTL, LCTL_DLAB);
269 outp(uart_base + UART_DIVLO, div & 0xff);
270 outp(uart_base + UART_DIVHI, (div >> 8) & 0xff);
271 outp(uart_base + UART_LCTL, fmt); /* fmt should be LCTL_8N1, LCTL_8N2 etc */
272 outp(uart_base + UART_FIFO, FIFO_ENABLE | FIFO_SEND_CLEAR | FIFO_RECV_CLEAR);
273 outp(uart_base + UART_MCTL, MCTL_DTR | MCTL_RTS | MCTL_OUT2);
274 outp(uart_base + UART_INTR, INTR_RECV);
279 static void com_close(void)
282 outp(uart_base + UART_INTR, 0);
283 outp(uart_base + UART_MCTL, 0);
284 _dos_setvect(uart_intr_num, prev_recv_intr);
288 static void com_putc(char c)
290 while(!com_can_send());
291 while((inp(uart_base + UART_MSTAT) & MST_CTS) == 0);
292 outp(uart_base + UART_DATA, c);
295 static void com_puts(const char *s)
302 static int com_getc(void)
305 while(!(have = com_have_recv()));
306 return inp(uart_base + UART_DATA);
309 static char *com_gets(char *buf, int sz)
314 while(sz-- > 1 && (c = com_getc()) != -1) {
328 static int com_have_recv(void)
330 unsigned short stat = inp(uart_base + UART_LSTAT);
331 if(stat & LST_ERROR) {
332 fprintf(stderr, "receive error\n");
335 return stat & LST_DRDY;
338 static int com_can_send(void)
340 return inp(uart_base + UART_LSTAT) & LST_TREG_EMPTY;
343 static void __interrupt __far recv_intr()
345 static char buf[128];
346 static char *bptr = buf;
348 int idreg, c, datasz;
350 while(((idreg = inp(uart_base + UART_IID)) & IID_PENDING) == 0) {
351 while(com_have_recv()) {
352 if((c = inp(uart_base + UART_DATA)) == '\r') {
357 pkt = pktbuf + pktbuf_widx;
358 pktbuf_widx = BNEXT(pktbuf_widx);
360 if(pktbuf_widx == pktbuf_ridx) {
361 /* we overflowed, drop the oldest packet */
362 pktbuf_ridx = BNEXT(pktbuf_ridx);
365 if(datasz > sizeof pkt->data) {
366 datasz = sizeof pkt->data; /* truncate */
369 memcpy(pkt->data, buf + 1, datasz);
371 } else if(bptr - buf < sizeof buf - 1) {
377 outp(PIC1_CMD_PORT, OCW2_EOI);
380 static void read_motion(int *m, const char *s)
385 long val = ((((long)s[0] & 0xf) << 12) |
386 (((long)s[1] & 0xf) << 8) |
387 (((long)s[2] & 0xf) << 4) |
388 ((long)s[3] & 0xf)) - 32768;
394 static void read_keystate(unsigned int *stptr, const char *s)
400 st |= ((unsigned int)*s++ & 0xf) << bit;