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