25 #define UART1_BASE 0x3f8
26 #define UART2_BASE 0x2f8
41 /* interrupt enable register bits */
47 /* fifo control register bits */
48 #define FIFO_ENABLE 0x01
49 #define FIFO_RECV_CLEAR 0x02
50 #define FIFO_SEND_CLEAR 0x04
52 #define FIFO_TRIG_4 0x40
53 #define FIFO_TRIG_8 0x80
54 #define FIFO_TRIG_14 0xc0
56 /* interrupt id register bits */
57 #define IID_PENDING 0x01
61 #define IID_FIFO_EN 0xc0
63 #define IID_SOURCE 0xe
69 #define IID_STATUS 0x6
71 /* line control register bits */
72 #define LCTL_BITS_8 0x03
73 #define LCTL_STOP_2 0x04
74 #define LCTL_DLAB 0x80
75 #define LCTL_8N1 LCTL_BITS_8
76 #define LCTL_8N2 (LCTL_BITS_8 | LCTL_STOP_2)
78 /* modem control register bits */
81 #define MCTL_OUT1 0x04
82 #define MCTL_OUT2 0x08
83 #define MCTL_LOOP 0x10
85 /* line status register bits */
87 #define LST_ERR_OVER 0x02
88 #define LST_ERR_PARITY 0x04
89 #define LST_ERR_FRAME 0x08
90 #define LST_ERR_BRK 0x10
91 #define LST_TREG_EMPTY 0x20
92 #define LST_TIDLE 0x40
93 #define LST_ERROR 0x80
95 /* modem status register bits */
96 #define MST_DELTA_CTS 0x01
97 #define MST_DELTA_DSR 0x02
99 #define MST_DELTA_DCD 0x08
102 #define MST_RING 0x40
105 /* interrupt controller stuff */
106 #define PIC1_CMD_PORT 0x20
107 #define PIC1_DATA_PORT 0x21
108 #define PIC2_CMD_PORT 0xa0
109 #define PIC2_DATA_PORT 0xa1
110 #define OCW2_EOI 0x20
117 static int init_smouse(void);
118 static void read_motion(int *m, const char *s);
119 static void read_keystate(unsigned int *stptr, const char *s);
120 static void procpkt(struct packet *p);
121 static void enqueue_event(sball_event *ev);
123 #define COM_FMT_8N1 LCTL_8N1
124 #define COM_FMT_8N2 LCTL_8N2
125 static void com_setup(int port, int baud, unsigned int fmt);
126 static void com_close(void);
128 static void com_putc(char c);
129 static void com_puts(const char *s);
130 static int com_getc(void);
131 static char *com_gets(char *buf, int sz);
133 static int com_have_recv(void);
134 static int com_can_send(void);
137 #define INTERRUPT __interrupt __far
138 static void (INTERRUPT *prev_recv_intr)(void);
144 static _go32_dpmi_seginfo intr, prev_intr;
146 #define outp(port, val) outportb(port, val)
147 #define inp(port) inportb(port)
150 static void INTERRUPT recv_intr(void);
152 static int uart_base, uart_intr_num;
154 static struct packet pktbuf[16];
155 static int pktbuf_ridx, pktbuf_widx;
156 #define BNEXT(x) (((x) + 1) & 0xf)
157 #define BEMPTY(b) (b##_ridx == b##_widx)
159 static sball_event evbuf[16];
160 static int evbuf_ridx, evbuf_widx;
165 com_setup(0, 9600, COM_FMT_8N2);
170 void sball_shutdown(void)
175 int sball_getdev(void)
180 int sball_pending(void)
183 while(!BEMPTY(pktbuf)) {
184 procpkt(pktbuf + pktbuf_ridx);
185 pktbuf_ridx = BNEXT(pktbuf_ridx);
188 return !BEMPTY(evbuf);
191 int sball_getevent(sball_event *ev)
194 while(!BEMPTY(pktbuf)) {
195 procpkt(pktbuf + pktbuf_ridx);
196 pktbuf_ridx = BNEXT(pktbuf_ridx);
203 *ev = evbuf[evbuf_ridx];
204 evbuf_ridx = BNEXT(evbuf_ridx);
208 static int init_smouse(void)
210 /* try repeatedly zeroing the device until we get a response */
214 } while(BEMPTY(pktbuf));
216 /* then ask for id string and request motion updates */
222 static void procpkt(struct packet *p)
224 static unsigned int bnstate;
226 unsigned int st, delta, prev;
231 ev = evbuf + evbuf_widx;
232 read_motion(ev->motion.motion, p->data);
233 ev->type = SBALL_EV_MOTION;
238 read_keystate(&st, p->data);
240 delta = st ^ bnstate;
244 for(i=0; i<32; i++) {
246 ev = evbuf + evbuf_widx;
247 ev->type = SBALL_EV_BUTTON;
249 ev->button.pressed = st & 1;
250 ev->button.state = prev ^ (1 << i);
259 printf("Device: %s\n", p->data);
263 printf("DBG %c -> %s\n", (char)p->id, p->data);
268 static void enqueue_event(sball_event *ev)
270 if(ev != evbuf + evbuf_widx) {
271 evbuf[evbuf_widx] = *ev;
274 evbuf_widx = BNEXT(evbuf_widx);
275 if(evbuf_widx == evbuf_ridx) {
276 fprintf(stderr, "enqueue_event: overflow, dropping oldest\n");
277 evbuf_ridx = BNEXT(evbuf_ridx);
281 static void com_setup(int port, int baud, unsigned int fmt)
284 unsigned short div = 115200 / baud;
285 static int base[] = {UART1_BASE, UART2_BASE};
286 static int irq[] = {UART1_IRQ, UART2_IRQ};
288 uart_base = base[port];
289 uart_intr_num = irq[port] | 8;
293 prev_recv_intr = _dos_getvect(uart_intr_num);
294 _dos_setvect(uart_intr_num, recv_intr);
297 _go32_dpmi_get_protected_mode_interrupt_vector(uart_intr_num, &prev_intr);
298 intr.pm_offset = (intptr_t)recv_intr;
299 intr.pm_selector = _go32_my_cs();
300 _go32_dpmi_allocate_iret_wrapper(&intr);
301 _go32_dpmi_set_protected_mode_interrupt_vector(uart_intr_num, &intr);
303 /* unmask the appropriate interrupt */
304 outp(PIC1_DATA_PORT, inp(PIC1_DATA_PORT) & ~(1 << irq[port]));
306 outp(uart_base + UART_LCTL, LCTL_DLAB);
307 outp(uart_base + UART_DIVLO, div & 0xff);
308 outp(uart_base + UART_DIVHI, (div >> 8) & 0xff);
309 outp(uart_base + UART_LCTL, fmt); /* fmt should be LCTL_8N1, LCTL_8N2 etc */
310 outp(uart_base + UART_FIFO, FIFO_ENABLE | FIFO_SEND_CLEAR | FIFO_RECV_CLEAR);
311 outp(uart_base + UART_MCTL, MCTL_DTR | MCTL_RTS | MCTL_OUT2);
312 outp(uart_base + UART_INTR, INTR_RECV);
317 static void com_close(void)
320 outp(uart_base + UART_INTR, 0);
321 outp(uart_base + UART_MCTL, 0);
323 _dos_setvect(uart_intr_num, prev_recv_intr);
326 _go32_dpmi_set_protected_mode_interrupt_vector(uart_intr_num, &prev_intr);
327 _go32_dpmi_free_iret_wrapper(&intr);
332 static void com_putc(char c)
334 while(!com_can_send());
335 while((inp(uart_base + UART_MSTAT) & MST_CTS) == 0);
336 outp(uart_base + UART_DATA, c);
339 static void com_puts(const char *s)
346 static int com_getc(void)
349 while(!(have = com_have_recv()));
350 return inp(uart_base + UART_DATA);
353 static char *com_gets(char *buf, int sz)
358 while(sz-- > 1 && (c = com_getc()) != -1) {
372 static int com_have_recv(void)
374 unsigned short stat = inp(uart_base + UART_LSTAT);
375 if(stat & LST_ERROR) {
376 fprintf(stderr, "receive error\n");
379 return stat & LST_DRDY;
382 static int com_can_send(void)
384 return inp(uart_base + UART_LSTAT) & LST_TREG_EMPTY;
387 static void INTERRUPT recv_intr()
389 static char buf[128];
390 static char *bptr = buf;
392 int idreg, c, datasz;
394 while(((idreg = inp(uart_base + UART_IID)) & IID_PENDING) == 0) {
395 while(com_have_recv()) {
396 if((c = inp(uart_base + UART_DATA)) == '\r') {
401 pkt = pktbuf + pktbuf_widx;
402 pktbuf_widx = BNEXT(pktbuf_widx);
404 if(pktbuf_widx == pktbuf_ridx) {
405 /* we overflowed, drop the oldest packet */
406 pktbuf_ridx = BNEXT(pktbuf_ridx);
409 if(datasz > sizeof pkt->data) {
410 datasz = sizeof pkt->data; /* truncate */
413 memcpy(pkt->data, buf + 1, datasz);
415 } else if(bptr - buf < sizeof buf - 1) {
421 outp(PIC1_CMD_PORT, OCW2_EOI);
424 static void read_motion(int *m, const char *s)
429 long val = ((((long)s[0] & 0xf) << 12) |
430 (((long)s[1] & 0xf) << 8) |
431 (((long)s[2] & 0xf) << 4) |
432 ((long)s[3] & 0xf)) - 32768;
438 static void read_keystate(unsigned int *stptr, const char *s)
444 st |= ((unsigned int)*s++ & 0xf) << bit;