Annotation of researchv8dc/sys/dev/scn.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.