1 /*
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc.
7 *
8 * %sccs.include.redist.c%
9 *
10 * from: $Hdr: ms.c,v 4.300 91/06/09 06:22:04 root Rel41 $ SONY
11 *
12 * @(#)ms.c 8.1 (Berkeley) 06/11/93
13 */
14
15 #include "ms.h"
16 #if NMS > 0
17 /*
18 * mouse
19 */
20
21 #include <sys/types.h>
22 #include <machine/cpu.h>
23 #include <machine/pte.h>
24 #include <sys/param.h>
25 #include <sys/proc.h>
26 #include <sys/user.h>
27 #include <sys/buf.h>
28 #include <sys/malloc.h>
29 #include <sys/systm.h>
30 #include <sys/uio.h>
31 #include <sys/kernel.h>
32 #include <sys/file.h>
33
34 #include <news3400/iop/mouse.h>
35 #include <news3400/iop/msreg.h>
36
37 #include <news3400/sio/scc.h>
38 #include <news3400/hbdev/hbvar.h>
39
40 #ifndef mips
41 #define volatile
42 #endif
43
44 struct ms_stat ms_stat[NMS];
45
46 int msprobe(), msattach();
47
48 struct hb_device *msinfo[NMS];
49 struct hb_driver msdriver = {
50 msprobe, 0, msattach, 0, 0, "ms", msinfo, "mc", 0, 0
51 };
52
53 extern int tty00_is_console;
54
55 #ifdef news3400
56 #define splms spl4
57 #else
58 #define splms spl5
59 #endif
60
61 /*ARGSUSED*/
62 msprobe(ii)
63 struct hb_device *ii;
64 {
65 return(sizeof(struct ms_stat));
66 }
67
68 /*ARGSUSED*/
69 msattach(ii)
70 struct hb_device *ii;
71 {
72
73 }
74
75 /* queue structure operators */
76
msq_init(unit)77 msq_init(unit)
78 int unit;
79 {
80 register volatile struct ms_queue *q = ms_stat[unit].mss_queue;
81
82 q->mq_head = q->mq_tail = 0;
83 }
84
85 int
msq_stat(unit)86 msq_stat(unit)
87 int unit;
88 {
89 register volatile struct ms_queue *q = ms_stat[unit].mss_queue;
90
91 while (q->mq_head != q->mq_tail) {
92 if (!q->mq_queue[q->mq_head].mse_inval)
93 break;
94 q->mq_head = ++q->mq_head % MS_MAXREPORT;
95 }
96 return (q->mq_head != q->mq_tail);
97 }
98
99 struct ms_event *
msq_read(unit)100 msq_read(unit)
101 int unit;
102 {
103 register volatile struct ms_queue *q = ms_stat[unit].mss_queue;
104 register struct ms_event *data;
105
106 while (q->mq_head != q->mq_tail && q->mq_queue[q->mq_head].mse_inval)
107 q->mq_head = ++q->mq_head % MS_MAXREPORT;
108 if (q->mq_head == q->mq_tail) {
109 data = NULL;
110 } else {
111 data = q->mq_queue + q->mq_head++;
112 q->mq_head %= MS_MAXREPORT;
113 }
114 return (data);
115 }
116
117 struct ms_event *
msq_write(unit)118 msq_write(unit)
119 int unit;
120 {
121 register volatile struct ms_queue *q = ms_stat[unit].mss_queue;
122 register struct ms_event *data = q->mq_queue + q->mq_tail;
123 register int new;
124
125 /* if queue is full, newest data is gone away */
126 new = (q->mq_tail + 1) % MS_MAXREPORT;
127 if (new != q->mq_head)
128 q->mq_tail = new;
129 return (data);
130 }
131
msq_flush(unit,trig)132 msq_flush(unit, trig)
133 int unit;
134 char trig;
135 {
136 register volatile struct ms_queue *q = ms_stat[unit].mss_queue;
137 register int i;
138
139 i = q->mq_head;
140 while (i != q->mq_tail) {
141 if (q->mq_queue[i].mse_trig == trig)
142 q->mq_queue[i].mse_inval = -1;
143 i = ++i % MS_MAXREPORT;
144 }
145 }
146
147 /*
148 * Mouse open function.
149 */
msopen(dev,flag)150 msopen(dev, flag)
151 dev_t dev;
152 int flag;
153 {
154 register int unit = MSUNIT(dev);
155 register struct ms_stat *ms = &ms_stat[unit];
156 register struct hb_device *ii = msinfo[unit];
157 static struct ms_coord initxy = { 0, 0 };
158
159 /* check device */
160 if (unit < 0 || unit >= NMS || ii == NULL || ii->hi_alive == 0)
161 return(ENXIO);
162
163 /* check duplicable open */
164 if (ms->mss_stat & MS_ACTIVE)
165 return(EBUSY);
166
167 ms->mss_queue = malloc(sizeof(struct ms_queue), M_DEVBUF, M_WAITOK);
168 if (ms->mss_queue == NULL)
169 return (ENOMEM);
170 msq_init(unit);
171 ms->mss_mode = flag;
172 ms->mss_stat = MS_ACTIVE;
173
174 /* communicate to IOP .. clear event mask, set initial xy. */
175 ms->mss_eventmask = 0;
176 ms->mss_data.md_sw = 0; /* XXX */
177 ms->mss_data.md_x = 0;
178 ms->mss_data.md_y = 0;
179 ms->mss_param.mp_delta = 5;
180 ms->mss_param.mp_mag = 3;
181 ms->mss_range.mr_min.mc_x = 0x80000000;
182 ms->mss_range.mr_min.mc_y = 0x80000000;
183 ms->mss_range.mr_max.mc_x = 0x7fffffff;
184 ms->mss_range.mr_max.mc_y = 0x7fffffff;
185
186 if (curproc->p_pgrp->pg_id == 0) {
187 if (ms->mss_pgrp == 0)
188 ms->mss_pgrp = curproc->p_pid;
189 curproc->p_pgrp->pg_id = ms->mss_pgrp;
190 }
191 if (tty00_is_console)
192 kbm_open(SCC_KEYBOARD);
193 kbm_open(SCC_MOUSE);
194
195 return (0);
196 }
197
198 /*
199 * Mouse close function.
200 */
201
202 /*ARGSUSED*/
msclose(dev,flag)203 msclose(dev, flag)
204 dev_t dev;
205 int flag;
206 {
207 int unit = MSUNIT(dev);
208 register struct ms_stat *ms = &ms_stat[unit];
209 register struct hb_device *ii = msinfo[unit];
210
211 /* check unit no. */
212 if (unit < 0 || unit >= NMS || ii == NULL || ii->hi_alive == 0)
213 return ENXIO;
214
215 /* check status */
216 if (!(ms->mss_stat & MS_ACTIVE))
217 return ENXIO;
218
219 /* clear eventmask and status */
220 ms->mss_stat = 0;
221 ms->mss_eventmask = 0;
222
223 free(ms->mss_queue, M_DEVBUF);
224 ms->mss_pgrp = 0;
225 if (tty00_is_console)
226 kbm_close(SCC_KEYBOARD);
227 kbm_close(SCC_MOUSE);
228
229 return (0);
230 }
231
232 /*
233 * Mouse read function.
234 */
235
msread(dev,uio,flag)236 msread(dev, uio, flag)
237 dev_t dev;
238 struct uio *uio;
239 int flag;
240 {
241 register int unit = MSUNIT(dev);
242 register struct ms_stat *ms = &ms_stat[unit];
243 register struct hb_device *ii = msinfo[unit];
244 register volatile struct ms_event *data;
245 struct ms_data xy;
246 int s, error;
247
248 /* check argument */
249 if (unit < 0 || unit >= NMS || ii == NULL || ii->hi_alive == 0)
250 return ENXIO;
251
252 /* event mode -> waiting */
253 if (ms->mss_eventmask & MS_EMEVENT) {
254 s = splms();
255 if (msq_stat(unit) == 0 && (ms->mss_stat & MS_NBIO)) {
256 splx(s);
257 return (EWOULDBLOCK);
258 }
259 while (msq_stat(unit) == 0) {
260 ms->mss_stat |= MS_EVWAIT;
261 sleep((caddr_t)&ms->mss_queue, MSPRI);
262 ms->mss_stat &= ~MS_EVWAIT;
263 }
264 splx(s);
265 if(MSOLDIF(dev)) {
266 while ((data = msq_read(unit)) != NULL &&
267 uio->uio_resid >= sizeof(struct ms_data)) {
268 error = uiomove((caddr_t)&data->mse_data,
269 sizeof(struct ms_data), uio);
270 if (error)
271 return error;
272 }
273 } else {
274 while ((data = msq_read(unit)) != NULL &&
275 uio->uio_resid >= sizeof(struct ms_event)) {
276 error = uiomove((caddr_t)data,
277 sizeof(struct ms_event), uio);
278 if (error)
279 return error;
280 }
281 }
282 } else {
283 while (uio->uio_resid >= sizeof(struct ms_data)) {
284 s = splms();
285 xy = ms->mss_data;
286 splx(s);
287 error = uiomove((caddr_t)&xy,
288 sizeof(struct ms_data), uio);
289 if (error)
290 return error;
291 }
292 }
293 return 0;
294 }
295
296 /*
297 * Mouse write function
298 */
299
mswrite(dev,uio,flag)300 mswrite(dev, uio, flag)
301 dev_t dev;
302 struct uio *uio;
303 int flag;
304 {
305 register int unit = MSUNIT(dev);
306 register struct ms_stat *ms = &ms_stat[unit];
307 register struct hb_device *ii = msinfo[unit];
308 struct ms_coord xy;
309 register int s, error;
310
311 /* check argument */
312 if (unit < 0 || unit >= NMS || ii == NULL || ii->hi_alive == 0)
313 return ENXIO;
314
315 while (uio->uio_resid >= sizeof(struct ms_coord)) {
316 error = uiomove((caddr_t)&xy, sizeof(xy), uio);
317 if (error)
318 return error;
319 s = splms();
320 ms->mss_data.md_x = xy.mc_x;
321 ms->mss_data.md_y = xy.mc_y;
322 splx(s);
323 lock_bitmap();
324 updateCursor(&ms->mss_data.md_x, &ms->mss_data.md_y, 1);
325 unlock_bitmap();
326 }
327 return 0;
328 }
329
330
331 /*
332 * Mouse I/O control function
333 */
334
335 /*ARGSUSED*/
msioctl(dev,cmd,data,flag)336 msioctl(dev, cmd, data, flag)
337 dev_t dev;
338 int cmd;
339 caddr_t data;
340 int flag;
341 {
342 register int unit = MSUNIT(dev);
343 register struct ms_stat *ms = &ms_stat[unit];
344 register struct hb_device *ii = msinfo[unit];
345 register int s;
346
347 if (unit < 0 || unit >= NMS || ii == NULL || ii->hi_alive == 0)
348 return EIO;
349
350 s = splms();
351
352 switch (cmd) {
353 case MSIOCGETEM:
354 (*(int*)data) = ms->mss_eventmask;
355 break;
356 case MSIOCSETEM:
357 ms->mss_eventmask = *(int *)data;
358 break;
359 case MSIOCSETXY:
360 ms->mss_data.md_x = ((struct ms_coord*)data)->mc_x;
361 ms->mss_data.md_y = ((struct ms_coord*)data)->mc_y;
362 lock_bitmap();
363 updateCursor(&ms->mss_data.md_x, &ms->mss_data.md_y, 1);
364 unlock_bitmap();
365 msq_flush(unit, MSE_MOTION);
366 break;
367 case MSIOCFLUSH:
368 msq_init(unit);
369 break;
370 case MSIOCSETPARAM:
371 ms->mss_param = *(struct ms_param*)data;
372 break;
373 case MSIOCSETRANGE:
374 ms->mss_range = *(struct ms_range*)data;
375 break;
376 case FIONBIO:
377 if (*(int *)data)
378 ms->mss_stat |= MS_NBIO;
379 else
380 ms->mss_stat &= ~MS_NBIO;
381 break;
382 case FIOASYNC:
383 if (*(int *)data)
384 ms->mss_stat |= MS_ASYNC;
385 else
386 ms->mss_stat &= ~MS_ASYNC;
387 break;
388 case TIOCSPGRP:
389 ms->mss_pgrp = *(int *)data;
390 break;
391 case TIOCGPGRP:
392 *(int *)data = ms->mss_pgrp;
393 break;
394 default:
395 splx(s);
396 return ENOTTY;
397 }
398 splx(s);
399 return 0;
400 }
401
msselect(dev,flag)402 msselect(dev, flag)
403 dev_t dev;
404 int flag;
405 {
406 register int unit = MSUNIT(dev);
407 register struct ms_stat *ms;
408 int s;
409
410 if (unit < 0 || unit >= NMS)
411 return(0);
412
413 s = splms();
414 ms = &ms_stat[unit];
415
416 switch(flag) {
417 case FREAD:
418 if (!(ms->mss_eventmask & MS_EMEVENT))
419 goto win;
420 if(msq_stat(unit))
421 goto win;
422
423 if (ms->mss_rsel && ms->mss_rsel->p_wchan == (caddr_t)&selwait)
424 ms->mss_stat |= MS_RCOLL;
425 else
426 ms->mss_rsel = curproc;
427 break;
428
429 case FWRITE:
430 goto win;
431 }
432 splx(s);
433 return(0);
434 win:
435 splx(s);
436 return(1);
437 }
438
msselwakeup(ms)439 msselwakeup(ms)
440 register struct ms_stat *ms;
441 {
442 if (ms->mss_rsel) {
443 selwakeup(ms->mss_rsel, ms->mss_stat&MS_RCOLL);
444 ms->mss_stat &= ~MS_RCOLL;
445 ms->mss_rsel = 0;
446 }
447 if (ms->mss_stat & MS_ASYNC)
448 gsignal(ms->mss_pgrp, SIGIO);
449 }
450
mssint()451 mssint()
452 {
453 printf("mssint\n");
454 }
455
msputevent(unit,trig,dir,code)456 msputevent(unit, trig, dir, code)
457 int unit, trig, dir, code;
458 {
459 register struct ms_stat *ms = &ms_stat[unit];
460 register volatile struct ms_event *me;
461 register int s;
462
463 me = msq_write(unit);
464
465 s = splclock();
466 me->mse_time = time;
467 me->mse_inval = 0;
468 splx(s);
469
470 me->mse_trig = trig;
471 me->mse_dir = dir;
472 me->mse_code = code;
473 me->mse_data = ms->mss_data;
474
475 if (ms->mss_stat & MS_EVWAIT)
476 wakeup((caddr_t)&ms->mss_queue);
477
478 msselwakeup(ms);
479
480 return (0);
481 }
482
483 /*
484 * for keyboard
485 */
mskeytrigger(unit,up,keycode)486 mskeytrigger(unit, up, keycode)
487 int unit;
488 int up;
489 int keycode;
490 {
491 register struct ms_stat *ms = &ms_stat[unit];
492
493 if((ms->mss_eventmask & MS_EMEVENT) == 0)
494 return 0;
495 if((ms->mss_eventmask & MS_EMKEY) == 0)
496 return 0;
497
498 (void) msputevent(unit, MSE_KEY, up ? MSE_UP : MSE_DOWN, keycode);
499
500 return 1;
501 }
502
503 /*
504 * msconv - convert mouse hardware reports(3 bytes) into internal mouse data
505 * it leaves the old mouse data in ms_data_old and
506 * new mouse data in ms_data.
507 */
msconv(unit,rep)508 msconv(unit, rep)
509 int unit;
510 register char rep[];
511 {
512 register struct ms_stat *ms = &ms_stat[unit];
513 register int s_byte;
514 register int sw = 0;
515 register int dx, dy;
516 int adx, ady;
517
518 ms->mss_data_old = ms->mss_data;
519
520 /* switch status */
521 s_byte = rep[MS_S_BYTE];
522 if (s_byte & MS_S_SW1)
523 sw |= MS_BUTNL;
524 if (s_byte & MS_S_SW2)
525 sw |= MS_BUTNR;
526 if (s_byte & MS_S_SW3)
527 sw |= MS_BUTNM;
528 ms->mss_data.md_sw = sw;
529
530 /* delta x */
531 dx = rep[MS_X_BYTE] & MS_X_X06;
532 if (s_byte & MS_S_X7)
533 dx = (~0&~MS_X_X06)|dx;
534
535 dy = rep[MS_Y_BYTE] & MS_Y_Y06;
536 if (s_byte & MS_S_Y7)
537 dy = (~0&~MS_Y_Y06)|dy;
538
539 #define ABS(x) ((x)>=0 ? (x) : -(x))
540 adx = ABS(dx);
541 ady = ABS(dy);
542 #undef ABS
543
544 if (adx > ms->mss_param.mp_delta) {
545 adx = ms->mss_param.mp_delta +
546 (adx - ms->mss_param.mp_delta) * ms->mss_param.mp_mag;
547 if (dx < 0)
548 dx = -adx;
549 else
550 dx = adx;
551 }
552 if (ady > ms->mss_param.mp_delta) {
553 ady = ms->mss_param.mp_delta +
554 (ady - ms->mss_param.mp_delta) * ms->mss_param.mp_mag;
555 if (dy < 0)
556 dy = -ady;
557 else
558 dy = ady;
559 }
560 ms->mss_data.md_x += dx;
561 ms->mss_data.md_y += dy;
562
563 if (dx > 0)
564 ms->mss_data.md_x = min(ms->mss_data.md_x,
565 ms->mss_range.mr_max.mc_x);
566 else
567 ms->mss_data.md_x = max(ms->mss_data.md_x,
568 ms->mss_range.mr_min.mc_x);
569 if (dy > 0)
570 ms->mss_data.md_y = min(ms->mss_data.md_y,
571 ms->mss_range.mr_max.mc_y);
572 else
573 ms->mss_data.md_y = max(ms->mss_data.md_y,
574 ms->mss_range.mr_min.mc_y);
575
576 if (dx != 0 || dy != 0)
577 updateCursor(&ms->mss_data.md_x, &ms->mss_data.md_y, 0);
578 }
579
mscheckevent(unit)580 mscheckevent(unit)
581 int unit;
582 {
583 register struct ms_stat *ms = &ms_stat[unit];
584 register int i;
585 register int changebits;
586 register int dir;
587
588 if ((ms->mss_eventmask & MS_EMEVENT) == 0)
589 return;
590
591 if (ms->mss_data_old.md_sw != ms->mss_data.md_sw) {
592
593 changebits = (ms->mss_data_old.md_sw ^ ms->mss_data.md_sw);
594 changebits &= ms->mss_eventmask;
595
596 for(i = 0; i < 3; i++) {
597 if(changebits & (1 << i)) {
598 if((1 << i) & ms->mss_data.md_sw)
599 dir = MSE_DOWN;
600 else
601 dir = MSE_UP;
602 msputevent(unit, MSE_BUTTON, dir, i);
603 }
604 }
605 }
606
607 if ((ms->mss_eventmask & MS_EMMOTION) &&
608 (ms->mss_data_old.md_x != ms->mss_data.md_x ||
609 ms->mss_data_old.md_y != ms->mss_data.md_y)) {
610 msputevent(unit, MSE_MOTION, 0, 0);
611 return;
612 }
613 }
614
615 /*
616 * _ms_helper - open the mouse line and read mouse data and
617 * convert them into mouse data (events)
618 */
_ms_helper(unit)619 _ms_helper(unit)
620 int unit;
621 {
622 register int c;
623 static int counter = 0;
624 static char buf[MS_DB_SIZE];
625
626 #ifdef notyet /* KU:XXX */
627 intrcnt[INTR_MOUSE]++;
628 #endif
629
630 #if NBM > 0
631 rst_dimmer_cnt();
632 #endif
633
634 while ((c = xgetc(SCC_MOUSE)) >= 0) {
635 if (c & MS_S_MARK)
636 counter = 0;
637 buf[counter] = c;
638 if (++counter == 3) {
639 msconv(unit, buf);
640 mscheckevent(unit);
641 counter = 0;
642 }
643 }
644 }
645 #endif /* NMS > 0 */
646