Annotation of coherent/b/STREAMS/io.386/xlft.c, revision 1.1

1.1     ! root        1: #define MWC_FT 1
        !             2: 
        !             3: /*
        !             4:  * File:       xlft.c
        !             5:  *
        !             6:  * Purpose:    Floppy tape device control.
        !             7:  *             Inspired by the Archive "xl" driver.
        !             8:  *             Requires 765 controller module fdc.c
        !             9:  *             FDC = floppy disk controller, e.g. NEC upd765
        !            10:  *
        !            11:  * Revised: Tue Jun  1 19:16:37 1993 CDT
        !            12:  */
        !            13: 
        !            14: /*
        !            15:  * ----------------------------------------------------------------------
        !            16:  * Includes.
        !            17:  */
        !            18: #include       <sys/coherent.h>
        !            19: 
        !            20: #include       <sys/errno.h>
        !            21: #include       <sys/buf.h>
        !            22: #include       <sys/con.h>
        !            23: #include       <sys/devices.h>
        !            24: #include       <sys/fdc765.h>
        !            25: #include       <sys/fdioctl.h>
        !            26: #include       <sys/file.h>
        !            27: #include       <sys/sched.h>
        !            28: #include       <sys/stat.h>
        !            29: #include       <sys/xl.h>
        !            30: #include       <sys/xlfdc.h>
        !            31: #include       <sys/xlft.h>
        !            32: #include       <sys/xl8237.h>
        !            33: 
        !            34: /*
        !            35:  * ----------------------------------------------------------------------
        !            36:  * Definitions.
        !            37:  *     Constants.
        !            38:  *     Macros with argument lists.
        !            39:  *     Typedefs.
        !            40:  *     Enums.
        !            41:  */
        !            42: #define        HDRSZ   0x4000          /* 16k, size of qic-40 header           */
        !            43: #define        BFRSZ   0x8000          /* 32k, size of qic-40 buffer           */
        !            44: 
        !            45: #define MAX_PCN                200
        !            46: 
        !            47: /* compatibility area */
        !            48: 
        !            49: #define bcopy(src, dest, nbytes)       memcpy(dest, src, nbytes)
        !            50: #define copyin(userSrc, drvrDest, nbytes) \
        !            51:        ukcopy(userSrc, drvrDest, nbytes)
        !            52: #define copyout(drvrSrc, userDest, nbytes) \
        !            53:        kucopy(drvrSrc, userDest, nbytes)
        !            54: #define getfdc(unit)                   setFtIntr(1)
        !            55: #define getfdcn(unit)                  setFtIntr(1)
        !            56: #define kvtophys(vaddr)                        vtop(vaddr)
        !            57: #define relfdc()                       setFtIntr(0)
        !            58: #define sleep(address, priority)       \
        !            59:        x_sleep(address, pritape, slpriSigLjmp, #address)
        !            60: #define spl5()                         sphi()
        !            61: #define splx(lvl)                      spl(lvl)
        !            62: #define        tenmicrosec()                   busyWait2(NULL, 12)
        !            63: 
        !            64: static void    cmn_err();
        !            65: 
        !            66: enum {
        !            67:        CE_CONT = 0,            /* used to continue a previous message */
        !            68:        CE_NOTE,                /* used to display a NOTICE: message */
        !            69:        CE_WARN,                /* used to display a WARNING: message */
        !            70:        CE_PANIC,               /* used to display a PANIC: message */
        !            71:        CE_INVALID              /* used to warn about invalid severity */
        !            72: };
        !            73: 
        !            74: /************************************************************************/
        !            75: /*     Additional fdc equates                                          */
        !            76: /************************************************************************/
        !            77: 
        !            78: #define        FDTMO   65535           /* xlfdc_in_byte, xlfdc_out_byte timeout*/
        !            79: #define        IOTMO   (12 * HZ)       /* io timeout                           */
        !            80: #define        TMSKP   18              /* # segments missed if IOTMO           */
        !            81: 
        !            82: /*
        !            83:  * ----------------------------------------------------------------------
        !            84:  * Functions.
        !            85:  *     Import Functions.
        !            86:  *     Export Functions.
        !            87:  *     Local Functions.
        !            88:  */
        !            89: extern int     nulldev();
        !            90: 
        !            91: extern int     xl_tbi();       /* init ecc tables                      */
        !            92: extern int     xl_enc();       /* encode ecc data                      */
        !            93: extern int     xl_dec();       /* decode ecc data                      */
        !            94: 
        !            95: /* CON entry points. */
        !            96: static int     ftblock();
        !            97: static int     ftclose();
        !            98: static int     ftioctl();
        !            99: static int     ftload();
        !           100: static int     ftopen();
        !           101: static int     ftread();
        !           102: static int     ftunload();
        !           103: static int     ftwrite();
        !           104: 
        !           105: static int     getmem();
        !           106: static int     putrb();
        !           107: static struct  rb *getrb();
        !           108: static void    stdma();
        !           109: static void    strbfm();               /* set up rb for format         */
        !           110: static  void   strbsg();
        !           111: static  void   stseg();
        !           112: static  void   wvtbl();
        !           113: 
        !           114: static void    xlcal(), xlcal0(), (*pfcal)();  /* calibrate            */
        !           115: static void    xlcomplete();
        !           116: static void    xldelay(), (*pfdly)();  /* "delay"                      */
        !           117: static void    xldma();
        !           118: static unchar  xlfdc_in_byte();
        !           119: static unchar  xlfdc_out_byte();
        !           120: static unchar  xlfdc_out_str();
        !           121: static void    xlfdc_reset();
        !           122: static void    xlflush();
        !           123: static void    xlfmq(), xlfmq0(), xlfmq1(), xlfmq2(); /* format queue  */
        !           124: static void    xlfms(), xlfm0(), (*pffms)();   /* format segment       */
        !           125: static int     xlformat();             /* format main routine          */
        !           126: static void    xlgtdat();
        !           127: static void    xlhalt(), (*pfhlt)();   /* halt tape motion             */
        !           128: static void    xlintr(), (*pfint)();   /* xl2 ptr to intr handler      */
        !           129: static void    xlnull();
        !           130: static int     xlopn();
        !           131: static void    xloutput_step();        /* output steps, exit=pfint     */
        !           132: static void    xlpark(), (*pfprk)();
        !           133: static void    xlpark0(), xlpark1(), xlpark2();
        !           134: static void    xlpos(), xlpos0(), xlpos1(), xlpos2(), xlpos3(), (*pfpos)();
        !           135: static void    xlptdat();
        !           136: static void    xlque(), xlqr0(), xlqw0();
        !           137: static void    xlrds(), xlrd0(), xlrd1(), (*pfrds)();  /* read segment */
        !           138: static void    xlreadid(), xlreadid0(), (*pfrdi)();    /* read id      */
        !           139: static void    xlready(), xlready0(), (*pfrdy)(); /* "wait" for ready  */
        !           140: static void    xlrel();
        !           141: static void    xlreset(), xlreset0(), (*pfrst)();      /* reset drive  */
        !           142: static void    xlrn9(), xlrn17();
        !           143: static void    xlrnb(), xlrnb0(), (*pfrnb)();  /* report next bits     */
        !           144: static void    xlrqr();
        !           145: static void    xlseek(), (*pfsek)();   /* seek to tptrk                */
        !           146: static void    xlseek0(), xlseek1();
        !           147: static void    xlsel();
        !           148: static void    xlskipb(), (*pfskp)();  /* skip n segs back             */
        !           149: static void    xlskipb0(), xlskipb1(), xlskipb2();
        !           150: static void    xlstatus(), (*pfsts)(); /* get status                   */
        !           151: static void    xlstatus0(), xlstatus1();
        !           152: static void    xltimout(), xltimfn();
        !           153: static int     xlwait();
        !           154: static void    xlwds(), (*pfwds)();    /* write del adm segment        */
        !           155: static void    xlwts(), (*pfwts)();    /* write segment                */
        !           156: static void    xlwt0(), xlwt1();
        !           157: 
        !           158: static void    xlDbPrintErr(), xlDbPrintCmd(), xlDbPrintStat();
        !           159: 
        !           160: static void    ftDbPrtStat();
        !           161: static int     ftCmd();
        !           162: static void    ftIrqHandler();
        !           163: static int     ftRecal();
        !           164: static void    ftSelect();
        !           165: 
        !           166: /*
        !           167:  * ----------------------------------------------------------------------
        !           168:  * Global Data.
        !           169:  *     Import Variables.
        !           170:  *     Export Variables.
        !           171:  *     Local Variables.
        !           172:  */
        !           173: 
        !           174: /* from assembler module */
        !           175: extern ushort  *xltbl;         /* ptr to rb.tbl                        */
        !           176: extern unchar  xlbst;          /* base sector for segment              */
        !           177: extern unchar  xlsct;          /* sector # for next chunk              */
        !           178: extern int     xlcnt;          /* # bytes to xfer next chunk           */
        !           179: extern int     xlofs;          /* offset for next chunk                */
        !           180: 
        !           181: CON    ftxlcon = {
        !           182:        DFCHR,                          /* Flags */
        !           183:        FL_MAJOR,                       /* Major index */
        !           184:        ftopen,                         /* Open */
        !           185:        ftclose,                        /* Close */
        !           186:        ftblock,                        /* Block */
        !           187:        ftread,                         /* Read */
        !           188:        ftwrite,                        /* Write */
        !           189:        ftioctl,                        /* Ioctl */
        !           190:        nulldev,                        /* Powerfail */
        !           191:        nulldev,                        /* Timeout */
        !           192:        ftload,                         /* Load */
        !           193:        ftunload,                       /* Unload */
        !           194:        nulldev                         /* Poll */
        !           195: };
        !           196: 
        !           197: /*
        !           198:  * Patchable variables.
        !           199:  */
        !           200: int    XL_VERBOSE = 1;
        !           201: int    XL_NBUFS = 17;          /* ~ 3K total 'DATA' for driver         */
        !           202:                                /* 1.25K for ecc, + XL_NBUFS * 94       */
        !           203: 
        !           204: /* Parameters for FDC Specify Command */
        !           205: int FT_SRT = 0xE;
        !           206: int FT_HUT = 0xF;
        !           207: int FT_HLT = 0x1;
        !           208: 
        !           209: /************************************************************************/
        !           210: /*     UNIX data areas  and externals                                  */
        !           211: /************************************************************************/
        !           212: static ulong   allocated_add;  /* mem allocate addr for kernel buffer  */
        !           213: 
        !           214: /************************************************************************/
        !           215: /*     data area                                                       */
        !           216: /************************************************************************/
        !           217: static int     xldataw;                /* data queue wakeup flag       */
        !           218: static int     xlcompw;                /* completion wakeup flag       */
        !           219: static int     xlfreew;                /* free queue wakeup flag       */
        !           220: static int     xlcompf;                /* completion flag              */
        !           221: static int     xlnactw;                /* inactive wakeup flag         */
        !           222: static int     xlskip_count;           /* # segments to skip           */
        !           223: 
        !           224: static fplng   ptr_header;             /* ptr to header bfr            */
        !           225: static fplng   ptr_buffer;             /* ptr to bfr                   */
        !           226: 
        !           227: static struct  rb  * rbmp;             /* request packet pool          */
        !           228: 
        !           229: static struct  rbq xlfree_q;           /* free queue                   */
        !           230: static struct  rbq req;                /* request queue                */
        !           231: static struct  rbq data_queue;         /* read data queue              */
        !           232: 
        !           233: static int     xlmem_allocated = 0;    /* set if memory allocated      */
        !           234: 
        !           235: static struct  {                       /* flags                        */
        !           236:        unsigned short init :1;
        !           237:        unsigned short open :1;
        !           238:        unsigned short writ :1;
        !           239:        unsigned short cal  :1;
        !           240:        unsigned short actv :1;
        !           241:        unsigned short tmov :1;
        !           242:        unsigned short werr :1;
        !           243: }f;
        !           244: 
        !           245: static int     nseg_p_track;           /* # segments/track             */
        !           246: static int     nseg_p_head;            /* # segments/head              */
        !           247: static int     nseg_p_cyl;             /* # segments/cylinder          */
        !           248: 
        !           249: static int     fdcmd;                  /* last fdc cmd                 */
        !           250: 
        !           251: static unchar  status_buf[ 10 ];       /* status buffer                */
        !           252:                                        /* bytes 0-6 = 8272 status      */
        !           253:                                        /*      7   = nec phase err     */
        !           254:                                        /*      8   = 8272 st3          */
        !           255: 
        !           256: static ushort  xlrnbw;                 /* xl2 report next bit word     */
        !           257: static unchar  xlster;                 /* set if last bit not a 1      */
        !           258: static unchar  xl6sts;                 /* xl2 status                   */
        !           259: static unchar  xlests;
        !           260: static ushort  xl7sts;
        !           261: static int     xlbcnt;                 /* xlrnb counter, # of sts bits */
        !           262: 
        !           263: static unchar  fdstb[ 4 ] = { 0x1c, 0x2d, 0x4e, 0x8f };
        !           264: static unchar  fdsel, unit, fdselr, ftfmt;
        !           265: 
        !           266: static ushort  sgwrd;                  /* strbsg params                */
        !           267: static ulong   sgmap;
        !           268: 
        !           269: static paddr_t xadr;                   /* segment io params            */
        !           270: static struct  rb *xprb;
        !           271: static ushort  xtbl;
        !           272: static int     xsct;
        !           273: static int     xrty;
        !           274: static int     xstop;                  /* stop io flag (close)         */
        !           275: 
        !           276: static int     tptrk;                  /* current tape track           */
        !           277: static int     tpseg;                  /* next tape segment            */
        !           278: static int     fmtrk;                  /* format track                 */
        !           279: static int     vftrk;                  /* verify track (debug display) */
        !           280: 
        !           281: static int     xltimoutf = 0;          /* timeout flag                 */
        !           282: 
        !           283: /*     fdc commands                                                    */
        !           284: static unchar  sf2cms[ 3 ] = { 0x03, 0xef, 0x02 };
        !           285: 
        !           286: static unchar  sf3cms[ 3 ] = { 0x03, 0xdf, 0x02 };
        !           287: static unchar  sekcms[ 3 ] = { 0x0f, 0x00, 0x00 };
        !           288: static unchar  rdicms[ 2 ] = { 0x4a, 0x00 };
        !           289: static unchar  rwdcms[ 9 ] = { 0x46, 0, 0, 0, 0, 3, 226, 1, 0xff };
        !           290: static unchar  fmtcms[ 6 ] = { 0x4d, 0, 3, 32, 233, 0x6d };
        !           291: /*             sekcms[ 2 ] = current track, see xlintr()               */
        !           292: 
        !           293: static unchar  vtbl[  ] = "VTBL";
        !           294: static unchar  xnxnm[  ] = "unix";
        !           295: static unchar  xnxvs[ 20 ] = {
        !           296:                                0x55, 0xaa, 0x55, 0xaa, 0x02, 0x00, 0x00, 0x00,
        !           297:                                0x01, 0x00, 0x02, 0x00, 0x4f, 0x05, 0x00, 0x00,
        !           298:                                0x00, 0x00, 0x00, 0x00
        !           299:                        };
        !           300: 
        !           301: static int     h0sgn, h1sgn;           /* header seg #                 */
        !           302: static int     volume_seg_num;         /* volume seg #                 */
        !           303: static int     data_seg_num;           /* data seg #                   */
        !           304: static int     curr_seg_num;           /* current seg #                */
        !           305: static int     read_ahead_seg_num;     /* read ahead seg #             */
        !           306: static struct  rb *cprb;               /* offset to current rb         */
        !           307: static fpchr   cptr;                   /* ptr to current bfr           */
        !           308: static int     cnbr;                   /* # bytes remaining            */
        !           309: static fpchr   wptr;                   /* copy of cptr for write encod */
        !           310: static int     last_seg_num;           /* last segment                 */
        !           311: static int     lnbr;                   /* last seg # bytes             */
        !           312: 
        !           313: static int     rnbr;                   /* # requested bytes remaining  */
        !           314: static int     rcnt;                   /* # bytes to copy              */
        !           315: 
        !           316: static struct  rb *fprb;               /* used to enque requests       */
        !           317: 
        !           318: static TIM     xltmo, xldly;
        !           319: 
        !           320: static struct  FT {
        !           321:        unsigned char ft_pcn;           /* present cylinder #           */
        !           322:        unsigned char ft_bitsNeeded;    /* # of Report Next Bit's to do */
        !           323:        unsigned char ft_wakeMeUp;      /* 1 = sleeping til next FDC IRQ */
        !           324:        unsigned char ft_dumpIrq;       /* 1 = dump IRQ status          */
        !           325:        unsigned char ft_senseDrvStat;  /* 1 = need to sense drv status */
        !           326: } ft;
        !           327: 
        !           328: /*
        !           329:  * ----------------------------------------------------------------------
        !           330:  * Code.
        !           331:  */
        !           332: 
        !           333: /*
        !           334:  * CON struct routines.
        !           335:  */
        !           336: 
        !           337: /************************************************************************/
        !           338: /*     ftblock                                                         */
        !           339: /*                                                                     */
        !           340: /* Tape is not a block device, but we need a block entry point since   */
        !           341: /* the same driver controls diskette access.                           */
        !           342: /************************************************************************/
        !           343: static int
        !           344: ftblock(bp)
        !           345: BUF *bp;
        !           346: {
        !           347:        u.u_error = EIO;
        !           348:        bp->b_flag |= BFERR;
        !           349:        bdone(bp);
        !           350:        return;
        !           351: }
        !           352: 
        !           353: /************************************************************************
        !           354:  * ftclose
        !           355:  *
        !           356:  ***********************************************************************/
        !           357: static int
        !           358: ftclose(dev, mode)
        !           359: dev_t dev;
        !           360: int mode;
        !           361: {
        !           362: #if MWC_FT
        !           363:        printf("ftclose ");
        !           364:        f.open = 0;
        !           365: #else
        !           366:        if (f.open) {
        !           367:                /* f.open = 0;          reset open flag  U001           */
        !           368:                xlflush();              /* flush all bfrs               */
        !           369:                if (f.werr)             /* flag error if occurred       */
        !           370:                        u.u_error = EIO;
        !           371: 
        !           372:                getfdc(unit);   
        !           373:                xlsel(unit);
        !           374:                if (minor(dev) & M_REW) { /* rewind if rewind_on_close  */
        !           375:                        pfprk = xlcomplete;/* clear drive status and rewind*/
        !           376:                        xlpark();
        !           377:                        xlwait();
        !           378:                } else {
        !           379:                        pfsts = xlcomplete;     /* clear drive status   */
        !           380:                        xlstatus();
        !           381:                        xlwait();
        !           382:                }
        !           383:                xlrel();
        !           384:                relfdc();
        !           385:                f.open = 0;             /* reset open flag      U001    */
        !           386:                cmn_err(CE_CONT, "xlclose: xlster %x  f.werr %d\n", xlster, f.werr);
        !           387:        }
        !           388: #endif
        !           389: }
        !           390: 
        !           391: /************************************************************************/
        !           392: /*     ftioctl                                                         */
        !           393: /*     Handle tape drive & controller commands like erase, rewind,     */
        !           394: /*     retension, read filemark, and write filemark                    */
        !           395: /************************************************************************/
        !           396: ftioctl(dev, cmd, arg)
        !           397: register int   dev, cmd;
        !           398: int            arg;
        !           399: {
        !           400:        int                     xlarg;  /* ioctl argument               */
        !           401:        union   xl_status       xl;     /* status structure             */
        !           402: 
        !           403:        cmn_err(CE_CONT, "ftioctl: cmd %x\n", cmd);
        !           404: 
        !           405:        if ((cmd & 0xff00) != XLIOC) {
        !           406:                u.u_error = EINVAL;
        !           407:                return;
        !           408:        }
        !           409: 
        !           410:        getfdc(unit);                   /* get control of fdc           */
        !           411:        xlsel(unit);                    /* select tape drive            */
        !           412: 
        !           413:        switch (cmd) {
        !           414:        case XL_DEBUG:
        !           415:                if  (copyin(arg, (caddr_t)&XL_VERBOSE, sizeof(int)) == -1)
        !           416:                        u.u_error = EFAULT;
        !           417:                break;
        !           418:        case XL_STATUS:                 /* read status                  */
        !           419:                /*
        !           420:                * Report current status, then clear
        !           421:                * any errors by reading the status again.
        !           422:                */
        !           423:                xl.stat[ 0 ] = xl6sts;
        !           424:                xl.stat[ 1 ] = xl7sts;
        !           425:                xl.stat[ 2 ] = xl7sts >> 8;
        !           426: 
        !           427:                if (copyout(xl.stat, arg, sizeof(xl.stat)) == -1)
        !           428:                        u.u_error = EFAULT;
        !           429:                else {
        !           430:                        xlster = 0;
        !           431:                        xlests = 0;
        !           432:                        xl7sts = 0;
        !           433:                        pfsts = xlcomplete;
        !           434:                        xlstatus();
        !           435:                        xlwait();
        !           436:                        if (f.werr)     /* flag error if occurred       */
        !           437:                                u.u_error = EIO;
        !           438:                        break;
        !           439: 
        !           440:                case XL_RESET:          /* reset drive                  */
        !           441:                        pfrst = xlcomplete;
        !           442:                        xlreset();
        !           443:                        xlwait();
        !           444:                        if (f.werr)     /* flag error if occurred       */
        !           445:                                u.u_error = EIO;
        !           446:                        break;
        !           447: 
        !           448:                case XL_RETEN :         /* retention tape               */
        !           449:                        pfint = xlready;
        !           450:                        pfrdy = xlcomplete;
        !           451:                        xloutput_step(QIC_CMD_EOT);
        !           452:                        xlwait();
        !           453: 
        !           454:                        pfint = xlready;
        !           455:                        pfrdy = xlcomplete;
        !           456:                        xloutput_step(QIC_CMD_BOT);
        !           457:                        xlwait();
        !           458:                        if (xlster)
        !           459:                                u.u_error = ENXIO;
        !           460: 
        !           461:                        break;
        !           462: 
        !           463:                case XL_REWIND:         /* rewind                       */
        !           464:                        pfint = xlready;
        !           465:                        pfrdy = xlcomplete;
        !           466:                        xloutput_step(QIC_CMD_BOT);
        !           467:                        xlwait();
        !           468:                        if (xlster)
        !           469:                                u.u_error = ENXIO;
        !           470:                        break;
        !           471: 
        !           472:                case XL_ERASE:          /* erase tape                   */
        !           473:                        break;
        !           474: 
        !           475:                case XL_AMOUNT:         /* report amount of data xfered */
        !           476:                        /*if (copyout(&ct_amount, arg, sizeof(ct_amount)) == -1)
        !           477:                        u.u_error = EFAULT;*/
        !           478:                        break;
        !           479: 
        !           480:                case XL_FORMAT:         /* format tape                  */
        !           481:                        if  (copyin(arg, (caddr_t) &xlarg, sizeof(int)) == -1)
        !           482:                                u.u_error = EFAULT;
        !           483: 
        !           484:                        else if ((xlarg >= 0 && xlarg <= 14 && ftfmt == 0) ||
        !           485:                                 (xlarg >= 0 && xlarg <= 28 && ftfmt == 1)) {
        !           486:                                xlformat(xlarg);
        !           487:                                if (f.werr)     /* flag err if occurred */
        !           488:                                        u.u_error = EIO;
        !           489:                        } else          /* invalid track number         */
        !           490:                                u.u_error = EINVAL;
        !           491:                }
        !           492:                break;
        !           493:        case XL_RFM:                    /* read file mark               */
        !           494:                ;                       /* not implemented              */
        !           495: 
        !           496:        default:
        !           497:                u.u_error = EINVAL;
        !           498:                break;
        !           499:        }
        !           500:        xlrel();                        /* release fdc                  */
        !           501:        relfdc();
        !           502:        cmn_err(CE_CONT, "xlioctl: returning\n");
        !           503: }
        !           504: 
        !           505: /************************************************************************/
        !           506: /*     ftload                                                          */
        !           507: /************************************************************************/
        !           508: static int
        !           509: ftload()
        !           510: {
        !           511:        register int    eflag;
        !           512:        register int    s, t;
        !           513: 
        !           514: #if MWC_FT
        !           515:        ftIntr = ftIrqHandler;
        !           516: #else
        !           517:        ftIntr = xlintr;
        !           518: #endif
        !           519: 
        !           520:        f.init = 0;                     /* reset flags                  */
        !           521:        f.open = 0;
        !           522:        f.cal = 0;
        !           523:        f.actv = 0;
        !           524:        f.tmov = 0;
        !           525:        xlnactw = 0;
        !           526:        xlfreew = 0;
        !           527:        xldataw = 0;
        !           528:        xlcompw = 0;
        !           529:        xlcompf = 0;
        !           530:        xlster = 0;
        !           531:        status_buf[ 7 ] = 0;
        !           532:        pfint = xlnull;                 /* reset ptr to fun             */
        !           533:        xl_tbi();                       /* init ecc tables              */
        !           534:        if(getmem())
        !           535:                printf("XL: getmem() failed.\n");
        !           536:        else
        !           537:                printf("Archive xl floppy tape driver v1.0 COH loaded\n");
        !           538: }
        !           539: 
        !           540: /************************************************************************
        !           541:  * ftopen
        !           542:  *
        !           543:  ***********************************************************************/
        !           544: static int
        !           545: ftopen(dev, mode)
        !           546: dev_t dev;
        !           547: int mode;
        !           548: {
        !           549:        unsigned int drvStat;
        !           550:        int i;
        !           551:        int bit;
        !           552: 
        !           553: printf("ftopen %x ", dev);
        !           554: 
        !           555:        /* Can't append to tape. */
        !           556:        if (mode & IPAPPEND) {
        !           557: printf("can't append ");
        !           558:                u.u_error = EINVAL;
        !           559:                return;
        !           560:        }
        !           561: 
        !           562:        /* Only one open at a time. */
        !           563:        if (f.open) {
        !           564: printf("only one ftopen at a time ");
        !           565:                u.u_error = EBUSY;
        !           566:                return;
        !           567:        }
        !           568:        f.open = 1;
        !           569: 
        !           570:        unit = FT_UNIT(dev);            /* set unit #                   */
        !           571: 
        !           572:        if (! getfdcn(unit)) {  /* get control of fdc           */
        !           573: printf("fdc unavailable ");
        !           574:                u.u_error = EBUSY;      /* exit if fdc is being used    */
        !           575:                f.open = 0;
        !           576:                return;
        !           577:        }
        !           578: 
        !           579: #if MWC_FT
        !           580:        /* Select tape drive. */
        !           581:        ftSelect(unit);
        !           582: 
        !           583:        /* Do recal to set pcn in fdc - shouldn't affect tape drive. */
        !           584:        if (ftRecal(unit)
        !           585:          || fdc.fdc_nintstat < 2
        !           586:          || fdc.fdc_intstat[1] != 0) {
        !           587: printf("recal failed ");
        !           588:                u.u_error = EIO;
        !           589:                f.open = 0;
        !           590:                setFtIntr(0);
        !           591:                return;
        !           592:        }
        !           593: 
        !           594:        if (ftCmd(QIC_CMD_STS)) {
        !           595: printf("get drive status failed ");
        !           596:                u.u_error = EIO;
        !           597:                f.open = 0;
        !           598:                setFtIntr(0);
        !           599:                return;
        !           600:        }
        !           601: 
        !           602:        xlrel();
        !           603:        relfdc();
        !           604: #else
        !           605:        /* Select tape unit. */
        !           606:        xlsel(unit);
        !           607: 
        !           608:        if (0 == f.init) {              /* init drive if 1st time       */
        !           609:                pfrst = xlcomplete;
        !           610:                xlreset();
        !           611:                if (xlwait()) {
        !           612: printf("init interrupted ");
        !           613:                        u.u_error = EINTR;
        !           614:                        f.open = 0;
        !           615:                        relfdc();
        !           616:                        return;
        !           617:                }
        !           618:                f.init = 1;
        !           619:        }
        !           620: 
        !           621:        if (!xlopn(minor(dev))) {       /* open drive                   */
        !           622:                /* init current params                                  */
        !           623:                read_ahead_seg_num = curr_seg_num = data_seg_num;
        !           624:                cmn_err(CE_CONT, "xlopen: volume_seg_num %d  data_seg_num %d  last_seg_num %d  lnbr %d\n",
        !           625:                   volume_seg_num, data_seg_num, last_seg_num, lnbr);
        !           626: 
        !           627:                cnbr = 0;
        !           628:                xstop = 0;
        !           629:                f.writ = 0;
        !           630:                f.werr = 0;
        !           631:        } else {
        !           632: printf("xlopn failed ");
        !           633:                u.u_error = ENODEV;     /* set no device                */
        !           634:                f.open = 0;
        !           635:        }
        !           636:        xlrel();                        /* release fdc                  */
        !           637:        relfdc();
        !           638:        cmn_err(CE_CONT, "xlopen: xlster %x, xl6sts %x, xlests %x, xl7sts %x\n",
        !           639:           xlster, xl6sts, xlests, xl7sts);
        !           640: #endif
        !           641: }
        !           642: 
        !           643: /************************************************************************
        !           644:  * ftread
        !           645:  *
        !           646:  ***********************************************************************/
        !           647: static int
        !           648: ftread(dev, iop)
        !           649: dev_t dev;
        !           650: IO * iop;
        !           651: {
        !           652:        if (!f.open) {                  /* exit if not open             */
        !           653:                u.u_error = EIO;
        !           654:                return;
        !           655:        }
        !           656:        xlgtdat(iop);
        !           657: }
        !           658: 
        !           659: /************************************************************************
        !           660:  * ftunload
        !           661:  *
        !           662:  ***********************************************************************/
        !           663: static int
        !           664: ftunload()
        !           665: {
        !           666: }
        !           667: 
        !           668: /************************************************************************
        !           669:  * ftwrite
        !           670:  *
        !           671:  ***********************************************************************/
        !           672: static int
        !           673: ftwrite(dev, iop)
        !           674: dev_t dev;
        !           675: IO * iop;
        !           676: {
        !           677:        if (!f.open) {                  /* exit if not open             */
        !           678:                u.u_error = EIO;
        !           679:                return;
        !           680:        }
        !           681:        if (xl6sts & XLSWRP) {          /* exit if write protect        */
        !           682:                u.u_error = EIO;
        !           683:                return;
        !           684:        }
        !           685:        while(fprb = getrb(&data_queue))/* rel any pending read bfrs*/
        !           686:                putrb(&xlfree_q, fprb);/* allows swt from read to write*/
        !           687:        f.writ = 1;                     /* set write flag               */
        !           688:        xlptdat(iop);
        !           689:        if (f.werr)                     /* flag error if occurred       */
        !           690:                u.u_error = EIO;
        !           691: }
        !           692: 
        !           693: /*
        !           694:  * Support routines.
        !           695:  */
        !           696: 
        !           697: /************************************************************************/
        !           698: /*     cmn_err() - doesn't really belong here                          */
        !           699: /************************************************************************/
        !           700: static void
        !           701: cmn_err(level, format)
        !           702: int level;
        !           703: char * format;
        !           704: {
        !           705:        if (XL_VERBOSE)
        !           706:                printf("%r ", &format);
        !           707: }
        !           708: 
        !           709: /************************************************************************/
        !           710: /*     dsperr  display floppy error                                    */
        !           711: /************************************************************************/
        !           712: static int
        !           713: dsperr()
        !           714: {                                      /* disregard fdc ecc error */
        !           715:        if (!(status_buf[ 0 ] == 0x41 &&
        !           716:               status_buf[ 1 ] == 0x20 &&
        !           717:               status_buf[ 2 ] == 0x20)) 
        !           718:                cmn_err(CE_CONT, "fdcerr: ST0=%x ST1=%x ST2=%x\n",
        !           719:                        status_buf[ 0 ], status_buf[ 1 ], status_buf[ 2 ]);
        !           720: }
        !           721: 
        !           722: /*
        !           723:  * For debugging, print command status and interrupt status to console.
        !           724:  */
        !           725: static void
        !           726: ftDbPrtStat()
        !           727: {
        !           728:        int i;
        !           729: 
        !           730:        printf("[[");
        !           731:        if (fdc.fdc_ncmdstat) {
        !           732:                printf("cmd ");
        !           733:                for (i = 0; i < fdc.fdc_ncmdstat; i++)
        !           734:                        printf("%x ", fdc.fdc_cmdstat[i]);
        !           735:        }
        !           736:        if (fdc.fdc_nintstat) {
        !           737:                printf("int ");
        !           738:                for (i = 0; i < fdc.fdc_nintstat; i++)
        !           739:                        printf("%x ", fdc.fdc_intstat[i]);
        !           740:        }
        !           741:        printf("]] ");
        !           742: }
        !           743: 
        !           744: /*
        !           745:  * Given a QIC-117 command number, cause that number of step pulses
        !           746:  * to be sent from the FDC by faking a seek command.
        !           747:  */
        !           748: static int
        !           749: ftCmdSend(cmd)
        !           750: int cmd;
        !           751: {
        !           752:        /* Like NEC - pcn=present cylinder #; ncn=new cylinder #. */
        !           753:        unsigned char ncn;
        !           754:        
        !           755:        xlDbPrintCmd(cmd);
        !           756: 
        !           757:        /*
        !           758:         * Will fake a seek command.
        !           759:         * Figure out whether to simulate seek to lower or higher
        !           760:         * cylinder number.
        !           761:         */
        !           762:        if (ft.ft_pcn + cmd <= MAX_PCN) {
        !           763:                ncn = ft.ft_pcn + cmd;
        !           764:        } else if (ft.ft_pcn - cmd >= 0) {
        !           765:                ncn = ft.ft_pcn - cmd;
        !           766:        } else {
        !           767:                printf("ftCmd %d invalid, pcn %d ", cmd, ft.ft_pcn);
        !           768:                return -1;
        !           769:        }
        !           770: 
        !           771:        ft.ft_dumpIrq = 1;
        !           772:        fdcSeek(unit, 0, ncn);
        !           773: }
        !           774: 
        !           775: /*
        !           776:  * Given a QIC-117 command number, send the command.
        !           777:  * If report bits are expected in response, initialize the bit counter.
        !           778:  * Then sleep until the commmand is done and report bits are gathered.
        !           779:  */
        !           780: static int
        !           781: ftCmd(cmd)
        !           782: int cmd;
        !           783: {
        !           784: #if MWC_FT
        !           785: 
        !           786:        /* Will sleep until command done and report bits are in. */
        !           787:        ft.ft_wakeMeUp = 1;
        !           788: 
        !           789:        /*
        !           790:         * The following commands expect report bits from the tape drive.
        !           791:         * The drive sends a leading ACK bit (always 1), then data bits
        !           792:         * (least significant bit first), then a trailing 1.  So, the
        !           793:         * number of bits needed is 2 more than the number of data bits
        !           794:         * in the report, or zero.
        !           795:         */
        !           796:        switch(cmd) {
        !           797:        case QIC_CMD_STS:
        !           798:        case QIC_CMD_DRVCN:
        !           799:        case QIC_CMD_ROMVN:
        !           800:        case QIC_CMD_TPSTAT:
        !           801:                ft.ft_bitsNeeded = 10;
        !           802:                break;
        !           803:        case QIC_CMD_ECD:
        !           804:        case QIC_CMD_VNDID:
        !           805:                ft.ft_bitsNeeded = 18;
        !           806:                break;
        !           807:        default:
        !           808:                ft.ft_bitsNeeded = 0;
        !           809:        }
        !           810: 
        !           811:        ftCmdSend(cmd);
        !           812: 
        !           813:        if (x_sleep(&ft.ft_wakeMeUp, pritape, slpriSigCatch, "ftCmd"))
        !           814:                return -1;
        !           815:        else
        !           816:                return 0;
        !           817: #else
        !           818:        sekcms[ 1 ] = unit;
        !           819:        if (sekcms[ 2 ] > 80)
        !           820:                sekcms[ 2 ] -= cnt;
        !           821:        else
        !           822:                sekcms[ 2 ] += cnt;
        !           823:        xlfdc_out_str(sekcms, 3);       /* start seek cmd               */
        !           824: #endif
        !           825: }
        !           826: 
        !           827: /*
        !           828:  * Interrupt handler.
        !           829:  */
        !           830: static void
        !           831: ftIrqHandler()
        !           832: {
        !           833:        /*
        !           834:         * Need to get FDC status from result phase, and clear interrupt
        !           835:         * that may have been generated by diskette change or seek/recal
        !           836:         * complete.
        !           837:         */
        !           838:        if (FDC_BUSY()) {
        !           839:                fdcCmdStatus();
        !           840:        } else {
        !           841:                /* After seek or recal, must Sense Interrupt to clear IRQ. */
        !           842:                fdcIntStatus();
        !           843: 
        !           844:                /* Update present cylinder number. */
        !           845:                if (fdc.fdc_nintstat >= 2)
        !           846:                        ft.ft_pcn = fdc.fdc_intstat[1];
        !           847:        }
        !           848: 
        !           849:        /*
        !           850:         * If report bits are needed
        !           851:         *   Get current report bit.
        !           852:         *   Update number of bits needed.
        !           853:         */
        !           854:        if (ft.ft_bitsNeeded) {
        !           855:                ft.ft_bitsNeeded--;
        !           856: 
        !           857:                /*
        !           858:                 * Need unit # for Sense Drive Status command.
        !           859:                 * Get it from preceding Sense Interrupt command.
        !           860:                 */
        !           861:                if (fdc.fdc_nintstat > 1) {
        !           862:                        unit = fdc.fdc_intstat[0] & 3;
        !           863:                        ft.ft_senseDrvStat = 0;
        !           864:                        fdcDrvStatus(unit, 0);  /* Send FDC command.            */
        !           865:                        fdcCmdStatus();         /* Stash command result.        */
        !           866:                } else {
        !           867:                        printf("missing int status \n");
        !           868:                }
        !           869: 
        !           870:                if (fdc.fdc_ncmdstat == 1) {
        !           871:                        int bit;
        !           872:                        bit = (fdc.fdc_cmdstat[0] & ST3_T0) ? 1 : 0;
        !           873:                        printf("<%d>", bit);
        !           874:                } else {
        !           875:                        printf("rnb status bad ");
        !           876:                }
        !           877:        }
        !           878: 
        !           879:        /*
        !           880:         * If more report bits will be needed
        !           881:         *   Send request for next bit.
        !           882:         * Else
        !           883:         *   See if original requestor needs wakeup, etc.
        !           884:         */
        !           885:        if (ft.ft_bitsNeeded) {
        !           886:                ftCmdSend(QIC_CMD_RNB);
        !           887:        } else {
        !           888:                if (ft.ft_wakeMeUp) {
        !           889:                        ft.ft_wakeMeUp = 0;
        !           890:                        wakeup(&ft.ft_wakeMeUp);
        !           891:                }
        !           892:        }
        !           893: 
        !           894:        /* Print debug output if needed. */
        !           895:        if (ft.ft_dumpIrq) {
        !           896:                ft.ft_dumpIrq = 0;
        !           897:                defer(ftDbPrtStat);
        !           898:        }
        !           899: }
        !           900: 
        !           901: /*
        !           902:  * Send Recalibrate command to FDC and wait for it to finish.
        !           903:  *
        !           904:  * Return 0 if normal operation, -1 if signaled before recal complete.
        !           905:  */
        !           906: static int
        !           907: ftRecal(unit)
        !           908: int unit;
        !           909: {
        !           910:        ft.ft_wakeMeUp = 1;
        !           911:        fdcRecal(unit);
        !           912:        if (x_sleep(&ft.ft_wakeMeUp, pritape, slpriSigCatch, "ftRecal"))
        !           913:                return -1;
        !           914:        else
        !           915:                return 0;
        !           916: }
        !           917: 
        !           918: /*
        !           919:  * Select tape unit.
        !           920:  */
        !           921: static void
        !           922: ftSelect(unit)
        !           923: int unit;
        !           924: {
        !           925:        fdcRate(FDC_RATE_500K);         /* set transfer rate            */
        !           926:        fdcDrvSelect(unit, 1);          /* 1=motor on                   */
        !           927:        fdcResetSel();                  /* Reset, preserving selection  */
        !           928:        fdcSpecify(FT_SRT, FT_HUT, FT_HLT);
        !           929: 
        !           930:        /* 80 MB nseg_p_track = 100, nseg_p_head = 600, nseg_p_cyl = 4  */
        !           931:        /* 40 MB nseg_p_track = 68, nseg_p_head = 680, nseg_p_cyl = 4   */
        !           932:        if (ftfmt) {
        !           933:                nseg_p_track = 100;     /* set for 80 MB drive          */
        !           934:                nseg_p_head = 600;
        !           935:                nseg_p_cyl = 4;
        !           936:        } else {
        !           937:                nseg_p_track = 68;      /* set for 40 MB drive          */
        !           938:                nseg_p_head = 680;
        !           939:                nseg_p_cyl = 4;
        !           940:        }
        !           941: }
        !           942: 
        !           943: /************************************************************************
        !           944:  * getmem
        !           945:  *
        !           946:  * Grab XL_NBUFS # of 32k DMA buffers.
        !           947:  * Only use 16k of one of these, for QIC headers.
        !           948:  *
        !           949:  * Return 0 on success, 1 on failure.
        !           950:  ***********************************************************************/
        !           951: static int
        !           952: getmem()
        !           953: {
        !           954:        register        int     i, nb;
        !           955:        struct          rb      *prb;
        !           956:        unsigned int    tmpad, highAddr;
        !           957: 
        !           958:        if (xlmem_allocated)
        !           959:                return 0;
        !           960: 
        !           961:        nb = XL_NBUFS;
        !           962:        if (nb < 4)
        !           963:                nb = 4;
        !           964: 
        !           965:        rbmp = (struct rb *)kalloc(XL_NBUFS * sizeof(struct rb));
        !           966:        if (rbmp == NULL) {
        !           967:                printf("XL: initial kalloc() failed\n");
        !           968:                return 1;
        !           969:        }
        !           970: 
        !           971:        allocated_add = getDmaMem(nb * BFRSZ, BFRSZ);
        !           972:        if (allocated_add == NULL) {
        !           973:                printf("XL: getDmaMem() failed\n");
        !           974:                return 1;
        !           975:        }
        !           976: 
        !           977:        highAddr = allocated_add + (nb * BFRSZ);
        !           978: 
        !           979:        cmn_err(CE_CONT, "Allocated %d buffers.  Virtual <%x-%x>.  "
        !           980:          "Physical <%x-%x>.\n",
        !           981:          nb, allocated_add, highAddr, vtop(allocated_add), vtop(highAddr));
        !           982: 
        !           983:        /* tmpad = 1st 32k bfr adr                      */
        !           984:        tmpad = (allocated_add + BFRSZ);
        !           985: 
        !           986:        ptr_header = (fplng)allocated_add;
        !           987: 
        !           988:        xlfree_q.top = prb = rbmp;/* build free pool    */
        !           989:        for (i = 0; i < (nb - 1); ++i) {
        !           990:                xlfree_q.bot = prb;
        !           991:                ++prb;
        !           992:                xlfree_q.bot->nxt = prb;
        !           993:                xlfree_q.bot->adr = tmpad;
        !           994:                tmpad += BFRSZ;
        !           995:        }
        !           996:        xlfree_q.bot->nxt = 0;
        !           997: 
        !           998:        cmn_err(CE_CONT, "getmem: allocated %d buffers\n", nb);
        !           999: 
        !          1000:        xlmem_allocated = 1;
        !          1001:        data_queue.top = 0;
        !          1002:        data_queue.bot = 0;
        !          1003:        return 0;
        !          1004: }
        !          1005: 
        !          1006: /************************************************************************/
        !          1007: /*     getrb   get request buffer from queue                           */
        !          1008: /************************************************************************/
        !          1009: static struct  rb *
        !          1010: getrb(prbq)
        !          1011: struct rbq     *prbq;
        !          1012: {
        !          1013:        struct  rb *prb;
        !          1014:        int     ilv;
        !          1015: 
        !          1016:        if (0 == (prb = prbq->top))     /* return if empty              */
        !          1017:                return 0;
        !          1018:        ilv = spl5();                   /* playing with queue           */
        !          1019:        prbq->top = prb->nxt;           /* advance top ptr              */
        !          1020:        if (0 == prbq->top)
        !          1021:                prbq->bot = 0;
        !          1022:        splx(ilv);                      /* done with queue              */
        !          1023:        return prb;
        !          1024: }
        !          1025: 
        !          1026: /************************************************************************/
        !          1027: /*     putrb   add req buf to end of queue                             */
        !          1028: /*     return 1 if added to empty queue                                */
        !          1029: /************************************************************************/
        !          1030: static int
        !          1031: putrb(prbq, prb)
        !          1032: struct rbq     *prbq;
        !          1033: struct rb      *prb;
        !          1034: {
        !          1035:        int     ilv;
        !          1036: 
        !          1037:        prb->nxt = 0;                   /* reset this buf's fwd ptr     */
        !          1038:        ilv = spl5();                   /* playing with queues          */
        !          1039:        if (0 == prbq->top) {           /* if empty queue,              */
        !          1040:                prbq->top = prb;        /* pnt top and bot to new buf   */
        !          1041:                prbq->bot = prb;
        !          1042:                splx(ilv);
        !          1043:                return 1;
        !          1044:        } else {
        !          1045:                (prbq->bot)->nxt = prb;/* else pnt old end to new buf   */
        !          1046:                prbq->bot = prb;        /* and bot to new buf           */
        !          1047:                splx(ilv);
        !          1048:                return 0;
        !          1049:        }
        !          1050: }
        !          1051: 
        !          1052: /************************************************************************/
        !          1053: /*     stdma    set dma                                                */
        !          1054: /************************************************************************/
        !          1055: static void
        !          1056: stdma(mode, adr, count)
        !          1057: int    mode;
        !          1058: paddr_t        adr;
        !          1059: int    count;
        !          1060: {
        !          1061:        cmn_err(CE_CONT, "dir: %x Vadd: %x, Padd: %x, count: %x\n",
        !          1062:          mode, adr, kvtophys(adr), count);
        !          1063: 
        !          1064:        /* dma_param(DMA_CH2, mode, kvtophys(adr), count - 1); */
        !          1065:        /* dma_enable(DMA_CH2); */
        !          1066:        xldma((char)(mode + DMA_CH2), (long)kvtophys(adr), count - 1);
        !          1067: }
        !          1068: 
        !          1069: /************************************************************************/
        !          1070: /*     strbfm  set up rb params for format                             */
        !          1071: /************************************************************************/
        !          1072: static void
        !          1073: strbfm(prb)
        !          1074: struct rb      *prb;
        !          1075: {
        !          1076:        register fpchr  p0;
        !          1077:        register int d0;
        !          1078:        int     d1;
        !          1079: 
        !          1080:        d0 = prb->sgn;                  /* get segment #                */
        !          1081:        prb->hed = d0/nseg_p_head;      /* set up fdc params            */
        !          1082:        d0 = d0 % nseg_p_head;
        !          1083:        prb->cyl = d0/nseg_p_cyl;
        !          1084:        prb->sct = ((d0 % nseg_p_cyl) << 5) + 1;
        !          1085: 
        !          1086:        p0 = (fpchr)cprb->adr;
        !          1087: 
        !          1088:        /*                              fill format bfr                 */
        !          1089: 
        !          1090:        d0 = prb->sct;
        !          1091:        for (d1 = d0 + 32; d0 != d1; ++d0) {
        !          1092:                *p0++ = prb->cyl;
        !          1093:                *p0++ = prb->hed;
        !          1094:                *p0++ = d0;
        !          1095:                *p0++ = 3;
        !          1096:        }
        !          1097: }
        !          1098: 
        !          1099: /************************************************************************/
        !          1100: /*     strbsg  set up rb params for segment                            */
        !          1101: /*             should be called at task time                           */
        !          1102: /*                                                                     */
        !          1103: /*     rb.tbl  is used to skip bad sectors in segments.                */
        !          1104: /*             segments are split up into "chunks"                     */
        !          1105: /*             index into rb.tbl with relative sector.                 */
        !          1106: /*             each word in rb.tbl:                                    */
        !          1107: /*             bits 15-10:  sector count for chunk                     */
        !          1108: /*             bits  9- 5:  dma offset for chunk                       */
        !          1109: /*             bits  4- 0:  sector # for chunk                         */
        !          1110: /************************************************************************/
        !          1111: static void
        !          1112: strbsg(prb)
        !          1113: struct rb      *prb;
        !          1114: {
        !          1115:        register int    d0, d1, d2;
        !          1116:        ushort          *p0;
        !          1117: 
        !          1118:        prb->erc = 0;                   /* reset error count            */
        !          1119:        d0 = prb->sgn;                  /* set tape params              */
        !          1120:        prb->trk = d0 / nseg_p_track;
        !          1121:        prb->tps = d0 % nseg_p_track;
        !          1122:        prb->hed = d0 / nseg_p_head;    /* set up fdc params            */
        !          1123:        d0 = d0 % nseg_p_head;
        !          1124:        prb->cyl = d1 = d0 / nseg_p_cyl;
        !          1125:        prb->sct = d0 = ((d0 % nseg_p_cyl) << 5) + 1;
        !          1126:        if (d0 == 1) {                  /* set up position params       */
        !          1127:                --d1;
        !          1128:                d0 = (nseg_p_cyl << 5) - 16;
        !          1129:        }
        !          1130:        else
        !          1131:                d0 -= 16;
        !          1132:        prb->idc = d1;
        !          1133:        prb->ids = d0;
        !          1134:        d2 = 32;                        /* set up rb.tbl                */
        !          1135:        sgwrd = 0;
        !          1136:        sgmap = prb->map;
        !          1137:        p0 = prb->tbl;
        !          1138:        prb->nbk = 0;
        !          1139:        while(d2) {
        !          1140:                d0 = d2;                /* d0 = # scts to skip          */
        !          1141:                while(sgmap & 1) {
        !          1142:                        --d2;
        !          1143:                        sgmap >>= 1;
        !          1144:                }
        !          1145:                d0 -= d2;
        !          1146:                sgwrd += d0;            /* bump sct # in sgwrd          */
        !          1147:                if (!d2)                /* exit if done                 */
        !          1148:                        break;
        !          1149:                d1 = d2;                /* d1 = # scts this chunk       */
        !          1150:                while(d2 && 0 == (sgmap & 1)) {
        !          1151:                        --d2;
        !          1152:                        sgmap >>= 1;
        !          1153:                }
        !          1154:                d1 -= d2;
        !          1155:                prb->nbk += d1;         /* adjust # blocks in segment   */
        !          1156:                sgwrd += d1 << 10;      /* set count in sgwrd           */
        !          1157:                while(d0) {             /* fill table for skipped scts  */
        !          1158:                        *p0++ = sgwrd;
        !          1159:                        --d0;
        !          1160:                }
        !          1161:                while(d1) {             /* for each sct xferred         */
        !          1162:                        *p0++ = sgwrd;  /* store table entry            */
        !          1163:                        sgwrd += 0xfc21;/* dec cnt, bump ofset bump sct */
        !          1164:                        --d1;
        !          1165:                }
        !          1166:        }
        !          1167:        for (++d0; d0; --d0)            /* zero out rest of rb.tbl      */
        !          1168:                *p0++ = 0;
        !          1169: }
        !          1170: 
        !          1171: /************************************************************************/
        !          1172: /*     stseg   set up segment io                                       */
        !          1173: /************************************************************************/
        !          1174: static void
        !          1175: stseg(prb)
        !          1176: struct rb      *prb;
        !          1177: {
        !          1178:        rwdcms[ 1 ] = unit;             /* set rwdcmd constants         */
        !          1179:        rwdcms[ 2 ] = prb->cyl;
        !          1180:        rwdcms[ 3 ] = prb->hed;
        !          1181:        xadr = prb->adr;                /* set base adr                 */
        !          1182:        xsct = prb->sct;                /* set base sct                 */
        !          1183:        xrty = 6;                       /* set default # retries        */
        !          1184: }
        !          1185: 
        !          1186: /************************************************************************/
        !          1187: /*     wvtbl   create volume table entry                               */
        !          1188: /************************************************************************/
        !          1189: static void
        !          1190: wvtbl()
        !          1191: {
        !          1192:        xlvtbl  *p;
        !          1193:        int     ilvl;
        !          1194:        int     i;
        !          1195: 
        !          1196:        ilvl = spl5();                  /*   wait for a new buffer      */
        !          1197:        while(!(cprb = getrb(&xlfree_q))) {
        !          1198:                if (!f.actv)
        !          1199:                        xlque();
        !          1200:                xlfreew = 1;
        !          1201:                sleep(&xlfreew, PRIBIO);
        !          1202:        }
        !          1203:        splx(ilvl);
        !          1204:        p = (xlvtbl *)cprb->adr;
        !          1205:        wptr = (fpchr)p;                /* save ptr for encode          */
        !          1206:        for (i = 0; vtbl[ i ]; ++i)
        !          1207:                p->ident[ i ] = vtbl[ i ];
        !          1208:        p->data_seg_num = (unsigned short)data_seg_num;
        !          1209:        p->last_seg_num = (unsigned short)curr_seg_num - 1;
        !          1210:        for (i = 0; p->op_system[ i ] = xnxnm[ i ]; ++i);
        !          1211: 
        !          1212:        for (ilvl = 0; ilvl < 43; ++ilvl)       /* fill zero not implemented */ 
        !          1213:                p->p1[ ilvl ] = 0;
        !          1214:        p->c_seq_num = 1;                       /* cartridge sequence # =1   */
        !          1215: 
        !          1216:        for (ilvl = 0; ilvl < 34; ++ilvl)       /* fill zero                 */
        !          1217:                p->p3[ ilvl ] = 0;
        !          1218: 
        !          1219:        p->last_blk_size = (unsigned short)(lnbr - cnbr);
        !          1220:        cprb->sgn = volume_seg_num;
        !          1221:        cprb->map = ptr_header[ volume_seg_num + 0x200 ];
        !          1222:        cprb->fun = RBFWT;
        !          1223:        strbsg(cprb);
        !          1224:        xl_enc(wptr, cprb->nbk);
        !          1225:        putrb(&req, cprb);
        !          1226:        ilvl = spl5();
        !          1227:        if (!f.actv)
        !          1228:                xlque();
        !          1229:        splx(ilvl);
        !          1230: }
        !          1231: 
        !          1232: /************************************************************************/
        !          1233: /*     xlcal()         calibrate drive                                 */
        !          1234: /*                     exits via (*xlosb)()                            */
        !          1235: /************************************************************************/
        !          1236: static void
        !          1237: xlcal()
        !          1238: {
        !          1239:        if (xlster) {                   /* exit if error                */
        !          1240:                (*pfcal)();
        !          1241:                return;
        !          1242:        }
        !          1243:        f.cal = 0;                      /* reset calibrate sent flag    */
        !          1244:        pfrdy = xlcal0;                 /* wait for ready               */
        !          1245:        xlready();
        !          1246: }
        !          1247: 
        !          1248: static void
        !          1249: xlcal0()
        !          1250: {
        !          1251:        if (xlster) {                   /* exit if error                */
        !          1252:                (*pfcal)();
        !          1253:                return;
        !          1254:        }
        !          1255:        if ((xl6sts & 0xf7) == 0x65) {/* if ok, seek track 0, exit      */
        !          1256: printf("xlcal:Seek tk 0 ");
        !          1257:                tptrk = 0;
        !          1258:                pfsek = pfcal;
        !          1259:                xlseek();
        !          1260:                return;
        !          1261:        }
        !          1262:        if ((xl6sts & XLSREF) == 0) {/* if not referenced               */
        !          1263: printf("xlcal:calibrate ");
        !          1264:                if (f.cal) {            /* and calibrate sent, exit     */
        !          1265:                        (*pfcal)();
        !          1266:                        return;
        !          1267:                }
        !          1268:                f.cal = 1;              /* else send calibrate          */
        !          1269:                pfint = xlready;
        !          1270:                xloutput_step(QIC_CMD_CAL);
        !          1271:                return;
        !          1272:        }
        !          1273:        pfint = xlready;                /* rewind tape                  */
        !          1274:        xloutput_step(QIC_CMD_BOT);
        !          1275: }
        !          1276: 
        !          1277: /************************************************************************/
        !          1278: /*     xlcomplete  interrupt sequence complete                         */
        !          1279: /************************************************************************/
        !          1280: static void
        !          1281: xlcomplete()
        !          1282: {
        !          1283:        pfint = xlnull;                 /* clean up int handler         */
        !          1284:        xlcompf = 1;                    /* indicate completion          */
        !          1285:        if (xlcompw) {                  /* wake up if waiting           */
        !          1286:                xlcompw = 0;
        !          1287:                wakeup(&xlcompw);
        !          1288:        }
        !          1289: }
        !          1290: 
        !          1291: /************************************************************************/
        !          1292: /*     xldelay         delay for cnt ticks                             */
        !          1293: /************************************************************************/
        !          1294: static void
        !          1295: xldelay(cnt)
        !          1296: int    cnt;
        !          1297: {
        !          1298:        if (cnt)
        !          1299:                timeout(&xldly, cnt, pfdly, 0);
        !          1300:        else
        !          1301:                timeout(&xldly, cnt, NULL, 0);
        !          1302: }
        !          1303: 
        !          1304: /************************************************************************/
        !          1305: /*     xldma                                                           */
        !          1306: /************************************************************************/
        !          1307: static void
        !          1308: xldma(rw, addr, count)
        !          1309: char   rw;
        !          1310: long   addr;
        !          1311: int    count;
        !          1312: {
        !          1313:        int     oldpri;
        !          1314: 
        !          1315:        oldpri = sphi();
        !          1316:        outb(DMA1CBPFF, 0);
        !          1317:        outb(DMA1WMR, rw);
        !          1318:        outb(DMA1BCA2, addr & 0xff);
        !          1319:        outb(DMA1BCA2, (addr >> 8) & 0xff);
        !          1320:        outb(DMACH2PG, (addr >> 16) & 0xff);
        !          1321:        tenmicrosec();
        !          1322:        outb(DMA1BCWC2, count & 0xff);
        !          1323:        outb(DMA1BCWC2, (count >> 8) & 0xff);
        !          1324:        spl(oldpri);
        !          1325:        outb(DMA1WSMR, 2);
        !          1326: }
        !          1327: 
        !          1328: /************************************************************************/
        !          1329: /*     xlfdc_in_byte   input byte from fdc                             */
        !          1330: /************************************************************************/
        !          1331: static unchar
        !          1332: xlfdc_in_byte()                                /* input byte from fdc          */
        !          1333: {
        !          1334:        register int    d0;
        !          1335: 
        !          1336:        for (d0 = FDTMO; d0; --d0) {    /* wait for ready               */
        !          1337: 
        !          1338:                /* Wait for Request from Master asserted. */
        !          1339:                if (inb(FDSTAT) & 0x80) {
        !          1340:                        /* exit if in output mode                       */
        !          1341:                        if ((inb(FDSTAT) & 0x40) == 0)
        !          1342:                                return(status_buf[ 7 ] = -1);
        !          1343:                        return(inb(FDDATA));
        !          1344:                }
        !          1345:        }
        !          1346:        return(status_buf[ 7 ] = -1);   /* exit if timeout              */
        !          1347: }
        !          1348: 
        !          1349: /************************************************************************/
        !          1350: /*     xlfdc_out_byte  output byte to fdc                              */
        !          1351: /************************************************************************/
        !          1352: static unchar
        !          1353: xlfdc_out_byte(chr)                    /* output byte to fdc           */
        !          1354: int    chr;
        !          1355: {
        !          1356:        register int    d0;
        !          1357: 
        !          1358:        for (d0 = FDTMO; d0; --d0) {    /* wait for ready               */
        !          1359: 
        !          1360:                /* Wait for Request from Master asserted. */
        !          1361:                if (inb(FDSTAT) & 0x80) {
        !          1362:                        /* exit if in status mode                       */
        !          1363:                        if (inb(FDSTAT) & 0x40)
        !          1364:                                return(status_buf[ 7 ] = -1);
        !          1365:                        outb(FDDATA, chr);      /* output byte, exit ok */
        !          1366:                        return 0;
        !          1367:                }
        !          1368:        }
        !          1369:        return(status_buf[ 7 ] = -1);   /* exit if timeout              */
        !          1370: }
        !          1371: 
        !          1372: /************************************************************************/
        !          1373: /*     xlfdc_out_str   output cmd string to fdc                        */
        !          1374: /************************************************************************/
        !          1375: static unchar
        !          1376: xlfdc_out_str(cms, cnt)                /* output command string        */
        !          1377: unchar *cms;
        !          1378: int    cnt;
        !          1379: {
        !          1380:        register unchar *p0, *p1;
        !          1381: 
        !          1382:        p0 = cms;                       /* set up for output            */
        !          1383:        fdcmd = *p0;                    /* save command type            */
        !          1384:        for (p1 = p0 + cnt; p0 != p1; ++p0) {
        !          1385:                if (xlfdc_out_byte((int)(*p0)))/* stop if error */
        !          1386:                        break;
        !          1387:        }
        !          1388:        return(status_buf[ 7 ]);         /* exit ok                     */
        !          1389: }
        !          1390: 
        !          1391: /************************************************************************/
        !          1392: /*     xlfdc_reset     reset fdc                                       */
        !          1393: /************************************************************************/
        !          1394: static void
        !          1395: xlfdc_reset()                          /* fdc reset                    */
        !          1396: {
        !          1397:        sekcms[ 1 ] = 0xff;
        !          1398:        status_buf[ 7 ] = 0;            /* reset error flag             */
        !          1399:        outb(FDCTRL, fdselr);           /* reset fdc                    */
        !          1400:        outb(FDCTRL, fdsel);
        !          1401: }
        !          1402: 
        !          1403: /************************************************************************/
        !          1404: /*     xlflush flush any pending io's                                  */
        !          1405: /************************************************************************/
        !          1406: static void
        !          1407: xlflush(dev)
        !          1408: {
        !          1409:        int     ilvl;
        !          1410: 
        !          1411:        xstop = 1;                      /* stop any pending reads       */
        !          1412:        if (f.writ) {                   /* flush any pending writes     */
        !          1413:                if (cnbr && cprb->fun == RBFWT) {
        !          1414:                        xl_enc(wptr, cprb->nbk);
        !          1415:                        putrb(&req, cprb);
        !          1416:                }
        !          1417:                ilvl = spl5();
        !          1418:                if (!f.actv)
        !          1419:                        xlque();
        !          1420:                splx(ilvl);
        !          1421:                wvtbl();
        !          1422:        }
        !          1423:        ilvl = spl5();                  /* wait for idle state          */
        !          1424:        while(f.actv) {
        !          1425:                xlnactw = 1;
        !          1426:                sleep(&xlnactw, PRIBIO);
        !          1427:        }
        !          1428:        splx(ilvl);
        !          1429:        cnbr = 0;
        !          1430:        xstop = 0;
        !          1431:        while(cprb = getrb(&data_queue))/* relse pending read bfrs      */
        !          1432:                putrb(&xlfree_q, cprb);
        !          1433:        while(cprb = getrb(&req))       /* release any pending que bfrs */
        !          1434:                putrb(&xlfree_q, cprb);
        !          1435: }
        !          1436: 
        !          1437: /************************************************************************/
        !          1438: /*     xlfmq   format queue handler                                    */
        !          1439: /************************************************************************/
        !          1440: static void
        !          1441: xlfmq()
        !          1442: {
        !          1443:        while(xprb = getrb(&req)) {     /* while more to do             */
        !          1444:                if (!f.actv) {          /* if not active, start tape    */
        !          1445:                        f.actv = 1;
        !          1446:                        f.tmov = 1;
        !          1447:                        pfint = xlfmq0;
        !          1448:                        xloutput_step(QIC_CMD_FWD);
        !          1449:                        return;
        !          1450:                }
        !          1451:                else{
        !          1452:                        pffms = xlfmq1; /* else, continue format        */
        !          1453:                        xlfms();
        !          1454:                        return;
        !          1455:                }
        !          1456:        }
        !          1457: 
        !          1458:        pfrdy = xlfmq2;                 /* wait for tape stopped        */
        !          1459:        xlready();
        !          1460:        return;
        !          1461: }
        !          1462: 
        !          1463: static void
        !          1464: xlfmq0()
        !          1465: {
        !          1466:        pffms = xlfmq1;
        !          1467:        xlfms();
        !          1468:        return;
        !          1469: }
        !          1470: 
        !          1471: static void
        !          1472: xlfmq1()
        !          1473: {
        !          1474:        if (xprb->sts)          /* set f.werr if error          */
        !          1475:                f.werr = 1;
        !          1476:        putrb(&xlfree_q, xprb); /* relse bfr back to free pool  */
        !          1477:        if (xlfreew) {                  /* wakeup if needed             */
        !          1478:                xlfreew = 0;
        !          1479:                wakeup(&xlfreew);
        !          1480:        }
        !          1481:        xlfmq();                        /* start next i/o               */
        !          1482: }
        !          1483: 
        !          1484: static void
        !          1485: xlfmq2()
        !          1486: {
        !          1487:        if (xlnactw) {                  /* if sleepg on xlnactw, wakeup */
        !          1488:                xlnactw = 0;
        !          1489:                wakeup(&xlnactw);
        !          1490:        }
        !          1491:        f.actv = 0;                     /* rset actv, moving flgs, exit */
        !          1492:        f.tmov = 0;
        !          1493:        return;
        !          1494: }
        !          1495: 
        !          1496: /************************************************************************/
        !          1497: /*     xlfms   format a segment                                        */
        !          1498: /************************************************************************/
        !          1499: static void
        !          1500: xlfms()
        !          1501: {
        !          1502:        pfint = xlfm0;                  /* set up for format            */
        !          1503:        xprb->sts = 0;
        !          1504:        if (f.werr) {                   /* if error, do idle int        */
        !          1505:                xloutput_step(0);
        !          1506:                return;
        !          1507:        }
        !          1508:        fmtcms[ 1 ] = unit;
        !          1509:        stdma(DMA_Wrmode, xprb->adr, 128);
        !          1510: 
        !          1511:        xltimout(IOTMO);                /* do the format                */
        !          1512:        xlfdc_out_str(fmtcms, 6);
        !          1513:        if (status_buf[ 7 ]) {          /* exit if nec error            */
        !          1514:                xltimout(0);
        !          1515:                xlster |= XLSNEC;
        !          1516:                xprb->sts = 1;
        !          1517:                pfint = xlnull;
        !          1518:                (*pffms)();
        !          1519:                return;
        !          1520:        }
        !          1521: }
        !          1522: 
        !          1523: static void
        !          1524: xlfm0()
        !          1525: {
        !          1526:        if (status_buf[ 0 ] & 0xc0)
        !          1527:                xprb->sts = 1;
        !          1528:        (*pffms)();
        !          1529: }
        !          1530: 
        !          1531: /************************************************************************/
        !          1532: /*     xlformat                format tape, task time                  */
        !          1533: /************************************************************************/
        !          1534: static int
        !          1535: xlformat(ntrkf)
        !          1536: int    ntrkf;
        !          1537: {
        !          1538:        int     ilvl, i;
        !          1539:        fplng   p0;
        !          1540: 
        !          1541:        cmn_err(CE_CONT, "xlformat: formatting %d tracks\n", ntrkf);
        !          1542: 
        !          1543:        pfint = xlready;                /* rewind tape                  */
        !          1544:        pfrdy = xlcomplete;
        !          1545:        xloutput_step(QIC_CMD_BOT);
        !          1546:        xlwait();
        !          1547:        if (xlster)
        !          1548:                return 2;
        !          1549: 
        !          1550:        bcopy((fpchr)xnxvs, ptr_header, 20);    /* init header          */
        !          1551:        bcopy(ptr_header + 4, ptr_header + 5, 16 * 1024 - 20);
        !          1552: 
        !          1553:        pfint = xlcomplete;             /* format mode                  */
        !          1554:        xloutput_step(QIC_CMD_FMD);
        !          1555:        xlwait();
        !          1556: 
        !          1557:        cmn_err(CE_CONT, "writing reference bursts...\n");
        !          1558:        pfint = xlready;
        !          1559:        pfrdy = xlcomplete;
        !          1560:        xloutput_step(QIC_CMD_WRF);     /* start wrt reference bursts   */
        !          1561:        xlwait();
        !          1562: 
        !          1563:        cmn_err(CE_CONT, "reference bursts write done, starting format...\n");
        !          1564: 
        !          1565:        f.werr = 0;
        !          1566: 
        !          1567:        for (fmtrk = 0; fmtrk < ntrkf; fmtrk += 2) {
        !          1568: 
        !          1569:                tptrk = fmtrk;          /* set tape track               */
        !          1570:                curr_seg_num = fmtrk * nseg_p_track;
        !          1571: 
        !          1572:                pfint = xlcomplete;     /* normal mode                  */
        !          1573:                xloutput_step(QIC_CMD_NMD);
        !          1574:                xlwait();
        !          1575: 
        !          1576:                pfint = xlcomplete;     /* format mode                  */
        !          1577:                xloutput_step(QIC_CMD_FMD);
        !          1578:                xlwait();
        !          1579:                /*                              format a track pair     */
        !          1580:                do{
        !          1581:                        cmn_err(CE_CONT, "\tformatting track %d\n", tptrk);
        !          1582:                        pfsek = xlcomplete;     /* seek to track        */
        !          1583:                        xlseek();
        !          1584:                        xlwait();
        !          1585:                        for (last_seg_num = curr_seg_num + nseg_p_track; curr_seg_num != last_seg_num; ++curr_seg_num) {
        !          1586:                                /* wait for a new buffer                */
        !          1587:                                ilvl = spl5();  
        !          1588:                                while(!(cprb = getrb(&xlfree_q))) {
        !          1589:                                        if (!f.actv)
        !          1590:                                                xlfmq();
        !          1591:                                        xlfreew = 1;
        !          1592:                                        sleep(&xlfreew, PRIBIO);
        !          1593:                                }
        !          1594:                                splx(ilvl);
        !          1595:                                /* set up buffer                        */
        !          1596:                                cprb->sgn = curr_seg_num;
        !          1597:                                strbfm(cprb);
        !          1598:                                putrb(&req, cprb);
        !          1599:                        }       /* queue up format request              */
        !          1600: 
        !          1601:                        ilvl = spl5();  /* track done, wait for idle    */
        !          1602:                        while(f.actv) {
        !          1603:                                xlnactw = 1;
        !          1604:                                sleep(&xlnactw, PRIBIO);
        !          1605:                        }
        !          1606:                        splx(ilvl);
        !          1607:                        ++tptrk;
        !          1608:                }  while(tptrk & 1);
        !          1609:                if (f.werr) {           /* exit if error formatting     */
        !          1610:                        pfprk = xlcomplete;
        !          1611:                        xlpark();
        !          1612:                        xlwait();
        !          1613:                        return 1;
        !          1614:                }
        !          1615: 
        !          1616:                /*                              verify a track pair     */
        !          1617:                pfint = xlcomplete;     /* normal mode                  */
        !          1618:                xloutput_step(QIC_CMD_NMD);
        !          1619:                xlwait();
        !          1620: 
        !          1621:                pfint = xlcomplete;     /* verify mode                  */
        !          1622:                xloutput_step(QIC_CMD_VMD);
        !          1623:                xlwait();
        !          1624: 
        !          1625:                /* set up for verify                                    */
        !          1626:                curr_seg_num = fmtrk * nseg_p_track;
        !          1627:                xlrel();
        !          1628:                relfdc();
        !          1629:                vftrk = -1;
        !          1630: 
        !          1631:                read_ahead_seg_num = curr_seg_num;/* queue up requests  */
        !          1632:                while(cprb = getrb(&xlfree_q)) {
        !          1633:                        cprb->sgn = read_ahead_seg_num;
        !          1634:                        cprb->map = 0L;
        !          1635:                        cprb->fun = RBFRD;
        !          1636:                        strbsg(cprb);
        !          1637:                        cprb->erc = 3;  /* no errors allowed            */
        !          1638:                        putrb(&req, cprb);
        !          1639:                        ++read_ahead_seg_num;
        !          1640:                }
        !          1641:                for (last_seg_num = curr_seg_num + 2 * nseg_p_track; curr_seg_num != last_seg_num; ++curr_seg_num ) {
        !          1642:                        ilvl = spl5();  /* wait for a new buffer        */
        !          1643:                        while(!(cprb = getrb(&data_queue))) {
        !          1644:                                if (!f.actv)
        !          1645:                                        xlque();
        !          1646:                                xldataw = 1;
        !          1647:                                sleep(&xldataw, PRIBIO);
        !          1648:                        }
        !          1649:                        splx(ilvl);
        !          1650:                        if (vftrk != cprb->trk) {
        !          1651:                                vftrk = cprb->trk;
        !          1652:                                cmn_err(CE_CONT, "\tverifying track %d\n", vftrk);
        !          1653:                        }
        !          1654:                        if (cprb->sts) /* mask out segment if error     */
        !          1655:                                *(ptr_header + 0x200 + cprb->sgn) = 0xffffffffL;
        !          1656:                        /* generate another request or                  */
        !          1657:                        if (read_ahead_seg_num != last_seg_num) {
        !          1658:                                cprb->sgn = read_ahead_seg_num;
        !          1659:                                cprb->map = 0L;
        !          1660:                                cprb->fun = RBFRD;
        !          1661:                                strbsg(cprb);
        !          1662:                                cprb->erc = 3;
        !          1663:                                putrb(&req, cprb);
        !          1664:                                ++read_ahead_seg_num;
        !          1665:                        } else {
        !          1666:                                putrb(&xlfree_q, cprb);
        !          1667:                        }
        !          1668:                }       /*  release buffer                              */
        !          1669: 
        !          1670:                ilvl = spl5();  /* track pair done, wait for idle       */
        !          1671:                while(f.actv) {
        !          1672:                        xlnactw = 1;
        !          1673:                        sleep(&xlnactw, PRIBIO);
        !          1674:                }
        !          1675:                splx(ilvl);
        !          1676: 
        !          1677:                getfdc(unit);   /* get fdc again                */
        !          1678:                xlsel(unit);
        !          1679:        }
        !          1680: 
        !          1681:        if (xlster) {                   /* if fatal error, exit         */
        !          1682:                pfprk = xlcomplete;
        !          1683:                xlpark();
        !          1684:                xlwait();
        !          1685:                return 1;
        !          1686:        }
        !          1687: 
        !          1688:        pfint = xlcomplete;             /* normal mode                  */
        !          1689:        xloutput_step(QIC_CMD_NMD);
        !          1690:        xlwait();
        !          1691: 
        !          1692:        /*      done with format / verify                               */
        !          1693:        /*      now find out where headers and volumne table go         */
        !          1694: 
        !          1695:        p0 = ptr_header + 0x200;
        !          1696:        for (i = 0; *p0++; ++i);        /* set hdr segment  #'s         */
        !          1697:        ((fpwrd)ptr_header)[ 3 ] = h0sgn = i;   /*  and vol segment     */
        !          1698:        do {
        !          1699:                ++i;
        !          1700:        } while(*p0++);
        !          1701:        ((fpwrd)ptr_header)[ 4 ] = h1sgn = i;
        !          1702:        do {
        !          1703:                ++i;
        !          1704:        } while(*p0++);
        !          1705:        ((fpwrd)ptr_header)[ 5 ] = volume_seg_num = i;
        !          1706:        /* set last seg number                                          */
        !          1707:        ((fpwrd)ptr_header)[ 6 ] = last_seg_num = ntrkf * nseg_p_track - 1;
        !          1708: 
        !          1709:        cmn_err(CE_CONT,
        !          1710:            "xlformat: h0sgn %d  h1sgn %d  volume_seg_num %d  last_seg_num %d\n",
        !          1711:           h0sgn, h1sgn, volume_seg_num, last_seg_num);
        !          1712: 
        !          1713:        pfprk = xlcomplete;             /* park tape                    */
        !          1714:        xlpark();
        !          1715:        xlwait();
        !          1716: 
        !          1717:        if (volume_seg_num > 10)        /* if too many bad segment exit */
        !          1718:                return 1;
        !          1719: 
        !          1720:        xlrel();                        /* relse fdc, so xlque can work */
        !          1721:        relfdc();
        !          1722: 
        !          1723:        /* start header writes                                          */
        !          1724:        for (curr_seg_num = 0; curr_seg_num <= volume_seg_num; ++curr_seg_num) {
        !          1725:                ilvl = spl5();          /*   get a buffer               */
        !          1726:                while(!(cprb = getrb(&xlfree_q))) {
        !          1727:                        if (!f.actv)
        !          1728:                                xlque();
        !          1729:                        xlfreew = 1;
        !          1730:                        sleep(&xlfreew, PRIBIO);
        !          1731:                }
        !          1732:                splx(ilvl);
        !          1733:                cprb->sgn = curr_seg_num;/* set up for hdr or del adm write */
        !          1734:                cprb->map = 0L;
        !          1735:                if (ptr_header[ curr_seg_num + 0x200 ]) {
        !          1736:                        cmn_err(CE_CONT, "-");
        !          1737:                        cprb->fun = RBWFD;
        !          1738:                }
        !          1739:                else{
        !          1740:                        cmn_err(CE_CONT, "*");
        !          1741:                        cprb->fun = RBFWT;
        !          1742:                }
        !          1743:                strbsg(cprb);
        !          1744:                cptr = (fpchr)cprb->adr;
        !          1745: 
        !          1746:                bcopy(ptr_header, cptr, 16 * 1024);/* copy in header    */
        !          1747:                bcopy(cptr + 16 * 1024 - 4, cptr + 16 * 1024, 13 * 1024 - 4);
        !          1748:                xl_enc(cptr, cprb->nbk);
        !          1749:                putrb(&req, cprb);
        !          1750:        }               /* queue up the request */
        !          1751: 
        !          1752:        if (!f.actv)                    /* activate driver              */
        !          1753:                xlque();
        !          1754: 
        !          1755:        ilvl = spl5();                  /* wait for idle state          */
        !          1756:        while(f.actv) {
        !          1757:                xlnactw = 1;
        !          1758:                sleep(&xlnactw, PRIBIO);
        !          1759:        }
        !          1760:        splx(ilvl);
        !          1761: 
        !          1762:        getfdc(unit);                   /* park tape                    */
        !          1763:        xlsel(unit);
        !          1764:        pfprk = xlcomplete;
        !          1765:        xlpark();
        !          1766:        xlwait();
        !          1767:        return 0;
        !          1768: }
        !          1769: 
        !          1770: /************************************************************************/
        !          1771: /*     xlgtdat get data                                                */
        !          1772: /************************************************************************/
        !          1773: static void
        !          1774: xlgtdat(iop)
        !          1775: IO * iop;
        !          1776: {
        !          1777:        caddr_t p0;
        !          1778:        fpchr   p1;
        !          1779:        int     ilvl;
        !          1780: 
        !          1781:        /*      set up requests using all free buffers                  */
        !          1782:        xlrqr();
        !          1783: 
        !          1784:        /*      set up to xfer data to user buffer                      */
        !          1785: 
        !          1786:        rnbr = iop->io_ioc;             /* set request params           */
        !          1787:        p0 = iop->io.vbase;
        !          1788: 
        !          1789:        p1 = cptr;                      /* use local copy of cptr       */
        !          1790: 
        !          1791:        while(rnbr) {                   /* while more to xfer           */
        !          1792:                if (curr_seg_num > last_seg_num) {
        !          1793:                        break;
        !          1794:                }
        !          1795:                if (!cnbr) {            /* if a new segment is needed   */
        !          1796:                        ilvl = spl5();  /* wait for data                */
        !          1797:                        while(!(cprb = getrb(&data_queue))) {
        !          1798:                                if (!f.actv)
        !          1799:                                        xlque();
        !          1800:                                xldataw = 1;
        !          1801:                                sleep(&xldataw, PRIBIO);
        !          1802:                        }
        !          1803:                        splx(ilvl);
        !          1804: 
        !          1805:                        /*      just got a new buffer from data queue   */
        !          1806: 
        !          1807:                        p1 = (fpchr)cprb->adr;
        !          1808:                        if (cprb->sts) {/* check for errors             */
        !          1809:                                u.u_error = EIO;
        !          1810:                        }
        !          1811:                        else{
        !          1812:                                if (!xl_dec(p1, cprb->nbk, cprb->erc,
        !          1813:                                   cprb->ers[ 0 ], cprb->ers[ 1 ], cprb->ers[ 2 ])) {
        !          1814:                                        u.u_error = EIO;
        !          1815:                                }
        !          1816:                        }
        !          1817:                        /* cnbr = # data bytes                          */
        !          1818:                        cnbr = (cprb->nbk - 3) << 10;
        !          1819:                        if (cprb->sgn != curr_seg_num)
        !          1820:                                curr_seg_num = cprb->sgn;
        !          1821:                        if (cprb->sgn == last_seg_num) {
        !          1822:                                cnbr = lnbr;
        !          1823:                        }
        !          1824:                }
        !          1825:                /* copy some data                                       */
        !          1826:                rcnt = (cnbr >= rnbr) ? rnbr : cnbr;
        !          1827:                copyout(p1, p0, rcnt);
        !          1828:                p0 += rcnt;             /* adjust pointers and counts   */
        !          1829:                p1 += rcnt;
        !          1830:                rnbr -= rcnt;
        !          1831:                cnbr -= rcnt;
        !          1832:                iop->io_ioc -= rcnt;
        !          1833:                if (!cnbr) {            /* release bfr if done          */
        !          1834:                        putrb(&xlfree_q, cprb);
        !          1835:                        ++curr_seg_num;
        !          1836:                        xlrqr();
        !          1837:                }
        !          1838:        }                               /* set up new read request      */
        !          1839: 
        !          1840:        cptr = p1;                      /* update cptr                  */
        !          1841: }
        !          1842: 
        !          1843: /************************************************************************/
        !          1844: /*     xlhalt  halt tape                                               */
        !          1845: /************************************************************************/
        !          1846: static void
        !          1847: xlhalt()
        !          1848: {
        !          1849:        /* adjust tpseg for ramp down/up                                */
        !          1850:        if (f.tmov)
        !          1851:                tpseg += 2;
        !          1852:        f.tmov = 0;                     /* reset tape moving flag       */
        !          1853:        if (xlster) {                   /* exit if error                */
        !          1854:                (*pfhlt)();
        !          1855:                return;
        !          1856:        }
        !          1857:        pfint = xlready;                /* after stop cmd wait for rdy  */
        !          1858:        pfrdy = pfhlt;                  /* after ready, exit            */
        !          1859:        xloutput_step(QIC_CMD_STOP);
        !          1860: }
        !          1861: 
        !          1862: /************************************************************************/
        !          1863: /*     xlintr  xl interrupt handler                                    */
        !          1864: /************************************************************************/
        !          1865: static void
        !          1866: xlintr()                               /* fdc interrupt handler        */
        !          1867: {
        !          1868:        register unchar *p0, *p1;
        !          1869: 
        !          1870:        xltimout(0);                    /* reset interrupt timeout      */
        !          1871: 
        !          1872:        /*
        !          1873:         * Wait for Request from Master asserted in Main Status -
        !          1874:         * indicates data register available for read/write.
        !          1875:         */
        !          1876:        while (inb(FDSTAT) & 0x80 == 0);
        !          1877: 
        !          1878:        /* FDC busy indicates read/write command in progress. */
        !          1879:        if (inb(FDSTAT) & 0x10) {       /* br if non-data int           */
        !          1880:                p0 = status_buf;        /* set up                       */
        !          1881:                for (p1 = p0 + 7; p0 != p1; ++p0) {
        !          1882:                        *p0 = xlfdc_in_byte();  /* store next byte      */
        !          1883:                        if (status_buf[ 7 ]) {
        !          1884:                                xlster |= XLSNEC;
        !          1885:                                break;
        !          1886:                        }
        !          1887:                }
        !          1888:        } else {
        !          1889:                /* handle non-I/O int           */
        !          1890:                for(;;) {
        !          1891:                        if (xlfdc_out_byte(8))/* start sense int        */
        !          1892:                                break;
        !          1893:                        status_buf[ 0 ] = xlfdc_in_byte();/* get 1st sts byte*/
        !          1894:                        if (status_buf[ 7 ]) {
        !          1895:                                xlster |= XLSNEC;
        !          1896:                                break;
        !          1897:                        }
        !          1898:                        if (status_buf[ 0 ] == 0x80) {/* br if done     */
        !          1899:                                status_buf[ 0 ] = unit;
        !          1900:                                if (xltimoutf) {
        !          1901:                                        xltimoutf = 0;
        !          1902:                                        status_buf[ 0 ] = 0xc0;
        !          1903:                                }
        !          1904:                                break;
        !          1905:                        }
        !          1906:                        status_buf[ 1 ] = xlfdc_in_byte();/* get 2nd sts byte*/
        !          1907:                        /* update track if my unit                      */
        !          1908:                        if (unit == (3 & status_buf[ 0 ]))
        !          1909:                                sekcms[ 2 ] = status_buf[ 1 ];
        !          1910:                        /* check for more bytes                         */
        !          1911:                }
        !          1912:        }
        !          1913:        (*pfint)();                     /* exit via caller handler      */
        !          1914:        return;
        !          1915: }
        !          1916: 
        !          1917: /************************************************************************/
        !          1918: /*     xlnull  null interrupt handler                                  */
        !          1919: /************************************************************************/
        !          1920: static void
        !          1921: xlnull()
        !          1922: {
        !          1923: }
        !          1924: 
        !          1925: /************************************************************************/
        !          1926: /*     xlopn   open tape (task time call)                              */
        !          1927: /************************************************************************/
        !          1928: static int
        !          1929: xlopn(dev)
        !          1930: dev_t  dev;
        !          1931: {
        !          1932:        register int    i;
        !          1933:        xlvtbl          *pp;
        !          1934: 
        !          1935: printf("xlopn ");
        !          1936: 
        !          1937:        /* try 100 times to see drive ready - will fix this later */
        !          1938:        for (i = 0; i < 100; i++) {
        !          1939:                xlster = 0;             /* reset error status           */
        !          1940:                xlests = 0;
        !          1941:                xl7sts = 0;
        !          1942:                pfsts = xlcomplete;     /* get drive status             */
        !          1943:                xlstatus();
        !          1944:                xlwait();
        !          1945: printf("try:%d ", i+1);
        !          1946:                if (xl6sts & XLSRDY)
        !          1947:                        break;
        !          1948:        }
        !          1949: 
        !          1950:        xlster &= ~XLSSFT;              /* clear soft error bits        */
        !          1951:        xlests = 0;
        !          1952:        xl7sts = 0;
        !          1953: 
        !          1954:        if (!(xl6sts & XLSCIN)) {       /* exit if no cartridge         */
        !          1955: printf("no cart ");
        !          1956:                xlster |= XLSSFT;
        !          1957:                return 2;
        !          1958:        }
        !          1959: 
        !          1960:        if (xlster) {                   /* exit if fatal error          */
        !          1961: printf("fatal error ");
        !          1962:                return 2;
        !          1963:        }
        !          1964: 
        !          1965:        if (dev & M_CTL) {              /* exit if control open         */
        !          1966:                volume_seg_num = data_seg_num = 0;
        !          1967:                return 0;
        !          1968:        }
        !          1969: 
        !          1970:        if (dev & M_RET) {              /* retension if retension_on_open */
        !          1971:                pfint = xlready;
        !          1972:                pfrdy = xlcomplete;
        !          1973:                xloutput_step(QIC_CMD_EOT);
        !          1974:                xlwait();
        !          1975:                if (xlster) {
        !          1976: printf("another fatal error ");
        !          1977:                        return 2;
        !          1978:                }
        !          1979:        }
        !          1980:        pfint = xlready;                /* rewind tape                  */
        !          1981:        pfrdy = xlcomplete;
        !          1982:        xloutput_step(QIC_CMD_BOT);
        !          1983:        xlwait();
        !          1984: printf("should now be at BOT ");
        !          1985:        if (xlster) {
        !          1986: printf("yet another fatal error ");
        !          1987:                return 2;
        !          1988:        }
        !          1989: 
        !          1990:        pfcal = xlcomplete;             /* calibrate drive              */
        !          1991:        xlcal();
        !          1992:        xlwait();
        !          1993: printf("should now be referenced ");
        !          1994:        if (xlster) {                   /* exit if fatal error          */
        !          1995: printf("still yet another fatal error ");
        !          1996:                return 2;
        !          1997:        }
        !          1998:        i = xl6sts & 0xf7;
        !          1999:        if (i == 0x45) {                /* return if no ref bursts      */
        !          2000: printf("no ref bursts ");
        !          2001:                return 1;
        !          2002:        }
        !          2003:        if (i != 0x65) {                /* return general error         */
        !          2004: printf("general error ");
        !          2005:                xlster |= XLSSFT;
        !          2006:                return 2;
        !          2007:        }
        !          2008:        xprb = getrb(&xlfree_q);        /* get a buffer for open        */
        !          2009:        xprb->sgn = 0;                  /* set up buffer                */
        !          2010: xlopn0:
        !          2011:        xprb->map = 0L;
        !          2012:        strbsg(xprb);
        !          2013: 
        !          2014:        ptr_buffer = (fplng)xprb->adr;
        !          2015: 
        !          2016:        pfpos = xlrds;                  /* read a segment               */
        !          2017:        pfrds = xlcomplete;
        !          2018:        xlpos();
        !          2019:        xlwait();
        !          2020: 
        !          2021:        if (!xprb->sts) {       /* ck for errors */
        !          2022: printf("xlopn trying ecc ");
        !          2023:                if (!xl_dec(ptr_buffer, xprb->nbk, xprb->erc,
        !          2024:                   xprb->ers[ 0 ], xprb->ers[ 1 ], xprb->ers[ 2 ])) {
        !          2025: printf("failed ");
        !          2026:                        xprb->sts = 1;
        !          2027:                } else {
        !          2028: printf("succeeded ");
        !          2029:                }
        !          2030:        }
        !          2031: 
        !          2032:        if (xprb->sts) {                /* if error, try next segment   */
        !          2033:                ++xprb->sgn;
        !          2034:                if (xprb->sgn < 10 && !xlster) {
        !          2035:                        goto xlopn0;
        !          2036:                }
        !          2037:        }
        !          2038:        if (xprb->sts) {                /* if fatal, return bfr & exit  */
        !          2039:                putrb(&xlfree_q, xprb);
        !          2040:                pfprk = xlcomplete;
        !          2041:                xlpark();
        !          2042:                xlwait();
        !          2043: printf("fatal ");
        !          2044:                return 2;
        !          2045:        }
        !          2046: 
        !          2047:        bcopy(ptr_buffer, ptr_header, HDRSZ);   /* copy header data     */
        !          2048: 
        !          2049:        volume_seg_num = ((fpwrd)ptr_header)[ 5 ];/* set seg numbers    */
        !          2050:        data_seg_num = volume_seg_num + 1;
        !          2051: 
        !          2052:        xprb->sgn = volume_seg_num;     /* read in volume segment       */
        !          2053:        xprb->map = ptr_header[ volume_seg_num + 0x200 ];
        !          2054:        strbsg(xprb);
        !          2055:        pfpos = xlrds;
        !          2056:        pfrds = xlcomplete;
        !          2057:        xlpos();
        !          2058:        xlwait();
        !          2059: 
        !          2060:        if (!xprb->sts) {               /* ck for errors                */
        !          2061: printf("xlopn trying 2nd ecc ");
        !          2062:                if (!xl_dec(ptr_buffer, xprb->nbk, xprb->erc,
        !          2063:                   xprb->ers[ 0 ], xprb->ers[ 1 ], xprb->ers[ 2 ])) {
        !          2064: printf("failed ");
        !          2065:                        xprb->sts = 1;
        !          2066:                } else {
        !          2067: printf("succeeded ");
        !          2068:                }
        !          2069:        }
        !          2070: 
        !          2071:        /* set last seg num     */
        !          2072:        pp = (xlvtbl *)ptr_buffer;
        !          2073:        last_seg_num = (int)pp->last_seg_num;
        !          2074:        /* set last # bytes     */
        !          2075:        lnbr = (int)pp->last_blk_size;
        !          2076:        putrb(&xlfree_q, xprb); /* return buffer                */
        !          2077:        pfprk = xlcomplete;             /* park tape                    */
        !          2078:        xlpark();
        !          2079:        xlwait();
        !          2080:        if (xprb->sts) {                /* return error if error        */
        !          2081: printf("sts err ");
        !          2082:                return 2;
        !          2083:        }
        !          2084:        return 0;
        !          2085: }
        !          2086: 
        !          2087: /************************************************************************/
        !          2088: /*     xloutput_step   output cnt steps                                */
        !          2089: /************************************************************************/
        !          2090: static void
        !          2091: xloutput_step(cnt)                     /* output cnt steps             */
        !          2092: int    cnt;
        !          2093: {
        !          2094: 
        !          2095:        xlDbPrintCmd(cnt);
        !          2096: 
        !          2097:        sekcms[ 1 ] = unit;
        !          2098:        if (sekcms[ 2 ] > 80)
        !          2099:                sekcms[ 2 ] -= cnt;
        !          2100:        else
        !          2101:                sekcms[ 2 ] += cnt;
        !          2102:        xlfdc_out_str(sekcms, 3);       /* start seek cmd               */
        !          2103:        if (status_buf[ 7 ]) {          /* exit if nec error            */
        !          2104:                xlster |= XLSNEC;
        !          2105:                (*pfint)();
        !          2106:        }
        !          2107: }
        !          2108: 
        !          2109: /************************************************************************/
        !          2110: /*     xlpark  park tape                                               */
        !          2111: /************************************************************************/
        !          2112: static void
        !          2113: xlpark()
        !          2114: {
        !          2115:        if (xlster) {                   /* exit if error                */
        !          2116:                (*pfprk)();
        !          2117:                return;
        !          2118:        }
        !          2119:        pfsts = xlpark0;                /* clear any drive status       */
        !          2120:        xlstatus();
        !          2121: }
        !          2122: 
        !          2123: static void
        !          2124: xlpark0()
        !          2125: {
        !          2126:        if (xlster) {                   /* exit if error                */
        !          2127:                (*pfprk)();
        !          2128:                return;
        !          2129:        }
        !          2130:        pfint = xlpark1;                /* set normal mode              */
        !          2131:        xloutput_step(QIC_CMD_NMD);
        !          2132: }
        !          2133: 
        !          2134: static void
        !          2135: xlpark1()
        !          2136: {
        !          2137:        tpseg = tptrk = 0;              /* reset current track, segment */
        !          2138:        pfsek = xlpark2;                /* seek track 0                 */
        !          2139:        xlseek();
        !          2140: }
        !          2141: 
        !          2142: static void
        !          2143: xlpark2()
        !          2144: {
        !          2145:        if (xlster) {                   /* exit if error                */
        !          2146:                (*pfprk)();
        !          2147:                return;
        !          2148:        }
        !          2149:        pfint = xlready;                /* after rewind, wait for rdy   */
        !          2150:        pfrdy = pfprk;                  /* after ready, exit            */
        !          2151:        xloutput_step(QIC_CMD_BOT);     /* start rewind                 */
        !          2152: }
        !          2153: 
        !          2154: /************************************************************************/
        !          2155: /*     xlpos   position to segment                                     */
        !          2156: /*             in: xprb = pointer to r                                 */
        !          2157: /************************************************************************/
        !          2158: static void
        !          2159: xlpos()
        !          2160: {
        !          2161:        register int d0;
        !          2162: 
        !          2163:        cmn_err(CE_CONT, "xlpos ");
        !          2164: 
        !          2165:        if (xlster) {                   /* exit if error                */
        !          2166:                pfint = xlpos0;         /* use null int to cleanup stak */
        !          2167:                xloutput_step(0);
        !          2168:                return;
        !          2169:        }
        !          2170:        d0 = xprb->trk;
        !          2171:        if (tptrk != d0) {              /* if not same track            */
        !          2172:                if ((tptrk ^ d0) & 1)   /* adjust tpseg         */
        !          2173:                        tpseg = nseg_p_track + 5 - tpseg;
        !          2174:                /* adjust tpseg if 1st seg on trk                       */
        !          2175:                if (!xprb->tps)
        !          2176:                        tpseg = nseg_p_track;
        !          2177: printf("seek %d->%d ", tptrk, d0);
        !          2178:                tptrk = d0;             /* seek track                   */
        !          2179:                pfsek = xlpos0;
        !          2180:                xlseek();
        !          2181:                return;
        !          2182:        }
        !          2183: 
        !          2184:        d0 = xprb->tps;                 /* d0 = new tpseg               */
        !          2185:        /* adjust tpseg if 1st seg on trk                               */
        !          2186:        if (!d0)
        !          2187:                tpseg = nseg_p_track;
        !          2188:        if (d0 == tpseg && f.tmov == 1) { /* exit if on target          */
        !          2189: printf("xpos on target ");
        !          2190:                (*pfpos)();
        !          2191:                return;
        !          2192:        }
        !          2193:        if (d0 > tpseg) {               /* if before target read id     */
        !          2194: printf("before: %d < %d ", tpseg, d0);
        !          2195:                pfrdi = xlpos2;
        !          2196:                if (f.tmov) {
        !          2197:                        xlreadid();
        !          2198:                        return;
        !          2199:                }
        !          2200:                f.tmov = 1;
        !          2201:                pfint = xlreadid;
        !          2202:                xloutput_step(QIC_CMD_FWD);
        !          2203:                return;
        !          2204:        }
        !          2205:        else{
        !          2206:                pfskp = xlpos1;         /* else skip backwards          */
        !          2207:                xlskipb(tpseg - d0);
        !          2208:                return;
        !          2209:        }
        !          2210: }
        !          2211: 
        !          2212: static void
        !          2213: xlpos0()                               /* new track, tape stopped      */
        !          2214: {
        !          2215:        register int d0;
        !          2216: 
        !          2217:        if (xlster) {                   /* exit if error                */
        !          2218:                (*pfpos)();
        !          2219:                return;
        !          2220:        }
        !          2221:        d0 = xprb->tps;                 /* d0 = new tpseg               */
        !          2222:        /* adjust tpseg if 1st seg on trk                               */
        !          2223:        if (!d0)
        !          2224:                tpseg = nseg_p_track;
        !          2225:        if (d0 >= tpseg) {              /* if before target             */
        !          2226:                f.tmov = 1;
        !          2227:                pfint = xlreadid;       /* start tape fwd and read id   */
        !          2228:                pfrdi = xlpos2;
        !          2229:                xloutput_step(QIC_CMD_FWD);
        !          2230:                return;
        !          2231:        }
        !          2232:        else{
        !          2233:                pfskp = xlpos1;         /* else skip backwards          */
        !          2234:                xlskipb(tpseg - d0);
        !          2235:                return;
        !          2236:        }
        !          2237: }
        !          2238: 
        !          2239: static void
        !          2240: xlpos1()                               /* skip backwards done          */
        !          2241: {
        !          2242:        cmn_err(CE_CONT, "xlpos1()\n");
        !          2243: 
        !          2244:        if (xlster) {                   /* exit if error                */
        !          2245:                (*pfpos)();
        !          2246:                return;
        !          2247:        }
        !          2248:        f.tmov = 1;
        !          2249:        if (!xprb->tps) {               /* check for 1st seg on trk     */
        !          2250:                pfint = pfpos;
        !          2251:                xloutput_step(QIC_CMD_FWD);
        !          2252:                return;
        !          2253:        }
        !          2254:        pfint = xlreadid;               /* start tape fwd and read id's */
        !          2255:        pfrdi = xlpos2;
        !          2256:        xloutput_step(QIC_CMD_FWD);
        !          2257: }
        !          2258: 
        !          2259: static void
        !          2260: xlpos2()                               /* read id finished             */
        !          2261: {
        !          2262:        cmn_err(CE_CONT, "xlpos2()");
        !          2263: 
        !          2264:        if (xlster) {                   /* exit if error                */
        !          2265:                (*pfpos)();
        !          2266:                return;
        !          2267:        }
        !          2268:        if (status_buf[ 0 ] & 0xc0) {   /* error handler                */
        !          2269:                /* if crc error, read id again                          */
        !          2270:                if (status_buf[ 1 ] & 0x20) {
        !          2271: printf("crc err ");
        !          2272:                        xlreadid();
        !          2273:                        return;
        !          2274:                }
        !          2275:                pfhlt = xlpos3;
        !          2276:                xlhalt();
        !          2277:                return;
        !          2278:        }
        !          2279:        if (xprb->idc > status_buf[ 3 ] ||/* if bef tgt, read id again  */
        !          2280:                                        xprb->ids > status_buf[ 5 ]) {
        !          2281: printf("before target ");
        !          2282:                xlreadid();
        !          2283:                return;
        !          2284:        }
        !          2285:        if (xprb->cyl <= status_buf[ 3 ] &&     /* if past it back up   */
        !          2286:                                        xprb->sct <= status_buf[ 5 ]) {
        !          2287:                pfskp = xlpos1;
        !          2288:                xlskipb(9);
        !          2289:                return;
        !          2290:        }
        !          2291:                                        /* we are at target spot        */
        !          2292:        tpseg = xprb->tps;              /* set tpseg and exit           */
        !          2293:        (*pfpos)();
        !          2294: }
        !          2295: 
        !          2296: static void
        !          2297: xlpos3()                               /* status complete tape stopped */
        !          2298: {
        !          2299:        cmn_err(CE_CONT, "xlpos3()\n");
        !          2300: 
        !          2301:        if (xlster) {                   /* exit if error                */
        !          2302:                (*pfpos)();
        !          2303:                return;
        !          2304:        }
        !          2305:        if (xl6sts & (XLSEOT | XLSBOT)) {/* if end track skip backwd    */
        !          2306:                pfskp = xlpos1;
        !          2307:                xlskipb((int)(nseg_p_track + 5 - xprb->tps));
        !          2308:                return;
        !          2309:        }
        !          2310:        xlster |= XLSNID;               /* else can't read id's         */
        !          2311:        (*pfpos)();
        !          2312: }
        !          2313: 
        !          2314: /************************************************************************/
        !          2315: /*     xlptdat put data                                                */
        !          2316: /************************************************************************/
        !          2317: static void
        !          2318: xlptdat(iop)
        !          2319: IO * iop;
        !          2320: {
        !          2321:        caddr_t p0;
        !          2322:        fpchr   p1;
        !          2323:        int     ilvl;
        !          2324: 
        !          2325:        rnbr = iop->io_ioc;             /* set request params           */
        !          2326:        p0 = iop->io.vbase;
        !          2327:        while(rnbr) {
        !          2328:                if (!cnbr) {            /* if a new buffer is needed    */
        !          2329:                        ilvl = spl5();  /* wait for a new buffer        */
        !          2330:                        while(!(cprb = getrb(&xlfree_q))) {
        !          2331:                                if (!f.actv)
        !          2332:                                        xlque();
        !          2333:                                xlfreew = 1;
        !          2334:                                sleep(&xlfreew, PRIBIO);
        !          2335:                        }
        !          2336:                        splx(ilvl);
        !          2337:                        do{
        !          2338:                                /* set up segment                       */
        !          2339:                                cprb->sgn = curr_seg_num;
        !          2340:                                cprb->map = ptr_header[ curr_seg_num + 0x200 ];
        !          2341:                                cprb->fun = RBFWT;
        !          2342:                                strbsg(cprb);
        !          2343:                                ++curr_seg_num;
        !          2344:                        }while(cprb->nbk < 4);
        !          2345:                        cnbr = (cprb->nbk - 3) << 10;   /* set params   */
        !          2346:                        lnbr = cnbr;
        !          2347:                        cptr = (fpchr)cprb->adr;
        !          2348:                        wptr = cptr;
        !          2349:                }               /* save ptr for later encode            */
        !          2350:                p1 = cptr;                      /* copy data            */
        !          2351:                rcnt = (cnbr >= rnbr) ? rnbr : cnbr;
        !          2352:                copyin(p0, p1, rcnt);
        !          2353:                p0 += rcnt;
        !          2354:                p1 += rcnt;
        !          2355:                cptr = p1;
        !          2356:                rnbr -= rcnt;           /* adjust count                 */
        !          2357:                cnbr -= rcnt;
        !          2358:                if (!cnbr) {            /* if filled, encode and q bfr  */
        !          2359:                        xl_enc(wptr, cprb->nbk);
        !          2360:                        putrb(&req, cprb);
        !          2361:                }
        !          2362:        }
        !          2363:        iop->io_ioc = 0;
        !          2364: }
        !          2365: 
        !          2366: /************************************************************************/
        !          2367: /*     xlque           process queue request                           */
        !          2368: /************************************************************************/
        !          2369: static void
        !          2370: xlque()
        !          2371: {
        !          2372:        cmn_err(CE_CONT, "xlque()\n");
        !          2373: xlque0:
        !          2374:        xprb = getrb(&req);             /* get next request             */
        !          2375:        if (!xprb) {                    /* if end queue and             */
        !          2376:                if (f.tmov) {           /* if tape moving, stop tape    */
        !          2377:                        cmn_err(CE_CONT, "xlque: stopping\n");
        !          2378:                        pfhlt = xlque;
        !          2379:                        xlhalt();
        !          2380:                        return;
        !          2381:                }
        !          2382:                cmn_err(CE_CONT, "xlque: inactive\n");
        !          2383: 
        !          2384:                if (f.actv) {           /* if active, release fdc       */
        !          2385:                        xlrel();
        !          2386:                        relfdc();
        !          2387:                }
        !          2388:                if (xlnactw) {          /* if sleeping on xlnactw, wakeup */
        !          2389:                        xlnactw = 0;
        !          2390:                        wakeup(&xlnactw);
        !          2391:                }
        !          2392:                f.actv = 0;             /* reset active flag, exit      */
        !          2393:                return;
        !          2394:        }
        !          2395:        if (!f.actv) {          /* if called from task (not active)     */
        !          2396:                getfdc(unit);   /*    get fdc                   */
        !          2397:                xlsel(unit);
        !          2398:        }
        !          2399:        f.actv = 1;
        !          2400:        switch(xprb->fun) {
        !          2401:        case RBFRD:                     /* read segment                 */
        !          2402:                if (xstop) {            /* if stop, ignore request      */
        !          2403:                        putrb(&xlfree_q, xprb);
        !          2404:                        goto xlque0;
        !          2405:                }
        !          2406:                pfpos = xlrds;
        !          2407:                pfrds = xlqr0;
        !          2408:                xlpos();
        !          2409:                return;
        !          2410:        case RBFWT:                     /* write segment                */
        !          2411:                pfpos = xlwts;
        !          2412:                pfwts = xlqw0;
        !          2413:                xlpos();
        !          2414:                return;
        !          2415:        case RBWFD:                     /* write del adr mrk segment    */
        !          2416:                pfpos = xlwds;
        !          2417:                pfwds = xlqw0;
        !          2418:                xlpos();
        !          2419:                return;
        !          2420:        default:
        !          2421:                ;
        !          2422:        }
        !          2423: }
        !          2424: 
        !          2425: static void
        !          2426: xlqr0()
        !          2427: {
        !          2428:        putrb(&data_queue, xprb);       /* add to data queue            */
        !          2429:        if (xldataw) {                  /* wakeup if needed             */
        !          2430:                xldataw = 0;
        !          2431:                wakeup(&xldataw);
        !          2432:        }
        !          2433:        xlque();                        /* start next i/o               */
        !          2434: }
        !          2435: 
        !          2436: static void
        !          2437: xlqw0()
        !          2438: {
        !          2439:        if (xprb->sts)          /* set f.werr if error          */
        !          2440:                f.werr = 1;
        !          2441:        putrb(&xlfree_q, xprb); /* relse bfr back to free pool  */
        !          2442:        if (xlfreew) {                  /* wakeup if needed             */
        !          2443:                xlfreew = 0;
        !          2444:                wakeup(&xlfreew);
        !          2445:        }
        !          2446:        xlque();                        /* start next i/o               */
        !          2447: }
        !          2448: 
        !          2449: /************************************************************************/
        !          2450: /*     xlrds   read segment                                            */
        !          2451: /*             in: xprb = pointer to rb                                */
        !          2452: /************************************************************************/
        !          2453: static void
        !          2454: xlrds()
        !          2455: {
        !          2456:        if (xlster || xstop) {          /* exit if error or stop        */
        !          2457:                pfint = xlrd0;          /* use null int to cleanup stck */
        !          2458:                xloutput_step(0);
        !          2459:                return;
        !          2460:        }
        !          2461:        rwdcms[ 0 ] = 0x46;             /* set for read                 */
        !          2462:        stseg(xprb);
        !          2463:        xrty = 2;                       /* 2 tries per sector           */
        !          2464:        xlrd0();                        /* start io                     */
        !          2465: }
        !          2466: 
        !          2467: static void
        !          2468: xlrd0()                                        /* initiate io                  */
        !          2469: {
        !          2470:        if (xlster || xstop) {          /* exit if error or stop        */
        !          2471: printf("xlrd0 - err xlster=%x xstop=%x ", xlster, xstop);
        !          2472:                pfint = xlnull;
        !          2473:                xprb->sts = 1;
        !          2474:                (*pfrds)();
        !          2475:                return;
        !          2476:        }
        !          2477:        pfint = xlrd1;                  /* set int handler              */
        !          2478:        xtbl = (xprb->tbl)[ xsct - xprb->sct ];/* get rb.tbl entry      */
        !          2479:        if (xtbl) {                   /* if more data, start other read */
        !          2480:                rwdcms[ 4 ] = (xtbl & 0x1f) + xprb->sct;
        !          2481:                stdma(DMA_Rdmode, xadr | ((xtbl & 0x3e0) << 5), (int)(xtbl & 0xfc00));
        !          2482:                xltimout(IOTMO);
        !          2483:                xlfdc_out_str(rwdcms, 9);
        !          2484:                if (status_buf[ 7 ]) {  /* exit if nec error    */
        !          2485:                        xltimout(0);
        !          2486:                        xlster |= XLSNEC;
        !          2487:                        pfint = xlnull;
        !          2488:                        (*pfrds)();
        !          2489:                        return;
        !          2490:                }
        !          2491:                return;
        !          2492:        }
        !          2493:        else{                           /* else, seg is done            */
        !          2494:                xprb->sts = 0;
        !          2495:                tpseg = xprb->tps + 1;
        !          2496:                if (tpseg == nseg_p_track) {    /* if last seg on trk,  */
        !          2497:                        pfrdy = pfrds;          /* exit via xlready     */
        !          2498:                        xlready();
        !          2499:                        return;
        !          2500:                }
        !          2501:                pfint = xlnull;         /* else just exit               */
        !          2502:                (*pfrds)();
        !          2503:                return;
        !          2504:        }
        !          2505: }
        !          2506: 
        !          2507: static void
        !          2508: xlrd1()
        !          2509: {
        !          2510:        if (xlster || xstop) {          /* exit if error or stop        */
        !          2511: printf("xlrd1 - err xlster=%x xstop=%x ", xlster, xstop);
        !          2512:                pfint = xlnull;
        !          2513:                xprb->sts = 1;
        !          2514:                (*pfrds)();
        !          2515:                return;
        !          2516:        }
        !          2517:        if (status_buf[ 0 ] & 0xc0) {   /* if error                     */
        !          2518:                dsperr();
        !          2519:                if (status_buf[ 2 ] & 0x40) {/* if del adr mark, exit   */
        !          2520:                        ++tpseg;
        !          2521:                        goto xlrd2;
        !          2522:                }
        !          2523:                if (status_buf[ 0 ] == 0xc0)/* adjust tpseg             */
        !          2524:                        tpseg += TMSKP;
        !          2525:                else{
        !          2526:                        tpseg += 2;
        !          2527:                }
        !          2528:                if (tpseg > nseg_p_track)
        !          2529:                        tpseg = nseg_p_track;
        !          2530: 
        !          2531:                if (status_buf[ 0 ] != 0xc0) { /* if not timeout        */
        !          2532:                        /* if no data read                              */
        !          2533:                        if (xsct == status_buf[ 5 ]) {
        !          2534:                                --xrty;         /* skip sct if 2nd time */
        !          2535:                                if (xrty == 0) {
        !          2536:                                        if (xprb->erc < 3) {
        !          2537:                                                xprb->ers[ xprb->erc ] = xsct-xprb->sct;
        !          2538:                                                ++xprb->erc;
        !          2539:                                                ++xsct;
        !          2540:                                                xrty = 2;
        !          2541:                                        }
        !          2542:                                        else{   /* fail if too many err */
        !          2543:                                                goto xlrd2;
        !          2544:                                        }
        !          2545:                                }
        !          2546:                        }
        !          2547:                        else{                   /* some data read in    */
        !          2548:                                xrty = 1;       /* 1mor try on this sct */
        !          2549:                                xsct = status_buf[ 5 ];
        !          2550:                        }
        !          2551:                }                               /* update xsct          */
        !          2552:                else{                           /* if timeout           */
        !          2553:                        --xrty;                 /* fail if too many err */
        !          2554:                        if (!xrty) {
        !          2555: xlrd2:
        !          2556: printf("xlrd2 - err xlster=%x xstop=%x ", xlster, xstop);
        !          2557:                                xprb->sts = 1;
        !          2558:                                pfint = xlnull;
        !          2559:                                (*pfrds)();
        !          2560:                                return;
        !          2561:                        }
        !          2562:                }
        !          2563:                pfpos = xlrd0;          /* restart io after positioning */
        !          2564:                xlpos();
        !          2565:                return;
        !          2566:        }
        !          2567: 
        !          2568:        /*      no errors, start io for next part of segment (if any)   */
        !          2569: 
        !          2570:        xsct = status_buf[ 5 ];         /* update xsct, start next io   */
        !          2571:        xlrd0();
        !          2572: }
        !          2573: 
        !          2574: /************************************************************************/
        !          2575: /*     xlreadid        read id                                                 */
        !          2576: /************************************************************************/
        !          2577: static void
        !          2578: xlreadid()
        !          2579: {
        !          2580:        cmn_err(CE_CONT, "xlreadid()");
        !          2581: 
        !          2582:        pfint = xlreadid0;              /* set pfint                    */
        !          2583:        xltimout(IOTMO);
        !          2584:        xlfdc_out_str(rdicms, 2);       /* start read id cmd            */
        !          2585:        if (xlster) {                   /* exit if error                */
        !          2586: printf("readid err ");
        !          2587:                xltimout(0);
        !          2588:                pfint = xlnull;
        !          2589:                (*pfrdi)();
        !          2590:                return;
        !          2591:        }
        !          2592: }
        !          2593: 
        !          2594: static void
        !          2595: xlreadid0()
        !          2596: {
        !          2597:        pfint = xlnull;                 /* reset pfint                  */
        !          2598:        (*pfrdi)();                     /* and exit                     */
        !          2599: }
        !          2600: 
        !          2601: /************************************************************************/
        !          2602: /*     xlready         wait for ready                                  */
        !          2603: /************************************************************************/
        !          2604: static void
        !          2605: xlready()
        !          2606: {
        !          2607:        if (xlster) {                   /* exit if error                */
        !          2608:                (*pfrdy)();
        !          2609:                return;
        !          2610:        }
        !          2611:        pfsts = xlready0;               /* get drive status             */
        !          2612:        xlstatus();
        !          2613: }
        !          2614: 
        !          2615: static void
        !          2616: xlready0()
        !          2617: {
        !          2618:        if (xlster || (xl6sts & XLSRDY)) {      /* exit if done         */
        !          2619:                (*pfrdy)();
        !          2620:                return;
        !          2621:        }
        !          2622:        xlstatus();                     /* else get status again        */
        !          2623: }
        !          2624: 
        !          2625: /************************************************************************/
        !          2626: /*     xlrel   release unit                                            */
        !          2627: /************************************************************************/
        !          2628: static void
        !          2629: xlrel()
        !          2630: {
        !          2631:        while(0x80 != (0xc0 & inb(FDSTAT)));  /* wait for ready */
        !          2632:        outb(FDCTRL, 0x0c);             /* deselect all units           */
        !          2633:        xlfdc_out_str(sf3cms, 3);       /* set step rate to 3ms         */
        !          2634: }
        !          2635: 
        !          2636: /************************************************************************/
        !          2637: /*     xlreset         reset drive                                     */
        !          2638: /************************************************************************/
        !          2639: static void
        !          2640: xlreset()
        !          2641: {
        !          2642:        pfint = xlreset0;               /* output 1 step                */
        !          2643:        xloutput_step(QIC_CMD_RST);
        !          2644: }
        !          2645: 
        !          2646: static void
        !          2647: xlreset0()
        !          2648: {
        !          2649:        pfint = xlnull;                 /* reset pfint                  */
        !          2650:        pfdly = xlready;                /* after delay "wait" for ready */
        !          2651:        pfrdy = pfrst;                  /* after ready, exit via pfrst  */
        !          2652:        xldelay(HZ);                    /* start delay                  */
        !          2653: }
        !          2654: 
        !          2655: /************************************************************************/
        !          2656: /*     xlrnb   report next bit(s)                                      */
        !          2657: /************************************************************************/
        !          2658: static void
        !          2659: xlrnb(cnt)
        !          2660: int    cnt;
        !          2661: {
        !          2662:        xlrnbw = 0;                     /* reset status int             */
        !          2663:        pfint = xlrnb0;                 /* set int handler              */
        !          2664:        xlbcnt = cnt;                   /* set up                       */
        !          2665:        xloutput_step(QIC_CMD_RNB);     /* start 2 step seek            */
        !          2666: }
        !          2667: 
        !          2668: static void
        !          2669: xlrn9()                                /* get 9 bits                   */
        !          2670: {
        !          2671:        xlrnbw = 0;
        !          2672:        pfint = xlrnb0;
        !          2673:        xlbcnt = 9;
        !          2674:        xloutput_step(QIC_CMD_RNB);
        !          2675: }
        !          2676: 
        !          2677: static void
        !          2678: xlrn17()                               /* get 17 bits                  */
        !          2679: {
        !          2680:        xlrnbw = 0;
        !          2681:        pfint = xlrnb0;
        !          2682:        xlbcnt = 17;
        !          2683:        xloutput_step(QIC_CMD_RNB);
        !          2684: }
        !          2685: 
        !          2686: static void
        !          2687: xlrnb0()
        !          2688: {
        !          2689:        register int xlrnbb;            /* xl2 status bit               */
        !          2690:        int bit;
        !          2691: 
        !          2692:        /* Sense drive status. */
        !          2693:        xlfdc_out_byte(4);
        !          2694:        xlfdc_out_byte((int)unit);
        !          2695: 
        !          2696:        /* Read ST3, look at T0 bit. */
        !          2697:        bit = (0x10 & xlfdc_in_byte()) ? 1 : 0;
        !          2698: 
        !          2699:        xlrnbb = bit ? 0x8000 : 0x0000;
        !          2700:        if (status_buf[ 7 ])            /* exit if nec handshake error  */
        !          2701:                xlster |= XLSNEC;
        !          2702:        if (xlster) {
        !          2703:                pfint = xlnull;
        !          2704:                (*pfrnb)();
        !          2705:                return;
        !          2706:        }
        !          2707:        --xlbcnt;
        !          2708:        if (xlbcnt) {                   /* if not done, shift in bit    */
        !          2709:                xlrnbw >>= 1;           /*  and continue                */
        !          2710:                xlrnbw |= xlrnbb;
        !          2711:                xloutput_step(QIC_CMD_RNB);
        !          2712:                return;
        !          2713:        } else {
        !          2714:                if (!xlrnbb)            /* last bit must = 1            */
        !          2715:                        xlster |= XLSLSB;
        !          2716:                pfint = xlnull;
        !          2717:                (*pfrnb)();             /* call end step handler        */
        !          2718:                return;
        !          2719:        }
        !          2720: }
        !          2721: 
        !          2722: /************************************************************************/
        !          2723: /*     xlrqr   set up read requests                                    */
        !          2724: /************************************************************************/
        !          2725: static void
        !          2726: xlrqr()
        !          2727: {
        !          2728:        while(fprb = getrb(&xlfree_q)) {/* enqueue any free bfrs        */
        !          2729: xlrqr0:
        !          2730:                if (read_ahead_seg_num > last_seg_num) {
        !          2731:                        putrb(&xlfree_q, fprb);
        !          2732:                        break;
        !          2733:                }
        !          2734:                fprb->sgn = read_ahead_seg_num;
        !          2735:                fprb->map = ptr_header[ read_ahead_seg_num + 0x200 ];
        !          2736:                fprb->fun = RBFRD;
        !          2737:                strbsg(fprb);
        !          2738:                if (fprb->nbk < 4) {    /* skip if < 4 sectors          */
        !          2739:                        ++read_ahead_seg_num;
        !          2740:                        goto xlrqr0;
        !          2741:                }
        !          2742:                putrb(&req, fprb);      /* add bfr to req queue         */
        !          2743:                ++read_ahead_seg_num;
        !          2744:        }
        !          2745: }
        !          2746: 
        !          2747: /************************************************************************/
        !          2748: /*     xlseek  seek head to tptrk                                      */
        !          2749: /************************************************************************/
        !          2750: static void
        !          2751: xlseek()
        !          2752: {
        !          2753:        if (xlster) {                   /* exit if error                */
        !          2754:                (*pfsek)();
        !          2755:                return;
        !          2756:        }
        !          2757:        pfhlt = xlseek0;                /* halt tape                    */
        !          2758:        xlhalt();
        !          2759: }
        !          2760: 
        !          2761: static void
        !          2762: xlseek0()
        !          2763: {
        !          2764:        if (xlster) {                   /* exit if error                */
        !          2765:                (*pfsek)();
        !          2766:                return;
        !          2767:        }
        !          2768:        pfint = xlseek1;                /* do 13 steps                  */
        !          2769:        xloutput_step(QIC_CMD_SEEK);
        !          2770: }
        !          2771: 
        !          2772: static void
        !          2773: xlseek1()
        !          2774: {
        !          2775:        if (xlster) {                   /* exit if error                */
        !          2776:                (*pfsek)();
        !          2777:                return;
        !          2778:        }
        !          2779:        pfint = xlready;                /* after seek "wait" for rdy    */
        !          2780:        pfrdy = pfsek;                  /* after ready, exit            */
        !          2781:        xloutput_step(2 + tptrk);
        !          2782: }
        !          2783: 
        !          2784: /************************************************************************
        !          2785:  *     xlsel   select unit, wait for done
        !          2786:  ***********************************************************************/
        !          2787: static void
        !          2788: xlsel()
        !          2789: {
        !          2790:        fdsel = fdstb[unit];
        !          2791:        fdselr = 0xfb & fdsel;
        !          2792:        outb(FDCSR1, 0);                /* set 500khz speed             */
        !          2793:        outb(FDCTRL, fdsel);            /* select unit                  */
        !          2794:        pfint = xlcomplete;             /* reset fdc                    */
        !          2795:        xlfdc_reset();
        !          2796:        xlwait();
        !          2797:        xlfdc_out_str(sf2cms, 3);       /* set step rate to 2ms         */
        !          2798: 
        !          2799:        /* 80 MB nseg_p_track = 100, nseg_p_head = 600, nseg_p_cyl = 4  */
        !          2800:        /* 40 MB nseg_p_track = 68, nseg_p_head = 680, nseg_p_cyl = 4   */
        !          2801:        if (ftfmt) {
        !          2802:                nseg_p_track = 100;     /* set for 80 MB drive          */
        !          2803:                nseg_p_head = 600;
        !          2804:                nseg_p_cyl = 4;
        !          2805:        } else {
        !          2806:                nseg_p_track = 68;      /* set for 40 MB drive          */
        !          2807:                nseg_p_head = 680;
        !          2808:                nseg_p_cyl = 4;
        !          2809:        }
        !          2810: }
        !          2811: 
        !          2812: /************************************************************************/
        !          2813: /*     xlskipb         skip n segments back                            */
        !          2814: /************************************************************************/
        !          2815: static void
        !          2816: xlskipb(cnt)
        !          2817: int    cnt;
        !          2818: {
        !          2819:        if (xlster) {                   /* exit if error                */
        !          2820:                (*pfskp)();
        !          2821:                return;
        !          2822:        }
        !          2823:        f.tmov = 0;                     /* tape will be halted          */
        !          2824:        xlskip_count = cnt;             /* set skip count               */
        !          2825:        pfint = xlready;                /* stop tape first              */
        !          2826:        pfrdy = xlskipb0;
        !          2827:        xloutput_step(QIC_CMD_STOP);
        !          2828: }
        !          2829: 
        !          2830: static void
        !          2831: xlskipb0()
        !          2832: {
        !          2833:        pfint = xlskipb1;               /* start skip back cmd          */
        !          2834:        xloutput_step(QIC_CMD_SKPB);
        !          2835: }
        !          2836: 
        !          2837: static void
        !          2838: xlskipb1()
        !          2839: {
        !          2840:        if (xlster) {                   /* exit if error                */
        !          2841:                (*pfskp)();
        !          2842:                return;
        !          2843:        }
        !          2844:        pfint = xlskipb2;               /* issue 2nd part of cmd        */
        !          2845:        xloutput_step(2 + (0xf & xlskip_count));
        !          2846: }
        !          2847: 
        !          2848: static void
        !          2849: xlskipb2()
        !          2850: {
        !          2851:        if (xlster) {                   /* exit if error                */
        !          2852:                (*pfskp)();
        !          2853:                return;
        !          2854:        }
        !          2855:        /* after 3rd part cmd, wait for ready                           */
        !          2856:        pfint = xlready;
        !          2857:        pfrdy = pfskp;                  /* after ready, exit            */
        !          2858:        /* start 3rd part cmd   */
        !          2859:        xloutput_step(2 + (0xf & (xlskip_count >> 4)));
        !          2860: }
        !          2861: 
        !          2862: /************************************************************************/
        !          2863: /*     xlstatus()      get drive status                                */
        !          2864: /************************************************************************/
        !          2865: static void
        !          2866: xlstatus()
        !          2867: {
        !          2868:        if (xlster) {                   /* exit if error                */
        !          2869:                pfint = xlnull;
        !          2870:                (*pfsts)();
        !          2871:                return;
        !          2872:        }
        !          2873:        /* after 6 steps, get 9 report bits                             */
        !          2874:        pfint = xlrn9;
        !          2875:        pfrnb = xlstatus0;              /* after 9 bits, goto xlstatus0 */
        !          2876:        xloutput_step(QIC_CMD_STS);     /* start steps                  */
        !          2877: }
        !          2878: 
        !          2879: static void
        !          2880: xlstatus0()
        !          2881: {
        !          2882:        if (xlster) {                   /* exit if error                */
        !          2883:                pfint = xlnull;
        !          2884:                (*pfsts)();
        !          2885:                return;
        !          2886:        }
        !          2887: 
        !          2888:        xl6sts = xlrnbw >> 8;           /* set xl6sts                   */
        !          2889: 
        !          2890:        if (xl6sts == 0xff) {           /* exit if not tape drive       */
        !          2891:                xlster |= XLSNTD;
        !          2892:                pfint = xlnull;
        !          2893:                (*pfsts)();
        !          2894:                return;
        !          2895:        } else {
        !          2896:                xlDbPrintStat(xl6sts);
        !          2897:        }
        !          2898: 
        !          2899:        if (xl6sts & (XLSEXC | XLSCHG)) {/* if exception condition,     */
        !          2900:                xlests = xl6sts;        /* start type 7 status          */
        !          2901:                pfint = xlrn17;
        !          2902:                pfrnb = xlstatus1;
        !          2903:                xloutput_step(QIC_CMD_ECD);
        !          2904:                return;
        !          2905:        }
        !          2906: 
        !          2907:        if (xlests || !(xl6sts & XLSCIN)) { /* set soft err if needed   */
        !          2908: printf("soft err ");
        !          2909:                xlster |= XLSSFT;
        !          2910:        }
        !          2911: 
        !          2912:        pfint = xlnull;                 /* exit                         */
        !          2913:        (*pfsts)();
        !          2914: }
        !          2915: 
        !          2916: static void
        !          2917: xlstatus1()
        !          2918: {
        !          2919:        if (xlster) {                   /* exit if error                */
        !          2920:                pfint = xlnull;
        !          2921:                (*pfsts)();
        !          2922:                return;
        !          2923:        }
        !          2924:        xl7sts = xlrnbw;                /* save type 7 status           */
        !          2925:        xlDbPrintErr(xl7sts);
        !          2926:        pfint = xlrn9;                  /* restart normal status sequce */
        !          2927:        pfrnb = xlstatus0;
        !          2928:        xloutput_step(QIC_CMD_STS);
        !          2929: }
        !          2930: 
        !          2931: /************************************************************************
        !          2932:  *     xltimout                set timeout for int
        !          2933:  *
        !          2934:  * "cnt" is number of ticks.  if zero, cancel any pending timeout
        !          2935:  ***********************************************************************/
        !          2936: static void
        !          2937: xltimout(cnt)
        !          2938: int    cnt;
        !          2939: {
        !          2940:        if (cnt)
        !          2941:                timeout(&xltmo, cnt, xltimfn, 0);
        !          2942:        else
        !          2943:                timeout(&xltmo, cnt, NULL, 0);
        !          2944: }
        !          2945: 
        !          2946: static void
        !          2947: xltimfn()
        !          2948: {
        !          2949:        cmn_err(CE_CONT, "Timeout!!\n");
        !          2950:        xltimoutf = 1;
        !          2951:        xlfdc_reset();
        !          2952: }
        !          2953: 
        !          2954: /************************************************************************/
        !          2955: /*     xlwait  wait for xlcomplete (xlcompw wakeup)                    */
        !          2956: /************************************************************************/
        !          2957: static int
        !          2958: xlwait()
        !          2959: {
        !          2960:        register int ilvl;
        !          2961: 
        !          2962:        ilvl = spl5();
        !          2963:        while(!xlcompf) {               /* wait for xlcompf to be set   */
        !          2964:                xlcompw = 1;
        !          2965:                if (x_sleep(&xlcompw, pritape, slpriSigCatch, "xlwait")) {
        !          2966: printf("xlwait signaled ");
        !          2967:                        return 1;
        !          2968:                }
        !          2969:        }
        !          2970:        xlcompf = 0;                    /* reset flag                   */
        !          2971:        splx(ilvl);
        !          2972:        return 0;
        !          2973: }
        !          2974: 
        !          2975: /************************************************************************/
        !          2976: /*     xlwds   write del adm segment                                   */
        !          2977: /*             in: xprb = pointer to rb                                */
        !          2978: /************************************************************************/
        !          2979: static void
        !          2980: xlwds()
        !          2981: {
        !          2982:        pfwts = pfwds;                  /* using xlwts                  */
        !          2983:        if (xlster) {                   /* exit if error                */
        !          2984:                pfint = xlwt0;          /* use null int to cleanup stck */
        !          2985:                xloutput_step(0);
        !          2986:                return;
        !          2987:        }
        !          2988:        rwdcms[ 0 ] = 0x49;             /* set for write del adm        */
        !          2989:        stseg(xprb);
        !          2990:        xrty = 2;
        !          2991:        pfint = xlwt1;
        !          2992:        xlwt0();
        !          2993: }
        !          2994: 
        !          2995: /************************************************************************/
        !          2996: /*     xlwts   write segment                                           */
        !          2997: /*             in: xprb = pointer to rb                                */
        !          2998: /************************************************************************/
        !          2999: static void
        !          3000: xlwts()
        !          3001: {
        !          3002:        if (xlster) {                   /* exit if error                */
        !          3003:                pfint = xlwt0;          /* use null int to cleanup stck */
        !          3004:                xloutput_step(0);
        !          3005:                return;
        !          3006:        }
        !          3007:        rwdcms[ 0 ] = 0x45;             /* set for write                */
        !          3008:        stseg(xprb);
        !          3009:        xlwt0();
        !          3010: }
        !          3011: 
        !          3012: static void
        !          3013: xlwt0()                                        /* start io                     */
        !          3014: {
        !          3015:        if (xlster) {                   /* exit if error                */
        !          3016:                xprb->sts = 1;
        !          3017:                pfint = xlnull;
        !          3018:                (*pfwts)();
        !          3019:                return;
        !          3020:        }
        !          3021:        xtbl = (xprb->tbl)[ xsct - xprb->sct ];/* get rb.tbl entry      */
        !          3022:        if (xtbl) {                   /* if more data start other write */
        !          3023:                pfint = xlwt1;
        !          3024:                rwdcms[ 4 ] = (xtbl & 0x1f) + xprb->sct;
        !          3025:                stdma(DMA_Wrmode, xadr | ((xtbl & 0x3e0) << 5), (int)(xtbl & 0xfc00));
        !          3026:                xltimout(IOTMO);
        !          3027:                xlfdc_out_str(rwdcms, 9);
        !          3028:                if (status_buf[ 7 ]) {  /* exit if nec error    */
        !          3029:                        xltimout(0);
        !          3030:                        xlster |= XLSNEC;
        !          3031:                        xprb->sts = 1;
        !          3032:                        pfint = xlnull;
        !          3033:                        (*pfwts)();
        !          3034:                        return;
        !          3035:                }
        !          3036:                return;
        !          3037:        }
        !          3038:        else{                           /* else, seg is ok              */
        !          3039:                xprb->sts = 0;
        !          3040:                tpseg = xprb->tps + 1;
        !          3041:                if (tpseg == nseg_p_track) {    /* if last seg on trk,  */
        !          3042:                        pfrdy = pfwts;  /* exit via xlready             */
        !          3043:                        xlready();
        !          3044:                        return;
        !          3045:                }
        !          3046:                pfint = xlnull;         /* else just exit               */
        !          3047:                (*pfwts)();
        !          3048:                return;
        !          3049:        }
        !          3050: }
        !          3051: 
        !          3052: static void
        !          3053: xlwt1()
        !          3054: {
        !          3055:        if (xlster) {                   /* exit if error                */
        !          3056:                xprb->sts = 1;
        !          3057:                pfint = xlnull;
        !          3058:                (*pfwts)();
        !          3059:                return;
        !          3060:        }
        !          3061:        if (status_buf[ 0 ] & 0xc0) {   /* check for io error           */
        !          3062:                dsperr();
        !          3063:                if (status_buf[ 0 ] == 0xc0)/* adjust tpseg             */
        !          3064:                        tpseg += TMSKP;
        !          3065:                else
        !          3066:                        tpseg += 2;
        !          3067:                if (status_buf[ 0 ] != 0xc0)/* update xsct              */
        !          3068:                        xsct = status_buf[ 5 ];
        !          3069:                --xrty;                 /* retry if more to try         */
        !          3070:                if (xrty) {
        !          3071:                        pfpos = xlwt0;
        !          3072:                        xlpos();
        !          3073:                        return;
        !          3074:                }
        !          3075:                else{
        !          3076:                        /* if del adm write, continue                   */
        !          3077:                        if (rwdcms[ 0 ] == 0x49) {
        !          3078:                                ++xsct;
        !          3079:                                xrty = 2;
        !          3080:                                pfpos = xlwt0;
        !          3081:                                xlpos();
        !          3082:                                return;
        !          3083:                        }
        !          3084:                        xprb->sts = 1;  /* give up on segment, exit     */
        !          3085:                        pfint = xlnull;
        !          3086:                        (*pfwts)();
        !          3087:                        return;
        !          3088:                }
        !          3089:        }
        !          3090:        xsct = status_buf[ 5 ];         /* if no error, start next io   */
        !          3091:        xlwt0();
        !          3092: }
        !          3093: 
        !          3094: /******************* DEBUG AREA ******************/
        !          3095: static char    *qicErr[] = {
        !          3096:        "NULL err",
        !          3097:        "command received while drive not ready",
        !          3098:        "cartridge not present or removed",
        !          3099:        "motor speed error (not within 1%)",
        !          3100:        "motor speed fault (jammed, or gross speed error)",
        !          3101:        "cartridge write protected",
        !          3102:        "undefined or reserved command code",
        !          3103:        "illegal track address specified for seek",
        !          3104:        "illegal command in report subcontext",
        !          3105:        "illegal entry into a diagnostic mode",
        !          3106:        "broken tape detected (based on hole sensor)",
        !          3107:        "warning - read gain setting error",
        !          3108:        "command received while error status pending (obsolete)",
        !          3109:        "command received while new cartridge pending",
        !          3110:        "command illegal or undefined in primary mode",
        !          3111:        "command illegal or undefined in format mode",
        !          3112:        "command illegal or undefined in verify mode",
        !          3113:        "logical forward not at logical BOT in format mode",
        !          3114:        "logical EOT before all segments generated",
        !          3115:        "command illegal when cartridge not referenced",
        !          3116:        "self-diagnostic failed (cannot be cleared)",
        !          3117:        "warning EEPROM not initialized, defaults set",
        !          3118:        "EEPROM corrupt or hardware failure",
        !          3119:        "motion timeout error",
        !          3120:        "data segment too long - logical forward or pause",
        !          3121:        "transmit overrun (obsolete)",
        !          3122:        "power on reset occurred",
        !          3123:        "software reset occurred",
        !          3124:        "diagnostic mode 1 error",
        !          3125:        "diagnostic mode 2 error",
        !          3126:        "command received during noninterruptible process",
        !          3127:        "rate selection error",
        !          3128:        "illegal command while in high speed mode",
        !          3129:        "illegal seek segment value"
        !          3130: };
        !          3131: 
        !          3132: static char    *qicStat[] = {
        !          3133:        "drive ready or idle",
        !          3134:        "error detected",
        !          3135:        "cartridge present",
        !          3136:        "cartridge write protected",
        !          3137:        "new cartridge",
        !          3138:        "cartridge referenced",
        !          3139:        "at physical BOT",
        !          3140:        "at physical EOT"
        !          3141: };
        !          3142: 
        !          3143: static char    *qicCmd[] = {
        !          3144:        "NULL cmd",
        !          3145:        "soft reset",
        !          3146:        "report next bit",
        !          3147:        "pause",
        !          3148:        "micro step pause",
        !          3149:        "alternate command timeout",
        !          3150:        "report drive status",
        !          3151:        "report error code",
        !          3152:        "report drive configuration",
        !          3153:        "report ROM version",
        !          3154:        "logical forward",
        !          3155:        "physical reverse",
        !          3156:        "physical forward",
        !          3157:        "seek head to track",
        !          3158:        "seek load point",
        !          3159:        "enter format mode",
        !          3160:        "write reference burst",
        !          3161:        "enter verify mode",
        !          3162:        "stop tape",
        !          3163:        "reserved (19)",
        !          3164:        "reserved (20)",
        !          3165:        "micro step head up",
        !          3166:        "micro step head down",
        !          3167:        "reserved (23)",
        !          3168:        "reserved (24)",
        !          3169:        "skip n segments reverse",
        !          3170:        "skip n segments forward",
        !          3171:        "select rate",
        !          3172:        "enter diag mode 1",
        !          3173:        "enter diag mode 2",
        !          3174:        "enter primary mode",
        !          3175:        "reserved (31)",
        !          3176:        "report vendor ID",
        !          3177:        "report tape status",
        !          3178:        "skip n segments extended reverse",
        !          3179:        "skip n segments extended forward"
        !          3180: };
        !          3181: 
        !          3182: /* print 2-byte error status as <error-code,command> */
        !          3183: static void
        !          3184: xlDbPrintErr(errword)
        !          3185: unsigned int errword;
        !          3186: {
        !          3187:        unsigned int lo, hi;
        !          3188: 
        !          3189:        lo = errword & 0xff;
        !          3190:        hi = (errword >> 8) & 0xff;
        !          3191: 
        !          3192:        if (lo >= 1 && lo < sizeof(qicErr)/sizeof(qicErr[0]))
        !          3193:                printf("<%s,", qicErr[lo]);
        !          3194:        else
        !          3195:                printf("<%d,", lo);
        !          3196: 
        !          3197:        if (hi >= 1 && hi < sizeof(qicCmd)/sizeof(qicCmd[0]))
        !          3198:                printf("%s> ", qicCmd[hi]);
        !          3199:        else
        !          3200:                printf("%d> ", hi);
        !          3201: }
        !          3202: 
        !          3203: /* print command as [command] */
        !          3204: static void
        !          3205: xlDbPrintCmd(cmd)
        !          3206: unsigned int cmd;
        !          3207: {
        !          3208:        if (cmd >= 1 && cmd < sizeof(qicCmd)/sizeof(qicCmd[0])) {
        !          3209:                if (cmd == QIC_CMD_RNB)
        !          3210:                        putchar ('.');
        !          3211:                else
        !          3212:                        printf("[%s] ", qicCmd[cmd]);
        !          3213:        } else
        !          3214:                printf("[%d] ", cmd);
        !          3215: }
        !          3216: 
        !          3217: /* print tape status as { status string,... } */
        !          3218: static void
        !          3219: xlDbPrintStat(stat)
        !          3220: unsigned int stat;
        !          3221: {
        !          3222:        int i;
        !          3223: 
        !          3224:        printf("{ ");
        !          3225:        for (i = 0; i < 8; i++) {
        !          3226:                if (xl6sts & (1 << i))
        !          3227:                        printf("%s, ", qicStat[i]);
        !          3228:        }
        !          3229:        putchar('}');
        !          3230: }

unix.superglobalmegacorp.com

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