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

unix.superglobalmegacorp.com

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