Annotation of 42BSD/sys/vaxuba/uda.c, revision 1.1.1.1

1.1       root        1: /*     uda.c   6.1     83/07/29        */
                      2: 
                      3: #include "ra.h"
                      4: #if NUDA > 0
                      5: /*
                      6:  * UDA50/RAxx disk device driver
                      7:  *
                      8:  * Restrictions:
                      9:  *     Unit numbers must be less than 8.
                     10:  *
                     11:  * TO DO:
                     12:  *     write dump code
                     13:  */
                     14: #include "../machine/pte.h"
                     15: 
                     16: #include "../h/param.h"
                     17: #include "../h/systm.h"
                     18: #include "../h/buf.h"
                     19: #include "../h/conf.h"
                     20: #include "../h/dir.h"
                     21: #include "../h/user.h"
                     22: #include "../h/map.h"
                     23: #include "../h/vm.h"
                     24: #include "../h/dk.h"
                     25: #include "../h/cmap.h"
                     26: #include "../h/uio.h"
                     27: 
                     28: #include "../vax/cpu.h"
                     29: #include "../vaxuba/ubareg.h"
                     30: #include "../vaxuba/ubavar.h"
                     31: 
                     32: #define        NRSPL2  3               /* log2 number of response packets */
                     33: #define        NCMDL2  3               /* log2 number of command packets */
                     34: #define        NRSP    (1<<NRSPL2)
                     35: #define        NCMD    (1<<NCMDL2)
                     36: 
                     37: #include "../vaxuba/udareg.h"
                     38: #include "../vax/mscp.h"
                     39: 
                     40: struct uda_softc {
                     41:        short   sc_state;       /* state of controller */
                     42:        short   sc_mapped;      /* Unibus map allocated for uda struct? */
                     43:        int     sc_ubainfo;     /* Unibus mapping info */
                     44:        struct uda *sc_uda;     /* Unibus address of uda struct */
                     45:        int     sc_ivec;        /* interrupt vector address */
                     46:        short   sc_credits;     /* transfer credits */
                     47:        short   sc_lastcmd;     /* pointer into command ring */
                     48:        short   sc_lastrsp;     /* pointer into response ring */
                     49: } uda_softc[NUDA];
                     50: 
                     51: /*
                     52:  * Controller states
                     53:  */
                     54: #define        S_IDLE  0               /* hasn't been initialized */
                     55: #define        S_STEP1 1               /* doing step 1 init */
                     56: #define        S_STEP2 2               /* doing step 2 init */
                     57: #define        S_STEP3 3               /* doing step 3 init */
                     58: #define        S_SCHAR 4               /* doing "set controller characteristics" */
                     59: #define        S_RUN   5               /* running */
                     60: 
                     61: struct uda {
                     62:        struct udaca    uda_ca;         /* communications area */
                     63:        struct mscp     uda_rsp[NRSP];  /* response packets */
                     64:        struct mscp     uda_cmd[NCMD];  /* command packets */
                     65: } uda[NUDA];
                     66: 
                     67: /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
                     68: struct size {
                     69:        daddr_t nblocks;
                     70:        daddr_t blkoff;
                     71: } ra_sizes[8] ={
                     72:        15884,  0,              /* A=blk 0 thru 15883 */
                     73:        33440,  15884,          /* B=blk 15884 thru 49323 */
                     74:        -1,     0,              /* C=blk 0 thru end */
                     75:        15884,  340670,         /* D=blk 340670 thru 356553 */
                     76:        55936,  356554,         /* E=blk 356554 thru 412489 */
                     77:        -1,     412490,         /* F=blk 412490 thru end */
                     78:        82080,  49324,          /* G=blk 49324 thru 131403 */
                     79:        -1,     131404,         /* H=blk 131404 thru end */
                     80: };
                     81: /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
                     82: 
                     83: int    udaerror = 0;                   /* causes hex dump of packets */
                     84: int    udadebug = 0;
                     85: #define        printd  if (udadebug) printf
                     86: 
                     87: daddr_t        radsize[NRA];                   /* disk size, from ONLINE end packet */
                     88: 
                     89: int    udprobe(), udslave(), udattach(), udintr();
                     90: struct mscp *udgetcp();
                     91: struct uba_ctlr *udminfo[NUDA];
                     92: struct uba_device *uddinfo[NRA];
                     93: struct uba_device *udip[NUDA][8];      /* 8 == max number of drives */
                     94: 
                     95: u_short        udstd[] = { 0772150, 0772550, 0777550, 0 };
                     96: struct uba_driver udadriver =
                     97:  { udprobe, udslave, udattach, 0, udstd, "ra", uddinfo, "uda", udminfo, 0 };
                     98: struct buf rudbuf[NRA];
                     99: struct buf udutab[NRA];
                    100: struct buf udwtab[NUDA];               /* I/O wait queue, per controller */
                    101: 
                    102: #define        b_qsize         b_resid         /* queue size per drive, in udutab */
                    103: #define        b_ubinfo        b_resid         /* Unibus mapping info, per buffer */
                    104: 
                    105: udprobe(reg, ctlr)
                    106:        caddr_t reg;
                    107:        int ctlr;
                    108: {
                    109:        register int br, cvec;
                    110:        register struct uda_softc *sc = &uda_softc[ctlr];
                    111: 
                    112: #ifdef lint
                    113:        br = 0; cvec = br; br = cvec; reg = reg;
                    114:        udreset(0); udintr(0);
                    115: #endif
                    116:        /* SHOULD CHECK THAT IT REALLY IS A UDA */
                    117:        br = 0x15;
                    118:        cvec = sc->sc_ivec = (uba_hd[numuba].uh_lastiv -= 4);
                    119:        return(sizeof (struct udadevice));
                    120: }
                    121: 
                    122: udslave(ui, reg)
                    123:        struct uba_device *ui;
                    124:        caddr_t reg;
                    125: {
                    126:        /*
                    127:         * TOO HARD TO FIND OUT IF DISK IS THERE UNTIL
                    128:         * INITIALIZED.  WE'LL FIND OUT WHEN WE FIRST
                    129:         * TRY TO ACCESS IT.
                    130:         */
                    131: #ifdef lint
                    132:        ui = ui; reg = reg;
                    133: #endif
                    134:        return(1);
                    135: }
                    136: 
                    137: udattach(ui)
                    138:        register struct uba_device *ui;
                    139: {
                    140: 
                    141:        if (ui->ui_dk >= 0)
                    142:                dk_mspw[ui->ui_dk] = 1.0 / (60 * 31 * 256);     /* approx */
                    143:        ui->ui_flags = 0;
                    144:        udip[ui->ui_ctlr][ui->ui_slave] = ui;
                    145:        radsize[ui->ui_unit] = (daddr_t)0xffffff;       /* max possible size */
                    146: }
                    147: 
                    148: /*
                    149:  * Open a UDA.  Initialize the device and
                    150:  * set the unit online.
                    151:  */
                    152: udopen(dev, flag)
                    153:        dev_t dev;
                    154:        int flag;
                    155: {
                    156:        register int unit;
                    157:        register struct uba_device *ui;
                    158:        register struct uda_softc *sc;
                    159:        int s;
                    160: 
                    161: #ifdef lint
                    162:        flag = flag;
                    163: #endif
                    164:        unit = minor(dev) >> 3;
                    165:        if (unit >= NRA || (ui = uddinfo[unit]) == 0 || ui->ui_alive == 0)
                    166:                return (ENXIO);
                    167:        sc = &uda_softc[ui->ui_ctlr];
                    168:        s = spl5();
                    169:        if (sc->sc_state != S_RUN) {
                    170:                if (sc->sc_state == S_IDLE)
                    171:                        udinit(ui->ui_ctlr);
                    172:                /* wait for initialization to complete */
                    173:                sleep((caddr_t)ui->ui_mi, 0);
                    174:                if (sc->sc_state != S_RUN)
                    175:                        return (EIO);
                    176:        }
                    177:        splx(s);
                    178:        /* SHOULD PROBABLY FORCE AN ONLINE ATTEMPT
                    179:           TO SEE IF DISK IS REALLY THERE */
                    180:        return (0);
                    181: }
                    182: 
                    183: /*
                    184:  * Initialize a UDA.  Set up UBA mapping registers,
                    185:  * initialize data structures, and start hardware
                    186:  * initialization sequence.
                    187:  */
                    188: udinit(d)
                    189:        int d;
                    190: {
                    191:        register struct uda_softc *sc;
                    192:        register struct uda *ud;
                    193:        struct udadevice *udaddr;
                    194:        struct uba_ctlr *um;
                    195: 
                    196:        sc = &uda_softc[d];
                    197:        um = udminfo[d];
                    198:        um->um_tab.b_active++;
                    199:        ud = &uda[d];
                    200:        udaddr = (struct udadevice *)um->um_addr;
                    201:        if (sc->sc_mapped == 0) {
                    202:                /*
                    203:                 * Map the communications area and command
                    204:                 * and response packets into Unibus address
                    205:                 * space.
                    206:                 */
                    207:                sc->sc_ubainfo = uballoc(um->um_ubanum, (caddr_t)ud,
                    208:                    sizeof (struct uda), 0);
                    209:                sc->sc_uda = (struct uda *)(sc->sc_ubainfo & 0x3ffff);
                    210:                sc->sc_mapped = 1;
                    211:        }
                    212: 
                    213:        /*
                    214:         * Start the hardware initialization sequence.
                    215:         */
                    216:        udaddr->udaip = 0;              /* start initialization */
                    217:        while ((udaddr->udasa & UDA_STEP1) == 0)
                    218:                ;
                    219:        udaddr->udasa = UDA_ERR|(NCMDL2<<11)|(NRSPL2<<8)|UDA_IE|(sc->sc_ivec/4);
                    220:        /*
                    221:         * Initialization continues in interrupt routine.
                    222:         */
                    223:        sc->sc_state = S_STEP1;
                    224:        sc->sc_credits = 0;
                    225: }
                    226: 
                    227: udstrategy(bp)
                    228:        register struct buf *bp;
                    229: {
                    230:        register struct uba_device *ui;
                    231:        register struct uba_ctlr *um;
                    232:        register struct buf *dp;
                    233:        register int unit;
                    234:        int xunit = minor(bp->b_dev) & 07;
                    235:        daddr_t sz, maxsz;
                    236:        int s;
                    237: 
                    238:        sz = (bp->b_bcount+511) >> 9;
                    239:        unit = dkunit(bp);
                    240:        if (unit >= NRA)
                    241:                goto bad;
                    242:        ui = uddinfo[unit];
                    243:        um = ui->ui_mi;
                    244:        if (ui == 0 || ui->ui_alive == 0)
                    245:                goto bad;
                    246:        if ((maxsz = ra_sizes[xunit].nblocks) < 0)
                    247:                maxsz = radsize[unit] - ra_sizes[xunit].blkoff;
                    248:        if (bp->b_blkno < 0 || bp->b_blkno+sz > maxsz ||
                    249:            ra_sizes[xunit].blkoff >= radsize[unit])
                    250:                goto bad;
                    251:        s = spl5();
                    252:        /*
                    253:         * Link the buffer onto the drive queue
                    254:         */
                    255:        dp = &udutab[ui->ui_unit];
                    256:        if (dp->b_actf == 0)
                    257:                dp->b_actf = bp;
                    258:        else
                    259:                dp->b_actl->av_forw = bp;
                    260:        dp->b_actl = bp;
                    261:        bp->av_forw = 0;
                    262:        /*
                    263:         * Link the drive onto the controller queue
                    264:         */
                    265:        if (dp->b_active == 0) {
                    266:                dp->b_forw = NULL;
                    267:                if (um->um_tab.b_actf == NULL)
                    268:                        um->um_tab.b_actf = dp;
                    269:                else
                    270:                        um->um_tab.b_actl->b_forw = dp;
                    271:                um->um_tab.b_actl = dp;
                    272:                dp->b_active = 1;
                    273:        }
                    274:        if (um->um_tab.b_active == 0) {
                    275: #if defined(VAX750)
                    276:                if (cpu == VAX_750
                    277:                    && udwtab[um->um_ctlr].av_forw == &udwtab[um->um_ctlr]) {
                    278:                        if (um->um_ubinfo != 0)
                    279:                                printf("udastrat: ubinfo 0x%x\n",um->um_ubinfo);
                    280:                        else
                    281:                                um->um_ubinfo =
                    282:                                   uballoc(um->um_ubanum, (caddr_t)0, 0,
                    283:                                        UBA_NEEDBDP);
                    284:                }
                    285: #endif
                    286:                (void) udstart(um);
                    287:        }
                    288:        splx(s);
                    289:        return;
                    290: 
                    291: bad:
                    292:        bp->b_flags |= B_ERROR;
                    293:        iodone(bp);
                    294:        return;
                    295: }
                    296: 
                    297: udstart(um)
                    298:        register struct uba_ctlr *um;
                    299: {
                    300:        register struct buf *bp, *dp;
                    301:        register struct mscp *mp;
                    302:        register struct uda_softc *sc;
                    303:        register struct uba_device *ui;
                    304:        struct udadevice *udaddr;
                    305:        int i;
                    306: 
                    307:        sc = &uda_softc[um->um_ctlr];
                    308:        
                    309: loop:
                    310:        if ((dp = um->um_tab.b_actf) == NULL) {
                    311:                /*
                    312:                 * Release uneeded UBA resources and return
                    313:                 */
                    314:                um->um_tab.b_active = 0;
                    315:                return (0);
                    316:        }
                    317:        if ((bp = dp->b_actf) == NULL) {
                    318:                /*
                    319:                 * No more requests for this drive, remove
                    320:                 * from controller queue and look at next drive.
                    321:                 * We know we're at the head of the controller queue.
                    322:                 */
                    323:                dp->b_active = 0;
                    324:                um->um_tab.b_actf = dp->b_forw;
                    325:                goto loop;
                    326:        }
                    327:        um->um_tab.b_active++;
                    328:        udaddr = (struct udadevice *)um->um_addr;
                    329:        if ((udaddr->udasa&UDA_ERR) || sc->sc_state != S_RUN) {
                    330:                harderr(bp, "ra");
                    331:                printf("udasa %o, state %d\n", udaddr->udasa&0xffff, sc->sc_state);
                    332:                udinit(um->um_ctlr);
                    333:                /* SHOULD REQUEUE OUTSTANDING REQUESTS, LIKE UDRESET */
                    334:                return (0);
                    335:        }
                    336:        ui = uddinfo[dkunit(bp)];
                    337:        /*
                    338:         * If no credits, can't issue any commands
                    339:         * until some outstanding commands complete.
                    340:         */
                    341:        if (sc->sc_credits < 2)
                    342:                return (0);
                    343:        if ((mp = udgetcp(um)) == NULL)
                    344:                return (0);
                    345:        sc->sc_credits--;       /* committed to issuing a command */
                    346:        if (ui->ui_flags == 0) {        /* not online */
                    347:                mp->mscp_opcode = M_OP_ONLIN;
                    348:                mp->mscp_unit = ui->ui_slave;
                    349:                dp->b_active = 2;
                    350:                um->um_tab.b_actf = dp->b_forw; /* remove from controller q */
                    351:                printd("uda: bring unit %d online\n", ui->ui_slave);
                    352:                *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT;
                    353:                i = udaddr->udaip;
                    354:                goto loop;
                    355:        }
                    356:        switch (cpu) {
                    357:        case VAX_780:
                    358:                i = UBA_NEEDBDP|UBA_CANTWAIT;
                    359:                break;
                    360: 
                    361:        case VAX_750:
                    362:                i = um->um_ubinfo|UBA_HAVEBDP|UBA_CANTWAIT;
                    363:                break;
                    364: 
                    365:        case VAX_730:
                    366:                i = UBA_CANTWAIT;
                    367:                break;
                    368:        }
                    369:        if ((i = ubasetup(um->um_ubanum, bp, i)) == 0) {
                    370:                mp->mscp_opcode = M_OP_GTUNT;
                    371:                mp->mscp_unit = ui->ui_slave;
                    372:                *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT;
                    373:                i = udaddr->udaip;      /* initiate polling */
                    374:                return(1);              /* wait for interrupt */
                    375:        }
                    376:        mp->mscp_cmdref = (long)bp;     /* pointer to get back */
                    377:        mp->mscp_opcode = bp->b_flags&B_READ ? M_OP_READ : M_OP_WRITE;
                    378:        mp->mscp_unit = ui->ui_slave;
                    379:        mp->mscp_lbn = bp->b_blkno + ra_sizes[minor(bp->b_dev)&7].blkoff;
                    380:        mp->mscp_bytecnt = bp->b_bcount;
                    381:        mp->mscp_buffer = (i & 0x3ffff) | (((i>>28)&0xf)<<24);
                    382: #if defined(VAX750)
                    383:        if (cpu == VAX_750)
                    384:                i &= 0xfffffff;         /* mask off bdp */
                    385: #endif
                    386:        bp->b_ubinfo = i;               /* save mapping info */
                    387:        *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT;
                    388:        i = udaddr->udaip;              /* initiate polling */
                    389:        if (ui->ui_dk >= 0) {
                    390:                dk_busy |= 1<<ui->ui_dk;
                    391:                dp->b_qsize++;
                    392:                dk_xfer[ui->ui_dk]++;
                    393:                dk_wds[ui->ui_dk] += bp->b_bcount>>6;
                    394:        }
                    395: 
                    396:        /*
                    397:         * Move drive to the end of the controller queue
                    398:         */
                    399:        if (dp->b_forw != NULL) {
                    400:                um->um_tab.b_actf = dp->b_forw;
                    401:                um->um_tab.b_actl->b_forw = dp;
                    402:                um->um_tab.b_actl = dp;
                    403:                dp->b_forw = NULL;
                    404:        }
                    405:        /*
                    406:         * Move buffer to I/O wait queue
                    407:         */
                    408:        dp->b_actf = bp->av_forw;
                    409:        dp = &udwtab[um->um_ctlr];
                    410:        bp->av_forw = dp;
                    411:        bp->av_back = dp->av_back;
                    412:        dp->av_back->av_forw = bp;
                    413:        dp->av_back = bp;
                    414:        goto loop;
                    415: }
                    416: 
                    417: /*
                    418:  * UDA interrupt routine.
                    419:  */
                    420: udintr(d)
                    421:        int d;
                    422: {
                    423:        register struct uba_ctlr *um = udminfo[d];
                    424:        register struct udadevice *udaddr = (struct udadevice *)um->um_addr;
                    425:        struct buf *bp;
                    426:        register int i;
                    427:        register struct uda_softc *sc = &uda_softc[d];
                    428:        register struct uda *ud = &uda[d];
                    429:        struct uda *uud;
                    430:        struct mscp *mp;
                    431: 
                    432:        printd("udintr: state %d, udasa %o\n", sc->sc_state, udaddr->udasa);
                    433:        switch (sc->sc_state) {
                    434:        case S_IDLE:
                    435:                printf("uda%d: random interrupt ignored\n", d);
                    436:                return;
                    437: 
                    438:        case S_STEP1:
                    439: #define        STEP1MASK       0174377
                    440: #define        STEP1GOOD       (UDA_STEP2|UDA_IE|(NCMDL2<<3)|NRSPL2)
                    441:                if ((udaddr->udasa&STEP1MASK) != STEP1GOOD) {
                    442:                        sc->sc_state = S_IDLE;
                    443:                        wakeup((caddr_t)um);
                    444:                        return;
                    445:                }
                    446:                udaddr->udasa = ((int)&sc->sc_uda->uda_ca.ca_ringbase)|
                    447:                    (cpu == VAX_780 ? UDA_PI : 0);
                    448:                sc->sc_state = S_STEP2;
                    449:                return;
                    450: 
                    451:        case S_STEP2:
                    452: #define        STEP2MASK       0174377
                    453: #define        STEP2GOOD       (UDA_STEP3|UDA_IE|(sc->sc_ivec/4))
                    454:                if ((udaddr->udasa&STEP2MASK) != STEP2GOOD) {
                    455:                        sc->sc_state = S_IDLE;
                    456:                        wakeup((caddr_t)um);
                    457:                        return;
                    458:                }
                    459:                udaddr->udasa = ((int)&sc->sc_uda->uda_ca.ca_ringbase)>>16;
                    460:                sc->sc_state = S_STEP3;
                    461:                return;
                    462: 
                    463:        case S_STEP3:
                    464: #define        STEP3MASK       0174000
                    465: #define        STEP3GOOD       UDA_STEP4
                    466:                if ((udaddr->udasa&STEP3MASK) != STEP3GOOD) {
                    467:                        sc->sc_state = S_IDLE;
                    468:                        wakeup((caddr_t)um);
                    469:                        return;
                    470:                }
                    471:                udaddr->udasa = UDA_GO;
                    472:                sc->sc_state = S_SCHAR;
                    473: 
                    474:                /*
                    475:                 * Initialize the data structures.
                    476:                 */
                    477:                uud = sc->sc_uda;
                    478:                for (i = 0; i < NRSP; i++) {
                    479:                        ud->uda_ca.ca_rspdsc[i] = UDA_OWN|UDA_INT|
                    480:                                (long)&uud->uda_rsp[i].mscp_cmdref;
                    481:                        ud->uda_rsp[i].mscp_dscptr = &ud->uda_ca.ca_rspdsc[i];
                    482:                        ud->uda_rsp[i].mscp_header.uda_msglen = sizeof (struct mscp);
                    483:                }
                    484:                for (i = 0; i < NCMD; i++) {
                    485:                        ud->uda_ca.ca_cmddsc[i] = UDA_INT|
                    486:                                (long)&uud->uda_cmd[i].mscp_cmdref;
                    487:                        ud->uda_cmd[i].mscp_dscptr = &ud->uda_ca.ca_cmddsc[i];
                    488:                        ud->uda_cmd[i].mscp_header.uda_msglen = sizeof (struct mscp);
                    489:                }
                    490:                bp = &udwtab[d];
                    491:                bp->av_forw = bp->av_back = bp;
                    492:                sc->sc_lastcmd = 0;
                    493:                sc->sc_lastrsp = 0;
                    494:                if ((mp = udgetcp(um)) == NULL) {
                    495:                        sc->sc_state = S_IDLE;
                    496:                        wakeup((caddr_t)um);
                    497:                        return;
                    498:                }
                    499:                mp->mscp_opcode = M_OP_STCON;
                    500:                mp->mscp_cntflgs = M_CF_ATTN|M_CF_MISC|M_CF_THIS;
                    501:                *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT;
                    502:                i = udaddr->udaip;      /* initiate polling */
                    503:                return;
                    504: 
                    505:        case S_SCHAR:
                    506:        case S_RUN:
                    507:                break;
                    508: 
                    509:        default:
                    510:                printf("uda%d: interrupt in unknown state %d ignored\n",
                    511:                        d, sc->sc_state);
                    512:                return;
                    513:        }
                    514: 
                    515:        if (udaddr->udasa&UDA_ERR) {
                    516:                printf("uda%d: fatal error (%o)\n", d, udaddr->udasa&0xffff);
                    517:                udaddr->udaip = 0;
                    518:                wakeup((caddr_t)um);
                    519:        }
                    520: 
                    521:        /*
                    522:         * Check for a buffer purge request.
                    523:         */
                    524:        if (ud->uda_ca.ca_bdp) {
                    525:                /*
                    526:                 * THIS IS A KLUDGE.
                    527:                 * Maybe we should change the entire
                    528:                 * UBA interface structure.
                    529:                 */
                    530:                int s = spl7();
                    531: 
                    532:                i = um->um_ubinfo;
                    533:                printd("uda: purge bdp %d\n", ud->uda_ca.ca_bdp);
                    534:                um->um_ubinfo = ud->uda_ca.ca_bdp<<28;
                    535:                ubapurge(um);
                    536:                um->um_ubinfo = i;
                    537:                (void) splx(s);
                    538:                ud->uda_ca.ca_bdp = 0;
                    539:                udaddr->udasa = 0;      /* signal purge complete */
                    540:        }
                    541: 
                    542:        /*
                    543:         * Check for response ring transition.
                    544:         */
                    545:        if (ud->uda_ca.ca_rspint) {
                    546:                ud->uda_ca.ca_rspint = 0;
                    547:                for (i = sc->sc_lastrsp;; i++) {
                    548:                        i %= NRSP;
                    549:                        if (ud->uda_ca.ca_rspdsc[i]&UDA_OWN)
                    550:                                break;
                    551:                        udrsp(um, ud, sc, i);
                    552:                        ud->uda_ca.ca_rspdsc[i] |= UDA_OWN;
                    553:                }
                    554:                sc->sc_lastrsp = i;
                    555:        }
                    556: 
                    557:        /*
                    558:         * Check for command ring transition.
                    559:         */
                    560:        if (ud->uda_ca.ca_cmdint) {
                    561:                printd("uda: command ring transition\n");
                    562:                ud->uda_ca.ca_cmdint = 0;
                    563:        }
                    564:        (void) udstart(um);
                    565: }
                    566: 
                    567: /*
                    568:  * Process a response packet
                    569:  */
                    570: udrsp(um, ud, sc, i)
                    571:        register struct uba_ctlr *um;
                    572:        register struct uda *ud;
                    573:        register struct uda_softc *sc;
                    574:        int i;
                    575: {
                    576:        register struct mscp *mp;
                    577:        struct uba_device *ui;
                    578:        struct buf *dp, *bp;
                    579:        int st;
                    580: 
                    581:        mp = &ud->uda_rsp[i];
                    582:        mp->mscp_header.uda_msglen = sizeof (struct mscp);
                    583:        sc->sc_credits += mp->mscp_header.uda_credits & 0xf;
                    584:        if ((mp->mscp_header.uda_credits & 0xf0) > 0x10)
                    585:                return;
                    586:        /*
                    587:         * If it's an error log message (datagram),
                    588:         * pass it on for more extensive processing.
                    589:         */
                    590:        if ((mp->mscp_header.uda_credits & 0xf0) == 0x10) {
                    591:                uderror(um, (struct mslg *)mp);
                    592:                return;
                    593:        }
                    594:        if (mp->mscp_unit >= 8)
                    595:                return;
                    596:        if ((ui = udip[um->um_ctlr][mp->mscp_unit]) == 0)
                    597:                return;
                    598:        st = mp->mscp_status&M_ST_MASK;
                    599:        switch (mp->mscp_opcode) {
                    600:        case M_OP_STCON|M_OP_END:
                    601:                if (st == M_ST_SUCC)
                    602:                        sc->sc_state = S_RUN;
                    603:                else
                    604:                        sc->sc_state = S_IDLE;
                    605:                um->um_tab.b_active = 0;
                    606:                wakeup((caddr_t)um);
                    607:                break;
                    608: 
                    609:        case M_OP_ONLIN|M_OP_END:
                    610:                /*
                    611:                 * Link the drive onto the controller queue
                    612:                 */
                    613:                dp = &udutab[ui->ui_unit];
                    614:                dp->b_forw = NULL;
                    615:                if (um->um_tab.b_actf == NULL)
                    616:                        um->um_tab.b_actf = dp;
                    617:                else
                    618:                        um->um_tab.b_actl->b_forw = dp;
                    619:                um->um_tab.b_actl = dp;
                    620:                if (st == M_ST_SUCC) {
                    621:                        ui->ui_flags = 1;       /* mark it online */
                    622:                        radsize[ui->ui_unit] = (daddr_t)mp->mscp_untsize;
                    623:                        printd("uda: unit %d online\n", mp->mscp_unit);
                    624: #ifdef notdef
                    625:                        printf("uda%d: online, size=%d\n",
                    626:                              mp->mscp_unit, (daddr_t)mp->mscp_untsize);
                    627: #endif
                    628:                } else {
                    629:                        harderr(dp->b_actf, "ra");
                    630:                        printf("OFFLINE\n");
                    631:                        while (bp = dp->b_actf) {
                    632:                                dp->b_actf = bp->av_forw;
                    633:                                bp->b_flags |= B_ERROR;
                    634:                                iodone(bp);
                    635:                        }
                    636:                }
                    637:                dp->b_active = 1;
                    638:                break;
                    639: 
                    640:        case M_OP_AVATN:
                    641:                printd("uda: unit %d attention\n", mp->mscp_unit);
                    642:                ui->ui_flags = 0;       /* it went offline and we didn't notice */
                    643:                break;
                    644: 
                    645:        case M_OP_READ|M_OP_END:
                    646:        case M_OP_WRITE|M_OP_END:
                    647:                bp = (struct buf *)mp->mscp_cmdref;
                    648:                ubarelse(um->um_ubanum, (int *)&bp->b_ubinfo);
                    649:                /*
                    650:                 * Unlink buffer from I/O wait queue.
                    651:                 */
                    652:                bp->av_back->av_forw = bp->av_forw;
                    653:                bp->av_forw->av_back = bp->av_back;
                    654: #if defined(VAX750)
                    655:                if (cpu == VAX_750
                    656:                    && udwtab[um->um_ctlr].av_forw == &udwtab[um->um_ctlr]) {
                    657:                        if (um->um_ubinfo == 0)
                    658:                                printf("udintr: um_ubinfo == 0\n");
                    659:                        else
                    660:                                ubarelse(um->um_ubanum, &um->um_ubinfo);
                    661:                }
                    662: #endif
                    663:                dp = &udutab[ui->ui_unit];
                    664:                if (ui->ui_dk >= 0)
                    665:                        if (--dp->b_qsize == 0)
                    666:                                dk_busy &= ~(1<<ui->ui_dk);
                    667:                if (st == M_ST_OFFLN || st == M_ST_AVLBL) {
                    668:                        ui->ui_flags = 0;       /* mark unit offline */
                    669:                        /*
                    670:                         * Link the buffer onto the front of the drive queue
                    671:                         */
                    672:                        if ((bp->av_forw = dp->b_actf) == 0)
                    673:                                dp->b_actl = bp;
                    674:                        dp->b_actf = bp;
                    675:                        /*
                    676:                         * Link the drive onto the controller queue
                    677:                         */
                    678:                        if (dp->b_active == 0) {
                    679:                                dp->b_forw = NULL;
                    680:                                if (um->um_tab.b_actf == NULL)
                    681:                                        um->um_tab.b_actf = dp;
                    682:                                else
                    683:                                        um->um_tab.b_actl->b_forw = dp;
                    684:                                um->um_tab.b_actl = dp;
                    685:                                dp->b_active = 1;
                    686:                        }
                    687: #if defined(VAX750)
                    688:                        if (cpu == VAX750 && um->um_ubinfo == 0)
                    689:                                um->um_ubinfo =
                    690:                                   uballoc(um->um_ubanum, (caddr_t)0, 0,
                    691:                                        UBA_NEEDBDP);
                    692: #endif
                    693:                        return;
                    694:                }
                    695:                if (st != M_ST_SUCC) {
                    696:                        harderr(bp, "ra");
                    697:                        printf("status %o\n", mp->mscp_status);
                    698:                        bp->b_flags |= B_ERROR;
                    699:                }
                    700:                bp->b_resid = bp->b_bcount - mp->mscp_bytecnt;
                    701:                iodone(bp);
                    702:                break;
                    703: 
                    704:        case M_OP_GTUNT|M_OP_END:
                    705:                break;
                    706: 
                    707:        default:
                    708:                printf("uda: unknown packet\n");
                    709:        }
                    710: }
                    711: 
                    712: 
                    713: /*
                    714:  * Process an error log message
                    715:  *
                    716:  * For now, just log the error on the console.
                    717:  * Only minimal decoding is done, only "useful"
                    718:  * information is printed.  Eventually should
                    719:  * send message to an error logger.
                    720:  */
                    721: uderror(um, mp)
                    722:        register struct uba_ctlr *um;
                    723:        register struct mslg *mp;
                    724: {
                    725:        printf("uda%d: %s error, ", um->um_ctlr,
                    726:                mp->mslg_flags&M_LF_SUCC ? "soft" : "hard");
                    727:        switch (mp->mslg_format) {
                    728:        case M_FM_CNTERR:
                    729:                printf("controller error, event 0%o\n", mp->mslg_event);
                    730:                break;
                    731: 
                    732:        case M_FM_BUSADDR:
                    733:                printf("host memory access error, event 0%o, addr 0%o\n",
                    734:                        mp->mslg_event, mp->mslg_busaddr);
                    735:                break;
                    736: 
                    737:        case M_FM_DISKTRN:
                    738:                printf("disk transfer error, unit %d, grp 0x%x, hdr 0x%x\n",
                    739:                        mp->mslg_unit, mp->mslg_group, mp->mslg_hdr);
                    740:                break;
                    741: 
                    742:        case M_FM_SDI:
                    743:                printf("SDI error, unit %d, event 0%o, hdr 0x%x\n",
                    744:                        mp->mslg_unit, mp->mslg_event, mp->mslg_hdr);
                    745:                break;
                    746: 
                    747:        case M_FM_SMLDSK:
                    748:                printf("small disk error, unit %d, event 0%o, cyl %d\n",
                    749:                        mp->mslg_unit, mp->mslg_event, mp->mslg_sdecyl);
                    750:                break;
                    751: 
                    752:        default:
                    753:                printf("unknown error, unit %d, format 0%o, event 0%o\n",
                    754:                        mp->mslg_unit, mp->mslg_format, mp->mslg_event);
                    755:        }
                    756: 
                    757:        if (udaerror) {
                    758:                register long *p = (long *)mp;
                    759:                register int i;
                    760: 
                    761:                for (i = 0; i < mp->mslg_header.uda_msglen; i += sizeof(*p))
                    762:                        printf("%x ", *p++);
                    763:                printf("\n");
                    764:        }
                    765: }
                    766: 
                    767: 
                    768: /*
                    769:  * Find an unused command packet
                    770:  */
                    771: struct mscp *
                    772: udgetcp(um)
                    773:        struct uba_ctlr *um;
                    774: {
                    775:        register struct mscp *mp;
                    776:        register struct udaca *cp;
                    777:        register struct uda_softc *sc;
                    778:        register int i;
                    779: 
                    780:        cp = &uda[um->um_ctlr].uda_ca;
                    781:        sc = &uda_softc[um->um_ctlr];
                    782:        i = sc->sc_lastcmd;
                    783:        if ((cp->ca_cmddsc[i] & (UDA_OWN|UDA_INT)) == UDA_INT) {
                    784:                cp->ca_cmddsc[i] &= ~UDA_INT;
                    785:                mp = &uda[um->um_ctlr].uda_cmd[i];
                    786:                mp->mscp_unit = mp->mscp_modifier = 0;
                    787:                mp->mscp_opcode = mp->mscp_flags = 0;
                    788:                mp->mscp_bytecnt = mp->mscp_buffer = 0;
                    789:                mp->mscp_errlgfl = mp->mscp_copyspd = 0;
                    790:                sc->sc_lastcmd = (i + 1) % NCMD;
                    791:                return(mp);
                    792:        }
                    793:        return(NULL);
                    794: }
                    795: 
                    796: udread(dev, uio)
                    797:        dev_t dev;
                    798:        struct uio *uio;
                    799: {
                    800:        register int unit = minor(dev) >> 3;
                    801: 
                    802:        if (unit >= NRA)
                    803:                return (ENXIO);
                    804:        return (physio(udstrategy, &rudbuf[unit], dev, B_READ, minphys, uio));
                    805: }
                    806: 
                    807: udwrite(dev, uio)
                    808:        dev_t dev;
                    809:        struct uio *uio;
                    810: {
                    811:        register int unit = minor(dev) >> 3;
                    812: 
                    813:        if (unit >= NRA)
                    814:                return (ENXIO);
                    815:        return (physio(udstrategy, &rudbuf[unit], dev, B_WRITE, minphys, uio));
                    816: }
                    817: 
                    818: udreset(uban)
                    819:        int uban;
                    820: {
                    821:        register struct uba_ctlr *um;
                    822:        register struct uba_device *ui;
                    823:        register struct buf *bp, *dp;
                    824:        register int unit;
                    825:        struct buf *nbp;
                    826:        int d;
                    827: 
                    828:        for (d = 0; d < NUDA; d++) {
                    829:                if ((um = udminfo[d]) == 0 || um->um_ubanum != uban ||
                    830:                    um->um_alive == 0)
                    831:                        continue;
                    832:                printf(" uda%d", d);
                    833:                um->um_tab.b_active = 0;
                    834:                um->um_tab.b_actf = um->um_tab.b_actl = 0;
                    835:                uda_softc[d].sc_state = S_IDLE;
                    836:                for (unit = 0; unit < NRA; unit++) {
                    837:                        if ((ui = uddinfo[unit]) == 0)
                    838:                                continue;
                    839:                        if (ui->ui_alive == 0 || ui->ui_mi != um)
                    840:                                continue;
                    841:                        udutab[unit].b_active = 0;
                    842:                        udutab[unit].b_qsize = 0;
                    843:                }
                    844:                for (bp = udwtab[d].av_forw; bp != &udwtab[d]; bp = nbp) {
                    845:                        nbp = bp->av_forw;
                    846:                        bp->b_ubinfo = 0;
                    847:                        /*
                    848:                         * Link the buffer onto the drive queue
                    849:                         */
                    850:                        dp = &udutab[dkunit(bp)];
                    851:                        if (dp->b_actf == 0)
                    852:                                dp->b_actf = bp;
                    853:                        else
                    854:                                dp->b_actl->av_forw = bp;
                    855:                        dp->b_actl = bp;
                    856:                        bp->av_forw = 0;
                    857:                        /*
                    858:                         * Link the drive onto the controller queue
                    859:                         */
                    860:                        if (dp->b_active == 0) {
                    861:                                dp->b_forw = NULL;
                    862:                                if (um->um_tab.b_actf == NULL)
                    863:                                        um->um_tab.b_actf = dp;
                    864:                                else
                    865:                                        um->um_tab.b_actl->b_forw = dp;
                    866:                                um->um_tab.b_actl = dp;
                    867:                                dp->b_active = 1;
                    868:                        }
                    869:                }
                    870:                udinit(d);
                    871:        }
                    872: }
                    873: 
                    874: uddump()
                    875: {
                    876:        return(ENXIO);
                    877: }
                    878:  
                    879: udsize(dev)
                    880:        dev_t dev;
                    881: {
                    882:        int unit = minor(dev) >> 3;
                    883:        struct uba_device *ui;
                    884: 
                    885:        if (unit >= NRA || (ui = uddinfo[unit]) == 0 || ui->ui_alive == 0)
                    886:                return (-1);
                    887:        return (ra_sizes[minor(dev) & 07].nblocks);     /* XXX */
                    888: }
                    889: #endif

unix.superglobalmegacorp.com

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