📄 scsi1lib.c
字号:
{ errnoSet (S_scsiLib_NO_CONTROLLER); printErr ("No SCSI controller specified.\n"); return (ERROR); } } (pScsiCtrl->scsiBusReset) (pScsiCtrl); return (OK); } }/********************************************************************************* scsiDevSelect - call the scsiDevSelect routine in the SCSI_CTRL structure** This routine is not intended to be called directly by users, but rather* by other routines in scsiLib. It merely calls a driver-specific routine* to select the desired SCSI physical device.** RETURNS: OK if device was successfully selected, otherwise ERROR.*/LOCAL STATUS scsiDevSelect ( SCSI_PHYS_DEV *pScsiPhysDev, /* ptr to SCSI physical device */ SCSI_TRANSACTION *pScsiXaction /* ptr to SCSI transaction info */ ) { return ((*pScsiPhysDev->pScsiCtrl->scsiDevSelect) (pScsiPhysDev, pScsiXaction)); }/********************************************************************************* scsi1PhaseNameGet - get the name of a specified SCSI phase** This routine returns a pointer to a string which is the name of the SCSI* phase input as an integer. It's primarily used to improve readability of* debugging messages.** RETURNS: A pointer to a string naming the SCSI phase input** NOMANUAL*/LOCAL char *scsi1PhaseNameGet ( int scsiPhase /* phase whose name to look up */ ) { static char *phaseNameArray [] = { "DATA_OUT", "DATA_IN ", "COMMAND ", "STATUS ", "UNDEF(4)", "UNDEF(5)", "MSG_OUT ", "MSG_IN " }; return ((scsiPhase < SCSI_DATA_OUT_PHASE || scsiPhase > SCSI_MSG_IN_PHASE) ? "UNKNOWN " : phaseNameArray [scsiPhase]); }/********************************************************************************* scsi1CmdBuild - fills in the fields of a SCSI command descriptor block** Typically, this routine is not called directly by the user, but by other* routines in scsiLib. It fills in fields of a SCSI-command descriptor block* based on the input parameters. The field layouts vary based on the command* group, which is determined from the `opCode'.** RETURNS: ERROR if vendor-unique command group or out-of-bounds parameter,* otherwise OK.** NOMANUAL*/LOCAL STATUS scsi1CmdBuild ( SCSI_COMMAND scsiCmd, /* command to be built */ int *pCmdLength, /* ptr to command length variable */ UINT8 opCode, /* SCSI opCode for command */ int LUN, /* logical unit number for command */ BOOL relAdrs, /* whether to set relative address bit */ int logBlockAdrs, /* logical block address */ int xferLength, /* number of blocks or bytes to xfer */ UINT8 controlByte /* control byte for command */ ) { FAST int groupCode = (int) (opCode >> 5); FAST int cmdLength; /* array with the length of a SCSI command indexed by its group code * (NONE == vendor unique) */ LOCAL int scsiCmdLength [8] = { SCSI_GROUP_0_CMD_LENGTH, SCSI_GROUP_1_CMD_LENGTH, NONE, NONE, NONE, SCSI_GROUP_5_CMD_LENGTH, NONE, NONE }; if ((*pCmdLength = cmdLength = scsiCmdLength [groupCode]) == NONE) return (ERROR); if ((groupCode == 0) && (logBlockAdrs > 0x1fffff || xferLength > 0xff)) return (ERROR); else if (xferLength > 0xffff) return (ERROR); scsiCmd[0] = opCode; scsiCmd[1] = (UINT8) ((LUN & 0x7) << 5); switch (groupCode) { case 0: scsiCmd[1] |= (UINT8) ((logBlockAdrs >> 16) & 0x1f); scsiCmd[2] = (UINT8) ((logBlockAdrs >> 8) & 0xff); scsiCmd[3] = (UINT8) ((logBlockAdrs ) & 0xff); scsiCmd[4] = (UINT8) xferLength; scsiCmd[5] = controlByte; break; case 1: case 5: scsiCmd[1] |= (UINT8) (relAdrs ? 1 : 0); scsiCmd[2] = (UINT8) ((logBlockAdrs >> 24) & 0xff); scsiCmd[3] = (UINT8) ((logBlockAdrs >> 16) & 0xff); scsiCmd[4] = (UINT8) ((logBlockAdrs >> 8) & 0xff); scsiCmd[5] = (UINT8) ((logBlockAdrs ) & 0xff); scsiCmd[6] = (UINT8) 0; if (groupCode == 5) { scsiCmd[7] = (UINT8) 0; scsiCmd[8] = (UINT8) 0; } scsiCmd [cmdLength - 3] = (UINT8) ((xferLength >> 8) & 0xff); scsiCmd [cmdLength - 2] = (UINT8) ((xferLength ) & 0xff); scsiCmd [cmdLength - 1] = controlByte; break; } return (OK); }/********************************************************************************* scsi1TestUnitRdy - issue a TEST_UNIT_READY command to a SCSI device** This routine issues a TEST_UNIT_READY command to a specified SCSI device.** RETURNS: OK, or ERROR if the command fails.*/LOCAL STATUS scsi1TestUnitRdy ( SCSI_PHYS_DEV *pScsiPhysDev /* ptr to SCSI physical device */ ) { SCSI_COMMAND testUnitRdyCommand; /* SCSI command byte array */ SCSI_TRANSACTION scsiXaction; /* info on a SCSI transaction */ SCSI_DEBUG_MSG ("scsiTestUnitRdy:\n", 0, 0, 0, 0, 0, 0); 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; return ((*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction)); }/********************************************************************************* scsiStatusCheck - called by filesystems before doing open()'s or creat()'s** This routine issues a TEST_UNIT_READY command to a SCSI device to detect a* medium change.** RETURNS: OK or ERROR.*/LOCAL STATUS scsiStatusCheck ( BLK_DEV *pBlkDev /* ptr to a block 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 */ pScsiPhysDev = ((SCSI_BLK_DEV *) pBlkDev)->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; (*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction); if ((pScsiPhysDev->lastSenseKey != SCSI_SENSE_KEY_NO_SENSE) && (pScsiPhysDev->lastSenseKey != SCSI_SENSE_KEY_UNIT_ATTENTION)) { SCSI_DEBUG_MSG ("scsiStatusCheck returning ERROR, last Sense = %x\n", pScsiPhysDev->lastSenseKey, 0, 0, 0, 0, 0); return (ERROR); } else return (OK); }/********************************************************************************* scsi1FormatUnit - issue a FORMAT_UNIT command to a SCSI device** This routine issues a FORMAT_UNIT command to a specified SCSI device.** RETURNS: OK, or ERROR if the command fails.*/LOCAL STATUS scsi1FormatUnit ( SCSI_PHYS_DEV *pScsiPhysDev,/* ptr to SCSI physical device */ BOOL cmpDefectList, /* whether defect list is complete */ int defListFormat, /* defect list format */ int vendorUnique, /* vendor unique byte */ int interleave, /* interleave factor */ char *buffer, /* ptr to input data buffer */ int bufLength /* length of buffer in bytes */ ) { SCSI_COMMAND formatUnitCommand; /* SCSI command byte array */ SCSI_TRANSACTION scsiXaction; /* info on a SCSI transaction */ SCSI_DEBUG_MSG ("scsiFormatUnit:\n", 0, 0, 0, 0, 0, 0); formatUnitCommand[0] = SCSI_OPCODE_FORMAT_UNIT; formatUnitCommand[1] = (UINT8) ((pScsiPhysDev->scsiDevLUN & 0x7) << 5); if (buffer != (char *) NULL) { formatUnitCommand[1] |= SCSI_FORMAT_DATA_BIT; if (cmpDefectList) formatUnitCommand[1] |= SCSI_COMPLETE_LIST_BIT; formatUnitCommand[1] |= (defListFormat & 0x07); } formatUnitCommand[2] = (UINT8) vendorUnique; formatUnitCommand[3] = (UINT8) ((interleave >> 8) & 0xff); formatUnitCommand[4] = (UINT8) ((interleave ) & 0xff); formatUnitCommand[5] = (UINT8) 0; scsiXaction.cmdAddress = formatUnitCommand; scsiXaction.cmdLength = SCSI_GROUP_0_CMD_LENGTH; scsiXaction.dataAddress = (UINT8 *) buffer; scsiXaction.dataDirection = O_WRONLY; scsiXaction.dataLength = bufLength; scsiXaction.addLengthByte = NONE; scsiXaction.cmdTimeout = SCSI_TIMEOUT_FULL; return ((*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction)); }/********************************************************************************* scsi1Inquiry - issue an INQUIRY command to a SCSI device** This routine issues an INQUIRY command to a specified SCSI device.** RETURNS: OK, or ERROR if the command fails.*/LOCAL STATUS scsi1Inquiry ( 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 inquiryCommand; /* SCSI command byte array */ SCSI_TRANSACTION scsiXaction; /* info on a SCSI transaction */ SCSI_DEBUG_MSG ("scsiInquiry:\n", 0, 0, 0, 0, 0, 0); if (scsiCmdBuild (inquiryCommand, &scsiXaction.cmdLength, SCSI_OPCODE_INQUIRY, pScsiPhysDev->scsiDevLUN, FALSE, 0, bufLength, (UINT8) 0) == ERROR) return (ERROR); scsiXaction.cmdAddress = inquiryCommand; scsiXaction.dataAddress = (UINT8 *) buffer; scsiXaction.dataDirection = O_RDONLY; scsiXaction.dataLength = bufLength; scsiXaction.addLengthByte = INQUIRY_ADD_LENGTH_BYTE; scsiXaction.cmdTimeout = SCSI_TIMEOUT_5SEC; return ((*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction)); }/********************************************************************************* scsi1ModeSelect - issue a MODE_SELECT command to a SCSI device** This routine issues a MODE_SELECT command to a specified SCSI device.** RETURNS: OK, or ERROR if the command fails.*/LOCAL STATUS scsi1ModeSelect ( SCSI_PHYS_DEV *pScsiPhysDev,/* ptr to SCSI physical device */ int pageFormat, /* value of the page format bit (0-1) */ int saveParams, /* value of the save parameters bit (0-1) */ char *buffer, /* ptr to output data buffer */ int bufLength /* length of buffer in bytes */ ) { SCSI_COMMAND modeSelectCommand; /* SCSI command byte array */ SCSI_TRANSACTION scsiXaction; /* info on a SCSI transaction */ int tempLBAField; /* "logical block address" field */ SCSI_DEBUG_MSG ("scsiModeSelect:\n", 0, 0, 0, 0, 0, 0); tempLBAField = (pageFormat ? (1 << 20) : 0) | (saveParams ? (1 << 16) : 0); if (scsiCmdBuild (modeSelectCommand, &scsiXaction.cmdLength, SCSI_OPCODE_MODE_SELECT, pScsiPhysDev->scsiDevLUN, FALSE, tempLBAField, min (0xff, bufLength), (UINT8) 0) == ERROR) return (ERROR); scsiXaction.cmdAddress = modeSelectCommand; scsiXaction.dataAddress = (UINT8 *) buffer; scsiXaction.dataDirection = O_WRONLY; scsiXaction.dataLength = min (0xff, bufLength); scsiXaction.addLengthByte = NONE; scsiXaction.cmdTimeout = SCSI_TIMEOUT_5SEC; return ((*pScsiPhysDev->pScsiCtrl->scsiTransact) (pScsiPhysDev, &scsiXaction)); }/********************************************************************************* scsi1ModeSense - issue a MODE_SENSE command to a SCSI device** This routine issues a MODE_SENSE command to a specified SCSI device.** RETURNS: OK, or ERROR if the command fails.*/LOCAL STATUS scsi1ModeSense ( SCSI_PHYS_DEV *pScsiPhysDev,/* ptr to SCSI physical device */ int pageControl, /* value of the page control field (0-3) */ int pageCode, /* value of the page code field (0-0x3f) */ char *buffer, /* ptr to input data buffer */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -