|
|
1.1 root 1: /*
2: Imagitek Scanner -- Andrew Hume
3: 1100 (?), on DR-11/W
4: Ninth Edition Unix (related to BSD 4.1c)
5: */
6:
7: int imdebug = 0;
8: int imdebug1 = 0;
9: int imdebug2 = 0;
10: #define IMKEEPINT 100/**/
11:
12: enum states {
13: IDLE, /*0 idle or finishing off read */
14: WRITEPROBE, /*1 waiting for scanner ack */
15: WRITE, /*2 started dma to scanner */
16: WRITEDMA, /*3 got dma after WRITE */
17: WRITEATTN, /*4 got attn after WRITE */
18: READPROBE, /*5 waiting for ATTN from scanner */
19: READ, /*6 ready to start dma from scanner */
20: RESETTING /*7 imreset(dev) */
21: };
22: #include "sys/param.h"
23: #include "sys/conf.h"
24: #include "sys/user.h"
25: #include "sys/buf.h"
26: #include "sys/ubaddr.h"
27: #include "sys/systm.h"
28:
29: #include "sys/im.h"
30:
31: struct imdevice {
32: short wcr; /* Unibus word count reg */
33: u_short bar; /* Unibus address register */
34: u_short csr; /* Unibus status/command reg */
35: u_short idr; /* Input Data Register */
36: };
37: #define eir csr /* Error and Information Register */
38: #define odr idr /* Output Data Register */
39:
40: /*
41: * Unibus status/command register bits
42: */
43: #define GO 0x0001
44: #define HSTRB 0x0002 /* host strobe fn1 */
45: #define HINTR 0x0004 /* host interrupt fn2 */
46: #define HRESET 0x0008 /* host reset fn3 */
47: #define XMEM 0x0030
48: #define xmem(a) (((a) >> 12)&XMEM)
49: #define IENABLE 0x0040
50: #define READY 0x0080
51: #define SSTRB 0x0200 /* scanner strobe statc */
52: #define SINTR 0x0400 /* scanner interrupt statb */
53: #define SRESET 0x0800 /* scanner interface reset stata */
54: #define MAINT 0x1000
55: #define ATTN 0x2000 /* attention */
56: #define NEX 0x4000
57: #define ERROR 0x8000
58:
59: /*
60: * config glue
61: */
62: int imopen(), imclose(), imread(), imwrite(), imioctl();
63:
64: extern struct im im[];
65: extern struct ubaddr imaddr[];
66: extern int imcnt;
67: struct cdevsw imcdev = cdinit(imopen, imclose, imread, imwrite, imioctl);
68:
69: /*
70: * IOCTL
71: */
72: #define IMRESET (('i'<<8)|1)
73: #define IMWAIT (('i'<<8)|2)
74:
75: #define DMAPRI (PZERO-1)
76: #define WAITPRI (PZERO+1)
77: #define FUNCMASK (HSTRB|HINTR|HRESET)
78:
79: /*
80: this is a finite state automata driven by the interrupt routine
81: */
82:
83:
84: #ifdef IMKEEPINT
85: typedef struct iminterrupt
86: {
87: short csr, ostate, nstate, attn;
88: long time;
89: } iminterrupt;
90: iminterrupt imi[IMKEEPINT], *nimi;
91: #endif
92: #define IMN 1000
93: static short wcnt[IMN], rcnt[IMN], rscnt[IMN], wi, ri;
94:
95: imopen(d, f)
96: {
97: register struct im *imp;
98: register int dev;
99:
100: if((dev = minor(d)) >= imcnt) {
101: u.u_error = ENODEV;
102: return;
103: }
104: if((imp = &im[dev])->open) {
105: u.u_error = EBUSY;
106: return;
107: }
108: if((imp->addr = (struct imdevice *)ubaddr(&imaddr[dev])) == 0
109: || ubbadaddr(imaddr[dev].ubno, (caddr_t)imp->addr, sizeof(u_short))) {
110: printf("im%d absent\n", dev);
111: u.u_error = ENODEV;
112: return;
113: }
114: imp->addr->csr = 0;
115: imp->open = 1;
116: imp->state = IDLE;
117: #ifdef IMKEEPINT
118: nimi = imi;
119: #endif
120: wi = ri = 0;
121: }
122:
123: imclose(dev)
124: {
125: register struct im *imp = &im[minor(dev)];
126:
127: if(imp->state != IDLE)
128: imreset(imp);
129: imp->open = 0;
130: #ifdef IMKEEPINT
131: if(imdebug1){
132: iminterrupt *i;
133:
134: for(i = imi; i < nimi; i++)
135: printf("%d: csr=0x%x attn=%d ostate=%d nstate=%d\n",
136: i->time, i->csr&0xFFFF, i->attn, i->ostate, i->nstate);
137: }
138: #endif
139: if(imdebug2){
140: register i;
141:
142: printf("read: ");
143: for(i = 0; i < ri; i++)
144: printf("%d:%d[%d] ", i, rcnt[i], rscnt[i]);
145: printf("\nwrite: ");
146: for(i = 0; i < wi; i++)
147: if(wcnt[i]) printf("%d:%d ", i, wcnt[i]);
148: printf("\n");
149: }
150: }
151:
152: u_int
153: imminphys(bp)
154: register struct buf *bp;
155: {
156:
157: if(bp->b_bcount > 65536) /* may be able to do twice as much */
158: bp->b_bcount = 65536;
159: }
160:
161: imstrategy(bp)
162: register struct buf *bp;
163: {
164: register struct im *imp = &im[minor(bp->b_dev)];
165: register int s;
166: uaddr_t uaddr;
167: u_short csr;
168:
169: if(bp->b_bcount<=0 || (bp->b_bcount&1) || ((int)bp->b_un.b_addr&1)){
170: bp->b_flags |= B_ERROR;
171: iodone(bp);
172: return;
173: }
174: imp->ubm = ubmbuf(imaddr[minor(bp->b_dev)].ubno, bp, UBDP|USLP);
175: uaddr = ubadbuf(imaddr[minor(bp->b_dev)].ubno, bp, imp->ubm);
176: s = spl5();
177: csr = IENABLE| xmem(uaddr) | ((bp->b_flags&B_READ) ? 0: HINTR);
178: imp->addr->wcr = -(bp->b_bcount>>1); /* it's a word count */;
179: imp->addr->bar = uaddr;
180: imp->addr->csr = csr; /* No GO bit; let function codes settle */
181: imp->addr->csr = csr|GO;
182: if(tsleep((caddr_t)imp, DMAPRI+1, 15) != TS_OK){
183: printf("im dma timeout: csr=0x%x wcr=%d\n",
184: imp->addr->csr, imp->addr->wcr);
185: /* stop the dma */
186: imslam(imp->addr);
187: imp->addr->wcr = 0xFFFF; /* gently; -1 first... */
188: imp->addr->wcr = 0x0000; /* then zero */
189: /* reset device */
190: imreset(imp);
191: bp->b_flags |= B_ERROR;
192: }
193: splx(s);
194: ubmfree(imaddr[minor(bp->b_dev)].ubno, imp->ubm);
195: bp->b_resid = -(imp->addr->wcr<<1);
196: iodone(bp);
197: }
198:
199: imread(dev)
200: {
201: register struct im *imp = &im[minor(dev)];
202: int start;
203:
204: start = time*HZ+lbolt;
205: if(imdebug)
206: printf("read: ");
207: while((imp->state == WRITEDMA) || (imp->state == WRITEATTN) ||
208: (imp->state == READPROBE)){
209: if(tsleep((caddr_t)imp, DMAPRI+1, 15) != TS_OK){
210: imreset(imp);
211: return;
212: }
213: }
214: rscnt[ri] = time*HZ+lbolt-start;
215: if(imp->state != READ){
216: u.u_error = EGREG;
217: return;
218: }
219: u.u_count += 2;
220: imp->addr->csr = IENABLE; /* HSTRB ??*/
221: physio(imstrategy, &imp->buf, dev, B_READ, imminphys);
222: u.u_count -= 2;
223: imp->addr->csr = IENABLE;
224: rcnt[ri++] = time*HZ+lbolt-start;
225: }
226:
227: imwrite(dev)
228: {
229: register struct im *imp = &im[minor(dev)];
230: register int start, s, x;
231:
232: start = time*HZ+lbolt;
233: if(imp->state != IDLE){
234: u.u_error = EGREG;
235: return;
236: }
237: if(imp->addr->csr&(SINTR|SRESET)){ /* is it offline ? */
238: printf("im: offline csr=0x%x\n", imp->addr->csr);
239: u.u_error = ENXIO;
240: return;
241: }
242: s = spl5();
243: imp->state = WRITEPROBE;
244: imp->addr->csr = IENABLE | HINTR | HSTRB; /* poke scanner */
245: if(((x = tsleep((caddr_t)imp, DMAPRI+1, 15)) != TS_OK) ||
246: (imp->state != WRITE)){
247: printf("im%d: wtimo - type %d, state %d\n", x, imp->state);
248: imreset(imp);
249: return;
250: }
251: imp->addr->csr = HINTR;
252: splx(s);
253: physio(imstrategy, &imp->buf, dev, B_WRITE, imminphys);
254: /*
255: the write is done although we may not have both interrupts
256: */
257: wcnt[wi++] = time*HZ+lbolt-start;
258: }
259:
260: imslam(addr)
261: register struct imdevice *addr;
262: {
263: register i;
264:
265: addr->csr = MAINT;
266: for(i = 0; i < 10; i++)
267: ;
268: addr->csr = 0;
269: for(i = 0; i < 10; i++)
270: ;
271: }
272:
273: /*ARGSUSED*/
274: imioctl(dev, cmd, addr, flag)
275: caddr_t addr;
276: {
277: register struct im *imp = &im[minor(dev)];
278:
279: switch(cmd) {
280:
281: case IMRESET:
282: spl5();
283: imreset(imp);
284: if((tsleep((caddr_t)imp, WAITPRI, 15) != TS_OK) || (imp->state != IDLE)){
285: spl0();
286: u.u_error = EIO;
287: imp->state = IDLE;
288: return;
289: }
290: u.u_error = 0;
291: spl0();
292: break;
293:
294: case IMWAIT:
295: if(imp->state != READPROBE){
296: if(imdebug)
297: printf("im: wait state=%d\n", imp->state);
298: return;
299: }
300: if((tsleep((caddr_t)imp, WAITPRI, 150) != TS_OK) || (imp->state != READ)){
301: u.u_error = EIO;
302: return;
303: }
304: u.u_error = 0;
305: break;
306:
307: default:
308: u.u_error = ENOTTY;
309: break;
310: }
311: }
312:
313: im0int(dev)
314: {
315: register struct im *imp = &im[dev];
316: u_short csr;
317: int attn = 0;
318: int ostate = imp->state;
319: int dma;
320:
321: if((csr = imp->addr->csr) & ATTN)
322: attn = 1;
323: else if(csr&ERROR) {
324: imp->addr->eir |= ERROR;
325: printf("im: read goo CSR %x EIR %x BAR %x WCR %x\n",
326: csr, imp->addr->eir, imp->addr->bar, imp->addr->wcr);
327: imp->addr->csr = csr&~FUNCMASK;
328: imreset(imp);
329: }
330: #ifdef IMKEEPINT
331: nimi->time = time*HZ+lbolt;
332: nimi->csr = csr;
333: nimi->attn = attn;
334: nimi->ostate = ostate;
335: nimi->nstate = -1;
336: if(++nimi >= &imi[IMKEEPINT])
337: nimi--;
338: #endif
339: if(imdebug)
340: printf("imintr: csr=0x%x ostate=%d attn=%d ", csr, ostate, attn);
341: if(!(csr&READY))
342: return;
343: switch(imp->state) {
344:
345: case IDLE:
346: break;
347:
348: case WRITEPROBE:
349: if(attn)
350: imp->state = WRITE;
351: else
352: imreset(imp);
353: break;
354:
355: case WRITE:
356: dma = (csr&READY) && (imp->addr->wcr == 0);
357: if(attn){
358: if(dma){
359: imp->addr->csr = IENABLE;
360: imp->state = READPROBE;
361: } else
362: imp->state = WRITEATTN;
363: } else {
364: if(!dma)
365: printf("im: phooey! wcr=%d\n", imp->addr->wcr);
366: /* bad value: imp->state = WRITEDMA;*/
367: imp->addr->csr = IENABLE;
368: imp->state = READPROBE;
369: }
370: break;
371:
372: case WRITEDMA:
373: if(!attn)
374: printf("im: scrunt\n");
375: imp->addr->csr = IENABLE;
376: imp->state = READPROBE;
377: break;
378:
379: case WRITEATTN:
380: if(attn)
381: printf("im: poot\n");
382: imp->addr->csr = IENABLE;
383: imp->state = READPROBE;
384: break;
385:
386: case READPROBE:
387: if(attn)
388: imp->state = READ;
389: else
390: imreset(imp);
391: break;
392:
393: case READ:
394: /*
395: because we may not get both an attn and a dma done
396: drop into idle. if we get neither, something will screw
397: up; that's ok because the user is in trouble anyway.
398: */
399: dma = (csr&READY) && (imp->addr->wcr == 0);
400: if(imdebug)
401: printf("DMA=%d: ", dma);
402: if((csr & (SRESET|SINTR|SSTRB)) != SSTRB)
403: imreset(imp);
404: else
405: imp->state = IDLE;
406: break;
407:
408: case RESETTING:
409: if(!attn || (csr & SSTRB)){
410: printf("im: bad reset\n");
411: }
412: imp->addr->csr &= ~FUNCMASK;
413: imp->state = IDLE;
414: break;
415:
416: default:
417: printf("im0int: unknown state %d\n", imp->state);
418: imreset(imp);
419: }
420: if(imdebug)
421: printf("new state=%d\n", imp->state);
422: #ifdef IMKEEPINT
423: nimi[-1].nstate = imp->state;
424: #endif
425: wakeup((caddr_t)imp);
426: }
427:
428: imreset(imp)
429: register struct im *imp;
430: {
431: register int s;
432: u_short csr;
433:
434: s = spl5();
435: if(imdebug)
436: printf("imreset: state=%d\n", imp->state);
437: if(imp->addr->csr&SRESET)
438: return;
439: imp->state = RESETTING;
440: csr = IENABLE | HINTR | HRESET | HSTRB;
441: imp->addr->csr = csr;
442: splx(s);
443: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.