📄 scsi1lib.c
字号:
int ix; /* loop index */ /* initialize controller mutual exclusion semaphore */ if (semMInit (&pScsiCtrl->ctrlMutexSem, scsiCtrlMutexOptions) == ERROR) { printErr ("scsi1CtrlInit: semMInit of ctrlMutexSem failed.\n"); return (ERROR); } /* initialize controller interrupt waiting semaphore */ if (semBInit (&pScsiCtrl->ctrlSyncSem, scsiCtrlSemOptions, SEM_EMPTY) == ERROR) { printErr ("scsi1CtrlInit: semBInit of ctrlSyncSem failed.\n"); return (ERROR); } /* initialize the scsiBusReset to NULL (set by individual drivers) */ pScsiCtrl->scsiBusReset = (VOIDFUNCPTR) NULL; /* initialize the scsiPriority to NONE (set by individual drivers) */ pScsiCtrl->scsiPriority = NONE; /* initialize array of ptrs to SCSI_PHYS_DEV structures to NULL */ for (ix = 0; ix < MAX_SCSI_PHYS_DEVS; ix++) { pScsiCtrl->physDevArr [ix] = (SCSI_PHYS_DEV *) NULL; } return (OK); }/********************************************************************************* scsi1PhysDevDelete - delete a SCSI physical device structure** This routine deletes a specified SCSI physical device structure.** RETURNS: OK, or ERROR if `pScsiPhysDev' is NULL or SCSI_BLK_DEVs have* been created on the device.*/LOCAL STATUS scsi1PhysDevDelete ( FAST SCSI_PHYS_DEV *pScsiPhysDev /* ptr to SCSI physical device info */ ) { FAST SCSI_CTRL *pScsiCtrl; STATUS status; if ((pScsiPhysDev == (SCSI_PHYS_DEV *) NULL) || (pScsiPhysDev->pScsiBlkDev != (SCSI_BLK_DEV *) NULL)) return (ERROR); /* Reset target if the sync capacity is existing */ if ( pScsiPhysDev->syncXfer == TRUE ) { SCSI_SYNC_AGREEMENT syncAgreement; /* Send a sync message for async protocol */ status = scsiSyncTarget(pScsiPhysDev, pScsiPhysDev->syncXferPeriod , 0, &syncAgreement); /* Clear the next check status */ status = scsiTestUnitRdy(pScsiPhysDev); } pScsiCtrl = pScsiPhysDev->pScsiCtrl; pScsiCtrl->physDevArr [(pScsiPhysDev->scsiDevBusId << 3) | pScsiPhysDev->scsiDevLUN] = (SCSI_PHYS_DEV *) NULL; if (pScsiPhysDev->pReqSenseData != NULL) (void) free ((char *) pScsiPhysDev->pReqSenseData); (void) free ((char *) pScsiPhysDev); return (OK); }/********************************************************************************* scsi1PhysDevCreate - create a SCSI physical device structure** This routine enables access to a SCSI device and must be invoked first.* It should be called once for each physical device on the SCSI bus.** If `reqSenseLength' is specified as NULL (0), one or more REQUEST_SENSE* commands are issued to the device to determine the number of bytes of* sense data it typically returns. Note that if the device returns variable* amounts of sense data depending on its state, consult the device manual * to determine the maximum amount of sense data that can be returned.** If `devType' is specified as NONE (-1), an INQUIRY command is issued to* determine the device type, with the added benefit of acquiring the device's* make and model number. The scsiShow() routine displays this information.* Common values of `devType' can be found in scsiLib.h or in the SCSI* specification.** If `numBlocks' or `blockSize' are specified as NULL (0), a READ_CAPACITY* command is issued to determine those values. This will occur* only for device types which support READ_CAPACITY.** RETURNS: A pointer to the created SCSI_PHYS_DEV structure, or NULL if the* routine is unable to create the physical device structure.*/LOCAL SCSI_PHYS_DEV *scsi1PhysDevCreate ( SCSI_CTRL *pScsiCtrl, /* ptr to SCSI controller info */ int devBusId, /* device's SCSI bus ID */ int devLUN, /* device's logical unit number */ int reqSenseLength, /* length of REQUEST SENSE data dev returns */ int devType, /* type of SCSI device */ BOOL removable, /* whether medium is removable */ int numBlocks, /* number of blocks on device */ int blockSize /* size of a block in bytes */ ) { SCSI_PHYS_DEV *pScsiPhysDev; /* ptr to SCSI physical dev. struct */ /* REQ SENSE data for auto-sizing */ UINT8 reqSenseData [REQ_SENSE_ADD_LENGTH_BYTE + 1]; SCSI_PHYS_DEV *pPhysDev; /* use to check if it's already created */ /* check bus ID and LUN are within limits */ if ((devBusId < SCSI_MIN_BUS_ID) || (devBusId > SCSI_MAX_BUS_ID) || (devLUN < SCSI_MIN_LUN) || (devLUN > SCSI_MAX_LUN)) { errnoSet (S_scsiLib_ILLEGAL_PARAMETER); return ((SCSI_PHYS_DEV *) NULL); } /* Check if this device was already create and if it's support sync * capacity. */ pPhysDev = scsiPhysDevIdGet (pScsiCtrl,devBusId,devLUN); if (pPhysDev != (SCSI_PHYS_DEV *)NULL) { errnoSet (S_scsiLib_DEVICE_EXIST); return ((SCSI_PHYS_DEV *) NULL); } /* create a SCSI physical device structure */ pScsiPhysDev = (SCSI_PHYS_DEV *) calloc (1, sizeof (*pScsiPhysDev)); if (pScsiPhysDev == NULL) return ((SCSI_PHYS_DEV *) NULL); /* initialize device mutual exclusion semaphore */ if (semMInit (&pScsiPhysDev->devMutexSem, scsiPhysDevMutexOptions) == ERROR) { SCSI_DEBUG_MSG ("scsiPhysDevCreate: semMInit of devMutexSem failed.\n", 0, 0, 0, 0, 0, 0); (void) free ((char *) pScsiPhysDev); return ((SCSI_PHYS_DEV *) NULL); } /* initialize device interrupt waiting semaphore */ if (semBInit (&pScsiPhysDev->devSyncSem, scsiPhysDevSemOptions, SEM_EMPTY) == ERROR) { SCSI_DEBUG_MSG ("scsiPhysDevCreate: semBInit of devSyncSem failed.\n", 0, 0, 0, 0, 0, 0); (void) free ((char *) pScsiPhysDev); return ((SCSI_PHYS_DEV *) NULL); } /* initialize miscellaneous fields in the SCSI_PHYS_DEV struct */ pScsiPhysDev->scsiDevBusId = devBusId; pScsiPhysDev->scsiDevLUN = devLUN; pScsiPhysDev->devStatus = IDLE; (*pScsiCtrl->scsiSelTimeOutCvt) (pScsiCtrl, scsiSelectTimeout, &pScsiPhysDev->selTimeOut); pScsiPhysDev->pScsiCtrl = pScsiCtrl; pScsiCtrl->physDevArr [(devBusId << 3) | devLUN] = pScsiPhysDev; /* initialize block device list */ semMInit (&pScsiPhysDev->blkDevList.listMutexSem, blkDevListMutexOptions); lstInit (&pScsiPhysDev->blkDevList.blkDevNodes); if (reqSenseLength == 0) { /* determine if device uses Extended Sense Data Format */ if (scsiReqSense (pScsiPhysDev, (char *) reqSenseData, 1) == ERROR) { SCSI_DEBUG_MSG ("scsiPhysDevCreate: REQUEST SENSE failed.\n", 0, 0, 0, 0, 0, 0); (void) scsiPhysDevDelete (pScsiPhysDev); return ((SCSI_PHYS_DEV *) NULL); } SCSI_DEBUG_MSG ("scsiPhysDevCreate: reqSenseData[0] = %x\n", reqSenseData[0], 0, 0, 0, 0, 0); if ((reqSenseData[0] & SCSI_SENSE_DATA_CLASS) != SCSI_EXT_SENSE_CLASS) { /* device uses Nonextended Sense Data Format */ pScsiPhysDev->extendedSense = FALSE; pScsiPhysDev->reqSenseDataLength = NON_EXT_SENSE_DATA_LENGTH; } else if ((reqSenseData[0] & SCSI_SENSE_DATA_CODE) != SCSI_EXT_SENSE_CODE) { /* device uses Unknown Sense Data Format */ errnoSet (S_scsiLib_DEV_UNSUPPORTED); SCSI_DEBUG_MSG ("scsiPhysDevCreate: Unknown Sense Data Format ", 0, 0, 0, 0, 0, 0); SCSI_DEBUG_MSG ("(device not supported)\n", 0, 0, 0, 0, 0, 0); (void) scsiPhysDevDelete (pScsiPhysDev); return ((SCSI_PHYS_DEV *) NULL); } else { /* device uses Extended Sense Data Format */ if (scsiReqSense (pScsiPhysDev, (char *) reqSenseData, REQ_SENSE_ADD_LENGTH_BYTE + 1) == ERROR) { SCSI_DEBUG_MSG ("scsiPhysDevCreate: REQUEST SENSE failed.\n", 0, 0, 0, 0, 0, 0); (void) scsiPhysDevDelete (pScsiPhysDev); return ((SCSI_PHYS_DEV *) NULL); } SCSI_DEBUG_MSG ("scsiPhysDevCreate: reqSenseData[7] = %x\n", reqSenseData[REQ_SENSE_ADD_LENGTH_BYTE], 0, 0, 0, 0, 0); pScsiPhysDev->extendedSense = TRUE; pScsiPhysDev->reqSenseDataLength = REQ_SENSE_ADD_LENGTH_BYTE + (int) reqSenseData [REQ_SENSE_ADD_LENGTH_BYTE] + 1; } } else { pScsiPhysDev->reqSenseDataLength = reqSenseLength; if (reqSenseLength == 4) pScsiPhysDev->extendedSense = FALSE; else pScsiPhysDev->extendedSense = TRUE; } if ((pScsiPhysDev->pReqSenseData = (UINT8 *) calloc (pScsiPhysDev->reqSenseDataLength, sizeof (UINT8))) == NULL) { (void) scsiPhysDevDelete (pScsiPhysDev); return ((SCSI_PHYS_DEV *) NULL); } /* transact an INQUIRY command if devType is unspecified */ if ((devType == NONE) || (removable == NONE)) { UINT8 inquiryData [DEFAULT_INQUIRY_DATA_LENGTH]; int ix; /* do an INQUIRY command */ for (ix = 0; ix < DEFAULT_INQUIRY_DATA_LENGTH; ix++) inquiryData[ix] = (UINT8) 0;inquiryRetry: if ((scsiInquiry (pScsiPhysDev, (char *) inquiryData, sizeof (inquiryData)) == OK) && (inquiryData[0] != SCSI_LUN_NOT_PRESENT)) { pScsiPhysDev->scsiDevType = inquiryData[0]; pScsiPhysDev->removable = (BOOL) (inquiryData[1] & INQUIRY_REMOVABLE_MED_BIT); bcopy ((char *) &inquiryData[8], pScsiPhysDev->devVendorID, VENDOR_ID_LENGTH); bcopy ((char *) &inquiryData[16], pScsiPhysDev->devProductID, PRODUCT_ID_LENGTH); bcopy ((char *) &inquiryData[32], pScsiPhysDev->devRevLevel, REV_LEVEL_LENGTH); pScsiPhysDev->devVendorID [VENDOR_ID_LENGTH] = EOS; pScsiPhysDev->devProductID [PRODUCT_ID_LENGTH] = EOS; pScsiPhysDev->devRevLevel [REV_LEVEL_LENGTH] = EOS; } else if (pScsiPhysDev->resetFlag == TRUE) { pScsiPhysDev->resetFlag = FALSE; SCSI_DEBUG_MSG ("retrying scsiInquiry...\n", 0, 0, 0, 0, 0, 0); goto inquiryRetry; } else { if (inquiryData[0] == SCSI_LUN_NOT_PRESENT) { SCSI_DEBUG_MSG ("scsiPhysDevCreate: LUN not present.\n", 0, 0, 0, 0, 0, 0); errnoSet (S_scsiLib_LUN_NOT_PRESENT); } (void) scsiPhysDevDelete (pScsiPhysDev); return ((SCSI_PHYS_DEV *) NULL); } } else { pScsiPhysDev->scsiDevType = (UINT8) devType; pScsiPhysDev->removable = removable; } /* record numBlocks and blockSize in physical device */ if (((pScsiPhysDev->scsiDevType == SCSI_DEV_DIR_ACCESS) || (pScsiPhysDev->scsiDevType == SCSI_DEV_WORM) || (pScsiPhysDev->scsiDevType == SCSI_DEV_RO_DIR_ACCESS)) && ((numBlocks == 0) || (blockSize == 0))) { int lastLogBlkAdrs; int blkLength; /* do a READ_CAPACITY command */readCapRetry: if (scsiReadCapacity (pScsiPhysDev, &lastLogBlkAdrs, &blkLength) == OK) { pScsiPhysDev->numBlocks = lastLogBlkAdrs + 1; pScsiPhysDev->blockSize = blkLength; } else if (pScsiPhysDev->resetFlag == TRUE) { pScsiPhysDev->resetFlag = FALSE; SCSI_DEBUG_MSG ("retrying scsiReadCapacity...\n", 0, 0, 0, 0, 0, 0); goto readCapRetry; } else { (void) scsiPhysDevDelete (pScsiPhysDev); return ((SCSI_PHYS_DEV *) NULL); } } else { pScsiPhysDev->numBlocks = numBlocks; pScsiPhysDev->blockSize = blockSize; } return (pScsiPhysDev); }/********************************************************************************* scsi1PhysDevIdGet - return a pointer to a SCSI_PHYS_DEV structure** This routine returns a pointer to the SCSI_PHYS_DEV structure of the SCSI* physical device located at a specified bus ID (`devBusId') and logical* unit number (`devLUN') and attached to a specified SCSI controller* (`pScsiCtrl').** RETURNS: A pointer to the specified SCSI_PHYS_DEV structure, or NULL if the* structure does not exist.*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -