Index: Makefile.in
===================================================================
RCS file: /home/cvsroot/scsidev/Makefile.in,v
retrieving revision 1.9
retrieving revision 1.9.2.2
diff -u -r1.9 -r1.9.2.2
--- Makefile.in	2000/09/05 09:22:35	1.9
+++ Makefile.in	2002/07/27 00:17:23	1.9.2.2
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile.in,v 1.9 2000/09/05 09:22:35 garloff Exp $
+# $Id: Makefile.in,v 1.9.2.2 2002/07/27 00:17:23 garloff Exp $
 #
 ## Makefile for scsidev.
 
@@ -57,12 +57,11 @@
 
 dist: clean
 	rm Makefile
-	(cd .. && mv scsidev scsidev-$(VERSION) && tar cvvf - \
-	--exclude scsidev-$(VERSION)/CVS scsidev-$(VERSION) \
-	| gzip -9 > scsidev-$(VERSION).tar.gz; mv scsidev-$(VERSION) scsidev)
+	(DIR=`/bin/pwd`; DIR=`basename $$DIR`; cd .. && mv $$DIR scsidev-$(VERSION) \
+	&& tar cvvf - --exclude scsidev-$(VERSION)/CVS scsidev-$(VERSION) \
+	| gzip -9 > scsidev-$(VERSION).tar.gz; mv scsidev-$(VERSION) $$DIR)
 
 clean:
 	rm -f *~ .*~ *.o scsidev
 	/bin/rm -f config.status config.log config.cache config.h
-
 
Index: README
===================================================================
RCS file: /home/cvsroot/scsidev/README,v
retrieving revision 1.2
retrieving revision 1.2.2.1
diff -u -r1.2 -r1.2.2.1
--- README	2000/02/14 22:54:03	1.2
+++ README	2002/07/27 00:16:10	1.2.2.1
@@ -1,9 +1,9 @@
-#	$Id: README,v 1.2 2000/02/14 22:54:03 garloff Exp $	
+#	$Id: README,v 1.2.2.1 2002/07/27 00:16:10 garloff Exp $	
 NOTE: This docu is out of date. Please refer to the man page and the
 =====  web page mentioned there.  KG.
 
-	The linux SCSI code assigns minor numbers to devices dynamicly.  Thus
-if you add or remove a device, the device numbering will change, and this
+	The linux SCSI code assigns minor numbers to devices dynamically.  
+Thus if you add or remove a device, the device numbering will change, and this
 obviously screws up things like /etc/fstab, /etc/rc*, and a few other things.
 What we desire is a uniform naming scheme whereby the name used for a device
 remains the same as you add or remove other bits of hardware.
Index: VERSION
===================================================================
RCS file: /home/cvsroot/scsidev/VERSION,v
retrieving revision 1.8
diff -u -r1.8 VERSION
--- VERSION	2000/09/04 18:43:11	1.8
+++ VERSION	2002/07/27 00:25:55
@@ -1 +1 @@
-2.22
+2.23
Index: scsidev.8
===================================================================
RCS file: /home/cvsroot/scsidev/scsidev.8,v
retrieving revision 1.11
retrieving revision 1.11.2.1
diff -u -r1.11 -r1.11.2.1
--- scsidev.8	2000/07/14 23:59:35	1.11
+++ scsidev.8	2002/07/26 23:28:54	1.11.2.1
@@ -1,8 +1,8 @@
 #
-# $Id: scsidev.8,v 1.11 2000/07/14 23:59:35 garloff Exp $
+# $Id: scsidev.8,v 1.11.2.1 2002/07/26 23:28:54 garloff Exp $
 #
 .\" -*- nroff -*-
-.TH SCSIDEV 8 "July 2000" "Version 2.20"
+.TH SCSIDEV 8 "July 2002" "Version 2.23"
 .SH NAME
 scsidev \- populate /dev/scsi with device names that are independent of reconfiguration.
 .SH SYNOPSIS
