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