1 /* $NetBSD: ms.c,v 1.29 2008/06/25 08:19:37 isaki Exp $ */
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
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.
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.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
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. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * @(#)ms.c 8.1 (Berkeley) 6/11/93
47 #include <sys/cdefs.h>
48 __KERNEL_RCSID(0, "$NetBSD: ms.c,v 1.29 2008/06/25 08:19:37 isaki Exp $");
50 #include <sys/param.h>
52 #include <sys/ioctl.h>
53 #include <sys/kernel.h>
55 #include <sys/syslog.h>
56 #include <sys/systm.h>
58 #include <sys/device.h>
59 #include <sys/signalvar.h>
61 #include <dev/ic/z8530reg.h>
62 #include <machine/z8530var.h>
64 #include <arch/x68k/dev/event_var.h>
65 #include <machine/vuid_event.h>
66 #include <arch/x68k/dev/mfp.h>
72 * How many input characters we can buffer.
73 * The port-specific var.h may override this.
74 * Note: must be a power of two!
76 #define MS_RX_RING_SIZE 256
77 #define MS_RX_RING_MASK (MS_RX_RING_SIZE-1)
79 * Output buffer. Only need a few chars.
81 #define MS_TX_RING_SIZE 16
82 #define MS_TX_RING_MASK (MS_TX_RING_SIZE-1)
84 * Mouse serial line is fixed at 4800 bps.
89 * Mouse state. A SHARP X1/X680x0 mouse is a fairly simple device,
90 * producing three-byte blobs of the form:
94 * where b is the button state, encoded as 0x80|(buttons)---there are
95 * two buttons (2=left, 1=right)---and dx,dy are X and Y delta values.
97 * It needs a trigger for the transmission. When zs RTS negated, the
98 * mouse begins the sequence. RTS assertion has no effect.
101 device_t ms_dev
; /* required first: base device */
102 struct zs_chanstate
*ms_cs
;
104 struct callout ms_modem_ch
;
106 /* Flags to communicate with ms_softintr() */
107 volatile int ms_intr_flags
;
108 #define INTR_RX_OVERRUN 1
109 #define INTR_TX_EMPTY 2
110 #define INTR_ST_CHECK 4
113 * The receive ring buffer.
115 u_int ms_rbget
; /* ring buffer `get' index */
116 volatile u_int ms_rbput
; /* ring buffer `put' index */
117 u_short ms_rbuf
[MS_RX_RING_SIZE
]; /* rr1, data pairs */
120 * State of input translator
122 short ms_byteno
; /* input byte number, for decode */
123 char ms_mb
; /* mouse button state */
124 char ms_ub
; /* user button state */
125 int ms_dx
; /* delta-x */
126 int ms_dy
; /* delta-y */
127 int ms_rts
; /* MSCTRL */
131 * State of upper interface.
133 volatile int ms_ready
; /* event queue is ready */
134 struct evvar ms_events
; /* event queue state */
137 static int ms_match(device_t
, cfdata_t
, void *);
138 static void ms_attach(device_t
, device_t
, void *);
139 static void ms_trigger(struct zs_chanstate
*, int);
140 void ms_modem(void *);
142 CFATTACH_DECL_NEW(ms
, sizeof(struct ms_softc
),
143 ms_match
, ms_attach
, NULL
, NULL
);
145 static void ms_rxint(struct zs_chanstate
*);
146 static void ms_stint(struct zs_chanstate
*, int);
147 static void ms_txint(struct zs_chanstate
*);
148 static void ms_softint(struct zs_chanstate
*);
149 static void ms_input(struct ms_softc
*, int);
151 struct zsops zsops_ms
= {
152 ms_rxint
, /* receive char available */
153 ms_stint
, /* external/status */
154 ms_txint
, /* xmit buffer empty */
155 ms_softint
, /* process software interrupt */
158 dev_type_open(msopen
);
159 dev_type_close(msclose
);
160 dev_type_read(msread
);
161 dev_type_ioctl(msioctl
);
162 dev_type_poll(mspoll
);
163 dev_type_kqfilter(mskqfilter
);
165 const struct cdevsw ms_cdevsw
={
166 msopen
, msclose
, msread
, nowrite
, msioctl
,
167 nostop
, notty
, mspoll
, nommap
, mskqfilter
,
171 * ms_match: how is this zs channel configured?
174 ms_match(device_t parent
, cfdata_t cf
, void *aux
)
176 struct zsc_attach_args
*args
= aux
;
177 struct zsc_softc
*zsc
= device_private(parent
);
179 /* Exact match required for the mouse. */
180 if (cf
->cf_loc
[ZSCCF_CHANNEL
] != args
->channel
)
182 if (args
->channel
!= 1)
184 if (&zsc
->zsc_addr
->zs_chan_b
!= (struct zschan
*)ZSMS_PHYSADDR
)
191 ms_attach(device_t parent
, device_t self
, void *aux
)
193 struct ms_softc
*ms
= device_private(self
);
194 struct zsc_softc
*zsc
= device_private(parent
);
195 struct zs_chanstate
*cs
;
200 callout_init(&ms
->ms_modem_ch
, 0);
202 cf
= device_cfdata(self
);
205 cs
->cs_ops
= &zsops_ms
;
208 /* Initialize the speed, etc. */
210 /* May need reset... */
211 reset
= ZSWR9_B_RESET
;
212 zs_write_reg(cs
, 9, reset
);
213 /* We don't care about status or tx interrupts. */
214 cs
->cs_preg
[1] = ZSWR1_RIE
;
215 cs
->cs_preg
[4] = ZSWR4_CLK_X16
| ZSWR4_TWOSB
;
216 (void)zs_set_speed(cs
, MS_BPS
);
217 zs_loadchannelregs(cs
);
220 /* Initialize translator. */
226 /****************************************************************
227 * Entry points for /dev/mouse
228 * (open,close,read,write,...)
229 ****************************************************************/
232 msopen(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
236 ms
= device_lookup_private(&ms_cd
, minor(dev
));
240 /* This is an exclusive open device. */
241 if (ms
->ms_events
.ev_io
)
243 ms
->ms_events
.ev_io
= l
->l_proc
;
244 ev_init(&ms
->ms_events
); /* may cause sleep */
246 ms
->ms_ready
= 1; /* start accepting events */
251 /* start sequencer */
258 msclose(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
262 ms
= device_lookup_private(&ms_cd
, minor(dev
));
263 ms
->ms_ready
= 0; /* stop accepting events */
264 callout_stop(&ms
->ms_modem_ch
);
265 ev_fini(&ms
->ms_events
);
267 ms
->ms_events
.ev_io
= NULL
;
272 msread(dev_t dev
, struct uio
*uio
, int flags
)
276 ms
= device_lookup_private(&ms_cd
, minor(dev
));
277 return ev_read(&ms
->ms_events
, uio
, flags
);
281 msioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
285 ms
= device_lookup_private(&ms_cd
, minor(dev
));
289 case FIONBIO
: /* we will remove this someday (soon???) */
293 ms
->ms_events
.ev_async
= *(int *)data
!= 0;
297 if (-*(int *)data
!= ms
->ms_events
.ev_io
->p_pgid
298 && *(int *)data
!= ms
->ms_events
.ev_io
->p_pid
)
303 if (*(int *)data
!= ms
->ms_events
.ev_io
->p_pgid
)
308 /* we only do firm_events */
309 *(int *)data
= VUID_FIRM_EVENT
;
313 if (*(int *)data
!= VUID_FIRM_EVENT
)
321 mspoll(dev_t dev
, int events
, struct lwp
*l
)
325 ms
= device_lookup_private(&ms_cd
, minor(dev
));
326 return ev_poll(&ms
->ms_events
, events
, l
);
330 mskqfilter(dev_t dev
, struct knote
*kn
)
334 ms
= device_lookup_private(&ms_cd
, minor(dev
));
335 return ev_kqfilter(&ms
->ms_events
, kn
);
338 /****************************************************************
339 * Middle layer (translator)
340 ****************************************************************/
343 * Called by our ms_softint() routine on input.
346 ms_input(struct ms_softc
*ms
, int c
)
348 struct firm_event
*fe
;
349 int mb
, ub
, d
, get
, put
, any
;
350 static const char to_one
[] = { 1, 2, 3 };
351 static const int to_id
[] = { MS_LEFT
, MS_RIGHT
, MS_MIDDLE
};
354 * Discard input if not ready. Drop sync on parity or framing
355 * error; gain sync on button byte.
357 if (ms
->ms_ready
== 0)
362 * Run the decode loop, adding to the current information.
363 * We add, rather than replace, deltas, so that if the event queue
364 * fills, we accumulate data for when it opens up again.
366 switch (ms
->ms_byteno
) {
380 ms
->ms_dx
+= (char)c
;
386 ms
->ms_dy
+= (char)c
;
395 * We have at least one event (mouse button, delta-X, or
396 * delta-Y; possibly all three, and possibly three separate
397 * button events). Deliver these events until we are out
398 * of changes or out of room. As events get delivered,
399 * mark them `unchanged'.
402 get
= ms
->ms_events
.ev_get
;
403 put
= ms
->ms_events
.ev_put
;
404 fe
= &ms
->ms_events
.ev_q
[put
];
406 /* NEXT prepares to put the next event, backing off if necessary */
408 if ((++put) % EV_QSIZE == get) { \
412 /* ADVANCE completes the `put' of the event */
415 if (put >= EV_QSIZE) { \
417 fe = &ms->ms_events.ev_q[0]; \
422 while ((d
= mb
^ ub
) != 0) {
424 * Mouse button change. Convert up to three changes
425 * to the `first' change, and drop it into the event queue.
428 d
= to_one
[d
- 1]; /* from 1..7 to {1,2,4} */
429 fe
->id
= to_id
[d
- 1]; /* from {1,2,4} to ID */
430 fe
->value
= mb
& d
? VKEY_DOWN
: VKEY_UP
;
438 fe
->id
= LOC_X_DELTA
;
439 fe
->value
= ms
->ms_dx
;
447 fe
->id
= LOC_Y_DELTA
;
448 fe
->value
= -ms
->ms_dy
; /* XXX? */
457 ms
->ms_events
.ev_put
= put
;
458 EV_WAKEUP(&ms
->ms_events
);
462 /****************************************************************
463 * Interface to the lower layer (zscc)
464 ****************************************************************/
467 ms_rxint(struct zs_chanstate
*cs
)
477 * First read the status, because reading the received char
478 * destroys the status of this char.
480 rr1
= zs_read_reg(cs
, 1);
481 c
= zs_read_data(cs
);
483 if (rr1
& (ZSRR1_FE
| ZSRR1_DO
| ZSRR1_PE
)) {
484 /* Clear the receive error. */
485 zs_write_csr(cs
, ZSWR0_RESET_ERRORS
);
488 ms
->ms_rbuf
[put
] = (c
<< 8) | rr1
;
489 put_next
= (put
+ 1) & MS_RX_RING_MASK
;
491 /* Would overrun if increment makes (put==get). */
492 if (put_next
== ms
->ms_rbget
) {
493 ms
->ms_intr_flags
|= INTR_RX_OVERRUN
;
495 /* OK, really increment. */
502 /* Ask for softint() call. */
508 ms_txint(struct zs_chanstate
*cs
)
513 zs_write_csr(cs
, ZSWR0_RESET_TXINT
);
514 ms
->ms_intr_flags
|= INTR_TX_EMPTY
;
515 /* Ask for softint() call. */
521 ms_stint(struct zs_chanstate
*cs
, int force
)
528 rr0
= zs_read_csr(cs
);
529 zs_write_csr(cs
, ZSWR0_RESET_STATUS
);
532 * We have to accumulate status line changes here.
533 * Otherwise, if we get multiple status interrupts
534 * before the softint runs, we could fail to notice
535 * some status line changes in the softint routine.
536 * Fix from Bill Studenmund, October 1996.
538 cs
->cs_rr0_delta
|= (cs
->cs_rr0
^ rr0
);
540 ms
->ms_intr_flags
|= INTR_ST_CHECK
;
542 /* Ask for softint() call. */
548 ms_softint(struct zs_chanstate
*cs
)
557 /* Atomically get and clear flags. */
559 intr_flags
= ms
->ms_intr_flags
;
560 ms
->ms_intr_flags
= 0;
562 /* Now lower to spltty for the rest. */
566 * Copy data from the receive ring to the event layer.
569 while (get
!= ms
->ms_rbput
) {
570 ring_data
= ms
->ms_rbuf
[get
];
571 get
= (get
+ 1) & MS_RX_RING_MASK
;
573 /* low byte of ring_data is rr1 */
574 c
= (ring_data
>> 8) & 0xff;
576 if (ring_data
& ZSRR1_DO
)
577 intr_flags
|= INTR_RX_OVERRUN
;
578 if (ring_data
& (ZSRR1_FE
| ZSRR1_PE
)) {
579 log(LOG_ERR
, "%s: input error (0x%x)\n",
580 device_xname(ms
->ms_dev
), ring_data
);
581 c
= -1; /* signal input error */
584 /* Pass this up to the "middle" layer. */
587 if (intr_flags
& INTR_RX_OVERRUN
) {
588 log(LOG_ERR
, "%s: input overrun\n",
589 device_xname(ms
->ms_dev
));
593 if (intr_flags
& INTR_TX_EMPTY
) {
595 * Transmit done. (Not expected.)
597 log(LOG_ERR
, "%s: transmit interrupt?\n",
598 device_xname(ms
->ms_dev
));
601 if (intr_flags
& INTR_ST_CHECK
) {
603 * Status line change. (Not expected.)
605 log(LOG_ERR
, "%s: status interrupt?\n",
606 device_xname(ms
->ms_dev
));
607 cs
->cs_rr0_delta
= 0;
615 ms_trigger(struct zs_chanstate
*cs
, int onoff
)
617 /* for front connected one */
619 cs
->cs_preg
[5] |= ZSWR5_RTS
;
621 cs
->cs_preg
[5] &= ~ZSWR5_RTS
;
622 cs
->cs_creg
[5] = cs
->cs_preg
[5];
623 zs_write_reg(cs
, 5, cs
->cs_preg
[5]);
625 /* for keyborad connected one */
626 mfp_send_usart(onoff
| 0x40);
630 * mouse timer interrupt.
631 * called after system tick interrupt is done.
636 struct ms_softc
*ms
= arg
;
644 if (ms
->ms_nodata
++ > 250) { /* XXX */
645 log(LOG_ERR
, "%s: no data for 5 secs. resetting.\n",
646 device_xname(ms
->ms_dev
));
653 if (ms
->ms_byteno
== -1) {
654 /* start next sequence */
656 ms_trigger(ms
->ms_cs
, ms
->ms_rts
);
661 ms_trigger(ms
->ms_cs
, ms
->ms_rts
);
665 callout_reset(&ms
->ms_modem_ch
, 2, ms_modem
, ms
);