1: /*
2: * Copyright (c) 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)dr.c 1.5 (2.11BSD GTE) 1997/2/14
7: */
8:
9: /*
10: * DR11-W device driver
11: */
12:
13: #include "dr.h"
14: #if NDR > 0
15:
16: #include "param.h"
17: #include "../machine/seg.h"
18:
19: #include "user.h"
20: #include "proc.h"
21: #include "buf.h"
22: #include "conf.h"
23: #include "ioctl.h"
24: #include "drreg.h"
25: #include <sys/kernel.h>
26:
27: struct dr11w {
28: int i_flags; /* interface flags */
29: int i_req; /* request number (for timeout) */
30: int i_unit; /* unit number of device */
31: int i_prev; /* previous request number (timeout) */
32: short i_fun; /* function bits */
33: struct proc *i_proc; /* process pointer of opening process */
34: int i_sig; /* signal to send on ATTN */
35: int i_tsig; /* signal to send on timeout */
36: struct buf i_tab; /* buffer for device */
37: struct drdevice *i_addr; /* address of DR11-W interface */
38: };
39:
40: struct dr11w dr11[NDR];
41:
42: drattach(addr, unit)
43: struct drdevice *addr;
44: int unit;
45: {
46: if(unit > NDR)
47: return(0);
48: if((addr != (struct drdevice *)NULL) && (fioword(addr) != -1))
49: {
50: dr11[unit].i_addr = addr;
51: dr11[unit].i_flags = DR_ALIVE; /* mark as active */
52: dr11[unit].i_unit = unit;
53: return(1);
54: }
55: return(0);
56: }
57:
58: dropen(dev)
59: dev_t dev;
60: {
61: register int unit;
62: register struct dr11w *drptr;
63: extern int drtimeout();
64:
65: unit = minor(dev) & 07; /* get minor device number */
66: drptr = &dr11[unit];
67: if((unit > NDR) || !(drptr->i_flags & DR_ALIVE))
68: return(ENXIO); /* not attatched or present */
69: drptr->i_flags |= DR_OPEN;
70: drptr->i_flags &= ~(DR_IGNORE | DR_TIMEOUT);
71: drptr->i_proc = u.u_procp; /* process pointer of opener */
72: drptr->i_sig = 0; /* clear signals (set by ioctl) */
73: drptr->i_tsig = 0;
74: drptr->i_fun = 0; /* clear function */
75: timeout(drtimeout, (caddr_t)drptr, hz);
76: return(0);
77: }
78:
79: drclose(dev, flag)
80: dev_t dev;
81: {
82: register int unit;
83: register struct drdevice *addr;
84:
85: unit = minor(dev) & 07;
86: dr11[unit].i_flags &= ~DR_OPEN; /* clear opened status */
87: addr = dr11[unit].i_addr; /* get address of DR11-W */
88: addr->csr = dr11[unit].i_fun; /* clear IE and GO bits */
89: }
90:
91: drstrategy(bp)
92: register struct buf *bp;
93: {
94: register struct buf *dp;
95: register struct dr11w *drptr;
96: int s;
97:
98: drptr = &dr11[minor(bp->b_dev) & 07];
99: if(!(drptr->i_flags & DR_OPEN))
100: {
101: bp->b_flags |= B_ERROR; /* unit not open */
102: iodone(bp);
103: return;
104: }
105: dp = &(drptr->i_tab); /* point to buffer */
106: bp->av_forw = NULL;
107: s = splbio(); /* lock out interrupts */
108:
109: mapalloc(bp);
110:
111: if(dp->b_actf == NULL) /* if nothing in current buffer */
112: dp->b_actf = bp; /* this request is first */
113: dp->b_actl = bp; /* set last request */
114: if(dp->b_active == 0) /* if not active now */
115: drstart(drptr); /* start the DR11-W */
116: splx(s); /* return to normal state */
117: }
118:
119: drstart(drptr)
120: register struct dr11w *drptr;
121: {
122: register struct buf *bp, *dp;
123: register struct drdevice *addr;
124: short com;
125:
126: if(!drptr)
127: return;
128: dp = &(drptr->i_tab); /* point dp to device buffer */
129: if((bp = dp->b_actf) == NULL) /* if nothing in queue */
130: return; /* return */
131:
132: drptr->i_req++; /* increment request number */
133: if(drptr->i_flags & DR_TIMEOUT) /* do we need timeout checking */
134: {
135: drptr->i_flags |= DR_TACTIVE; /* mark active timeout */
136: }
137: dp->b_active = 1; /* set active flag */
138: addr = drptr->i_addr; /* get device pointer */
139: /*
140: * Set up DR11-W for specific operation
141: */
142: addr->bar = (short)bp->b_un.b_addr;
143: addr->wcr = -(bp->b_bcount >> 1); /* DR deals in words */
144: com = ((bp->b_xmem & 3) << 4) | drptr->i_fun;
145: addr->csr = com; /* set csr fun and address */
146: com |= (DR_IE | DR_GO); /* set IE and GO bits (also) */
147: addr->csr = com;
148: }
149:
150: drintr(unit)
151: int unit;
152: {
153: register struct buf *bp;
154: register struct drdevice *dr;
155: register struct dr11w *drptr;
156: mapinfo map;
157:
158: drptr = &dr11[unit]; /* point to struct for device */
159: dr = drptr->i_addr; /* get address of device */
160: if(drptr->i_tab.b_active == 0) /* if not active, return */
161: return;
162: bp = drptr->i_tab.b_actf; /* point to current buffer */
163: if(dr->csr & DR_ERR) /* if error */
164: {
165: /*
166: * The error bit can be set in one of two ways:
167: * a 'real' error (timing, non-existant memory) or
168: * by the interface setting ATTN true. This is
169: * not considered an 'error' but cause to send
170: * a signal to the parent process. He (hopefully)
171: * will know what to do then.
172: */
173: if(dr->csr & DR_ATTN)
174: {
175: dr->csr = drptr->i_fun;
176: savemap(map);
177: if(drptr->i_sig)
178: psignal(drptr->i_proc, drptr->i_sig);
179: restormap(map);
180: }
181: else
182: {
183: printf("dr%d: error ", unit);
184: printf("csr=%b, ", dr->csr, DRCSR_BITS);
185: dr->csr = DR_ERR | drptr->i_fun;
186: printf("eir=%b\n", dr->csr, DREIR_BITS);
187: /* now reset the DR11-W interface */
188: dr->csr = DR_MANT | drptr->i_fun;
189: dr->csr = drptr->i_fun;
190: bp->b_flags |= B_ERROR;
191: }
192: }
193: drptr->i_flags &= ~DR_TACTIVE; /* we beat the timeout */
194: drptr->i_tab.b_active = 0; /* clear global stuff */
195: drptr->i_tab.b_errcnt = 0;
196: drptr->i_tab.b_actf = bp->b_forw; /* link to next request */
197: bp->b_resid = -(dr->wcr) << 1; /* change words to bytes */
198: iodone(bp); /* tell system we are done */
199: if(drptr->i_tab.b_actf) /* start next request */
200: drstart(drptr);
201: }
202:
203: drioctl(dev, cmd, data, flag)
204: dev_t dev;
205: u_int cmd;
206: register caddr_t data;
207: int flag;
208: {
209: register struct dr11w *drptr;
210: register struct drdevice *dr;
211: int *sgbuf = (int *)data;
212:
213: drptr = &dr11[minor(dev) & 07];
214: dr = drptr->i_addr;
215: if(drptr->i_tab.b_active)
216: return (EINVAL);
217:
218: switch(cmd) {
219: case DRGTTY:
220: sgbuf[0] = drptr->i_flags;
221: sgbuf[1] = drptr->i_fun >> 1;
222: break;
223:
224: case DRSTTY:
225: drptr->i_fun = (sgbuf[1] & 07) << 1;
226: dr->csr = drptr->i_fun;
227: drptr->i_flags &= ~(DR_TIMEOUT | DR_IGNORE);
228: drptr->i_flags |= sgbuf[0] & (DR_TIMEOUT | DR_IGNORE);
229: break;
230:
231: case DRSFUN:
232: drptr->i_fun = (sgbuf[0] & 07) << 1;
233: dr->csr = drptr->i_fun;
234: break;
235:
236: case DRSFLAG:
237: drptr->i_flags &= ~(DR_TIMEOUT | DR_IGNORE);
238: drptr->i_flags |= sgbuf[0] & (DR_TIMEOUT | DR_IGNORE);
239: break;
240:
241: case DRGCSR:
242: sgbuf[0] = dr->csr;
243: sgbuf[1] = dr->wcr;
244: break;
245:
246: case :
247: drptr->i_sig = sgbuf[0];
248: if((drptr->i_sig < 0) || (drptr->i_sig > 15)) {
249: drptr->i_sig = 0;
250: return (EINVAL);
251: }
252: break;
253:
254: case DRESET:
255: dr->csr = DR_MANT | drptr->i_fun;
256: dr->csr = drptr->i_fun;
257: break;
258:
259: case DRSTIME:
260: drptr->i_tsig = sgbuf[0];
261: if((drptr->i_tsig < 0) || (drptr->i_tsig > 15)) {
262: drptr->i_tsig = 0;
263: return (EINVAL);
264: }
265: drptr->i_flags |= DR_TIMEOUT;
266: drptr->i_flags &= ~DR_IGNORE;
267: break;
268:
269: case DRCTIME:
270: drptr->i_flags &= ~(DR_TIMEOUT | DR_IGNORE);
271: break;
272:
273: case DRITIME:
274: drptr->i_flags |= DR_IGNORE;
275: break;
276:
277: case DROUTPUT:
278: dr->dar = sgbuf[0];
279: break;
280:
281: case DRINPUT:
282: sgbuf[0] = dr->dar;
283: break;
284:
285: default:
286: return (EINVAL);
287: }
288: return (0);
289: }
290:
291: drtimeout(ptr)
292: caddr_t ptr;
293: {
294: register struct dr11w *drptr;
295: mapinfo map;
296:
297: drptr = (struct dr11w *)ptr;
298: if((drptr->i_flags & DR_TACTIVE) && (drptr->i_req == drptr->i_prev))
299: {
300: printf("dr%d: timeout error\n", drptr->i_unit);
301: savemap(map);
302: if(drptr->i_tsig)
303: psignal(drptr->i_proc, drptr->i_tsig);
304:
305: restormap(map);
306: drabort(drptr);
307: savemap(map);
308: if(drptr->i_tab.b_actf)
309: drstart(drptr); /* start next request */
310: restormap(map);
311: }
312: if(drptr->i_flags & (DR_TACTIVE | DR_OPEN))
313: {
314: drptr->i_prev = drptr->i_req; /* arm timeout */
315: timeout(drtimeout, ptr, hz);
316: }
317: }
318:
319: drabort(drptr)
320: register struct dr11w *drptr;
321: {
322: register struct buf *bp;
323: register struct drdevice *dr;
324: mapinfo map;
325:
326: savemap(map);
327: dr = drptr->i_addr; /* point to device */
328: bp = drptr->i_tab.b_actf; /* point to current buffer */
329: drptr->i_flags &= ~DR_TACTIVE; /* turn off timeout active */
330: drptr->i_tab.b_active = 0; /* clean up global stuff */
331: drptr->i_tab.b_errcnt = 0;
332: drptr->i_tab.b_actf = bp->b_forw; /* link to next request */
333: bp->b_resid = -(dr->wcr) << 1; /* make it bytes */
334: if(!(drptr->i_flags & DR_IGNORE))
335: bp->b_flags |= B_ERROR; /* set an error condition */
336: dr->csr = DR_MANT | drptr->i_fun; /* clear IE bit in csr */
337: dr->csr = drptr->i_fun; /* restore function bits */
338: restormap(map);
339: iodone(bp); /* done with that request */
340: }
341: #endif NDR
Defined functions
Defined variables
dr11
defined in line
40; used 10 times
Defined struct's
dr11w
defined in line
27; used 18 times