|
|
1.1 root 1: /* (-lgl
2: * COHERENT Driver Kit Version 1.1.0
3: * Copyright (c) 1982, 1990 by Mark Williams Company.
4: * All rights reserved. May not be copied without permission.
5: -lgl) */
6: /*
7: * Microsoft bus mouse (rodent) driver.
8: */
9:
10: #include <sys/coherent.h>
11: #include <sys/uproc.h>
12: #include <sys/con.h>
13: #include <sys/devices.h>
14: #include <sys/ms.h>
15: #include <errno.h>
16:
17: #define Help(fmt, p) printf(fmt, p)
18: #define Help2(fmt, p, q) printf(fmt, p, q)
19: #define Diag(fmt, p) /* Help(fmt, p) */
20: #define Diag2(fmt, p, q) /* Help2(fmt, p, q) */
21:
22: /*
23: * global patchable definitions
24: */
25: unsigned MSPORT = 0x23C; /* mouse 8255A registers: */
26: /* modified mouse is 0x23C */
27: /* Geac modified mouse is 0x230 */
28: unsigned MSIRQ = 2; /* mouse interrupt # */
29:
30: /*
31: * driver function definitions
32: */
33: int msload();
34: int msunload();
35: int msopen();
36: int msclose();
37: int msioctl();
38: int mspoll();
39: int msintr();
40: int nulldev();
41: int nonedev();
42:
43: /*
44: * configuration table
45: */
46: CON mscon = {
47: DFCHR|DFPOL, /* flags */
48: MS_MAJOR, /* major index */
49: msopen, /* open */
50: msclose, /* close */
51: nonedev, /* block */
52: nonedev, /* read */
53: nonedev, /* write */
54: msioctl, /* ioctl */
55: nulldev, /* power fail */
56: nulldev, /* timeout */
57: msload, /* load */
58: msunload, /* unload */
59: mspoll /* poll */
60: };
61:
62: /*
63: * ioctl function definitions
64: */
65:
66: int ms_setup();
67: int ms_setcrs();
68: int ms_readcrs();
69: int ms_setmick();
70: int ms_readmick();
71: int ms_readbtns();
72: int ms_readstat();
73: int ms_wait();
74:
75: int (*ioctls[])() = {
76: /* 0 1 2 3 4 */
77: ms_setup, ms_setcrs, ms_readcrs, ms_setmick, ms_readmick,
78:
79: /* 5 6 7 */
80: ms_readbtns, ms_readstat, ms_wait
81: };
82:
83: /*
84: * hardware constants
85: */
86: static int porta; /* port A (read/write) */
87: static int portb; /* port B (read/write) */
88: static int portc; /* port C (read/write) */
89: static int portcm; /* control port (write only) */
90:
91: static int u_stts = 0; /* changed-status flags */
92: static int u_mask = 0; /* user condition mask */
93:
94: static event_t ipolls;
95:
96: static struct msparms parms, initparm = {
97: 2, -16, 655, -16, 215, 8, 16
98: };
99:
100: static struct mspos crsr, csav, initcrsr = { 320, 100 };
101:
102: static struct msmick mick, initmick = { 0, 0 };
103:
104: static struct msbuts buttons, initbuttons = {
105: 0,
106: { {0, {320, 100}},
107: {0, {320, 100}},
108: {0, {320, 100}},
109: {0, {320, 100}}
110: }
111: };
112:
113: static int ms_inuse = 0; /* is mouse in use ? */
114:
115: msload()
116: {
117: int s;
118:
119: porta = MSPORT;
120: portb = MSPORT + 1;
121: portc = MSPORT + 2;
122: portcm = MSPORT + 3;
123:
124: s = sphi();
125: outb( portcm, 0x91 ); /* set 8255A mode 9 */
126: outb( portc, 0x10 ); /* disable interrupt */
127: setivec( MSIRQ, msintr ); /* set up irq vector */
128: spl(s);
129:
130: return 0;
131: }
132:
133: /*
134: * Unload function.
135: */
136: msunload()
137: {
138: clrivec( MSIRQ ); /* release irq vector */
139: outb( portcm, 0x91 ); /* set 8255A mode 9 */
140: outb( portc, 0x10 ); /* disable interrupt */
141: }
142:
143: msopen(dev, mode)
144: dev_t dev;
145: {
146: int s;
147:
148: s = sphi(s);
149: if (ms_inuse) {
150: u.u_error = EDBUSY;
151: spl(s);
152: return( -1 );
153: }
154:
155: outb( portcm, 0x91 ); /* set 8255A mode 9 */
156: outb( portb, 0x5a );
157:
158: if( inb( portb ) != 0x5a) { /* hardware installed? */
159: u.u_error = ENXIO;
160: spl(s);
161: return( -1 );
162: }
163:
164: outb( portc, 0x90 );
165: inb( porta );
166: outb( portc, 0xb0 );
167: inb( porta );
168: outb( portc, 0xd0 );
169: inb( porta );
170: outb( portc, 0xf0 );
171: inb( porta );
172: outb( portc, 0 ); /* clear all mouse registers */
173:
174: /* set things */
175: parms = initparm;
176: crsr = csav = initcrsr;
177: mick = initmick;
178: buttons = initbuttons;
179: u_stts = u.u_error = 0;
180: ms_inuse = 1;
181: spl(s);
182:
183: return( 0 );
184: }
185:
186: msclose()
187: {
188: int s;
189:
190: s = sphi();
191: outb( portc, 0x10 ); /* disable interrupt */
192: ms_inuse = u.u_error = 0;
193: spl(s);
194: return( 0 );
195: }
196:
197: msioctl( dev, com, vec )
198: dev_t dev;
199: int com;
200: char *vec;
201: {
202: int s;
203:
204: s = sphi();
205: if (com >= 0 && com < sizeof(ioctls)/sizeof(ioctls[0])) {
206: (*ioctls[com])(vec); /* indirect func call */
207: u.u_error = 0;
208: } else
209: u.u_error = EINVAL;
210: spl(s);
211: if (u.u_error)
212: return( -1 );
213:
214: return( 0 );
215: }
216:
217: /*
218: * Polling routine.
219: * [System V.3 Compatible].
220: */
221: mspoll( dev, ev, msec )
222: dev_t dev;
223: int ev;
224: int msec;
225: {
226: ev &= ~POLLPRI;
227: ev &= ~POLLOUT;
228:
229: /*
230: * No input.
231: */
232: if ( (u_stts & u_mask) == 0 ) {
233: /*
234: * Enable monitor if blocking poll.
235: */
236: if ( msec != 0 )
237: pollopen( &ipolls );
238: /*
239: * Look again to avoid interrupt race.
240: */
241: if ( (u_stts & u_mask) == 0 )
242: ev &= ~POLLIN;
243: }
244:
245: return ev;
246: }
247:
248: /*
249: * write setup structure
250: */
251: ms_setup( newparm )
252: struct msparms *newparm;
253: {
254: ukcopy(newparm, &parms, sizeof(struct msparms));
255: if (parms.h_mpr == 0)
256: parms.h_mpr = 1;
257: if (parms.v_mpr == 0)
258: parms.v_mpr = 1;
259: }
260:
261: /*
262: * write cursor position
263: */
264: ms_setcrs( pos )
265: struct mspos *pos;
266: {
267: ukcopy(pos, &crsr, sizeof(struct mspos));
268: u_stts &= ~MS_S_MOVE; /* clear u_stts pos bit */
269: }
270:
271: /*
272: * read cursor postion
273: */
274: ms_readcrs( pos )
275: struct mspos *pos;
276: {
277: kucopy(&crsr, pos, sizeof(struct mspos));
278: u_stts &= ~MS_S_MOVE; /* clear u_stts pos bit */
279: }
280:
281: /*
282: * write mickey postion
283: */
284: ms_setmick( pos )
285: struct msmick *pos;
286: {
287: ukcopy(pos, &mick, sizeof(struct msmick));
288: }
289:
290: /*
291: * read mickey postion
292: */
293: ms_readmick( pos )
294: struct msmick *pos;
295: {
296: kucopy(&mick, pos, sizeof(struct msmick));
297: }
298:
299: /*
300: * read button status
301: */
302: ms_readbtns( btns )
303: struct msbuts *btns;
304: {
305: kucopy(&buttons, btns, sizeof(struct msbuts));
306: u_stts &= ~MS_S_BUTTONS; /* clear u_stts button bits */
307: }
308:
309: /*
310: * read "changed status" mask
311: */
312: ms_readstat( stat )
313: int *stat;
314: {
315: kucopy(&u_stts, stat, sizeof(int));
316: }
317:
318: /*
319: * wait on "changed status" mask
320: */
321: ms_wait( flag )
322: int *flag;
323: {
324: ukcopy(flag, &u_mask, sizeof(int));
325: while ((u_mask & u_stts) == 0) /* wait until any bit is on */
326: sleep(&u_stts, 0x7fff, 0x7fff, 0);
327: u_mask = 0;
328: }
329:
330: /*
331: * mouse interrupt service routine
332: */
333: msintr()
334: {
335: static int h_fpix = 0; /* fractional pixel */
336: static int v_fpix = 0; /* ditto */
337: int s, n_l, n_h, h_diff, v_diff, tmp, left, right;
338:
339: if (!ms_inuse) /* dev not open - ignore interrupts */
340: return;
341:
342: s = sphi();
343: outb( portc, 0x90 ); /* get horizontal change */
344: n_l = inb( porta );
345: outb( portc, 0xb0 );
346: n_h = inb( porta );
347: h_diff = (char) ((n_l & 0x0f) | (n_h << 4));
348:
349: outb( portc, 0xd0 ); /* get vertical change */
350: n_l = inb( porta );
351: outb( portc, 0xf0 );
352: n_h = inb( porta );
353: v_diff = (char) ((n_l & 0x0f) | (n_h << 4));
354:
355: outb( portc, 0 );
356: left = right = 0; /* set button status */
357: if (!(n_h & 0x80)) left = MS_L_DOWN; /* left button.. */
358: if ((buttons.bbstat & MS_L_DOWN) ^ left) {
359: if (left)
360: button(MS_B_L_PRESS, MS_S_L_PRESS);
361: else
362: button(MS_B_L_RELEASE, MS_S_L_RELEASE);
363: }
364: if (!(n_h & 0x20)) /* right button.. */
365: right = MS_R_DOWN;
366: if ((buttons.bbstat & MS_R_DOWN) ^ right) {
367: if (right)
368: button(MS_B_R_PRESS, MS_S_R_PRESS);
369: else
370: button(MS_B_R_RELEASE, MS_S_R_RELEASE);
371: }
372:
373: buttons.bbstat = left | right; /* set new button status */
374:
375: if (h_diff || v_diff) { /* any motion? */
376: mick.h_mick += h_diff; /* yes - update positions */
377: mick.v_mick += v_diff;
378: if ((abs(h_diff) > parms.accel_t) || (abs(v_diff) > parms.accel_t)) {
379: h_diff *= 2;
380: v_diff *= 2;
381: }
382:
383: if (h_diff) { /* horizontal change */
384: tmp = h_fpix + 8 * h_diff;
385: h_fpix = tmp % parms.h_mpr;
386: tmp = crsr.h_crsr + tmp / parms.h_mpr;
387: crsr.h_crsr = c_range(tmp, parms.h_cmin, parms.h_cmax);
388: }
389:
390: if (v_diff) { /* vertical change */
391: tmp = v_fpix + 8 * v_diff;
392: v_fpix = tmp % parms.v_mpr;
393: tmp = crsr.v_crsr + tmp / parms.v_mpr;
394: crsr.v_crsr = c_range(tmp, parms.v_cmin, parms.v_cmax);
395: }
396:
397: if ((crsr.h_crsr != csav.h_crsr) || (crsr.v_crsr != csav.v_crsr)) {
398: u_stts |= MS_S_MOVE;
399: csav = crsr;
400: }
401: }
402:
403: if (u_stts & u_mask) {
404: wakeup(&u_stts);
405: if ( ipolls.e_procp )
406: pollwake( &ipolls );
407: }
408:
409: spl(s);
410: }
411:
412: /*
413: * update button-press/release data
414: */
415: button( bp, sbit )
416: int bp;
417: unsigned sbit;
418: {
419: ++buttons.buts[bp].cnt;
420: buttons.buts[bp].bpos = crsr;
421: u_stts |= sbit;
422: }
423:
424: /*
425: * force return value to be within specified range
426: */
427: c_range(c, cmin, cmax)
428: int c, cmin, cmax;
429: {
430: if( c < cmin )
431: c = cmin;
432: else if( c > cmax )
433: c = cmax;
434: return( c );
435: }
436:
437: abs(i)
438: int i;
439: {
440: if (i < 0)
441: return (-i);
442: return i;
443: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.