|
|
1.1 ! root 1: /* ! 2: * DSA tape class driver ! 3: * drives TMSCP tapes ! 4: */ ! 5: ! 6: #include "sys/param.h" ! 7: #include "sys/buf.h" ! 8: #include "sys/ta.h" ! 9: #include "sys/mscp.h" ! 10: #include "sys/user.h" ! 11: #include "sys/file.h" ! 12: #include "sys/conf.h" ! 13: #include "sys/mtio.h" ! 14: ! 15: extern struct msaddr taaddr[]; ! 16: extern struct tatape tatape[]; ! 17: extern int tacnt; ! 18: static long tarefno; /* ref seq num */ ! 19: extern struct buf tabuf[]; ! 20: ! 21: static tacmd(), taonline(), tasonl(), tacinit(); ! 22: ! 23: int taopen(), taread(), tawrite(), taioctl(), tastrategy(), taclose(); ! 24: struct bdevsw tabdev = bdinit(taopen, taclose, tastrategy, B_TAPE); ! 25: struct cdevsw tacdev = cdinit(taopen, taclose, taread, tawrite, taioctl); ! 26: ! 27: /* ! 28: * minor device number split ! 29: * ! 30: * NOCACHE disables write-behind caching; probably useless ! 31: * DENS selects one of the eight TMSCP density values; ! 32: * the drive is instructed to use 1<<DENS(dev) in whatever ! 33: * density language it believes ! 34: * here are some languages: ! 35: * for 9-track tapes, (0) 800 bpi (1) PE (2) GCR ! 36: * for old cartridge tapes (TK50), (3) block tape ! 37: * for new cartridge tapes (TK70), (0) low density (1) high density ! 38: * for other TMSCP devices, (0) is usually the right number ! 39: */ ! 40: #define UNIT(d) ((d)&07) ! 41: #define DENS(d) (((d)&070)>>3) ! 42: #define NOCACHE(d) ((d)&0100) ! 43: #define NOREW(d) ((d)&0200) ! 44: ! 45: /* ! 46: * reused bits of buf/iobuf struct ! 47: */ ! 48: ! 49: #define b_next av_forw /* next buffer in queue */ ! 50: #define b_pkt av_back /* pointer to mscp command */ ! 51: #define b_crf b_resid /* saved refno for pending command */ ! 52: ! 53: /* ! 54: * flags in tatape.flags ! 55: */ ! 56: ! 57: #define ONLINE 01 /* drive is online */ ! 58: #define WONLINE 02 /* waiting for online */ ! 59: #define OPEN 04 /* someone has drive open */ ! 60: #define WRITTEN 010 /* some data was written */ ! 61: #define WPROT 020 /* drive is write protected */ ! 62: #define NEEDCMD 040 /* waiting for some command to start */ ! 63: #define CMDDONE 0100 /* command is finished */ ! 64: #define CMDERR 0200 /* command finished, and error */ ! 65: #define UNHAPPY 0400 /* needs `cache data loss' clear */ ! 66: #define WONLY 01000 /* tape was opened only for writing */ ! 67: ! 68: /* ! 69: * random numbers ! 70: */ ! 71: ! 72: #define PRIONL (PZERO-1) ! 73: #define IDTA 1 /* connection ID for MSCP */ ! 74: ! 75: /* ! 76: * open a drive ! 77: */ ! 78: ! 79: int taseql(), tadg(); ! 80: ! 81: taopen(dev, flag) ! 82: dev_t dev; ! 83: { ! 84: register int unit; ! 85: register struct tatape *ta; ! 86: register struct msaddr *rp; ! 87: int wasoff; ! 88: ! 89: unit = UNIT(dev); ! 90: if (unit > tacnt) { ! 91: u.u_error = ENXIO; ! 92: return; ! 93: } ! 94: ta = &tatape[unit]; ! 95: rp = &taaddr[unit]; ! 96: if (ta->flags & OPEN) { ! 97: u.u_error = EBUSY; ! 98: return; ! 99: } ! 100: if (rp->ctype < 0 || rp->ctype >= nmsport ! 101: || (ta->port = msportsw[rp->ctype]) == NULL) { ! 102: u.u_error = ENXIO; ! 103: return; ! 104: } ! 105: ta->flags |= OPEN; ! 106: ta->flags &=~ (WRITTEN|WPROT|WONLY); ! 107: if ((*ta->port->mp_init)(rp->ctl, rp->ctype, 0, IDTA, taseql, tadg) == 0) { ! 108: u.u_error = ENXIO; ! 109: ta->flags &=~ OPEN; ! 110: return; ! 111: } ! 112: tacinit(ta, rp); ! 113: spl6(); ! 114: wasoff = (ta->flags & ONLINE) == 0; ! 115: if ((ta->flags & ONLINE) == 0) ! 116: taonline(ta, rp); ! 117: spl0(); ! 118: if ((ta->flags & ONLINE) == 0) { ! 119: u.u_error = ENXIO; ! 120: ta->flags &=~ OPEN; ! 121: return; ! 122: } ! 123: if ((ta->flags & WPROT) && (flag & FWRITE)) { ! 124: u.u_error = ENODEV; ! 125: if (!NOREW(dev)) ! 126: tacmd(unit, 1, OPAVL, 0, 0); ! 127: ta->flags &=~ (OPEN|ONLINE); ! 128: return; ! 129: } ! 130: ta->dens = (1<<DENS(dev)); ! 131: if (tacmd(unit, 0, OPGUS, 0, 0) /* fill in language in dens */ ! 132: || tacmd(unit, 0, OPSUC, NOCACHE(dev)?0:UFWBK, wasoff?ta->dens:0)) { ! 133: u.u_error = ENXIO; ! 134: if (!NOREW(dev)) ! 135: tacmd(unit, 1, OPAVL, 0, 0); ! 136: ta->flags &=~ (OPEN|ONLINE); ! 137: return; ! 138: } ! 139: if ((flag & (FREAD|FWRITE)) == FWRITE) ! 140: ta->flags |= WONLY; ! 141: } ! 142: ! 143: taclose(dev) ! 144: { ! 145: register struct tatape *ta; ! 146: int unit; ! 147: ! 148: unit = UNIT(dev); ! 149: ta = &tatape[unit]; ! 150: if (ta->flags & ONLINE) { ! 151: if (ta->flags & (WONLY|WRITTEN)) { ! 152: tacmd(unit, 0, OPWRM, 0, 0); ! 153: tacmd(unit, 0, OPWRM, 0, 0); ! 154: tacmd(unit, 0, OPPOS, 0, -1); ! 155: } ! 156: /* annoyance: OPAVL always rewinds. */ ! 157: if (!NOREW(dev)) ! 158: tacmd(unit, 1, OPAVL, 0, 0); ! 159: } ! 160: ta->flags &=~ OPEN; ! 161: } ! 162: ! 163: /* ! 164: * send some non-io command to a tape drive ! 165: * op is the MSCP opcode; ! 166: * p0 and p1 are some parameters ! 167: * if async == 0, don't return until command does ! 168: */ ! 169: ! 170: #define TWPRI PZERO ! 171: #define TCPRI (PZERO+1) ! 172: ! 173: static ! 174: tacmd(dev, async, op, p0, p1) ! 175: { ! 176: register struct mscmd *mp; ! 177: register struct tatape *ta; ! 178: register struct msaddr *rp; ! 179: register s; ! 180: register err; ! 181: ! 182: ta = &tatape[dev]; ! 183: rp = &taaddr[dev]; ! 184: if ((ta->flags & ONLINE) == 0) ! 185: return (1); ! 186: mp = (*ta->port->mp_get)(rp->ctl); ! 187: bzero((caddr_t)mp, sizeof(struct mscmd)); /* clear reserved fields */ ! 188: mp->m_crf = ++tarefno; ! 189: mp->m_unit = rp->unit; ! 190: mp->m_opcd = op; ! 191: mp->m_mod = MDCSX; ! 192: switch (op) { ! 193: case OPPOS: /* position: type, nobjs */ ! 194: if (p1 < 0) { ! 195: p1 = -p1; ! 196: mp->m_mod |= MDREV; ! 197: } ! 198: if (p0 == -1) { /* -1 == rewind */ ! 199: mp->m_mod |= MDREW; ! 200: mp->m_mod |= p1; /* hack */ ! 201: } ! 202: else if (p0 == 0) /* 0 == skip files */ ! 203: mp->m_fcnt = p1; ! 204: else { /* 1 == skip records */ ! 205: mp->m_mod |= MDOBJ; ! 206: mp->m_rcnt = p1; ! 207: } ! 208: break; ! 209: ! 210: case OPSUC: /* set unit char: unit flags, density */ ! 211: mp->m_unfl |= p0; ! 212: mp->m_fmt = p1; ! 213: break; ! 214: ! 215: case OPGUS: /* get unit status */ ! 216: mp->m_mod = p0; /* wretched TK50 */ ! 217: break; ! 218: ! 219: default: /* anything else: modifiers, 0 */ ! 220: mp->m_mod |= p0; ! 221: break; ! 222: } ! 223: s = spl6(); ! 224: while (ta->cmdp) { ! 225: ta->flags |= NEEDCMD; ! 226: sleep((caddr_t)ta, TWPRI); ! 227: } ! 228: ta->cmdp = mp; ! 229: ta->flags &=~ (CMDERR|CMDDONE); ! 230: if (ta->flags & UNHAPPY) { ! 231: ta->flags &=~ UNHAPPY; ! 232: mp->m_mod |= MDCDL; ! 233: } ! 234: (*ta->port->mp_send)(rp->ctl, IDTA, mp); ! 235: if (async == 0) { ! 236: while ((ta->flags & CMDDONE) == 0) ! 237: if (tsleep((caddr_t)ta, TCPRI, 0) == TS_SIG) ! 238: break; ! 239: } ! 240: err = ((ta->flags & CMDERR) != 0); ! 241: ta->cmdp = NULL; ! 242: if (ta->flags & NEEDCMD) { ! 243: ta->flags &=~ NEEDCMD; ! 244: wakeup((caddr_t)ta); ! 245: } ! 246: splx(s); ! 247: return (err); ! 248: } ! 249: ! 250: int tastrategy(); ! 251: ! 252: taread(dev) ! 253: { ! 254: physio(tastrategy, &tabuf[UNIT(dev)], dev, B_READ, minphys); ! 255: } ! 256: ! 257: tawrite(dev) ! 258: { ! 259: physio(tastrategy, &tabuf[UNIT(dev)], dev, B_WRITE, minphys); ! 260: } ! 261: ! 262: /* ! 263: * strategy routine; ! 264: * send the packet right away ! 265: */ ! 266: ! 267: tastrategy(bp) ! 268: register struct buf *bp; ! 269: { ! 270: register struct tatape *ta; ! 271: register struct mscmd *mp; ! 272: register int unit; ! 273: register struct msaddr *rp; ! 274: int count; ! 275: ! 276: unit = UNIT(minor(bp->b_dev)); ! 277: ta = &tatape[unit]; ! 278: rp = &taaddr[unit]; ! 279: count = bp->b_bcount; ! 280: spl6(); ! 281: if ((ta->flags & ONLINE) == 0 && taonline(ta, rp) == 0) { ! 282: bp->b_flags |= B_ERROR; ! 283: iodone(bp); ! 284: spl0(); ! 285: return; ! 286: } ! 287: mp = (*ta->port->mp_get)(rp->ctl); ! 288: mp->m_crf = ++tarefno; ! 289: mp->m_unit = rp->unit; ! 290: mp->m_opcd = (bp->b_flags & B_READ) ? OPRD : OPWR; ! 291: mp->m_mod = MDCSX; ! 292: if (ta->flags & UNHAPPY && (bp->b_flags & B_READ) == 0) { ! 293: ta->flags &=~ UNHAPPY; ! 294: mp->m_mod |= MDCDL; ! 295: } ! 296: mp->m_unfl = 0; ! 297: mp->m_bcnt = count; ! 298: /* seek on block device? later */ ! 299: (*ta->port->mp_map)(rp->ctl, mp, bp); ! 300: bp->b_pkt = (struct buf *)mp; ! 301: bp->b_crf = mp->m_crf; ! 302: bp->b_next = NULL; ! 303: if (ta->actf) ! 304: ta->actl->b_next = bp; ! 305: else ! 306: ta->actf = bp; ! 307: ta->actl = bp; ! 308: if ((bp->b_flags & B_READ) == 0) ! 309: ta->flags |= WRITTEN; ! 310: (*ta->port->mp_send)(rp->ctl, IDTA, mp); ! 311: spl0(); ! 312: } ! 313: ! 314: /* ! 315: * ioctl ! 316: * a subset of the berkeley ones ! 317: */ ! 318: ! 319: taioctl(dev, cmd, addr, flag) ! 320: dev_t dev; ! 321: caddr_t addr; ! 322: { ! 323: struct mtop mt; ! 324: int func, p0, p1; ! 325: ! 326: switch (cmd) { ! 327: default: ! 328: u.u_error = ENOTTY; ! 329: break; ! 330: /* does anything use the other ones? */ ! 331: ! 332: case MTIOCTOP: ! 333: if (copyin(addr, (caddr_t)&mt, sizeof(struct mtop)) < 0) { ! 334: u.u_error = EFAULT; ! 335: return; ! 336: } ! 337: if (mt.mt_op == MTWEOF) { /* oddball */ ! 338: if ((flag & FWRITE) == 0) { ! 339: u.u_error = EBADF; ! 340: return; ! 341: } ! 342: while (mt.mt_count-- > 0) ! 343: if (tacmd(UNIT(dev), 0, OPWRM, 0, 0)) { ! 344: u.u_error = EIO; ! 345: return; ! 346: } ! 347: return; ! 348: } ! 349: if (mt.mt_op == MTRST) { /* another oddball */ ! 350: (*tatape[UNIT(dev)].port->mp_init)(taaddr[UNIT(dev)].ctl, taaddr[UNIT(dev)].ctype, 1, IDTA, taseql, tadg); ! 351: return; ! 352: } ! 353: p1 = mt.mt_count; ! 354: func = OPPOS; ! 355: switch (mt.mt_op) { /* arcane arguments to tapos */ ! 356: case MTBSF: ! 357: p1 = -p1; ! 358: case MTFSF: ! 359: p0 = 0; ! 360: break; ! 361: ! 362: case MTBSR: ! 363: p1 = -p1; ! 364: case MTFSR: ! 365: p0 = 1; ! 366: break; ! 367: ! 368: case MTREW: ! 369: p1 = 0; ! 370: p0 = -1; ! 371: break; ! 372: ! 373: case MTOFFL: ! 374: func = OPAVL; ! 375: p1 = 0; ! 376: p0 = MDUNL; ! 377: break; ! 378: ! 379: case MTNOP: ! 380: return; /* silly */ ! 381: } ! 382: if (tacmd(UNIT(dev), 0, func, p0, p1)) ! 383: u.u_error = EIO; ! 384: break; ! 385: } ! 386: } ! 387: ! 388: /* ! 389: * here when the port gets a sequential message ! 390: */ ! 391: taseql(ctl, type, ep) ! 392: int ctl, type; ! 393: register struct msend *ep; ! 394: { ! 395: register struct buf *bp; ! 396: register struct tatape *ta; ! 397: register int unit; ! 398: register struct buf *obp; ! 399: int sts; ! 400: ! 401: if (ep->m_opcd == 0 && ep->m_sts == STRST) { ! 402: tareset(ctl, type); ! 403: return; ! 404: } ! 405: /* get rid of this wretched loop somehow */ ! 406: for (unit = 0; unit < tacnt; unit++) ! 407: if (taaddr[unit].ctl == ctl ! 408: && taaddr[unit].ctype == type ! 409: && taaddr[unit].unit == ep->m_unit) ! 410: break; ! 411: if (unit >= tacnt) { ! 412: printf("tmscp stray unit: ctl%d typ%d ta%d sts %o opcode %o\n", ! 413: ctl, type, ep->m_unit, ep->m_sts, ep->m_opcd); ! 414: return; ! 415: } ! 416: ta = &tatape[unit]; ! 417: if (ep->m_flgs & EFCDL) ! 418: ta->flags |= UNHAPPY; ! 419: switch (ep->m_opcd & 0377) { ! 420: case OPEND: /* eg invalid command */ ! 421: printf("tmscp ctl%d ta%d ill cmd crf %d off %d\n", ctl, ! 422: ep->m_unit, ep->m_crf, ep->m_sts>>8); ! 423: if (ta->cmdp && ta->cmdp->m_crf == ep->m_crf) ! 424: goto fincmd; ! 425: /* else maybe it's a transfer; fall in */ ! 426: case OPRD|OPEND: ! 427: case OPWR|OPEND: ! 428: for (bp = ta->actf, obp = NULL; bp; obp = bp, bp = bp->b_next) ! 429: if (ep->m_crf == bp->b_crf) ! 430: break; ! 431: if (bp == NULL) { ! 432: printf("ta%d stray end: crf %d sts x%x opcode 0%o\n", ! 433: unit, ep->m_crf, ep->m_sts, ep->m_opcd & 0377); ! 434: return; ! 435: } ! 436: if (obp) ! 437: obp->b_next = bp->b_next; ! 438: else ! 439: ta->actf = bp->b_next; ! 440: if (bp == ta->actl) ! 441: ta->actl = obp; ! 442: sts = ep->m_sts & STMSK; ! 443: if (sts == STAVL || sts == STOFL) ! 444: ta->flags &=~ ONLINE; /* help! */ ! 445: bp->b_resid = bp->b_bcount - ep->m_bcnt; ! 446: if (sts == STTPM) ! 447: sts = STSUC; /* tape mark -> empty read */ ! 448: if (sts != STSUC) { ! 449: bp->b_flags |= B_ERROR; ! 450: switch (sts) { ! 451: case STRDT: ! 452: case STOFL: ! 453: case STAVL: ! 454: case STWPR: /* well ... */ ! 455: break; ! 456: default: ! 457: printf("err on ta%d block %D: sts 0%o flgs 0%o\n", unit, bp->b_blkno, ep->m_sts, ep->m_flgs); ! 458: } ! 459: } ! 460: if (ep->m_flgs & EFEOT && (bp->b_flags & B_READ) == 0) { ! 461: bp->b_error = ENOSPC; ! 462: bp->b_flags |= B_ERROR; ! 463: } ! 464: (*ta->port->mp_unmap)(ctl, (struct mscmd *)bp->b_pkt); ! 465: iodone(bp); ! 466: return; ! 467: ! 468: case OPGUS|OPEND: ! 469: ta->dens &= TFMASK; ! 470: ta->dens |= ep->m_menu & ~TFMASK; ! 471: goto fincmd; ! 472: ! 473: case OPAVL|OPEND: ! 474: if (ep->m_sts == STSUC) /* sic */ ! 475: ta->flags &=~ ONLINE; ! 476: case OPWRM|OPEND: ! 477: case OPPOS|OPEND: ! 478: case OPFLS|OPEND: ! 479: case OPSUC|OPEND: ! 480: fincmd: ! 481: if ((ep->m_sts & STMSK) == STAVL || (ep->m_sts & STMSK) == STOFL) ! 482: ta->flags &=~ ONLINE; ! 483: if (ta->cmdp) { ! 484: ta->flags |= CMDDONE; ! 485: if ((ep->m_sts & STMSK) != STSUC) { ! 486: printf("ta%d: cmd 0%o sts 0%o flgs 0%o\n", unit, ep->m_opcd&0377, ep->m_sts, ep->m_flgs); ! 487: ta->flags |= CMDERR; ! 488: } ! 489: wakeup((caddr_t)ta); ! 490: } ! 491: return; ! 492: ! 493: case OPONL|OPEND: ! 494: tasonl(ta, ep); ! 495: return; ! 496: ! 497: case OPSCC|OPEND: ! 498: if ((ep->m_sts & STMSK) != STSUC) ! 499: printf("tmscp ctl%d typ%d: bad init\n", ctl, type); ! 500: return; ! 501: ! 502: default: ! 503: printf("stray tmscp msg ta%d opcd 0%o sts x%x\n", ! 504: unit, ep->m_opcd&0377, ep->m_sts&0177777); ! 505: return; ! 506: } ! 507: } ! 508: ! 509: /* ! 510: * controller was reset ! 511: * discard all pending io, ! 512: * awake all sleepers, ! 513: * mark everything offline ! 514: */ ! 515: ! 516: tareset(ctl, type) ! 517: int ctl, type; ! 518: { ! 519: register int unit; ! 520: register struct tatape *ta; ! 521: register struct buf *bp, *nbp; ! 522: ! 523: for (unit = 0; unit < tacnt; unit++) { ! 524: if (taaddr[unit].ctl != ctl || taaddr[unit].ctype != type) ! 525: continue; ! 526: ta = &tatape[unit]; ! 527: for (bp = ta->actf; bp; bp = nbp) { ! 528: nbp = bp->b_next; ! 529: (*ta->port->mp_unmap)(ctl, (struct mscmd *)bp->b_pkt); ! 530: bp->b_flags |= B_ERROR; ! 531: iodone(bp); ! 532: } ! 533: ta->actf = ta->actl = NULL; ! 534: ta->flags &=~ (ONLINE|WONLINE); ! 535: if (ta->cmdp) ! 536: ta->flags |= CMDDONE|CMDERR; ! 537: wakeup((caddr_t)ta); ! 538: } ! 539: } ! 540: ! 541: /* ! 542: * here with a datagram message ! 543: * explanations really shouldn't be in the driver ! 544: */ ! 545: ! 546: static char *taevents[] = { ! 547: "ok", ! 548: "inv cmd", ! 549: "op aborted", ! 550: "offline", ! 551: "available", ! 552: "med fmt", ! 553: "write prot", ! 554: "comp err", ! 555: "data err", ! 556: "host buf access err", ! 557: "cntl err", ! 558: "drive err", ! 559: }; ! 560: #define MAXEVT 0xb ! 561: ! 562: tadg(ctl, type, ep) ! 563: int ctl, type; ! 564: register struct mserl *ep; ! 565: { ! 566: ! 567: if (ep->l_evnt == STSEX) /* boring, at least for now */ ! 568: return; ! 569: printf("ta%d ctl%d typ%d seq %d: %s err; fmt x%x ev x%x fl x%x\n", ! 570: ep->l_unit, ctl, type, ep->l_seq, /* phys unit, not log */ ! 571: ep->l_flgs&(LFSUC|LFCON) ? "soft" : "hard", ! 572: ep->l_fmt, ep->l_evnt, ep->l_flgs&0377); ! 573: if ((ep->l_evnt & STMSK) <= MAXEVT) ! 574: printf("%s; ", taevents[ep->l_evnt & STMSK]); ! 575: switch (ep->l_fmt) { ! 576: case FMCNT: ! 577: /* now the thing should be marked disastrously bad */ ! 578: printf("oops\n"); ! 579: break; ! 580: ! 581: case FMBAD: ! 582: printf("host mem access; addr x%x\n", ep->l_badr); ! 583: break; ! 584: ! 585: case FMTAPE: ! 586: printf("lvl x%x retry x%x\n", ep->l_lvl, ep->l_rtry); ! 587: break; ! 588: ! 589: default: ! 590: printf("\n"); ! 591: break; ! 592: } ! 593: } ! 594: ! 595: /* ! 596: * unit is believed offline ! 597: * try to bring it on ! 598: */ ! 599: ! 600: static ! 601: taonline(ta, rp) ! 602: register struct tatape *ta; ! 603: register struct msaddr *rp; ! 604: { ! 605: register struct mscmd *mp; ! 606: int s; ! 607: ! 608: s = spl6(); ! 609: if ((ta->flags & WONLINE) == 0) { ! 610: mp = (*ta->port->mp_get)(rp->ctl); ! 611: bzero((caddr_t)mp, sizeof(struct mscmd)); /* clear reserved fields */ ! 612: mp->m_crf = ++tarefno; ! 613: mp->m_unit = rp->unit; ! 614: mp->m_opcd = OPONL; ! 615: mp->m_mod = MDCSX|MDXCL; ! 616: if (ta->flags & UNHAPPY) { ! 617: ta->flags &=~ UNHAPPY; ! 618: mp->m_mod |= MDCDL; ! 619: } ! 620: mp->m_unfl = 0; ! 621: mp->m_fmt = 0; /* ta->dens? */ ! 622: (*ta->port->mp_send)(rp->ctl, IDTA, mp); ! 623: ta->flags |= WONLINE; ! 624: } ! 625: while (ta->flags & WONLINE) ! 626: tsleep((caddr_t)ta, PRIONL, 60); ! 627: splx(s); ! 628: if ((ta->flags & ONLINE) == 0) ! 629: return (0); ! 630: return (1); ! 631: } ! 632: ! 633: static ! 634: tasonl(ta, ep) ! 635: register struct tatape *ta; ! 636: register struct msend *ep; ! 637: { ! 638: ! 639: if (ta->flags & WONLINE) { ! 640: ta->flags &=~ WONLINE; ! 641: wakeup((caddr_t)ta); ! 642: } ! 643: if ((ep->m_sts & STMSK) != STSUC) ! 644: return; ! 645: ta->flags |= ONLINE; ! 646: if (ep->m_unfl & UFWPH) ! 647: ta->flags |= WPROT; ! 648: } ! 649: ! 650: /* ! 651: * controller init ! 652: * set characteristics to turn off host timeouts ! 653: */ ! 654: ! 655: static ! 656: tacinit(ta, rp) ! 657: struct tatape *ta; ! 658: struct msaddr *rp; ! 659: { ! 660: register struct mscmd *mp; ! 661: register int s; ! 662: ! 663: mp = (*ta->port->mp_get)(rp->ctl); ! 664: bzero((caddr_t)mp, sizeof(struct mscmd)); /* clear reserved fields */ ! 665: mp->m_crf = ++tarefno; ! 666: mp->m_opcd = OPSCC; ! 667: mp->m_mod = MDCSX; ! 668: mp->m_cntf = CFMSC | CFTHS; ! 669: mp->m_vrsn = MSCPVER; ! 670: s = spl6(); ! 671: (*ta->port->mp_send)(rp->ctl, IDTA, mp); ! 672: splx(s); ! 673: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.