Annotation of researchv9/sys/boot/stand/st.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * @(#)st.c 1.1 86/02/03 Copyright (c) 1985 by Sun Microsystems, Inc.
        !             3:  */
        !             4: 
        !             5: #include <sys/types.h>
        !             6: #include <sys/inode.h>
        !             7: #include <sun/dklabel.h>
        !             8: #include <sun/dkio.h>
        !             9: #include <sys/buf.h>
        !            10: #include <sundev/screg.h>
        !            11: #include <sundev/sireg.h>
        !            12: #include <sundev/scsi.h>
        !            13: #include <sundev/streg.h>
        !            14: #include <machine/idprom.h>
        !            15: #include "saio.h"
        !            16: #include "param.h"
        !            17: 
        !            18: /*
        !            19:  * Driver for Sysgen SC4000 and EMULEX MT-02 SCSI tape controllers.
        !            20:  * Supports qic11 format only.
        !            21:  */
        !            22: extern int scdoit();
        !            23: #ifdef SUN3
        !            24: extern int sidoit();
        !            25: #endif
        !            26: 
        !            27: #define min(a,b)       ((a)<(b)? (a): (b))
        !            28: 
        !            29: #define NSD 1
        !            30: unsigned long staddrs[NSD] = { 0x0, };
        !            31: 
        !            32: extern int xxprobe(), xxboot();
        !            33: int stopen(), stclose(), ststrategy();
        !            34: 
        !            35: 
        !            36: struct stparam {
        !            37:        int             st_target;
        !            38:        int             st_unit;
        !            39:        int             st_eof;
        !            40:        int             st_lastcmd;
        !            41:        int             st_ctype;
        !            42: #ifdef SUN3
        !            43:        int             st_ha_type;
        !            44: #endif
        !            45:        struct          saioreq subsip[1];      /* sip for host adapter */
        !            46: };
        !            47: 
        !            48: /*
        !            49:  * DMA-able buffers
        !            50:  */
        !            51: #ifdef SUN2
        !            52: /* virtual addresses are precious on Sun-2 */
        !            53: #define        MAXSTBSIZE      (20*1024)       
        !            54: #endif
        !            55: #ifdef SUN3
        !            56: #define        MAXSTBSIZE      (127*512)       
        !            57: #endif
        !            58: struct stdma {
        !            59:        char    sbuffer[SENSE_LENGTH];
        !            60:        char    databuffer[MAXSTBSIZE];
        !            61: };
        !            62: 
        !            63: #define STSBUF         (((struct stdma *)sip->si_dmaaddr)->sbuffer)
        !            64: #define STBUF          (((struct stdma *)sip->si_dmaaddr)->databuffer)
        !            65: 
        !            66: #define ISAEMULEX(stp) (stp->st_ctype == ST_TYPE_EMULEX ? 1 : 0)
        !            67: 
        !            68: /*
        !            69:  * What resources we need to run
        !            70:  */
        !            71: struct devinfo stinfo = {
        !            72:        0,                              /* No device to map in */
        !            73:        sizeof (struct stdma),
        !            74:        sizeof (struct stparam),
        !            75:        NSD,                            /* Dummy devices */
        !            76:        staddrs,                        /* Dummy devices */
        !            77:        MAP_MAINMEM,
        !            78:        MAXSTBSIZE,                     /* transfer size */
        !            79: };
        !            80: 
        !            81: struct boottab stdriver = {
        !            82:        "st",   xxprobe, xxboot,
        !            83:        stopen, stclose, ststrategy,
        !            84:        "st: SCSI tape", &stinfo
        !            85: };
        !            86: 
        !            87: #define        TAPE_TARGET             4       /* default SCSI target # for tape */
        !            88: 
        !            89: #define SENSE_BITS \
        !            90: "\020\17NoCart\16NoDrive\15WriteProt\14EndMedium\13HardErr\12WrongBlock\
        !            91: \11FileMark\7InvCmd\6NoData\5Flaking\4BOT\0034\0022\1GotReset"
        !            92: 
        !            93: #define SENSELOC       4       /* sysgen returns sense at this offset */
        !            94: 
        !            95: #define        ROUNDUP(x)      ((x + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1))
        !            96: 
        !            97: #ifdef SUN3
        !            98: /*
        !            99:  * Determine type of host adaptor interface, si or sc.
        !           100:  * Returns 1 if si host adaptor and 0 if sc host adaptor.
        !           101:  */
        !           102: st_probe(sip)
        !           103:        struct saioreq *sip;
        !           104: {
        !           105:        if (siprobe(sip)) {
        !           106:                return (1);
        !           107:        } else {
        !           108:                return (0);
        !           109:        }
        !           110: }
        !           111: #endif
        !           112: 
        !           113: /*
        !           114:  * Open the SCSI Tape controller
        !           115:  */
        !           116: int
        !           117: stopen(sip)
        !           118:        register struct saioreq *sip;
        !           119: {
        !           120:        register struct stparam *stp;
        !           121:        register int r;
        !           122:        register int skip;
        !           123:        register int i;
        !           124:        struct scsi_cdb cdb;
        !           125:        struct scsi_scb scb;
        !           126: 
        !           127:        stp = (struct stparam *) sip->si_devdata;
        !           128:        bzero( (char *)stp, (sizeof (struct stparam)));
        !           129: 
        !           130:        *stp->subsip = *sip;    /* initialize subsip */
        !           131: 
        !           132: #ifdef SUN3
        !           133:        {
        !           134:                extern struct boottab scdriver;
        !           135:                extern struct boottab sidriver;
        !           136: 
        !           137:                /* FIXME, find out which scsi interface to use */
        !           138:                if (st_probe(sip)) {
        !           139:                        stp->st_ha_type = 1;
        !           140: 
        !           141:                        /* FIXME, must vector thru table */
        !           142:                        stp->subsip->si_boottab = &sidriver;
        !           143:                } else {
        !           144:                        stp->st_ha_type = 0;
        !           145: 
        !           146:                        /* FIXME, must vector thru table */
        !           147:                        stp->subsip->si_boottab = &scdriver;
        !           148:                }
        !           149:        }
        !           150: #endif
        !           151: #ifdef SUN2
        !           152:        {
        !           153:                extern struct boottab scdriver;
        !           154: 
        !           155:                stp->subsip->si_boottab = &scdriver;    
        !           156:        }
        !           157: #endif
        !           158: 
        !           159:        stp->subsip->si_unit = sip->si_unit >> 3;       /* Target number */
        !           160:        if (stp->subsip->si_unit == 0) {
        !           161:                stp->subsip->si_unit = TAPE_TARGET;
        !           162:        }
        !           163: 
        !           164:        r = devopen(stp->subsip);
        !           165:        if (r < 0) return r;
        !           166: 
        !           167:        /* Logical unit number */
        !           168:        stp->st_unit = sip->si_unit & 0x07;
        !           169: 
        !           170:        /*
        !           171:         * Must wait for tape controller to become ready.
        !           172:         * This takes about 10 seconds for the Emulex.
        !           173:         */
        !           174:        /*
        !           175:         * Test for the controller being ready. First test will fail if
        !           176:         * the SCSI bus is permanently busy or if a previous op was 
        !           177:         * interrupted in mid-transfer. Second one should work.
        !           178:         */
        !           179:        for (i = 0; i < 2; i++) {
        !           180:                bzero((char *) &cdb, sizeof cdb);
        !           181:                cdb.cmd = SC_TEST_UNIT_READY;
        !           182:                cdb.count = 0;
        !           183:                stp->subsip->si_cc = 0;
        !           184:                stp->subsip->si_ma = 0;
        !           185: #ifdef SUN3
        !           186:                if (stp->st_ha_type)
        !           187:                        r = sidoit(&cdb, &scb, stp->subsip);
        !           188:                else
        !           189: #endif
        !           190:                        r = scdoit(&cdb, &scb, stp->subsip);
        !           191:        }
        !           192: 
        !           193:        /* 
        !           194:         * To figure out what type of tape controller is out there we send 
        !           195:         * a REQUEST_SENSE command and see how much sense data comes back.  
        !           196:         */
        !           197:        stp->st_ctype = ST_TYPE_EMULEX;
        !           198:        cdb.cmd = SC_REQUEST_SENSE;
        !           199:        stp->subsip->si_cc = cdb.count = ST_EMULEX_SENSE_LEN;
        !           200:        stp->subsip->si_ma = STSBUF;
        !           201: #ifdef SUN3
        !           202:        if (stp->st_ha_type)
        !           203:                r = sidoit(&cdb, &scb, stp->subsip);
        !           204:        else
        !           205: #endif
        !           206:                r = scdoit(&cdb, &scb, stp->subsip);
        !           207:        if (r != ST_EMULEX_SENSE_LEN) {
        !           208:                stp->st_ctype = ST_TYPE_SYSGEN;
        !           209:                cdb.cmd = SC_REQUEST_SENSE;
        !           210:                stp->subsip->si_cc = cdb.count = ST_SYSGEN_SENSE_LEN;
        !           211:                stp->subsip->si_ma = STSBUF;
        !           212: #ifdef SUN3
        !           213:                if (stp->st_ha_type)
        !           214:                        r = sidoit(&cdb, &scb, stp->subsip);
        !           215:                else
        !           216: #endif
        !           217:                        r = scdoit(&cdb, &scb, stp->subsip);
        !           218:                if (r == -1) {
        !           219:                        printf("stopen: cannot get sense, %d\n", r);
        !           220:                        return (-1);
        !           221:                }
        !           222:        } 
        !           223: 
        !           224:        /* 
        !           225:         * Default format mode for emulex is qic24.
        !           226:         * Needs to be qic11.
        !           227:         */
        !           228:        if (ISAEMULEX(stp)) {
        !           229:                sip->si_cc = EM_MS_PL_LEN;
        !           230:                if (stcmd(SC_QIC11, sip, 1) == 0) {
        !           231:                        printf("stopen: mode select command fail");
        !           232:                        return (-1);
        !           233:                }
        !           234:        }
        !           235: 
        !           236:        /*
        !           237:         * Rewind a few times until it works.  First one will fail if
        !           238:         * the SCSI bus is permanently busy if a previous op was interrupted
        !           239:         * in mid-transfer.  Second one will fail with POR status, after
        !           240:         * the scsi bus is reset from the busy.  Third one should work.  
        !           241:         */
        !           242:        sip->si_cc = 0;
        !           243:        if (stcmd(SC_REWIND, sip, 0) == 0 &&
        !           244:            stcmd(SC_REWIND, sip, 0) == 0 &&
        !           245:            stcmd(SC_REWIND, sip, 1) == 0) {
        !           246:                return (-1);
        !           247:        }
        !           248:        skip = sip->si_boff;
        !           249:        while (skip--) {
        !           250:                sip->si_cc = 0;
        !           251:                if (stcmd(SC_SPACE_FILE, sip, 1) == 0) {
        !           252:                        return (-1);
        !           253:                }
        !           254:        }
        !           255:        stp->st_eof = 0;
        !           256:        stp->st_lastcmd = 0;
        !           257:        return (0);
        !           258: }
        !           259: 
        !           260: /*
        !           261:  * Close the tape drive.
        !           262:  */
        !           263: stclose(sip)
        !           264:        register struct saioreq *sip;
        !           265: {
        !           266:        register struct stparam *stp;
        !           267: 
        !           268:        stp = (struct stparam *) sip->si_devdata;
        !           269:        if (stp->st_lastcmd == SC_WRITE) {
        !           270:                (void) stcmd(SC_WRITE_FILE_MARK, sip, 0);
        !           271:        }
        !           272:        (void) stcmd(SC_REWIND, sip, 0);
        !           273: }
        !           274: 
        !           275: 
        !           276: /*
        !           277:  * Perform a read or write of the SCSI tape.
        !           278:  */
        !           279: int
        !           280: ststrategy(sip, rw)
        !           281:        register struct saioreq *sip;
        !           282:        int rw;
        !           283: {
        !           284:        register struct stparam *stp;
        !           285: 
        !           286:        stp = (struct stparam *) sip->si_devdata;
        !           287:        if (stp->st_eof) {
        !           288:                stp->st_eof = 0;
        !           289:                return (0);
        !           290:        }
        !           291:        return (stcmd(rw == WRITE ? SC_WRITE : SC_READ, sip, 1));
        !           292: }
        !           293: 
        !           294: /*
        !           295:  * Execute a scsi tape command
        !           296:  */
        !           297: int
        !           298: stcmd(cmd, sip, errprint)
        !           299:        int cmd;
        !           300:        register struct saioreq *sip;
        !           301:        int errprint;
        !           302: {
        !           303:        register struct st_emulex_mspl *mode;
        !           304:        register int r, i, c;
        !           305:        register char *buf;
        !           306:        register struct stparam *stp;
        !           307:        struct scsi_cdb cdb, scdb;
        !           308:        struct scsi_scb scb, sscb;
        !           309:        int count;
        !           310:        int qic;
        !           311:        int sense_length;
        !           312:        char *cp;
        !           313:        struct st_emulex_sense *ems;
        !           314:        struct st_sysgen_sense *scs;
        !           315: 
        !           316:        count = sip->si_cc;
        !           317:        stp = (struct stparam *)sip->si_devdata;
        !           318:        buf =  sip->si_ma;
        !           319: 
        !           320:        if (cmd == SC_WRITE && buf != STBUF) {
        !           321:                bcopy(buf, STBUF, (unsigned)count);
        !           322:        }
        !           323: 
        !           324:        /* set up cdb */
        !           325:        bzero((char *) &cdb, sizeof cdb);
        !           326:        cdb.cmd = cmd;
        !           327:        cdb.lun = stp->st_unit;
        !           328:        c = ROUNDUP(count) / DEV_BSIZE;
        !           329:        cdb.high_count = c >> 16;
        !           330:        cdb.mid_count = (c >> 8) & 0xFF;
        !           331:        cdb.low_count = c & 0xFF;
        !           332:        stp->subsip->si_ma = STBUF;
        !           333:        stp->subsip->si_cc = ROUNDUP(count);
        !           334: 
        !           335:        /* some fields in the cdb are command specific */
        !           336:        switch (cmd) {
        !           337: 
        !           338:        case SC_QIC11:
        !           339:                stp->subsip->si_ma = 0;
        !           340:                stp->subsip->si_cc = 0; 
        !           341:                if (ISAEMULEX(stp)) {
        !           342:                        qic = ST_EMULEX_QIC11;
        !           343:                        cdb.cmd = SC_MODE_SELECT;
        !           344:                        goto MODE;
        !           345:                } else {
        !           346:                        cdb.cmd = SC_QIC02;
        !           347:                        cdb.high_count = ST_SYSGEN_QIC11;
        !           348:                        break;
        !           349:                }
        !           350:                /* NOTREACHED */
        !           351: 
        !           352:        case SC_QIC24:
        !           353:                stp->subsip->si_ma = 0;
        !           354:                stp->subsip->si_cc = 0; 
        !           355:                if (ISAEMULEX(stp)) {
        !           356:                        qic = ST_EMULEX_QIC24;
        !           357:                        cdb.cmd = SC_MODE_SELECT;
        !           358:                        goto MODE;
        !           359:                } else {
        !           360:                        cdb.cmd = SC_QIC02;
        !           361:                        cdb.high_count = ST_SYSGEN_QIC24;
        !           362:                        break;
        !           363:                }
        !           364:                /* NOTREACHED */
        !           365: MODE:
        !           366:        case SC_MODE_SELECT:
        !           367:                mode = (struct st_emulex_mspl *)STSBUF;
        !           368:                bzero(mode, sizeof(*mode));
        !           369:                mode->hdr.bufm = 1;
        !           370:                mode->bd.density = qic;
        !           371:                mode->hdr.bd_len = EM_MS_BD_LEN;
        !           372:                stp->subsip->si_ma = (char *)mode;
        !           373:                stp->subsip->si_cc = cdb.count = EM_MS_PL_LEN;
        !           374:                break;
        !           375: 
        !           376:        case SC_SPACE_FILE:
        !           377:                cdb.cmd = SC_SPACE;     /* the real SCSI cmd */
        !           378:                cdb.t_code = 1;         /* space file, not rec */
        !           379:                cdb.low_count = 1;      /* space 1 file, not 0 */
        !           380:                stp->subsip->si_ma = 0;
        !           381:                stp->subsip->si_cc = 0;
        !           382:                break;
        !           383: 
        !           384:        case SC_WRITE_FILE_MARK:
        !           385:                cdb.count = 1;  
        !           386:                /* fall through... */
        !           387: 
        !           388:        case SC_TEST_UNIT_READY:
        !           389:        case SC_REWIND:
        !           390:        case SC_LOAD:
        !           391:                stp->subsip->si_ma = 0;
        !           392:                stp->subsip->si_cc = 0;
        !           393:                break;
        !           394: 
        !           395:        case SC_READ:
        !           396:        case SC_WRITE:
        !           397:                if (ISAEMULEX(stp)) {
        !           398:                        cdb.t_code = 1;
        !           399:                }
        !           400:                break;
        !           401: 
        !           402:        default:
        !           403:                if (errprint)
        !           404:                        printf("st: unknown command\n");
        !           405:                return (0);
        !           406:        }
        !           407: 
        !           408:        /* execute the command */
        !           409: #ifdef SUN3
        !           410:        if (stp->st_ha_type)
        !           411:                r = sidoit(&cdb, &scb, stp->subsip);
        !           412:        else
        !           413: #endif
        !           414:                r = scdoit(&cdb, &scb, stp->subsip);
        !           415: 
        !           416:        /* allow for tape blocking */
        !           417:        if (r > count)
        !           418:                r = count;
        !           419:        /* error */
        !           420:        if (r == -1) 
        !           421:                return (0);
        !           422: 
        !           423:        if (cmd == SC_READ) {
        !           424:                if (min(count, r))
        !           425:                        bcopy(STBUF, buf, (unsigned)(min(count, r)));
        !           426:        }
        !           427: 
        !           428:        /* we may need to get sense data */
        !           429:        if (scb.chk) {
        !           430:                bzero((char *) &scdb, sizeof scdb);
        !           431:                scdb.cmd = SC_REQUEST_SENSE;
        !           432:                scdb.lun = stp->st_unit;
        !           433:                if (ISAEMULEX(stp)) {
        !           434:                        sense_length = stp->subsip->si_cc =
        !           435:                            scdb.count = ST_EMULEX_SENSE_LEN;
        !           436:                } else {
        !           437:                        sense_length = stp->subsip->si_cc = 
        !           438:                            scdb.count = ST_SYSGEN_SENSE_LEN;
        !           439:                }
        !           440:                stp->subsip->si_ma = STSBUF;
        !           441: #ifdef SUN3
        !           442:                if (stp->st_ha_type)
        !           443:                        i = sidoit(&scdb, &sscb, stp->subsip );
        !           444:                else
        !           445: #endif
        !           446:                        i = scdoit(&scdb, &sscb, stp->subsip );
        !           447:                if (i != sense_length) {
        !           448:                        if (errprint) {
        !           449:                                printf("st: sense error\n");
        !           450:                        }
        !           451:                        stp->st_eof = 1;
        !           452:                        return (0);
        !           453:                } 
        !           454:                if (ISAEMULEX(stp)) {
        !           455:                        ems = (struct st_emulex_sense *)STSBUF;
        !           456:                        if ((ems->ext_sense.fil_mk == 0) && errprint) {
        !           457:                                printf("st: error:\n");
        !           458:                                printf("\tsense key is %x", 
        !           459:                                    ems->ext_sense.key);
        !           460:                                printf("\terror is %x\n",
        !           461:                                    ems->error);
        !           462:                        }
        !           463:                        stp->st_eof = 1;
        !           464:                        return (r);
        !           465:                } else  {
        !           466:                        scs = (struct st_sysgen_sense *)STSBUF;
        !           467:                        if ((scs->qic_sense.file_mark == 0) && errprint) {
        !           468: #ifdef STBOOT
        !           469:                                printf("st: error %x\n", 
        !           470:                                        *(unsigned short *)&STSBUF[SENSELOC]);
        !           471: #else  STBOOT
        !           472:                                printf("st: error %b\n", 
        !           473:                                        *(unsigned short *)&STSBUF[SENSELOC],
        !           474:                                        SENSE_BITS);
        !           475: #endif STBOOT
        !           476:                        }
        !           477:                        stp->st_eof = 1;
        !           478:                        return (r);
        !           479:                }
        !           480:        }
        !           481:        if (r >= count) {
        !           482:                return (count ? count : 1);
        !           483:        } else {
        !           484:                if (errprint) {
        !           485:                        printf("st: short transfer\n");
        !           486:                }
        !           487:                return (r);
        !           488:        }
        !           489: }
        !           490: 

unix.superglobalmegacorp.com

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