|
|
1.1 ! root 1: /* @(#)tmscp.c 7.14 (Berkeley) 7/1/90 */ ! 2: ! 3: #ifndef lint ! 4: static char *sccsid = "@(#)tmscp.c 1.24 (ULTRIX) 1/21/86"; ! 5: #endif lint ! 6: ! 7: ! 8: /************************************************************************ ! 9: * * ! 10: * Licensed from Digital Equipment Corporation * ! 11: * Copyright (c) * ! 12: * Digital Equipment Corporation * ! 13: * Maynard, Massachusetts * ! 14: * 1985, 1986 * ! 15: * All rights reserved. * ! 16: * * ! 17: * The Information in this software is subject to change * ! 18: * without notice and should not be construed as a commitment * ! 19: * by Digital Equipment Corporation. Digital makes no * ! 20: * representations about the suitability of this software for * ! 21: * any purpose. It is supplied "As Is" without expressed or * ! 22: * implied warranty. * ! 23: * * ! 24: * If the Regents of the University of California or its * ! 25: * licensees modify the software in a manner creating * ! 26: * diriviative copyright rights, appropriate copyright * ! 27: * legends may be placed on the drivative work in addition * ! 28: * to that set forth above. * ! 29: * * ! 30: ************************************************************************ ! 31: * ! 32: * tmscp.c - TMSCP (TK50/TU81) tape device driver ! 33: * ! 34: * Modification History: ! 35: * ! 36: * 06-Jan-86 - afd ! 37: * Changed the probe routine to use DELAY (not TODR). This now ! 38: * works for MicroVAXen as well. This eliminates the busy-wait ! 39: * for MicroVAXen so a dead TK50 controller will not hang autoconf. ! 40: * ! 41: * 06-Dec-85 - afd ! 42: * Fixed a bug in density selection. The "set unit characteristics" ! 43: * command to select density, was clearing the "unit flags" field ! 44: * where the CACHE bit was for TU81-E. Now the unit's "format" and ! 45: * "unitflgs" are saved in tms_info struct. And are used on STUNT ! 46: * commands. ! 47: * ! 48: * 19-Oct-85 - afd ! 49: * Added support to the open routine to allow drives to be opened ! 50: * for low density (800 or 1600 bpi) use. When the slave routine ! 51: * initiates a "get-unit-char" cmd, the format menu for the unit ! 52: * is saved in the tms_info structure. The format menu is used in the ! 53: * start routine to select the proper low density. ! 54: * ! 55: * 02-Oct-85 - afd ! 56: * When a tmscp-type controller is initializing, it is possible for ! 57: * the sa reg to become 0 between states. Thus the init code in ! 58: * the interrupt routine had to be modified to reflect this. ! 59: * ! 60: * 21-Sep-85 - afd ! 61: * The TK50 declares a serious exception when a tape mark is encountered. ! 62: * This causes problems to dd (& other UN*X utilities). So a flag ! 63: * is set in the rsp() routine when a tape mark is encountered. If ! 64: * this flag is set, the start() routine appends the Clear Serious ! 65: * Exception modifier to the next command. ! 66: * ! 67: * 03-Sep-85 -- jaw ! 68: * messed up previous edit.. ! 69: * ! 70: * 29-Aug-85 - jaw ! 71: * fixed bugs in 8200 and 750 buffered datapath handling. ! 72: * ! 73: * 06-Aug-85 - afd ! 74: * 1. When repositioning records or files, the count of items skipped ! 75: * does NOT HAVE to be returned by controllers (& the TU81 doesn't). ! 76: * So tmscprsp() had to be modified to stop reporting ! 77: * residual count errors on reposition commands. ! 78: * ! 79: * 2. Fixed bug in the open routine which allowed multiple opens. ! 80: * ! 81: * 18-Jul-85 - afd ! 82: * 1. Need to return status when mt status (or corresponding ioctl) is done. ! 83: * Save resid, flags, endcode & status in tmscprsp() routine (except on ! 84: * clear serious exception no-op). Return these fields when status ! 85: * ioctl is done (in tmscpcommand()). How they are returned: ! 86: * mt_resid = resid ! 87: * mt_dsreg = flags|endcode ! 88: * mt_erreg = status ! 89: * ! 90: * 2. Added latent support for enabling/disabling caching. This is ! 91: * handled along with all other ioctl commands. ! 92: * ! 93: * 3. Need to issue a no-op on unrecognized ioctl in tmscpstart(), since ! 94: * we have already commited to issuing a command at that point. ! 95: * ! 96: * 4. In tmscprsp() routine if encode is 0200 (invalid command issued); ! 97: * We need to: Unlink the buffer from the I/O wait queue, ! 98: * and signal iodone, so the higher level command can exit! ! 99: * Just as if it were a valid command. ! 100: * ! 101: * 11-jul-85 -- jaw ! 102: * fix bua/bda map registers. ! 103: * ! 104: * 19-Jun-85 -- jaw ! 105: * VAX8200 name change. ! 106: * ! 107: * 06-Jun-85 - jaw ! 108: * fixes for 8200. ! 109: * ! 110: * 9-Apr-85 - afd ! 111: * Added timeout code to the probe routine, so if the controller ! 112: * fails to init in 10 seconds we return failed status. ! 113: * ! 114: * 13-Mar-85 -jaw ! 115: * Changes for support of the VAX8200 were merged in. ! 116: * ! 117: * 27-Feb-85 -tresvik ! 118: * Changes for support of the VAX8600 were merged in. ! 119: * ! 120: */ ! 121: ! 122: #include "tms.h" ! 123: #if NTMSCP > 0 ! 124: ! 125: #include "param.h" ! 126: #include "systm.h" ! 127: #include "buf.h" ! 128: #include "conf.h" ! 129: #include "errno.h" ! 130: #include "file.h" ! 131: #include "map.h" ! 132: #include "vm.h" ! 133: #include "ioctl.h" ! 134: #include "syslog.h" ! 135: #include "mtio.h" ! 136: #include "cmap.h" ! 137: #include "uio.h" ! 138: #include "tprintf.h" ! 139: ! 140: #include "../vax/pte.h" ! 141: #include "../vax/cpu.h" ! 142: #include "../vax/mtpr.h" ! 143: #include "ubareg.h" ! 144: #include "ubavar.h" ! 145: ! 146: #define TENSEC (1000) ! 147: #define TMS_PRI LOG_INFO ! 148: ! 149: #define NRSPL2 3 /* log2 number of response packets */ ! 150: #define NCMDL2 3 /* log2 number of command packets */ ! 151: #define NRSP (1<<NRSPL2) ! 152: #define NCMD (1<<NCMDL2) ! 153: ! 154: #include "tmscpreg.h" ! 155: #include "../vax/tmscp.h" ! 156: ! 157: /* Software state per controller */ ! 158: ! 159: struct tmscp_softc { ! 160: short sc_state; /* state of controller */ ! 161: short sc_mapped; /* Unibus map allocated for tmscp struct? */ ! 162: int sc_ubainfo; /* Unibus mapping info */ ! 163: struct tmscp *sc_tmscp; /* Unibus address of tmscp struct */ ! 164: int sc_ivec; /* interrupt vector address */ ! 165: short sc_credits; /* transfer credits */ ! 166: short sc_lastcmd; /* pointer into command ring */ ! 167: short sc_lastrsp; /* pointer into response ring */ ! 168: short sc_ipl; /* interrupt priority (Q-bus) */ ! 169: } tmscp_softc[NTMSCP]; ! 170: ! 171: struct tmscp { ! 172: struct tmscpca tmscp_ca; /* communications area */ ! 173: struct mscp tmscp_rsp[NRSP]; /* response packets */ ! 174: struct mscp tmscp_cmd[NCMD]; /* command packets */ ! 175: } tmscp[NTMSCP]; ! 176: ! 177: /* ! 178: * Per drive-unit info ! 179: */ ! 180: struct tms_info { ! 181: daddr_t tms_dsize; /* Max user size from online pkt */ ! 182: unsigned tms_type; /* Drive type int field */ ! 183: int tms_resid; /* residual from last xfer */ ! 184: u_char tms_endcode; /* last command endcode */ ! 185: u_char tms_flags; /* last command end flags */ ! 186: unsigned tms_status; /* Command status from last command */ ! 187: char tms_openf; /* lock against multiple opens */ ! 188: char tms_lastiow; /* last op was a write */ ! 189: char tms_serex; /* set when serious exception occurs */ ! 190: char tms_clserex; /* set when serex being cleared by no-op */ ! 191: short tms_fmtmenu; /* the unit's format (density) menu */ ! 192: short tms_unitflgs; /* unit flag parameters */ ! 193: short tms_format; /* the unit's current format (density) */ ! 194: tpr_t tms_tpr; /* tprintf handle */ ! 195: } tms_info[NTMS]; ! 196: struct uba_ctlr *tmscpminfo[NTMSCP]; ! 197: struct uba_device *tmsdinfo[NTMS]; ! 198: /* ! 199: * ifdef other tmscp devices here if they allow more than 1 unit/controller ! 200: */ ! 201: struct uba_device *tmscpip[NTMSCP][1]; ! 202: struct buf ctmscpbuf[NTMSCP]; /* internal cmd buffer (for ioctls) */ ! 203: struct buf tmsutab[NTMS]; /* Drive queue */ ! 204: struct buf tmscpwtab[NTMSCP]; /* I/O wait queue, per controller */ ! 205: int tmscpmicro[NTMSCP]; /* to store microcode level */ ! 206: short utoctlr[NTMS]; /* Slave unit to controller mapping */ ! 207: /* filled in by the slave routine */ ! 208: ! 209: /* Bits in minor device */ ! 210: #define TMSUNIT(dev) (minor(dev)&03) ! 211: #define T_NOREWIND 04 ! 212: #define T_HIDENSITY 010 ! 213: ! 214: /* Slave unit to controller mapping */ ! 215: #define TMSCPCTLR(dev) (utoctlr[TMSUNIT(dev)]) ! 216: ! 217: /* ! 218: * Internal (ioctl) command codes (these must also be declared in the ! 219: * tmscpioctl routine). These correspond to ioctls in mtio.h ! 220: */ ! 221: #define TMS_WRITM 0 /* write tape mark */ ! 222: #define TMS_FSF 1 /* forward space file */ ! 223: #define TMS_BSF 2 /* backward space file */ ! 224: #define TMS_FSR 3 /* forward space record */ ! 225: #define TMS_BSR 4 /* backward space record */ ! 226: #define TMS_REW 5 /* rewind tape */ ! 227: #define TMS_OFFL 6 /* rewind tape & mark unit offline */ ! 228: #define TMS_SENSE 7 /* noop - do a get unit status */ ! 229: #define TMS_CACHE 8 /* enable cache */ ! 230: #define TMS_NOCACHE 9 /* disable cache */ ! 231: /* These go last: after all real mt cmds, just bump the numbers up */ ! 232: #define TMS_CSE 10 /* clear serious exception */ ! 233: #define TMS_LOWDENSITY 11 /* set unit to low density */ ! 234: #define TMS_HIDENSITY 12 /* set unit to high density */ ! 235: ! 236: /* ! 237: * Controller states ! 238: */ ! 239: #define S_IDLE 0 /* hasn't been initialized */ ! 240: #define S_STEP1 1 /* doing step 1 init */ ! 241: #define S_STEP2 2 /* doing step 2 init */ ! 242: #define S_STEP3 3 /* doing step 3 init */ ! 243: #define S_SCHAR 4 /* doing "set controller characteristics" */ ! 244: #define S_RUN 5 /* running */ ! 245: ! 246: int tmscperror = 0; /* causes hex dump of packets */ ! 247: int tmscp_cp_wait = 0; /* Something to wait on for command */ ! 248: /* packets and or credits. */ ! 249: int wakeup(); ! 250: extern int hz; /* Should find the right include */ ! 251: ! 252: #ifdef DEBUG ! 253: #define printd if (tmscpdebug) printf ! 254: int tmscpdebug = 1; ! 255: #define printd10 if(tmscpdebug >= 10) printf ! 256: #endif ! 257: ! 258: int tmscpprobe(), tmscpslave(), tmscpattach(), tmscpintr(); ! 259: struct mscp *tmscpgetcp(); ! 260: ! 261: #define DRVNAME "tms" ! 262: #define CTRLNAME "tmscp" ! 263: ! 264: u_short tmscpstd[] = { 0174500, 0 }; ! 265: struct uba_driver tmscpdriver = ! 266: { tmscpprobe, tmscpslave, tmscpattach, 0, tmscpstd, DRVNAME, tmsdinfo, CTRLNAME ! 267: , tmscpminfo, 0}; ! 268: ! 269: #define b_qsize b_resid /* queue size per drive, in tmsutab */ ! 270: #define b_ubinfo b_resid /* Unibus mapping info, per buffer */ ! 271: ! 272: ! 273: /*************************************************************************/ ! 274: ! 275: #define DELAYTEN 1000 ! 276: ! 277: /* ! 278: * Unfortunately qbgetpri can't be used because the TK50 doesn't flip the ! 279: * TMSCP_STEP2 flag in the tmscpsa register until after the pending interrupt ! 280: * has been acknowledged by the cpu. If you are at spl6(), the TMSCP_STEP2 ! 281: * flag never gets set and you return (0). ! 282: */ ! 283: tmscpprobe(reg, ctlr) ! 284: caddr_t reg; /* address of the IP register */ ! 285: int ctlr; /* index of controller in the tmscp_softc array */ ! 286: { ! 287: register int br, cvec; /* MUST be 1st (r11 & r10): IPL and intr vec */ ! 288: register struct tmscp_softc *sc = &tmscp_softc[ctlr]; ! 289: /* ptr to software controller structure */ ! 290: struct tmscpdevice *tmscpaddr; /* ptr to tmscpdevice struct (IP & SA) */ ! 291: int count; /* for probe delay time out */ ! 292: ! 293: # ifdef lint ! 294: br = 0; cvec = br; br = cvec; reg = reg; ! 295: tmscpreset(0); tmscpintr(0); ! 296: # endif ! 297: ! 298: tmscpaddr = (struct tmscpdevice *) reg; ! 299: /* ! 300: * Set host-settable interrupt vector. ! 301: * Assign 0 to the ip register to start the tmscp-device initialization. ! 302: * The device is not really initialized at this point, this is just to ! 303: * find out if the device exists. ! 304: */ ! 305: sc->sc_ivec = (uba_hd[numuba].uh_lastiv -= 4); ! 306: tmscpaddr->tmscpip = 0; ! 307: ! 308: count=0; ! 309: while(count < DELAYTEN) ! 310: { /* wait for at most 10 secs */ ! 311: if((tmscpaddr->tmscpsa & TMSCP_STEP1) != 0) ! 312: break; ! 313: DELAY(10000); ! 314: count=count+1; ! 315: } ! 316: if (count == DELAYTEN) ! 317: return(0); ! 318: ! 319: tmscpaddr->tmscpsa = TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8)|TMSCP_IE|(sc->sc_ivec/4); ! 320: ! 321: count=0; ! 322: while(count < DELAYTEN) ! 323: { ! 324: if((tmscpaddr->tmscpsa & TMSCP_STEP2) != 0) ! 325: break; ! 326: DELAY(10000); ! 327: count = count+1; ! 328: } ! 329: if (count == DELAYTEN) ! 330: return(0); ! 331: ! 332: #ifdef QBA ! 333: sc->sc_ipl = br = 0x15; ! 334: #endif ! 335: return(sizeof (struct tmscpdevice)); ! 336: } ! 337: ! 338: /* ! 339: * Try to find a slave (a drive) on the controller. ! 340: * If the controller is not in the run state, call init to initialize it. ! 341: */ ! 342: tmscpslave (ui, reg) ! 343: struct uba_device *ui; /* ptr to the uba device structure */ ! 344: caddr_t reg; /* addr of the device controller */ ! 345: { ! 346: register struct uba_ctlr *um = tmscpminfo[ui->ui_ctlr]; ! 347: register struct tmscp_softc *sc = &tmscp_softc[ui->ui_ctlr]; ! 348: register struct tms_info *tms = &tms_info[ui->ui_unit]; ! 349: struct tmscpdevice *tmscpaddr; /* ptr to IP & SA */ ! 350: struct mscp *mp; ! 351: int i; /* Something to write into to start */ ! 352: /* the tmscp polling */ ! 353: ! 354: # ifdef lint ! 355: reg = reg; ! 356: # endif ! 357: tmscpaddr = (struct tmscpdevice *)um->um_addr; ! 358: /* ! 359: * If its not in the run state, start the initialization process ! 360: * (tmscpintr will complete it); if the initialization doesn't start; ! 361: * then return. ! 362: */ ! 363: if(sc->sc_state != S_RUN) ! 364: { ! 365: # ifdef DEBUG ! 366: printd("tmscpslave: ctlr not running: calling init \n"); ! 367: # endif ! 368: if(!tmscpinit(ui->ui_ctlr)) ! 369: return(0); ! 370: } ! 371: /* ! 372: * Wait for the controller to come into the run state or go idle. ! 373: * If it goes idle return. ! 374: */ ! 375: # ifdef DEBUG ! 376: i=1; ! 377: # endif ! 378: while(sc->sc_state != S_RUN && sc->sc_state != S_IDLE) ! 379: # ifdef DEBUG ! 380: if (tmscpaddr->tmscpsa & TMSCP_ERR && i) ! 381: { ! 382: printd("tmscp-device: fatal error (%o)\n", tmscpaddr->tmscpsa&0xffff); ! 383: i=0; ! 384: } ! 385: # endif ! 386: ; /* wait */ ! 387: if(sc->sc_state == S_IDLE) ! 388: { /* The tmscp device failed to initialize */ ! 389: printf("tmscp controller failed to init\n"); ! 390: return(0); ! 391: } ! 392: /* The controller is up so see if the drive is there */ ! 393: if(0 == (mp = tmscpgetcp(um))) ! 394: { ! 395: printf("tmscp can't get command packet\n"); ! 396: return(0); ! 397: } ! 398: /* Need to determine the drive type for generic driver */ ! 399: mp->mscp_opcode = M_OP_GTUNT; /* This should give us the device type */ ! 400: mp->mscp_unit = ui->ui_slave; ! 401: mp->mscp_cmdref = (long) ui->ui_slave; ! 402: tms->tms_status = 0; /* set to zero */ ! 403: tmscpip[ui->ui_ctlr][ui->ui_slave] = ui; ! 404: *((long *) mp->mscp_dscptr ) |= TMSCP_OWN | TMSCP_INT;/* maybe we should poll*/ ! 405: i = tmscpaddr->tmscpip; ! 406: #ifdef lint ! 407: i = i; ! 408: #endif ! 409: while(!tms->tms_status) ! 410: ; /* Wait for some status */ ! 411: # ifdef DEBUG ! 412: printd("tmscpslave: status = %o\n",tms->tms_status & M_ST_MASK); ! 413: # endif ! 414: tmscpip[ui->ui_ctlr][ui->ui_slave] = 0; ! 415: if(!tms->tms_type) /* packet from a GTUNT */ ! 416: return(0); /* Failed No such drive */ ! 417: else ! 418: return(1); /* Got it and it is there */ ! 419: } ! 420: ! 421: ! 422: /* ! 423: * Set ui flags to zero to show device is not online & set tmscpip. ! 424: * Unit to Controller mapping is set up here. ! 425: * Open routine will issue the online command, later. ! 426: */ ! 427: tmscpattach (ui) ! 428: register struct uba_device *ui; /* ptr to unibus dev struct */ ! 429: { ! 430: ! 431: ui->ui_flags = 0; ! 432: tmscpip[ui->ui_ctlr][ui->ui_slave] = ui; ! 433: # ifdef DEBUG ! 434: /* ! 435: * Check to see if the drive is available. ! 436: * If not then just print debug. ! 437: */ ! 438: if(tms_info[ui->ui_unit].tms_status != M_ST_AVLBL) ! 439: printd("tmscpattach: unavailable \n"); ! 440: # endif ! 441: utoctlr[ui->ui_unit] = ui->ui_ctlr; ! 442: } ! 443: ! 444: ! 445: /* ! 446: * TMSCP interrupt routine. ! 447: */ ! 448: tmscpintr (d) ! 449: int d; /* index to the controller */ ! 450: { ! 451: register struct uba_ctlr *um = tmscpminfo[d]; ! 452: register struct tmscpdevice *tmscpaddr = (struct tmscpdevice *)um->um_addr; ! 453: struct buf *bp; ! 454: register int i; ! 455: register struct tmscp_softc *sc = &tmscp_softc[d]; ! 456: register struct tmscp *tm = &tmscp[d]; ! 457: struct tmscp *ttm; ! 458: struct mscp *mp; ! 459: ! 460: # ifdef DEBUG ! 461: printd10("tmscpintr: state %d, tmscpsa %o\n", sc->sc_state, tmscpaddr->tmscpsa); ! 462: # endif ! 463: ! 464: #ifdef QBA ! 465: splx(sc->sc_ipl); ! 466: #endif ! 467: /* ! 468: * How the interrupt is handled depends on the state of the controller. ! 469: */ ! 470: switch (sc->sc_state) { ! 471: ! 472: case S_IDLE: ! 473: printf("tmscp%d: random interrupt ignored\n", d); ! 474: return; ! 475: ! 476: /* Controller was in step 1 last, see if its gone to step 2 */ ! 477: case S_STEP1: ! 478: # define STEP1MASK 0174377 ! 479: # define STEP1GOOD (TMSCP_STEP2|TMSCP_IE|(NCMDL2<<3)|NRSPL2) ! 480: for (i = 0; i < 150; i++) ! 481: { ! 482: if ((tmscpaddr->tmscpsa&STEP1MASK) != STEP1GOOD) ! 483: { /* still in step 1 (wait 1/100 sec) */ ! 484: DELAY(10000); ! 485: # ifdef DEBUG ! 486: printd("still in step 1, delaying\n"); ! 487: # endif DEBUG ! 488: } ! 489: else ! 490: break; ! 491: } ! 492: if (i > 149) ! 493: { ! 494: sc->sc_state = S_IDLE; ! 495: printf("failed to initialize, in step1: sa 0x%x", tmscpaddr->tmscpsa); ! 496: wakeup((caddr_t)um); ! 497: return; ! 498: } ! 499: tmscpaddr->tmscpsa = ((int)&sc->sc_tmscp->tmscp_ca.ca_ringbase) ! 500: | ((cpu == VAX_780 || cpu == VAX_8600) ? TMSCP_PI : 0); ! 501: sc->sc_state = S_STEP2; ! 502: return; ! 503: ! 504: /* Controller was in step 2 last, see if its gone to step 3 */ ! 505: case S_STEP2: ! 506: # define STEP2MASK 0174377 ! 507: # define STEP2GOOD (TMSCP_STEP3|TMSCP_IE|(sc->sc_ivec/4)) ! 508: for (i = 0; i < 150; i++) ! 509: { ! 510: if ((tmscpaddr->tmscpsa&STEP2MASK) != STEP2GOOD) ! 511: { /* still in step 2 (wait 1/100 sec) */ ! 512: DELAY(10000); ! 513: # ifdef DEBUG ! 514: printd("still in step 2, delaying\n"); ! 515: # endif DEBUG ! 516: } ! 517: else ! 518: break; ! 519: } ! 520: if (i > 149) ! 521: { ! 522: sc->sc_state = S_IDLE; ! 523: printf("failed to initialize, in step2: sa 0x%x", tmscpaddr->tmscpsa); ! 524: wakeup((caddr_t)um); ! 525: return; ! 526: } ! 527: tmscpaddr->tmscpsa = ((int)&sc->sc_tmscp->tmscp_ca.ca_ringbase)>>16; ! 528: sc->sc_state = S_STEP3; ! 529: return; ! 530: ! 531: /* Controller was in step 3 last, see if its gone to step 4 */ ! 532: case S_STEP3: ! 533: # define STEP3MASK 0174000 ! 534: # define STEP3GOOD TMSCP_STEP4 ! 535: for (i = 0; i < 150; i++) ! 536: { ! 537: if ((tmscpaddr->tmscpsa&STEP3MASK) != STEP3GOOD) ! 538: { /* still in step 3 (wait 1/100 sec) */ ! 539: DELAY(10000); ! 540: # ifdef DEBUG ! 541: printd("still in step 3, delaying\n"); ! 542: # endif DEBUG ! 543: } ! 544: else ! 545: break; ! 546: } ! 547: if (i > 149) ! 548: { ! 549: sc->sc_state = S_IDLE; ! 550: printf("failed to initialize, in step3: sa 0x%x", tmscpaddr->tmscpsa); ! 551: wakeup((caddr_t)um); ! 552: return; ! 553: } ! 554: /* ! 555: * Get microcode version and model number of controller; ! 556: * Signal initialization complete (_GO) (to the controller); ! 557: * ask for Last Fail response if tmscperror is set; ! 558: * Set state to "set controller characteristics". ! 559: */ ! 560: tmscpmicro[d] = tmscpaddr->tmscpsa; ! 561: tmscpaddr->tmscpsa = TMSCP_GO | (tmscperror? TMSCP_LF : 0); ! 562: sc->sc_state = S_SCHAR; ! 563: # ifdef DEBUG ! 564: printd("tmscpintr: completed state %d \n", sc->sc_state); ! 565: printd("tmscp%d Version %d model %d\n",d,tmscpmicro[d]&0xF, ! 566: (tmscpmicro[d]>>4) & 0xF); ! 567: # endif ! 568: ! 569: /* ! 570: * Initialize the data structures (response and command queues). ! 571: */ ! 572: ttm = sc->sc_tmscp; ! 573: for (i = 0; i < NRSP; i++) ! 574: { ! 575: tm->tmscp_ca.ca_rspdsc[i] = TMSCP_OWN | TMSCP_INT | ! 576: (long)&ttm->tmscp_rsp[i].mscp_cmdref; ! 577: tm->tmscp_rsp[i].mscp_dscptr = &tm->tmscp_ca.ca_rspdsc[i]; ! 578: tm->tmscp_rsp[i].mscp_header.tmscp_msglen = mscp_msglen; ! 579: } ! 580: for (i = 0; i < NCMD; i++) ! 581: { ! 582: tm->tmscp_ca.ca_cmddsc[i] = TMSCP_INT | ! 583: (long)&ttm->tmscp_cmd[i].mscp_cmdref; ! 584: tm->tmscp_cmd[i].mscp_dscptr = &tm->tmscp_ca.ca_cmddsc[i]; ! 585: tm->tmscp_cmd[i].mscp_header.tmscp_msglen = mscp_msglen; ! 586: tm->tmscp_cmd[i].mscp_header.tmscp_vcid = 1; ! 587: } ! 588: bp = &tmscpwtab[d]; ! 589: bp->av_forw = bp->av_back = bp; ! 590: sc->sc_lastcmd = 1; ! 591: sc->sc_lastrsp = 0; ! 592: mp = &tmscp[um->um_ctlr].tmscp_cmd[0]; ! 593: mp->mscp_unit = mp->mscp_modifier = 0; ! 594: mp->mscp_flags = 0; ! 595: mp->mscp_version = 0; ! 596: mp->mscp_cntflgs = M_CF_ATTN|M_CF_MISC|M_CF_THIS; ! 597: /* ! 598: * A host time out value of 0 means that the controller will not ! 599: * time out. This is ok for the TK50. ! 600: */ ! 601: mp->mscp_hsttmo = 0; ! 602: mp->mscp_time.val[0] = 0; ! 603: mp->mscp_time.val[1] = 0; ! 604: mp->mscp_cntdep = 0; ! 605: mp->mscp_opcode = M_OP_STCON; ! 606: *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; ! 607: i = tmscpaddr->tmscpip; /* initiate polling */ ! 608: return; ! 609: ! 610: case S_SCHAR: ! 611: case S_RUN: ! 612: break; ! 613: ! 614: default: ! 615: printf("tmscp%d: interrupt in unknown state %d ignored\n",d,sc->sc_state); ! 616: return; ! 617: } /* end switch */ ! 618: ! 619: /* ! 620: * The controller state is S_SCHAR or S_RUN ! 621: */ ! 622: ! 623: /* ! 624: * If the error bit is set in the SA register then print an error ! 625: * message and reinitialize the controller. ! 626: */ ! 627: if (tmscpaddr->tmscpsa&TMSCP_ERR) ! 628: { ! 629: printf("tmscp%d: fatal error (%o)\n", d, tmscpaddr->tmscpsa&0xffff); ! 630: tmscpaddr->tmscpip = 0; ! 631: wakeup((caddr_t)um); ! 632: } ! 633: /* ! 634: * Check for a buffer purge request. (Won't happen w/ TK50 on Q22 bus) ! 635: */ ! 636: if (tm->tmscp_ca.ca_bdp) ! 637: { ! 638: UBAPURGE(um->um_hd->uh_uba, tm->tmscp_ca.ca_bdp); ! 639: tm->tmscp_ca.ca_bdp = 0; ! 640: tmscpaddr->tmscpsa = 0; /* signal purge complete */ ! 641: } ! 642: ! 643: /* ! 644: * Check for response ring transition. ! 645: */ ! 646: if (tm->tmscp_ca.ca_rspint) ! 647: { ! 648: tm->tmscp_ca.ca_rspint = 0; ! 649: for (i = sc->sc_lastrsp;; i++) ! 650: { ! 651: i %= NRSP; ! 652: if (tm->tmscp_ca.ca_rspdsc[i]&TMSCP_OWN) ! 653: break; ! 654: tmscprsp(um, tm, sc, i); ! 655: tm->tmscp_ca.ca_rspdsc[i] |= TMSCP_OWN; ! 656: } ! 657: sc->sc_lastrsp = i; ! 658: } ! 659: ! 660: /* ! 661: * Check for command ring transition. ! 662: */ ! 663: if (tm->tmscp_ca.ca_cmdint) ! 664: { ! 665: # ifdef DEBUG ! 666: printd("tmscpintr: command ring transition\n"); ! 667: # endif ! 668: tm->tmscp_ca.ca_cmdint = 0; ! 669: } ! 670: if(tmscp_cp_wait) ! 671: wakeup((caddr_t)&tmscp_cp_wait); ! 672: (void) tmscpstart(um); ! 673: } ! 674: ! 675: ! 676: /* ! 677: * Open a tmscp device and set the unit online. If the controller is not ! 678: * in the run state, call init to initialize the tmscp controller first. ! 679: */ ! 680: ! 681: /* ARGSUSED */ ! 682: tmscpopen(dev, flag) ! 683: dev_t dev; ! 684: int flag; ! 685: { ! 686: register int unit; ! 687: register struct uba_device *ui; ! 688: register struct tmscp_softc *sc; ! 689: register struct tms_info *tms; ! 690: register struct mscp *mp; ! 691: register struct uba_ctlr *um; ! 692: struct tmscpdevice *tmscpaddr; ! 693: int s,i; ! 694: ! 695: unit = TMSUNIT(dev); ! 696: # ifdef DEBUG ! 697: printd("tmscpopen unit %d\n",unit); ! 698: if(tmscpdebug)DELAY(10000); ! 699: # endif ! 700: if (unit >= NTMS || (ui = tmsdinfo[unit]) == 0 || ui->ui_alive == 0) ! 701: return (ENXIO); ! 702: tms = &tms_info[ui->ui_unit]; ! 703: if (tms->tms_openf) ! 704: return (EBUSY); ! 705: sc = &tmscp_softc[ui->ui_ctlr]; ! 706: tms->tms_openf = 1; ! 707: tms->tms_tpr = tprintf_open(); ! 708: s = spl5(); ! 709: if (sc->sc_state != S_RUN) ! 710: { ! 711: if (sc->sc_state == S_IDLE) ! 712: if(!tmscpinit(ui->ui_ctlr)) ! 713: { ! 714: printf("tmscp controller failed to init\n"); ! 715: (void) splx(s); ! 716: tms->tms_openf = 0; ! 717: return(ENXIO); ! 718: } ! 719: /* ! 720: * Wait for initialization to complete ! 721: */ ! 722: timeout(wakeup,(caddr_t)ui->ui_mi,11*hz); /* to be sure*/ ! 723: sleep((caddr_t)ui->ui_mi, 0); ! 724: if (sc->sc_state != S_RUN) ! 725: { ! 726: (void) splx(s); ! 727: tms->tms_openf = 0; ! 728: return (EIO); ! 729: } ! 730: } ! 731: /* ! 732: * Check to see if the device is really there. ! 733: * this code was taken from Fred Canters 11 driver ! 734: */ ! 735: um = ui->ui_mi; ! 736: tmscpaddr = (struct tmscpdevice *) um->um_addr; ! 737: (void) splx(s); ! 738: if(ui->ui_flags == 0) ! 739: { ! 740: s = spl5(); ! 741: while(0 ==(mp = tmscpgetcp(um))) ! 742: { ! 743: tmscp_cp_wait++; ! 744: sleep((caddr_t)&tmscp_cp_wait,PSWP+1); ! 745: tmscp_cp_wait--; ! 746: } ! 747: (void) splx(s); ! 748: mp->mscp_opcode = M_OP_ONLIN; ! 749: mp->mscp_unit = ui->ui_slave; ! 750: mp->mscp_cmdref = (long) & tms->tms_type; ! 751: /* need to sleep on something */ ! 752: # ifdef DEBUG ! 753: printd("tmscpopen: bring unit %d online\n",ui->ui_unit); ! 754: # endif ! 755: *((long *) mp->mscp_dscptr ) |= TMSCP_OWN | TMSCP_INT; ! 756: i = tmscpaddr->tmscpip; ! 757: #ifdef lint ! 758: i = i; ! 759: #endif ! 760: /* ! 761: * To make sure we wake up, timeout in 240 seconds. ! 762: * Wakeup in tmscprsp routine. ! 763: * 240 seconds (4 minutes) is necessary since a rewind ! 764: * can take a few minutes. ! 765: */ ! 766: timeout(wakeup,(caddr_t) mp->mscp_cmdref,240 * hz); ! 767: sleep((caddr_t) mp->mscp_cmdref,PSWP+1); ! 768: } ! 769: if(ui->ui_flags == 0) { ! 770: tms->tms_openf = 0; ! 771: return(ENXIO); /* Didn't go online */ ! 772: } ! 773: tms->tms_lastiow = 0; ! 774: /* ! 775: * If the high density device is not specified, set unit to low ! 776: * density. This is done as an "internal" ioctl command so ! 777: * that the command setup and response handling ! 778: * is done thru "regular" command routines. ! 779: */ ! 780: if ((minor(dev) & T_HIDENSITY) == 0) ! 781: tmscpcommand(dev, TMS_LOWDENSITY, 1); ! 782: else ! 783: tmscpcommand(dev, TMS_HIDENSITY, 1); ! 784: return (0); ! 785: } ! 786: ! 787: ! 788: /* ! 789: * Close tape device. ! 790: * ! 791: * If tape was open for writing or last operation was ! 792: * a write, then write two EOF's and backspace over the last one. ! 793: * Unless this is a non-rewinding special file, rewind the tape. ! 794: * ! 795: * NOTE: ! 796: * We want to be sure that any serious exception is cleared on the ! 797: * close. A Clear Serious Exception (CSE) modifier is always done on ! 798: * the rewind command. For the non-rewind case we check to see if the ! 799: * "serex" field is set in the softc struct; if it is then issue a noop ! 800: * command with the CSE modifier. ! 801: * Make the tape available to others, by clearing openf flag. ! 802: */ ! 803: tmscpclose(dev, flag) ! 804: register dev_t dev; ! 805: register flag; ! 806: { ! 807: register struct tms_info *tms; ! 808: register struct uba_device *ui; ! 809: ! 810: ui = tmsdinfo[TMSUNIT(dev)]; ! 811: # ifdef DEBUG ! 812: printd("tmscpclose: ctlr = %d\n",TMSCPCTLR(dev)); ! 813: printd("tmscpclose: unit = %d\n",TMSUNIT(dev)); ! 814: if(tmscpdebug)DELAY(10000); ! 815: # endif ! 816: tms = &tms_info[ui->ui_unit]; ! 817: if (flag == FWRITE || (flag&FWRITE) && tms->tms_lastiow) ! 818: { ! 819: /* device, command, count */ ! 820: tmscpcommand (dev, TMS_WRITM, 1); ! 821: tmscpcommand (dev, TMS_WRITM, 1); ! 822: tmscpcommand (dev, TMS_BSR, 1); ! 823: } ! 824: if ((minor(dev)&T_NOREWIND) == 0) ! 825: /* ! 826: * Don't hang waiting for rewind complete. ! 827: */ ! 828: tmscpcommand(dev, TMS_REW, 0); ! 829: else ! 830: if (tms->tms_serex) ! 831: { ! 832: # ifdef DEBUG ! 833: printd("tmscpclose: clearing serex\n"); ! 834: if(tmscpdebug)DELAY(10000); ! 835: # endif ! 836: tmscpcommand(dev, TMS_CSE, 1); ! 837: } ! 838: tprintf_close(tms->tms_tpr); ! 839: tms->tms_openf = 0; ! 840: return (0); ! 841: } ! 842: ! 843: ! 844: /* ! 845: * Execute a command on the tape drive a specified number of times. ! 846: * This routine sets up a buffer and calls the strategy routine which ! 847: * links the buffer onto the drive's buffer queue. ! 848: * The start routine will take care of creating a tmscp command packet ! 849: * with the command. The start routine is called by the strategy or the ! 850: * interrupt routine. ! 851: */ ! 852: ! 853: tmscpcommand (dev, com, count) ! 854: register dev_t dev; ! 855: int com, count; ! 856: { ! 857: register struct uba_device *ui; ! 858: register struct buf *bp; ! 859: register int s; ! 860: int unit = TMSUNIT(dev); ! 861: ! 862: ui = tmsdinfo[unit]; ! 863: bp = &ctmscpbuf[ui->ui_ctlr]; ! 864: ! 865: s = spl5(); ! 866: while (bp->b_flags&B_BUSY) ! 867: { ! 868: /* ! 869: * This special check is because B_BUSY never ! 870: * gets cleared in the non-waiting rewind case. ! 871: */ ! 872: if (bp->b_bcount == 0 && (bp->b_flags&B_DONE)) ! 873: break; ! 874: bp->b_flags |= B_WANTED; ! 875: sleep((caddr_t)bp, PRIBIO); ! 876: } ! 877: bp->b_flags = B_BUSY|B_READ; ! 878: splx(s); ! 879: /* ! 880: * Load the buffer. The b_count field gets used to hold the command ! 881: * count. the b_resid field gets used to hold the command mneumonic. ! 882: * These 2 fields are "known" to be "safe" to use for this purpose. ! 883: * (Most other drivers also use these fields in this way.) ! 884: */ ! 885: bp->b_dev = dev; ! 886: bp->b_bcount = count; ! 887: bp->b_resid = com; ! 888: bp->b_blkno = 0; ! 889: tmscpstrategy(bp); ! 890: /* ! 891: * In case of rewind from close, don't wait. ! 892: * This is the only case where count can be 0. ! 893: */ ! 894: if (count == 0) ! 895: return; ! 896: iowait(bp); ! 897: if (bp->b_flags&B_WANTED) ! 898: wakeup((caddr_t)bp); ! 899: bp->b_flags &= B_ERROR; ! 900: } ! 901: ! 902: /* ! 903: * Find an unused command packet ! 904: */ ! 905: struct mscp * ! 906: tmscpgetcp(um) ! 907: struct uba_ctlr *um; ! 908: { ! 909: register struct mscp *mp; ! 910: register struct tmscpca *cp; ! 911: register struct tmscp_softc *sc; ! 912: register int i; ! 913: int s; ! 914: ! 915: s = spl5(); ! 916: cp = &tmscp[um->um_ctlr].tmscp_ca; ! 917: sc = &tmscp_softc[um->um_ctlr]; ! 918: /* ! 919: * If no credits, can't issue any commands ! 920: * until some outstanding commands complete. ! 921: */ ! 922: i = sc->sc_lastcmd; ! 923: # ifdef DEBUG ! 924: printd10("tmscpgetcp: %d credits remain\n", sc->sc_credits); ! 925: # endif ! 926: if(((cp->ca_cmddsc[i]&(TMSCP_OWN|TMSCP_INT))==TMSCP_INT) && ! 927: (sc->sc_credits >= 2)) ! 928: { ! 929: sc->sc_credits--; /* This commits to issuing a command */ ! 930: cp->ca_cmddsc[i] &= ~TMSCP_INT; ! 931: mp = &tmscp[um->um_ctlr].tmscp_cmd[i]; ! 932: mp->mscp_unit = mp->mscp_modifier = 0; ! 933: mp->mscp_opcode = mp->mscp_flags = 0; ! 934: mp->mscp_bytecnt = mp->mscp_buffer = 0; ! 935: sc->sc_lastcmd = (i + 1) % NCMD; ! 936: (void) splx(s); ! 937: return(mp); ! 938: } ! 939: (void) splx(s); ! 940: return(NULL); ! 941: } ! 942: ! 943: ! 944: /* ! 945: * Initialize a TMSCP device. Set up UBA mapping registers, ! 946: * initialize data structures, and start hardware ! 947: * initialization sequence. ! 948: */ ! 949: tmscpinit (d) ! 950: int d; /* index to the controller */ ! 951: { ! 952: register struct tmscp_softc *sc; ! 953: register struct tmscp *t; /* communications area; cmd & resp packets */ ! 954: struct tmscpdevice *tmscpaddr; ! 955: struct uba_ctlr *um; ! 956: ! 957: sc = &tmscp_softc[d]; ! 958: um = tmscpminfo[d]; ! 959: um->um_tab.b_active++; ! 960: t = &tmscp[d]; ! 961: tmscpaddr = (struct tmscpdevice *)um->um_addr; ! 962: if (sc->sc_mapped == 0) ! 963: { ! 964: /* ! 965: * Map the communications area and command ! 966: * and response packets into Unibus address ! 967: * space. ! 968: */ ! 969: sc->sc_ubainfo = uballoc(um->um_ubanum, (caddr_t)t, sizeof (struct tmscp), 0); ! 970: sc->sc_tmscp = (struct tmscp *)(UBAI_ADDR(sc->sc_ubainfo)); ! 971: sc->sc_mapped = 1; ! 972: } ! 973: ! 974: /* ! 975: * Start the hardware initialization sequence. ! 976: */ ! 977: tmscpaddr->tmscpip = 0; /* start initialization */ ! 978: ! 979: while((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0) ! 980: { ! 981: # ifdef DEBUG ! 982: printd("tmscpinit: tmscpsa = 0%o\n",tmscpaddr->tmscpsa); ! 983: DELAY(100000); ! 984: # endif ! 985: if(tmscpaddr->tmscpsa & TMSCP_ERR) ! 986: return(0); /* CHECK */ ! 987: } ! 988: tmscpaddr->tmscpsa=TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8)|TMSCP_IE|(sc->sc_ivec/4); ! 989: /* ! 990: * Initialization continues in the interrupt routine. ! 991: */ ! 992: sc->sc_state = S_STEP1; ! 993: sc->sc_credits = 0; ! 994: return(1); ! 995: } ! 996: ! 997: ! 998: /* ! 999: * Start I/O operation ! 1000: * This code is convoluted. The majority of it was copied from the uda driver. ! 1001: */ ! 1002: ! 1003: tmscpstart(um) ! 1004: register struct uba_ctlr *um; ! 1005: { ! 1006: register struct buf *bp, *dp; ! 1007: register struct mscp *mp; ! 1008: register struct tmscp_softc *sc; ! 1009: register struct tms_info *tms; ! 1010: register struct uba_device *ui; ! 1011: struct tmscpdevice *tmscpaddr; ! 1012: struct tmscp *tm = &tmscp[um->um_ctlr]; ! 1013: int i,tempi; ! 1014: char ioctl; /* flag: set true if its an IOCTL command */ ! 1015: ! 1016: sc = &tmscp_softc[um->um_ctlr]; ! 1017: ! 1018: for(;;) ! 1019: { ! 1020: if ((dp = um->um_tab.b_actf) == NULL) ! 1021: { ! 1022: /* ! 1023: * Release unneeded UBA resources and return ! 1024: * (drive was inactive) ! 1025: */ ! 1026: um->um_tab.b_active = 0; ! 1027: break; ! 1028: } ! 1029: if ((bp = dp->b_actf) == NULL) ! 1030: { ! 1031: /* ! 1032: * No more requests for this drive, remove ! 1033: * from controller queue and look at next drive. ! 1034: * We know we're at the head of the controller queue. ! 1035: */ ! 1036: dp->b_active = 0; ! 1037: um->um_tab.b_actf = dp->b_forw; ! 1038: continue; /* Need to check for loop */ ! 1039: } ! 1040: um->um_tab.b_active++; ! 1041: tmscpaddr = (struct tmscpdevice *)um->um_addr; ! 1042: ui = tmsdinfo[(TMSUNIT(bp->b_dev))]; ! 1043: tms = &tms_info[ui->ui_unit]; ! 1044: if ((tmscpaddr->tmscpsa&TMSCP_ERR) || sc->sc_state != S_RUN) ! 1045: { ! 1046: tprintf(tms->tms_tpr, ! 1047: "tms%d: hard error bn%d\n", ! 1048: minor(bp->b_dev)&03, bp->b_blkno); ! 1049: log(TMS_PRI, "tmscp%d: sa 0%o, state %d\n",um->um_ctlr, ! 1050: tmscpaddr->tmscpsa&0xffff, sc->sc_state); ! 1051: (void)tmscpinit(um->um_ctlr); ! 1052: /* SHOULD REQUEUE OUTSTANDING REQUESTS, LIKE TMSCPRESET */ ! 1053: break; ! 1054: } ! 1055: /* ! 1056: * Default is that last command was NOT a write command; ! 1057: * if a write command is done it will be detected in tmscprsp. ! 1058: */ ! 1059: tms->tms_lastiow = 0; ! 1060: if (ui->ui_flags == 0) ! 1061: { /* not online */ ! 1062: if ((mp = tmscpgetcp(um)) == NULL) ! 1063: break; ! 1064: mp->mscp_opcode = M_OP_ONLIN; ! 1065: mp->mscp_unit = ui->ui_slave; ! 1066: dp->b_active = 2; ! 1067: um->um_tab.b_actf = dp->b_forw; /* remove from controller q */ ! 1068: *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; ! 1069: if (tmscpaddr->tmscpsa&TMSCP_ERR) ! 1070: printf("tmscp%d fatal error (0%o)\n",um->um_ctlr, ! 1071: tmscpaddr->tmscpsa&0xffff); ! 1072: i = tmscpaddr->tmscpip; ! 1073: continue; ! 1074: } ! 1075: switch (cpu) { ! 1076: ! 1077: case VAX_8600: ! 1078: case VAX_780: ! 1079: i = UBA_NEEDBDP|UBA_CANTWAIT; ! 1080: break; ! 1081: case VAX_750: ! 1082: i = um->um_ubinfo|UBA_HAVEBDP|UBA_CANTWAIT; ! 1083: break; ! 1084: case VAX_730: ! 1085: case VAX_630: ! 1086: i = UBA_CANTWAIT; ! 1087: break; ! 1088: } /* end switch (cpu) */ ! 1089: /* ! 1090: * If command is an ioctl command then set the ioctl flag for later use. ! 1091: * If not (i.e. it is a read or write) then attempt ! 1092: * to set up a buffer pointer. ! 1093: */ ! 1094: ioctl = 0; ! 1095: if (bp == &ctmscpbuf[um->um_ctlr]) ! 1096: ioctl = 1; ! 1097: else ! 1098: if ((i = ubasetup(um->um_ubanum, bp, i)) == 0) ! 1099: { ! 1100: if(dp->b_qsize != 0) ! 1101: break; /* When a command completes and */ ! 1102: /* frees a bdp tmscpstart will be called */ ! 1103: if ((mp = tmscpgetcp(um)) == NULL) ! 1104: break; ! 1105: # ifdef DEBUG ! 1106: printd("tmscpstart: GTUNT %d ubasetup = %d\n",ui->ui_unit, i); ! 1107: if(tmscpdebug)DELAY(10000); ! 1108: # endif ! 1109: mp->mscp_opcode = M_OP_GTUNT; ! 1110: mp->mscp_unit = ui->ui_slave; ! 1111: *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; ! 1112: if (tmscpaddr->tmscpsa&TMSCP_ERR) ! 1113: printf("tmscp%d: fatal error (0%o)\n",um->um_ctlr, ! 1114: tmscpaddr->tmscpsa&0xffff); ! 1115: i = tmscpaddr->tmscpip; /* initiate polling */ ! 1116: break; ! 1117: } ! 1118: # if defined(VAX750) ! 1119: if (cpu == VAX_750) ! 1120: tempi = i & 0xfffffff; /* mask off bdp */ ! 1121: else ! 1122: # endif ! 1123: tempi = i; ! 1124: if ((mp = tmscpgetcp(um)) == NULL) ! 1125: { ! 1126: if (!ioctl) /* only need to release if NOT ioctl */ ! 1127: ubarelse(um->um_ubanum,&tempi); ! 1128: break; ! 1129: } ! 1130: mp->mscp_cmdref = (long)bp; /* pointer to get back */ ! 1131: mp->mscp_unit = ui->ui_slave; ! 1132: /* ! 1133: * If its an ioctl-type command then set up the appropriate ! 1134: * tmscp command; by doing a switch on the "b_resid" field where ! 1135: * the command mneumonic is stored. ! 1136: */ ! 1137: if (ioctl) ! 1138: { ! 1139: # ifdef DEBUG ! 1140: printd("tmscpstart: doing ioctl cmd %d\n", bp->b_resid); ! 1141: # endif ! 1142: /* ! 1143: * The reccnt and tmkcnt fields are set to zero by the getcp ! 1144: * routine (as bytecnt and buffer fields). Thus reccnt and ! 1145: * tmkcnt are only modified here if they need to be set to ! 1146: * a non-zero value. ! 1147: */ ! 1148: switch ((int)bp->b_resid) { ! 1149: ! 1150: case TMS_WRITM: ! 1151: mp->mscp_opcode = M_OP_WRITM; ! 1152: break; ! 1153: case TMS_FSF: ! 1154: mp->mscp_opcode = M_OP_REPOS; ! 1155: mp->mscp_tmkcnt = bp->b_bcount; ! 1156: break; ! 1157: case TMS_BSF: ! 1158: mp->mscp_opcode = M_OP_REPOS; ! 1159: mp->mscp_modifier = M_MD_REVRS; ! 1160: mp->mscp_tmkcnt = bp->b_bcount; ! 1161: break; ! 1162: case TMS_FSR: ! 1163: mp->mscp_opcode = M_OP_REPOS; ! 1164: mp->mscp_modifier = M_MD_OBJCT; ! 1165: mp->mscp_reccnt = bp->b_bcount; ! 1166: break; ! 1167: case TMS_BSR: ! 1168: mp->mscp_opcode = M_OP_REPOS; ! 1169: mp->mscp_modifier = M_MD_REVRS | M_MD_OBJCT; ! 1170: mp->mscp_reccnt = bp->b_bcount; ! 1171: break; ! 1172: /* ! 1173: * Clear serious exception is done for Rewind & Available cmds ! 1174: */ ! 1175: case TMS_REW: ! 1176: mp->mscp_opcode = M_OP_REPOS; ! 1177: mp->mscp_modifier = M_MD_REWND | M_MD_CLSEX; ! 1178: if (bp->b_bcount == 0) ! 1179: mp->mscp_modifier |= M_MD_IMMED; ! 1180: tms->tms_serex = 0; ! 1181: break; ! 1182: case TMS_OFFL: ! 1183: mp->mscp_opcode = M_OP_AVAIL; ! 1184: mp->mscp_modifier = M_MD_UNLOD | M_MD_CLSEX; ! 1185: tms->tms_serex = 0; ! 1186: break; ! 1187: case TMS_SENSE: ! 1188: mp->mscp_opcode = M_OP_GTUNT; ! 1189: break; ! 1190: case TMS_CACHE: ! 1191: mp->mscp_opcode = M_OP_STUNT; ! 1192: tms->tms_unitflgs |= M_UF_WBKNV; ! 1193: mp->mscp_unitflgs = tms->tms_unitflgs; ! 1194: mp->mscp_format = tms->tms_format; ! 1195: /* default device dependant parameters */ ! 1196: mp->mscp_mediaid = 0; ! 1197: break; ! 1198: case TMS_NOCACHE: ! 1199: mp->mscp_opcode = M_OP_STUNT; ! 1200: tms->tms_unitflgs &= ~(M_UF_WBKNV); ! 1201: mp->mscp_unitflgs = tms->tms_unitflgs; ! 1202: mp->mscp_format = tms->tms_format; ! 1203: /* default device dependant parameters */ ! 1204: mp->mscp_mediaid = 0; ! 1205: break; ! 1206: case TMS_CSE: ! 1207: /* ! 1208: * This is a no-op command. It performs a ! 1209: * clear serious exception only. (Done on a ! 1210: * non-rewinding close after a serious exception.) ! 1211: */ ! 1212: mp->mscp_opcode = M_OP_REPOS; ! 1213: mp->mscp_modifier = M_MD_CLSEX; ! 1214: tms->tms_serex = 0; ! 1215: tms->tms_clserex = 1; ! 1216: break; ! 1217: case TMS_LOWDENSITY: ! 1218: /* ! 1219: * Set the unit to low density ! 1220: */ ! 1221: mp->mscp_opcode = M_OP_STUNT; ! 1222: mp->mscp_unitflgs = tms->tms_unitflgs; ! 1223: mp->mscp_mediaid = 0; /* default device dependant parameters */ ! 1224: if ((tms->tms_fmtmenu & M_TF_800) != 0) ! 1225: mp->mscp_format = M_TF_800; ! 1226: else ! 1227: mp->mscp_format = M_TF_PE & tms->tms_fmtmenu; ! 1228: tms->tms_format = mp->mscp_format; ! 1229: break; ! 1230: case TMS_HIDENSITY: ! 1231: /* ! 1232: * Set the unit to high density (format == 0) ! 1233: */ ! 1234: mp->mscp_opcode = M_OP_STUNT; ! 1235: mp->mscp_unitflgs = tms->tms_unitflgs; ! 1236: mp->mscp_mediaid = 0; /* default device dependant parameters */ ! 1237: mp->mscp_format = 0; ! 1238: tms->tms_format = 0; ! 1239: break; ! 1240: default: ! 1241: printf("Bad ioctl on tms unit %d\n", ui->ui_unit); ! 1242: /* Need a no-op. Reposition no amount */ ! 1243: mp->mscp_opcode = M_OP_REPOS; ! 1244: break; ! 1245: } /* end switch (bp->b_resid) */ ! 1246: } ! 1247: else /* Its a read/write command (not an ioctl) */ ! 1248: { ! 1249: mp->mscp_opcode = bp->b_flags&B_READ ? M_OP_READ : M_OP_WRITE; ! 1250: mp->mscp_bytecnt = bp->b_bcount; ! 1251: mp->mscp_buffer = UBAI_ADDR(i) | (UBAI_BDP(i) << 24); ! 1252: ! 1253: bp->b_ubinfo = tempi; /* save mapping info */ ! 1254: } ! 1255: if (tms->tms_serex == 2) /* if tape mark read */ ! 1256: { ! 1257: mp->mscp_modifier |= M_MD_CLSEX; /* clear serious exc */ ! 1258: tms->tms_serex = 0; ! 1259: } ! 1260: *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; ! 1261: # ifdef DEBUG ! 1262: printd("tmscpstart: opcode 0%o mod %o unit %d cnt %d\n",mp->mscp_opcode,mp->mscp_modifier,mp->mscp_unit,mp->mscp_bytecnt); ! 1263: if(tmscpdebug)DELAY(100000); ! 1264: # endif ! 1265: i = tmscpaddr->tmscpip; /* initiate polling */ ! 1266: dp->b_qsize++; ! 1267: /* ! 1268: * Move drive to the end of the controller queue ! 1269: */ ! 1270: if (dp->b_forw != NULL) ! 1271: { ! 1272: um->um_tab.b_actf = dp->b_forw; ! 1273: um->um_tab.b_actl->b_forw = dp; ! 1274: um->um_tab.b_actl = dp; ! 1275: dp->b_forw = NULL; ! 1276: } ! 1277: /* ! 1278: * Move buffer to I/O wait queue ! 1279: */ ! 1280: dp->b_actf = bp->av_forw; ! 1281: dp = &tmscpwtab[um->um_ctlr]; ! 1282: bp->av_forw = dp; ! 1283: bp->av_back = dp->av_back; ! 1284: dp->av_back->av_forw = bp; ! 1285: dp->av_back = bp; ! 1286: if (tmscpaddr->tmscpsa&TMSCP_ERR) ! 1287: { ! 1288: printf("tmscp%d: fatal error (0%o)\n", um->um_ctlr, tmscpaddr->tmscpsa&0xffff); ! 1289: (void)tmscpinit(um->um_ctlr); ! 1290: break; ! 1291: } ! 1292: } /* end for */ ! 1293: /* ! 1294: * Check for response ring transitions lost in the ! 1295: * Race condition ! 1296: */ ! 1297: for (i = sc->sc_lastrsp;; i++) ! 1298: { ! 1299: i %= NRSP; ! 1300: if (tm->tmscp_ca.ca_rspdsc[i]&TMSCP_OWN) ! 1301: break; ! 1302: tmscprsp(um, tm, sc, i); ! 1303: tm->tmscp_ca.ca_rspdsc[i] |= TMSCP_OWN; ! 1304: } ! 1305: sc->sc_lastrsp = i; ! 1306: } ! 1307: ! 1308: ! 1309: /* ! 1310: * Process a response packet ! 1311: */ ! 1312: tmscprsp(um, tm, sc, i) ! 1313: register struct uba_ctlr *um; ! 1314: register struct tmscp *tm; ! 1315: register struct tmscp_softc *sc; ! 1316: int i; ! 1317: { ! 1318: register struct mscp *mp; ! 1319: register struct tms_info *tms; ! 1320: struct uba_device *ui; ! 1321: struct buf *dp, *bp; ! 1322: int st; ! 1323: ! 1324: mp = &tm->tmscp_rsp[i]; ! 1325: mp->mscp_header.tmscp_msglen = mscp_msglen; ! 1326: sc->sc_credits += mp->mscp_header.tmscp_credits & 0xf; /* low 4 bits */ ! 1327: if ((mp->mscp_header.tmscp_credits & 0xf0) > 0x10) /* Check */ ! 1328: return; ! 1329: # ifdef DEBUG ! 1330: printd("tmscprsp, opcode 0%o status 0%o\n",mp->mscp_opcode,mp->mscp_status&M_ST_MASK); ! 1331: # endif ! 1332: /* ! 1333: * If it's an error log message (datagram), ! 1334: * pass it on for more extensive processing. ! 1335: */ ! 1336: if ((mp->mscp_header.tmscp_credits & 0xf0) == 0x10) ! 1337: { /* check */ ! 1338: tmserror(um, (struct mslg *)mp); ! 1339: return; ! 1340: } ! 1341: st = mp->mscp_status&M_ST_MASK; ! 1342: /* ! 1343: * The controller interrupts as drive 0. ! 1344: * This means that you must check for controller interrupts ! 1345: * before you check to see if there is a drive 0. ! 1346: */ ! 1347: if((M_OP_STCON|M_OP_END) == mp->mscp_opcode) ! 1348: { ! 1349: if (st == M_ST_SUCC) ! 1350: { ! 1351: # ifdef DEBUG ! 1352: printd("ctlr has %d credits\n", mp->mscp_header.tmscp_credits & 0xf); ! 1353: printd("ctlr timeout = %d\n", mp->mscp_cnttmo); ! 1354: # endif ! 1355: sc->sc_state = S_RUN; ! 1356: } ! 1357: else ! 1358: sc->sc_state = S_IDLE; ! 1359: um->um_tab.b_active = 0; ! 1360: wakeup((caddr_t)um); ! 1361: return; ! 1362: } ! 1363: if (mp->mscp_unit >= NTMS) ! 1364: return; ! 1365: if ((ui = tmscpip[um->um_ctlr][mp->mscp_unit]) == 0) ! 1366: return; ! 1367: tms = &tms_info[ui->ui_unit]; ! 1368: /* ! 1369: * Save endcode, endflags, and status for mtioctl get unit status. ! 1370: * NOTE: Don't do this on Clear serious exception (reposition no-op); ! 1371: * which is done on close since this would ! 1372: * overwrite the real status we want. ! 1373: */ ! 1374: if (tms->tms_clserex != 1) ! 1375: { ! 1376: tms->tms_endcode = mp->mscp_opcode; ! 1377: tms->tms_flags = mp->mscp_flags; ! 1378: tms->tms_status = st; ! 1379: } ! 1380: else tms->tms_clserex = 0; ! 1381: ! 1382: switch (mp->mscp_opcode) { ! 1383: case M_OP_ONLIN|M_OP_END: ! 1384: tms->tms_type = mp->mscp_mediaid; ! 1385: dp = &tmsutab[ui->ui_unit]; ! 1386: if (st == M_ST_SUCC) ! 1387: { ! 1388: /* ! 1389: * Link the drive onto the controller queue ! 1390: */ ! 1391: dp->b_forw = NULL; ! 1392: if (um->um_tab.b_actf == NULL) ! 1393: um->um_tab.b_actf = dp; ! 1394: else ! 1395: um->um_tab.b_actl->b_forw = dp; ! 1396: um->um_tab.b_actl = dp; ! 1397: ui->ui_flags = 1; /* mark it online */ ! 1398: tms->tms_dsize=(daddr_t)mp->mscp_maxwrt; ! 1399: # ifdef DEBUG ! 1400: printd("tmscprsp: unit %d online\n", mp->mscp_unit); ! 1401: # endif ! 1402: /* ! 1403: * This define decodes the Media type identifier ! 1404: */ ! 1405: # define F_to_C(x,i) ( ((x)->mscp_mediaid) >> (i*5+7) & 0x1f ? ( ( (((x)->mscp_mediaid) >>( i*5 + 7)) & 0x1f) + 'A' - 1): ' ') ! 1406: # ifdef DEBUG ! 1407: printd("tmscprsp: unit %d online %x %c%c %c%c%c%d\n" ! 1408: ,mp->mscp_unit, mp->mscp_mediaid ,F_to_C(mp,4) ! 1409: ,F_to_C(mp,3), F_to_C(mp,2) ! 1410: ,F_to_C(mp,1), F_to_C(mp,0), mp->mscp_mediaid & 0x7f); ! 1411: # endif ! 1412: dp->b_active = 1; ! 1413: } /* end if st == M_ST_SUCC */ ! 1414: else ! 1415: { ! 1416: if (bp = dp->b_actf) ! 1417: tprintf(tms->tms_tpr, ! 1418: "tms%d: hard error bn%d: OFFLINE\n", ! 1419: minor(bp->b_dev)&03, bp->b_blkno); ! 1420: else ! 1421: tprintf(tms->tms_tpr, ! 1422: "tms%d: hard error: OFFLINE\n", ! 1423: ui->ui_unit); ! 1424: while (bp = dp->b_actf) ! 1425: { ! 1426: dp->b_actf = bp->av_forw; ! 1427: bp->b_flags |= B_ERROR; ! 1428: iodone(bp); ! 1429: } ! 1430: } ! 1431: if(mp->mscp_cmdref!=NULL) ! 1432: /* Seems to get lost sometimes in uda */ ! 1433: wakeup((caddr_t)mp->mscp_cmdref); ! 1434: break; ! 1435: /* ! 1436: * The AVAILABLE ATTENTION message occurs when the ! 1437: * unit becomes available after loading, ! 1438: * marking the unit offline (ui_flags = 0) will force an ! 1439: * online command prior to using the unit. ! 1440: */ ! 1441: case M_OP_AVATN: ! 1442: ui->ui_flags = 0; ! 1443: tms->tms_type = mp->mscp_mediaid; ! 1444: break; ! 1445: case M_OP_END: ! 1446: /* ! 1447: * An endcode without an opcode (0200) is an invalid command. ! 1448: * The mscp specification states that this would be a protocol ! 1449: * type error, such as illegal opcodes. The mscp spec. also ! 1450: * states that parameter error type of invalid commands should ! 1451: * return the normal end message for the command. This does not appear ! 1452: * to be the case. An invalid logical block number returned an endcode ! 1453: * of 0200 instead of the 0241 (read) that was expected. ! 1454: */ ! 1455: ! 1456: printf("tmscp%d: invalid cmd, endcode = %o, status=%o\n", ! 1457: um->um_ctlr, mp->mscp_opcode, st); ! 1458: bp = (struct buf *)mp->mscp_cmdref; ! 1459: /* ! 1460: * Unlink buffer from I/O wait queue. ! 1461: * And signal iodone, so the higher level command can exit! ! 1462: * ! 1463: */ ! 1464: bp->av_back->av_forw = bp->av_forw; ! 1465: bp->av_forw->av_back = bp->av_back; ! 1466: dp = &tmsutab[ui->ui_unit]; ! 1467: dp->b_qsize--; ! 1468: iodone(bp); ! 1469: break; ! 1470: case M_OP_WRITE|M_OP_END: ! 1471: /* mark the last io op as a write */ ! 1472: tms->tms_lastiow = 1; ! 1473: case M_OP_READ|M_OP_END: ! 1474: case M_OP_WRITM|M_OP_END: ! 1475: case M_OP_REPOS|M_OP_END: ! 1476: case M_OP_STUNT|M_OP_END: ! 1477: /* ! 1478: * The AVAILABLE message occurs when the mt ioctl "rewoffl" is ! 1479: * issued. For the ioctl, "rewoffl", a tmscp AVAILABLE command is ! 1480: * done with the UNLOAD modifier. This performs a rewind, followed ! 1481: * by marking the unit offline. So mark the unit offline ! 1482: * software wise as well (ui_flags = 0 and ! 1483: * tms->tms_openf = 0). ! 1484: */ ! 1485: case M_OP_AVAIL|M_OP_END: ! 1486: # ifdef DEBUG ! 1487: printd("tmscprsp: position = %d\n", mp->mscp_lbn); ! 1488: # endif ! 1489: bp = (struct buf *)mp->mscp_cmdref; ! 1490: /* ! 1491: * Only need to release buffer if the command was read or write. ! 1492: * No ubasetup was done in "tmscpstart" if it was an ioctl cmd. ! 1493: */ ! 1494: if (mp->mscp_opcode == (M_OP_READ|M_OP_END) || ! 1495: mp->mscp_opcode == (M_OP_WRITE|M_OP_END)) ! 1496: ubarelse(um->um_ubanum, (int *)&bp->b_ubinfo); ! 1497: /* ! 1498: * Unlink buffer from I/O wait queue. ! 1499: */ ! 1500: bp->av_back->av_forw = bp->av_forw; ! 1501: bp->av_forw->av_back = bp->av_back; ! 1502: # if defined(VAX750) ! 1503: if (cpu == VAX_750) { ! 1504: if ((tmscpwtab[um->um_ctlr].av_forw == &tmscpwtab[um->um_ctlr]) && ! 1505: (um->um_ubinfo != 0)) { ! 1506: ubarelse(um->um_ubanum, &um->um_ubinfo); ! 1507: } ! 1508: else { ! 1509: if (mp->mscp_opcode == (M_OP_READ|M_OP_END) || ! 1510: mp->mscp_opcode == (M_OP_WRITE|M_OP_END)) ! 1511: UBAPURGE(uba_hd[um->um_ubanum].uh_uba,(um->um_ubinfo >>28) & 0x0f); ! 1512: } ! 1513: } ! 1514: # endif ! 1515: dp = &tmsutab[ui->ui_unit]; ! 1516: dp->b_qsize--; ! 1517: if (st == M_ST_OFFLN || st == M_ST_AVLBL) ! 1518: { ! 1519: ui->ui_flags = 0; /* mark unit offline */ ! 1520: tms->tms_openf = 0; ! 1521: tms->tms_type = mp->mscp_mediaid; ! 1522: /* ! 1523: * Link the buffer onto the front of the drive queue ! 1524: */ ! 1525: if ((bp->av_forw = dp->b_actf) == 0) ! 1526: dp->b_actl = bp; ! 1527: dp->b_actf = bp; ! 1528: /* ! 1529: * Link the drive onto the controller queue ! 1530: */ ! 1531: if (dp->b_active == 0) ! 1532: { ! 1533: dp->b_forw = NULL; ! 1534: if (um->um_tab.b_actf == NULL) ! 1535: um->um_tab.b_actf = dp; ! 1536: else ! 1537: um->um_tab.b_actl->b_forw = dp; ! 1538: um->um_tab.b_actl = dp; ! 1539: dp->b_active = 1; ! 1540: } ! 1541: # if defined(VAX750) ! 1542: if (cpu == VAX_750 && um->um_ubinfo == 0) ! 1543: um->um_ubinfo = uballoc(um->um_ubanum, (caddr_t)0, 0, UBA_NEEDBDP); ! 1544: # endif ! 1545: return; ! 1546: } ! 1547: if (st != M_ST_SUCC) ! 1548: { ! 1549: if (mp->mscp_flags & M_EF_SEREX) ! 1550: tms->tms_serex = 1; ! 1551: if (st != M_ST_TAPEM) ! 1552: { ! 1553: tprintf(tms->tms_tpr, ! 1554: "tms%d: hard error bn%d\n", ! 1555: minor(bp->b_dev)&03, bp->b_blkno); ! 1556: errinfo(st); /* produces more info */ ! 1557: # ifdef DEBUG ! 1558: printd("tmscprsp: error; status sub-code = 0%o, flags = 0%o\n", ! 1559: (mp->mscp_status & 177740)>>5, mp->mscp_flags); ! 1560: # endif ! 1561: bp->b_flags |= B_ERROR; ! 1562: } ! 1563: else ! 1564: /* Hit a tape mark - Set serex flag to ! 1565: * a special value so we can clear the ! 1566: * serious exception on the next command. ! 1567: */ ! 1568: tms->tms_serex = 2; ! 1569: } ! 1570: /* ! 1571: * The tmscp spec states that controllers do not have to ! 1572: * report the number of records or files skipped. So on ! 1573: * reposition commands we go strictly by cmd status. ! 1574: */ ! 1575: if (mp->mscp_opcode != (M_OP_REPOS|M_OP_END)) ! 1576: bp->b_resid = bp->b_bcount - mp->mscp_bytecnt; ! 1577: else ! 1578: bp->b_resid = 0; ! 1579: tms->tms_resid = bp->b_resid; ! 1580: iodone(bp); ! 1581: break; ! 1582: ! 1583: case M_OP_GTUNT|M_OP_END: ! 1584: # ifdef DEBUG ! 1585: printd("tmscprsp: GTUNT end packet status = 0%o\n",st); ! 1586: printd("tmscprsp: unit %d mediaid %x %c%c %c%c%c%d %x %x t=%d\n" ! 1587: ,mp->mscp_unit, mp->mscp_mediaid ! 1588: ,F_to_C(mp,4),F_to_C(mp,3),F_to_C(mp,2) ! 1589: ,F_to_C(mp,1),F_to_C(mp,0) ! 1590: ,mp->mscp_mediaid & 0x7f ! 1591: ,mp->mscp_unitid.val[0] ! 1592: ,mp->mscp_unitid.val[1] ! 1593: ,mp->mscp_format); ! 1594: # endif ! 1595: tms->tms_type = mp->mscp_mediaid; ! 1596: tms->tms_fmtmenu = mp->mscp_fmtmenu; ! 1597: tms->tms_unitflgs = mp->mscp_unitflgs; ! 1598: break; ! 1599: ! 1600: default: ! 1601: printf("tmscp unknown packet\n"); ! 1602: tmserror(um, (struct mslg *)mp); ! 1603: } /* end switch mp->mscp_opcode */ ! 1604: } ! 1605: ! 1606: ! 1607: /* ! 1608: * Give a meaningful error when the mscp_status field returns an error code. ! 1609: */ ! 1610: ! 1611: errinfo(st) ! 1612: int st; /* the status code */ ! 1613: { ! 1614: switch(st) { ! 1615: case M_ST_ICMD: ! 1616: printf("invalid command\n"); ! 1617: break; ! 1618: case M_ST_ABRTD: ! 1619: printf("command aborted\n"); ! 1620: break; ! 1621: case M_ST_OFFLN: ! 1622: printf("unit offline\n"); ! 1623: break; ! 1624: case M_ST_WRTPR: ! 1625: printf("unit write protected\n"); ! 1626: break; ! 1627: case M_ST_COMP: ! 1628: printf("compare error\n"); ! 1629: break; ! 1630: case M_ST_DATA: ! 1631: printf("data error\n"); ! 1632: break; ! 1633: case M_ST_HSTBF: ! 1634: printf("host buffer access error\n"); ! 1635: break; ! 1636: case M_ST_CNTLR: ! 1637: printf("controller error\n"); ! 1638: break; ! 1639: case M_ST_DRIVE: ! 1640: printf("drive error\n"); ! 1641: break; ! 1642: case M_ST_FMTER: ! 1643: printf("formatter error\n"); ! 1644: break; ! 1645: case M_ST_BOT: ! 1646: printf("BOT encountered\n"); ! 1647: break; ! 1648: case M_ST_TAPEM: ! 1649: printf("tape mark encountered\n"); ! 1650: break; ! 1651: case M_ST_RDTRN: ! 1652: printf("record data truncated\n"); ! 1653: break; ! 1654: case M_ST_PLOST: ! 1655: printf("position lost\n"); ! 1656: break; ! 1657: case M_ST_SEX: ! 1658: printf("serious exception\n"); ! 1659: break; ! 1660: case M_ST_LED: ! 1661: printf("LEOT detected\n"); ! 1662: break; ! 1663: } ! 1664: } ! 1665: ! 1666: ! 1667: /* ! 1668: * Manage buffers and perform block mode read and write operations. ! 1669: */ ! 1670: ! 1671: tmscpstrategy (bp) ! 1672: register struct buf *bp; ! 1673: { ! 1674: register struct uba_device *ui; ! 1675: register struct uba_ctlr *um; ! 1676: register struct buf *dp; ! 1677: register int unit = TMSUNIT(bp->b_dev); ! 1678: int s; ! 1679: ! 1680: if (unit >= NTMS) ! 1681: { ! 1682: # ifdef DEBUG ! 1683: printd ("tmscpstrategy: bad unit # %d\n",unit); ! 1684: # endif ! 1685: bp->b_flags |= B_ERROR; ! 1686: iodone(bp); ! 1687: return; ! 1688: } ! 1689: ui = tmsdinfo[unit]; ! 1690: um = ui->ui_mi; ! 1691: if (ui == 0 || ui->ui_alive == 0) ! 1692: { ! 1693: bp->b_flags |= B_ERROR; ! 1694: iodone(bp); ! 1695: return; ! 1696: } ! 1697: s = spl5(); ! 1698: /* ! 1699: * Link the buffer onto the drive queue ! 1700: */ ! 1701: dp = &tmsutab[ui->ui_unit]; ! 1702: if (dp->b_actf == 0) ! 1703: dp->b_actf = bp; ! 1704: else ! 1705: dp->b_actl->av_forw = bp; ! 1706: dp->b_actl = bp; ! 1707: bp->av_forw = 0; ! 1708: /* ! 1709: * Link the drive onto the controller queue ! 1710: */ ! 1711: if (dp->b_active == 0) ! 1712: { ! 1713: dp->b_forw = NULL; ! 1714: if (um->um_tab.b_actf == NULL) ! 1715: um->um_tab.b_actf = dp; ! 1716: else ! 1717: um->um_tab.b_actl->b_forw = dp; ! 1718: um->um_tab.b_actl = dp; ! 1719: dp->b_active = 1; ! 1720: } ! 1721: /* ! 1722: * If the controller is not active, start it. ! 1723: */ ! 1724: if (um->um_tab.b_active == 0) ! 1725: { ! 1726: # if defined(VAX750) ! 1727: if (cpu == VAX_750 ! 1728: && tmscpwtab[um->um_ctlr].av_forw == &tmscpwtab[um->um_ctlr]) ! 1729: { ! 1730: if (um->um_ubinfo != 0) ! 1731: log(TMS_PRI, "tmscpstrategy: ubinfo 0x%x\n", ! 1732: um->um_ubinfo); ! 1733: else ! 1734: um->um_ubinfo = uballoc(um->um_ubanum, (caddr_t)0, 0, UBA_NEEDBDP); ! 1735: } ! 1736: # endif ! 1737: # ifdef DEBUG ! 1738: printd10("tmscpstrategy: Controller not active, starting it\n"); ! 1739: # endif ! 1740: (void) tmscpstart(um); ! 1741: } ! 1742: splx(s); ! 1743: return; ! 1744: } ! 1745: ! 1746: #define DBSIZE 32 ! 1747: ! 1748: #define ca_Rspdsc ca_rspdsc[0] ! 1749: #define ca_Cmddsc ca_rspdsc[1] ! 1750: #define tmscp_Rsp tmscp_rsp[0] ! 1751: #define tmscp_Cmd tmscp_cmd[0] ! 1752: ! 1753: struct tmscp tmscpd[NTMSCP]; ! 1754: ! 1755: tmscpdump(dev) ! 1756: dev_t dev; ! 1757: { ! 1758: struct tmscpdevice *tmscpaddr; ! 1759: struct tmscp *tmscp_ubaddr; ! 1760: char *start; ! 1761: int num, blk, unit; ! 1762: register struct uba_regs *uba; ! 1763: register struct uba_device *ui; ! 1764: register struct tmscp *tmscpp; ! 1765: register struct pte *io; ! 1766: register int i; ! 1767: ! 1768: unit = minor(dev) & 03; ! 1769: if (unit >= NTMS) ! 1770: return (ENXIO); ! 1771: # define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) ! 1772: ui = phys(struct uba_device *, tmsdinfo[unit]); ! 1773: if (ui->ui_alive == 0) ! 1774: return (ENXIO); ! 1775: uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; ! 1776: ubainit(uba); ! 1777: tmscpaddr = (struct tmscpdevice *)ui->ui_physaddr; ! 1778: DELAY(2000000); ! 1779: tmscpp = phys(struct tmscp *, &tmscpd[ui->ui_ctlr]); ! 1780: ! 1781: num = btoc(sizeof(struct tmscp)) + 1; ! 1782: io = &uba->uba_map[NUBMREG-num]; ! 1783: for(i = 0; i<num; i++) ! 1784: *(int *)io++ = UBAMR_MRV|(btop(tmscpp)+i); ! 1785: tmscp_ubaddr = (struct tmscp *)(((int)tmscpp & PGOFSET)|((NUBMREG-num)<<9)); ! 1786: ! 1787: tmscpaddr->tmscpip = 0; ! 1788: while ((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0) ! 1789: if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); ! 1790: tmscpaddr->tmscpsa = TMSCP_ERR; ! 1791: while ((tmscpaddr->tmscpsa & TMSCP_STEP2) == 0) ! 1792: if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); ! 1793: tmscpaddr->tmscpsa = (short)&tmscp_ubaddr->tmscp_ca.ca_ringbase; ! 1794: while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0) ! 1795: if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); ! 1796: tmscpaddr->tmscpsa = (short)(((int)&tmscp_ubaddr->tmscp_ca.ca_ringbase) >> 16); ! 1797: while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0) ! 1798: if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); ! 1799: tmscpaddr->tmscpsa = TMSCP_GO; ! 1800: tmscpp->tmscp_ca.ca_Rspdsc = (long)&tmscp_ubaddr->tmscp_Rsp.mscp_cmdref; ! 1801: tmscpp->tmscp_ca.ca_Cmddsc = (long)&tmscp_ubaddr->tmscp_Cmd.mscp_cmdref; ! 1802: tmscpp->tmscp_Cmd.mscp_header.tmscp_vcid = 1; /* for tape */ ! 1803: tmscpp->tmscp_Cmd.mscp_cntflgs = 0; ! 1804: tmscpp->tmscp_Cmd.mscp_version = 0; ! 1805: if (tmscpcmd(M_OP_STCON, tmscpp, tmscpaddr) == 0) { ! 1806: return(EFAULT); ! 1807: } ! 1808: tmscpp->tmscp_Cmd.mscp_unit = ui->ui_slave; ! 1809: if (tmscpcmd(M_OP_ONLIN, tmscpp, tmscpaddr) == 0) { ! 1810: return(EFAULT); ! 1811: } ! 1812: ! 1813: num = maxfree; ! 1814: start = 0; ! 1815: while (num > 0) ! 1816: { ! 1817: blk = num > DBSIZE ? DBSIZE : num; ! 1818: io = uba->uba_map; ! 1819: for (i = 0; i < blk; i++) ! 1820: *(int *)io++ = (btop(start)+i) | UBAMR_MRV; ! 1821: *(int *)io = 0; ! 1822: tmscpp->tmscp_Cmd.mscp_lbn = btop(start); ! 1823: tmscpp->tmscp_Cmd.mscp_unit = ui->ui_slave; ! 1824: tmscpp->tmscp_Cmd.mscp_bytecnt = blk*NBPG; ! 1825: # ifdef MVAX ! 1826: if( cpu == MVAX_I ) ! 1827: tmscpp->tmscp_Cmd.mscp_buffer = (long) start; ! 1828: else ! 1829: # endif MVAX ! 1830: tmscpp->tmscp_Cmd.mscp_buffer = 0; ! 1831: if (tmscpcmd(M_OP_WRITE, tmscpp, tmscpaddr) == 0) ! 1832: return(EIO); ! 1833: start += blk*NBPG; ! 1834: num -= blk; ! 1835: } ! 1836: return (0); ! 1837: } ! 1838: ! 1839: ! 1840: /* ! 1841: * Perform a standalone tmscp command. This routine is only used by tmscpdump. ! 1842: */ ! 1843: ! 1844: tmscpcmd(op, tmscpp, tmscpaddr) ! 1845: int op; ! 1846: register struct tmscp *tmscpp; ! 1847: struct tmscpdevice *tmscpaddr; ! 1848: { ! 1849: int i; ! 1850: ! 1851: ! 1852: tmscpp->tmscp_Cmd.mscp_opcode = op; ! 1853: tmscpp->tmscp_Rsp.mscp_header.tmscp_msglen = mscp_msglen; ! 1854: tmscpp->tmscp_Cmd.mscp_header.tmscp_msglen = mscp_msglen; ! 1855: tmscpp->tmscp_ca.ca_Rspdsc |= TMSCP_OWN|TMSCP_INT; ! 1856: tmscpp->tmscp_ca.ca_Cmddsc |= TMSCP_OWN|TMSCP_INT; ! 1857: if (tmscpaddr->tmscpsa&TMSCP_ERR) ! 1858: printf("tmscp fatal error (0%o)\n", tmscpaddr->tmscpsa&0xffff); ! 1859: i = tmscpaddr->tmscpip; ! 1860: #ifdef lint ! 1861: i = i; ! 1862: #endif ! 1863: for (;;) ! 1864: { ! 1865: if (tmscpp->tmscp_ca.ca_cmdint) ! 1866: tmscpp->tmscp_ca.ca_cmdint = 0; ! 1867: if (tmscpp->tmscp_ca.ca_rspint) ! 1868: break; ! 1869: } ! 1870: tmscpp->tmscp_ca.ca_rspint = 0; ! 1871: if (tmscpp->tmscp_Rsp.mscp_opcode != (op|M_OP_END) || ! 1872: (tmscpp->tmscp_Rsp.mscp_status&M_ST_MASK) != M_ST_SUCC) ! 1873: { ! 1874: printf("error: com %d opc 0x%x stat 0x%x\ndump ", op, ! 1875: tmscpp->tmscp_Rsp.mscp_opcode, tmscpp->tmscp_Rsp.mscp_status); ! 1876: return(0); ! 1877: } ! 1878: return(1); ! 1879: } ! 1880: ! 1881: /* ! 1882: * Catch ioctl commands, and call the "command" routine to do them. ! 1883: */ ! 1884: ! 1885: /* ARGSUSED */ ! 1886: tmscpioctl(dev, cmd, data, flag) ! 1887: dev_t dev; ! 1888: int cmd; ! 1889: caddr_t data; ! 1890: int flag; ! 1891: { ! 1892: register struct buf *bp = &ctmscpbuf[TMSCPCTLR(dev)]; ! 1893: register callcount; /* number of times to call cmd routine */ ! 1894: register struct uba_device *ui; ! 1895: register struct tms_info *tms; ! 1896: int fcount; /* number of files (or records) to space */ ! 1897: int error = 0; ! 1898: register struct mtop *mtop; /* mag tape cmd op to perform */ ! 1899: register struct mtget *mtget; /* mag tape struct to get info in */ ! 1900: ! 1901: /* we depend of the values and order of the TMS ioctl codes here */ ! 1902: static tmsops[] = ! 1903: {TMS_WRITM,TMS_FSF,TMS_BSF,TMS_FSR,TMS_BSR,TMS_REW,TMS_OFFL,TMS_SENSE, ! 1904: TMS_CACHE,TMS_NOCACHE}; ! 1905: ! 1906: switch (cmd) { ! 1907: case MTIOCTOP: /* tape operation */ ! 1908: mtop = (struct mtop *)data; ! 1909: switch (mtop->mt_op) { ! 1910: ! 1911: case MTWEOF: ! 1912: callcount = mtop->mt_count; ! 1913: fcount = 1; ! 1914: break; ! 1915: case MTFSF: case MTBSF: ! 1916: case MTFSR: case MTBSR: ! 1917: callcount = 1; ! 1918: fcount = mtop->mt_count; ! 1919: break; ! 1920: case MTREW: case MTOFFL: case MTNOP: ! 1921: case MTCACHE: case MTNOCACHE: ! 1922: callcount = 1; ! 1923: fcount = 1; /* wait for this rewind */ ! 1924: break; ! 1925: default: ! 1926: return (ENXIO); ! 1927: } /* end switch mtop->mt_op */ ! 1928: ! 1929: if (callcount <= 0 || fcount <= 0) ! 1930: return (EINVAL); ! 1931: while (--callcount >= 0) ! 1932: { ! 1933: tmscpcommand(dev, tmsops[mtop->mt_op], fcount); ! 1934: if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && ! 1935: bp->b_resid) ! 1936: return (EIO); ! 1937: if (bp->b_flags & B_ERROR) /* like hitting BOT */ ! 1938: break; ! 1939: } ! 1940: if (bp->b_flags&B_ERROR) ! 1941: if ((error = bp->b_error)==0) ! 1942: return (EIO); ! 1943: return (error); ! 1944: ! 1945: case MTIOCGET: ! 1946: /* ! 1947: * Return status info associated with the particular UNIT. ! 1948: */ ! 1949: ui = tmsdinfo[TMSUNIT(dev)]; ! 1950: tms = &tms_info[ui->ui_unit]; ! 1951: mtget = (struct mtget *)data; ! 1952: mtget->mt_type = MT_ISTMSCP; ! 1953: mtget->mt_dsreg = tms->tms_flags << 8; ! 1954: mtget->mt_dsreg |= tms->tms_endcode; ! 1955: mtget->mt_erreg = tms->tms_status; ! 1956: mtget->mt_resid = tms->tms_resid; ! 1957: break; ! 1958: ! 1959: default: ! 1960: return (ENXIO); ! 1961: } ! 1962: return (0); ! 1963: } ! 1964: ! 1965: ! 1966: /* ! 1967: * Reset (for raw mode use only). ! 1968: */ ! 1969: ! 1970: tmscpreset (uban) ! 1971: int uban; ! 1972: { ! 1973: register struct uba_ctlr *um; ! 1974: register struct uba_device *ui; ! 1975: register struct buf *bp, *dp; ! 1976: register int unit; ! 1977: struct buf *nbp; ! 1978: int d; ! 1979: ! 1980: for (d = 0; d < NTMSCP; d++) ! 1981: { ! 1982: if ((um = tmscpminfo[d]) == 0 || um->um_ubanum != uban || ! 1983: um->um_alive == 0) ! 1984: continue; ! 1985: printf(" tmscp%d", d); ! 1986: um->um_tab.b_active = 0; ! 1987: um->um_tab.b_actf = um->um_tab.b_actl = 0; ! 1988: tmscp_softc[d].sc_state = S_IDLE; ! 1989: tmscp_softc[d].sc_mapped = 0; ! 1990: for (unit = 0; unit < NTMS; unit++) ! 1991: { ! 1992: if ((ui = tmsdinfo[unit]) == 0) ! 1993: continue; ! 1994: if (ui->ui_alive == 0 || ui->ui_mi != um) ! 1995: continue; ! 1996: tmsutab[unit].b_active = 0; ! 1997: tmsutab[unit].b_qsize = 0; ! 1998: } ! 1999: for (bp = tmscpwtab[d].av_forw; bp != &tmscpwtab[d]; bp = nbp) ! 2000: { ! 2001: nbp = bp->av_forw; ! 2002: bp->b_ubinfo = 0; ! 2003: /* ! 2004: * Link the buffer onto the drive queue ! 2005: */ ! 2006: dp = &tmsutab[TMSUNIT(bp->b_dev)]; ! 2007: if (dp->b_actf == 0) ! 2008: dp->b_actf = bp; ! 2009: else ! 2010: dp->b_actl->av_forw = bp; ! 2011: dp->b_actl = bp; ! 2012: bp->av_forw = 0; ! 2013: /* ! 2014: * Link the drive onto the controller queue ! 2015: */ ! 2016: if (dp->b_active == 0) ! 2017: { ! 2018: dp->b_forw = NULL; ! 2019: if (um->um_tab.b_actf == NULL) ! 2020: um->um_tab.b_actf = dp; ! 2021: else ! 2022: um->um_tab.b_actl->b_forw = dp; ! 2023: um->um_tab.b_actl = dp; ! 2024: dp->b_active = 1; ! 2025: } ! 2026: } ! 2027: (void)tmscpinit(d); ! 2028: } ! 2029: } ! 2030: ! 2031: ! 2032: /* ! 2033: * Process an error log message ! 2034: * ! 2035: * Only minimal decoding is done, only "useful" ! 2036: * information is printed. Eventually should ! 2037: * send message to an error logger. ! 2038: */ ! 2039: ! 2040: tmserror(um, mp) ! 2041: register struct uba_ctlr *um; ! 2042: register struct mslg *mp; ! 2043: { ! 2044: register i; ! 2045: ! 2046: # ifdef DEBUG ! 2047: printd("tmserror:\n"); ! 2048: # endif ! 2049: if(!(mp->mslg_flags & (M_LF_SUCC | M_LF_CONT))) ! 2050: log(TMS_PRI, "tmscp%d: %s error, ", um->um_ctlr, ! 2051: mp->mslg_flags & ( M_LF_SUCC | M_LF_CONT ) ? "soft" : "hard"); ! 2052: ! 2053: switch (mp->mslg_format) { ! 2054: ! 2055: case M_FM_CNTERR: ! 2056: log(TMS_PRI, "controller error, event 0%o\n", mp->mslg_event); ! 2057: break; ! 2058: case M_FM_BUSADDR: ! 2059: log(TMS_PRI, "host memory access error, event 0%o, addr 0%o\n", ! 2060: mp->mslg_event, mp->mslg_busaddr); ! 2061: break; ! 2062: case M_FM_TAPETRN: ! 2063: log(TMS_PRI, "tape transfer error, unit %d, grp 0x%x, event 0%o\n", ! 2064: mp->mslg_unit, mp->mslg_group, mp->mslg_event); ! 2065: break; ! 2066: case M_FM_STIERR: ! 2067: log(TMS_PRI, "STI error, unit %d, event 0%o\n", ! 2068: mp->mslg_unit, mp->mslg_event); ! 2069: #ifdef notdef ! 2070: /* too painful to do with log() */ ! 2071: for(i = 0; i < 62;i++) ! 2072: mprintf("\t0x%x",mp->mslg_stiunsucc[i] & 0xff); ! 2073: mprintf("\n"); ! 2074: #endif ! 2075: break; ! 2076: case M_FM_STIDEL: ! 2077: log(TMS_PRI, "STI Drive Error Log, unit %d, event 0%o\n", ! 2078: mp->mslg_unit, mp->mslg_event); ! 2079: break; ! 2080: case M_FM_STIFEL: ! 2081: log(TMS_PRI, "STI Formatter Error Log, unit %d, event 0%o\n", ! 2082: mp->mslg_unit, mp->mslg_event); ! 2083: break; ! 2084: default: ! 2085: log(TMS_PRI, "unknown error, unit %d, format 0%o, event 0%o\n", ! 2086: mp->mslg_unit, mp->mslg_format, mp->mslg_event); ! 2087: } ! 2088: ! 2089: if (tmscperror) ! 2090: { ! 2091: register long *p = (long *)mp; ! 2092: ! 2093: for (i = 0; i < mp->mslg_header.tmscp_msglen; i += sizeof(*p)) ! 2094: printf("%x ", *p++); ! 2095: printf("\n"); ! 2096: } ! 2097: } ! 2098: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.