@@ -32,6 +32,9 @@
 .B \-r
 ]
 [
+.B \-e
+]
+[
 .B \-s
 ]
 [
@@ -151,9 +154,17 @@
 will do the right guesses. So using \-r in bootup scripts is safe. After you
 removed devices from your SCSI config, it isn't safe any longer.
 .TP
+.I \-e
+Instructs 
+.B scsidev 
+to use devfs like names, i.e. using the cbtu (controller, bus, target
+unit) chraracters instead of hcil (host, channel, scsi Id, scsi Lun) to
+build the device name.
+.TP
 .I \-s
 Tells scsidev to print out the device serial numbers of all detected
-devices on the system.  This string can be useful for forming aliases.
+devices on the system. This string can be useful for forming aliases.
+If supported, also the WWID is printed.
 .TP
 .I \-v
 Verbosity.  Mainly used for debugging purposes.  Use multiple times for
@@ -208,7 +219,16 @@
 Specifies the serial number of the device.  Not all devices implement
 this, but for those that do it provides a convenient mechanism to
 uniquely identify a device no matter where it is found on the
-scsi chain.
+scsi chain. The serial number is the one reported in INQUIRY page
+0x80 with EVPD=1. It is displayed by
+.B scsidev -s .
+.TP
+.I wwid=
+Specifies the WWID number of a device. This is a 64bit world wide
+unique number, which is supported by SCSI-3 devices and reported
+via INQUIRY page 0x83 with EVPD=1. If supported, it's displayed
+by 
+.B scsidev -s .
 .TP
 .I id=
 Specifies the scsi id number for the device.
Index: scsidev.c
===================================================================
RCS file: /home/cvsroot/scsidev/scsidev.c,v
retrieving revision 1.28
retrieving revision 1.28.2.7
diff -u -r1.28 -r1.28.2.7
--- scsidev.c	2000/09/04 18:43:01	1.28
+++ scsidev.c	2002/07/27 00:16:10	1.28.2.7
@@ -61,6 +61,20 @@
  *    - Bugfix for long hostnames from Doug Gilbert (=> 2.21)
  *    - Fix parsing of scsi.alias file: Broke on missing LF at the end
  *  -> 2.22
+ * 
+ *  * 2002/07/26: Kurt Garloff <garloff@suse.de>
+ *    - optional (-e) cbtu naming scheme
+ *    - bugfix WRT alias handling of subdevices (parititons, non-rew. tap)
+ *    - Support for large SCSI IDs and LUNs. (from MGE)
+ *    - Support WWID (INQ EVPD 0x83) report + aliases
+ *    - Fix hex number parser
+ *  -> 2.23
+ * 
+ *  * 2002/07/30: Kurt Garloff <garloff@suse.de>
+ *    - Support for /proc/scsi/scsi extensions
+ *    - More sane way of storing permissions
+ *  -> 2.25
+ * 
  */
 
 #include <stdio.h>
@@ -75,13 +89,15 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <scsi/scsi_ioctl.h>
 
 
-static char rcsid[] ="$Id: scsidev.c,v 1.28 2000/09/04 18:43:01 garloff Exp $";
+static char rcsid[] ="$Id: scsidev.c,v 1.28.2.7 2002/07/27 00:16:10 garloff Exp $";
 static char *versid = "scsidev " VERSION " 2000/01/17";
 static char *copyright = "Copyright: GNU GPL  (see file COPYING)\n" \
 " (w)  1994--1997 Eric Youngdale <eric@andante.org>\n"\
-"      2000        Kurt Garloff   <garoff@suse.de>";
+"      2000--2002 Kurt Garloff   <garloff@suse.de>";
 
 
 #include "config.h"
@@ -107,17 +123,19 @@
 int filemode = 0600;
 int verbose = 0;
 int quiet = 0;
-int maxmiss = 0;
+int maxmiss = 8;
 int force = 0;
 int san_del = 0;
 int no_san = 0;
+int nm_cbtu = 0;
 int supp_rmvbl = 0;
 char * no_serial = "No serial number";
+unsigned long long no_wwid = 0;
 
 #define DEVSCSI "/dev/scsi"
 #define TESTDEV DEVSCSI "/testdev"
+#define PROCSCSI "/proc/scsi/scsi"
 
-
 /*
  * This program builds entries in /dev/scsi that have names that are tied
  * to the actual device number and lun.   This is pretty solid as long as
@@ -141,17 +159,18 @@
     char * model;
     char * rev;
     char * serial;
+    unsigned long long wwid;
     char inq_devtp;
     char rmvbl;
-    char hostnum;
     char unsafe;
     int  hostid;
     int  major;
     int  minor;
     char * hostname;
-    char chan;
-    char id;
-    char lun;
+    int  hostnum;
+    int  chan;
+    int  id;
+    int  lun;
     char partition;
     struct regnames * alias; // TBR
     struct regnames * related;
@@ -174,6 +193,7 @@
 			       ( memcmp (spnt->model, "SC-", 3) && \
 				 memcmp (spnt->model, "DI-", 3) && \
 				 memcmp (spnt->model, "DP-", 3) && \
+				 memcmp (spnt->model, "FW-", 3) && \
 				 memcmp (spnt->model, "USB", 3) ) ) )
 
 
@@ -187,8 +207,9 @@
     sname * pnt;
     for (pnt = reglist; pnt; pnt = pnt->next) 
     {
-	printf ("%s: %s %s %s (%s)\n", pnt->name,
-		pnt->manufacturer, pnt->model, pnt->rev, pnt->serial);
+	printf ("%s: %s %s %s (%s) %Lx\n", pnt->name,
+		pnt->manufacturer, pnt->model, pnt->rev, pnt->serial,
+		pnt->wwid);
 	printf ("  on %s (%d-%x): c%di%dl%d", pnt->hostname,
 		pnt->hostnum, pnt->hostid, pnt->chan, pnt->id, pnt->lun);
 	if (pnt->partition != -1) printf ("p%d", pnt->partition);
@@ -225,6 +246,7 @@
     if (strcmp (sp1->model, sp2->model)) return 7;
     if (strcmp (sp1->rev, sp2->rev)) return 8;
     if (strcmp (sp1->serial, sp2->serial)) return 9;
+    if (sp1->wwid != sp2->wwid) return 10;
     return 0;
 }
 
@@ -256,6 +278,7 @@
      * Initialize this - they may be needed later.
      */
     spnt->model = spnt->manufacturer = spnt->serial = spnt->rev = NULL;
+    spnt->wwid = no_wwid;
     spnt->next = reglist; reglist = spnt;
     return spnt;
 }
