diff -uNr linux-2.4.19/Documentation/Configure.help linux-2.4.19-gamap/Documentation/Configure.help --- linux-2.4.19/Documentation/Configure.help Fri Aug 2 17:39:42 2002 +++ linux-2.4.19-gamap/Documentation/Configure.help Mon Oct 14 11:16:22 2002 @@ -6795,6 +6795,19 @@ module if your root file system (the one containing the directory /) is located on a SCSI device. +Geographical Address Mapping support +CONFIG_GAMAP + This driver will provide device filesystem dynamic mapping of WWNs + to their logical geographical address. The result is that block + storage devices can be accessed using: + + /dev/scsi/chassis/slot/host + + This feature also works after an fdisk updating the appropriate files + to match the state of the system. + + This feature is only supported by the Qlogic V6 driver. + SCSI disk support CONFIG_BLK_DEV_SD If you want to use a SCSI hard disk or the SCSI or parallel port diff -uNr linux-2.4.19/Documentation/devices.txt linux-2.4.19-gamap/Documentation/devices.txt --- linux-2.4.19/Documentation/devices.txt Wed Nov 7 15:46:01 2001 +++ linux-2.4.19-gamap/Documentation/devices.txt Mon Oct 14 11:06:00 2002 @@ -417,8 +417,8 @@ 218 = /dev/kchuid Inter-process chuid control 219 = /dev/modems/mwave MWave modem firmware upload 220 = /dev/mptctl Message passing technology (MPT) control - 221 = /dev/mvista/hssdsi Montavista PICMG hot swap system driver - 222 = /dev/mvista/hasi Montavista PICMG high availability + 221 = /dev/scsi/hotswap MontaVista SCSI/FC hotswap driver + 222 = /dev/scsi/gamap MontaVista SCSI/FC geographical address mapping driver 240-255 Reserved for local use 11 char Raw keyboard device diff -uNr linux-2.4.19/drivers/scsi/Config.in linux-2.4.19-gamap/drivers/scsi/Config.in --- linux-2.4.19/drivers/scsi/Config.in Fri Aug 2 17:39:44 2002 +++ linux-2.4.19-gamap/drivers/scsi/Config.in Mon Oct 14 11:17:07 2002 @@ -1,5 +1,6 @@ comment 'SCSI support type (disk, tape, CD-ROM)' +dep_bool ' FibreChannel Geographical Address devfs mapper' CONFIG_GAMAP $CONFIG_SCSI dep_tristate ' SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then diff -uNr linux-2.4.19/drivers/scsi/Makefile linux-2.4.19-gamap/drivers/scsi/Makefile --- linux-2.4.19/drivers/scsi/Makefile Fri Aug 2 17:39:44 2002 +++ linux-2.4.19-gamap/drivers/scsi/Makefile Mon Oct 14 11:15:59 2002 @@ -21,7 +21,7 @@ O_TARGET := scsidrv.o -export-objs := scsi_syms.o 53c700.o +export-objs := scsi_syms.o 53c700.o gamap.o mod-subdirs := pcmcia ../acorn/scsi @@ -130,6 +130,7 @@ subdir-$(CONFIG_ARCH_ACORN) += ../acorn/scsi obj-$(CONFIG_ARCH_ACORN) += ../acorn/scsi/acorn-scsi.o +obj-$(CONFIG_GAMAP) += gamap.o obj-$(CONFIG_CHR_DEV_ST) += st.o obj-$(CONFIG_CHR_DEV_OSST) += osst.o obj-$(CONFIG_BLK_DEV_SD) += sd_mod.o diff -uNr linux-2.4.19/drivers/scsi/gamap.c linux-2.4.19-gamap/drivers/scsi/gamap.c --- linux-2.4.19/drivers/scsi/gamap.c Wed Dec 31 17:00:00 1969 +++ linux-2.4.19-gamap/drivers/scsi/gamap.c Mon Oct 14 11:06:00 2002 @@ -0,0 +1,439 @@ +/* + * gamap.c + * + * SCSI/FibreChannel geographical address map driver implementation + * + * Author: MontaVista Software, Inc. + * Steven Dake (sdake@mvista.com) + * source@mvista.com + * + * Copyright (C) 2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``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. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define __KERNEL_SYSCALLS__ + +#include +#include +#include + +#include +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "constants.h" + +#include + +#define GAMAPENTRIES 255 + +struct gamap { + int chassis; + int slot; + unsigned long long wwn; +}; + +extern devfs_handle_t scsi_devfs_handle; + +static devfs_handle_t gamap_devfs_handle; + +struct gamap gamap[GAMAPENTRIES]; + +static int gamap_ioctl (struct inode *inode, + struct file *file, + unsigned int cmd, + unsigned long parameters); + +int ioctl_gamap_getga_from_fc_wwn (unsigned long parameters); +int ioctl_gamap_getwwn_from_ga (unsigned long parameters); +int ioctl_gamap_insert_by_scsi_id (unsigned long parameters); +int ioctl_gamap_remove_by_scsi_id (unsigned long parameters); +int ioctl_gamap_insert_by_fc_wwn (unsigned long parameters); +int ioctl_gamap_remove_by_fc_wwn (unsigned long parameters); + +struct file_operations gamap_fileoperations = { + owner: THIS_MODULE, + ioctl: gamap_ioctl +}; + +int gamap_getga_from_fc_wwn (unsigned long long wwn, int *chassis, int *slot) { +int i; + + for (i = 0; gamap[i].wwn != wwn; i++) { + if (i >= GAMAPENTRIES) { + return (-ENOENT); + } + } + + *chassis = gamap[i].chassis; + *slot = gamap[i].slot; + return (0); +} + +int gamap_getwwn_from_ga (int chassis, int slot, unsigned long long *wwn) { +int i; + + for (i = 0; (gamap[i].chassis != chassis && gamap[i].slot != slot); i++) { + if (i >= GAMAPENTRIES) { + return (-ENOENT); + } + } + + *wwn = gamap[i].wwn; + return (0); +} + +int gamap_insert_by_scsi_id (int chassis, int slot, unsigned long id) { + return (-ENOSYS); +} + +int gamap_remove_by_scsi_id (int chassis, int slot, unsigned long id) { + return (-ENOSYS); +} + +int gamap_insert_by_fc_wwn (int chassis, int slot, unsigned long long wwn) { +int i = 0; +struct Scsi_Host *hba_p; +Scsi_Device *scsi_device; +int host, channel, lun, id; +char devname[32]; +struct gendisk *gendisk; +int part; + + /* + * Ensure entry not already present in map + * chassis and slot are a match, wwn is seperate match + */ + for (i = 0; i < GAMAPENTRIES; i++) { + if ((gamap[i].chassis == chassis && + gamap[i].slot == slot) || + gamap[i].wwn == wwn) { + return (0); + } + } + for (i = 0; gamap[i].chassis != -1; i++) { + if (i >= GAMAPENTRIES) { + return (-ENOSPC); + } + } + gamap[i].chassis = chassis; + gamap[i].slot = slot; + gamap[i].wwn = wwn; + + /* + * Add device node to the scsi_device structure and system + */ + scsi_hostlist->hostt->get_scsi_info_from_wwn (1, wwn, &host, &channel, &lun, &id); + + for (hba_p = scsi_hostlist; hba_p; hba_p = hba_p->next) { + if (hba_p->host_no == host) { + break; + } + } + /* + * No matching host adaptor found + */ + if (hba_p == 0) { + return (0); + } + + for (scsi_device = hba_p->host_queue; scsi_device; scsi_device = scsi_device->next) { + if (scsi_device->id == id && + scsi_device->lun == lun && + scsi_device->channel == channel) { + break; + } + } + if (scsi_device == 0) { + return (0); + } + + /* + * Create a devfs name if the device is already mapped into the + * system. If device not mapped in, devices will be created by scsi_scan + */ + gendisk = sd_get_gendisk (id); + + sprintf (devname, "chassis%d/host%d/slot%d", + chassis, scsi_device->host->host_no, slot); + + gendisk->de_gadir = devfs_mk_dir (scsi_devfs_handle, devname, NULL); + + gendisk->part[id << 4].de_gamap = devfs_register (gendisk->de_gadir, + "disc", DEVFS_FL_DEFAULT, gendisk->major, id << 4, + S_IFBLK | S_IRUSR | S_IWUSR, gendisk->fops, NULL); + + for (part = 1; part < gendisk->max_p; part++) { + /* + * No disk present, skip adding a device for it + */ + if (gendisk->part[(id << 4) + part].nr_sects < 1) { + continue; + } + + /* + * Partition present, add a device to the filesystem + */ + sprintf (devname, "part%d", part); + gendisk->part[(id << 4) + part].de_gamap = devfs_register ( + gendisk->de_gadir, devname, DEVFS_FL_DEFAULT, + gendisk->major, (id << 4) + part, + S_IFBLK | S_IRUSR | S_IWUSR, + gendisk->fops, NULL); + } + + return (0); +} + +int gamap_remove_by_fc_wwn (int chassis, int slot, unsigned long long wwn) { +int i; + for (i = 0; gamap[i].chassis != chassis && gamap[i].slot != slot && + gamap[i].wwn != wwn; i++) { + if (i >= GAMAPENTRIES) { + return (-ENOENT); + } + } + gamap[i].chassis = -1; + gamap[i].slot = -1; + gamap[i].wwn = 0; + return (0); +} + + +int gamap_init (void) { +int i; + printk (KERN_INFO "Copyright (C) 2002 MontaVista Software - SCSI/FC geographical address map driver\n"); + + gamap_devfs_handle = devfs_register (scsi_devfs_handle, + "gamap", + DEVFS_FL_NONE, + 10, + 222, + S_IFCHR | S_IRUSR | S_IWUSR, + &gamap_fileoperations, + NULL); + + if (gamap_devfs_handle == 0) { + return (-ENXIO); + } + + for (i = 0; i < GAMAPENTRIES; i++) { + gamap[i].chassis = -1; + gamap[i].slot = -1; + gamap[i].wwn = 0; + } + + return (0); +} + +static int gamap_ioctl (struct inode *inode, + struct file *file, + unsigned int cmd, + unsigned long parameters) { + +int result = -EINVAL; + + switch (cmd) { + case IOCTL_GAMAP_GETGA_FROM_FC_WWN: + result = ioctl_gamap_getga_from_fc_wwn (parameters); + break; + case IOCTL_GAMAP_GETWWN_FROM_GA: + result = ioctl_gamap_getwwn_from_ga (parameters); + break; + case IOCTL_GAMAP_INSERT_BY_SCSI_ID: + result = ioctl_gamap_insert_by_scsi_id (parameters); + break; + case IOCTL_GAMAP_REMOVE_BY_SCSI_ID: + result = ioctl_gamap_remove_by_scsi_id (parameters); + break; + case IOCTL_GAMAP_INSERT_BY_FC_WWN: + result = ioctl_gamap_insert_by_fc_wwn (parameters); + break; + case IOCTL_GAMAP_REMOVE_BY_FC_WWN: + result = ioctl_gamap_remove_by_fc_wwn (parameters); + break; + } + return (result); +} + + +int ioctl_gamap_getwwn_from_ga (unsigned long parameters) { +struct s_ioctl_gamap_getwwn_from_ga_parameters ioctl_gamap_getwwn_from_ga_parameters; + + if (copy_from_user ((int*)&ioctl_gamap_getwwn_from_ga_parameters, + (void *)parameters, + sizeof (struct s_ioctl_gamap_getwwn_from_ga_parameters))) { + return (-EFAULT); + } + ioctl_gamap_getwwn_from_ga_parameters.result = + gamap_getwwn_from_ga ( + ioctl_gamap_getwwn_from_ga_parameters.chassis, + ioctl_gamap_getwwn_from_ga_parameters.slot, + &ioctl_gamap_getwwn_from_ga_parameters.wwn); + + if (copy_to_user ((int *)parameters, + &ioctl_gamap_getwwn_from_ga_parameters, + sizeof (struct s_ioctl_gamap_getwwn_from_ga_parameters))) { + return (-EFAULT); + } + return (0); +} + +int ioctl_gamap_getga_from_fc_wwn (unsigned long parameters) { +struct s_ioctl_gamap_getga_from_fc_wwn_parameters ioctl_gamap_getga_from_fc_wwn_parameters; + + + if (copy_from_user ((int*)&ioctl_gamap_getga_from_fc_wwn_parameters, + (void *)parameters, + sizeof (struct s_ioctl_gamap_getga_from_fc_wwn_parameters))) { + return (-EFAULT); + } + ioctl_gamap_getga_from_fc_wwn_parameters.result = + gamap_getga_from_fc_wwn ( + ioctl_gamap_getga_from_fc_wwn_parameters.wwn, + &ioctl_gamap_getga_from_fc_wwn_parameters.chassis, + &ioctl_gamap_getga_from_fc_wwn_parameters.slot); + + if (copy_to_user ((int *)parameters, + &ioctl_gamap_getga_from_fc_wwn_parameters, + sizeof (struct s_ioctl_gamap_getga_from_fc_wwn_parameters))) { + return (-EFAULT); + } + return (0); +} +int ioctl_gamap_insert_by_scsi_id (unsigned long parameters) { +struct s_ioctl_gamap_insert_by_scsi_id_parameters ioctl_gamap_insert_by_scsi_id_parameters; + + if (copy_from_user ((int*)&ioctl_gamap_insert_by_scsi_id_parameters, + (void *)parameters, sizeof (struct s_ioctl_gamap_insert_by_scsi_id_parameters))) { + return (-EFAULT); + } + ioctl_gamap_insert_by_scsi_id_parameters.result = + gamap_insert_by_scsi_id ( + ioctl_gamap_insert_by_scsi_id_parameters.chassis, + ioctl_gamap_insert_by_scsi_id_parameters.slot, + ioctl_gamap_insert_by_scsi_id_parameters.id); + + if (copy_to_user ((int *)parameters, + &ioctl_gamap_insert_by_scsi_id_parameters, + sizeof (struct s_ioctl_gamap_insert_by_scsi_id_parameters))) { + return (-EFAULT); + } + return (0); +} + +int ioctl_gamap_remove_by_scsi_id (unsigned long parameters) { +struct s_ioctl_gamap_remove_by_scsi_id_parameters ioctl_gamap_remove_by_scsi_id_parameters; + + if (copy_from_user ((int*)&ioctl_gamap_remove_by_scsi_id_parameters, + (void *)parameters, + sizeof (struct s_ioctl_gamap_remove_by_scsi_id_parameters))) { + return (-EFAULT); + } + ioctl_gamap_remove_by_scsi_id_parameters.result = + gamap_remove_by_scsi_id ( + ioctl_gamap_remove_by_scsi_id_parameters.chassis, + ioctl_gamap_remove_by_scsi_id_parameters.slot, + ioctl_gamap_remove_by_scsi_id_parameters.id); + + if (copy_to_user ((int *)parameters, + &ioctl_gamap_remove_by_scsi_id_parameters, + sizeof (struct s_ioctl_gamap_remove_by_scsi_id_parameters))) { + return (-EFAULT); + } + return (0); +} +int ioctl_gamap_insert_by_fc_wwn (unsigned long parameters) { +struct s_ioctl_gamap_insert_by_fc_wwn_parameters ioctl_gamap_insert_by_fc_wwn_parameters; + + if (copy_from_user ((int*)&ioctl_gamap_insert_by_fc_wwn_parameters, + (void *)parameters, + sizeof (struct s_ioctl_gamap_insert_by_fc_wwn_parameters))) { + return (-EFAULT); + } + ioctl_gamap_insert_by_fc_wwn_parameters.result = + gamap_insert_by_fc_wwn ( + ioctl_gamap_insert_by_fc_wwn_parameters.chassis, + ioctl_gamap_insert_by_fc_wwn_parameters.slot, + ioctl_gamap_insert_by_fc_wwn_parameters.wwn); + + if (copy_to_user ((int *)parameters, + &ioctl_gamap_insert_by_fc_wwn_parameters, + sizeof (struct s_ioctl_gamap_insert_by_fc_wwn_parameters))) { + return (-EFAULT); + } + return (0); +} + +int ioctl_gamap_remove_by_fc_wwn (unsigned long parameters) { +struct s_ioctl_gamap_remove_by_fc_wwn_parameters ioctl_gamap_remove_by_fc_wwn_parameters; + + if (copy_from_user ((int*)&ioctl_gamap_remove_by_fc_wwn_parameters, + (void *)parameters, + sizeof (struct s_ioctl_gamap_remove_by_fc_wwn_parameters))) { + return (-EFAULT); + } + ioctl_gamap_remove_by_fc_wwn_parameters.result = + gamap_remove_by_fc_wwn ( + ioctl_gamap_remove_by_fc_wwn_parameters.chassis, + ioctl_gamap_remove_by_fc_wwn_parameters.slot, + ioctl_gamap_remove_by_fc_wwn_parameters.wwn); + + if (copy_to_user ((int *)parameters, + &ioctl_gamap_remove_by_fc_wwn_parameters, + sizeof (struct s_ioctl_gamap_remove_by_fc_wwn_parameters))) { + return (-EFAULT); + } + return (0); +} + + +void gamap_exit (void) { + devfs_unregister (gamap_devfs_handle); + return; +} + +EXPORT_SYMBOL (gamap_getga_from_fc_wwn); +EXPORT_SYMBOL (gamap_getwwn_from_ga); +EXPORT_SYMBOL (gamap_insert_by_scsi_id); +EXPORT_SYMBOL (gamap_remove_by_scsi_id); +EXPORT_SYMBOL (gamap_insert_by_fc_wwn); +EXPORT_SYMBOL (gamap_remove_by_fc_wwn); diff -uNr linux-2.4.19/drivers/scsi/hosts.h linux-2.4.19-gamap/drivers/scsi/hosts.h --- linux-2.4.19/drivers/scsi/hosts.h Mon Feb 25 12:38:04 2002 +++ linux-2.4.19-gamap/drivers/scsi/hosts.h Mon Oct 14 11:15:02 2002 @@ -220,6 +220,13 @@ */ void (*select_queue_depths)(struct Scsi_Host *, Scsi_Device *); + /* + * Used to determine the id to send the inquiry command to during + * hot additions + */ + int (*get_scsi_info_from_wwn)(int mode, unsigned long long wwn, int *host, int *channel, int *lun, int *id); + int (*get_wwn_from_scsi_info) (int host, int id, unsigned long long *wwn); + /* * This determines if we will use a non-interrupt driven * or an interrupt driven scheme, It is set to the maximum number diff -uNr linux-2.4.19/drivers/scsi/scsi.c linux-2.4.19-gamap/drivers/scsi/scsi.c --- linux-2.4.19/drivers/scsi/scsi.c Fri Aug 2 17:39:44 2002 +++ linux-2.4.19-gamap/drivers/scsi/scsi.c Mon Oct 14 11:17:54 2002 @@ -66,6 +66,8 @@ #include #include +#include + #include "scsi.h" #include "hosts.h" #include "constants.h" @@ -2611,6 +2613,10 @@ */ init_bh(SCSI_BH, scsi_bottom_half_handler); +#if defined(CONFIG_GAMAP) + gamap_init (); +#endif /* CONFIG_GAMAP */ + return 0; } @@ -2620,6 +2626,10 @@ remove_bh(SCSI_BH); +#if defined(CONFIG_GAMAP) + gamap_exit (); +#endif /* CONFIG_GAMAP */ + devfs_unregister (scsi_devfs_handle); for (shn = scsi_host_no_list;shn;shn = shn->next) { if (shn->name) diff -uNr linux-2.4.19/drivers/scsi/scsi_scan.c linux-2.4.19-gamap/drivers/scsi/scsi_scan.c --- linux-2.4.19/drivers/scsi/scsi_scan.c Fri Aug 2 17:39:44 2002 +++ linux-2.4.19-gamap/drivers/scsi/scsi_scan.c Mon Oct 14 11:06:21 2002 @@ -527,6 +527,8 @@ int bflags, type = -1; extern devfs_handle_t scsi_devfs_handle; int scsi_level; + int chassis, slot; + unsigned long long wwn; SDpnt->host = shpnt; SDpnt->id = dev; @@ -684,10 +686,37 @@ print_inquiry(scsi_result); - sprintf (devname, "host%d/bus%d/target%d/lun%d", - SDpnt->host->host_no, SDpnt->channel, SDpnt->id, SDpnt->lun); - if (SDpnt->de) printk ("DEBUG: dir: \"%s\" already exists\n", devname); - else SDpnt->de = devfs_mk_dir (scsi_devfs_handle, devname, NULL); + +#ifdef CONFIG_GAMAP + if (SDpnt->host->hostt->get_wwn_from_scsi_info) { + SDpnt->host->hostt->get_wwn_from_scsi_info (SDpnt->host->host_no, SDpnt->id, &wwn); + + if (gamap_getga_from_fc_wwn (wwn, &chassis, &slot)) { + /* + * GA not mapped in + */ + sprintf (devname, "host%d/bus%d/target%d/lun%d", + SDpnt->host->host_no, SDpnt->channel, SDpnt->id, SDpnt->lun); + } else { + /* + * Successfully found GA, set device entry and create device name + */ + sprintf (devname, "chassis%d/slot%d/host%d", + chassis, slot, SDpnt->host->host_no); + } + } else { +#endif /* CONFIG_GAMAP */ + sprintf (devname, "host%d/bus%d/target%d/lun%d", + SDpnt->host->host_no, SDpnt->channel, SDpnt->id, SDpnt->lun); +#ifdef CONFIG_GAMAP + } +#endif /* CONFIG_GAMAP */ + + if (SDpnt->de) { + printk ("DEBUG: dir: \"%s\" already exists\n", devname); + } else { + SDpnt->de = devfs_mk_dir (scsi_devfs_handle, devname, NULL); + } for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) diff -uNr linux-2.4.19/drivers/scsi/sd.c linux-2.4.19-gamap/drivers/scsi/sd.c --- linux-2.4.19/drivers/scsi/sd.c Fri Aug 2 17:39:44 2002 +++ linux-2.4.19-gamap/drivers/scsi/sd.c Mon Oct 14 11:06:21 2002 @@ -588,6 +588,13 @@ #define SD_GENDISK(i) sd_gendisks[(i) / SCSI_DISKS_PER_MAJOR] +#ifdef CONFIG_GAMAP +struct gendisk *sd_get_gendisk (int id) { + return (&SD_GENDISK(id)); +} +#endif /* CONFIG_GAMAP */ + + /* * rw_intr is the interrupt routine for the device driver. * It will be notified on the end of a SCSI read / write, and diff -uNr linux-2.4.19/fs/partitions/check.c linux-2.4.19-gamap/fs/partitions/check.c --- linux-2.4.19/fs/partitions/check.c Fri Aug 2 17:39:45 2002 +++ linux-2.4.19-gamap/fs/partitions/check.c Mon Oct 14 11:06:21 2002 @@ -334,6 +334,35 @@ } #endif /* CONFIG_DEVFS_FS */ +#ifdef CONFIG_GAMAP +static void devfs_gamap_register_partition (struct gendisk *gendisk, int minor, int part) { +char devname[16]; + + /* + * No disc entry + */ + if (gendisk->part[minor].de_gamap == 0) { + return; + } + + /* + * Partition already defined + */ + if (gendisk->part[minor + part].de_gamap) { + return; + } + + /* + * Generate partition in devfs + */ + sprintf (devname, "part%d", part); + gendisk->part[minor + part].de_gamap = devfs_register ( + devfs_get_parent (gendisk->part[minor].de_gamap), devname, + DEVFS_FL_DEFAULT, gendisk->major, minor + part, + S_IFBLK | S_IRUSR | S_IWUSR, gendisk->fops, NULL); +} +#endif /* CONFIG_GAMAP */ + void devfs_register_partitions (struct gendisk *dev, int minor, int unregister) { #ifdef CONFIG_DEVFS_FS @@ -346,11 +375,26 @@ (dev->part[part + minor].nr_sects < 1) ) { devfs_unregister (dev->part[part + minor].de); dev->part[part + minor].de = NULL; +#ifdef CONFIG_GAMAP + if (dev->part[part + minor].de_gamap) { + devfs_unregister (dev->part[part + minor].de_gamap); + dev->part[part + minor].de_gamap = NULL; + } +#endif /* CONFIG_GAMAP */ continue; } devfs_register_partition (dev, minor, part); +#ifdef CONFIG_GAMAP + devfs_gamap_register_partition (dev, minor, part); +#endif /* CONFIG_GAMAP */ } if (unregister) { +#ifdef CONFIG_GAMAP + if (dev->part[minor].de_gamap) { + devfs_unregister (dev->part[minor].de_gamap); + dev->part[minor].de_gamap = NULL; + } +#endif /* CONFIG_GAMAP */ devfs_unregister (dev->part[minor].de); dev->part[minor].de = NULL; devfs_dealloc_unique_number (&disc_numspace, diff -uNr linux-2.4.19/include/linux/gamap.h linux-2.4.19-gamap/include/linux/gamap.h --- linux-2.4.19/include/linux/gamap.h Wed Dec 31 17:00:00 1969 +++ linux-2.4.19-gamap/include/linux/gamap.h Mon Oct 14 11:06:21 2002 @@ -0,0 +1,106 @@ +/* + * gamap.h + * + * SCSI/FibreChannel geographical address map driver interface + * + * Author: MontaVista Software, Inc. + * Steven Dake (sdake@mvista.com) + * source@mvista.com + * + * Copyright (C) 2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``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. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __GAMAP_H +#define __GAMAP_H + +/* + * Software Interface + */ +extern int gamap_getga (unsigned long long wwn, int *chassis, int *slot); +extern int gamap_getwwn (int chassis, int slot, unsigned long long *wwn); +extern int gamap_insert_by_scsi_id (int chassis, int slot, + unsigned long id); +extern int gamap_remove_by_scsi_id (int chassis, int slot, + unsigned long id); +extern int gamap_insert_by_fc_wwn (int chassis, int slot, + unsigned long long wwn); +extern int gamap_remove_by_fc_wwn (int chassis, int slot, + unsigned long long wwn); + +extern int gamap_init(void); + +extern void gamap_exit(void); + +/* + * Ioctl Interface + */ +struct s_ioctl_gamap_getga_from_fc_wwn_parameters { + unsigned long long wwn; + int chassis; + int slot; + int result; +}; +struct s_ioctl_gamap_getwwn_from_ga_parameters { + int chassis; + int slot; + unsigned long long wwn; + int result; +}; + +struct s_ioctl_gamap_insert_by_scsi_id_parameters { + int chassis; + int slot; + unsigned int id; + int result; +}; + +struct s_ioctl_gamap_remove_by_scsi_id_parameters { + int chassis; + int slot; + unsigned int id; + int result; +}; +struct s_ioctl_gamap_insert_by_fc_wwn_parameters { + int chassis; + int slot; + unsigned long long wwn; + int result; +}; + +struct s_ioctl_gamap_remove_by_fc_wwn_parameters { + int chassis; + int slot; + unsigned long long wwn; + int result; +}; + +#define GAMAP_IOC_MAGIC 'c' + +#define IOCTL_GAMAP_GETGA_FROM_FC_WWN _IOWR (GAMAP_IOC_MAGIC, 0, struct s_ioctl_gamap_getga_from_fc_wwn_parameters) +#define IOCTL_GAMAP_GETWWN_FROM_GA _IOWR (GAMAP_IOC_MAGIC, 1, struct s_ioctl_gamap_getwwn_from_ga_parameters) +#define IOCTL_GAMAP_INSERT_BY_SCSI_ID _IOWR (GAMAP_IOC_MAGIC, 2, struct s_ioctl_gamap_insert_by_scsi_id_parameters) +#define IOCTL_GAMAP_REMOVE_BY_SCSI_ID _IOWR (GAMAP_IOC_MAGIC, 3, struct s_ioctl_gamap_remove_by_scsi_id_parameters) +#define IOCTL_GAMAP_INSERT_BY_FC_WWN _IOWR (GAMAP_IOC_MAGIC, 4, struct s_ioctl_gamap_insert_by_fc_wwn_parameters) +#define IOCTL_GAMAP_REMOVE_BY_FC_WWN _IOWR (GAMAP_IOC_MAGIC, 5, struct s_ioctl_gamap_remove_by_fc_wwn_parameters) + +#endif /* __GAMAP_H */ diff -uNr linux-2.4.19/include/linux/genhd.h linux-2.4.19-gamap/include/linux/genhd.h --- linux-2.4.19/include/linux/genhd.h Fri Aug 2 17:39:45 2002 +++ linux-2.4.19-gamap/include/linux/genhd.h Mon Oct 14 11:14:20 2002 @@ -63,6 +63,8 @@ unsigned long nr_sects; devfs_handle_t de; /* primary (master) devfs entry */ int number; /* stupid old code wastes space */ + devfs_handle_t de_gamap; /* ga map device entry */ + /* Performance stats: */ unsigned int ios_in_flight; @@ -98,6 +100,8 @@ struct gendisk *next; struct block_device_operations *fops; + devfs_handle_t de_gadir; /* GA device entry directory chassis/slot/host */ + devfs_handle_t de_gamap[17]; /* for GA Mapping, need 17 entries (disc + 16 parts ) */ devfs_handle_t *de_arr; /* one per physical disc */ char *flags; /* one per physical disc */ };