?? scsiseqlib.c
字號:
if ((scsiSpace (pScsiSeqDev, -1, SPACE_CODE_FILEMARK)) == ERROR) { printf ("Backward space unsuccessful\n"); return (ERROR); } } return (unitsRead); } return (numDataUnits); }/********************************************************************************* scsiWrtTape - write data to a SCSI tape device** This routine writes data to the current block on a specified physical* device. If the boolean <fixedSize> is true, then <numBytes>* represents the number of blocks of size <blockSize>, * defined in the `pScsiPhysDev' structure. If variable block sizes are used* (<fixedSize> = FALSE), then <numBytes> represents the actual number of bytes* to be written. If <numBytes> is greater than the `maxBytesLimit' field* defined in the `pScsiPhysDev' structure, then more than one SCSI transaction* is used to transfer the data.** RETURNS: OK, or ERROR if the data cannot be written or zero bytes are * written.*/STATUS scsiWrtTape ( SCSI_SEQ_DEV *pScsiSeqDev, /* ptr to SCSI sequential device info */ int numBytes, /* total bytes or blocks to be written */ char *buffer, /* ptr to input data buffer */ BOOL fixedSize /* if variable size blocks */ ) { 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 = ERROR; /* status of transaction */ UINT8 * bufPtr; /* ptr to input data buffer */ UINT timeout; /* scsi command timeout */ int xferLength; /* transfer length */ int numBlocks; int maxVarBlockLimit; int writeBytes; int xferBlocks; SCSI_DEBUG_MSG ("scsiWrtTape:\n", 0, 0, 0, 0, 0, 0); pScsiPhysDev = pScsiSeqDev->pScsiPhysDev; /* * Fixed block size transfer. The block size must be defined in * pScsiPhysDev prior to calling this function */ if (fixedSize) { numBlocks = numBytes; /* numBytes means numBlocks for fixed blk size */ if (numBlocks > SCSI_MAX_XFER_BLOCKS) return (ERROR); /* * Check if the number of blocks to be transferred * is less than the max permissible size */ if (numBlocks <= (pScsiPhysDev->pScsiCtrl->maxBytesPerXfer / pScsiSeqDev->seqDev.sd_blkSize)) { scsiCmdFill (pScsiSeqDev, scsiCommand, SCSI_WRITE, TRUE, numBlocks); bufPtr = (UINT8 *) buffer; xferLength = numBlocks * pScsiSeqDev->seqDev.sd_blkSize; /* * timeout value is based on 100kB/sec xfer and a 5 * sec threshold */ timeout = SCSI_TIMEOUT_5SEC * 50 + (10 * numBlocks * pScsiPhysDev->blockSize); scsiXactionFill (&scsiXaction, scsiCommand, SCSI_WRITE, SCSI_GROUP_0_CMD_LENGTH, timeout, xferLength, bufPtr); status = (*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction); return (status); } else { /* determine the max number of blocks that can be transferred */ xferBlocks = (pScsiPhysDev->pScsiCtrl->maxBytesPerXfer) / (pScsiSeqDev->seqDev.sd_blkSize); while (numBlocks > 0) { scsiCmdFill (pScsiSeqDev, scsiCommand, SCSI_WRITE, TRUE, xferBlocks); bufPtr = (UINT8 *) buffer; xferLength = xferBlocks * pScsiSeqDev->seqDev.sd_blkSize; /* * timeout value is based on 100kB/sec xfer and a 5 * sec threshold */ timeout = SCSI_TIMEOUT_5SEC * 50 + (10 * xferBlocks * pScsiPhysDev->blockSize); scsiXactionFill (&scsiXaction, scsiCommand, SCSI_WRITE, SCSI_GROUP_0_CMD_LENGTH, timeout, xferLength, bufPtr); status = (*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction); if (status == OK ) { numBlocks -= xferBlocks; buffer += (xferBlocks * pScsiSeqDev->seqDev.sd_blkSize); if (numBlocks <= (pScsiPhysDev->pScsiCtrl->maxBytesPerXfer / pScsiSeqDev->seqDev.sd_blkSize)) xferBlocks = numBlocks; } else return (status); } return (status); } } /* get the maximum variable block size for the device */ maxVarBlockLimit = pScsiPhysDev->maxVarBlockLimit; if ( maxVarBlockLimit > pScsiPhysDev->pScsiCtrl->maxBytesPerXfer) maxVarBlockLimit = pScsiPhysDev->pScsiCtrl->maxBytesPerXfer; /* multiple transactions needed if numBytes > maxVarBlockLimit */ for (writeBytes=0; numBytes > maxVarBlockLimit; numBytes -= maxVarBlockLimit, writeBytes += maxVarBlockLimit) { scsiCmdFill (pScsiSeqDev, scsiCommand, SCSI_WRITE, FALSE, maxVarBlockLimit); bufPtr = (UINT8 *) buffer + writeBytes; xferLength = maxVarBlockLimit; timeout = SCSI_TIMEOUT_5SEC * 50 + (maxVarBlockLimit * 10); scsiXactionFill (&scsiXaction, scsiCommand, SCSI_WRITE, SCSI_GROUP_0_CMD_LENGTH, timeout, xferLength, bufPtr); status = (*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction); if (status == ERROR) return (status); } if (numBytes > 0) { scsiCmdFill (pScsiSeqDev, scsiCommand, SCSI_WRITE, FALSE, numBytes); bufPtr = (UINT8 *) buffer + writeBytes; xferLength = numBytes; timeout = SCSI_TIMEOUT_5SEC * 50 + (numBytes * 10); scsiXactionFill (&scsiXaction, scsiCommand, SCSI_WRITE, SCSI_GROUP_0_CMD_LENGTH, timeout, xferLength, bufPtr); status = (*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction); } return (status); }/********************************************************************************* scsiRewind - issue a REWIND command to a SCSI device** This routine issues a REWIND command to a specified SCSI device.** RETURNS: OK, or ERROR if the command fails.*/STATUS scsiRewind ( SCSI_SEQ_DEV *pScsiSeqDev /* ptr to SCSI Sequential device */ ) { SCSI_COMMAND rewindCommand; /* SCSI command byte array */ SCSI_TRANSACTION scsiXaction; /* info on a SCSI transaction */ SCSI_PHYS_DEV * pScsiPhysDev; /* ptr to SCSI physical device */ STATUS status; /* holds status of transaction */ SCSI_DEBUG_MSG ("scsiRewind:\n", 0, 0, 0, 0, 0, 0); pScsiPhysDev = pScsiSeqDev->pScsiPhysDev; rewindCommand[0] = SCSI_OPCODE_REWIND; rewindCommand[1] = (UINT8) ((pScsiPhysDev->scsiDevLUN & 0x7) << 5); rewindCommand[2] = (UINT8) 0; rewindCommand[3] = (UINT8) 0; rewindCommand[4] = (UINT8) 0; rewindCommand[5] = (UINT8) 0; scsiXaction.cmdAddress = rewindCommand; scsiXaction.cmdLength = SCSI_GROUP_0_CMD_LENGTH; scsiXaction.dataAddress = (UINT8 *) NULL; scsiXaction.dataDirection = O_WRONLY; scsiXaction.dataLength = 0; scsiXaction.addLengthByte = NULL; scsiXaction.cmdTimeout = SCSI_TIMEOUT_FULL; scsiXaction.tagType = SCSI_TAG_DEFAULT; scsiXaction.priority = SCSI_THREAD_TASK_PRIORITY; status = (*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction); return (status); }/********************************************************************************* scsiReserveUnit - issue a RESERVE UNIT command to a SCSI device** This routine issues a RESERVE UNIT command to a specified SCSI device.** RETURNS: OK, or ERROR if the command fails.*/STATUS scsiReserveUnit ( SCSI_SEQ_DEV *pScsiSeqDev /* ptr to SCSI sequential device */ ) { SCSI_COMMAND reserveUnitCommand; /* SCSI command byte array */ SCSI_TRANSACTION scsiXaction; /* info on a SCSI transaction */ SCSI_PHYS_DEV *pScsiPhysDev; /* ptr to SCSI physical device */ STATUS status; /* status of transaction */ SCSI_DEBUG_MSG ("scsiReserveUnit:\n", 0, 0, 0, 0, 0, 0); pScsiPhysDev = pScsiSeqDev->pScsiPhysDev; reserveUnitCommand[0] = SCSI_OPCODE_RESERVE; reserveUnitCommand[1] = (UINT8) 0; reserveUnitCommand[2] = (UINT8) 0; reserveUnitCommand[3] = (UINT8) 0; reserveUnitCommand[4] = (UINT8) 0; reserveUnitCommand[5] = (UINT8) 0; scsiXaction.cmdAddress = reserveUnitCommand; scsiXaction.cmdLength = SCSI_GROUP_0_CMD_LENGTH; scsiXaction.dataAddress = (UINT8 *) NULL; scsiXaction.dataDirection = O_WRONLY; scsiXaction.dataLength = 0; scsiXaction.addLengthByte = NULL; scsiXaction.cmdTimeout = SCSI_TIMEOUT_5SEC; scsiXaction.tagType = SCSI_TAG_DEFAULT; scsiXaction.priority = SCSI_THREAD_TASK_PRIORITY; status = (*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction); return (status); }/********************************************************************************* scsiReleaseUnit - issue a RELEASE UNIT command to a SCSI device** This routine issues a RELEASE UNIT command to a specified SCSI device.** RETURNS: OK, or ERROR if the command fails.*/STATUS scsiReleaseUnit ( SCSI_SEQ_DEV *pScsiSeqDev /* ptr to SCSI sequential device */ ) { SCSI_COMMAND releaseUnitCommand; /* SCSI command byte array */ SCSI_TRANSACTION scsiXaction; /* info on a SCSI transaction */ SCSI_PHYS_DEV *pScsiPhysDev; /* ptr to SCSI physical device */ STATUS status; /* status of transaction */ SCSI_DEBUG_MSG ("scsiReleaseUnit:\n", 0, 0, 0, 0, 0, 0); pScsiPhysDev = pScsiSeqDev->pScsiPhysDev; releaseUnitCommand[0] = SCSI_OPCODE_RELEASE; releaseUnitCommand[1] = (UINT8) 0; releaseUnitCommand[2] = (UINT8) 0; releaseUnitCommand[3] = (UINT8) 0; releaseUnitCommand[4] = (UINT8) 0; releaseUnitCommand[5] = (UINT8) 0; scsiXaction.cmdAddress = releaseUnitCommand; scsiXaction.cmdLength = SCSI_GROUP_0_CMD_LENGTH; scsiXaction.dataAddress = (UINT8 *) NULL; scsiXaction.dataDirection = O_WRONLY; scsiXaction.dataLength = 0; scsiXaction.addLengthByte = NULL; scsiXaction.cmdTimeout = SCSI_TIMEOUT_5SEC; scsiXaction.tagType = SCSI_TAG_DEFAULT; scsiXaction.priority = SCSI_THREAD_TASK_PRIORITY; status = (*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction); return (status); }/********************************************************************************* scsiLoadUnit - issue a LOAD/UNLOAD command to a SCSI device** This routine issues a LOAD/UNLOAD command to a specified SCSI device.** RETURNS: OK, or ERROR if the command fails.*/STATUS scsiLoadUnit ( SCSI_SEQ_DEV * pScsiSeqDev, /* ptr to SCSI physical device */ BOOL load, /* TRUE=load, FALSE=unload */ BOOL reten, /* TRUE=retention and unload */ BOOL eot /* TRUE=end of tape and unload */ ) { SCSI_COMMAND loadCommand; /* SCSI command byte array */ SCSI_TRANSACTION scsiXaction; /* info on a SCSI transaction */ SCSI_PHYS_DEV *pScsiPhysDev; /* ptr to SCSI physical device */ STATUS status; /* status of transaction */ SCSI_DEBUG_MSG ("scsiLoadUnit:\n", 0, 0, 0, 0, 0, 0); pScsiPhysDev = pScsiSeqDev->pScsiPhysDev; loadCommand[0] = SCSI_OPCODE_LOAD_UNLOAD; loadCommand[1] = (UINT8) 0; loadCommand[2] = (UINT8) 0; loadCommand[3] = (UINT8) 0; /* * Check for load, retension and eot (TRUE/FALSE) conditions. * Byte4 bit2 of CDB: eot * Byte4 bit1 of CDB: reten * Byte4 bit0 of CDB: load */ if (load && eot) /* invalid condition */ return (ERROR); if (load) loadCommand[4] = (UINT8) 1; else /* unload */ { loadCommand[4] = (UINT8) 0; if (eot) loadCommand[4] |= (0x1 << 2); } if (reten) loadCommand[4] |= (0x1 << 1); loadCommand[5] = (UINT8) 0; scsiXaction.cmdAddress = loadCommand; scsiXaction.cmdLength = SCSI_GROUP_0_CMD_LENGTH; scsiXaction.dataAddress = (UINT8 *) NULL; scsiXaction.dataDirection = O_WRONLY; scsiXaction.dataLength = 0; scsiXaction.addLengthByte = NULL; scsiXaction.cmdTimeout = SCSI_TIMEOUT_5SEC * 10; scsiXaction.tagType = SCSI_TAG_DEFAULT; scsiXaction.priority = SCSI_THREAD_TASK_PRIORITY; status = (*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction); return (status); }/********************************************************************************* scsiWrtFileMarks - write file marks to a SCSI sequential device** This routine writes file marks to a specified physical device.** RETURNS: OK, or ERROR if the file mark cannot be written.*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -