|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.