@@ -384,9 +407,14 @@
 	    sprintf (app, "p%d", spnt->minor % 0x10);
     }
     genpart = nm + strlen (nm);
-    sprintf (genpart, "s%ch%d-%xc%di%dl%d", devchar,
-	     spnt->hostnum, spnt->hostid,
-	     spnt->chan, spnt->id, spnt->lun);
+    if (nm_cbtu) 
+	sprintf (genpart, "s%cc%db%dt%du%d", devchar,
+		 spnt->hostnum, 
+		 spnt->chan, spnt->id, spnt->lun);
+    else
+	sprintf (genpart, "s%ch%d-%xc%di%dl%d", devchar,
+		 spnt->hostnum, spnt->hostid,
+		 spnt->chan, spnt->id, spnt->lun);
     if (*app) strcat (genpart, app);
     spnt->name = strdup (nm);
     return spnt->name;
@@ -603,12 +631,12 @@
     if (verbose == 2)
 	fprintf (stderr, "Found %x with idlun %x\n", 
 		 makedev (spnt->major, spnt->minor), id[0]);
-    spnt->hostnum = id[0] >> 24; 
-    spnt->chan    = id[0] >> 16; //()&0xff
-    spnt->lun     = id[0] >>  8;
-    spnt->id      = id[0];
+    spnt->hostnum = id[0] >> 24 & 0xff;
+    spnt->chan    = id[0] >> 16 & 0xff;
+    spnt->lun     = id[0] >>  8 & 0xff;
+    spnt->id      = id[0]       & 0xff;
     spnt->hostid  = id[1];
-	
+
     status = inquiry (fd, spnt);
     scsiname (spnt);
     return status;
@@ -878,6 +906,135 @@
 	status = getscsiinfo (fd, spnt);
 	close (fd);
 
+	if (status) { 
+		free (spnt); miss++;
+		if (miss > maxmiss) break;
+		else { minor++; continue; }
+	}
+	scsiname (spnt);
+
+	spnt->next = reglist; reglist = spnt;
+	create_dev (spnt);
+
+	if (!quiet) printf ("Found %s (Type %02x) %c on %s \n", spnt->name,
+			    spnt->inq_devtp, (spnt->rmvbl? 'R' : ' '),
+			    spnt->hostname);
+
+	/* Now register cdroms, tapes, and disks as well */
+	switch (spnt->inq_devtp) {
+	  case TYPE_DISK:
+	  case TYPE_MOD:
+	    if (!build_disk (spnt, disks)) disks++;
+	    else if (!build_disk (spnt, disks+1)) disks += 2;
+	    break;
+	  case TYPE_TAPE:
+	    if (OSST_SUPPORTS(spnt)) 
+	    {
+		if (!build_os_tape (spnt, tapes)) tapes++;
+		else if (!build_os_tape (spnt, tapes+1)) tapes += 2;
+	    }		    
+	    else
+	    {
+		if (!build_tape (spnt, tapes)) tapes++;
+		else if (!build_tape (spnt, tapes+1)) tapes += 2;
+	    }
+	    break;
+	  case TYPE_ROM:
+	  case TYPE_WORM:
+	    if (!build_cdrom (spnt, cdroms)) cdroms++;
+	    else if (!build_cdrom (spnt, cdroms+1)) cdroms += 2;
+	    break;
+	  default:
+	    ;/* nothing to be done */
+	}
+	minor += 1;
+    }
+    //unlink (TESTDEV);
+}
+
+#if 0
+
+/* Test for availability of /proc/scsi/scsi extensions */
+int scsi_ext_status ()
+{
+}
+
+/* Try to switch on extensions */
+void scsi_ext_on ()
+{
+}
+
+/* Try to switch on extensions */
+void scsi_ext_off ()
+{
+}
+
+void build_sgdevlist_procscsi ()
+{
+    int fd; 
+    struct stat statbuf;
+    int status;
+    sname * spnt;
+    int miss = 0;	
+    int minor = 0; int major = SCSI_GENERIC_MAJOR; 
+    char devchar = 'g'; int mode = O_RDWR;
+    int devtype = (SCSI_BLK_MAJOR(major)? S_IFBLK: S_IFCHR);
+    char* buf; int buflen;
+    FILE* mapfile;
+
+    status = stat (DEVSCSI, &statbuf);
+    if (status == -1)
+	return;
+
+    status = stat (TESTDEV, &statbuf);
+    if (status == 0)
+	unlink (TESTDEV);
+
+    if (verbose >= 1)
+	fprintf (stderr, "Building list for s%c (%s dev major %i)\n",
+		 devchar, (SCSI_BLK_MAJOR(major)? "block": "char"), major);
+    
+    mapfile = fopen (PROCSCSI, "r");
+    if (!mapfile) {
+	fprintf (stderr, "scsidev: could not open " PROCSCSI ": %s\n",
+		 strerror (errno));
+	return;
+    }
+    
+    buf = malloc(128); buflen = 128;
+
+	
+	
+    while (getline (&buf, &buflen, mapfile) != -1)
+    {
+	int h,c,i,l;
+	int inqtp, onl;
+	char *nm, *dev, *rest;
+	if (buf[0] == '#')
+		continue;
+	
+	errno = 0;
+	status = mknod ( TESTDEV, 0600 | devtype ,
+			 makedev (major, minor) );
+	if (status) { perror ("scsidev: mknod"); exit (3); }
+	fd = open (TESTDEV, mode);
+	unlink (TESTDEV);
+	if (fd == -1) {
+	    if (verbose == 2)
+	    {
+		fprintf (stderr, "open(%x/%x) returned %d (%d)\n",
+			 major, minor, fd, errno);
+	    }
+	    miss++;
+	    if (miss > maxmiss) break;
+	    else { minor++; continue; }
+	}
+	spnt = (sname*) malloc (sizeof (sname));
+	spnt->major = major;   spnt->minor = minor;
+	spnt->name  = TESTDEV; spnt->partition = -1;
+	status = getscsiinfo (fd, spnt);
+	close (fd);
+
 	if (status) { free (spnt); return; };
 	scsiname (spnt);
 
@@ -918,9 +1075,25 @@
 	minor += 1;
     }
     //unlink (TESTDEV);
+    free(buf);
 }
 
+int try_procscsi ()
+{
+	int se_status = scsi_ext_status();
+	if (!se_status)
+		scsi_ext_on();
+	if (!scsi_ext_status())
+		return -1;
+	
+	build_sgdevlist_procscsi();
+	
+	if (!se_status)
+		scsi_ext_off();
+}
+#endif
 
