530 lines
20 KiB
C
530 lines
20 KiB
C
/**************************************************************************
|
|
* *
|
|
* Copyright (C) 1993, Silicon Graphics, Inc. *
|
|
* *
|
|
* These coded instructions, statements, and computer programs contain *
|
|
* unpublished proprietary information of Silicon Graphics, Inc., and *
|
|
* are protected by Federal copyright law. They may not be disclosed *
|
|
* to third parties or copied or duplicated in any form, in whole or *
|
|
* in part, without the prior written consent of Silicon Graphics, Inc. *
|
|
* *
|
|
**************************************************************************/
|
|
|
|
#ident "$Revision: 1.3 $"
|
|
|
|
/*
|
|
* Administrative interface definitions for the UltraStor U144F RAID controller.
|
|
*
|
|
* These are definitions of arguments and argument formats for use
|
|
* with the ioctl() syscall against a file descriptor for the open
|
|
* block or character device referring to an UltraStor U144F RAID
|
|
* controller.
|
|
*
|
|
* The USRAID device driver opens the RAID device with the EXCLUSIVE
|
|
* flag, so no other access to the device is permitted (eg: via /dev/scsi)
|
|
* while the device is open. The driver releases the exclusive flag
|
|
* when there are no active opens of the device through that driver,
|
|
* however, so operations not supported by this driver can be performed.
|
|
*
|
|
* Please note that this interface may change at any time.
|
|
*/
|
|
|
|
#define USRAID_DEVNAME "rad" /* as in /dev/rdsk/rad4d2vh */
|
|
|
|
#define USRAID_IOC_UPPER (('R'<<24) | ('A'<<16) | ('D'<<8))
|
|
#define USRAID_IOC_MASK (~0xff) /* is this a USRAID ioctl? */
|
|
#define USRAID_IOC_(NUM) (USRAID_IOC_UPPER | (NUM))
|
|
|
|
/* XXXGROT: renumber the IOC's */
|
|
|
|
/*============================================================================
|
|
* UltraStor U144F Specific "Maintenance" Commands
|
|
*============================================================================*/
|
|
|
|
/*
|
|
* There can be only one "maintenance" command in process on the
|
|
* controller at any one time. A log page tells if there is a
|
|
* maintenance command executing on the controller, what type of
|
|
* command it is (eg: rebuild, integrity check, etc), and the first
|
|
* LBA of the stripe just completed by that command. It is intended
|
|
* that that information be used by the host to manage the operation
|
|
* of maintenance commands on the controller.
|
|
*
|
|
* The maintenance commands all support a particular method for
|
|
* asynchronous operation. That method uses two bits in the command,
|
|
* the "immediate" bit and the "abort" bit.
|
|
*
|
|
* The "immediate" bit is used to initiate a maintenance operation
|
|
* and have the command return good status immediately. The
|
|
* maintenance command continues operating in the controller, but
|
|
* the host is not waiting for a response. The command operates in
|
|
* the normal block-and-wait-for-completion mode if the "immediate"
|
|
* bit is not set.
|
|
*
|
|
* If an error occurs and the "immediate" bit is not set, traditional
|
|
* error processing happens. If the "immediate" bit is set, a check
|
|
* condition is returned to the host via either the sentinel command
|
|
* or the next available command. The returned sense information will
|
|
* then indicate that an "immediate" maintenance command has failed,
|
|
* and the LBA of the error. If no error occurs and the maintenance
|
|
* command finishes successfully, then no direct indication of that
|
|
* completion is given to the host. In either case, the log page will
|
|
* be updated to show that there are no active maintenance commands.
|
|
*
|
|
* The "abort" bit is used to interrupt a maintenance operation that
|
|
* is currently running on the controller. If a maintenance command
|
|
* of type "X" is running, sending another "X" command to the controller,
|
|
* this one with the "abort" bit set, will cause the first "X" command
|
|
* to gracefully stop.
|
|
*
|
|
* As an example, if an "integrity check" command is active, sending
|
|
* another "integrity check" command with with the "abort" bit set
|
|
* will cause the controller to stop checking integrity.
|
|
*
|
|
* If the active maintenance command did not have the "immediate" bit
|
|
* set, it will return with an error (that it was aborted). If it
|
|
* was started with the "immediate" bit, there will be no indication
|
|
* to the host.
|
|
*
|
|
* If the active maintenance command is aborted, the second command
|
|
* (the one with the "abort" bit set) will return a good completion.
|
|
* If there are no active maintenance commands to abort, or there is
|
|
* some other problem, the second command will return with an error.
|
|
*
|
|
* SGI plans not to use the "immediate" bit, but will use "abort".
|
|
* That should avoid most of the complexity of the above description.
|
|
*/
|
|
|
|
|
|
/*
|
|
* Initialize Logical Unit
|
|
*
|
|
* This command initializes the logical drive to a pattern of 0x00.
|
|
* It starts from the sector specified in the LBA field and runs through
|
|
* the end of the drive. If the initialize fails for some reason,
|
|
* the LBA of the failure will be returned.
|
|
*
|
|
* The SCSI "format" command is an alias (with the LBA defaulted to 0)
|
|
* for this command.
|
|
*
|
|
* The ioctl arg should be an unsigned int giving the starting LBA
|
|
* for the operation.
|
|
*/
|
|
#define USRAID_INITDRIVE USRAID_IOC_(0x01)
|
|
|
|
|
|
/*
|
|
* Scan Logical Unit
|
|
*
|
|
* This command reads the contents of the logical drive starting at the
|
|
* specified LBA. It will run until an error occurs or the the end of
|
|
* the drive is reached. If an error occurs, the LBA of the failure will
|
|
* be returned.
|
|
*
|
|
* Note that this command does simple reads, basically checking for
|
|
* unreadable sectors, it does not compare the data against the parity.
|
|
* See the "check integrity" command.
|
|
*
|
|
* The ioctl arg should be an unsigned int giving the starting LBA
|
|
* for the operation.
|
|
*/
|
|
#define USRAID_SCANDRIVE USRAID_IOC_(0x02)
|
|
|
|
|
|
/*
|
|
* Integrity Check
|
|
*
|
|
* This command initiates an integrity check of the parity sectors of
|
|
* the indicated logical unit. The integrity check starts at the
|
|
* indicated LBA, and continues through the end of the drive or until
|
|
* an error occurs. It will either return a command complete (the
|
|
* whole drive's integrity is good), or an error (indicating the address
|
|
* that the failure occurred).
|
|
*
|
|
* Each stripe is checked to see if the data and parity correspond.
|
|
*
|
|
* The ioctl arg should be an unsigned int giving the starting LBA
|
|
* for the operation.
|
|
*/
|
|
#define USRAID_INTEGRITY USRAID_IOC_(0x03)
|
|
|
|
|
|
/*
|
|
* Fix Integrity
|
|
*
|
|
* This command is used if the Integrity Check command failed.
|
|
*
|
|
* This command will update the parity block of the stripe specified by
|
|
* the LBA so that the parity block is correct for the existing data in
|
|
* that stripe. It will only operate on one stripe.
|
|
*
|
|
* It will return a command complete with no error (the stripe has been
|
|
* restored), or with an error (indicating the address that the failure
|
|
* occured).
|
|
*
|
|
* The ioctl arg should be an unsigned int. The starting LBA of the
|
|
* stripe to be fixed is passed in through that long.
|
|
*/
|
|
#define USRAID_FIXINTEG USRAID_IOC_(0x04)
|
|
|
|
|
|
/*
|
|
* Rebuild
|
|
*
|
|
* This command rebuilds the data of the specified logical drive.
|
|
* The failed physical unit is NOT determined by internal data
|
|
* structures but from the drive-ID/channel-number specified in the
|
|
* command. The command will start reconstructing that drive using
|
|
* the existing data sectors and the parity sectors.
|
|
*
|
|
* This command will not complete until either reconstruction is
|
|
* complete, or an unrecoverable error is encountered on the non-failed
|
|
* drives.
|
|
*
|
|
* The ioctl arg should be a pointer to the following structure.
|
|
* The "drive" field tell which drive must be rebuilt. The "lba"
|
|
* field contains starting LBA for the rebuild, and the value is
|
|
* modified to the first LBA of the last completed stripe on error
|
|
* or good completion.
|
|
*/
|
|
#define USRAID_REBUILD USRAID_IOC_(0x05)
|
|
struct usraid_rebuild {
|
|
int drive; /* which drive to rebuild */
|
|
unsigned int lba; /* IN: starting LBA, OUT: final LBA */
|
|
};
|
|
|
|
|
|
/*============================================================================
|
|
* Other UltraStor U144F Specific Commands
|
|
*============================================================================*/
|
|
|
|
|
|
/*
|
|
* Execute Pass Through Command
|
|
*
|
|
* This command issues the included CDB as a normal SCSI command to a
|
|
* specific physical disk within the RAID.
|
|
*
|
|
* The command is excecuted in a single threaded mode, ie: no other
|
|
* activity on that drive, and no other commands will be accepted
|
|
* while this command is executing.
|
|
*
|
|
* If the passed through command needs or generates data, it will be
|
|
* transferred from the host to the controller, which will pass it
|
|
* on the the drive.
|
|
*
|
|
* The ioctl arg should be a pointer to the following structure:
|
|
*
|
|
* The drive field identifies which physical drive the command is to
|
|
* be pass to. The drives are numbered from 0 to 4; corresponding
|
|
* to SCSI IDs and slot numbers.
|
|
*
|
|
* The "fromdisk", "todisk", and "xfercount" fields describe the data
|
|
* transfer required by the executing command. "fromdisk" and "todisk"
|
|
* can be any combination except 1 and 1. If any data is to be
|
|
* transferred (ie: fromdisk or todisk is nonzero), then "xfercount"
|
|
* must be nonzero.
|
|
*
|
|
* The SCSI command to be executed is stored in "cdb", and "cdblen"
|
|
* tells how many bytes are valid.
|
|
*
|
|
* The "databuf" field should point to a buffer that either contains
|
|
* the data that the passed through command will be requesting, or a
|
|
* buffer large enough to accept the data being passed back. If there
|
|
* is no data transfer for the passed through command, the arg may be
|
|
* NULL. If data transfer is required and the "databuf" field is NULL,
|
|
* an error will be returned.
|
|
*
|
|
* If the passed through command encounters an error, sense data
|
|
* will be gotten and placed in the "sensebuf" field.
|
|
*/
|
|
#define USRAID_PASSTHRU USRAID_IOC_(0x07)
|
|
struct usraid_passthru {
|
|
int drive; /* which slot to pass thru to */
|
|
int fromdisk; /* data xfer disk->controller (T/F) */
|
|
int todisk; /* data xfer controller->disk (T/F) */
|
|
int xfercount; /* # bytes of data to be xfer'd by CDB */
|
|
int cdblen; /* number of valid bytes in CDB */
|
|
u_char cdb[12]; /* the SCSI command block itself */
|
|
caddr_t databuf; /* ptr to data for CDB */
|
|
u_char sensebuf[64]; /* sense data if CDB gets an error */
|
|
};
|
|
|
|
#if _KERNEL
|
|
struct irix5_usraid_passthru {
|
|
int drive; /* which slot to pass thru to */
|
|
int fromdisk; /* data xfer disk->controller (T/F) */
|
|
int todisk; /* data xfer controller->disk (T/F) */
|
|
int xfercount; /* # bytes of data to be xfer'd by CDB */
|
|
int cdblen; /* number of valid bytes in CDB */
|
|
u_char cdb[12]; /* the SCSI command block itself */
|
|
app32_ptr_t databuf; /* ptr to data for CDB */
|
|
u_char sensebuf[64]; /* sense data if CDB gets an error */
|
|
};
|
|
#endif /* _KERNEL */
|
|
|
|
|
|
/*
|
|
* Download new firmware into the controller
|
|
*
|
|
* This command is used to download new firmware into the FLASH EPROM
|
|
* on the controller.
|
|
*
|
|
* The *firmware image* is not checked for validity in any way by the
|
|
* system, the controller is final and only judge of acceptability of
|
|
* the new *image*. On the other hand, the system will refuse to
|
|
* pass the image to the controller if the controller is not already
|
|
* running an SGI version of firmware.
|
|
*
|
|
* The ioctl arg should point to the following structure. The buffer
|
|
* field should point to a memory area contining the image to be
|
|
* downloaded, and the size field should contain the number of valid
|
|
* bytes in that image.
|
|
*/
|
|
#define USRAID_DOWNLOAD USRAID_IOC_(0x19)
|
|
struct usraid_download {
|
|
caddr_t buffer; /* firmware image in memory buffer */
|
|
int size; /* size of firmware image */
|
|
};
|
|
|
|
#if _KERNEL
|
|
struct irix5_usraid_download {
|
|
app32_ptr_t buffer; /* firmware image in memory buffer */
|
|
int size; /* size of firmware image */
|
|
};
|
|
#endif /* _KERNEL */
|
|
|
|
|
|
/*
|
|
* Isolate Channel
|
|
* Un-Isolate Channel
|
|
*
|
|
* Isolate channel -
|
|
* This command makes the specified channel, with all units attached
|
|
* to it, inactive. The purpose is to allow the user to replace a
|
|
* failed unit with a new one. The effect is exactly the same as if
|
|
* the disk side SCSI channel had failed.
|
|
*
|
|
* Unisolate channel -
|
|
* This command makes the specified channel, with all units attached
|
|
* to it, active after a failed unit has been replaced. There is no
|
|
* recovery associated with this command, just re-enabling the SCSI
|
|
* channel.
|
|
*
|
|
* The ioctl arg should be an integer showing which drive to operate on.
|
|
*/
|
|
#define USRAID_ISOLATE USRAID_IOC_(0x0a)
|
|
#define USRAID_UNISOLATE USRAID_IOC_(0x0b)
|
|
|
|
|
|
/*
|
|
* Return Physical Connection
|
|
*
|
|
* This command returns drive specific information about the physical
|
|
* disk in the indicated slot in the RAID. The SCSI target ID of each
|
|
* drive must match the slot number (ie: the SCSI channel number) that
|
|
* it is plugged into. If there is no disk in the given slot, then an
|
|
* error will be returned.
|
|
*
|
|
* The ioctl arg should be a pointer to the following structure. The
|
|
* "drive" field is set to indicate which drive information in requested
|
|
* on, and the other fields are filled in as a result.
|
|
*/
|
|
#define USRAID_PHYS_CONN USRAID_IOC_(0x0c)
|
|
struct usraid_phys_conn {
|
|
int drive; /* IN: which drive to ask about */
|
|
char vendor[9]; /* OUT: vendor ID string (8 valid bytes) */
|
|
char product[17]; /* OUT: product ID string (16 valid bytes) */
|
|
char revision[5]; /* OUT: revision ID string (4 valid bytes) */
|
|
int totalsize; /* OUT: total number sectors on drive */
|
|
int blocksize; /* OUT: sector size of drive */
|
|
};
|
|
|
|
|
|
/*
|
|
* Return Physical Units Down
|
|
* Clear Physical Units Down
|
|
* Set Physical Units Down
|
|
*
|
|
* Return physical units down -
|
|
* The data will show which drives are marked as being down.
|
|
* A non-zero value shows the corresponding drive is down.
|
|
*
|
|
* Clear physical units down -
|
|
* The data will show which drives are are to be marked as being
|
|
* up again. A non-zero value says to mark the drive as up.
|
|
* This command is normally used after the host has completed its
|
|
* drive replacement procedure in order to declare that the drive
|
|
* is now usable.
|
|
*
|
|
* Set physical units down -
|
|
* The data will show which drives are are to be marked as being
|
|
* down. A non-zero value says to mark the drive as down. This
|
|
* command is used to force the controller to treat a physical
|
|
* disk in the RAID as if it had failed.
|
|
*
|
|
* In SGI's usage of the U144F controller, the SCSI target ID of
|
|
* a drive must match the channel number that it is plugged into.
|
|
* There are 5 elements in the array, indexed by the slot-number.
|
|
* Each element refers to the corresponding drive.
|
|
*
|
|
* The ioctl arg should be a pointer to an array of 5 integers. The
|
|
* elements of the array will be used to reference the corresponding
|
|
* drive in the RAID. A non-zero element shows that a drive is down,
|
|
* or that you would like it to be changed to down or up.
|
|
*/
|
|
#define USRAID_RET_DOWN USRAID_IOC_(0x0d)
|
|
#define USRAID_CLR_DOWN USRAID_IOC_(0x0e)
|
|
#define USRAID_SET_DOWN USRAID_IOC_(0x0f)
|
|
struct usraid_units_down {
|
|
int drive[5];
|
|
};
|
|
|
|
|
|
/*
|
|
* Get NVRAM
|
|
* Set NVRAM
|
|
* Clear NVRAM
|
|
*
|
|
* Get NVRAM -
|
|
* The ioctl will return 4 bytes from the controller's NVRAM.
|
|
* The 4 bytes will come from byte offset "4*addr" into the
|
|
* controller's NVRAM. This command is normally used to read
|
|
* saved configuration state in the NVRAM.
|
|
*
|
|
* Set NVRAM -
|
|
* The ioctl will transfer 4 bytes to the controller's NVRAM.
|
|
* The 4 bytes will be put in byte offset "4*addr" into the
|
|
* controller's NVRAM. This command is normally used to write
|
|
* saved configuration state in the NVRAM.
|
|
*
|
|
* Clear NVRAM -
|
|
* This ioctl will clears the "key" byte in the NVRAM so that
|
|
* when the controller is next power cycled, the entire NVRAM
|
|
* will be re-initialized to the factory ship state. All
|
|
* settings or status stored in the NVRAM will be lost.
|
|
* NOTE: this command has no data phase, no arguments are required.
|
|
*
|
|
* The NVRAM is accessed in 32 bit segments. If the NVRAM were an
|
|
* array of 32 bit quantities, the "addr" would be the array index
|
|
* of the desired entry. An "addr" of 6 will return bytes 24, 25,
|
|
* 26, and 27 from the NVRAM. The NVRAM is 256 bytes long, and SGI
|
|
* has exclusive use of the last 32 bytes (8 words).
|
|
*
|
|
* For the "get" and "put" commands, the ioctl arg should be a
|
|
* pointer to the following structure. The "addr" field is set
|
|
* to indicate which word in NVRAM is to be operated on, and the
|
|
* "data" field is filled in as a result. Only the last 8 words
|
|
* are writeable through this interface, but all are readable.
|
|
*
|
|
* For the "clear" command, the ioctl arg is ignored.
|
|
*/
|
|
#define USRAID_GET_NVRAM USRAID_IOC_(0x10)
|
|
#define USRAID_SET_NVRAM USRAID_IOC_(0x11)
|
|
#define USRAID_CLEAR_NVRAM USRAID_IOC_(0x12)
|
|
struct usraid_nvram_data {
|
|
int addr; /* IN: NVRAM word address */
|
|
unsigned int data; /* IN/OUT: data to write/read */
|
|
};
|
|
|
|
/*
|
|
* Word offsets into the NVRAM of relevant information.
|
|
* SGI has the final 8 words (out of 64) reserved for our use.
|
|
*/
|
|
#define USRAID_NVRAM_INITTED 0 /* bit 0, RAID initialized */
|
|
#define USRAID_NVRAM_FIRSTSPARE 56 /* first SGI spare byte in NVRAM */
|
|
#define USRAID_NVRAM_FLAGBITS 59 /* 4byte: flag bits */
|
|
#define USRAID_NVRAM_WRTPROT 0x0001 /* bit: RAID is marked write-protected */
|
|
#define USRAID_NVRAM_TIME_SEC 61 /* 4byte: time of format (sec) */
|
|
#define USRAID_NVRAM_TIME_USEC 62 /* 4byte: time of format (usec) */
|
|
#define USRAID_NVRAM_CONFIG_ID 63 /* 4byte: config identifier */
|
|
|
|
|
|
/*============================================================================
|
|
* UltraStor U144F Specific Sense/Mode Pages
|
|
*============================================================================*/
|
|
|
|
|
|
/*
|
|
* Miscellaneous Control Page
|
|
*
|
|
* This mode page determines the controller's performance characteristics
|
|
* while a maintenance operation is in progress.
|
|
*
|
|
* utilization - shows the maximum percentage utilization of the
|
|
* controller's bandwidth to be used by maintenance commands.
|
|
* Possible values range from 1 thru 100 (0x64). A value of 0
|
|
* is special and may (in the future) refer to a special mode.
|
|
*
|
|
* The ioctl arg should be a pointer to the following structure.
|
|
* The fields can be set or read via this structure.
|
|
*/
|
|
#define USRAID_SET_MISC_PG USRAID_IOC_(0x13)
|
|
#define USRAID_GET_MISC_PG USRAID_IOC_(0x14)
|
|
struct usraid_misc_page {
|
|
int utilization; /* % ctlr usage for maint cmds */
|
|
};
|
|
|
|
|
|
/*
|
|
* Drive Group Definition Control Page
|
|
*
|
|
* This mode page defines the I/O optimization characteristics of the
|
|
* RAID. It controls the striping parameters and RAID4 versus RAID5 mode.
|
|
*
|
|
* RAID5 is optimized for many concurrent threads of I/O, while RAID4 is
|
|
* (very much like RAID3) optimized for a small number of very high
|
|
* bandwidth I/O threads.
|
|
*
|
|
* stripe depth - defines the number of logically contigous blocks on
|
|
* a given drive before the next logically contiguous block is on
|
|
* the next drive. In other words, it is 25% of the total stripe size.
|
|
* This field is limited to between 1 block and 128 blocks, inclusive.
|
|
*
|
|
* num_stripes - the number of stripes of the indicated size in the whole
|
|
* RAID. Range: 1 thru 0xffffffff.
|
|
*
|
|
* mode - choose between RAID5 (mode == 0) and RAID4 (mode == 1).
|
|
*
|
|
* The ioctl arg should be a pointer to the following structure.
|
|
* The fields can be set or read via this structure.
|
|
*/
|
|
#define USRAID_SET_DEFN_PG USRAID_IOC_(0x15)
|
|
#define USRAID_GET_DEFN_PG USRAID_IOC_(0x16)
|
|
struct usraid_defn_page {
|
|
int stripe_depth; /* # sectors on 1 drive in a stripe */
|
|
unsigned int num_stripes; /* # stripes in the RAID */
|
|
int mode; /* 0==RAID5 mode, 1==RAID4 mode */
|
|
};
|
|
|
|
|
|
/*
|
|
* Partition Definition Control Page
|
|
*
|
|
* This mode page defines a "partition". Note that these are not the
|
|
* same kinds of things as a UNIX partition. These really controll how
|
|
* much of the physical drives will be available as part of the RAID.
|
|
* Sectors not included in the "partition" are NOT available for ANY use.
|
|
* The same base sector number and number of sectors will be used for
|
|
* all drives in the RAID.
|
|
*
|
|
* This gives the controller a range of sectors from each drive that
|
|
* the "drive group definition" page will then use to define a RAID4
|
|
* or RAID5 storage area.
|
|
*
|
|
* base - defines the first sector on each drive that belongs to the
|
|
* "partition". Note that these "partitions" aren't the same as
|
|
* UNIX partitions.
|
|
*
|
|
* size - number of sectors on each drive that are part of the "partition".
|
|
*
|
|
* The ioctl arg should be a pointer to the following structure.
|
|
* The fields can be set or read via this structure.
|
|
*/
|
|
#define USRAID_SET_PART_PG USRAID_IOC_(0x17)
|
|
#define USRAID_GET_PART_PG USRAID_IOC_(0x18)
|
|
struct usraid_part_page {
|
|
unsigned int base; /* base addr of user data on drive */
|
|
unsigned int size; /* number sectors of user data on each drive */
|
|
};
|