📄 scsi1lib.c
字号:
LOCAL SCSI_PHYS_DEV * scsi1PhysDevIdGet ( SCSI_CTRL *pScsiCtrl, /* ptr to SCSI controller info */ int devBusId, /* device's SCSI bus ID */ int devLUN /* device's logical unit number */ ) { /* check for valid ptr to SCSI_CTRL */ if (pScsiCtrl == NULL) { if (pSysScsiCtrl != NULL) pScsiCtrl = pSysScsiCtrl; else { errnoSet (S_scsiLib_NO_CONTROLLER); SCSI_DEBUG_MSG ("No SCSI controller specified.\n", 0, 0, 0, 0, 0, 0); return ((SCSI_PHYS_DEV *) NULL); } } return (pScsiCtrl->physDevArr [(devBusId << 3) | devLUN]); }/********************************************************************************* scsi1AutoConfig - configure all devices connected to a SCSI controller** This routine cycles through all legal SCSI bus IDs (and logical unit* numbers (LUNs)), attempting a scsiPhysDevCreate() with default parameters* on each. All devices which support the INQUIRY routine are* configured. The scsiShow() routine can be used to find the system's table* of SCSI physical devices attached to a specified SCSI controller. In* addition, scsiPhysDevIdGet() can be used programmatically to get a* pointer to the SCSI_PHYS_DEV structure associated with the device at a* specified SCSI bus ID and LUN.** RETURNS: OK, or ERROR if `pScsiCtrl' and `pSysScsiCtrl' are both NULL.*/LOCAL STATUS scsi1AutoConfig ( SCSI_CTRL *pScsiCtrl /* ptr to SCSI controller info */ ) { int busId, lun; /* loop indices */ SCSI_PHYS_DEV *pScsiPhysDev; /* ptr to SCSI physical device info */ /* check for valid input parameters */ if (pScsiCtrl == (SCSI_CTRL *) NULL) { if (pSysScsiCtrl == (SCSI_CTRL *) NULL) { errnoSet (S_scsiLib_NO_CONTROLLER); printErr ("No SCSI controller specified.\n"); return (ERROR); } pScsiCtrl = pSysScsiCtrl; } /* loop through all SCSI bus ID's and LUN's (logical units); if a given * bus ID times out during selection, do not test for other LUN's at * that bus ID, since there cannot be any. */ for (busId = SCSI_MIN_BUS_ID; busId <= SCSI_MAX_BUS_ID; busId++) { if (busId != pScsiCtrl->scsiCtrlBusId) { for (lun = SCSI_MIN_LUN; lun <= SCSI_MAX_LUN; lun++) { SCSI_DEBUG_MSG ("scsiAutoConfig: bus ID = %d, LUN = %d\n", busId, lun, 0, 0, 0, 0); if ((pScsiPhysDev = scsiPhysDevCreate (pScsiCtrl, busId, lun, 0, NONE, 0, 0, 0)) == (SCSI_PHYS_DEV *) NULL) { if (errnoGet () == S_scsiLib_SELECT_TIMEOUT) break; } } } } return (OK); }/********************************************************************************* strIsPrintable - determine whether a string contains all printable chars** RETURNS: TRUE | FALSE.*/LOCAL BOOL strIsPrintable ( FAST char *pString /* ptr to string to be tested */ ) { FAST char ch; while ((ch = *pString++) != EOS) { if (!isprint (ch)) return (FALSE); } return (TRUE); }/********************************************************************************* scsi1Show - list the physical devices attached to a SCSI controller** This routine displays the SCSI bus ID, logical unit number (LUN), vendor ID,* product ID, firmware revision (rev.), device type, number of blocks,* block size in bytes, and a pointer to the associated SCSI_PHYS_DEV* structure for each physical SCSI device known to be attached to a specified* SCSI controller.** NOTE:* If `pScsiCtrl' is NULL, the value of the global variable `pSysScsiCtrl'* is used, unless it is also NULL.** RETURNS: OK, or ERROR if both `pScsiCtrl' and `pSysScsiCtrl' are NULL.*/LOCAL STATUS scsi1Show ( FAST SCSI_CTRL *pScsiCtrl /* ptr to SCSI controller info */ ) { FAST SCSI_PHYS_DEV *pScsiPhysDev; /* SCSI physical device info */ FAST int ix; /* loop variable */ if (pScsiCtrl == NULL) { if (pSysScsiCtrl != NULL) pScsiCtrl = pSysScsiCtrl; else { errnoSet (S_scsiLib_NO_CONTROLLER); SCSI_DEBUG_MSG ("No SCSI controller specified.\n", 0, 0, 0, 0, 0, 0); return (ERROR); } } printf ("ID LUN VendorID ProductID Rev. "); printf ("Type Blocks BlkSize pScsiPhysDev \n"); printf ("-- --- -------- ---------------- ---- "); printf ("---- -------- ------- ------------\n"); for (ix = 0; ix < MAX_SCSI_PHYS_DEVS; ix++) if ((pScsiPhysDev = pScsiCtrl->physDevArr[ix]) != (SCSI_PHYS_DEV *) NULL) { printf ("%2d " , pScsiPhysDev->scsiDevBusId); printf ("%2d " , pScsiPhysDev->scsiDevLUN); printf (" %8s" , strIsPrintable (pScsiPhysDev->devVendorID) ? pScsiPhysDev->devVendorID : " "); printf (" %16s", strIsPrintable (pScsiPhysDev->devProductID) ? pScsiPhysDev->devProductID : " "); printf (" %4s ", strIsPrintable (pScsiPhysDev->devRevLevel) ? pScsiPhysDev->devRevLevel : " "); printf ("%3d" , pScsiPhysDev->scsiDevType); printf (pScsiPhysDev->removable ? "R" : " "); printf (" %7d " , pScsiPhysDev->numBlocks); printf (" %5d " , pScsiPhysDev->blockSize); printf (" 0x%08x ", (int) pScsiPhysDev); printf ("\n"); } return (OK); }/********************************************************************************* scsi1BlkDevCreate - define a logical partition on a SCSI block device** This routine creates and initializes a BLK_DEV structure, which* describes a logical partition on a SCSI physical block device. A logical* partition is an array of contiguously addressed blocks; it can be completely* described by the number of blocks and the address of the first block in* the partition. In normal configurations, partitions do not overlap, although* such a condition is not an error.** NOTE:* If `numBlocks' is 0, the rest of device is used.** RETURNS: A pointer to the created BLK_DEV, or NULL if parameters exceed* physical device boundaries, the physical device is not a block device, or* memory is insufficient for the structures.*/LOCAL BLK_DEV *scsi1BlkDevCreate ( SCSI_PHYS_DEV *pScsiPhysDev, /* ptr to SCSI physical device info */ int numBlocks, /* number of blocks in block device */ int blockOffset /* address of first block in volume */ ) { SCSI_BLK_DEV *pScsiBlkDev; /* ptr to SCSI block dev struct */ SCSI_BLK_DEV_NODE *pScsiBlkDevNode; /* ptr to SCSI block dev node struct */ /* check parameters for validity */ if ((pScsiPhysDev == NULL) || (numBlocks < 0) || (blockOffset < 0) || ((blockOffset + numBlocks) > pScsiPhysDev->numBlocks)) { errnoSet (S_scsiLib_ILLEGAL_PARAMETER); SCSI_DEBUG_MSG ("scsi1BlkDevCreate: Invalid input parameter(s).\n", 0, 0, 0, 0, 0, 0); return ((BLK_DEV *) NULL); } /* return NULL if sequential access (or other non-block) device */ if (!((pScsiPhysDev->scsiDevType == SCSI_DEV_DIR_ACCESS) || (pScsiPhysDev->scsiDevType == SCSI_DEV_WORM) || (pScsiPhysDev->scsiDevType == SCSI_DEV_RO_DIR_ACCESS))) { errnoSet (S_scsiLib_ILLEGAL_OPERATION); SCSI_DEBUG_MSG ("scsi1BlkDevCreate:", 0, 0, 0, 0, 0, 0); SCSI_DEBUG_MSG ("Physical device is not a block device.\n", 0, 0, 0, 0, 0, 0); return ((BLK_DEV *) NULL); } /* disallow multiple partitions on removable media */ if ((pScsiPhysDev->pScsiBlkDev != NULL) && pScsiPhysDev->removable) { printErr ("scsi1BlkDevCreate: "); printErr ("Can't create multiple partitions on removable media.\n"); return ((BLK_DEV *) NULL); } /* create a SCSI block device node structure */ pScsiBlkDevNode = (SCSI_BLK_DEV_NODE *) calloc (1, sizeof (SCSI_BLK_DEV_NODE)); if (pScsiBlkDevNode == NULL) return ((BLK_DEV *) NULL); pScsiBlkDev = &pScsiBlkDevNode->scsiBlkDev; /* fill in the member data */ pScsiBlkDev->blkDev.bd_blkRd = (FUNCPTR) scsiRdSecs; pScsiBlkDev->blkDev.bd_blkWrt = (FUNCPTR) scsiWrtSecs; pScsiBlkDev->blkDev.bd_ioctl = (FUNCPTR) scsiBlkDevIoctl; pScsiBlkDev->blkDev.bd_reset = (FUNCPTR) NULL; if (pScsiPhysDev->removable) pScsiBlkDev->blkDev.bd_statusChk = (FUNCPTR) scsiStatusCheck; else pScsiBlkDev->blkDev.bd_statusChk = (FUNCPTR) NULL; pScsiBlkDev->blkDev.bd_removable = pScsiPhysDev->removable; pScsiBlkDev->blkDev.bd_nBlocks = (ULONG) (numBlocks == 0 ? pScsiPhysDev->numBlocks - blockOffset : numBlocks); pScsiBlkDev->blkDev.bd_bytesPerBlk = (ULONG) pScsiPhysDev->blockSize; pScsiBlkDev->blkDev.bd_retry = 1; pScsiBlkDev->blkDev.bd_mode = O_RDWR; pScsiBlkDev->blkDev.bd_readyChanged = TRUE; pScsiBlkDev->pScsiPhysDev = pScsiPhysDev; pScsiBlkDev->blockOffset = blockOffset; pScsiBlkDev->numBlocks = (int) pScsiBlkDev->blkDev.bd_nBlocks; /* add block device to list created on the physical device */ semTake (&pScsiPhysDev->blkDevList.listMutexSem, WAIT_FOREVER); lstAdd (&pScsiPhysDev->blkDevList.blkDevNodes, &pScsiBlkDevNode->blkDevNode); semGive (&pScsiPhysDev->blkDevList.listMutexSem); return (&pScsiBlkDev->blkDev); }/********************************************************************************* scsi1BlkDevInit - initialize fields in a SCSI logical partition** This routine specifies the disk geometry parameters required by certain* file systems (e.g., dosFs). It should be called after a SCSI_BLK_DEV* structure is created via scsiBlkDevCreate(), but before a file system* initialization routine. It is generally required only for removable media* devices.** RETURNS: N/A*/LOCAL void scsi1BlkDevInit ( SCSI_BLK_DEV *pScsiBlkDev, /* ptr to SCSI block dev. struct */ int blksPerTrack, /* blocks per track */ int nHeads /* number of heads */ ) { pScsiBlkDev->blkDev.bd_blksPerTrack = (ULONG) blksPerTrack; pScsiBlkDev->blkDev.bd_nHeads = (ULONG) nHeads; }/********************************************************************************* scsi1BlkDevShow - show the BLK_DEV structures on a specified physical device** This routine displays all of the BLK_DEV structures created on a specified* physical device. This routine is called by scsiShow(), but may also be* invoked directly, usually from the shell.** RETURNS: N/A*/LOCAL void scsi1BlkDevShow ( SCSI_PHYS_DEV *pScsiPhysDev /* ptr to SCSI physical device info */ ) { SCSI_BLK_DEV_NODE *pScsiBlkDevNode; int ix = 0; printf ("Block Device # physical address size (blocks)\n"); printf ("-------------- ---------------- -------------\n"); if (lstCount (&pScsiPhysDev->blkDevList.blkDevNodes) == 0) return; semTake (&pScsiPhysDev->blkDevList.listMutexSem, WAIT_FOREVER); for (pScsiBlkDevNode = (SCSI_BLK_DEV_NODE *) lstFirst (&pScsiPhysDev->blkDevList.blkDevNodes); pScsiBlkDevNode != NULL; pScsiBlkDevNode = (SCSI_BLK_DEV_NODE *) lstNext (&pScsiBlkDevNode->blkDevNode)) { printf ("%8d %8d %8d\n", ix++, pScsiBlkDevNode->scsiBlkDev.blockOffset, pScsiBlkDevNode->scsiBlkDev.numBlocks); } semGive (&pScsiPhysDev->blkDevList.listMutexSem); }/********************************************************************************* scsi1BusReset - pulse the reset signal on the SCSI bus** This routine calls a controller-specific routine to reset a specified* controller's SCSI bus. If no controller is specified (`pScsiCtrl' is 0),* the value in `pSysScsiCtrl' is used.** RETURNS: OK, or ERROR if there is no controller or controller-specific* routine.*/LOCAL STATUS scsi1BusReset ( SCSI_CTRL *pScsiCtrl /* ptr to SCSI controller info */ ) { if (pScsiCtrl->scsiBusReset == (VOIDFUNCPTR) NULL) return (ERROR); else { if (pScsiCtrl == (SCSI_CTRL *) NULL) { if (pSysScsiCtrl != (SCSI_CTRL *) NULL) pScsiCtrl = pSysScsiCtrl; else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -