Annotation of coherent/b/STREAMS/io.386/xlft.c, revision 1.1.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.