diff -Nurp evms-2.2.2/aclocal.m4 evms-2.2.2-bios/aclocal.m4 --- evms-2.2.2/aclocal.m4 Tue Oct 21 17:56:25 2003 +++ evms-2.2.2-bios/aclocal.m4 Sun Feb 22 15:25:15 2004 @@ -131,11 +131,16 @@ AC_ARG_ENABLE([rsct], [Disable the RSCT plugin]), [build_rsct="$enableval"], [build_rsct="yes"]) +AC_ARG_ENABLE([bios], + AC_HELP_STRING([--disable-bios], + [Disable the BIOS plugin]), + [build_bios="$enableval"], + [build_bios="yes"]) # Create the list of plugin directories to build. This is where each plugin # can specify its dependencies. plugin_dirs="" -plugin_distdirs="aix bbr bbr_seg bsd csm disk dos drivelink ext2 gpt ha jfs lvm mac md ogfs os2 reiser replace rsct s390 snapshot sparse swap xfs" +plugin_distdirs="aix bbr bbr_seg bsd csm disk dos drivelink ext2 gpt ha jfs lvm mac md ogfs os2 reiser replace rsct s390 snapshot sparse swap xfs bios" # AIX if test "$build_aix" = "no"; then @@ -355,6 +360,14 @@ elif test "$have_uuid" = "no"; then else plugin_dirs="$plugin_dirs xfs" AC_MSG_NOTICE([ building xfs]) +fi + +# bios +if test "$build_bios" = "no"; then + AC_MSG_NOTICE([ not building bios ... disabled by user]) +else + plugin_dirs="$plugin_dirs bios" + AC_MSG_NOTICE([ building bios]) fi AC_SUBST(plugin_dirs) diff -Nurp evms-2.2.2/configure evms-2.2.2-bios/configure --- evms-2.2.2/configure Mon Jan 19 17:48:46 2004 +++ evms-2.2.2-bios/configure Sun Feb 22 15:27:31 2004 @@ -866,6 +866,7 @@ Optional Features: --disable-jfs Disable the JFS FSIM --disable-reiser Disable the ReiserFS FSIM --disable-xfs Disable the XFS FSIM + --disable-bios Disable the BIOS plugin --disable-swap Disable the Swap FSIM --disable-replace Disable the Replace plugin --disable-ha Disable the HA plugin @@ -10310,6 +10311,13 @@ if test "${enable_xfs+set}" = set; then else build_xfs="yes" fi; +# Check whether --enable-bios or --disable-bios was given. +if test "${enable_bios+set}" = set; then + enableval="$enable_bios" + build_bios="$enableval" +else + build_bios="yes" +fi; # Check whether --enable-swap or --disable-swap was given. if test "${enable_swap+set}" = set; then enableval="$enable_swap" @@ -10342,7 +10350,7 @@ fi; # Create the list of plugin directories to build. This is where each plugin # can specify its dependencies. plugin_dirs="" -plugin_distdirs="aix bbr bbr_seg bsd csm disk dos drivelink ext2 gpt ha jfs lvm mac md ogfs os2 reiser replace rsct s390 snapshot sparse swap xfs" +plugin_distdirs="aix bbr bbr_seg bsd csm disk dos drivelink ext2 gpt ha jfs lvm mac md ogfs os2 reiser replace rsct s390 snapshot sparse swap xfs bios" # AIX if test "$build_aix" = "no"; then @@ -10626,6 +10634,16 @@ else echo "$as_me: building xfs" >&6;} fi +# BIOS +if test "$build_bios" = "no"; then + { echo "$as_me:$LINENO: not building bios ... disabled by user" >&5 +echo "$as_me: not building bios ... disabled by user" >&6;} +else + plugin_dirs="$plugin_dirs bios" + { echo "$as_me:$LINENO: building bios" >&5 +echo "$as_me: building bios" >&6;} +fi + @@ -10751,7 +10769,7 @@ fi - ac_config_files="$ac_config_files make.rules Makefile lib/Makefile lib/dlist/Makefile engine/Makefile plugins/Makefile plugins/aix/Makefile plugins/bbr/Makefile plugins/bbr_seg/Makefile plugins/bsd/Makefile plugins/csm/Makefile plugins/disk/Makefile plugins/dos/Makefile plugins/drivelink/Makefile plugins/ext2/Makefile plugins/gpt/Makefile plugins/ha/Makefile plugins/jfs/Makefile plugins/lvm/Makefile plugins/mac/Makefile plugins/md/Makefile plugins/ogfs/Makefile plugins/os2/Makefile plugins/reiser/Makefile plugins/replace/Makefile plugins/rsct/Makefile plugins/s390/Makefile plugins/snapshot/Makefile plugins/sparse/Makefile plugins/swap/Makefile plugins/xfs/Makefile ui/Makefile ui/cli/Makefile ui/gtk/Makefile ui/ncurses/Makefile ui/ncurses2/Makefile ui/utils/Makefile include/Makefile doc/Makefile doc/man/Makefile tests/Makefile" + ac_config_files="$ac_config_files make.rules Makefile lib/Makefile lib/dlist/Makefile engine/Makefile plugins/Makefile plugins/aix/Makefile plugins/bbr/Makefile plugins/bbr_seg/Makefile plugins/bsd/Makefile plugins/csm/Makefile plugins/disk/Makefile plugins/dos/Makefile plugins/drivelink/Makefile plugins/ext2/Makefile plugins/gpt/Makefile plugins/ha/Makefile plugins/jfs/Makefile plugins/lvm/Makefile plugins/mac/Makefile plugins/md/Makefile plugins/ogfs/Makefile plugins/os2/Makefile plugins/reiser/Makefile plugins/replace/Makefile plugins/rsct/Makefile plugins/s390/Makefile plugins/snapshot/Makefile plugins/sparse/Makefile plugins/swap/Makefile plugins/xfs/Makefile plugins/bios/Makefile ui/Makefile ui/cli/Makefile ui/gtk/Makefile ui/ncurses/Makefile ui/ncurses2/Makefile ui/utils/Makefile include/Makefile doc/Makefile doc/man/Makefile tests/Makefile" cat >confcache <<\_ACEOF @@ -11335,6 +11353,7 @@ do "plugins/sparse/Makefile" ) CONFIG_FILES="$CONFIG_FILES plugins/sparse/Makefile" ;; "plugins/swap/Makefile" ) CONFIG_FILES="$CONFIG_FILES plugins/swap/Makefile" ;; "plugins/xfs/Makefile" ) CONFIG_FILES="$CONFIG_FILES plugins/xfs/Makefile" ;; + "plugins/bios/Makefile" ) CONFIG_FILES="$CONFIG_FILES plugins/bios/Makefile" ;; "ui/Makefile" ) CONFIG_FILES="$CONFIG_FILES ui/Makefile" ;; "ui/cli/Makefile" ) CONFIG_FILES="$CONFIG_FILES ui/cli/Makefile" ;; "ui/gtk/Makefile" ) CONFIG_FILES="$CONFIG_FILES ui/gtk/Makefile" ;; diff -Nurp evms-2.2.2/plugins/bios/Makefile.in evms-2.2.2-bios/plugins/bios/Makefile.in --- evms-2.2.2/plugins/bios/Makefile.in Thu Jan 1 01:00:00 1970 +++ evms-2.2.2-bios/plugins/bios/Makefile.in Fri Feb 27 21:20:57 2004 @@ -0,0 +1,52 @@ +# Enterprise Volume Management System +# +# (C) Copyright IBM Corp. 2003 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +# the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +include @top_srcdir@/make.rules + +NAME = bios +TARGET = $(PLUGIN_TARGET) + +MAJOR_VERSION = 0 +MINOR_VERSION = 0 +PATCH_LEVEL = 0 + +EVMS_DEFS += -D_FILEOFFSET_BITS=64 + +all: $(TARGET) + +$(TARGET): .depend .export $(OBJECTS) + $(BUILD_PLUGIN) + +install: all + $(MKINSTALLDIRS) $(DESTDIR)$(evmspluginsdir) + $(INSTALL) -m 755 $(TARGET) $(DESTDIR)$(evmspluginsdir) + +uninstall: + rm -f $(DESTDIR)$(evmspluginsdir)/$(TARGET) + +clean: + rm -f .depend .export $(OBJECTS) $(TARGET) + +distclean: clean + rm -f Makefile + +ifeq (.depend, $(wildcard .depend)) +include .depend +endif diff -Nurp evms-2.2.2/plugins/bios/bios.c evms-2.2.2-bios/plugins/bios/bios.c --- evms-2.2.2/plugins/bios/bios.c Thu Jan 1 01:00:00 1970 +++ evms-2.2.2-bios/plugins/bios/bios.c Fri Feb 27 21:22:03 2004 @@ -0,0 +1,1355 @@ +/* + * (C) Copyright IBM Corp. 2001, 2003 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * BIOS Disk Manager plugin. + * + * Wilfried Weissmann (c) 2004 + * + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "bios.h" + +engine_functions_t * EngFncs = NULL; + +char * sysfs_mount_point; /* FIXME: use sysfs */ + +#define IDEDIR "/proc/ide" + +/** + * hptdisk + * + * structure for defining a disk that is attachted to the HPT37x controller + **/ +struct hptdisk { + char devname[PATH_MAX]; /* define name of the disk */ + char claimed; /* set to true if the disk + is attachted to a raid volume */ + struct highpoint_raid_conf superblock; + int hardsector_size; + int32_t major; + int32_t minor; + int block_size; + + struct hptdisk * next; +}; + +/** + * hptraid + * + * structure for a hpt-raid volume + **/ +struct hptraid { + char name[PATH_MAX]; /* device name of volume */ + unsigned int stride; /* stripesize */ + unsigned int disks; /* number of disks in array */ + u_int64_t sectors; /* disksize in sectors */ + u_int32_t magic_0; + u_int32_t magic_1; + u_int8_t type; /* raid level (raid-0, raid-1, ...) */ + u_int32_t hardsector_size; + int block_size; + + enum {setup=0, operational, broken} status; + + dm_target_t * dm_target; /* data structure for the device + mapper */ + + struct hptdisk * disk[8]; /* pointers to the disks of the + raid volume */ + + int fd; /* filedestriptor for open_dev(), + LD_read/write(), ... */ + + struct hptraid * next; +}; + +static struct hptdisk * scanlist=NULL; /* linked list of disk attached to + the hpt37x controller */ + +static struct hptraid * raidlist=NULL; /* linked list of detected raid + volumes */ + +/** + * isHardDisk + * @hd: pathname of HD in proc filesystem + * + * returns true if the device is a hard disk + **/ +static int isHardDisk(const char *hd) { + char buffer[50]; + FILE *fd; + + strncpy(buffer, hd, sizeof(buffer) - 1); + strncat(buffer, "/media", sizeof(buffer) - 1); + + fd=fopen(buffer, "r"); + + if( !fd ) { + return 0; + } + + fgets(buffer, sizeof(buffer)-1, fd); + + fclose(fd); + + return strcmp(buffer, "disk\n")?0:1; +} + +/** + * loadHPTConf + * @disk: disk structure of the harddisk + * + * loads the raid configuration data into the disk parameter structure + **/ +static int loadHPTConf(struct hptdisk * disk) { + struct stat stat; + int fd=open(disk->devname, O_RDONLY); + + if(fd < 0) { + return 0; /* cannot open disk */ + } + + if(fstat(fd, &stat) == -1) goto err; + + disk->minor=minor(stat.st_rdev); + disk->major=major(stat.st_rdev); + + if(ioctl(fd, BLKSSZGET, &(disk->hardsector_size)) == -1) goto err; + + if(ioctl(fd, BLKBSZGET, &(disk->block_size)) == -1) goto err; + + if(lseek(fd, CONFIGOFFSET, SEEK_SET) == -1) goto err; + + if(read(fd, (void *) &disk->superblock, sizeof(struct highpoint_raid_conf)) != + sizeof(struct highpoint_raid_conf)) goto err; + + close(fd); + return 1; + +err: + close(fd); + return 0; +} + +/** + * addDisk + * @name: device node of the harddisk (without heading "/dev/") + * + * allocates the disk structure and load the raid configuration data + **/ +static struct hptdisk * addDisk(const char *name) { + + struct hptdisk * disk=EngFncs->engine_alloc(sizeof(struct hptdisk)); + + if(!disk) { + return NULL; /* Oops: out of memory! */ + } + + memset(disk, 0, sizeof(struct hptdisk)); + + strcpy(disk->devname, "/dev/"); + strcat(disk->devname, name); + + if(loadHPTConf(disk) && disk->superblock.magic == 0x5a7816f0) { + disk->next=scanlist; /* add disk */ + scanlist=disk; + } else { + EngFncs->engine_free(disk); /* no config block => remove */ + disk=NULL; + } + + return disk; +} + +/** + * hpt370xScan + * @name: path to the controller directory in proc-fs + * @vendor: pci vendor id of the ide controller + * @device: pci device id of the ide controller + * + * scans the attached harddisks of the ide controller + **/ +static void hpt37xScan(const char *name, int vendor, int device) { + DIR *ctrldir; + struct dirent *dir; + struct hptdisk * current; + char buffer[50]=IDEDIR "/"; + char hdpath[50]; + + switch(vendor) { /* FIXME: this only supports the HPT370A */ + case 0x1103: + break; + default: + return; + } + + switch(device) { + case 0x0004: + break; + default: + return; + } + + strncat(buffer, name, sizeof(buffer) - 1); + + ctrldir=opendir(buffer); + + if( !ctrldir ) { + perror(buffer); + return; + } + + while( (dir = readdir(ctrldir)) ) { + if( (dir->d_type == DT_DIR) && + !(strncmp(dir->d_name, "hd", 2)) ) { + + strncpy(hdpath, buffer, sizeof(buffer) - 1); + strncat(hdpath, "/", sizeof(buffer) - 1); + strncat(hdpath, dir->d_name, sizeof(buffer) - 1); + + if(isHardDisk(hdpath)) { + current=scanlist; + + while(current) { + if(!strcmp(current->devname+strlen("/dev/"), + dir->d_name)) { + break; /* disk is already there */ + } + current=current->next; + } + + /* add disk to scan list if disk is new*/ + if(!current) { + addDisk(dir->d_name); + } + } + } + } + + + closedir(ctrldir); +} + +/** + * findIDECtrl + * + * scan for supported IDE controllers and datafill the scanlist with + * the attached harddisks + **/ +static int findIDECtrl() { + DIR *idedir; + struct dirent * dir; + + idedir = opendir( IDEDIR ); + + if( ! idedir ) { + perror(IDEDIR); + return -1; + } + + while( (dir = readdir(idedir)) ) { + if( (dir->d_type == DT_DIR) && + !(strncmp(dir->d_name, "ide", 3)) ) { + + char config[50]=IDEDIR "/"; + FILE *fd; + int vendor, device; + + strncat(config, dir->d_name, sizeof(config)-1); + strncat(config, "/config", sizeof(config)-1); + + fd=fopen(config, "r"); + + if( !fd ) { + perror(config); + continue; + } + + if( fscanf(fd, "pci bus %*i device %*i vendor %x device %x", + &vendor, &device) == 2) { + + hpt37xScan(dir->d_name, vendor, device); + } + + fclose(fd); + } + } + + closedir(idedir); + return 0; +} + +/** + * round_down + * @value: Value (in sectors) to be rounded down. + * @boundary: Boundary (in bytes) to round-down to. + * + * Given a value, round it down to be a multiple of the specified boundary size. + **/ +static inline sector_count_t round_down(sector_count_t value, + u_int32_t boundary) +{ + sector_count_t boundary_in_vsectors = ((sector_count_t)boundary) >> + EVMS_VSECTOR_SIZE_SHIFT; + return (boundary > EVMS_VSECTOR_SIZE) ? + (value & ~(boundary_in_vsectors - 1)) : value; +} + +/** + * round_up + * @value: Value (in sectors) to be rounded up. + * @boundary: Boundary (in bytes) to round-up to. + * + * Given a value, round it up to be a multiple of the specified boundary size. + **/ +static inline sector_count_t round_up(sector_count_t value, + u_int32_t boundary) +{ + sector_count_t boundary_in_vsectors = ((sector_count_t)boundary) >> + EVMS_VSECTOR_SIZE_SHIFT; + sector_count_t temp_value = value + boundary_in_vsectors - 1; + return (boundary > EVMS_VSECTOR_SIZE) ? + (temp_value & ~(boundary_in_vsectors - 1)) : value; +} + +/** + * where_is_sysfs + * + * Is sysfs mounted. If so, return the mount point. The caller must free the + * returned string. + **/ +static boolean where_is_sysfs(char ** mount_name) +{ + boolean result = FALSE; + FILE * mount_records; + struct mntent * mount_entry; + + LOG_ENTRY(); + + if (mount_name) { + *mount_name = NULL; + } + + mount_records = setmntent(MOUNTED, "r"); + if (mount_records == NULL) { + mount_records = setmntent("/proc/mounts", "r"); + } + if (mount_records == NULL) { + LOG_ERROR("Could not get list of mounted devices.\n"); + goto out; + } + + while (!result && (mount_entry = getmntent(mount_records)) != NULL) { + if (strcmp(mount_entry->mnt_type, "sysfs") == 0) { + result = TRUE; + if (mount_name) { + *mount_name = strdup(mount_entry->mnt_dir); + } + } + } + + endmntent(mount_records); + +out: + LOG_EXIT_BOOL(result); + return result; +} + +static int LD_setup(engine_functions_t * engine_function_table) +{ + /* save info we get from the engine */ + EngFncs = engine_function_table; + + LOG_ENTRY(); + + where_is_sysfs(&sysfs_mount_point); + + LOG_EXIT_INT(0); + return 0; +} + +/** + * open_dev + * + * Open the specified disk. Use O_DIRECT to avoid caching. Use O_SYNC in case + * the kernel does not honor O_DIRECT. Use the Engine's service so we + * automatically get a dev-node in the /dev/evms/.nodes/ tree. Record the + * file handle in the disk's private data. + **/ +static int open_dev(storage_object_t * disk) +{ + int rc = 0; + int * fd = &((struct hptraid *)disk->private_data)->fd; + + LOG_ENTRY(); + + if (*fd <= 0) { + *fd = EngFncs->open_object(disk, O_RDWR | O_DIRECT | O_SYNC); + if (*fd < 0) { + rc = -*fd; + LOG_DEBUG("Error opening disk %s: %d: %s\n", + disk->name, rc, strerror(rc)); + } + } + + LOG_EXIT_INT(rc); + return rc; +} + +/** + * close_dev + * + * Close the disk and clear the file handle. + **/ +static void close_dev(storage_object_t * disk) +{ + int * fd = &((struct hptraid *)disk->private_data)->fd; + int rc; + + LOG_ENTRY(); + + if (*fd >= 0) { + rc = EngFncs->close_object(disk, *fd); + if (!rc) { + *fd = -1; + } + } + + LOG_EXIT_VOID(); +} + +/** + * LD_cleanup + * + * Find any disks and close the device that was opended during discovery. + **/ +static void LD_cleanup(void) +{ + int rc; + dlist_t disk_list; + storage_object_t * disk; + struct hptraid * raid; + + LOG_ENTRY(); + + /* Get a list of disks that are managed by this plug-in. */ + rc = EngFncs->get_object_list(DISK, 0, my_plugin_record, + NULL, 0, &disk_list); + if (!rc) { + /* Close any dev handles that might be open. */ + DLIST_FOR_EACH(disk, disk_list, rc) { + raid = (struct hptraid *)disk->private_data; + if(raid->status == operational) { + EngFncs->dm_deactivate(disk); + EngFncs->dm_deallocate_targets(raid->dm_target); + close_dev(disk); + } + EngFncs->engine_free(disk->private_data); + } + DestroyList(&disk_list, FALSE); + } + + if (sysfs_mount_point) { + free(sysfs_mount_point); + sysfs_mount_point = NULL; + } + + LOG_EXIT_VOID(); +} + +/** + * get_block_size + * + * Use the BLKBSZGET ioctl to get the block-size for the specified disk. + **/ +static int get_block_size(storage_object_t * disk) +{ + int fd = ((struct hptraid *)disk->private_data)->fd; + int rc, block_size; + + LOG_ENTRY(); + + rc = ioctl(fd, BLKBSZGET, &block_size); + if (rc) { + rc = errno; + LOG_ERROR("Error getting block size for disk %s: %d: %s.\n", + disk->name, rc, strerror(rc)); + } else { + LOG_DEBUG("Disk %s has block-size %d.\n", + disk->name, block_size); + disk->geometry.block_size = block_size; + } + + LOG_EXIT_INT(rc); + return rc; +} + +/** + * set_block_size + * + * Use the BLKBSZSET ioctl to set the disk's block-size. + **/ +static int set_block_size(storage_object_t * disk, int block_size) +{ + int rc; + int fd = ((struct hptraid *)disk->private_data)->fd; + + LOG_ENTRY(); + + rc = ioctl(fd, BLKBSZSET, &block_size); + if (rc) { + rc = errno; + LOG_ERROR("Error setting block size (%d) for disk %s: %d: " + "%s.\n", block_size, disk->name, rc, strerror(rc)); + } else { + LOG_DEBUG("Setting disk %s block-size to %d.\n", + disk->name, block_size); + disk->geometry.block_size = block_size; + } + + LOG_EXIT_INT(rc); + return rc; +} + +/** + * create_logical_disk + * + * Allocate a new disk and initialize all fields. + **/ +static storage_object_t * create_logical_disk(struct hptraid * raid) +{ + storage_object_t * disk = NULL; + int rc; + + LOG_ENTRY(); + + rc = EngFncs->allocate_logical_disk(raid->name, &disk); + if (rc) { + LOG_SERIOUS("Error allocating new disk object for disk %s: %d: " + "%s.\n", raid->name, rc, EngFncs->strerror(rc)); + goto out; + } + + disk->data_type = DATA_TYPE; + disk->private_data = raid; + disk->plugin = my_plugin_record; + disk->size=raid->sectors; + disk->geometry.cylinders=raid->sectors / ( 255 * 63 ); + disk->geometry.heads=255; + disk->geometry.sectors_per_track=63; + disk->geometry.block_size=raid->block_size; + disk->geometry.bytes_per_sector=raid->hardsector_size; + +out: + LOG_EXIT_PTR(disk); + return disk; +} + +/** + * hptRAIDScan + * @index: index number of the raid volume + * + * scans the "scanlist" of harddisks to detect hpt-raid volumes. return the + * allocated and datafilled hptraid structure and adds it to the raidlist. + * when no more volumes were found then NULL is returned. this function also + * detects "non-operatinal" volumes (e.g.: volumes with too less disks to + * become active). + **/ +static struct hptraid * hptRAIDScan(int index) { + struct hptdisk * current; + struct hptraid * raid=EngFncs->engine_alloc(sizeof(struct hptraid)); + + if(!raid) { + return NULL; + } + + memset(raid, 0, sizeof(struct hptraid)); + + sprintf(raid->name, "hptraid%ip", index); + + /* walk the scanlist of attached harddisks */ + for(current=scanlist; current; current=current->next) { + + if(current->claimed) continue; + + /* unclaimed disk => scan */ + + if(raid->disks) { + /* raid is not empty => check magic cookie */ + if(raid->magic_0 != current->superblock.magic_0) { + continue; + } + } + else { + /* raid is empty => accept any magic cookie */ + raid->magic_0 = current->superblock.magic_0; + } + + /* check for known raid types */ + switch(current->superblock.type) { + case HPT_T_RAID_0: + break; + default: + continue; + } + + if(current->superblock.disk_number > 8) { + continue; + } + + /* add disk to raid volume */ + raid->disk[current->superblock.disk_number]=current; + /* shift in sectors */ + raid->stride=1<superblock.raid0_shift; + raid->disks=current->superblock.raid_disks; + /* superblock contains size in sectors - 1 */ + raid->sectors=current->superblock.total_secs; + raid->magic_1 = current->superblock.magic_1; + raid->hardsector_size=current->hardsector_size; + raid->block_size=current->block_size; + + /* + * FIXME: re-enable to access the last sector + * + * the device mapper is only happy if + * (volume size)%(number of disks) == 0 + * + * maybe we can lie to the device mapper and tell it + * that the volume is bigger so that the expression from above + * is true. then use the true values for the evms engine to get + * the correct volume sizes. + */ +#if 0 + if (EngFncs->is_2_4_kernel()) { + /* round down to 1024 bytes boundary */ +#endif + raid->sectors += raid->sectors&1?1:0; +#if 0 + } + else { + raid->sectors++; + } +#endif + + current->claimed=1; + } + + if(raid->disks == 0) { + EngFncs->engine_free(raid); + return NULL; + } + + raid->next=raidlist; /* add to raid list */ + raidlist=raid; + + return raid; +} + +/** + * hptRAIDInit + * @raid: raid volume to be activated + * @output_list: output list for LD_discover() + * + * activate the raid volume and add is the the volume output_list + **/ +static int hptRAIDInit(struct hptraid * raid, dlist_t output_list) { + int disks=0, count; + storage_object_t * object; + void * handle; + + /* raid is already running */ + if(raid->status == operational) { + return 0; + } + + for(count=0; count < 8; count++) { + if(raid->disk[count]) { + disks++; + } + } + + if(raid->disks != disks) { /* missing disks */ + LOG_SERIOUS("Missing disks in %s (%i of %i).\n", raid->name, disks, raid->disks); + goto err; + } + + /* datafill device mapper structures */ + raid->dm_target = EngFncs->dm_allocate_target(DM_TARGET_STRIPE, 0, + raid->sectors, raid->disks); + + raid->dm_target->data.stripe->chunk_size=raid->stride; + raid->dm_target->data.stripe->num_stripes=raid->disks; + for(count=0; count < raid->disks; count++) { + struct dm_device * dm_device=raid->dm_target->data.stripe->devices+count; + struct hptdisk * hptdisk=raid->disk[count]; + dm_device->major=hptdisk->major; + dm_device->minor=hptdisk->minor; + dm_device->start=count?10:0; + } + + object=create_logical_disk(raid); + if(!object) { + LOG_SERIOUS("Failed to create %s.\n", raid->name); + goto err1; + } + + if( EngFncs->dm_activate(object, raid->dm_target) ) { + LOG_SERIOUS("Failed to activate %s.\n", object->name); + goto err2; + } + + LOG_DETAILS("New Logical Disk:\n"); + LOG_DETAILS(" name: %s\n", object->name); + LOG_DETAILS(" size: %"PRIu64"\n", object->size); + LOG_DETAILS(" device-number: %x:%x\n", object->dev_major, object->dev_minor); + LOG_DETAILS(" geometry:\n"); + LOG_DETAILS(" cylinders: %"PRIu64"\n", object->geometry.cylinders); + LOG_DETAILS(" heads: %d\n", object->geometry.heads); + LOG_DETAILS(" sectors: %d\n", object->geometry.sectors_per_track); + LOG_DETAILS(" sector size: %d (bytes)\n", object->geometry.bytes_per_sector); + LOG_DETAILS(" block size: %"PRIu64" (bytes)\n", object->geometry.block_size); + + open_dev(object); + + /* Insert the new disk into ouput list. */ + if( InsertObject(output_list, object, DISK_TAG, NULL, + AppendToList, TRUE, &handle) ) { + LOG_SERIOUS("Error adding new disk %s to output list. " + "Deleting the disk.\n", object->name); + EngFncs->engine_free(object->private_data); + EngFncs->free_logical_disk(object); + goto err; + } + + raid->status=operational; + return 1; + +err2: + EngFncs->free_logical_disk(object); +err1: + EngFncs->dm_deallocate_targets(raid->dm_target); +err: + raid->status=broken; + return 0; +} + +/** + * LD_discover + **/ +static int LD_discover(dlist_t input_list, + dlist_t output_list, + boolean final_call) +{ + int i; + struct hptraid * raid; + + LOG_ENTRY(); + + findIDECtrl(); /* get list of scan devices */ + + for(i=0; (raid=hptRAIDScan(i)); i++) { + hptRAIDInit(raid, output_list); + } + + GetListSize(output_list, &i); + LOG_DEBUG("Discovered %d disks.\n", i); + LOG_EXIT_INT(0); + return 0; +} + +/** + * get_alignment_size + * + * Return the size (in bytes) of the alignment restrictions for O_DIRECT. On + * 2.5 kernels, this will be the disk's hard-sector-size. On 2.4 kernels, this + * will be the disk's block-size. Since block-size can change at run-time, + * always check the current block-size. Also, since we want access to as much + * of the disk as possible, try to set the block-size to 1k if it isn't + * already. + **/ +static int get_alignment_size(storage_object_t * disk) +{ + int size; + int min_block_size = max(disk->geometry.bytes_per_sector, 1024); + + LOG_ENTRY(); + + if (EngFncs->is_2_4_kernel()) { + get_block_size(disk); + size = disk->geometry.block_size; + if (size > min_block_size) { + set_block_size(disk, min_block_size); + size = disk->geometry.block_size; + } + } else { + size = disk->geometry.bytes_per_sector; + } + + LOG_EXIT_INT(size); + return size; +} + +/** + * get_aligned_buffer + * @offset: Starting offset (in sectors) of engine I/O request. + * @count: Size (in sectors) of engine I/O request. + * @align_size: Size (in bytes) that the I/O must be aligned on. + * @local_offset: Aligned starting offset (in sectors). + * @local_count: Aligned I/O size (in sectors). + * @local_buffer: New data buffer. Not aligned, but need to return this + * pointer so it can be freed after using. + * @local_buffer_aligned: Aligned data buffer. This points somewhere + * within local_buffer. + * + * To use O_DIRECT, the buffer passed to read() or write() must be aligned on + * the device's block/sector size. The size and starting offset of the I/O must + * also be a multiple of the block/sector size. + **/ +static int get_aligned_buffer(lsn_t offset, + sector_count_t count, + int align_size, + lsn_t * local_offset, + sector_count_t * local_count, + void ** local_buffer, + void ** local_buffer_aligned) +{ + u_int32_t offset_diff, offset_diff_bytes; + u_int32_t local_buffer_bytes; + u_int32_t alignment_base, alignment_diff; + int rc = 0; + + LOG_ENTRY(); + + /* Round down starting offset to the alignment size. */ + *local_offset = round_down(offset, align_size); + + /* Difference between real offset and local offset. */ + offset_diff = offset - *local_offset; + offset_diff_bytes = offset_diff << EVMS_VSECTOR_SIZE_SHIFT; + + /* Round up total count of sectors to alignment size. */ + *local_count = round_up(count + offset_diff, align_size); + + /* Allocate the buffer that will actually perform the I/O. This needs + * to allocate enough extra to compensate for the alignment that will + * occur next. + */ + local_buffer_bytes = *local_count << EVMS_VSECTOR_SIZE_SHIFT; + *local_buffer = EngFncs->engine_alloc(local_buffer_bytes + + align_size - 1); + if (!*local_buffer) { + rc = ENOMEM; + goto out; + } + + /* Align the buffer on hard-sector-size. */ + alignment_base = (unsigned long)(*local_buffer) & (align_size - 1); + alignment_diff = (alignment_base + align_size - 1) & ~(align_size - 1); + alignment_diff -= alignment_base; + *local_buffer_aligned = *local_buffer + alignment_diff; + + /* Sanity check */ + if (((unsigned long)(*local_buffer_aligned) % align_size) != 0) { + LOG_ERROR("BUFFER NOT ALIGNED!!: buf: %p, size: %u\n", + *local_buffer_aligned, align_size); + } + +out: + LOG_EXIT_INT(rc); + return rc; +} + +/** + * LD_read + **/ +static int LD_read(storage_object_t * disk, + lsn_t offset, + sector_count_t count, + void * buffer) +{ + void * local_buffer = NULL, * local_buffer_aligned; + lsn_t local_offset; + sector_count_t local_count; + int fd = ((struct hptraid *)disk->private_data)->fd; + int rc, align_size; + + LOG_ENTRY(); + LOG_DEBUG("Read disk:%s offset:%"PRIu64" count:%"PRIu64"\n", + disk->name, offset, count); + + if (offset + count > disk->size) { + LOG_ERROR("Read request past end of disk.\n"); + rc = EINVAL; + goto out; + } + + /* Make sure the disk is open. */ + rc = open_dev(disk); + if (rc) { + goto out; + } + + /* Get the alignment restriction for O_DIRECT. */ + align_size = get_alignment_size(disk); + + /* Get a data buffer aligned with this restriction. */ + rc = get_aligned_buffer(offset, count, align_size, + &local_offset, &local_count, + &local_buffer, &local_buffer_aligned); + if (rc) { + goto out; + } + + /* Send the read to the engine. */ + rc = EngFncs->read_object(disk, fd, local_buffer_aligned, + local_count << EVMS_VSECTOR_SIZE_SHIFT, + local_offset << EVMS_VSECTOR_SIZE_SHIFT); + if (rc < 0) { + rc = -rc; + goto out; + } + + /* Copy the data back to the caller's buffer. */ + memcpy(buffer, local_buffer_aligned + + ((offset - local_offset) << EVMS_VSECTOR_SIZE_SHIFT), + count << EVMS_VSECTOR_SIZE_SHIFT); + + rc = 0; + +out: + EngFncs->engine_free(local_buffer); + LOG_EXIT_INT(rc); + return rc; +} + +/** + * LD_write + **/ +static int LD_write(storage_object_t * disk, + lsn_t offset, + sector_count_t count, + void * buffer) +{ + void * local_buffer = NULL, * local_buffer_aligned; + lsn_t local_offset; + sector_count_t local_count; + int fd = ((struct hptraid *)disk->private_data)->fd; + int rc, align_size; + + LOG_ENTRY(); + LOG_DEBUG("Write disk:%s offset:%"PRIu64" count:%"PRIu64"\n", + disk->name, offset, count); + + if (offset + count > disk->size) { + LOG_ERROR("Write request past end of disk.\n"); + rc = EINVAL; + goto out; + } + + /* Make sure the disk is open. */ + rc = open_dev(disk); + if (rc) { + goto out; + } + + /* Get the alignment restriction for O_DIRECT. */ + align_size = get_alignment_size(disk); + + /* Get a data buffer aligned with this restriction. */ + rc = get_aligned_buffer(offset, count, align_size, + &local_offset, &local_count, + &local_buffer, &local_buffer_aligned); + if (rc) { + goto out; + } + + if (local_count != count) { + rc = EngFncs->read_object(disk, fd, local_buffer_aligned, + local_count << EVMS_VSECTOR_SIZE_SHIFT, + local_offset << EVMS_VSECTOR_SIZE_SHIFT); + if (rc < 0) { + rc = -rc; + goto out; + } + } + + /* Put user data at the right place in the buffer */ + memcpy(local_buffer_aligned + + ((offset - local_offset) << EVMS_VSECTOR_SIZE_SHIFT), + buffer, count << EVMS_VSECTOR_SIZE_SHIFT); + + /* Send the write to the engine. */ + rc = EngFncs->write_object(disk, fd, local_buffer_aligned, + local_count << EVMS_VSECTOR_SIZE_SHIFT, + local_offset << EVMS_VSECTOR_SIZE_SHIFT); + if (rc < 0) { + rc = -rc; + goto out; + } + + rc = 0; + +out: + EngFncs->engine_free(local_buffer); + LOG_EXIT_INT(rc); + return rc; +} + +/** + * LD_add_sectors_to_kill_list + **/ +static int LD_add_sectors_to_kill_list(storage_object_t * disk, + lsn_t lsn, + sector_count_t count) +{ + int rc; + LOG_ENTRY(); + + if (lsn + count > disk->size) { + LOG_ERROR("Kill-sectors request past end of disk %s.\n", + disk->name); + rc = EINVAL; + } else { + rc = EngFncs->add_sectors_to_kill_list(disk, lsn, count); + } + + LOG_EXIT_INT(rc); + return rc; +} + +/** + * LD_commit_changes + * + * Disk manager doesn't do anything during commit. Just return success. + **/ +static int LD_commit_changes(storage_object_t * disk, commit_phase_t phase) +{ + LOG_ENTRY(); + LOG_EXIT_INT(0); + return 0; +} + +/** + * LD_get_info + * + * Returns DISK specific information + **/ +static int LD_get_info(storage_object_t * disk, + char * descriptor_name, + extended_info_array_t ** info) +{ + extended_info_array_t * Info; + uint count = 0; + int index = 0, rc = EINVAL; + + LOG_ENTRY(); + + if (!info) { + goto out; + } + *info = NULL; + + if (descriptor_name) { + goto out; + } + + Info = EngFncs->engine_alloc(sizeof(extended_info_array_t) + + 8 * sizeof(extended_info_t)); + if (!Info) { + rc = ENOMEM; + goto out; + } + + SET_STRING(Info->info[index].name, "Name"); + SET_STRING(Info->info[index].title, "Name"); + SET_STRING(Info->info[index].desc, "EVMS name for the DISK storage object"); + Info->info[index].type = EVMS_Type_String; + SET_STRING(Info->info[index].value.s, disk->name); + index++; + + SET_STRING(Info->info[index].name, "Size"); + SET_STRING(Info->info[index].title, "Size"); + SET_STRING(Info->info[index].desc, "Size of the disk in sectors"); + Info->info[index].type = EVMS_Type_Unsigned_Int64; + Info->info[index].unit = EVMS_Unit_Sectors; + Info->info[index].flags |= EVMS_EINFO_FLAGS_NO_UNIT_CONVERSION; + Info->info[index].value.ui64 = disk->size; + index++; + + SET_STRING(Info->info[index].name, "Cyl"); + SET_STRING(Info->info[index].title, "Cylinders"); + SET_STRING(Info->info[index].desc, "Drive geometry -- number of cylinders"); + Info->info[index].type = EVMS_Type_Unsigned_Int64; + Info->info[index].value.ui64 = disk->geometry.cylinders; + index++; + + SET_STRING(Info->info[index].name, "Heads"); + SET_STRING(Info->info[index].title, "Heads"); + SET_STRING(Info->info[index].desc, "Drive geometry -- number of heads"); + Info->info[index].type = EVMS_Type_Unsigned_Int32; + Info->info[index].value.ui32 = disk->geometry.heads; + index++; + + SET_STRING(Info->info[index].name, "Sectors"); + SET_STRING(Info->info[index].title, "Sectors"); + SET_STRING(Info->info[index].desc, "Drive geometry -- sectors per track"); + Info->info[index].type = EVMS_Type_Unsigned_Int32; + Info->info[index].value.ui32 = disk->geometry.sectors_per_track; + index++; + + SET_STRING(Info->info[index].name, "SectorSize"); + SET_STRING(Info->info[index].title, "Sector Size"); + SET_STRING(Info->info[index].desc, "Number of bytes per sector"); + Info->info[index].type = EVMS_Type_Unsigned_Int32; + Info->info[index].unit = EVMS_Unit_Bytes; + Info->info[index].value.ui32 = disk->geometry.bytes_per_sector; + index++; + + SET_STRING(Info->info[index].name, "BlockSize"); + SET_STRING(Info->info[index].title, "Block Size"); + SET_STRING(Info->info[index].desc, "Number of bytes per block"); + Info->info[index].type = EVMS_Type_Unsigned_Int64; + Info->info[index].unit = EVMS_Unit_Bytes; + Info->info[index].value.ui64 = disk->geometry.block_size; + index++; + + SET_STRING(Info->info[index].name, "BootLimit"); + SET_STRING(Info->info[index].title, "Boot Cylinder Limit"); + SET_STRING(Info->info[index].desc, "LBA of the first sector above the boot cylinder limit for this drive"); + Info->info[index].type = EVMS_Type_Unsigned_Int64; + Info->info[index].value.ui64 = disk->geometry.boot_cylinder_limit; + index++; + + GetListSize(disk->parent_objects, &count); + SET_STRING(Info->info[index].name, "Segments"); + SET_STRING(Info->info[index].title, "Segments"); + SET_STRING(Info->info[index].desc, "Number of segments discovered on the drive (metadata, data, freespace)"); + Info->info[index].type = EVMS_Type_Unsigned_Int32; + Info->info[index].value.ui32 = count; + index++; + + Info->count = index; + *info = Info; + rc = 0; + +out: + LOG_EXIT_INT(rc); + return rc; +} + +/** + * LD_get_plugin_info + * + * Returns plug-in specific information + **/ +static int LD_get_plugin_info(char * descriptor_name, + extended_info_array_t ** info) +{ + int rc = EINVAL; + extended_info_array_t * Info; + char version_string[64]; + char required_engine_api_version_string[64]; + char required_plugin_api_version_string[64]; + + LOG_ENTRY(); + + if (!info) { + goto out; + } + *info = NULL; + + if (descriptor_name) { + goto out; + } + + Info = EngFncs->engine_alloc(sizeof(extended_info_array_t) + + 6 * sizeof(extended_info_t)); + if (!Info) { + rc = ENOMEM; + goto out; + } + + Info->count = 6; + + sprintf(version_string, "%d.%d.%d", + MAJOR_VERSION, MINOR_VERSION, PATCH_LEVEL); + + sprintf(required_engine_api_version_string, "%d.%d.%d", + my_plugin_record->required_engine_api_version.major, + my_plugin_record->required_engine_api_version.minor, + my_plugin_record->required_engine_api_version.patchlevel); + + sprintf(required_plugin_api_version_string, "%d.%d.%d", + my_plugin_record->required_plugin_api_version.plugin.major, + my_plugin_record->required_plugin_api_version.plugin.minor, + my_plugin_record->required_plugin_api_version.plugin.patchlevel); + + SET_STRING(Info->info[0].name, "Short Name"); + SET_STRING(Info->info[0].title, "Short Name"); + SET_STRING(Info->info[0].desc, "A short name given to this plugin"); + Info->info[0].type = EVMS_Type_String; + SET_STRING(Info->info[0].value.s, my_plugin_record->short_name); + + SET_STRING(Info->info[1].name, "Long Name"); + SET_STRING(Info->info[1].title, "Long Name"); + SET_STRING(Info->info[1].desc, "A long name given to this plugin"); + Info->info[1].type = EVMS_Type_String; + SET_STRING(Info->info[1].value.s, my_plugin_record->long_name); + + SET_STRING(Info->info[2].name, "Type"); + SET_STRING(Info->info[2].title, "Plug-in Type"); + SET_STRING(Info->info[2].desc, "There are various types of plugins, each responsible for some kind of storage object."); + Info->info[2].type = EVMS_Type_String; + SET_STRING(Info->info[2].value.s, "Device Manager"); + + SET_STRING(Info->info[3].name, "Version"); + SET_STRING(Info->info[3].title, "Plugin Version"); + SET_STRING(Info->info[3].desc, "Version number of this plug-in"); + Info->info[3].type = EVMS_Type_String; + SET_STRING(Info->info[3].value.s, version_string); + + SET_STRING(Info->info[4].name, "Required Engine Services Version"); + SET_STRING(Info->info[4].title, "Required Engine Services Version"); + SET_STRING(Info->info[4].desc, "Version of the Engine services that this plug-in requires. It will not run on older versions of the Engine services."); + Info->info[4].type = EVMS_Type_String; + SET_STRING(Info->info[4].value.s, required_engine_api_version_string); + + SET_STRING(Info->info[5].name, "Required Plug-in API Version"); + SET_STRING(Info->info[5].title, "Required Plug-in API Version"); + SET_STRING(Info->info[5].desc, "Version of the Engine plug-in API that this plug-in requires. It will not run on older versions of the Engine plug-in API."); + Info->info[5].type = EVMS_Type_String; + SET_STRING(Info->info[5].value.s, required_plugin_api_version_string); + + *info = Info; + rc = 0; + +out: + LOG_EXIT_INT(rc); + return rc; +} + +/** + * LD_direct_plugin_communication + * + * Device-manager-specific commands for starting and stopping the cache, and + * opening and closing a disk. + **/ +static int LD_direct_plugin_communication(void * object, + boolean target_kernel_plugin, + void * arg) +{ + int rc = 0; + storage_object_t * disk = object; + ldm_dpc_t * dcp = arg; + + LOG_ENTRY(); + if (disk) { + LOG_DEBUG("Action targeted at %s.\n", disk->name); + } + + switch (dcp->function) { + + case START_CACHE: + LOG_DEBUG("START_CACHE\n"); + break; + + case STOP_CACHE: + LOG_DEBUG("STOP_CACHE\n"); + break; + + case LDM_CLOSE_DISK: + LOG_DEBUG("LDM_CLOSE_DISK\n"); + close_dev(disk); + break; + + case LDM_OPEN_DISK: + LOG_DEBUG("LDM_OPEN_DISK\n"); + rc = open_dev(disk); + break; + + default: + LOG_ERROR("%d is not a valid function code.\n", dcp->function); + rc = EINVAL; + } + + LOG_EXIT_INT(rc); + return rc; +} + +static plugin_functions_t ft_sysfs = { + .setup_evms_plugin = LD_setup, + .cleanup_evms_plugin = LD_cleanup, + .discover = LD_discover, + .add_sectors_to_kill_list = LD_add_sectors_to_kill_list, + .commit_changes = LD_commit_changes, + .get_info = LD_get_info, + .get_plugin_info = LD_get_plugin_info, + .read = LD_read, + .write = LD_write, + .direct_plugin_communication = LD_direct_plugin_communication +}; + +plugin_record_t LD_Plugin = { + /* FIXME: get official evms ids */ + .id = SetPluginID((EVMS_OEM_IBM+1), EVMS_DEVICE_MANAGER, 4), + .version = { + .major = MAJOR_VERSION, + .minor = MINOR_VERSION, + .patchlevel = PATCH_LEVEL + }, + .required_engine_api_version = { + .major = 12, + .minor = 0, + .patchlevel = 0 + }, + .required_plugin_api_version = { + .plugin = { + .major = 11, + .minor = 0, + .patchlevel = 0 + } + }, + .short_name = "BIOSDskMgr", + .long_name = "BIOS Disk Manager", + .oem_name = "IBM", + .functions = { + .plugin = &ft_sysfs + }, + .container_functions = NULL +}; + +plugin_record_t * my_plugin_record = &LD_Plugin; + +plugin_record_t * evms_plugin_records[] = { &LD_Plugin, + NULL }; + diff -Nurp evms-2.2.2/plugins/bios/bios.h evms-2.2.2-bios/plugins/bios/bios.h --- evms-2.2.2/plugins/bios/bios.h Thu Jan 1 01:00:00 1970 +++ evms-2.2.2-bios/plugins/bios/bios.h Sat Feb 14 18:52:54 2004 @@ -0,0 +1,131 @@ +/* + * (C) Copyright IBM Corp. 2001, 2003 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BIOS_H__ +#define __BIOS_H__ 1 + +#ifndef O_DIRECT +#define O_DIRECT 0 +#endif + +#define BLKGETSIZE64 _IOR(0x12,114,size_t) +#define BLKSSZGET _IO(0x12,104) +#define BLKBSZGET _IOR(0x12,112,size_t) +#define BLKBSZSET _IOW(0x12,113,size_t) +#define HDIO_GETGEO 0x0301 +#define HDIO_GETGEO_BIG 0x0330 + +struct hd_geometry { + unsigned char heads; + unsigned char sectors; + unsigned short cylinders; + unsigned long start; +}; + +struct hd_big_geometry { + unsigned char heads; + unsigned char sectors; + unsigned int cylinders; + unsigned long start; +}; + +extern engine_functions_t *EngFncs; +extern plugin_record_t *my_plugin_record; + +/*- + * Copyright (c) 2000,2001 Søren Schmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +struct highpoint_raid_conf +{ + int8_t filler1[32]; + u_int32_t magic; +#define HPT_MAGIC_OK 0x5a7816f0 +#define HPT_MAGIC_BAD 0x5a7816fd + + u_int32_t magic_0; + u_int32_t magic_1; + u_int32_t order; +#define HPT_O_MIRROR 0x01 +#define HPT_O_STRIPE 0x02 +#define HPT_O_OK 0x04 + + u_int8_t raid_disks; + u_int8_t raid0_shift; + u_int8_t type; +#define HPT_T_RAID_0 0x00 +#define HPT_T_RAID_1 0x01 +#define HPT_T_RAID_01_RAID_0 0x02 +#define HPT_T_SPAN 0x03 +#define HPT_T_RAID_3 0x04 +#define HPT_T_RAID_5 0x05 +#define HPT_T_SINGLEDISK 0x06 +#define HPT_T_RAID_01_RAID_1 0x07 + + u_int8_t disk_number; + u_int32_t total_secs; + u_int32_t disk_mode; + u_int32_t boot_mode; + u_int8_t boot_disk; + u_int8_t boot_protect; + u_int8_t error_log_entries; + u_int8_t error_log_index; + struct + { + u_int32_t timestamp; + u_int8_t reason; +#define HPT_R_REMOVED 0xfe +#define HPT_R_BROKEN 0xff + + u_int8_t disk; + u_int8_t status; + u_int8_t sectors; + u_int32_t lba; + } errorlog[32]; + u_int8_t filler[60]; +}; + +#define CONFIGOFFSET 4608 + +#endif +