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