|
|
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.