📄 scsiseqlib.c
字号:
scsiXaction.cmdTimeout = SCSI_TIMEOUT_5SEC; scsiXaction.tagType = SCSI_TAG_DEFAULT; scsiXaction.priority = SCSI_THREAD_TASK_PRIORITY; status = (*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction); if (status == ERROR) return (ERROR); *pMaxBlockLength = readBlkLimitData.maxBlockLength; *pMinBlockLength = readBlkLimitData.minBlockLength; SCSI_SWAB (pMaxBlockLength, sizeof (*pMaxBlockLength)); SCSI_SWAB (pMinBlockLength, sizeof (*pMinBlockLength)); return (OK); }/********************************************************************************* scsiSeqReadBlockLimits - issue a READ_BLOCK_LIMITS command to a SCSI device** This routine issues a READ_BLOCK_LIMITS command to a specified SCSI device.** RETURNS: OK, or ERROR if the command fails.*/STATUS scsiSeqReadBlockLimits ( SCSI_SEQ_DEV * pScsiSeqDev, /* ptr to SCSI sequential device */ int *pMaxBlockLength, /* where to return maximum block length */ UINT16 *pMinBlockLength /* where to return minimum block length */ ) { SCSI_PHYS_DEV * pScsiPhysDev = pScsiSeqDev->pScsiPhysDev; return (scsiReadBlockLimits (pScsiPhysDev, pMaxBlockLength, pMinBlockLength)); }/********************************************************************************* scsiCmdFill - fill the SCSI_COMMAND structure.** RETURNS: N/A.*/LOCAL VOID scsiCmdFill ( SCSI_SEQ_DEV * pScsiSeqDev, SCSI_COMMAND scsiCommand, /* scsi command structure to be filled */ BOOL commandType, /* read or write command */ BOOL fixed, /* variable or fixed */ int xferLength /* total bytes or blocks to xfer */ ) { SCSI_PHYS_DEV *pScsiPhysDev; /* ptr to SCSI physical device info */ pScsiPhysDev = pScsiSeqDev->pScsiPhysDev; if ( commandType == SCSI_READ ) scsiCommand[0] = SCSI_OPCODE_READ; else scsiCommand[0] = SCSI_OPCODE_WRITE; scsiCommand[1] = (UINT8) ((pScsiPhysDev->scsiDevLUN & 0x7) << 5); if (fixed) scsiCommand[1] |= 0x01; /* set for fixed block size */ scsiCommand[2] = (UINT8) ((xferLength >> 16) & 0xff); scsiCommand[3] = (UINT8) ((xferLength >> 8) & 0xff); scsiCommand[4] = (UINT8) (xferLength & 0xff); scsiCommand[5] = (UINT8) 0; }/********************************************************************************* scsiXactionFill - fill the SCSI_TRANSACTION structure.** RETURNS: N/A.*/LOCAL VOID scsiXactionFill ( SCSI_TRANSACTION * scsiXaction, /* scsi Transaction structure */ SCSI_COMMAND scsiCommand, /* scsi command structure */ BOOL commandType, /* read or write command */ int cmdLength, /* scsi command length */ UINT cmdTimeout, /* scsi command timeout */ int dataXferLen, /* data transfer length */ UINT8 * bufAdrs /* scsi data address */ ) { if ( commandType == SCSI_READ ) scsiXaction->dataDirection = O_RDONLY; else scsiXaction->dataDirection = O_WRONLY; scsiXaction->cmdAddress = scsiCommand; scsiXaction->cmdLength = cmdLength; scsiXaction->dataAddress = bufAdrs; scsiXaction->dataLength = dataXferLen; scsiXaction->addLengthByte = NULL; scsiXaction->cmdTimeout = cmdTimeout; scsiXaction->tagType = SCSI_TAG_DEFAULT; scsiXaction->priority = SCSI_THREAD_TASK_PRIORITY; }/********************************************************************************* scsiRdTapeFixedBlocks - reads the number of blocks specified** This routine reads the specified number of blocks from a specified* physical device. If `numBlocks' is greater than the `maxBytesLimit' field* defined in the `pScsiPhysDev' structure, then more than one SCSI transaction* is used to transfer the data.** RETURNS: Number of blocks actually read, 0 if EOF, or ERROR.*/LOCAL int scsiRdTapeFixedBlocks ( SCSI_SEQ_DEV *pScsiSeqDev, /* ptr to SCSI sequential device info */ UINT numBlocks, /* total # of blocks to be read */ char * buffer /* ptr to iput data buffer */ ) { SCSI_PHYS_DEV *pScsiPhysDev; /* ptr to SCSI physical device info */ SCSI_COMMAND readCommand; /* SCSI command byte array */ SCSI_TRANSACTION scsiXaction; /* info on a SCSI transaction */ UINT8 * bufPtr; /* ptr to input data buffer */ UINT timeout; /* scsi command timeout */ int xferLength; /* transfer length */ int nBlocks = 0; /* number of blocks read */ int xferBlocks; /* number of blocks to be xferred */ UINT blocksRead = 0; /* actual number of blocks read */ pScsiPhysDev = pScsiSeqDev->pScsiPhysDev; 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, readCommand, SCSI_READ, 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, readCommand, SCSI_READ, SCSI_GROUP_0_CMD_LENGTH, timeout, xferLength, bufPtr); if (((*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction)) == ERROR) return (ERROR); if ((blocksRead = scsiCalcDataRead (pScsiSeqDev, numBlocks)) == ERROR) return (ERROR); return (blocksRead); } else { /* determine the max number of blocks that can be transferred */ xferBlocks = (pScsiPhysDev->pScsiCtrl->maxBytesPerXfer) / (pScsiSeqDev->seqDev.sd_blkSize); while (numBlocks > 0) { scsiCmdFill (pScsiSeqDev, readCommand, SCSI_READ, 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, readCommand, SCSI_READ, SCSI_GROUP_0_CMD_LENGTH, timeout, xferLength, bufPtr); if (((*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction)) == ERROR) return (ERROR); if ((nBlocks = scsiCalcDataRead (pScsiSeqDev, numBlocks)) == ERROR) return (ERROR); numBlocks -= xferBlocks; buffer += (xferBlocks * pScsiSeqDev->seqDev.sd_blkSize); if (numBlocks <= (pScsiPhysDev->pScsiCtrl->maxBytesPerXfer / pScsiSeqDev->seqDev.sd_blkSize)) xferBlocks = numBlocks; blocksRead += nBlocks; } return (blocksRead); } }/********************************************************************************* scsiRdTapeVariableBlocks - reads the number of bytes specified** This routine reads the specified number of bytes from a specified* physical device. 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: Number of bytes actually read, 0 if EOF, or ERROR.*/LOCAL int scsiRdTapeVariableBlocks ( SCSI_SEQ_DEV *pScsiSeqDev, /* ptr to SCSI sequential device info */ UINT numBytes, /* total # of bytes to be read */ char * buffer /* ptr to input data buffer */ ) { SCSI_PHYS_DEV *pScsiPhysDev; /* ptr to SCSI physical device info */ SCSI_COMMAND readCommand; /* SCSI command byte array */ SCSI_TRANSACTION scsiXaction; /* info on a SCSI transaction */ UINT8 * bufPtr; /* ptr to input data buffer */ UINT timeout; /* scsi command timeout */ int xferLength; /* transfer length */ int nBytes; /* number of bytes read */ int maxVarBlockLimit; /* maximum variable block limit */ UINT bytesRead = 0; /* actual number of bytes read */ int readBytes; /* for multiple read transactions */ pScsiPhysDev = pScsiSeqDev->pScsiPhysDev; /* 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 (readBytes=0; numBytes > maxVarBlockLimit; numBytes -= maxVarBlockLimit, readBytes += maxVarBlockLimit) { scsiCmdFill (pScsiSeqDev, readCommand, SCSI_READ, FALSE, maxVarBlockLimit); bufPtr = (UINT8 *) buffer + readBytes; xferLength = maxVarBlockLimit; timeout = SCSI_TIMEOUT_5SEC * 50 + (maxVarBlockLimit * 10); scsiXactionFill (&scsiXaction, readCommand, SCSI_READ, SCSI_GROUP_0_CMD_LENGTH, timeout, xferLength, bufPtr); if (((*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction)) == ERROR) return (ERROR); if ((nBytes = scsiCalcDataRead (pScsiSeqDev, xferLength)) == ERROR) return (ERROR); bytesRead += nBytes; } if (numBytes > 0) { scsiCmdFill (pScsiSeqDev, readCommand, SCSI_READ, FALSE, numBytes); bufPtr = (UINT8 *) buffer + readBytes; timeout = SCSI_TIMEOUT_5SEC * 50 + (numBytes * 10); scsiXactionFill (&scsiXaction, readCommand, SCSI_READ, SCSI_GROUP_0_CMD_LENGTH, timeout, numBytes, bufPtr); if (((*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction)) == ERROR) return (ERROR); if ((nBytes = scsiCalcDataRead (pScsiSeqDev, numBytes)) == ERROR) return (ERROR); bytesRead += nBytes; } return (bytesRead); }/********************************************************************************* scsiRdTape - read bytes or blocks from a SCSI tape device** This routine reads the specified number of bytes or blocks from 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 read. ** RETURNS: Number of bytes or blocks actually read, 0 if EOF, or ERROR.*/int scsiRdTape ( SCSI_SEQ_DEV *pScsiSeqDev, /* ptr to SCSI sequential device info */ UINT count, /* total bytes or blocks to be read */ char *buffer, /* ptr to input data buffer */ BOOL fixedSize /* if variable size blocks */ ) { SCSI_PHYS_DEV *pScsiPhysDev; /* ptr to SCSI physical device info */ int dataCount; /* blocks or bytes read */ pScsiPhysDev = pScsiSeqDev->pScsiPhysDev; SCSI_DEBUG_MSG ("scsiRdTape:\n", 0, 0, 0, 0, 0, 0); /* Invalidate the request sense data */ pScsiPhysDev->pReqSenseData[0] &= 0x7f; if (fixedSize) dataCount = scsiRdTapeFixedBlocks (pScsiSeqDev, count, buffer); else dataCount = scsiRdTapeVariableBlocks (pScsiSeqDev, count, buffer); return (dataCount); }/********************************************************************************* scsiCalcDataRead - calculates the actual # of bytes read** This routine calculates the actual number of bytes or blocks read after* a read operation, by examining the request sense data if it is valid.** RETURNS: bytes or blocks read, 0 if EOF or ERROR if tape move was * unsuccessful.* * NOMANUAL*/LOCAL int scsiCalcDataRead ( SCSI_SEQ_DEV *pScsiSeqDev, /* ptr to SCSI sequential device info */ UINT numDataUnits /* total bytes or blocks to be read */ ) { SCSI_PHYS_DEV *pScsiPhysDev; /* ptr to SCSI physical device info */ int residue; /* diff between requested & xfered data */ UINT unitsRead = 0; /* actual number of bytes read */ pScsiPhysDev = pScsiSeqDev->pScsiPhysDev; /* if request sense data is valid */ if (pScsiPhysDev->pReqSenseData[0] & 0x80) { residue = (pScsiPhysDev->pReqSenseData[3] << 24) + (pScsiPhysDev->pReqSenseData[4] << 16) + (pScsiPhysDev->pReqSenseData[5] << 8) + (pScsiPhysDev->pReqSenseData[6]); if (residue < 0) unitsRead = numDataUnits; else unitsRead = numDataUnits - residue; /* Invalidate the request sense data */ pScsiPhysDev->pReqSenseData[0] = pScsiPhysDev->pReqSenseData[0] & 0x7f; /* * Check the request sense data to see if End of Filemark * or End of Medium was encountered. */ if ((pScsiPhysDev->pReqSenseData[2] & 0x40) || (pScsiPhysDev->pReqSenseData[2] & 0x80)) { /* move tape head to the beginning of filemark */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -