xref: /netbsd-src/sys/arch/x68k/dev/ms.c (revision 93f9db1b75d415b78f73ed629beeb86235153473)
1 /*	$NetBSD: ms.c,v 1.5 1998/08/05 16:08:36 minoura Exp $ */
2 
3 /*
4  * Copyright (c) 1992, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This software was developed by the Computer Systems Engineering group
8  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9  * contributed to Berkeley.
10  *
11  * All advertising materials mentioning features or use of this software
12  * must display the following acknowledgement:
13  *	This product includes software developed by the University of
14  *	California, Lawrence Berkeley Laboratory.
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions
18  * are met:
19  * 1. Redistributions of source code must retain the above copyright
20  *    notice, this list of conditions and the following disclaimer.
21  * 2. Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the
23  *    documentation and/or other materials provided with the distribution.
24  * 3. All advertising materials mentioning features or use of this software
25  *    must display the following acknowledgement:
26  *	This product includes software developed by the University of
27  *	California, Berkeley and its contributors.
28  * 4. Neither the name of the University nor the names of its contributors
29  *    may be used to endorse or promote products derived from this software
30  *    without specific prior written permission.
31  *
32  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
33  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42  * SUCH DAMAGE.
43  *
44  *	@(#)ms.c	8.1 (Berkeley) 6/11/93
45  */
46 
47 /*
48  * X68k mouse driver.
49  */
50 
51 #include <sys/param.h>
52 #include <sys/conf.h>
53 #include <sys/ioctl.h>
54 #include <sys/kernel.h>
55 #include <sys/proc.h>
56 #include <sys/syslog.h>
57 #include <sys/systm.h>
58 #include <sys/tty.h>
59 #include <sys/device.h>
60 
61 #include <dev/ic/z8530reg.h>
62 #include <machine/z8530var.h>
63 
64 #include <arch/x68k/dev/event_var.h>
65 #include <machine/vuid_event.h>
66 
67 #include "locators.h"
68 
69 /*
70  * How many input characters we can buffer.
71  * The port-specific var.h may override this.
72  * Note: must be a power of two!
73  */
74 #define	MS_RX_RING_SIZE	256
75 #define MS_RX_RING_MASK (MS_RX_RING_SIZE-1)
76 /*
77  * Output buffer.  Only need a few chars.
78  */
79 #define	MS_TX_RING_SIZE	16
80 #define MS_TX_RING_MASK (MS_TX_RING_SIZE-1)
81 /*
82  * Mouse serial line is fixed at 4800 bps.
83  */
84 #define MS_BPS 4800
85 
86 /*
87  * Mouse state.  A SHARP X1/X680x0 mouse is a fairly simple device,
88  * producing three-byte blobs of the form:
89  *
90  *	b dx dy
91  *
92  * where b is the button state, encoded as 0x80|(buttons)---there are
93  * two buttons (2=left, 1=right)---and dx,dy are X and Y delta values.
94  *
95  * It needs trigger for the transmission.  When zs RTS negated, the mouse
96  * begins the sequence.  RTS assertion has no effect.
97  */
98 struct ms_softc {
99 	struct	device ms_dev;		/* required first: base device */
100 	struct	zs_chanstate *ms_cs;
101 
102 	/* Flags to communicate with ms_softintr() */
103 	volatile int ms_intr_flags;
104 #define	INTR_RX_OVERRUN 1
105 #define INTR_TX_EMPTY   2
106 #define INTR_ST_CHECK   4
107 
108 	/*
109 	 * The receive ring buffer.
110 	 */
111 	u_int	ms_rbget;	/* ring buffer `get' index */
112 	volatile u_int	ms_rbput;	/* ring buffer `put' index */
113 	u_short	ms_rbuf[MS_RX_RING_SIZE]; /* rr1, data pairs */
114 
115 	/*
116 	 * State of input translator
117 	 */
118 	short	ms_byteno;		/* input byte number, for decode */
119 	char	ms_mb;			/* mouse button state */
120 	char	ms_ub;			/* user button state */
121 	int	ms_dx;			/* delta-x */
122 	int	ms_dy;			/* delta-y */
123 	int	ms_rts;			/* MSCTRL */
124 	int	ms_nodata;
125 
126 	/*
127 	 * State of upper interface.
128 	 */
129 	volatile int ms_ready;		/* event queue is ready */
130 	struct	evvar ms_events;	/* event queue state */
131 } ms_softc;
132 
133 cdev_decl(ms);
134 
135 static int ms_match __P((struct device*, struct cfdata*, void*));
136 static void ms_attach __P((struct device*, struct device*, void*));
137 static void ms_trigger __P((struct zs_chanstate*, int));
138 void ms_modem __P((void));
139 
140 struct cfattach ms_ca = {
141 	sizeof(struct ms_softc), ms_match, ms_attach
142 };
143 
144 extern struct zsops zsops_ms;
145 extern struct cfdriver ms_cd;
146 
147 /*
148  * ms_match: how is this zs channel configured?
149  */
150 int
151 ms_match(parent, cf, aux)
152 	struct device *parent;
153 	struct cfdata *cf;
154 	void   *aux;
155 {
156 	struct zsc_attach_args *args = aux;
157 	struct zsc_softc *zsc = (void*) parent;
158 
159 	/* Exact match required for the mouse. */
160 	if (cf->cf_loc[ZSCCF_CHANNEL] != args->channel)
161 		return 0;
162 	if (args->channel != 1)
163 		return 0;
164 
165 	return 1;
166 }
167 
168 void
169 ms_attach(parent, self, aux)
170 	struct device *parent, *self;
171 	void   *aux;
172 
173 {
174 	struct zsc_softc *zsc = (void *) parent;
175 	struct ms_softc *ms = (void *) self;
176 	struct zsc_attach_args *args = aux;
177 	struct zs_chanstate *cs;
178 	struct cfdata *cf;
179 	int reset, s;
180 
181 	cf = ms->ms_dev.dv_cfdata;
182 	cs = zsc->zsc_cs[1];
183 	cs->cs_private = ms;
184 	cs->cs_ops = &zsops_ms;
185 	ms->ms_cs = cs;
186 
187 	/* Initialize the speed, etc. */
188 	s = splzs();
189 	/* May need reset... */
190 	reset = ZSWR9_B_RESET;
191 	zs_write_reg(cs, 9, reset);
192 	/* We don't care about status or tx interrupts. */
193 	cs->cs_preg[1] = ZSWR1_RIE;
194 	cs->cs_preg[4] = ZSWR4_CLK_X16 | ZSWR4_TWOSB;
195 	(void) zs_set_speed(cs, MS_BPS);
196 	zs_loadchannelregs(cs);
197 	splx(s);
198 
199 	/* Initialize translator. */
200 	ms->ms_ready = 0;
201 
202 	printf ("\n");
203 }
204 
205 /****************************************************************
206  *  Entry points for /dev/mouse
207  *  (open,close,read,write,...)
208  ****************************************************************/
209 
210 int
211 msopen(dev, flags, mode, p)
212 	dev_t dev;
213 	int flags, mode;
214 	struct proc *p;
215 {
216 	struct ms_softc *ms;
217 	int unit;
218 
219 printf ("msopen\n");
220 	unit = minor(dev);
221 	if (unit >= ms_cd.cd_ndevs)
222 		return (ENXIO);
223 	ms = ms_cd.cd_devs[unit];
224 	if (ms == NULL)
225 		return (ENXIO);
226 
227 	/* This is an exclusive open device. */
228 	if (ms->ms_events.ev_io)
229 		return (EBUSY);
230 	ms->ms_events.ev_io = p;
231 	ev_init(&ms->ms_events);	/* may cause sleep */
232 
233 	ms->ms_ready = 1;		/* start accepting events */
234 	ms->ms_rts = 1;
235 	ms_trigger(ms->ms_cs, 1);	/* set MSCTR high (standby) */
236 	ms->ms_byteno = -1;
237 	ms->ms_nodata = 0;
238 	return (0);
239 }
240 
241 int
242 msclose(dev, flags, mode, p)
243 	dev_t dev;
244 	int flags, mode;
245 	struct proc *p;
246 {
247 	struct ms_softc *ms;
248 
249 	ms = ms_cd.cd_devs[minor(dev)];
250 	ms->ms_ready = 0;		/* stop accepting events */
251 	ev_fini(&ms->ms_events);
252 
253 	ms->ms_events.ev_io = NULL;
254 	return (0);
255 }
256 
257 int
258 msread(dev, uio, flags)
259 	dev_t dev;
260 	struct uio *uio;
261 	int flags;
262 {
263 	struct ms_softc *ms;
264 
265 	ms = ms_cd.cd_devs[minor(dev)];
266 	return (ev_read(&ms->ms_events, uio, flags));
267 }
268 
269 /* this routine should not exist, but is convenient to write here for now */
270 int
271 mswrite(dev, uio, flags)
272 	dev_t dev;
273 	struct uio *uio;
274 	int flags;
275 {
276 
277 	return (EOPNOTSUPP);
278 }
279 
280 int
281 msioctl(dev, cmd, data, flag, p)
282 	dev_t dev;
283 	u_long cmd;
284 	register caddr_t data;
285 	int flag;
286 	struct proc *p;
287 {
288 	struct ms_softc *ms;
289 
290 	ms = ms_cd.cd_devs[minor(dev)];
291 
292 	switch (cmd) {
293 
294 	case FIONBIO:		/* we will remove this someday (soon???) */
295 		return (0);
296 
297 	case FIOASYNC:
298 		ms->ms_events.ev_async = *(int *)data != 0;
299 		return (0);
300 
301 	case TIOCSPGRP:
302 		if (*(int *)data != ms->ms_events.ev_io->p_pgid)
303 			return (EPERM);
304 		return (0);
305 
306 	case VUIDGFORMAT:
307 		/* we only do firm_events */
308 		*(int *)data = VUID_FIRM_EVENT;
309 		return (0);
310 
311 	case VUIDSFORMAT:
312 		if (*(int *)data != VUID_FIRM_EVENT)
313 			return (EINVAL);
314 		return (0);
315 	}
316 	return (ENOTTY);
317 }
318 
319 int
320 mspoll(dev, events, p)
321 	dev_t dev;
322 	int events;
323 	struct proc *p;
324 {
325 	struct ms_softc *ms;
326 
327 	ms = ms_cd.cd_devs[minor(dev)];
328 	return (ev_poll(&ms->ms_events, events, p));
329 }
330 
331 
332 /****************************************************************
333  * Middle layer (translator)
334  ****************************************************************/
335 
336 static void ms_input __P((struct ms_softc *, int c));
337 
338 
339 /*
340  * Called by our ms_softint() routine on input.
341  */
342 static void
343 ms_input(ms, c)
344 	register struct ms_softc *ms;
345 	register int c;
346 {
347 	register struct firm_event *fe;
348 	register int mb, ub, d, get, put, any;
349 	static const char to_one[] = { 1, 2, 3 };
350 	static const int to_id[] = { MS_LEFT, MS_RIGHT, MS_MIDDLE };
351 
352 	/*
353 	 * Discard input if not ready.  Drop sync on parity or framing
354 	 * error; gain sync on button byte.
355 	 */
356 	if (ms->ms_ready == 0)
357 		return;
358 
359 	ms->ms_nodata = 0;
360 	/*
361 	 * Run the decode loop, adding to the current information.
362 	 * We add, rather than replace, deltas, so that if the event queue
363 	 * fills, we accumulate data for when it opens up again.
364 	 */
365 	switch (ms->ms_byteno) {
366 
367 	case -1:
368 		return;
369 
370 	case 0:
371 		/* buttons */
372 		ms->ms_byteno = 1;
373 		ms->ms_mb = c & 0x3;
374 		return;
375 
376 	case 1:
377 		/* delta-x */
378 		ms->ms_byteno = 2;
379 		ms->ms_dx += (char)c;
380 		return;
381 
382 	case 2:
383 		/* delta-y */
384 		ms->ms_byteno = -1;
385 		ms->ms_dy += (char)c;
386 		break;
387 
388 	default:
389 		panic("ms_input");
390 		/* NOTREACHED */
391 	}
392 
393 	/*
394 	 * We have at least one event (mouse button, delta-X, or
395 	 * delta-Y; possibly all three, and possibly three separate
396 	 * button events).  Deliver these events until we are out
397 	 * of changes or out of room.  As events get delivered,
398 	 * mark them `unchanged'.
399 	 */
400 	any = 0;
401 	get = ms->ms_events.ev_get;
402 	put = ms->ms_events.ev_put;
403 	fe = &ms->ms_events.ev_q[put];
404 
405 	/* NEXT prepares to put the next event, backing off if necessary */
406 #define	NEXT \
407 	if ((++put) % EV_QSIZE == get) { \
408 		put--; \
409 		goto out; \
410 	}
411 	/* ADVANCE completes the `put' of the event */
412 #define	ADVANCE \
413 	fe++; \
414 	if (put >= EV_QSIZE) { \
415 		put = 0; \
416 		fe = &ms->ms_events.ev_q[0]; \
417 	} \
418 
419 	mb = ms->ms_mb;
420 	ub = ms->ms_ub;
421 	while ((d = mb ^ ub) != 0) {
422 		/*
423 		 * Mouse button change.  Convert up to three changes
424 		 * to the `first' change, and drop it into the event queue.
425 		 */
426 		NEXT;
427 		d = to_one[d - 1];		/* from 1..7 to {1,2,4} */
428 		fe->id = to_id[d - 1];		/* from {1,2,4} to ID */
429 		fe->value = mb & d ? VKEY_DOWN : VKEY_UP;
430 		fe->time = time;
431 		ADVANCE;
432 		ub ^= d;
433 		any++;
434 	}
435 	if (ms->ms_dx) {
436 		NEXT;
437 		fe->id = LOC_X_DELTA;
438 		fe->value = ms->ms_dx;
439 		fe->time = time;
440 		ADVANCE;
441 		ms->ms_dx = 0;
442 		any++;
443 	}
444 	if (ms->ms_dy) {
445 		NEXT;
446 		fe->id = LOC_Y_DELTA;
447 		fe->value = -ms->ms_dy;	/* XXX? */
448 		fe->time = time;
449 		ADVANCE;
450 		ms->ms_dy = 0;
451 		any++;
452 	}
453 out:
454 	if (any) {
455 		ms->ms_ub = ub;
456 		ms->ms_events.ev_put = put;
457 		EV_WAKEUP(&ms->ms_events);
458 	}
459 }
460 
461 /****************************************************************
462  * Interface to the lower layer (zscc)
463  ****************************************************************/
464 
465 static void ms_rxint __P((struct zs_chanstate *));
466 static void ms_txint __P((struct zs_chanstate *));
467 static void ms_stint __P((struct zs_chanstate *));
468 static void ms_softint __P((struct zs_chanstate *));
469 
470 static void
471 ms_rxint(cs)
472 	register struct zs_chanstate *cs;
473 {
474 	register struct ms_softc *ms;
475 	register int put, put_next;
476 	register u_char c, rr1;
477 
478 	ms = cs->cs_private;
479 	put = ms->ms_rbput;
480 
481 	/*
482 	 * First read the status, because reading the received char
483 	 * destroys the status of this char.
484 	 */
485 	rr1 = zs_read_reg(cs, 1);
486 	c = zs_read_data(cs);
487 
488 	if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
489 		/* Clear the receive error. */
490 		zs_write_csr(cs, ZSWR0_RESET_ERRORS);
491 	}
492 
493 	ms->ms_rbuf[put] = (c << 8) | rr1;
494 	put_next = (put + 1) & MS_RX_RING_MASK;
495 
496 	/* Would overrun if increment makes (put==get). */
497 	if (put_next == ms->ms_rbget) {
498 		ms->ms_intr_flags |= INTR_RX_OVERRUN;
499 	} else {
500 		/* OK, really increment. */
501 		put = put_next;
502 	}
503 
504 	/* Done reading. */
505 	ms->ms_rbput = put;
506 
507 	/* Ask for softint() call. */
508 	cs->cs_softreq = 1;
509 }
510 
511 
512 static void
513 ms_txint(cs)
514 	register struct zs_chanstate *cs;
515 {
516 	register struct ms_softc *ms;
517 
518 	ms = cs->cs_private;
519 	zs_write_csr(cs, ZSWR0_RESET_TXINT);
520 	ms->ms_intr_flags |= INTR_TX_EMPTY;
521 	/* Ask for softint() call. */
522 	cs->cs_softreq = 1;
523 }
524 
525 
526 static void
527 ms_stint(cs)
528 	register struct zs_chanstate *cs;
529 {
530 	register struct ms_softc *ms;
531 	register int rr0;
532 
533 	ms = cs->cs_private;
534 
535 	rr0 = zs_read_csr(cs);
536 	zs_write_csr(cs, ZSWR0_RESET_STATUS);
537 
538 	/*
539 	 * We have to accumulate status line changes here.
540 	 * Otherwise, if we get multiple status interrupts
541 	 * before the softint runs, we could fail to notice
542 	 * some status line changes in the softint routine.
543 	 * Fix from Bill Studenmund, October 1996.
544 	 */
545 	cs->cs_rr0_delta |= (cs->cs_rr0 ^ rr0);
546 	cs->cs_rr0 = rr0;
547 	ms->ms_intr_flags |= INTR_ST_CHECK;
548 
549 	/* Ask for softint() call. */
550 	cs->cs_softreq = 1;
551 }
552 
553 
554 static void
555 ms_softint(cs)
556 	struct zs_chanstate *cs;
557 {
558 	register struct ms_softc *ms;
559 	register int get, c, s;
560 	int intr_flags;
561 	register u_short ring_data;
562 
563 	ms = cs->cs_private;
564 
565 	/* Atomically get and clear flags. */
566 	s = splzs();
567 	intr_flags = ms->ms_intr_flags;
568 	ms->ms_intr_flags = 0;
569 
570 	/* Now lower to spltty for the rest. */
571 	(void) spltty();
572 
573 	/*
574 	 * Copy data from the receive ring to the event layer.
575 	 */
576 	get = ms->ms_rbget;
577 	while (get != ms->ms_rbput) {
578 		ring_data = ms->ms_rbuf[get];
579 		get = (get + 1) & MS_RX_RING_MASK;
580 
581 		/* low byte of ring_data is rr1 */
582 		c = (ring_data >> 8) & 0xff;
583 
584 		if (ring_data & ZSRR1_DO)
585 			intr_flags |= INTR_RX_OVERRUN;
586 		if (ring_data & (ZSRR1_FE | ZSRR1_PE)) {
587 			log(LOG_ERR, "%s: input error (0x%x)\n",
588 				ms->ms_dev.dv_xname, ring_data);
589 			c = -1;	/* signal input error */
590 		}
591 
592 		/* Pass this up to the "middle" layer. */
593 		ms_input(ms, c);
594 	}
595 	if (intr_flags & INTR_RX_OVERRUN) {
596 		log(LOG_ERR, "%s: input overrun\n",
597 		    ms->ms_dev.dv_xname);
598 	}
599 	ms->ms_rbget = get;
600 
601 	if (intr_flags & INTR_TX_EMPTY) {
602 		/*
603 		 * Transmit done.  (Not expected.)
604 		 */
605 		log(LOG_ERR, "%s: transmit interrupt?\n",
606 		    ms->ms_dev.dv_xname);
607 	}
608 
609 	if (intr_flags & INTR_ST_CHECK) {
610 		/*
611 		 * Status line change.  (Not expected.)
612 		 */
613 		log(LOG_ERR, "%s: status interrupt?\n",
614 		    ms->ms_dev.dv_xname);
615 		cs->cs_rr0_delta = 0;
616 	}
617 
618 	splx(s);
619 }
620 
621 struct zsops zsops_ms = {
622 	ms_rxint,	/* receive char available */
623 	ms_stint,	/* external/status */
624 	ms_txint,	/* xmit buffer empty */
625 	ms_softint,	/* process software interrupt */
626 };
627 
628 
629 static void
630 ms_trigger (cs, onoff)
631 	struct zs_chanstate *cs;
632 	int onoff;
633 {
634 	/* for front connected one */
635 	if (onoff)
636 		cs->cs_preg[5] |= ZSWR5_RTS;
637 	else
638 		cs->cs_preg[5] &= ~ZSWR5_RTS;
639 	cs->cs_creg[5] = cs->cs_preg[5];
640 	zs_write_reg(cs, 5, cs->cs_preg[5]);
641 
642 	/* for keyborad connected one */
643 	while (!(mfp.tsr & MFP_TSR_BE));
644 	mfp.udr = onoff | 0x40;
645 }
646 
647 /*
648  * mouse timer interrupt.
649  * called after system tick interrupt is done.
650  */
651 void
652 ms_modem(void)
653 {
654 	struct ms_softc *ms = ms_cd.cd_devs[0];
655 	int s;
656 
657 	if (!ms->ms_ready)
658 		return;
659 	if (ms->ms_nodata++ > 300) { /* XXX */
660 		log(LOG_ERR, "%s: no data for 3 secs. resetting.\n",
661 		    ms->ms_dev.dv_xname);
662 		ms->ms_nodata = 0;
663 		ms->ms_byteno = -1;
664 		ms->ms_rts = 1;
665 		ms_trigger(ms->ms_cs, 1);
666 		return;
667 	}
668 
669 	s = splzs();
670 	if (ms->ms_rts) {
671 		if (ms->ms_byteno == -1) {
672 			/* start next sequence */
673 			ms->ms_rts = 0;
674 			ms_trigger(ms->ms_cs, ms->ms_rts);
675 			ms->ms_byteno = 0;
676 		}
677 	} else {
678 		ms->ms_rts = 1;
679 		ms_trigger(ms->ms_cs, ms->ms_rts);
680 	}
681 	splx(s);
682 }
683