+
 void usage()
 {
     fprintf (stderr, "%s\n", versid);
@@ -930,9 +1103,10 @@
     fprintf (stderr, " -d     : sanitize by Deleting undetected entries (def: minor->255)\n");
     fprintf (stderr, " -l/-L  : create symLinks for device names / alias names\n");
     fprintf (stderr, " -m mode: permissions to create dev nodes with\n");
-    fprintf (stderr, " -s     : list Serial numbers of devices (if available)\n");
+    fprintf (stderr, " -s     : list Serial numbers /WWIDs of devices (if available)\n");
     fprintf (stderr, " -c mxms: Continue scanning until mxms missing devs found\n");
     fprintf (stderr, " -r     : trust Removeable media (only safe after boot)\n");
+    fprintf (stderr, " -e     : use dEvfs like naming  (cbtu chars)\n");
     fprintf (stderr, " -v/-q  : Verbose/Quiet operation\n");
     fprintf (stderr, " -h     : print Help and exit.\n");
 }
@@ -955,7 +1129,7 @@
 	fprintf(stderr, DEVSCSI " either does not exist, or is not a directory\n");
 	exit(0);
     }
-    while ((c = getopt(argc, argv, "flLvqshndrm:c:")) != EOF)
+    while ((c = getopt(argc, argv, "flLvqshnderm:c:")) != EOF)
     {
 	switch (c)
 	{
@@ -977,6 +1151,8 @@
 	    san_del = 1; break;
 	  case 'r':
 	    supp_rmvbl = 1; break;
+	  case 'e':
+	    nm_cbtu = 1; break;
 	  case 'v':
 	    verbose++; break;
 	  case 'h':
@@ -993,22 +1169,24 @@
     if( force ) flush_sdev ();
 
 #ifdef DEBUG
-    register_dev("/dev/scsi/sdh4-334c0i0l0",   8,  0, 6, 0x334, 0, 0, 0, -1, "debug", NULL);
-    register_dev("/dev/scsi/sdh4-334c0i0l0p1", 8,  1, 6, 0x334, 0, 0, 0,  1, "debug", NULL);
-    register_dev("/dev/scsi/sdh4-334c0i0l0p2",8,  2,6, 0x334, 0, 0, 0,  2, "debug", NULL);
-    register_dev("/dev/scsi/sdh4-334c0i0l0p3",8,  3,6, 0x334, 0, 0, 0,  3, "debug", NULL);
-    register_dev("/dev/scsi/sgh4-334c0i0l0", 21,  0,6, 0x334, 0, 0, 0, -1, "debug", NULL);
-    register_dev("/dev/scsi/sgh4-334c0i2l0", 21,  1,6, 0x334, 0, 2, 0, -1, "debug", NULL);
-    register_dev("/dev/scsi/sgh4-334c0i5l0", 21,  2,6, 0x334, 0, 5, 0, -1, "debug", NULL);
-    register_dev("/dev/scsi/srh4-334c0i2l0", 11,  0,6, 0x334, 0, 2, 0, -1, "debug", NULL);
-    register_dev("/dev/scsi/sth4-334c0i5l0",  9,  0,6, 0x334, 0, 5, 0, -1, "debug", NULL);
-    register_dev("/dev/scsi/rsth4-334c0i5l0", 9,128,6, 0x334, 0, 5, 0, -1, "debug", NULL);
+    register_dev("/dev/scsi/sdh4-334c0i0l0",  8,  0, 6, 0x334, 0, 0, 0, -1, "debug", NULL);
+    register_dev("/dev/scsi/sdh4-334c0i0l0p1",8,  1, 6, 0x334, 0, 0, 0,  1, "debug", NULL);
+    register_dev("/dev/scsi/sdh4-334c0i0l0p2",8,  2, 6, 0x334, 0, 0, 0,  2, "debug", NULL);
+    register_dev("/dev/scsi/sdh4-334c0i0l0p3",8,  3, 6, 0x334, 0, 0, 0,  3, "debug", NULL);
+    register_dev("/dev/scsi/sgh4-334c0i0l0", 21,  0, 6, 0x334, 0, 0, 0, -1, "debug", NULL);
+    register_dev("/dev/scsi/sgh4-334c0i2l0", 21,  1, 6, 0x334, 0, 2, 0, -1, "debug", NULL);
+    register_dev("/dev/scsi/sgh4-334c0i5l0", 21,  2, 6, 0x334, 0, 5, 0, -1, "debug", NULL);
+    register_dev("/dev/scsi/srh4-334c0i2l0", 11,  0, 6, 0x334, 0, 2, 0, -1, "debug", NULL);
+    register_dev("/dev/scsi/sth4-334c0i5l0",  9,  0, 6, 0x334, 0, 5, 0, -1, "debug", NULL);
+    register_dev("/dev/scsi/rsth4-334c0i5l0", 9,128, 6, 0x334, 0, 5, 0, -1, "debug", NULL);
 #else
     build_sgdevlist ();
 #endif
 
     if( show_serial )
     {
+	if (verbose)
+	    dumplist();
 	for (spnt = reglist; spnt; spnt = spnt->next)
 	{
 	    if( spnt->partition != -1 ) continue;
@@ -1020,6 +1198,8 @@
 		printf("Device  %s has no serial number\n", spnt->name);
 	    else
 		printf("Serial number of %s: \"%s\"\n", spnt->name, spnt->serial);
+	    if ( spnt->wwid != no_wwid )
+		printf (" WWID: %Lx\n", spnt->wwid);
 	}
     }
 
@@ -1065,6 +1245,58 @@
     return pnt;
 }
 
+char * get_llnumber (char * pnt, unsigned long long * result)
+{
+    int base = 10;
+    unsigned long long num;
+
+    while (*pnt == ' ' || *pnt == '\t') pnt++;
+    if (pnt[0] == '0' && pnt[1] == 'x') { base = 16; pnt += 2; }
+
+    num = 0;
+    while (1)
+    {
+	if (base == 10 && *pnt >= '0' && *pnt <= '9' )
+	{
+	    num = num * 10ULL + *pnt - '0';
+	    pnt++;
+	    continue;
+	}
+	if ( base == 16 )
+	{
+	    if (*pnt >= '0' && *pnt <= '9')
+	    {
+		num = (num << 4) + *pnt - '0';
+		pnt++;
+		continue;
+	    }
+	    if (*pnt >= 'a' && *pnt <= 'f')
+	    {
+		num = (num << 4) + *pnt - 'a' + 10;
+		pnt++;
+		continue;
+	    }
+	    if (*pnt >= 'A' && *pnt <= 'F')
+	    {
+		num = (num << 4) + *pnt - 'A' + 10;
+		pnt++;
+		continue;
+	    }
+	    break;
+	}
+	/*
+	 * Isn't a digit.  Must be the end of the number.
+	 */
+	break;
+    }
+    while (*pnt == ' ' || *pnt == '\t') pnt++;
+    if (*pnt == ',') pnt++;
+    while (*pnt == ' ' || *pnt == '\t') pnt++;
+    *result = num;
+    return pnt;
+
+}
+
 char * get_number (char * pnt, int * result)
 {
     int base = 10;
@@ -1086,19 +1318,19 @@
 	{
 	    if (*pnt >= '0' && *pnt <= '9')
 	    {
-		num = num * 10 + *pnt - '0';
+		num = (num << 4) + *pnt - '0';
 		pnt++;
 		continue;
 	    }
 	    if (*pnt >= 'a' && *pnt <= 'f')
 	    {
-		num = num * 10 + *pnt - 'a' + 10;
+		num = (num << 4) + *pnt - 'a' + 10;
 		pnt++;
 		continue;
 	    }
 	    if (*pnt >= 'A' && *pnt <= 'F')
 	    {
-		num = num * 10 + *pnt - 'A' + 10;
+		num = (num << 4) + *pnt - 'A' + 10;
 		pnt++;
 		continue;
 	    }
@@ -1133,6 +1365,7 @@
  * MANUFACTURER="string"
  * MODEL="string"
  * SERIAL_NUMBER="string"	(for those devices that support this).
+ * WWID=number			( "    "      "     "      "      " )
  * REV="string"
  * NAME="string" (alias)
  * DEVTYPE="disk", "tape", "osst", "generic", or "cdrom".
@@ -1150,6 +1383,7 @@
 
     int lun, chan, id, part, hostid, hostnum;
     int line;
+    unsigned long long wwid;	/* host byte order ... */
     int devtype_i;
     char *manufacturer, *model, *serial_number, *name, *devtype, *rev, *host;
     char *scsialias;
@@ -1186,11 +1420,11 @@
 	lun = -1; id = -1;
 	chan = -1;
 	hostid = -1; hostnum = -1;
-	part = -1;
+	part = -1; wwid = no_wwid;
 	host = NULL;
 	manufacturer = NULL; model = NULL;
 	serial_number = NULL; rev = NULL;
-	name = NULL;
+	name = NULL; 
 	devtype = NULL;
 	pnt = buffer;
 	while (*pnt == ' ' || *pnt == '\t') pnt++;
@@ -1218,6 +1452,10 @@
 	    {
 		pnt = get_string(pnt1 + 1, &serial_number);
 	    }
+	    else if ( strcmp(pnt, "wwid") == 0 )
+	    {
+		pnt = get_llnumber(pnt1 + 1, &wwid);
+	    }
 	    else if ( strncmp(pnt, "rev", 3) == 0 )
 	    {
 		pnt = get_string(pnt1 + 1, &rev);
@@ -1320,6 +1558,7 @@
 	    if( part != spnt->partition ) continue;
 	    if( (spnt->major == SCSI_TAPE_MAJOR || spnt->major == OSST_MAJOR)
 		&& (spnt->minor & 0x80) != 0) continue;
+	    if( wwid != no_wwid && wwid != spnt->wwid ) continue;
 
 	    /*
 	     * OK, that matches, now obtain some of the strings
@@ -1386,7 +1625,7 @@
 		else fprintf (stderr, "\n");
 	    }
 
-	    if( devtype_i == SCSI_DISK0_MAJOR
+	    if( SCSI_DISK_MAJOR(devtype_i)
 		|| devtype_i == SCSI_CDROM_MAJOR )
 		type = S_IFBLK;
 	    else
@@ -1397,7 +1636,7 @@
 	     * Just create it.
 	     */
 	    sprintf (scsidev, DEVSCSI "/%s", name);
-	    register_dev (scsidev, match->major, match->minor | 0x80, 
+	    register_dev (scsidev, match->major, match->minor, 
 			  0, 0, 0, 0, 0, 0, 0, match);
 	    if (symlink_alias) {
 		unlink (scsidev);
@@ -1445,7 +1684,7 @@
 
 		    sprintf(scsidev, DEVSCSI "/%s-p%d", name, 
 			    spnt->partition);
-		    register_dev (scsidev, match->major, match->minor | 0x80, 
+		    register_dev (scsidev, match->major, spnt->minor, 
 				  0, 0, 0, 0, 0, 0, 0, spnt);
 		    if (symlink_alias) {
 			unlink (scsidev);
@@ -1490,6 +1729,48 @@
     return str;
 }
 
+unsigned long long extract_wwid (unsigned char* page)
+{
+	unsigned int hi, lo;
+	if (page[1] != 0x83)
+		return no_wwid;
+	/* We only support binary data */
+	if ((page[4] & 0x0f) != 1)
+		return no_wwid;
+	/* We support identifier types 2, 3 */
+	if ((page[5] & 0x0f) != 3 && (page[5] & 0x0f) != 2)
+		return no_wwid;
+	/* Id length should be 8 (64 bits) */
+	if (page[7] != 8)
+		return no_wwid;
+	/* Now translate network byte order to host byte order */
+	hi = ntohl (*(unsigned int*)(page+ 8));
+	lo = ntohl (*(unsigned int*)(page+12));
+	return ((unsigned long long) hi << 32) + (unsigned long long) lo;
+}
+
+#define INQBUFSZ 512
+int get_inq_page (int file, int lun, unsigned char* buf, unsigned char page, char evpd)
+{
+	unsigned char *cmd;
+	
+	memset (buf, 0, INQBUFSZ);
+	
+	*( (int *)  buf)	= 0;			/* length of input data */
+	*( ((int *) buf) + 1 )	= INQBUFSZ-32;	/* length of output buffer */
+	
+	cmd = (char *) ( ((int *) buf) + 2 );
+	
+	cmd[0] = 0x12;			/* INQUIRY */
+	cmd[1] = (lun << 5) | (evpd? 1: 0);	/* lun, evpd=... */
+	cmd[2] = page;			/* page code 0: std inquiry */
+	cmd[3] = 0x00;			/* (reserved) */
+	cmd[4] = 0xfc;			/* allocation length */
+	cmd[5] = 0x00;			/* control */
+	
+	return ioctl (file, SCSI_IOCTL_SEND_COMMAND, buf);
+}
+	
 int inquiry (int infile, sname * spnt)
 {
 #ifdef DEBUG
@@ -1508,73 +1789,68 @@
     }
 #else
     int status;
-    unsigned char *cmd;
-    unsigned char * pagestart;
-    unsigned char buffer[1024];
+    unsigned char buffer[INQBUFSZ];
+    unsigned char * const pagestart = buffer + 8;
     //int infile;
-
-    memset (buffer, 0, sizeof(buffer));
-  
-    *( (int *)  buffer )		= 0;	/* length of input data */
-    *( ((int *) buffer) + 1 )	= sizeof(buffer)-16;	/* length of output buffer */
-
-    cmd = (char *) ( ((int *) buffer) + 2 );
-  
-    cmd[0] = 0x12;			/* INQUIRY */
-    cmd[1] = (spnt->lun << 5) | 0x01;	/* lun, evpd=1 */
-    cmd[2] = 0x80;			/* page code = 0x80, serial number */
-    cmd[3] = 0x00;			/* (reserved) */
-    cmd[4] = 0xff;			/* allocation length */
-    cmd[5] = 0x00;			/* control */
-
+    char have_ser_page = 0;
+    char have_wwid_page = 0;
+    int ln; int off;
+    int lun; int ansi;
+	
     //infile = open(spnt->name, O_RDWR);
     if( infile == -1 ) return -1;
-
-    status = ioctl( infile, 1, buffer );
-    //close(infile);
-    pagestart = buffer + 8;
-
-    if (status) 
-	spnt->serial = no_serial;
-    else
-	spnt->serial = getstr (pagestart, 4, 3+pagestart[3]);
-
-    if (verbose == 2) printf ("Serial for %s: %s\n", spnt->name, spnt->serial);
 
-    memset (buffer, 0, sizeof(buffer));
-  
-    *( (int *)  buffer )	= 0;			/* length of input data */
-    *( ((int *) buffer) + 1 )	= sizeof(buffer)-16;	/* length of output buffer */
-
-    cmd = (char *) ( ((int *) buffer) + 2 );
-  
-    cmd[0] = 0x12;			/* INQUIRY */
-    cmd[1] = (spnt->lun << 5);		/* lun, evpd=0 */
-    cmd[2] = 0x00;			/* page code 0: std inquiry */
-    cmd[3] = 0x00;			/* (reserved) */
-    cmd[4] = 0xff;			/* allocation length */
-    cmd[5] = 0x00;			/* control */
-
-    //infile = open (spnt->name, O_RDWR);
-    //if( infile == -1 ) return -1;
-
-    status = ioctl( infile, 1, buffer );
-    //close(infile);
-    pagestart = buffer + 8;
+    // Std. inquiry
+    status = get_inq_page (infile, 0, buffer, 0, 0);
 
     if (status) 
     { 
-	fprintf (stderr, "INQUIRY failed for %s (%i-%i)!\n", 
-		 spnt->name, spnt->id, spnt->lun);
-	return -1; 
+	fprintf (stderr, "INQUIRY failed for %s (%i-%i/%02x:%02x)!\n",
+		 spnt->name, spnt->id, spnt->lun, spnt->major, spnt->minor);
+	return -1;
     }
-    if (verbose == 2) dumppage (pagestart);
+    if (verbose == 2) 
+		dumppage (pagestart);
     spnt->manufacturer = getstr (pagestart, 8, 15); 
     spnt->model = getstr (pagestart, 16, 31);
     spnt->rev = getstr (pagestart, 32, 35);
     spnt->inq_devtp = pagestart[0] & 0x1f;
     spnt->rmvbl = (pagestart[1] & 0x80) >> 7;
+    spnt->wwid = no_wwid; spnt->serial = no_serial;
+    ansi = pagestart[2] & 7;
+	
+    if (ansi >= 3)
+	lun = 0;
+    else
+	lun = spnt->lun;
+
+    /* TODO: Extract serial number from bytes 36--43 ? */
+    
+    // List of supported EVPD pages ...
+    if (get_inq_page (infile, lun, buffer, 0, 1))
+	return 0;
+    ln = pagestart[3];
+    for (off = 0; off < ln; ++off) {
+	if (pagestart[4+off] == 0x80)
+		have_ser_page = 1;    
+	if (pagestart[4+off] == 0x83)
+		have_wwid_page = 1;    
+    }
+    
+    if (have_ser_page && !get_inq_page (infile, lun, buffer, 0x80, 1)) {
+	spnt->serial = getstr (pagestart, 4, 3+pagestart[3]);
+	if (verbose == 2) 
+	    printf ("Serial for %s: %s\n", spnt->name, spnt->serial);
+    }
+
+    if (have_wwid_page && !get_inq_page (infile, lun, buffer, 0x83, 1)) {
+	spnt->wwid = extract_wwid (pagestart);
+
+	if (verbose == 2)
+	    printf ("WWID for %s: %Lx\n", spnt->name, spnt->wwid);
+    }
 
+    //close(infile);
     return 0;
 #endif
 }
