|
|
1.1 root 1: /*% cyntax -c -DKERNEL % && cc -c -DKERNEL %
2: * Metheus 3610 driver via dr11-w for 9Vr2
3: */
4: #include "sys/param.h"
5: #include "sys/conf.h"
6: #include "sys/user.h"
7: #include "sys/buf.h"
8: #include "sys/ubaddr.h"
9: #include "sys/om.h"
10: #define OMTIMEOUT 15 /* seconds */
11: int omopen(), omclose(), omread(), omwrite(), omioctl();
12: struct cdevsw omcdev=cdinit(omopen, omclose, omread, omwrite, nodev);
13: int omcnt; /* defined in conf */
14: extern struct ubaddr omaddr[]; /* defined in conf */
15: #define OPEN 1 /* somebody has the device open */
16: #define RUNNING 2 /* dma in progress */
17: #define LATE 4 /* dma ready to time out */
18: #define NOTIME 8 /* don't bother with timeout */
19: int omtiming; /* timeout exists */
20: /*
21: * dr11-w hardware registers
22: */
23: struct omreg{
24: short wc;
25: short addr;
26: short csr;
27: short data;
28: };
29: /*
30: * csr bits
31: */
32: #define ERROR 0100000
33: #define ATTN 020000
34: #define READY 0200
35: #define IENABLE 0100
36: #define XMEM 060
37: #define xmem(a) (((a)>>12)&XMEM)
38: #define WAKEUP 010
39: #define READ 02
40: #define GO 01
41: int omtimeout();
42: omopen(dev, flags){
43: register d=minor(dev);
44: register struct om *p=&om[d];
45: if(d>=omcnt
46: || p->flag&OPEN){
47: u.u_error=ENODEV;
48: return;
49: }
50: if((p->reg=(struct omreg *)ubaddr(&omaddr[d]))==0
51: || ubbadaddr(omaddr[d].ubno, (caddr_t)&p->reg->csr, sizeof(short))){
52: printf("om%d absent\n", d);
53: u.u_error=ENODEV;
54: return;
55: }
56: p->flag|=OPEN;
57: if(omtiming==0) {
58: omtiming=1;
59: timeout(omtimeout, (caddr_t)0, OMTIMEOUT*HZ);
60: }
61: }
62: omclose(dev){
63: om[minor(dev)].flag&=~OPEN;
64: }
65: omstrategy(bp)
66: struct buf *bp;
67: {
68: register d=minor(bp->b_dev), csr, pri;
69: register struct om *p=&om[d];
70: register struct omreg *omreg;
71: register uaddr_t ubad;
72: if(bp->b_bcount&1){
73: bp->b_flags|=B_ERROR;
74: iodone(bp);
75: return;
76: }
77: p->ubm=ubmbuf(omaddr[d].ubno, bp, UBDP|USLP);
78: ubad=ubadbuf(omaddr[d].ubno, bp, p->ubm);
79: pri=spl5();
80: omreg=p->reg;
81: omreg->wc=-(bp->b_bcount>>1);
82: omreg->addr=ubad;
83: csr=IENABLE|xmem(ubad);
84: if(bp->b_flags&B_READ) csr|=READ;
85: omreg->csr=csr;
86: omreg->csr=csr|GO;
87: if ((bp->b_flags & B_READ) == 0) {
88: p->flag |= RUNNING;
89: splx(pri);
90: return;
91: }
92: /*
93: * reading: no timeout (might wait forever for mouse data)
94: * hence must allow signals
95: * hence do our own sleep
96: */
97: p->flag |= (RUNNING|NOTIME);
98: if (tsleep((caddr_t)bp, PZERO+1, 0) != TS_OK) {
99: /* signal: tear down by hand */
100: omreg->csr = ATTN|WAKEUP|IENABLE;
101: bp->b_flags |= B_ERROR;
102: ubmfree(omaddr[d].ubno, p->ubm);
103: iodone(bp);
104: p->flag &=~ (RUNNING|NOTIME|LATE);
105: }
106: splx(pri);
107: }
108: omread(dev){
109: physio(omstrategy, &om[minor(dev)].buf, dev, B_READ, minphys);
110: }
111: omwrite(dev){
112: physio(omstrategy, &om[minor(dev)].buf, dev, B_WRITE, minphys);
113: }
114: om0int(d){
115: register struct buf *bp;
116: register struct om *p=&om[d];
117: register struct omreg *omreg=p->reg;
118: register csr=omreg->csr;
119: if(p->flag&RUNNING && csr&(READY|ATTN)){
120: omreg->csr=0;
121: bp=&p->buf;
122: if(csr&ERROR)
123: bp->b_flags|=B_ERROR;
124: bp->b_resid=(-omreg->wc)<<1;
125: ubmfree(omaddr[d].ubno, p->ubm);
126: iodone(bp);
127: p->flag&=~(RUNNING|NOTIME|LATE);
128: }
129: }
130: omtimeout(){
131: register struct om *p, *ep;
132: register int s;
133: ep=&om[omcnt];
134: s=spl5();
135: for(p=&om[0];p!=ep;p++) if((p->flag&(RUNNING|NOTIME))==RUNNING){
136: if((p->flag&LATE)==0)
137: p->flag|=LATE;
138: else {
139: p->reg->csr=ATTN|WAKEUP|IENABLE;
140: ubmfree(omaddr[p-om].ubno, p->ubm);
141: p->buf.b_flags|=B_ERROR;
142: iodone(&p->buf);
143: p->flag&=~(RUNNING|LATE);
144: }
145: }
146: splx(s);
147: timeout(omtimeout, (caddr_t)0, OMTIMEOUT*HZ);
148: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.