xref: /original-bsd/sys/news3400/hbdev/ms.c (revision b9df2d9d)
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) 06/04/92
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 
46 struct ms_stat	 ms_stat[NMS];
47 
48 int	msprobe(), msattach();
49 
50 struct hb_device   *msinfo[NMS];
51 struct hb_driver   msdriver = {
52 	msprobe, 0, msattach, 0, 0, "ms", msinfo, "mc", 0, 0
53 };
54 
55 #ifndef news700
56 extern 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*/
70 msprobe(ii)
71 	struct hb_device *ii;
72 {
73 	return(sizeof(struct ms_stat));
74 }
75 
76 /*ARGSUSED*/
77 msattach(ii)
78 	struct hb_device *ii;
79 {
80 
81 }
82 
83 /* queue structure operators */
84 
85 msq_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 
93 int
94 msq_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 
107 struct ms_event *
108 msq_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 
125 struct ms_event *
126 msq_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 
140 msq_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  */
158 msopen(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*/
215 msclose(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 
250 msread(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 
314 mswrite(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*/
350 msioctl(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 
416 msselect(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);
448 win:
449 	splx(s);
450 	return(1);
451 }
452 
453 msselwakeup(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 
465 mssint()
466 {
467 	printf("mssint\n");
468 }
469 
470 msputevent(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  */
500 mskeytrigger(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  */
522 msconv(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 
594 mscheckevent(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 */
660