?? scsiseqlib.c
字號:
STATUS scsiWrtFileMarks ( SCSI_SEQ_DEV * pScsiSeqDev, /* ptr to SCSI sequential device info */ int numMarks, /* number of file marks to write */ BOOL shortMark /* TRUE to write short file mark */ ) { SCSI_COMMAND scsiCommand; /* SCSI command byte array */ SCSI_TRANSACTION scsiXaction; /* info on a SCSI transaction */ SCSI_PHYS_DEV * pScsiPhysDev; /* ptr to SCSI physical device info */ STATUS status; /* status of transactions */ SCSI_DEBUG_MSG ("scsiWrtFileMarks:\n", 0, 0, 0, 0, 0, 0); pScsiPhysDev = pScsiSeqDev->pScsiPhysDev; scsiCommand[0] = SCSI_OPCODE_WRITE_FILEMARKS; scsiCommand[1] = (UINT8) ((pScsiPhysDev->scsiDevLUN & 0x7) << 5); scsiCommand[2] = (UINT8) ((numMarks >> 16) & 0xff); scsiCommand[3] = (UINT8) ((numMarks >> 8) & 0xff); scsiCommand[4] = (UINT8) (numMarks & 0xff); if (shortMark) scsiCommand [5] = 0x80; else scsiCommand[5] = (UINT8) 0; scsiXaction.cmdAddress = scsiCommand; scsiXaction.cmdLength = SCSI_GROUP_0_CMD_LENGTH; scsiXaction.dataAddress = NULL; scsiXaction.dataDirection = O_WRONLY; scsiXaction.dataLength = NULL; scsiXaction.addLengthByte = NULL; if (numMarks < 500) scsiXaction.cmdTimeout = SCSI_TIMEOUT_5SEC * (numMarks + 10); else scsiXaction.cmdTimeout = SCSI_TIMEOUT_FULL; scsiXaction.tagType = SCSI_TAG_DEFAULT; scsiXaction.priority = SCSI_THREAD_TASK_PRIORITY; status = (*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction); return (status); }/********************************************************************************* scsiSpace - move the tape on a specified physical SCSI device** This routine moves the tape on a specified SCSI physical device.* There are two types of space code that are mandatory in SCSI; currently* these are the only two supported:** .TS* tab(|);* lf3 lf3 cf3* l l c.* Code | Description | Support* _* 000 | Blocks | Yes* 001 | File marks | Yes* 010 | Sequential file marks | No* 011 | End-of-data | No* 100 | Set marks | No* 101 | Sequential set marks | No* .TE ** RETURNS: OK, or ERROR if an error is returned by the device.** ERRNO: S_scsiLib_ILLEGAL_REQUEST*/STATUS scsiSpace ( SCSI_SEQ_DEV * pScsiSeqDev, /* ptr to SCSI sequential device info */ int count, /* count for space command */ int spaceCode /* code for the type of space command */ ) { SCSI_PHYS_DEV *pScsiPhysDev; /* ptr to SCSI physical device info */ SCSI_COMMAND scsiCommand; /* SCSI command byte array */ SCSI_TRANSACTION scsiXaction; /* info on a SCSI transaction */ STATUS status; /* status of transaction */ SCSI_DEBUG_MSG ("scsiSpace:\n", 0, 0, 0, 0, 0, 0); pScsiPhysDev = pScsiSeqDev->pScsiPhysDev; if ((count == 0) || ((spaceCode != SPACE_CODE_DATABLK) && (spaceCode != SPACE_CODE_FILEMARK))) { errno = S_scsiLib_ILLEGAL_REQUEST; return (ERROR); } scsiCommand[0] = SCSI_OPCODE_SPACE; scsiCommand[1] = (UINT8) (((pScsiPhysDev->scsiDevLUN & 0x7) << 5) | (spaceCode)); scsiCommand[2] = (UINT8) ((count >> 16) & 0xff); scsiCommand[3] = (UINT8) ((count >> 8) & 0xff); scsiCommand[4] = (UINT8) (count & 0xff); scsiCommand[5] = (UINT8) 0; scsiXaction.cmdAddress = scsiCommand; scsiXaction.cmdLength = SCSI_GROUP_0_CMD_LENGTH; scsiXaction.dataAddress = NULL; scsiXaction.dataDirection = O_RDONLY; scsiXaction.dataLength = NULL; scsiXaction.addLengthByte = NULL; if (count < 500) scsiXaction.cmdTimeout = SCSI_TIMEOUT_5SEC * count * 10; else scsiXaction.cmdTimeout = SCSI_TIMEOUT_FULL; scsiXaction.tagType = SCSI_TAG_DEFAULT; scsiXaction.priority = SCSI_THREAD_TASK_PRIORITY; status = (*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction); return (status); }/********************************************************************************* scsiSeqStatusCheck - detect a change in media** This routine issues a TEST_UNIT_READY command to a SCSI device to detect a* change in media. It is called by file systems before executing open() or* creat().** INTERNAL* This function is a duplicate of that in scsiDirectLib, except for the fact* that this function operates on a SEQ_DEV.* * RETURNS: OK or ERROR.*/STATUS scsiSeqStatusCheck ( SCSI_SEQ_DEV *pScsiSeqDev /* ptr to a sequential dev */ ) { SCSI_PHYS_DEV *pScsiPhysDev; /* ptr to SCSI physical device */ SCSI_COMMAND testUnitRdyCommand; /* SCSI command byte array */ SCSI_TRANSACTION scsiXaction; /* info on a SCSI transaction */ char modeBuf[0xff]; /* get mode sense data array */ int modeBufLen; int pageControl; int pageCode; pScsiPhysDev = pScsiSeqDev->pScsiPhysDev; if (scsiCmdBuild (testUnitRdyCommand, &scsiXaction.cmdLength, SCSI_OPCODE_TEST_UNIT_READY, pScsiPhysDev->scsiDevLUN, FALSE, 0, 0, (UINT8) 0) == ERROR) { return (ERROR); } scsiXaction.cmdAddress = testUnitRdyCommand; scsiXaction.dataAddress = NULL; scsiXaction.dataDirection = NONE; scsiXaction.dataLength = 0; scsiXaction.addLengthByte = NONE; scsiXaction.cmdTimeout = SCSI_TIMEOUT_5SEC; scsiXaction.tagType = SCSI_TAG_DEFAULT; scsiXaction.priority = SCSI_THREAD_TASK_PRIORITY; if ((*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction) == ERROR) { SCSI_DEBUG_MSG ("scsiSeqStatusCheck returning ERROR, last Sense = %x\n", pScsiPhysDev->lastSenseKey, 0, 0, 0, 0, 0); return (ERROR); } pageControl = 0x0; /* current values */ pageCode = 0x0; /* no page formatting */ /* (Mode param hdr len) + (mode param block descriptor len) */ modeBufLen = 4 + 8; if (scsiModeSense (pScsiPhysDev, pageControl, pageCode, modeBuf, modeBufLen ) == ERROR) return (ERROR); /* Set the mode of the device */ pScsiSeqDev->seqDev.sd_mode = ( modeBuf [SCSI_MODE_DEV_SPECIFIC_PARAM] & (UINT8) SCSI_DEV_SPECIFIC_WP_MASK ) ? O_RDONLY : O_RDWR; return (OK); }/********************************************************************************* scsiSeqIoctl - perform an I/O control function for sequential access devices** This routine issues scsiSeqLib commands to perform sequential* device-specific I/O control operations.** RETURNS: OK or ERROR.** ERRNO: S_scsiLib_INVALID_BLOCK_SIZE*/int scsiSeqIoctl ( SCSI_SEQ_DEV * pScsiSeqDev, /* ptr to SCSI sequential device */ int function, /* ioctl function code */ int arg /* argument to pass to called function */ ) { char modeBuf[MODE_BUF_LENGTH]; int modeBufLen; int pageControl; int pageCode; int pageFormat; int savePages; int blkSize; SCSI_PHYS_DEV * pScsiPhysDev; /* ptr to SCSI physical device struct */ if ((pScsiPhysDev = pScsiSeqDev->pScsiPhysDev) == NULL) { /* XXX errno */ SCSI_DEBUG_MSG ("scsiSeqIoctl: pScsiSeqDev ptr NULL\n",0,0,0,0,0,0); return (ERROR); } switch (function) { case FIODENSITYSET: /* Execute a MODE SENSE to get the right buffer values */ pageControl = 0x0; /* current values */ pageCode = 0x0; /* no page formatting */ /* (Mode param hdr len) + (mode param block descriptor len) */ modeBufLen = 4 + 8; if (scsiModeSense (pScsiPhysDev, pageControl, pageCode, modeBuf, modeBufLen ) == ERROR) return (ERROR); /* Execute a MODE SELECT to set the density value */ modeBuf[0] = 0x0; /* mode data len not valid for mode select */ /* modeBuf[1] is reserved; medium type not valid for seq devices */ modeBuf[2] = 0x0; /* dev-specific param not defined for md sel */ modeBuf[4] = arg; /* set density code */ pageFormat = 0x0; /* no formatted pages */ savePages = 0x1; /* save page values */ if (scsiModeSelect (pScsiPhysDev, pageFormat, savePages, modeBuf, modeBufLen) == ERROR) return (ERROR); /* Check that the density was set correctly by issuing MODE SENSE */ if (scsiModeSense (pScsiPhysDev, pageControl, pageCode, modeBuf, modeBufLen ) == ERROR) return (ERROR); if (modeBuf[4] != arg) { /* XXX set errno */ return (ERROR); } pScsiSeqDev->seqDev.sd_density = arg; return (OK); case FIODENSITYGET: /* Execute a MODE SENSE to get the right buffer values */ pageControl = 0x0; /* current values */ pageCode = 0x0; /* no page formatting */ /* (Mode param hdr len) + (mode param block descriptor len) */ modeBufLen = 4 + 8; if (scsiModeSense (pScsiPhysDev, pageControl, pageCode, modeBuf, modeBufLen ) == ERROR) return (ERROR); * ((int *) arg) = modeBuf[4]; /* density */ return (OK); case FIOBLKSIZESET: /* Execute a MODE SENSE to get the right buffer values */ pageControl = 0x0; /* current values */ pageCode = 0x0; /* no page formatting */ /* (Mode param hdr len) + (mode param block descriptor len) */ modeBufLen = 4 + 8; if (scsiModeSense (pScsiPhysDev, pageControl, pageCode, modeBuf, modeBufLen ) == ERROR) return (ERROR); /* Execute a MODE SELECT to set the blkSize value */ modeBuf[0] = 0x0; /* mode data len not valid for mode select */ /* modeBuf[1] is reserved; medium type not valid for seq devices */ modeBuf[1] = 0x0; modeBuf[2] = 0x0; /* dev-specific param not defined for md sel */ /* Set the block size */ modeBuf[9] = (UINT8) ((arg >> 16) & 0xff); modeBuf[10] = (UINT8) ((arg >> 8) & 0xff); modeBuf[11] = (UINT8) ( arg & 0xff); pageFormat = 0x1; /* no formatted pages */ savePages = 0x0; /* save page values */ if (scsiModeSelect (pScsiPhysDev, pageFormat, savePages, modeBuf, modeBufLen) == ERROR) return (ERROR); /* Check that the block size was set correctly */ blkSize = scsiSeqIoctl (pScsiSeqDev, FIOBLKSIZEGET, 0); if (blkSize != arg) { errno = S_scsiLib_INVALID_BLOCK_SIZE; return (ERROR); } pScsiSeqDev->seqDev.sd_blkSize = blkSize; return (OK); case FIOBLKSIZEGET: /* Execute a MODE SENSE to get the right buffer values */ pageControl = 0x0; /* current values */ pageCode = 0x0; /* no page formatting */ /* (Mode param hdr len) + (mode param block descriptor len) */ modeBufLen = 4 + 8; if (scsiModeSense (pScsiPhysDev, pageControl, pageCode, modeBuf, modeBufLen ) == ERROR) return (ERROR); /* Construct the block size from the buffer */ blkSize = 0; blkSize = (modeBuf[9] << 16); blkSize |= (modeBuf[10] << 8); blkSize |= modeBuf[11]; return (blkSize); default: SCSI_DEBUG_MSG ("scsiSeqIoctl: bad IOCTL function\n",0,0,0,0,0,0); return (ERROR); } /* switch */ }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -