📄 scsi1lib.c
字号:
int bufLength /* length of buffer in bytes */ ) { SCSI_COMMAND modeSenseCommand; /* SCSI command byte array */ SCSI_TRANSACTION scsiXaction; /* info on a SCSI transaction */ SCSI_DEBUG_MSG ("scsiModeSense:\n", 0, 0, 0, 0, 0, 0); if (scsiCmdBuild (modeSenseCommand, &scsiXaction.cmdLength, SCSI_OPCODE_MODE_SENSE, pScsiPhysDev->scsiDevLUN, FALSE, 0, min (0xff, bufLength), (UINT8) 0) == ERROR) return (ERROR); modeSenseCommand [2] = (UINT8) ((pageControl << 6) | pageCode); scsiXaction.cmdAddress = modeSenseCommand; scsiXaction.dataAddress = (UINT8 *) buffer; scsiXaction.dataDirection = O_RDONLY; scsiXaction.dataLength = min (0xff, bufLength); scsiXaction.addLengthByte = MODE_SENSE_ADD_LENGTH_BYTE; scsiXaction.cmdTimeout = SCSI_TIMEOUT_5SEC; return ((*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction)); }/********************************************************************************* scsi1ReadCapacity - issue a READ_CAPACITY command to a SCSI device** This routine issues a READ_CAPACITY command to a specified SCSI device.** RETURNS: OK, or ERROR if the command fails.*/LOCAL STATUS scsi1ReadCapacity ( SCSI_PHYS_DEV *pScsiPhysDev,/* ptr to SCSI physical device */ int *pLastLBA, /* where to return last logical block address */ int *pBlkLength /* where to return block length */ ) { SCSI_COMMAND readCapCommand; /* SCSI command byte array */ RD_CAP_DATA readCapData; /* data structure for results */ SCSI_TRANSACTION scsiXaction; /* info on a SCSI transaction */ SCSI_DEBUG_MSG ("scsiReadCapacity:\n", 0, 0, 0, 0, 0, 0); if (scsiCmdBuild (readCapCommand, &scsiXaction.cmdLength, SCSI_OPCODE_READ_CAPACITY, pScsiPhysDev->scsiDevLUN, FALSE, 0, 0, (UINT8) 0) == ERROR) return (ERROR); scsiXaction.cmdAddress = readCapCommand; scsiXaction.dataAddress = (UINT8 *) &readCapData; scsiXaction.dataDirection = O_RDONLY; scsiXaction.dataLength = sizeof (readCapData); scsiXaction.addLengthByte = NONE; scsiXaction.cmdTimeout = SCSI_TIMEOUT_5SEC; if ((*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction) == ERROR) return (ERROR); else { *pLastLBA = readCapData.lastLogBlkAdrs; *pBlkLength = readCapData.blkLength; SCSI_SWAB (pLastLBA, sizeof (*pLastLBA)); SCSI_SWAB (pBlkLength, sizeof (*pBlkLength)); return (OK); } }/********************************************************************************* scsi1RdSecs - read sector(s) from a SCSI block device** This routine reads the specified physical sector(s) from a specified* physical device.** RETURNS: OK, or ERROR if the sector cannot be read.*/LOCAL STATUS scsi1RdSecs ( SCSI_BLK_DEV *pScsiBlkDev, /* ptr to SCSI block device info */ int sector, /* sector number to read */ int numSecs, /* total sectors to read */ char *buffer /* ptr to input data buffer */ ) { SCSI_COMMAND readCommand; /* SCSI command byte array */ SCSI_TRANSACTION scsiXaction; /* info on a SCSI transaction */ SCSI_PHYS_DEV *pScsiPhysDev = pScsiBlkDev->pScsiPhysDev; int startSec = sector + pScsiBlkDev->blockOffset; SCSI_DEBUG_MSG ("scsiRdSecs:\n", 0, 0, 0, 0, 0, 0); if (startSec <= 0x1FFFFF && numSecs <= 256) { /* build a 21 bit logical block address 'O_RDONLY' command */ if (scsiCmdBuild (readCommand, &scsiXaction.cmdLength, SCSI_OPCODE_READ, pScsiPhysDev->scsiDevLUN, FALSE, startSec, (numSecs == 256 ? 0 : numSecs), (UINT8) 0) == ERROR) return (ERROR); } else { /* build a 32 bit logical block address 'READ_EXTENDED' command */ if (scsiCmdBuild (readCommand, &scsiXaction.cmdLength, SCSI_OPCODE_READ_EXT, pScsiPhysDev->scsiDevLUN, FALSE, startSec, numSecs, (UINT8) 0) == ERROR) return (ERROR); } scsiXaction.cmdAddress = readCommand; scsiXaction.dataAddress = (UINT8 *) buffer; scsiXaction.dataDirection = O_RDONLY; scsiXaction.dataLength = numSecs * pScsiPhysDev->blockSize; scsiXaction.addLengthByte = NONE; if (numSecs < 2000) scsiXaction.cmdTimeout = SCSI_TIMEOUT_5SEC + (SCSI_TIMEOUT_1SEC * numSecs); else scsiXaction.cmdTimeout = SCSI_TIMEOUT_FULL; return ((*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction)); }/********************************************************************************* scsi1WrtSecs - write sector(s) to a SCSI block device** This routine writes the specified physical sector(s) to a specified physical* device.** RETURNS: OK, or ERROR if the sector cannot be written.*/LOCAL STATUS scsi1WrtSecs ( SCSI_BLK_DEV *pScsiBlkDev, /* ptr to SCSI block device info */ int sector, /* sector number to write */ int numSecs, /* total sectors to write */ char *buffer /* ptr to input data buffer */ ) { SCSI_COMMAND writeCommand; /* SCSI command byte array */ SCSI_TRANSACTION scsiXaction; /* info on a SCSI transaction */ SCSI_PHYS_DEV *pScsiPhysDev = pScsiBlkDev->pScsiPhysDev; int startSec = sector + pScsiBlkDev->blockOffset; SCSI_DEBUG_MSG ("scsiWrtSecs:\n", 0, 0, 0, 0, 0, 0); if (startSec <= 0x1FFFFF && numSecs <= 256) { /* build a 21 bit logical block address 'O_WRONLY' command */ if (scsiCmdBuild (writeCommand, &scsiXaction.cmdLength, SCSI_OPCODE_WRITE, pScsiPhysDev->scsiDevLUN, FALSE, startSec, (numSecs == 256 ? 0 : numSecs), (UINT8) 0) == ERROR) { return (ERROR); } } else { /* build a 32 bit logical block address 'WRITE_EXTENDED' command */ if (scsiCmdBuild (writeCommand, &scsiXaction.cmdLength, SCSI_OPCODE_WRITE_EXT, pScsiPhysDev->scsiDevLUN, FALSE, startSec, numSecs, (UINT8) 0) == ERROR) return (ERROR); } scsiXaction.cmdAddress = writeCommand; scsiXaction.dataAddress = (UINT8 *) buffer; scsiXaction.dataDirection = O_WRONLY; scsiXaction.dataLength = numSecs * pScsiPhysDev->blockSize; scsiXaction.addLengthByte = NONE; if (numSecs < 2000) scsiXaction.cmdTimeout = SCSI_TIMEOUT_5SEC + (SCSI_TIMEOUT_1SEC * numSecs); else scsiXaction.cmdTimeout = SCSI_TIMEOUT_FULL; return ((*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction)); }/********************************************************************************* scsi1ReqSense - issue a REQUEST_SENSE command to a device and read the results** This routine issues a REQUEST_SENSE command to a specified SCSI device and* read the results.** RETURNS: OK, or ERROR if the command fails.*/LOCAL STATUS scsi1ReqSense ( SCSI_PHYS_DEV *pScsiPhysDev,/* ptr to SCSI physical device */ char *buffer, /* ptr to input data buffer */ int bufLength /* length of buffer in bytes */ ) { SCSI_COMMAND reqSenseCommand; /* SCSI command byte array */ SCSI_TRANSACTION scsiXaction; /* info on a SCSI transaction */ SCSI_DEBUG_MSG ("scsiReqSense:\n", 0, 0, 0, 0, 0, 0); if (scsiCmdBuild (reqSenseCommand, &scsiXaction.cmdLength, SCSI_OPCODE_REQUEST_SENSE, pScsiPhysDev->scsiDevLUN, FALSE, 0, bufLength, (UINT8) 0) == ERROR) return (ERROR); scsiXaction.cmdAddress = reqSenseCommand; scsiXaction.dataAddress = (UINT8 *) buffer; scsiXaction.dataDirection = O_RDONLY; scsiXaction.dataLength = bufLength; scsiXaction.addLengthByte = REQ_SENSE_ADD_LENGTH_BYTE; scsiXaction.cmdTimeout = SCSI_TIMEOUT_5SEC; return ((*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction)); }/********************************************************************************* scsiPhaseSequence - manage all phases of a single SCSI bus sequence** This routine is called by scsiTransact after a device has been successfully* selected. It repeated calls the appropriate routine to detect the current* SCSI bus phase. It takes whatever action is specified in the supplied* SCSI_TRANSACTION structure, usually calling the appropiate routines to* input or output bytes to the device.** RETURNS: OK, or ERROR if not successful for any reason.*/LOCAL STATUS scsiPhaseSequence ( SCSI_PHYS_DEV *pScsiPhysDev, /* ptr to the target device */ SCSI_TRANSACTION *pScsiXaction /* ptr to the transaction info */ ) { SCSI_CTRL *pScsiCtrl; /* SCSI controller info for device */ STATUS status; /* routine return status */ int scsiPhase; /* passed to scsiBusPhaseGet routine */ UINT8 msgIn [MAX_MSG_IN_BYTES]; /* message returned from the SCSI device */ UINT8 *pMsgIn; /* ptr to next dest. for a message in */ BOOL transactionComplete; /* set TRUE upon 'disconn' or 'comm complete' */ pScsiCtrl = pScsiPhysDev->pScsiCtrl; /* save current command context requested */ pScsiPhysDev->pScsiXaction = pScsiXaction; transactionComplete = FALSE; if ((status = scsiDevSelect (pScsiPhysDev, pScsiXaction)) == ERROR) { SCSI_DEBUG_MSG ("scsiPhaseSequence: Unable to select device.\n", 0, 0, 0, 0, 0, 0); return (ERROR); } do { if ((*pScsiCtrl->scsiBusPhaseGet) (pScsiCtrl, pScsiXaction->cmdTimeout, &scsiPhase) != OK) { SCSI_DEBUG_MSG ("scsiBusPhaseGet returned ERROR.\n", 0, 0, 0, 0, 0, 0); return (ERROR); } phaseSwitch: switch (scsiPhase) { case SCSI_DATA_OUT_PHASE: status = (*pScsiCtrl->scsiBytesOut) (pScsiPhysDev, pScsiXaction->dataAddress, pScsiXaction->dataLength, scsiPhase); if (status == ERROR) { return (ERROR); } break; case SCSI_DATA_IN_PHASE: { int addLengthByte = pScsiXaction->addLengthByte; int dataLength = pScsiXaction->dataLength; UINT8 *dataAddress = pScsiXaction->dataAddress; if ((addLengthByte == NONE) || (dataLength <= (addLengthByte + 1))) { status = (*pScsiCtrl->scsiBytesIn) (pScsiPhysDev, dataAddress, dataLength, scsiPhase); if (status == ERROR) { return (ERROR); } } else { status = (*pScsiCtrl->scsiBytesIn) (pScsiPhysDev, dataAddress, addLengthByte + 1, scsiPhase); if (status == ERROR) { return (ERROR); } if ((*pScsiCtrl->scsiBusPhaseGet) (pScsiCtrl, 0, &scsiPhase) != OK) { SCSI_DEBUG_MSG ("scsiBusPhaseGet returned ERROR.\n", 0, 0, 0, 0, 0, 0); return (ERROR); } if (scsiPhase != SCSI_DATA_IN_PHASE) goto phaseSwitch; status = (*pScsiCtrl->scsiBytesIn) (pScsiPhysDev, dataAddress + addLengthByte + 1, min (dataAddress [addLengthByte], dataLength - (addLengthByte + 1)), scsiPhase); if (status == ERROR) { return (ERROR); } } break; } case SCSI_COMMAND_PHASE: status = (*pScsiCtrl->scsiBytesOut) (pScsiPhysDev, pScsiXaction->cmdAddress, pScsiXaction->cmdLength, scsiPhase); if (status != OK) { return (ERROR); } break; case SCSI_STATUS_PHASE: status = (*pScsiCtrl->scsiBytesIn) (pScsiPhysDev, &pScsiXaction->statusByte, sizeof (pScsiXaction->statusByte), scsiPhase); if (status == ERROR) { return (ERROR); } break; case SCSI_MSG_OUT_PHASE: status = (*pScsiCtrl->scsiBytesOut) (pScsiPhysDev, pScsiPhysDev->msgOutArray, pScsiPhysDev->msgLength, scsiPhase); if (status == ERROR) { return (ERROR); } else pScsiPhysDev->msgLength = 0; break; case SCSI_MSG_IN_PHASE: pMsgIn = msgIn; status = (*pScsiCtrl->scsiBytesIn) (p
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -