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