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