xref: /original-bsd/sys/news3400/hbdev/ms.c (revision ac773626)
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.4 (Berkeley) 03/09/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 
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
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 *
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 *
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 
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  */
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*/
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 
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 
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*/
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 
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 
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 
451 mssint()
452 {
453 	printf("mssint\n");
454 }
455 
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  */
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  */
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 
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  */
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