|
|
1.1 root 1: /* scn.c 84/09/05 */
2:
3: #include "scn.h"
4: #if NSCN > 0
5: /*
6: * UNIBUS DR11-B driver for teletype scanner
7: *
8: */
9:
10: #include "../h/param.h"
11: #include "../h/systm.h"
12: #include "../h/cpu.h"
13: #include "../h/nexus.h"
14: #include "../h/dk.h"
15: #include "../h/buf.h"
16: #include "../h/conf.h"
17: #include "../h/dir.h"
18: #include "../h/user.h"
19: #include "../h/proc.h"
20: #include "../h/map.h"
21: #include "../h/pte.h"
22: #include "../h/mtpr.h"
23: #include "../h/vm.h"
24: #include "../h/ubavar.h"
25: #include "../h/ubareg.h"
26: #include "../h/cmap.h"
27:
28: #include "../h/scncmd.h"
29:
30: struct scndevice{
31: u_short scn_recvst; /* receive status register */
32: u_short scn_recv; /* receive data register */
33: u_short scn_sendst; /* send status register */
34: u_short scn_send; /* send data register */
35: short scnwc; /* word count reg - unused but load -1 */
36: u_short scnba; /* base address reg - must be 16k bdry */
37: u_short scncs; /* command/status reg */
38: u_short scndata; /* data reg */
39: };
40: struct scnsoftc {
41: u_short sbmode; /*select bit mode*/
42: u_short bpmode; /* bit pack mode*/
43: u_short sc_intno; /* dr11b interrupt number */
44: int scnreg; /* index into uba_map */
45: u_short scn_offset; /* offset from 16k bdry */
46: u_int sc_maxi; /* max interrupt */
47: caddr_t scnb_addr;
48: unsigned scn_bdp;
49: u_short scn_sync;
50: } scnsoftc[NSCN];
51:
52: #define SCN_GO 01
53: #define SCN_IE 0100
54: #define SCN_NEX 040000
55: #define SCN_ERROR 0100000
56:
57: #define SCNSIZE 16384
58: #define SCNPAD 16384
59: #define SCNMASK (SCNPAD-1)
60: #define SCNHSIZE 8192
61: #define SCNHREG 16
62: #define SCNREGMASK 0760
63: #define SCNREST 037777740000
64:
65: #define SCN_LADDR 037777
66: #define SCN_HADDR 074
67:
68: int scnprobe(), scnattach(), scndgo(), scnintr();
69: int scnstrategy(), scnstart();
70: u_int scnminp();
71: struct uba_ctlr *scnminfo[NSCN];
72: struct uba_device *scndinfo[NSCN];
73: struct uba_ctlr scnctlr[NSCN]; /* scminfo points to this */
74: u_short scnstd[] = { 0174020, 0};
75: struct uba_driver scndriver =
76: { scnprobe,0,scnattach,scndgo,scnstd,"scn",scndinfo,"scn",scnminfo };
77:
78: #define ui_open ui_type
79: struct buf scnbuf[NSCN];
80: struct buf scnutab[NSCN];
81:
82:
83:
84:
85: /*ARGSUSED*/
86: scnprobe(reg)
87: caddr_t reg;
88: {
89: register int br, cvec; /*int vecs at 310 & 314 */
90: register struct scndevice *scnaddr = (struct scndevice *) reg;
91: register short bucket;
92: #ifdef LINT
93: br = 0; cvec = br; br = cvec;
94: #endif
95:
96: scnaddr->scn_recvst = SCN_REC_IE;
97: scnaddr->scn_send = SCNRS_S;
98: DELAY(10000);
99: bucket = scnaddr->scn_recv;
100: scnaddr->scn_recvst = 0;
101: return(1);
102: }
103:
104: scnattach(ui)
105: register struct uba_device *ui;
106: {
107: register struct uba_ctlr *um;
108: register int unit;
109:
110: unit = ui->ui_unit;
111:
112: um = &scnctlr[unit];
113: scnminfo[unit] = um;
114: ui->ui_ctlr = unit;
115: ui->ui_mi = um;
116: um->um_driver = ui->ui_driver;
117: um->um_ctlr = unit;
118: um->um_ubanum = ui->ui_ubanum;
119: um->um_alive = 1;
120: um->um_intr = ui->ui_intr;
121: um->um_addr = ui->ui_addr;
122: um->um_hd = ui->ui_hd;
123: }
124:
125: scnopen(dev)
126: dev_t dev;
127: {
128: register int unit = minor(dev);
129: register struct scnsoftc *scnp = &scnsoftc[minor(dev)];
130: register struct uba_device *ui = scndinfo[unit];
131: register struct scndevice *draddr = (struct scndevice *)ui->ui_addr;
132:
133: if((unit >= NSCN) || (scndinfo[unit]->ui_open)) {
134: u.u_error = ENXIO;
135: return;
136: }
137: scndinfo[unit]->ui_open++;
138: draddr->scn_recvst = 0;
139: scnp->sbmode = SCN_MOD_BW;
140: scnp->bpmode = 0;
141: }
142:
143: scnclose(dev)
144: dev_t dev;
145: {
146: register int unit;
147:
148: scndinfo[minor(dev)]->ui_open = 0;
149: }
150:
151: scnread(dev)
152: dev_t dev;
153: {
154: register int unit = minor(dev);
155: physio(scnstrategy,&scnbuf[unit],dev,B_READ,scnminp);
156:
157: }
158:
159: scnwrite(dev)
160: dev_t dev;
161: {
162: register int unit = minor(dev);
163:
164: physio(scnstrategy,&scnbuf[unit],dev,B_WRITE,scnminp);
165: }
166: u_int
167: scnminp(bp)
168: struct buf *bp;
169: {
170: register struct scnsoftc *scnp;
171: scnp = &scnsoftc[minor(bp->b_dev)];
172: scnp->sc_maxi = ((bp->b_bcount - SCNPAD)/SCNHSIZE);
173: }
174:
175: /*
176: * Due to the fact the scstrategy routine is called only by scnread
177: * and scnwrite via physio, there will only be one transaction in each
178: * DR11-B's queue at any time. Therefore, one can just tack the given
179: * buffer header pointer on at the end of the queue, and call scstart.
180: */
181: scnstrategy(bp)
182: register struct buf *bp;
183: {
184: register struct uba_device *ui;
185: register struct uba_ctlr *um;
186: register struct buf *dp;
187: register int s;
188: struct scndevice *draddr;
189: dev_t unit;
190:
191:
192: unit = minor(bp->b_dev); /* chose a DR11-B */
193: ui = scndinfo[unit];
194: um = ui->ui_mi; /* get ctlr ptr */
195: dp = &scnutab[unit];
196: s = spl5();
197: dp->b_actf = bp;
198: dp->b_actl = bp;
199: bp->av_forw = NULL;
200: um->um_tab.b_actf = dp;
201: um->um_tab.b_actl = dp;
202: scnstart(um);
203: splx(s); /*dennis says this should go away*/
204: switch(tsleep((caddr_t)bp, PRIBIO+1, 20)) {
205: case TS_OK:
206: break;
207: case TS_SIG: /* not supposed to happen*/
208: case TS_TIME:
209: draddr = (struct scndevice *)um->um_addr;
210: bp->b_flags |= B_ERROR;
211: s = spl6(); /* if other goes this can to*/
212: printf("timeout calling scintr\n");
213: scnintr(unit);
214: splx(s); /*likewise this*/
215: }
216: /* splx(s); this is where dennis thinks it should be*/
217:
218: }
219:
220: scnstart(um)
221: register struct uba_ctlr *um;
222: {
223: register struct buf *bp,*dp;
224: register struct scndevice *draddr;
225: register struct scnsoftc *scnp;
226: int cmd;
227:
228: dp = um->um_tab.b_actf;
229: bp = dp->b_actf;
230: scnp = &scnsoftc[minor(bp->b_dev)];
231:
232: scnp->sc_intno = 0;
233: um->um_tab.b_active++;
234: draddr = (struct scndevice *)um->um_addr;
235: draddr->scnwc = -1;
236: if(bp->b_flags & B_READ)
237: cmd = SCN_IE;
238: else{
239: u.u_error = EFAULT;
240: }
241: um->um_cmd = cmd|SCN_GO;
242: draddr->scndata = scnp->sbmode|scnp->bpmode|SCN_ARM;
243:
244: draddr->scncs = cmd;
245: bp->b_bcount = SCNSIZE + SCNPAD;
246:
247: DELAY(10);
248: if( ubago(scndinfo[minor(bp->b_dev)])== 0)
249: printf("ubago returned 0\n");
250: }
251:
252: scndgo(um)
253: struct uba_ctlr *um;
254: {
255: register struct scndevice *draddr = (struct scndevice *)um->um_addr;
256: register unsigned addr, temp;
257: register struct scnsoftc *scnp;
258: struct buf *bp, *dp;
259:
260: dp = um->um_tab.b_actf;
261: bp = dp->b_actf;
262: scnp = &scnsoftc[minor(bp->b_dev)];
263:
264: /* temp = bp->b_un.b_addr;*/
265: addr = um->um_ubinfo;
266: addr = (addr + (SCNSIZE-1)) & ~(SCNSIZE-1);
267: /* temp = (temp + (SCNSIZE-1)) & ~(SCNSIZE-1);*/
268: scnp->scnreg = UBAI_MR(addr);
269: scnp->scn_offset = (addr - um->um_ubinfo) & (SCNSIZE-1);
270: /* add half so intr can */
271: scnp->scnb_addr = bp->b_un.b_addr + SCNHSIZE + scnp->scn_offset;
272: /*was temp*/
273: temp = UBAI_BDP(addr);
274: scnp->scn_bdp = (temp << UBAMR_DPSHIFT) | UBAMR_MRV;
275: printf("scndgo uminfo %o addr %o reg %o b_addr %o\n",um->um_ubinfo,
276: addr, scnp->scnreg,bp->b_un.b_addr);
277: printf("ba %o cs %o scnbaddr %o offset %o\n",(addr&040000),
278: (um->um_cmd|((addr>>12)&SCN_HADDR)), scnp->scnb_addr,
279: scnp->scn_offset);
280:
281: draddr->scnba = 0;
282: scnp->scn_sync = 0;
283: draddr->scncs = um->um_cmd|((addr>>12)&SCN_HADDR);
284: draddr->scn_recvst |= SCN_REC_IE;
285: draddr->scn_send = SCN_SCAN;
286: }
287:
288: scnioctl(dev, cmd, arg)
289: dev_t dev;
290: int cmd;
291: register caddr_t arg;
292: {
293: register struct scnsoftc *scnp = &scnsoftc[minor(dev)];
294: register struct uba_device *ui = scndinfo[minor(dev)];
295: register struct scndevice *draddr = (struct scndevice *)ui->ui_addr;
296: register struct uba_ctlr *um;
297: u_short realcmd;
298: u_short stat;
299: if( (cmd != SCNRECST) && (cmd != SCNREC) && (cmd != SCNSENDST)
300: & (cmd != SCNHACK)){
301: if(copyin(arg, (caddr_t)&realcmd, sizeof(realcmd))){
302: u.u_error = EFAULT;
303: return;
304: }
305: }
306: switch(cmd){
307: case SCNSENDST:
308: realcmd = draddr->scn_sendst;
309: break;
310: case SCNSEND:
311: stat = draddr->scn_sendst;
312: if(stat & SCN_SREADY)
313: draddr->scn_send = realcmd;
314: else u.u_error = EFAULT;
315: return;
316: case SCNRECST:
317: realcmd = draddr->scn_recvst;
318: break;
319: case SCNREC:
320: realcmd = draddr->scn_recv;
321: break;
322: case SCNHACK:
323: realcmd = scnp->scn_offset;
324: break;
325: case SCNSBMOD:
326: scnp->sbmode = realcmd & SCN_SBMASK;
327: return;
328: case SCNBPMOD:
329: scnp->bpmode = realcmd & SCN_BPMASK;
330: return;
331: default:
332: u.u_error = ENXIO;
333: return;
334: }
335: if(copyout((caddr_t)&realcmd, arg, sizeof(realcmd)))
336: u.u_error = EFAULT;
337: }
338: scnreset() {}
339:
340: scnxintr(dr11)
341: register dr11;
342: {
343: register struct scndevice *draddr;
344: register struct uba_ctlr *um;
345: struct buf *dp, *bp;
346: register int stat;
347: struct scnsoftc *scnp;
348:
349: um = scnminfo[dr11];
350: draddr = (struct scndevice *)um->um_addr;
351:
352: stat = draddr->scn_recv;
353: if(stat == SCN_STATE2){
354: draddr->scn_send = SCN_WAIT;
355: return;
356: }
357: if(stat == SCN_STATE3){
358: scnp = &scnsoftc[minor(dr11)];
359: printf("got ack state 3:intno %o max %o\n", scnp->sc_intno,scnp->sc_maxi);
360: dp = um->um_tab.b_actf;
361: bp= dp->b_actf;
362: draddr->scndata = 0;
363: draddr->scn_recvst = 0;
364: draddr->scncs = 0;
365: um->um_tab.b_active = 0;
366: um->um_tab.b_errcnt = 0;
367: um->um_tab.b_actf = dp->b_forw;
368: dp->b_errcnt = 0;
369: dp->b_active = 0;
370: bp->b_resid = 0;
371: ubadone(um);
372: iodone(bp);
373: return;
374: }
375: return;
376: }
377:
378: scnintr(dr11)
379: register dr11;
380: {
381: register struct buf *bp,*dp;
382: register struct scndevice *draddr;
383: register struct uba_ctlr *um;
384: register unsigned stat, reg,temp;
385: u_short bit;
386: struct pte *io, *pte;
387: struct scnsoftc *scnp;
388:
389: um = scnminfo[dr11];
390: scnp = &scnsoftc[dr11];
391:
392: if(um->um_tab.b_active == 0)
393: return;
394:
395: if(scndinfo[dr11]->ui_open == 0)
396: return;
397: dp = um->um_tab.b_actf;
398: bp = dp->b_actf;
399: draddr = (struct scndevice *)um->um_addr;
400: stat = draddr->scncs;
401: if(stat & SCN_ERROR){
402: reg = draddr->scnba;
403: printf("scanner error %o addr %o intno %d\n",stat,
404: reg,scnp->sc_intno);
405: goto scbad;
406: }
407: if(scnp->sc_intno >= scnp->sc_maxi){
408: printf("quiting on maxi %o\n",scnp->sc_intno);
409: goto scbad;
410: }
411: bit = draddr->scnba & 020000;
412: if(scnp->scn_sync == bit)
413: printf("scn out of sync %d addr=%o\n",
414: scnp->sc_intno,draddr->scnba);
415: scnp->scn_sync = bit;
416: reg = scnp->scnreg;
417: if(scnp->sc_intno++ & 01)
418: reg += SCNHREG;
419: scnp->scnb_addr += SCNHSIZE;
420:
421: stat = btop(scnp->scnb_addr);
422: pte = vtopte(bp->b_proc, stat);
423:
424: io = &um->um_hd->uh_uba->uba_map[reg];
425: stat = SCNHREG;
426: temp = scnp->scn_bdp;
427: while(stat-- > 0){
428: if(pte->pg_pfnum == 0){
429: printf("about to write to 0 pte int %o stat %d\n",
430: scnp->sc_intno,stat);
431: goto scbad;
432: }
433: *(int *)io++ = pte++->pg_pfnum | temp;
434: }
435: return;
436:
437: scbad:
438: draddr->scndata = 0; /*turn off arm bit*/
439: draddr->scn_recvst = 0; /*turn off recv intr*/
440: draddr->scncs = 0; /*turn off scn intr*/
441: um->um_tab.b_active = 0;
442: um->um_tab.b_errcnt = 0;
443: um->um_tab.b_actf = dp->b_forw;
444: dp->b_errcnt = 0;
445: dp->b_active = 0;
446: bp->b_resid = 0;
447: ubadone(um);
448: iodone(bp);
449:
450: }
451: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.