📄 scsi_tape.c
字号:
* physio() and tzstrategy() called. * minphys() limits maximum transfer size. * */tzwrite(dev, uio) register dev_t dev; register struct uio *uio;{ int unit = UNIT(dev); return (physio(tzstrategy, &rszbuf[unit], dev, B_WRITE, minphys, uio));}/* TODO: debug (too handy to remove) */int tz_sk_print = 0;/* * * Name: tzioctl -Tape ioctl routine * * Abstract: This routine is called via the ioctl system call * to perform various non data transfer functions, * such as MTIOCTOP (magtape operation). * * Inputs: * * dev ULTRIX major/minor device number. * cmd The ioctl to execute. * data Pointer to data bassed with ioctl. * flag Flag passed with ioctl. * * Outputs: * Some ioctls pass data back to the caller. * Possible device off-line error message. * * Return Values: * * EINVAL Invalid argument to ioctl. * ENXIO Non supported ioctl. * 0 Success. * * Side Effects: * Several other routines called. * */tzioctl(dev, cmd, data, flag) dev_t dev; register int cmd; caddr_t data; int flag;{ register struct uba_device *ui; int unit = UNIT(dev); int cntlr; int targid; register struct sz_softc *sc; register int callcount; register int fcount; struct mtop *mtop; struct mtget *mtget; struct devget *devget; struct sz_modsns_dt *msdp; struct scsi_devtab *sdp; struct tape_opt_tab *todp; /* we depend of the values and order of the MT codes here * static tzops[] = { SZ_WFM,SZ_P_FSPACEF,SZ_P_BSPACEF,SZ_P_FSPACER, * SZ_P_BSPACER,SZ_REWIND,SZ_P_UNLOAD,SZ_P_CACHE, * SZ_P_NOCACHE,SZ_RQSNS }; */#define SZ_SZNOP SZ_INQ /* we depend on the values and order of the MT codes here */ static tzops[] = { SZ_WFM,SZ_P_FSPACEF,SZ_P_BSPACEF,SZ_P_FSPACER, /* MTWEOF MTFSF MTBSF MTFSR */ SZ_P_BSPACER,SZ_REWIND,SZ_P_UNLOAD,SZ_SZNOP, /* MTBSR MTREW MTOFFL MTNOP */ SZ_P_CACHE,SZ_P_NOCACHE,SZ_RQSNS,SZ_RQSNS, /* MTCACHE MTNOCACHE MTCSE MTCLX */ SZ_RQSNS,SZ_SZNOP,SZ_SZNOP,SZ_SZNOP,SZ_SZNOP,SZ_SZNOP, /* MTCLS MTENAEOT MTDISEOT MTFLUSH MTGTON MTGTOFF */ SZ_P_RETENSION}; /* MTRETEN */ ui = szdinfo[unit]; cntlr = ui->ui_ctlr; targid = ui->ui_slave; sc = &sz_softc[cntlr]; sdp = (struct scsi_devtab *)sc->sc_devtab[targid]; /* * get our tape option struct if available */ if( sdp->opt_tab != NULL){ todp = (struct tape_opt_tab *)sdp->opt_tab; } switch (cmd) { case MTIOCTOP: /* tape operation */ /* * If SZ_NODEVICE is set, the device was opened * with FNDELAY, but the device didn't respond. * We'll try again to see if the device is here, * if it is not, return an error */ if (sc->sc_szflags[targid] & SZ_NODEVICE) { DEV_UGH(sc->sc_device[targid],unit,"offline"); return(ENXIO); } mtop = (struct mtop *)data; switch (mtop->mt_op) { case MTWEOF: callcount = 1; if( sc->sc_category_flags[targid] & TPMARK_PENDING){ fcount = mtop->mt_count - 1; sc->sc_category_flags[targid] &= ~TPMARK_PENDING; } else { fcount = mtop->mt_count; } break; case MTFSF: callcount = 1; if( sc->sc_category_flags[targid] & TPMARK_PENDING){ fcount = mtop->mt_count - 1; if (fcount < 0 ){ fcount = 0; } if( fcount == 0){ sc->sc_category_flags[targid] &= ~TPMARK_PENDING; sc->sc_category_flags[targid] |= DEV_TPMARK; } else { sc->sc_category_flags[targid] &= ~TPMARK_PENDING; } } else { fcount = mtop->mt_count; } break; case MTBSF: callcount = 1; if( sc->sc_category_flags[targid] & TPMARK_PENDING){ fcount = mtop->mt_count + 1; sc->sc_category_flags[targid] &= ~TPMARK_PENDING; } else { fcount = mtop->mt_count; } break; case MTFSR: callcount = 1; if( sc->sc_category_flags[targid] & TPMARK_PENDING){ fcount = mtop->mt_count - 1; if (fcount < 0 ){ fcount = 0; } if( fcount == 0){ sc->sc_category_flags[targid] &= ~TPMARK_PENDING; sc->sc_category_flags[targid] |= DEV_TPMARK; } else { sc->sc_category_flags[targid] &= ~TPMARK_PENDING; } } else { fcount = mtop->mt_count; } break; case MTBSR: callcount = 1; if( sc->sc_category_flags[targid] & TPMARK_PENDING){ fcount = mtop->mt_count + 1; sc->sc_category_flags[targid] &= ~TPMARK_PENDING; } else { fcount = mtop->mt_count; } break; case MTOFFL: sc->sc_flags[targid] |= DEV_OFFLINE; sc->sc_category_flags[targid] &= ~TPMARK_PENDING; case MTREW: sc->sc_flags[targid] &= ~DEV_EOM; sc->sc_category_flags[targid] &= ~TPMARK_PENDING; callcount = 1; fcount = 1; break; case MTNOP: return(0); case MTCACHE: case MTNOCACHE: return(ENXIO); case MTFLUSH: return(ENXIO); case MTCSE: /* * Clear Serious Exception, used by tape utilities * to clean up after Nbuf I/O and end of media. */ sc->sc_category_flags[targid] &= ~DEV_TPMARK; sc->sc_flags[targid] |= DEV_CSE; return(0); case MTCLX: case MTCLS: return(0); case MTENAEOT: dis_eot_sz[unit] = 0; return(0); case MTDISEOT: dis_eot_sz[unit] = DISEOT; sc->sc_flags[targid] &= ~DEV_EOM; return(0); case MTRETEN: /* RETENSION command... */ sc->sc_flags[targid] &= ~DEV_EOM; sc->sc_category_flags[targid] &= ~TPMARK_PENDING; callcount = 1; fcount = 1; break; default: return (ENXIO); } if (callcount <= 0 || fcount <= 0) return (EINVAL); while (--callcount >= 0) { tzcommand(dev, tzops[mtop->mt_op], fcount, 0); if (sc->sc_c_status[targid] != SZ_GOOD) { /* TODO: debug (too handy to remove) */ if (tz_sk_print) { printf("tzioctl: Sense Key = 0x%x\n", sc->sc_c_snskey[targid]); } if ((sc->sc_c_snskey[targid] != SZ_NOSENSE) && (sc->sc_c_snskey[targid] != SZ_RECOVERR)) return(EIO); if (sc->sc_category_flags[targid] & DEV_TPMARK) return(EIO); } } return(0); case MTIOCGET: /* tape status */ mtget = (struct mtget *)data; /* MTX depends on DEV_EOM in sc_flags for EOT handling */ mtget->mt_dsreg = (unsigned short)sc->sc_flags[targid]; /* sorry no useful error information available */ mtget->mt_erreg = 0; /* best guess */ mtget->mt_resid = sc->sc_resid[targid]; /* this is a SCSI tape */ mtget->mt_type = MT_ISSCSI; break; case DEVIOCGET: /* device status */ devget = (struct devget *)data; bzero(devget,sizeof(struct devget)); devget->category = DEV_TAPE; devget->bus = DEV_NB; bcopy(DEV_VS_SCSI, devget->interface, strlen(DEV_VS_SCSI)); bcopy(sc->sc_device[targid], devget->device, DEV_SIZE); devget->adpt_num = 0; devget->nexus_num = 0; devget->bus_num = 0; devget->ctlr_num = cntlr; devget->rctlr_num = 0; devget->slave_num = targid; bcopy("tz", devget->dev_name, 3); devget->unit_num = unit; devget->soft_count = sc->sc_softcnt[targid]; devget->hard_count = sc->sc_hardcnt[targid]; devget->stat = sc->sc_flags[targid]; /* * we only want the lower 4 bits at this time * the rest is density which gwts filled in later */ devget->category_stat = (sc->sc_category_flags[targid] & 0X0F); /* * Do a mode sense to check for write locked drive. * First one can fail due to unit attention. */ tzcommand(dev, SZ_MODSNS, -1, 0); if (sc->sc_c_status[targid] != SZ_GOOD) tzcommand(dev, SZ_MODSNS, -1, 0); if (sc->sc_c_status[targid] == SZ_GOOD) { msdp = (struct sz_modsns_dt *)&sc->sz_dat[targid]; if (msdp->wp) { /* Tape is write locked. */ devget->stat |= DEV_WRTLCK; } /* * Setup the tape density. */ if (msdp->density <= density_entrys) { devget->category_stat |= density_table[msdp->density]; } /* * Setup default density codes. */ if (msdp->density == SCSI_DENS_DEFAULT) { switch (sdp->devtype) { case TZK10: devget->category_stat |= DEV_16000_BPI; break; case TLZ04: devget->category_stat |= DEV_61000_BPI; break; case TZK08: devget->category_stat |= DEV_54000_BPI; break; case TZ30: case TZK50: devget->category_stat |= DEV_6666BPI; break; default: if (sdp->opt_tab) { if (todp->opt_flags & SCSI_QIC) { devget->category_stat |= DEV_10000_BPI; } else if (todp->opt_flags & SCSI_9TRK) { devget->category_stat |= DEV_6250BPI; } } break; } /* End 'switch (sdp->devtype)' */ } /* End 'if (msdp->density == SCSI_DENS_DEFAULT)' */ } /* End 'if (sc->sc_c_status[targid] == SZ_GOOD)' */ break; default: return (ENXIO); } return (0);}/* * * Name: tzcomplete -Tape completion routine * * Abstract: This routine is called from the scsi state machine * to perform the completion work for the current data * transfer. * * Inputs: * * bp Buffer pointer of command to be completed. * * Outputs: * Only printing debug messages. * * Return Values: Nothing formal, b_resid is updated. * * Side Effects: * biodone() is called to free up the current bp. * The buffer queue is changed to free up the front entry. * */int tzcomplete( bp ) struct buf *bp;{ register struct uba_ctlr *um; register struct buf *dp; register int s; int unit = UNIT(bp->b_dev); int targid; int cntlr; register struct sz_softc *sc; struct uba_device *ui; ui = szdinfo[unit]; dp = &szutab[unit]; targid = ui->ui_slave; cntlr = ui->ui_ctlr; sc = &sz_softc[cntlr]; PRINTD( targid, 0x01, ("tzcomplete called unit %d\n", UNIT(bp->b_dev)) ); /* * Remove the completed request from the queue * and release the buffer. */ /* TODO: are we absolutely sure dp is valid? */ dp->b_actf = bp->av_forw; bp->b_resid = sc->sc_resid[targid]; PRINTD(targid, 0x04, ("resid = %d\n", bp->b_resid)); sc->sc_flags[targid] |= DEV_DONE; biodone(bp); sc->sc_xevent[targid] = SZ_BEGIN; sz_retries[sc->sc_unit[targid]] = 0; /* * The comand has ended */ dp->b_active = 0;}tzdump(){}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -