📄 scsidirectlib.c
字号:
/* scsiDirectLib.c - SCSI library for direct access devices (SCSI-2) *//* Copyright 1989-1996 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01g,10mar99,dat SPR 25196, return error if numsecs == 001f,28aug97,dds SPR 3425: "scsiFormatUnit" command, times out for disks which take a long time to format.01e,29oct96,dgp doc: editing for newly published SCSI libraries01d,23jul96,dds SPR 6718: added support for transfers above 16 MB.01c,06may96,jds more doc tweaks01b,20sep95,jdi doc tweak.01a,24jul95,jds written by extracting from scsi2Lib.*//*DESCRIPTIONThis library contains commands common to all direct-access SCSI devices.These routines are separated from scsi2Lib in order to create an additionallayer for better support of all SCSI direct-access devices.Commands in this library include:.TStab(|);lf3 lf3l l.Command | Op Code_FORMAT UNIT | (0x04)READ (6) | (0x08)READ (10) | (0x28)READ CAPACITY | (0x25)RELEASE | (0x17)RESERVE | (0x16)MODE SELECT (6) | (0x15)MODE SELECT (10) | (0x55)MODE SENSE (6) | (0x1a)MODE SENSE (10) | (0x5a)START STOP UNIT | (0x1b)WRITE (6) | (0x0a)WRITE (10) | (0x2a).TEINCLUDE FILESscsiLib.h, scsi2Lib.hSEE ALSO: dosFsLib, rt11FsLib, rawFsLib, scsi2Lib,.pG "I/O System, Local File Systems"*/#define INCLUDE_SCSI2#define SCSI_BLOCK_ADDRESS_SIZE 0x1fffff /* 21 Bit logical block address */#include "vxWorks.h"#include "ioLib.h"#include "intLib.h"#include "ctype.h"#include "cacheLib.h"#include "stdlib.h"#include "errnoLib.h"#include "taskLib.h"#include "lstLib.h"#include "logLib.h"#include "msgQLib.h"#include "string.h"#include "stdio.h"#include "sysLib.h"#include "scsiLib.h"#include "wdLib.h"/* imported globals */IMPORT BOOL scsiErrors; /* enable SCSI error messages */IMPORT BOOL scsiDebug; /* enable task level debug messages */IMPORT BOOL scsiIntsDebug; /* enable int level debug messages *//* global functions */void scsiDirectLibTblInit ();/* * Backward compatability functions localised */LOCAL STATUS scsi2ReadCapacity (SCSI_PHYS_DEV *, int *, int *);LOCAL STATUS scsi2RdSecs (SCSI_BLK_DEV *, int, int, char *);LOCAL STATUS scsiSectorRead (SCSI_BLK_DEV *, int, int, char *);LOCAL STATUS scsi2WrtSecs (SCSI_BLK_DEV *, int, int, char *);LOCAL STATUS scsiSectorWrite (SCSI_BLK_DEV *, int, int, char *);LOCAL STATUS scsi2FormatUnit (SCSI_PHYS_DEV *, BOOL, int, int, int, char *,int);LOCAL STATUS scsi2ModeSelect (SCSI_PHYS_DEV *, int, int, char *, int);LOCAL STATUS scsi2ModeSense (SCSI_PHYS_DEV *, int, int, char *, int);/* Block Device functions */LOCAL BLK_DEV * scsi2BlkDevCreate (SCSI_PHYS_DEV *, int, int);LOCAL void scsi2BlkDevInit (SCSI_BLK_DEV *, int, int);LOCAL void scsi2BlkDevShow (SCSI_PHYS_DEV *);LOCAL STATUS scsiStatusCheck (BLK_DEV *pBlkDev);LOCAL STATUS scsiBlkDevIoctl (SCSI_BLK_DEV *pScsiBlkDev, int function, int arg);/********************************************************************************* scsiDirectLibTblInit - initialize direct access functions in table ** Initialisation of array of function pointers for SCSI1 and SCSI2 switching** NOMANUAL*/void scsiDirectLibTblInit () { pScsiIfTbl->scsiBlkDevCreate = (FUNCPTR) scsi2BlkDevCreate; pScsiIfTbl->scsiBlkDevInit = (FUNCPTR) scsi2BlkDevInit; pScsiIfTbl->scsiBlkDevShow = (FUNCPTR) scsi2BlkDevShow; pScsiIfTbl->scsiFormatUnit = (FUNCPTR) scsi2FormatUnit; pScsiIfTbl->scsiModeSelect = (FUNCPTR) scsi2ModeSelect; pScsiIfTbl->scsiModeSense = (FUNCPTR) scsi2ModeSense; pScsiIfTbl->scsiReadCapacity = (FUNCPTR) scsi2ReadCapacity; pScsiIfTbl->scsiRdSecs = (FUNCPTR) scsi2RdSecs; pScsiIfTbl->scsiWrtSecs = (FUNCPTR) scsi2WrtSecs; }/********************************************************************************* scsi2BlkDevCreate - 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 *scsi2BlkDevCreate ( 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 ("scsiBlkDevCreate: 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 ("scsiBlkDevCreate:", 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->removable && (lstCount (&pScsiPhysDev->blkDevList) != 0)) { printErr ("scsiBlkDevCreate: "); 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->mutexSem, WAIT_FOREVER); lstAdd (&pScsiPhysDev->blkDevList, &pScsiBlkDevNode->blkDevNode); semGive (pScsiPhysDev->mutexSem); return (&pScsiBlkDev->blkDev); }/********************************************************************************* scsi2BlkDevInit - 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 scsi2BlkDevInit ( 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; }/********************************************************************************* scsi2BlkDevShow - 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 scsi2BlkDevShow ( 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) == 0) return; semTake (pScsiPhysDev->mutexSem, WAIT_FOREVER); for (pScsiBlkDevNode = (SCSI_BLK_DEV_NODE *) lstFirst (&pScsiPhysDev->blkDevList); pScsiBlkDevNode != NULL; pScsiBlkDevNode = (SCSI_BLK_DEV_NODE *) lstNext (&pScsiBlkDevNode->blkDevNode)) { printf ("%8d %8d %8d\n", ix++, pScsiBlkDevNode->scsiBlkDev.blockOffset, pScsiBlkDevNode->scsiBlkDev.numBlocks); } semGive (pScsiPhysDev->mutexSem); }/********************************************************************************* scsi2FormatUnit - 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 scsi2FormatUnit ( SCSI_PHYS_DEV *pScsiPhysDev,/* ptr to SCSI physical device */ BOOL cmpDefectList, /* whether defect list is complete */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -