|
|
1.1 root 1: /* @(#)vs.c 7.7 (MIT) 6/21/90 */
2: /****************************************************************************
3: * *
4: * Copyright (c) 1983, 1984 by *
5: * DIGITAL EQUIPMENT CORPORATION, Maynard, Massachusetts. *
6: * All rights reserved. *
7: * *
8: * This software is furnished on an as-is basis and may be used and copied *
9: * only with inclusion of the above copyright notice. This software or any *
10: * other copies thereof may be provided or otherwise made available to *
11: * others only for non-commercial purposes. No title to or ownership of *
12: * the software is hereby transferred. *
13: * *
14: * The information in this software is subject to change without notice *
15: * and should not be construed as a commitment by DIGITAL EQUIPMENT *
16: * CORPORATION. *
17: * *
18: * DIGITAL assumes no responsibility for the use or reliability of its *
19: * software on equipment which is not supplied by DIGITAL. *
20: * *
21: * *
22: ****************************************************************************/
23:
24: #include "vs.h"
25: #if NVS > 0
26:
27: #include "machine/pte.h"
28:
29: #include "param.h"
30: #include "user.h"
31: #include "buf.h"
32: #include "systm.h"
33: #include "map.h"
34: #include "kernel.h"
35: #include "ioctl.h"
36:
37: #include "vsio.h"
38:
39: #include "proc.h"
40: #include "uio.h"
41: #include "vmmac.h"
42: #include "file.h"
43:
44: #include "ubareg.h"
45: #include "ubavar.h"
46: #include "vsreg.h"
47:
48: #include "../vax/mtpr.h"
49:
50: #define VSWAITPRI (PZERO+1)
51: #define VSMAXEVQ 64 /* must be power of 2 */
52: #define EVROUND(x) ((x) & (VSMAXEVQ - 1))
53:
54:
55: #define VSBUFFSIZE 3072
56: struct vsBuffArea {
57: vsIoAddr vsioa;
58: char obuff[VSBUFFSIZE];
59: vsEvent ibuff[VSMAXEVQ];
60: };
61: struct vsBuffArea vsBuff[NVS];
62:
63:
64: int vsprobe(), vsattach();
65: struct uba_device *vsdinfo[NVS];
66: u_short vsstd[] = { 0 };
67: struct uba_driver vsdriver =
68: { vsprobe, 0, vsattach, 0, vsstd, "vs", vsdinfo, 0, 0 };
69:
70: #define VSUNIT(dev) (minor(dev))
71:
72: struct vs_softc {
73: unsigned inited : 1; /* has this ever been inited? */
74: unsigned open : 1; /* only one open, please */
75: unsigned linkAvail : 1; /* link is up */
76: short pgrp; /* process group for SIGHUP */
77: int romVersion; /* rom version */
78: struct vs_fparm offset; /* address base */
79: struct vs_csr csr; /* saved csr0 */
80: struct vs_intr irr; /* saved interrupt reason */
81: struct vs_kbd krr; /* saved keyboard */
82: struct vs_fparm pr; /* saved parameter regs */
83: struct proc *rsel; /* process waiting for select */
84: struct vs_fparm vs_nextgo; /* next packet to go */
85: short vs_status; /* status from previous packet */
86: vsStats stats; /* statistics */
87: int vsBuff_ubinfo; /* ubinfo for vsBuff */
88: }vs_softc[NVS];
89:
90: #define TRUE 1
91: #define FALSE 0
92:
93: #define printI if (vsIntrPrintfs)printf
94: #define printD if (vsDebugPrintfs)printf
95: #define printM if (vsMlpPrintfs) vsMlpPrintfs--,printf
96: int vsIntrPrintfs = 0;
97: int vsDebugPrintfs = 0;
98: int vsMlpPrintfs = 0;
99:
100: /*
101: * Tell the system that it's out there, and set up the device's interrupt
102: * vector. Since we are supporting vs100s and vs125s,
103: * this is a bit kludgey. The vs100 works much
104: * as one expects, but the vs125 tries to set all the fiber link
105: * related bits when you hit VS_IE, ignoring the way the 100 works.
106: * Also, the vs100 will let you set the interrupt vector, but
107: * the vs125 ignores this and uses its hard-wired value.
108: * And there's no sure fire to tell which variant it is.
109: * Ugh. Ugh. Ugh.
110: */
111:
112: vsprobe(reg)
113: caddr_t reg;
114: {
115: register int br, cvec; /* value-result */
116: register struct vsdevice *vsaddr = (struct vsdevice *)reg;
117:
118: #ifdef lint
119: br = 0; cvec = br; br = cvec;
120: vsintr(0);
121: #endif
122: br = 0x15;
123: cvec = (uba_hd[numuba].uh_lastiv -= 4*8);
124: /*
125: * uh_lastiv is the last free interrupt vector in the
126: * unibus addapter header (uba_hd).
127: */
128:
129: vsaddr->vs_csr0 = cvec >> 2; /* Save the vector for use on next device */
130: vsaddr->vs_irr = 0; /* Csr will only be read if irr == 0 */
131: vsaddr->vs_irr = 0; /* Clear interrupt reason register */
132: vsaddr->vs_pr1 = 0; /* Clear function parameter */
133: vsaddr->vs_pr2 = 0; /* Clear function parameter */
134: vsaddr->vs_ivr = cvec; /* set up vector (no-op for vs125) */
135:
136: DELAY(100000);
137: if (vsaddr->vs_csr0 & VS_LNK_AVL)
138: return(0); /* light won't go off! */
139: vsaddr->vs_csr0 &= ~VS_LNK_TRNS;
140: vsaddr->vs_csr0 |= VS_IE; /* enable interrupts */
141: DELAY(200000);
142:
143: return sizeof(struct vsdevice);
144: }
145:
146: vsattach(uip)
147: struct uba_device *uip;
148: {
149: register struct vs_softc *vsp;
150: register struct vsdevice *vsaddr;
151:
152: vsp = &vs_softc[VSUNIT(uip->ui_unit)];
153: vsp->inited = FALSE;
154: vsp->open = FALSE;
155: vsBuff[VSUNIT(uip->ui_unit)].vsioa.mbox.bottom = 0;
156: vsp->linkAvail = FALSE;
157: vsp->romVersion = 0;
158: vsp->vs_nextgo.fparm_all = NULL;
159:
160: vsaddr = (struct vsdevice *) uip->ui_addr;
161: vsaddr->vs_csr0 |= (VS_IE | VS_XMIT_ON);
162: }
163:
164: vsopen(dev, flag)
165: dev_t dev;
166: int flag;
167: {
168: register struct vs_softc *vsp;
169: register struct uba_device *uip;
170: register struct vsdevice *vsaddr;
171: int s;
172: int ret;
173: struct buf vsbuf;
174: struct vsBuffArea *vsb;
175: caddr_t vsBuffpage;
176: int vsBuffnpages;
177:
178: if (VSUNIT(dev) >= NVS || (vsp = &vs_softc[VSUNIT(dev)])->open ||
179: (uip = vsdinfo[VSUNIT(dev)]) == 0 || uip->ui_alive == 0)
180: return (ENXIO);
181:
182: vsaddr = (struct vsdevice *) uip->ui_addr;
183: vsb = &vsBuff[VSUNIT(dev)];
184: printM("vsopen csr0=%x, csr1=%x, csr2=%x, csr3=%x, csr4=%x, csr5=%x, csr6=%x, csr7=%x\n",
185: vsaddr->vs_csr0, vsaddr->vs_csr1, vsaddr->vs_csr2, vsaddr->vs_csr3,
186: vsaddr->vs_csr4, vsaddr->vs_csr5, vsaddr->vs_csr6, vsaddr->vs_csr7);
187:
188: /*
189: * Finally! We can now set up the device.
190: */
191:
192: if (!vsp->inited && !(flag & FNDELAY)) {
193: ret = vsInitDev(dev, TRUE);
194: if (ret)
195: return (ret);
196: if (ret = vsError(vsp))
197: return(ret);
198: }
199:
200: vsp->open = TRUE; /* we're open */
201: vsp->pgrp = u.u_procp->p_pgrp;
202:
203: /* reset statistics */
204: bzero((caddr_t) &vsp->stats, sizeof(vsStats));
205:
206: /* initialize user I/O addresses */
207: vsb->vsioa.ioreg = (short *)vsaddr;
208: vsb->vsioa.status = 0;
209: vsb->vsioa.obuff = vsb->obuff;
210: vsb->vsioa.obufflen = VSBUFFSIZE;
211: vsb->vsioa.ibuff = vsb->ibuff;
212: vsb->vsioa.ihead = 0;
213: vsb->vsioa.itail = 0;
214: vsb->vsioa.iqsize = VSMAXEVQ;
215: /* map io regs into user address space (assume they don't cross a page) */
216: maptouser(vsaddr);
217: /* map vsBuff into user address space */
218: vsBuffpage = (caddr_t)((int)vsb & ~PGOFSET);
219: vsBuffnpages = (((int)vsb & PGOFSET) +
220: (NBPG-1) + sizeof(struct vsBuffArea)) >> PGSHIFT;
221: while (vsBuffnpages>0) {
222: maptouser(vsBuffpage);
223: vsBuffpage += NBPG;
224: vsBuffnpages--;
225: }
226: /* lock in the buffer */
227: vsbuf.b_error = 0;
228: vsbuf.b_proc = u.u_procp;
229: vsbuf.b_un.b_addr = vsb->obuff;
230: vsbuf.b_flags = B_BUSY;
231: vsbuf.b_bcount = VSBUFFSIZE;
232: vsp->vsBuff_ubinfo = ubasetup(uip->ui_ubanum, &vsbuf, UBA_CANTWAIT);
233:
234: vsb->vsioa.reloc = (int) (vsp->offset.fparm_all
235: + UBAI_ADDR(vsp->vsBuff_ubinfo));
236: return(0);
237: }
238:
239: vsclose(dev)
240: dev_t dev;
241: {
242: register struct uba_device *uip = vsdinfo[VSUNIT(dev)];
243: register struct vs_softc *vsp = &vs_softc[VSUNIT(dev)];
244: int s, i;
245: struct vsdevice *vsaddr;
246: struct vsBuffArea *vsb;
247: caddr_t vsBuffpage;
248: int vsBuffnpages;
249:
250: vsaddr = (struct vsdevice *) uip->ui_addr;
251: printM("vsclose csr0=%x, csr1=%x, csr2=%x, csr3=%x, csr4=%x, csr5=%x, csr6=%x, csr7=%x\n",
252: vsaddr->vs_csr0, vsaddr->vs_csr1, vsaddr->vs_csr2, vsaddr->vs_csr3,
253: vsaddr->vs_csr4, vsaddr->vs_csr5, vsaddr->vs_csr6, vsaddr->vs_csr7);
254: vsb = &vsBuff[VSUNIT(dev)];
255: if (vsDebugPrintfs) {
256: printf("vs%d: %d errors, %d unsolicited interrupts",
257: VSUNIT(dev), vsp->stats.errors, vsp->stats.unsolIntr);
258: printf(", %d link errors", vsp->stats.linkErrors);
259: printf(", %d overruns", vsp->stats.overruns);
260: printf(", csr0 %x, csr1 %x", vsaddr->vs_csr0, vsaddr->vs_csr1);
261: printf("\n");
262: }
263:
264: vsp->open = FALSE;
265: vsp->inited = FALSE; /* init on every open */
266: vsp->vs_nextgo.fparm_all = NULL;
267: vsb->vsioa.mbox.bottom = 0;
268: /* release the buffer */
269: if (vsp->vsBuff_ubinfo!=0) {
270: ubarelse(uip->ui_ubanum, &vsp->vsBuff_ubinfo);
271: }
272:
273: #ifdef notdef
274: /* unmap io regs into user address space (assume they don't cross a page) */
275: unmaptouser(vsaddr);
276: /* unmap vsBuff into user address space */
277: vsBuffpage = (caddr_t)((int)vsb & ~PGOFSET);
278: vsBuffnpages = (((int)vsb&PGOFSET) +
279: (NBPG-1)+ sizeof(struct vsBuffArea)) >> PGSHIFT;
280: while (vsBuffnpages>0) {
281: unmaptouser(vsBuffpage);
282: vsBuffpage += NBPG;
283: vsBuffnpages--;
284: }
285: #endif
286: return (0);
287: }
288:
289: vsread(dev,uio)
290: dev_t dev;
291: struct uio *uio;
292: {
293: return(-1);
294: }
295:
296: vswrite(dev, uio)
297: dev_t dev;
298: struct uio *uio;
299: {
300: return(-1);
301: }
302:
303: /*ARGSUSED*/
304: vsioctl(dev, cmd, addr, flag)
305: dev_t dev;
306: register caddr_t addr;
307: {
308: register struct uba_device *uip = vsdinfo[VSUNIT(dev)];
309: register struct vs_softc *vsp = &vs_softc[VSUNIT(dev)];
310: register struct vsdevice *vsaddr = (struct vsdevice *) uip->ui_addr;
311: register struct vsBuffArea *vsb = &vsBuff[VSUNIT(dev)];
312: struct vs_fparm vsAddr;
313: int s, error = 0;
314: int func;
315: int ret;
316:
317: switch(cmd) { /* things that don't need the device */
318: case VSIOWAITGO:
319: /* wait for user I/O operation to complete, then go */
320: s = spl5();
321: if ((ret = vsb->vsioa.status) == 0) {
322: vsp->vs_nextgo.fparm_all = ((struct vs_fparm *) addr)->fparm_all;
323: do {
324: error = tsleep((caddr_t)vsp, VSWAITPRI | PCATCH,
325: devwait, 0);
326: } while (vsp->vs_nextgo.fparm_all && error == 0);
327: ret = vsp->vs_status;
328: } else {
329: vsaddr->vs_pr1 = ((struct vs_fparm *)addr)->fparm_low;
330: vsaddr->vs_pr2 = ((struct vs_fparm *)addr)->fparm_high;
331: vsb->vsioa.status = 0;
332: vsaddr->vs_csr0 &= ~VS_FCN; /* clear bits */
333: vsaddr->vs_csr0 |= (VS_IE | (VS_SEND << VS_FCSHIFT) | VS_GO);
334: }
335: splx(s);
336: if (error)
337: return (error);
338: if (ret & VS_ERROR)
339: return ((ret & VS_REASON) + 128);
340: return(0);
341:
342: case VSIOUSERWAIT:
343: /* wait for user I/O operation to complete */
344: s = spl5();
345: while (vsb->vsioa.status == 0) {
346: error = tsleep((caddr_t) vsp, VSWAITPRI | PCATCH,
347: devio, 0);
348: }
349: splx(s);
350: return (error);
351:
352: case VSIOGETVER: /* get ROM version */
353: if (!vsp->inited)
354: return(ENODEV);
355: *(int *) addr = vsp->romVersion;
356: return(0);
357:
358: case VSIOGETSTATS: /* get statistics block */
359: *(vsStats *)addr = vsp->stats;
360: return(0);
361:
362: case VSIOGETIOA: /* get io addresses */
363: if (vsp->vsBuff_ubinfo==0) {
364: return(EIO);
365: }
366: *((vsIoAddrAddr *)addr) = &vsb->vsioa;
367: return(0);
368:
369: default: /* a command that could block */
370: if (ret = vsError(vsp))
371: return(ret);
372: break;
373: }
374:
375: switch(cmd) { /* Commands that cause an interrupt */
376: case VSIOINIT: /* initialize device */
377: vsInitDev(dev, FALSE);
378: return(vsError(vsp));
379:
380: case VSIOSTART: /* start microcode */
381: vsAddr.fparm_all = *(caddr_t *)addr;
382: s = spl5();
383: vsaddr->vs_pr1 = vsAddr.fparm_low;
384: vsaddr->vs_pr2 = vsAddr.fparm_high;
385: vsaddr->vs_irr = 0;
386: vsaddr->vs_csr0 &= ~VS_FCN; /* clear bits */
387: vsaddr->vs_csr0 |= (VS_IE | (VS_START << VS_FCSHIFT) | VS_GO);
388: /* synchronous */
389: error = tsleep((caddr_t) vsp, VSWAITPRI | PCATCH, devwait, 0);
390: splx(s);
391: if (error)
392: return (error);
393: return(vsError(vsp));
394:
395: case VSIOABORT: /* abort a command chain */
396: s = spl5();
397: vsaddr->vs_irr = 0;
398: vsaddr->vs_csr0 &= ~VS_FCN;
399: vsaddr->vs_csr0 |= (VS_IE | (VS_ABORT << VS_FCSHIFT) | VS_GO);
400: error = tsleep((caddr_t) vsp, VSWAITPRI | PCATCH, devwait, 0);
401: splx(s);
402: if (error)
403: return (error);
404: return(vsError(vsp));
405:
406: case VSIOPWRUP: /* power-up reset */
407: s = spl5();
408: vsaddr->vs_irr = 0;
409: vsaddr->vs_csr0 &= ~VS_FCN;
410: vsaddr->vs_csr0 |= (VS_IE | (VS_PWRUP << VS_FCSHIFT) | VS_GO);
411: error = tsleep((caddr_t) vsp, VSWAITPRI | PCATCH, devwait, 0);
412: splx(s);
413: if (error)
414: return (error);
415: return(vsError(vsp));
416:
417: case VSIOBBACTL: /* enable/disable BBA */
418: s = spl5();
419: vsaddr->vs_irr = 0;
420: vsaddr->vs_csr0 &= ~VS_FCN;
421: func = *(int *)addr == VSIO_ON ? VS_ENABBA : VS_DISBBA;
422: vsaddr->vs_csr0 |= (VS_IE | (func << VS_FCSHIFT) | VS_GO);
423: error = tsleep((caddr_t) vsp, VSWAITPRI | PCATCH, devwait, 0);
424: splx(s);
425: if (error)
426: return (error);
427: return(vsError(vsp));
428:
429: case VSIOFIBCTL: /* turn the fiber lamp on/off */
430: s = spl5();
431: if (*(int *)addr == VSIO_OFF)
432: vsaddr->vs_csr0 &= ~VS_XMIT_ON;
433: else
434: vsaddr->vs_csr0 |= (VS_IE | VS_XMIT_ON);
435: error = tsleep((caddr_t) vsp, VSWAITPRI | PCATCH, devwait, 0);
436: splx(s);
437: if (error)
438: return (error);
439: return(vsError(vsp));
440:
441: case VSIOFIBRETRY: /* set fiber retries */
442: s = spl5();
443: vsaddr->vs_irr = 0;
444: vsaddr->vs_csr0 &= ~VS_FCN;
445: func = *(int *)addr == VS_FIB_FINITE ? VS_FINITE : VS_INFINITE;
446: vsaddr->vs_csr0 |= (VS_IE | (func << VS_FCSHIFT) | VS_GO);
447: error = tsleep((caddr_t) vsp, VSWAITPRI | PCATCH, devwait, 0);
448: splx(s);
449: if (error)
450: return (error);
451: return(vsError(vsp));
452:
453: case VSIOSYNC: /* get synchronized with device */
454: break;
455:
456: default:
457: return(ENOTTY);
458: }
459:
460: return(0);
461: }
462:
463: vsintr(dev)
464: dev_t dev;
465: {
466: register struct vsdevice *vsaddr;
467: register struct vs_softc *vsp;
468: register vsEvent *vep;
469: struct uba_device *uip;
470: register struct vsBuffArea *vsb;
471: int i;
472: vsCursor cur;
473:
474: if (VSUNIT(dev) >= NVS || (uip = vsdinfo[VSUNIT(dev)]) == 0
475: || uip->ui_alive == 0) {
476: printI("vs%d stray interrupt\n", VSUNIT(dev));
477: return;
478: }
479:
480: vsaddr = (struct vsdevice *) uip->ui_addr;
481: vsp = &vs_softc[VSUNIT(dev)];
482: vsb = &vsBuff[VSUNIT(dev)];
483: #ifdef notdef
484: printM("vsintr csr0=%x, csr1=%x, csr2=%x, csr3=%x, csr4=%x, csr5=%x, csr6=%x, csr7=%x\n",
485: vsaddr->vs_csr0, vsaddr->vs_csr1, vsaddr->vs_csr2, vsaddr->vs_csr3,
486: vsaddr->vs_csr4, vsaddr->vs_csr5, vsaddr->vs_csr6, vsaddr->vs_csr7);
487:
488: printI("vs%dintr ", VSUNIT(dev));
489: #endif
490:
491: /*
492: * get the information out of the soft registers
493: */
494:
495: vsp->irr.intr_reg = vsaddr->vs_irr;
496: vsp->krr.kbd_reg = vsaddr->vs_krr;
497: vsp->pr.fparm_low = vsaddr->vs_pr1;
498: vsp->pr.fparm_high = vsaddr->vs_pr2;
499: cur.x = vsaddr->vs_cxr;
500: cur.y = vsaddr->vs_cyr;
501: vsp->csr.csr_reg = vsaddr->vs_csr0;
502:
503: if (vsp->irr.intr_reason)
504: vsaddr->vs_irr = 0; /* clear int reason, if any */
505:
506: vsaddr->vs_csr0 &= ~VS_OWN; /* clear owner bit */
507:
508: if (vsp->csr.csr_linkTran) {
509: vsaddr->vs_csr0 &= ~VS_LNK_TRNS; /* clear the bit */
510: printI("link transition: ");
511: if (vsp->csr.csr_linkErr)
512: vsp->stats.linkErrors++;
513:
514: if (vsp->csr.csr_linkAvail == vsp->linkAvail) { /* flash */
515: vsp->stats.flashes++;
516: printI("flash\n");
517: } else if (!vsp->csr.csr_linkAvail && vsp->linkAvail) { /* on -> off */
518: vsp->stats.douses++;
519: printI("douse\n");
520: vsp->inited = FALSE;
521: if (vsp->open && vsp->pgrp)
522: gsignal(vsp->pgrp, SIGHUP);
523: wakeup((caddr_t) vsp);
524: } else { /* off -> on */
525: vsp->stats.ignites++;
526: printI("ignite\n");
527: wakeup((caddr_t) vsp);
528: }
529:
530: i = 200;
531: while ((vsaddr->vs_csr0 & VS_LNK_TRNS) && i)
532: i--;
533: if (i == 0) { /* bit stuck */
534: printI("vs%d: Link Transition bit stuck\n", VSUNIT(dev));
535: vsp->inited = FALSE;
536: if (vsp->open && vsp->pgrp)
537: gsignal(vsp->pgrp, SIGHUP);
538: vsaddr->vs_csr0 &= ~VS_XMIT_ON;
539: vsp->csr.csr_linkAvail = FALSE;
540: }
541:
542: vsp->linkAvail = vsp->csr.csr_linkAvail;
543:
544: return;
545: }
546:
547: if (vsp->irr.intr_error) {
548: printI("error 0x%x\n", vsp->irr.intr_reg&0xffff);
549: vsp->stats.errors++;
550: /* set status and wake up user if necessary */
551: if (vsp->vs_nextgo.fparm_all) {
552: vsp->vs_status = vsp->irr.intr_reg;
553: vsaddr->vs_pr1 = vsp->vs_nextgo.fparm_low;
554: vsaddr->vs_pr2 = vsp->vs_nextgo.fparm_high;
555: vsp->vs_nextgo.fparm_all = NULL;
556: vsaddr->vs_csr0 &= ~VS_FCN; /* clear bits */
557: vsaddr->vs_csr0 |= (VS_IE | (VS_SEND << VS_FCSHIFT) | VS_GO);
558: } else
559: vsb->vsioa.status = vsp->irr.intr_reg;
560: wakeup((caddr_t) vsp);
561: return;
562: }
563:
564: #ifdef notdef
565: printI("reason is %b\n", vsp->irr.intr_reason, VSIRR_BITS);
566: #endif
567: switch(vsp->irr.intr_reason) {
568: case VS_INT_CD: /* command done */
569: /* set status and start a new command if necessary */
570: if (vsp->vs_nextgo.fparm_all) {
571: vsp->vs_status = vsp->irr.intr_reg;
572: vsaddr->vs_pr1 = vsp->vs_nextgo.fparm_low;
573: vsaddr->vs_pr2 = vsp->vs_nextgo.fparm_high;
574: vsp->vs_nextgo.fparm_all = NULL;
575: vsaddr->vs_csr0 &= ~VS_FCN; /* clear bits */
576: vsaddr->vs_csr0 |= (VS_IE | (VS_SEND << VS_FCSHIFT) | VS_GO);
577: } else
578: vsb->vsioa.status = vsp->irr.intr_reg;
579: break;
580:
581: case VS_INT_MM: /* mouse moved */
582:
583: vsb->vsioa.mouse = cur;
584:
585: if (!vsp->open)
586: return; /* ignore on closed device */
587:
588: /* no event if inside box */
589: if (cur.y < vsb->vsioa.mbox.bottom &&
590: cur.y >= vsb->vsioa.mbox.top &&
591: cur.x < vsb->vsioa.mbox.right &&
592: cur.x >= vsb->vsioa.mbox.left)
593: return;
594:
595: /* trash box */
596: vsb->vsioa.mbox.bottom = 0;
597:
598: if (EVROUND(vsb->vsioa.itail+1) == vsb->vsioa.ihead)
599: return;
600: i = EVROUND(vsb->vsioa.itail-1);
601: if ((vsb->vsioa.itail != vsb->vsioa.ihead) &&
602: (i != vsb->vsioa.ihead)) {
603: vep = &vsb->ibuff[i];
604: if (vep->vse_type == VSE_MMOTION) {
605: vep->vse_x = cur.x;
606: vep->vse_y = cur.y;
607: vep->vse_time = mfpr(TODR);
608: return;
609: }
610: }
611: /* put event into queue and do select */
612: vep = &vsb->ibuff[vsb->vsioa.itail];
613: vep->vse_type = VSE_MMOTION;
614: vep->vse_x = cur.x;
615: vep->vse_y = cur.y;
616: vep->vse_time = mfpr(TODR);
617: vsb->vsioa.itail = EVROUND(vsb->vsioa.itail+1);
618: if (vsp->rsel) {
619: selwakeup(vsp->rsel, 0);
620: vsp->rsel = 0;
621: }
622: break;
623:
624: case VS_INT_BE: /* button event */
625: if (!vsp->open)
626: return; /* ignore on closed device */
627:
628: if (vsp->krr.kbd_device == VSE_MOUSE) {
629: vsb->vsioa.mouse.x = cur.x;
630: vsb->vsioa.mouse.y = cur.y;
631: }
632: /* check for room in the queue */
633: if ((i = EVROUND(vsb->vsioa.itail+1)) == vsb->vsioa.ihead)
634: return;
635: /* put event into queue and do select */
636: vep = &vsb->ibuff[vsb->vsioa.itail];
637: vep->vse_type = VSE_BUTTON;
638: vep->vse_key = vsp->krr.kbd_key;
639: vep->vse_direction = vsp->krr.kbd_transition;
640: vep->vse_device = vsp->krr.kbd_device;
641: vep->vse_time = mfpr(TODR);
642: vep->vse_x = vsb->vsioa.mouse.x;
643: vep->vse_y = vsb->vsioa.mouse.y;
644: vsb->vsioa.itail = i;
645: if (vsp->rsel) {
646: selwakeup(vsp->rsel, 0);
647: vsp->rsel = 0;
648: }
649: break;
650:
651: case VS_INT_TM: /* tablet moved */
652: if (!vsp->open)
653: return; /* ignore on closed device */
654:
655: if (EVROUND(vsb->vsioa.itail+1) == vsb->vsioa.ihead)
656: return;
657: i = EVROUND(vsb->vsioa.itail-1);
658: if ((vsb->vsioa.itail != vsb->vsioa.ihead) &&
659: (i != vsb->vsioa.ihead)) {
660: vep = &vsb->ibuff[i];
661: if (vep->vse_type == VSE_TMOTION) {
662: vep->vse_x = cur.x;
663: vep->vse_y = cur.y;
664: vep->vse_time = mfpr(TODR);
665: return;
666: }
667: }
668: /* put event into queue and do select */
669: vep = &vsb->ibuff[vsb->vsioa.itail];
670: vep->vse_type = VSE_TMOTION;
671: vep->vse_x = cur.x;
672: vep->vse_y = cur.y;
673: vep->vse_time = mfpr(TODR);
674: vsb->vsioa.itail = EVROUND(vsb->vsioa.itail+1);
675: if (vsp->rsel) {
676: selwakeup(vsp->rsel, 0);
677: vsp->rsel = 0;
678: }
679: break;
680:
681: case VS_INT_US: /* unsolicited */
682: vsp->stats.unsolIntr++;
683: return;
684:
685: case VS_INT_ID: /* Initialization done */
686: /* save offset from device */
687: vsp->offset.fparm_all = vsp->pr.fparm_all;
688: /* save rom version */
689: vsp->romVersion = cur.x;
690: vsp->inited = TRUE;
691: break;
692:
693: case VS_INT_SE: /* ucode started */
694: break;
695:
696: case VS_INT_PWR: /* power up complete */
697: /* save rom version */
698: vsp->romVersion = cur.x;
699: vsp->inited = FALSE;
700: if (vsp->open && vsp->pgrp)
701: gsignal(vsp->pgrp, SIGHUP);
702: break;
703:
704: default:
705: printI("vs%d: unknown interrupt %b\n", VSUNIT(dev),
706: vsp->irr.intr_reason, VSIRR_BITS);
707: return;
708: }
709: wakeup((caddr_t) vsp);
710: }
711:
712: vsreset(uban)
713: int uban;
714: {
715: register int i;
716: register struct uba_device *uip;
717: register struct vs_softc *vsp = vs_softc;
718:
719: for (i = 0; i < NVS; i++, vsp++) {
720: if ((uip = vsdinfo[i]) == 0 || uip->ui_alive == 0 ||
721: uip->ui_ubanum != uban || vsp->open == 0)
722: continue;
723: printf(" vs%d", i);
724: vsp->inited = FALSE;
725: if (vsp->open && vsp->pgrp)
726: gsignal(vsp->pgrp, SIGHUP);
727: }
728: }
729:
730: vsselect(dev, rw)
731: dev_t dev;
732: {
733: register struct vsBuffArea *vsb = &vsBuff[VSUNIT(dev)];
734: int s = spl5();
735:
736: switch(rw) {
737: case FREAD:
738: if (vsb->vsioa.ihead != vsb->vsioa.itail) {
739: splx(s);
740: return(1);
741: }
742: vs_softc[VSUNIT(dev)].rsel = u.u_procp;
743: splx(s);
744: return(0);
745:
746: default:
747: splx(s);
748: return(0); /* can never write */
749: }
750: }
751:
752: /*
753: * Initialize VS100 or SBO.
754: * Set XMITON. VS100 will respond with link available. SBO won't, so
755: * don't wait forever; assume everything is OK and warn user.
756: */
757:
758: vsInitFiber(dev)
759: dev_t dev;
760: {
761: struct vsdevice *vsaddr = (struct vsdevice *) vsdinfo[VSUNIT(dev)]->ui_addr;
762: register struct vs_softc *vsp = &vs_softc[VSUNIT(dev)];
763: int s, error;
764:
765: s = spl5();
766: vsaddr->vs_csr0 |= (VS_IE | VS_XMIT_ON); /* turn link on */
767: error = tsleep((caddr_t) vsp, VSWAITPRI, SLP_VS_INITF, 2*hz);
768: splx(s);
769: if (error == EWOULDBLOCK) /* timeout */
770: error = 0;
771: #ifdef VSSBO
772: if (!vsp->linkAvail) {
773: uprintf("\007This had better be a vs125!\n");
774: printf("vs%d must be a vs125\n", VSUNIT(dev));
775: vsp->linkAvail = TRUE;
776: }
777: #endif
778: return (error);
779: }
780:
781: vsInitDev(dev, retry)
782: dev_t dev;
783: int retry;
784: {
785: register struct vsdevice *vsaddr;
786: register struct vs_softc *vsp;
787: int s, error;
788:
789: vsaddr = (struct vsdevice *) vsdinfo[VSUNIT(dev)]->ui_addr;
790: vsp = &vs_softc[VSUNIT(dev)];
791:
792: if (!vsp->linkAvail)
793: if (error = vsInitFiber(dev))
794: return (error);
795: while (1) {
796: s = spl5();
797: vsaddr->vs_irr = 0;
798: vsaddr->vs_csr0 &= ~VS_FCN;
799: vsaddr->vs_csr0 |= (VS_IE | (VS_INIT << VS_FCSHIFT) | VS_GO);
800: error = tsleep((caddr_t) vsp, VSWAITPRI | PCATCH,
801: devwait, retry ? 10*hz : 0);
802: splx(s);
803: if (error == EWOULDBLOCK)
804: error = 0;
805: if (error)
806: return (error);
807: if (vsp->inited)
808: break;
809: printM("vs%d: VS_INIT fails\n", VSUNIT(dev));
810: uprintf("vsInitDev %x %x\n",vsaddr->vs_csr0, vsaddr->vs_csr1);
811: }
812: return (0);
813: }
814:
815: vsError(vsp)
816: register struct vs_softc *vsp;
817: {
818: if (vsp->irr.intr_error) {
819: register int ret = vsp->irr.intr_reg;
820:
821: printD("\treturning 0x%x\n", ret);
822: vsp->irr.intr_reg = 0;
823: return(ret+128);
824: }
825: return(0);
826: }
827: #endif
828:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.