📄 scsi2lib.c
字号:
printf(" transfer period: %d\n", (options.minPeriod * 4)); printf(" transfer width: %s bits\n", (options.xferWidth ? "16" : "8")); printf(" maximum transfer rate: %d MB/sec\n", (options.minPeriod == 0 ? 0 : (options.xferWidth ? (250 * 2 / options.minPeriod) : (250 / options.minPeriod)))); printf(" tag type: 0x%x\n", options.tagType); printf(" maximum tags: %d\n", options.maxTags); return (OK); }/********************************************************************************* scsi2PhysDevDelete - 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 scsi2PhysDevDelete ( FAST SCSI_PHYS_DEV *pScsiPhysDev /* ptr to SCSI physical device info */ ) { FAST SCSI_CTRL *pScsiCtrl; if ((pScsiPhysDev == (SCSI_PHYS_DEV *) NULL) || (lstCount (&pScsiPhysDev->blkDevList) != 0) || (lstCount (&pScsiPhysDev->activeThreads) != 0) || (lstCount (&pScsiPhysDev->waitingThreads) != 0)) return (ERROR); pScsiCtrl = pScsiPhysDev->pScsiCtrl; pScsiCtrl->physDevArr [(pScsiPhysDev->pScsiTarget->scsiDevBusId << 3) | pScsiPhysDev->scsiDevLUN] = (SCSI_PHYS_DEV *) NULL; if (pScsiPhysDev->pReqSenseData != NULL) (void) free ((char *) pScsiPhysDev->pReqSenseData); if (pScsiPhysDev->pTagInfo != 0) (void) free ((char *) pScsiPhysDev->pTagInfo); if (pScsiPhysDev->mutexSem != 0) (void) semDelete (pScsiPhysDev->mutexSem); (void) free ((char *) pScsiPhysDev); return (OK); }/********************************************************************************* scsi2PhysDevCreate - 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.** An INQUIRY command is issued to determine information about the device* including its type, make and model number, and its ability to accept* SCSI-2 features such as tagged commands. The scsiShow() routine displays* this information.** If the type device is a Direct Access, a Write Once Read Multiple, or a* Opticial Memory Device then a READ_CAPACITY command is issued to determine * the values of `numBlocks' and `blockSize'. For these types of devices, * values passed into `numBlocks' and `blockSize' are ignored.** For Sequential Access devices the values specified in `numBlocks' and * `blockSize' are entered into the SCSI_PHYS_DEV structure.** RETURNS: A pointer to the created SCSI_PHYS_DEV structure, or NULL if the* routine is unable to create the physical device structure.** NOTE: the `devType' and `removable' arguments are ignored.*/LOCAL SCSI_PHYS_DEV *scsi2PhysDevCreate ( 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 */ SCSI_TARGET *pScsiTarget; /* ptr to SCSI target structure */ /* REQ SENSE data for auto-sizing */ UINT8 reqSenseData [REQ_SENSE_ADD_LENGTH_BYTE + 1]; UINT8 inquiryData [DEFAULT_INQUIRY_DATA_LENGTH]; /* 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 created */ if (scsiPhysDevIdGet (pScsiCtrl, devBusId, devLUN) != 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); /* create device mutual exclusion semaphore */ if ((pScsiPhysDev->mutexSem = semMCreate (scsiPhysDevMutexOptions)) == NULL) { SCSI_DEBUG_MSG ("scsiPhysDevCreate: semMCreate of mutexSem failed.\n", 0, 0, 0, 0, 0, 0); goto failed; } /* initialize miscellaneous fields in the SCSI_PHYS_DEV struct */ pScsiTarget = &pScsiCtrl->targetArr [devBusId]; pScsiPhysDev->pScsiCtrl = pScsiCtrl; pScsiPhysDev->pScsiTarget = pScsiTarget; pScsiPhysDev->scsiDevLUN = devLUN; pScsiCtrl->physDevArr [(devBusId << 3) | devLUN] = pScsiPhysDev; /* initialize block device list */ lstInit (&pScsiPhysDev->blkDevList); /* initialize sequential dev ptr */ pScsiPhysDev->pScsiSeqDev = NULL; /* initialize lists of active and waiting threads */ lstInit (&pScsiPhysDev->activeThreads); lstInit (&pScsiPhysDev->waitingThreads); /* initialize state variables */ pScsiPhysDev->connected = FALSE; pScsiPhysDev->pendingCA = FALSE; pScsiPhysDev->curTag = SCSI_TAG_NONE; pScsiPhysDev->nexus = SCSI_NEXUS_NONE; pScsiPhysDev->savedNexus = SCSI_NEXUS_NONE; pScsiPhysDev->nTaggedNexus = 0; /* initialise tags: do not use tags until after the INQUIRY command ! */ pScsiPhysDev->tagType = SCSI_TAG_UNTAGGED; pScsiPhysDev->nTags = 0; pScsiPhysDev->pTagInfo = 0; scsiMgrPhysDevTagInit (pScsiPhysDev); /* * Issue a Request Sense command to establish length of sense data, * if not specified by caller. */ if (reqSenseLength != 0) { pScsiPhysDev->reqSenseDataLength = reqSenseLength; if (reqSenseLength <= NON_EXT_SENSE_DATA_LENGTH) pScsiPhysDev->extendedSense = FALSE; else pScsiPhysDev->extendedSense = TRUE; } else { /* determine if 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); goto failed; } 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); goto failed; } else { /* device uses Extended Sense Data Format */ 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; } } if ((pScsiPhysDev->pReqSenseData = (UINT8 *) calloc (pScsiPhysDev->reqSenseDataLength, sizeof (UINT8))) == NULL) { goto failed; } /* * Issue an INQUIRY command: retry while a reset condition persists */ bzero ((char *) inquiryData, sizeof (inquiryData)); while (scsiInquiry (pScsiPhysDev, (char *) inquiryData, sizeof (inquiryData)) != OK) { if (!pScsiPhysDev->resetFlag) goto failed; pScsiPhysDev->resetFlag = FALSE; SCSI_DEBUG_MSG ("retrying scsiInquiry...\n", 0, 0, 0, 0, 0, 0); } /* * The INQUIRY command was successful: is there a device on this LUN ? */ if (inquiryData[SCSI_INQUIRY_DEV_TYPE] == SCSI_LUN_NOT_PRESENT) { SCSI_DEBUG_MSG ("scsiPhysDevCreate: LUN not present.\n", 0, 0, 0, 0, 0, 0); errnoSet (S_scsiLib_LUN_NOT_PRESENT); goto failed; } /* * There is a supported device on this LUN */ { int devType = inquiryData[SCSI_INQUIRY_DEV_TYPE] & SCSI_INQUIRY_DEV_TYPE_MASK; BOOL removable = inquiryData[SCSI_INQUIRY_DEV_MODIFIER] & SCSI_INQUIRY_REMOVABLE_MASK; int ansiVersion = inquiryData[SCSI_INQUIRY_VERSION] & SCSI_INQUIRY_ANSI_VSN_MASK; BOOL supportsTags = inquiryData[SCSI_INQUIRY_FLAGS] & SCSI_INQUIRY_CMD_QUEUE_MASK; BOOL syncSupport = inquiryData[SCSI_INQUIRY_FLAGS] & 0x10; BOOL wideSupport = (inquiryData[SCSI_INQUIRY_FLAGS] & SCSI_INQUIRY_WIDE_16_MASK) | (inquiryData[SCSI_INQUIRY_FLAGS] & SCSI_INQUIRY_WIDE_32_MASK); /* * set the appropriate fields to indicate if the target * supports wide / synchronous transfers. */ pScsiTarget->wideSupport = wideSupport; pScsiTarget->syncSupport = syncSupport; pScsiPhysDev->scsiDevType = devType; pScsiPhysDev->removable = removable; pScsiPhysDev->tagType = (ansiVersion >= 2) && supportsTags ? pScsiTarget->tagType : SCSI_TAG_UNTAGGED; pScsiPhysDev->nTags = (pScsiPhysDev->tagType != SCSI_TAG_UNTAGGED) ? pScsiTarget->maxTags : 0; if (pScsiPhysDev->nTags != 0) { /* * Allocate tag info. table; re-initialise tag system */ if ((pScsiPhysDev->pTagInfo = malloc (pScsiPhysDev->nTags * sizeof (SCSI_TAG_INFO))) == 0) { SCSI_DEBUG_MSG ("scsiPhysDevCreate: can't allocate tag info.\n", 0, 0, 0, 0, 0, 0); goto failed; } scsiMgrPhysDevTagInit (pScsiPhysDev); } /* * Save product info. strings in physical device structure */ bcopy ((char *) &inquiryData[SCSI_INQUIRY_VENDOR_ID], pScsiPhysDev->devVendorID, SCSI_INQUIRY_VENDOR_ID_LENGTH); bcopy ((char *) &inquiryData[SCSI_INQUIRY_PRODUCT_ID], pScsiPhysDev->devProductID, SCSI_INQUIRY_PRODUCT_ID_LENGTH); bcopy ((char *) &inquiryData[SCSI_INQUIRY_REV_LEVEL], pScsiPhysDev->devRevLevel, SCSI_INQUIRY_REV_LEVEL_LENGTH); pScsiPhysDev->devVendorID [SCSI_INQUIRY_VENDOR_ID_LENGTH] = EOS; pScsiPhysDev->devProductID [SCSI_INQUIRY_PRODUCT_ID_LENGTH] = EOS; pScsiPhysDev->devRevLevel [SCSI_INQUIRY_REV_LEVEL_LENGTH] = EOS; } /* 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)) { int lastLogBlkAdrs; int blkLength; /* * Issue a READ_CAPACITY command: retry while reset condition occurs */ while (scsiReadCapacity (pScsiPhysDev, &lastLogBlkAdrs, &blkLength) != OK) { /* Test for removable & additional sense code MEDIUM NOT PRESENT */ if (pScsiPhysDev->removable &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -