public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH][RFC] Driverfs support for SCSI devices (updated)
  2002-06-17 23:16 [PATCH][RFC] Driverfs support for SCSI devices James Bottomley
@ 2002-06-18 21:56 ` sullivan
  0 siblings, 0 replies; 2+ messages in thread
From: sullivan @ 2002-06-18 21:56 UTC (permalink / raw)
  To: linux-kernel, linux-scsi; +Cc: James.Bottomley

[-- Attachment #1: Type: text/plain, Size: 392 bytes --]

On Mon, Jun 17, 2002 at 06:16:53PM -0500, James Bottomley wrote:
> I get a BUG in device.h:213 trying to insert the st.o module, but other than 
> that, it seems to be running OK.

Thanks James. Attached is an updated patch that fixes the st.o module and incorporates your other suggestions. The updated patch is also available at
http://www-124.ibm.com/devreg/linux-2.5.22-driverfs.patch.gz

[-- Attachment #2: linux-2.5.22-driverfs.patch --]
[-- Type: text/plain, Size: 38375 bytes --]

diff -Naur linux-2.5.22.orig/drivers/cdrom/cdrom.c linux-2.5.22-driverfs/drivers/cdrom/cdrom.c
--- linux-2.5.22.orig/drivers/cdrom/cdrom.c	Sun Jun 16 21:31:26 2002
+++ linux-2.5.22-driverfs/drivers/cdrom/cdrom.c	Mon Jun 17 21:14:07 2002
@@ -431,6 +431,11 @@
 		topCdromPtr = cdi->next;
 	cdi->ops->n_minors--;
 	devfs_unregister (cdi->de);
+	if (atomic_read (&cdi->cdrom_driverfs_dev.refcount)) {
+		device_remove_file (&cdi->cdrom_driverfs_dev, "name");
+		device_remove_file (&cdi->cdrom_driverfs_dev, "kdev");
+		put_device (&cdi->cdrom_driverfs_dev);
+	}
 	devfs_dealloc_unique_number (&cdrom_numspace, cdi->number);
 	cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
 	return 0;
diff -Naur linux-2.5.22.orig/drivers/scsi/hosts.h linux-2.5.22-driverfs/drivers/scsi/hosts.h
--- linux-2.5.22.orig/drivers/scsi/hosts.h	Sun Jun 16 21:31:29 2002
+++ linux-2.5.22-driverfs/drivers/scsi/hosts.h	Mon Jun 17 21:14:07 2002
@@ -418,6 +418,11 @@
      */
     struct pci_dev *pci_dev;
 
+    /* 
+     * Support for driverfs filesystem
+     */
+    struct device host_driverfs_dev;
+
     /*
      * We should ensure that this is aligned, both for better performance
      * and also because some compilers (m68k) don't automatically force
@@ -478,6 +483,7 @@
                                        struct pci_dev *pdev)
 {
 	SHpnt->pci_dev = pdev;
+	SHpnt->host_driverfs_dev.parent=&pdev->dev;
 }
 
 
@@ -516,6 +522,7 @@
     void (*detach)(Scsi_Device *);
     int (*init_command)(Scsi_Cmnd *);     /* Used by new queueing code. 
                                            Selects command for blkdevs */
+    struct device_driver scsi_driverfs_driver;
 };
 
 void  scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt);
diff -Naur linux-2.5.22.orig/drivers/scsi/scsi.c linux-2.5.22-driverfs/drivers/scsi/scsi.c
--- linux-2.5.22.orig/drivers/scsi/scsi.c	Sun Jun 16 21:31:33 2002
+++ linux-2.5.22-driverfs/drivers/scsi/scsi.c	Tue Jun 18 21:15:19 2002
@@ -1939,6 +1939,11 @@
 				}
 				printk(KERN_INFO "scsi%d : %s\n",		/* And print a little message */
 				       shpnt->host_no, name);
+				strncpy(shpnt->host_driverfs_dev.name,name,
+					DEVICE_NAME_SIZE-1);
+				sprintf(shpnt->host_driverfs_dev.bus_id,
+					"scsi%d",
+					shpnt->host_no);
 			}
 		}
 
@@ -1947,6 +1952,8 @@
 		 */
 		for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
 			if (shpnt->hostt == tpnt) {
+				/* first register parent with driverfs */
+				device_register(&shpnt->host_driverfs_dev);
 				scan_scsis(shpnt, 0, 0, 0, 0);
 				if (shpnt->select_queue_depths != NULL) {
 					(shpnt->select_queue_depths) (shpnt, shpnt->host_queue);
@@ -2101,6 +2108,7 @@
 				goto err_out;
 			}
 			devfs_unregister (SDpnt->de);
+			put_device(&SDpnt->sdev_driverfs_dev);
 		}
 	}
 
@@ -2151,6 +2159,7 @@
 		/* Remove the /proc/scsi directory entry */
 		sprintf(name,"%d",shpnt->host_no);
 		remove_proc_entry(name, tpnt->proc_dir);
+		put_device(&shpnt->host_driverfs_dev);
 		if (tpnt->release)
 			(*tpnt->release) (shpnt);
 		else {
@@ -2499,6 +2508,34 @@
 	mempool_free(sgl, sgp->pool);
 }
 
+static int scsi_bus_match(struct device *scsi_driverfs_dev, 
+                          struct device_driver *scsi_driverfs_drv)
+{
+        char *p=0;
+
+        if (!strcmp("sd", scsi_driverfs_drv->name)) {
+                if ((p = strstr(scsi_driverfs_dev->bus_id, ":disc")) || 
+		    (p = strstr(scsi_driverfs_dev->bus_id, ":p"))) { 
+                        return 1;
+                }
+        } else if (!strcmp("sg", scsi_driverfs_drv->name)) {
+                if (strstr(scsi_driverfs_dev->bus_id, ":gen"))
+                        return 1;
+        } else if (!strcmp("sr",scsi_driverfs_drv->name)) {
+                if (strstr(scsi_driverfs_dev->bus_id,":cd"))
+                        return 1;
+        } else if (!strcmp("st",scsi_driverfs_drv->name)) {
+                if (strstr(scsi_driverfs_dev->bus_id,":mt"))
+                        return 1;
+        }
+        return 0;
+}
+
+struct bus_type scsi_driverfs_bus_type = {
+        name: "scsi",
+        match: scsi_bus_match,
+};
+
 static int __init init_scsi(void)
 {
 	struct proc_dir_entry *generic;
@@ -2544,6 +2581,8 @@
         if (scsihosts)
 		printk(KERN_INFO "scsi: host order: %s\n", scsihosts);	
 	scsi_host_no_init (scsihosts);
+
+	bus_register(&scsi_driverfs_bus_type);
 	/*
 	 * This is where the processing takes place for most everything
 	 * when commands are completed.
diff -Naur linux-2.5.22.orig/drivers/scsi/scsi.h linux-2.5.22-driverfs/drivers/scsi/scsi.h
--- linux-2.5.22.orig/drivers/scsi/scsi.h	Sun Jun 16 21:31:27 2002
+++ linux-2.5.22-driverfs/drivers/scsi/scsi.h	Tue Jun 18 18:10:20 2002
@@ -417,6 +417,8 @@
 extern volatile int in_scan_scsis;
 extern const unsigned char scsi_command_size[8];
 
+extern struct bus_type scsi_driverfs_bus_type;
+
 
 /*
  * These are the error handling functions defined in scsi_error.c
@@ -622,6 +624,7 @@
 
 	// Flag to allow revalidate to succeed in sd_open
 	int allow_revalidate;
+	struct device sdev_driverfs_dev;
 };
 
 
diff -Naur linux-2.5.22.orig/drivers/scsi/scsi_scan.c linux-2.5.22-driverfs/drivers/scsi/scsi_scan.c
--- linux-2.5.22.orig/drivers/scsi/scsi_scan.c	Sun Jun 16 21:31:35 2002
+++ linux-2.5.22-driverfs/drivers/scsi/scsi_scan.c	Tue Jun 18 18:21:26 2002
@@ -54,6 +54,7 @@
 		char *scsi_result);
 static int find_lun0_scsi_level(unsigned int channel, unsigned int dev,
 				struct Scsi_Host *shpnt);
+static void scsi_load_identifier(Scsi_Device *SDpnt, Scsi_Request * SRpnt);
 
 struct dev_info {
 	const char *vendor;
@@ -288,6 +289,31 @@
 }
 #endif
 
+/* Driverfs file content handlers */
+static ssize_t scsi_device_type_read(struct device *driverfs_dev, char *page, 
+	size_t count, loff_t off)
+{
+	struct scsi_device *SDpnt = list_entry(driverfs_dev,
+		struct scsi_device, sdev_driverfs_dev);
+
+	if ((SDpnt->type <= MAX_SCSI_DEVICE_CODE) && 
+		(scsi_device_types[(int)SDpnt->type] != NULL))
+		return off ? 0 : 
+			sprintf(page, "%s\n", 
+				scsi_device_types[(int)SDpnt->type]);
+	else
+		return off ? 0 : sprintf(page, "UNKNOWN\n");
+
+	return 0;
+}
+
+static struct driver_file_entry scsi_device_type_file = {
+	name: "type",
+	mode: S_IRUGO,
+	show: scsi_device_type_read,
+};
+/* end content handlers */
+
 static void print_inquiry(unsigned char *data)
 {
 	int i;
@@ -786,6 +812,22 @@
 
 	print_inquiry(scsi_result);
 
+	/* interrogate scsi target to provide device identifier */
+	scsi_load_identifier(SDpnt, SRpnt);
+
+	/* create driverfs files */
+	sprintf(SDpnt->sdev_driverfs_dev.bus_id,"%d:%d:%d:%d",
+		SDpnt->host->host_no, SDpnt->channel, SDpnt->id, SDpnt->lun);
+	
+	SDpnt->sdev_driverfs_dev.parent = &SDpnt->host->host_driverfs_dev;
+	SDpnt->sdev_driverfs_dev.bus = &scsi_driverfs_bus_type;
+
+	device_register(&SDpnt->sdev_driverfs_dev); 
+
+	/* Create driverfs file entries */
+	device_create_file(&SDpnt->sdev_driverfs_dev, 
+			&scsi_device_type_file);
+
         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);
@@ -1306,3 +1348,374 @@
 	/* haven't found lun0, should send INQUIRY but take easy route */
 	return res;
 }
+
+#define SCSI_UID_DEV_ID  'U'
+#define SCSI_UID_SER_NUM 'S'
+#define SCSI_UID_UNKNOWN 'Z'
+
+unsigned char *scsi_get_evpd_page(Scsi_Device *SDpnt, Scsi_Request * SRpnt)
+{
+	unsigned char *evpd_page = NULL;
+	unsigned char *scsi_cmd = NULL;
+	int lun = SDpnt->lun;
+	int scsi_level = SDpnt->scsi_level;
+
+	evpd_page = kmalloc(255, 
+		(SDpnt->host->unchecked_isa_dma ? GFP_DMA : GFP_ATOMIC));
+	if (!evpd_page)
+		return NULL;
+
+	scsi_cmd = kmalloc(MAX_COMMAND_SIZE, GFP_ATOMIC);
+	if (!scsi_cmd) {
+		kfree(evpd_page);
+		return NULL;
+	}
+
+	/* Use vital product pages to determine serial number */
+	/* Try Supported vital product data pages 0x00 first */
+	scsi_cmd[0] = INQUIRY;
+	if ((lun > 0) && (scsi_level <= SCSI_2))
+		scsi_cmd[1] = ((lun << 5) & 0xe0) | 0x01;
+	else
+		scsi_cmd[1] = 0x01;	/* SCSI_3 and higher, don't touch */
+	scsi_cmd[2] = 0x00;
+	scsi_cmd[3] = 0;
+	scsi_cmd[4] = 255;
+	scsi_cmd[5] = 0;
+	SRpnt->sr_cmd_len = 0;
+	SRpnt->sr_sense_buffer[0] = 0;
+	SRpnt->sr_sense_buffer[2] = 0;
+	SRpnt->sr_data_direction = SCSI_DATA_READ;
+	scsi_wait_req(SRpnt, (void *) scsi_cmd, (void *) evpd_page,
+			255, SCSI_TIMEOUT+4*HZ, 3);
+
+	if (SRpnt->sr_result) {
+		kfree(scsi_cmd);
+		kfree(evpd_page);
+		return NULL;
+	}
+
+	/* check to see if response was truncated */
+	if (evpd_page[3] > 255) {
+		int max_lgth = evpd_page[3] + 4;
+
+		kfree(evpd_page);
+		evpd_page = kmalloc(max_lgth, (SDpnt->host->unchecked_isa_dma ? 
+			GFP_DMA : GFP_ATOMIC));
+		if (!evpd_page) {
+			kfree(scsi_cmd);
+			return NULL;
+		}
+		memset(scsi_cmd, 0, MAX_COMMAND_SIZE);
+		scsi_cmd[0] = INQUIRY;
+		if ((lun > 0) && (scsi_level <= SCSI_2))
+			scsi_cmd[1] = ((lun << 5) & 0xe0) | 0x01;
+		else
+			scsi_cmd[1] = 0x01; /* SCSI_3 and higher, don't touch */
+		scsi_cmd[2] = 0x00;
+		scsi_cmd[3] = 0;
+		scsi_cmd[4] = max_lgth;
+		scsi_cmd[5] = 0;
+		SRpnt->sr_cmd_len = 0;
+		SRpnt->sr_sense_buffer[0] = 0;
+		SRpnt->sr_sense_buffer[2] = 0;
+		SRpnt->sr_data_direction = SCSI_DATA_READ;
+		scsi_wait_req(SRpnt, (void *) scsi_cmd, (void *) evpd_page,
+			max_lgth, SCSI_TIMEOUT+4*HZ, 3);
+		if (SRpnt->sr_result) {
+			kfree(scsi_cmd);
+			kfree(evpd_page);
+			return NULL;
+		}
+	}
+	kfree(scsi_cmd);
+	/* some ill behaved devices return the std inquiry here rather than
+		the evpd data. snoop the data to verify */
+	if (evpd_page[3] > 16) {
+		/* if vend id appears in the evpd page assume evpd is invalid */
+		if (!strncmp(&evpd_page[8], SDpnt->vendor, 8)) {
+			kfree(evpd_page);
+			return NULL;
+		}
+	}
+	return evpd_page;
+}
+
+int scsi_get_deviceid(Scsi_Device *SDpnt,Scsi_Request * SRpnt)
+{
+	unsigned char *id_page = NULL;
+	unsigned char *scsi_cmd = NULL;
+	int scnt, i, j, idtype;
+	char * id = SDpnt->sdev_driverfs_dev.name;
+	int lun = SDpnt->lun;
+	int scsi_level = SDpnt->scsi_level;
+
+	id_page = kmalloc(255, 
+		(SDpnt->host->unchecked_isa_dma ? GFP_DMA : GFP_ATOMIC)); 
+	if (!id_page)
+		return 0;
+
+	scsi_cmd = kmalloc(MAX_COMMAND_SIZE, GFP_ATOMIC);
+	if (!scsi_cmd)
+		goto leave;
+
+	/* Use vital product pages to determine serial number */
+	/* Try Supported vital product data pages 0x00 first */
+	scsi_cmd[0] = INQUIRY;
+	if ((lun > 0) && (scsi_level <= SCSI_2))
+		scsi_cmd[1] = ((lun << 5) & 0xe0) | 0x01;
+	else
+		scsi_cmd[1] = 0x01;	/* SCSI_3 and higher, don't touch */
+	scsi_cmd[2] = 0x83;
+	scsi_cmd[3] = 0;
+	scsi_cmd[4] = 255;
+	scsi_cmd[5] = 0;
+	SRpnt->sr_cmd_len = 0;
+	SRpnt->sr_sense_buffer[0] = 0;
+	SRpnt->sr_sense_buffer[2] = 0;
+	SRpnt->sr_data_direction = SCSI_DATA_READ;
+	scsi_wait_req(SRpnt, (void *) scsi_cmd, (void *) id_page,
+			255, SCSI_TIMEOUT+4*HZ, 3);
+	if (SRpnt->sr_result) {
+		kfree(scsi_cmd);
+		goto leave;
+	}
+
+	/* check to see if response was truncated */
+	if (id_page[3] > 255) {
+		int max_lgth = id_page[3] + 4;
+
+		kfree(id_page);
+		id_page = kmalloc(max_lgth,
+			(SDpnt->host->unchecked_isa_dma ? 
+			GFP_DMA : GFP_ATOMIC)); 
+		if (!id_page) {
+			kfree(scsi_cmd);
+			return 0;
+		}
+		memset(scsi_cmd, 0, MAX_COMMAND_SIZE);
+		scsi_cmd[0] = INQUIRY;
+		if ((lun > 0) && (scsi_level <= SCSI_2))
+			scsi_cmd[1] = ((lun << 5) & 0xe0) | 0x01;
+		else
+			scsi_cmd[1] = 0x01; /* SCSI_3 and higher, don't touch */
+		scsi_cmd[2] = 0x83;
+		scsi_cmd[3] = 0;
+		scsi_cmd[4] = max_lgth;
+		scsi_cmd[5] = 0;
+		SRpnt->sr_cmd_len = 0;
+		SRpnt->sr_sense_buffer[0] = 0;
+		SRpnt->sr_sense_buffer[2] = 0;
+		SRpnt->sr_data_direction = SCSI_DATA_READ;
+		scsi_wait_req(SRpnt, (void *) scsi_cmd, (void *) id_page,
+				max_lgth, SCSI_TIMEOUT+4*HZ, 3);
+		if (SRpnt->sr_result) {
+			kfree(scsi_cmd);
+			goto leave;
+		}
+	}
+	kfree(scsi_cmd);
+
+	idtype = 3;
+	while (idtype > 0) {
+		for(scnt = 4; scnt <= id_page[3] + 3; 
+		    scnt += id_page[scnt + 3] + 4) {
+			if ((id_page[scnt + 1] & 0x0f) != idtype) {
+				continue;
+			}
+			if ((id_page[scnt] & 0x0f) == 2) {  
+				for(i = scnt + 4, j = 1;
+				    i < scnt + 4 + id_page[scnt + 3]; 
+				    i++) {
+					if (id_page[i] > 0x20) {
+						if (j == DEVICE_NAME_SIZE) {
+							memset(id, 0, 
+							    DEVICE_NAME_SIZE);
+							break;
+						}
+						id[j++] = id_page[i];
+					}
+				}
+			} else if ((id_page[scnt] & 0x0f) == 1) {
+				static const char hex_str[]="0123456789abcdef";
+				for(i = scnt + 4, j = 1;
+				    i < scnt + 4 + id_page[scnt + 3]; 
+				    i++) {
+					if ((j + 1) == DEVICE_NAME_SIZE) {
+						memset(id, 0, DEVICE_NAME_SIZE);
+						break;
+					}
+					id[j++] = hex_str[(id_page[i] & 0xf0) >>
+								4];
+					id[j++] = hex_str[id_page[i] & 0x0f];
+				}
+			}
+			if (id[1] != 0) goto leave;
+		}
+		idtype--;
+	}
+ leave:
+	kfree(id_page);
+	if (id[1] != 0) {
+		id[0] = SCSI_UID_DEV_ID;
+		return 1;
+	}
+	return 0;
+}
+
+int scsi_get_serialnumber(Scsi_Device *SDpnt, Scsi_Request * SRpnt)
+{
+	unsigned char *serialnumber_page = NULL;
+	unsigned char *scsi_cmd = NULL;
+	int lun = SDpnt->lun;
+	int scsi_level = SDpnt->scsi_level;
+	int i, j;
+
+	serialnumber_page = kmalloc(255, (SDpnt->host->unchecked_isa_dma ? 
+			GFP_DMA : GFP_ATOMIC));
+	if (!serialnumber_page)
+		return 0;
+
+	scsi_cmd = kmalloc(MAX_COMMAND_SIZE, GFP_ATOMIC);
+	if (!scsi_cmd)
+		goto leave;
+
+	/* Use vital product pages to determine serial number */
+	/* Try Supported vital product data pages 0x00 first */
+	scsi_cmd[0] = INQUIRY;
+	if ((lun > 0) && (scsi_level <= SCSI_2))
+		scsi_cmd[1] = ((lun << 5) & 0xe0) | 0x01;
+	else	
+		scsi_cmd[1] = 0x01;	/* SCSI_3 and higher, don't touch */
+	scsi_cmd[2] = 0x80;
+	scsi_cmd[3] = 0;
+	scsi_cmd[4] = 255;
+	scsi_cmd[5] = 0;
+	SRpnt->sr_cmd_len = 0;
+	SRpnt->sr_sense_buffer[0] = 0;
+	SRpnt->sr_sense_buffer[2] = 0;
+	SRpnt->sr_data_direction = SCSI_DATA_READ;
+	scsi_wait_req(SRpnt, (void *) scsi_cmd, (void *) serialnumber_page,
+			255, SCSI_TIMEOUT+4*HZ, 3);
+
+	if (SRpnt->sr_result) {
+		kfree(scsi_cmd);
+		goto leave;
+	}
+	/* check to see if response was truncated */
+	if (serialnumber_page[3] > 255) {
+		int max_lgth = serialnumber_page[3] + 4;
+
+		kfree(serialnumber_page);
+		serialnumber_page = kmalloc(max_lgth, 
+			(SDpnt->host->unchecked_isa_dma ? 
+			GFP_DMA : GFP_ATOMIC));
+		if (!serialnumber_page) {
+			kfree(scsi_cmd);
+			return 0;
+		}
+		memset(scsi_cmd, 0, MAX_COMMAND_SIZE);
+		scsi_cmd[0] = INQUIRY;
+		if ((lun > 0) && (scsi_level <= SCSI_2))
+			scsi_cmd[1] = ((lun << 5) & 0xe0) | 0x01;
+		else
+			scsi_cmd[1] = 0x01; /* SCSI_3 and higher, don't touch */
+		scsi_cmd[2] = 0x80;
+		scsi_cmd[3] = 0;
+		scsi_cmd[4] = max_lgth;
+		scsi_cmd[5] = 0;
+		SRpnt->sr_cmd_len = 0;
+		SRpnt->sr_sense_buffer[0] = 0;
+		SRpnt->sr_sense_buffer[2] = 0;
+		SRpnt->sr_data_direction = SCSI_DATA_READ;
+		scsi_wait_req(SRpnt, (void *) scsi_cmd, 
+				(void *) serialnumber_page,
+				max_lgth, SCSI_TIMEOUT+4*HZ, 3);
+		if (SRpnt->sr_result) {
+			kfree(scsi_cmd);
+			goto leave;
+		}
+	}
+	kfree(scsi_cmd);
+
+	SDpnt->sdev_driverfs_dev.name[0] = SCSI_UID_SER_NUM;
+	for(i = 0, j = 1; i < serialnumber_page[3]; i++) {
+		if (serialnumber_page[4 + i] > 0x20)
+			SDpnt->sdev_driverfs_dev.name[j++] = 
+				serialnumber_page[4 + i];
+	}
+	for(i = 0, j = strlen(SDpnt->sdev_driverfs_dev.name); i < 8; i++) {
+		if (SDpnt->vendor[i] > 0x20) {
+			SDpnt->sdev_driverfs_dev.name[j++] = SDpnt->vendor[i];
+		}
+	}
+	kfree(serialnumber_page);
+	return 1;
+ leave:
+	memset(SDpnt->sdev_driverfs_dev.name, 0, DEVICE_NAME_SIZE);
+	kfree(serialnumber_page);
+	return 0;
+}
+
+int scsi_get_default_name(Scsi_Device *SDpnt)
+{
+	int i, j;
+
+	SDpnt->sdev_driverfs_dev.name[0] = SCSI_UID_UNKNOWN;
+	for(i = 0, j = 1; i < 8; i++) {
+		if (SDpnt->vendor[i] > 0x20) {
+			SDpnt->sdev_driverfs_dev.name[j++] = 
+				SDpnt->vendor[i];
+		}
+	}
+	for(i = 0, j = strlen(SDpnt->sdev_driverfs_dev.name); 
+	    i < 16; i++) {
+		if (SDpnt->model[i] > 0x20) {
+			SDpnt->sdev_driverfs_dev.name[j++] = 
+				SDpnt->model[i];
+		}
+	}
+	for(i = 0, j = strlen(SDpnt->sdev_driverfs_dev.name); i < 4; i++) {
+		if (SDpnt->rev[i] > 0x20) {
+			SDpnt->sdev_driverfs_dev.name[j++] = SDpnt->rev[i];
+		}
+	}	
+	return 1;
+}
+
+
+static void scsi_load_identifier(Scsi_Device *SDpnt, Scsi_Request * SRpnt)
+{
+	unsigned char *evpd_page = NULL;
+	int cnt;
+
+	memset(SDpnt->sdev_driverfs_dev.name, 0, DEVICE_NAME_SIZE);
+	evpd_page = scsi_get_evpd_page(SDpnt, SRpnt);
+	if (!evpd_page) {
+		/* try to obtain serial number anyway */
+		if (!scsi_get_serialnumber(SDpnt, SRpnt))
+			goto leave;
+		goto leave;
+	}
+
+	for(cnt = 4; cnt <= evpd_page[3] + 3; cnt++) {
+		if (evpd_page[cnt] == 0x83) {
+			if (scsi_get_deviceid(SDpnt, SRpnt))
+				goto leave;
+		}
+	}
+
+	for(cnt = 4; cnt <= evpd_page[3] + 3; cnt++) {
+		if (evpd_page[cnt] == 0x80) {
+			if (scsi_get_serialnumber(SDpnt, SRpnt))
+				goto leave;
+		}
+	}
+
+leave:
+	if (SDpnt->sdev_driverfs_dev.name[0] == 0)
+		scsi_get_default_name(SDpnt);
+
+	if (evpd_page) kfree(evpd_page);
+	return;
+}
diff -Naur linux-2.5.22.orig/drivers/scsi/scsi_syms.c linux-2.5.22-driverfs/drivers/scsi/scsi_syms.c
--- linux-2.5.22.orig/drivers/scsi/scsi_syms.c	Sun Jun 16 21:31:32 2002
+++ linux-2.5.22-driverfs/drivers/scsi/scsi_syms.c	Tue Jun 18 21:13:34 2002
@@ -101,3 +101,8 @@
 extern int scsi_delete_timer(Scsi_Cmnd *);
 EXPORT_SYMBOL(scsi_add_timer);
 EXPORT_SYMBOL(scsi_delete_timer);
+
+/*
+ * driverfs support for determining driver types
+ */
+EXPORT_SYMBOL(scsi_driverfs_bus_type);
diff -Naur linux-2.5.22.orig/drivers/scsi/sd.c linux-2.5.22-driverfs/drivers/scsi/sd.c
--- linux-2.5.22.orig/drivers/scsi/sd.c	Sun Jun 16 21:31:27 2002
+++ linux-2.5.22-driverfs/drivers/scsi/sd.c	Tue Jun 18 22:45:19 2002
@@ -128,6 +128,7 @@
 
 static Scsi_Disk * sd_get_sdisk(int index);
 
+extern void driverfs_remove_partitions(struct gendisk *hd, int minor);
 
 #if defined(CONFIG_PPC32)
 /**
@@ -1276,12 +1277,15 @@
 
 		init_mem_lth(sd_gendisks[k].de_arr, N);
 		init_mem_lth(sd_gendisks[k].flags, N);
+		init_mem_lth(sd_gendisks[k].driverfs_dev_arr, N);
 
-		if (!sd_gendisks[k].de_arr || !sd_gendisks[k].flags)
+		if (!sd_gendisks[k].de_arr || !sd_gendisks[k].flags ||
+				!sd_gendisks[k].driverfs_dev_arr)
 			goto cleanup_gendisks;
 
 		zero_mem_lth(sd_gendisks[k].de_arr, N);
 		zero_mem_lth(sd_gendisks[k].flags, N);
+		zero_mem_lth(sd_gendisks[k].driverfs_dev_arr, N);
 
 		sd_gendisks[k].major = SD_MAJOR(k);
 		sd_gendisks[k].major_name = "sd";
@@ -1290,7 +1294,6 @@
 		sd_gendisks[k].sizes = sd_sizes + k * (N << 4);
 		sd_gendisks[k].nr_real = 0;
 	}
-
 	return 0;
 
 #undef init_mem_lth
@@ -1301,6 +1304,7 @@
 	for (k = 0; k < N_USED_SD_MAJORS; k++) {
 		vfree(sd_gendisks[k].de_arr);
 		vfree(sd_gendisks[k].flags);
+		vfree(sd_gendisks[k].driverfs_dev_arr);
 	}
 cleanup_mem:
 	vfree(sd_gendisks);
@@ -1435,6 +1439,8 @@
 	SD_GENDISK(dsk_nr).nr_real++;
         devnum = dsk_nr % SCSI_DISKS_PER_MAJOR;
         SD_GENDISK(dsk_nr).de_arr[devnum] = sdp->de;
+        SD_GENDISK(dsk_nr).driverfs_dev_arr[devnum] = 
+		&sdp->sdev_driverfs_dev;
         if (sdp->removable)
 		SD_GENDISK(dsk_nr).flags[devnum] |= GENHD_FL_REMOVABLE;
 	sd_dskname(dsk_nr, diskname);
@@ -1534,6 +1540,8 @@
 	max_p = 1 << sd_gendisk.minor_shift;
 	start = dsk_nr << sd_gendisk.minor_shift;
 	dev = MKDEV_SD_PARTITION(start);
+	driverfs_remove_partitions(&SD_GENDISK (dsk_nr), 
+					SD_MINOR_NUMBER (start));
 	wipe_partitions(dev);
 	for (j = max_p - 1; j >= 0; j--)
 		sd_sizes[start + j] = 0;
@@ -1555,9 +1563,16 @@
  **/
 static int __init init_sd(void)
 {
+	int rc;
 	SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n"));
 	sd_template.module = THIS_MODULE;
-	return scsi_register_device(&sd_template);
+	rc = scsi_register_device(&sd_template);
+	if (!rc) {
+		sd_template.scsi_driverfs_driver.name = (char *)sd_template.tag;
+		sd_template.scsi_driverfs_driver.bus = &scsi_driverfs_bus_type;
+		driver_register(&sd_template.scsi_driverfs_driver);
+	}
+	return rc;
 }
 
 /**
@@ -1590,6 +1605,7 @@
 	sd_template.dev_max = 0;
 	if (sd_gendisks != &sd_gendisk)
 		vfree(sd_gendisks);
+	remove_driver(&sd_template.scsi_driverfs_driver);
 }
 
 static Scsi_Disk * sd_get_sdisk(int index)
diff -Naur linux-2.5.22.orig/drivers/scsi/sg.c linux-2.5.22-driverfs/drivers/scsi/sg.c
--- linux-2.5.22.orig/drivers/scsi/sg.c	Sun Jun 16 21:31:31 2002
+++ linux-2.5.22-driverfs/drivers/scsi/sg.c	Tue Jun 18 22:43:06 2002
@@ -194,6 +194,7 @@
     volatile char detached;  /* 0->attached, 1->detached pending removal */
     volatile char exclude;   /* opened for exclusive access */
     char sgdebug;       /* 0->off, 1->sense, 9->dump dev, 10-> all devs */
+    struct device sg_driverfs_dev;
 } Sg_device; /* 36 bytes long on i386 */
 
 
@@ -1370,6 +1371,29 @@
 __setup("sg_def_reserved_size=", sg_def_reserved_size_setup);
 #endif
 
+/* Driverfs file support */
+static ssize_t sg_device_kdev_read(struct device *driverfs_dev, char *page, 
+		size_t count, loff_t off)
+{
+	Sg_device * sdp=list_entry(driverfs_dev, Sg_device, sg_driverfs_dev);
+	return off ? 0 : sprintf(page, "%x\n",sdp->i_rdev.value);
+}
+static struct driver_file_entry sg_device_kdev_file = {
+	name: "kdev",
+	mode: S_IRUGO,
+	show: sg_device_kdev_read,
+};
+
+static ssize_t sg_device_type_read(struct device *driverfs_dev, char *page, 
+		size_t count, loff_t off) 
+{
+	return off ? 0 : sprintf (page, "CHR\n");
+}
+static struct driver_file_entry sg_device_type_file = {
+	name: "type",
+	mode: S_IRUGO,
+	show: sg_device_type_read,
+};
 
 static int sg_attach(Scsi_Device * scsidp)
 {
@@ -1428,6 +1452,18 @@
     sdp->detached = 0;
     sdp->sg_tablesize = scsidp->host ? scsidp->host->sg_tablesize : 0;
     sdp->i_rdev = mk_kdev(SCSI_GENERIC_MAJOR, k);
+
+    memset(&sdp->sg_driverfs_dev, 0, sizeof(struct device));
+    sprintf(sdp->sg_driverfs_dev.bus_id, "%s:gen",
+	    scsidp->sdev_driverfs_dev.bus_id);
+    sprintf(sdp->sg_driverfs_dev.name, "%sgeneric", 
+	    scsidp->sdev_driverfs_dev.name);
+    sdp->sg_driverfs_dev.parent = &scsidp->sdev_driverfs_dev;
+    sdp->sg_driverfs_dev.bus = &scsi_driverfs_bus_type;
+    device_register(&sdp->sg_driverfs_dev);
+    device_create_file(&sdp->sg_driverfs_dev, &sg_device_type_file);
+    device_create_file(&sdp->sg_driverfs_dev, &sg_device_kdev_file);
+
     sdp->de = devfs_register (scsidp->de, "generic", DEVFS_FL_DEFAULT,
                              SCSI_GENERIC_MAJOR, k,
                              S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
@@ -1496,6 +1532,9 @@
             }
 	    SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d, dirty\n", k));
 	    devfs_unregister (sdp->de);
+	    device_remove_file(&sdp->sg_driverfs_dev,sg_device_type_file.name);
+	    device_remove_file(&sdp->sg_driverfs_dev,sg_device_kdev_file.name);
+	    put_device(&sdp->sg_driverfs_dev);
 	    sdp->de = NULL;
 	    if (NULL == sdp->headfp) {
 		kfree((char *)sdp);
@@ -1505,6 +1544,7 @@
         else { /* nothing active, simple case */
             SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d\n", k));
 	    devfs_unregister (sdp->de);
+	    put_device(&sdp->sg_driverfs_dev);
 	    kfree((char *)sdp);
 	    sg_dev_arr[k] = NULL;
         }
@@ -1529,9 +1569,16 @@
 MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd");
 
 static int __init init_sg(void) {
+    int rc;
     if (def_reserved_size >= 0)
 	sg_big_buff = def_reserved_size;
-    return scsi_register_device(&sg_template);
+    rc = scsi_register_device(&sg_template);
+    if (!rc) {
+	sg_template.scsi_driverfs_driver.name = (char *)sg_template.tag;
+	sg_template.scsi_driverfs_driver.bus = &scsi_driverfs_bus_type;
+	driver_register(&sg_template.scsi_driverfs_driver);
+    }
+    return rc; 
 }
 
 static void __exit exit_sg( void)
@@ -1546,6 +1593,7 @@
         sg_dev_arr = NULL;
     }
     sg_template.dev_max = 0;
+    remove_driver(&sg_template.scsi_driverfs_driver);
 }
 
 
diff -Naur linux-2.5.22.orig/drivers/scsi/sr.c linux-2.5.22-driverfs/drivers/scsi/sr.c
--- linux-2.5.22.orig/drivers/scsi/sr.c	Sun Jun 16 21:31:27 2002
+++ linux-2.5.22-driverfs/drivers/scsi/sr.c	Tue Jun 18 22:44:21 2002
@@ -730,6 +730,32 @@
 	return 1;
 }
 
+/* Driverfs file support */
+static ssize_t sr_device_kdev_read(struct device *driverfs_dev, 
+				   char *page, size_t count, loff_t off)
+{
+	kdev_t kdev; 
+	kdev.value=(int)driverfs_dev->driver_data;
+	return off ? 0 : sprintf(page, "%x\n",kdev.value);
+}
+static struct driver_file_entry sr_device_kdev_file = {
+	name: "kdev",
+	mode: S_IRUGO,
+	show: sr_device_kdev_read,
+};
+
+static ssize_t sr_device_type_read(struct device *driverfs_dev, 
+				   char *page, size_t count, loff_t off) 
+{
+	return off ? 0 : sprintf (page, "CHR\n");
+}
+static struct driver_file_entry sr_device_type_file = {
+	name: "type",
+	mode: S_IRUGO,
+	show: sr_device_type_read,
+};
+
+
 void sr_finish()
 {
 	int i;
@@ -775,6 +801,20 @@
 
 		sprintf(name, "sr%d", i);
 		strcpy(SCp->cdi.name, name);
+		sprintf(SCp->cdi.cdrom_driverfs_dev.bus_id, "%s:cd",
+			SCp->device->sdev_driverfs_dev.bus_id);
+		sprintf(SCp->cdi.cdrom_driverfs_dev.name, "%scdrom",
+			SCp->device->sdev_driverfs_dev.name);
+		SCp->cdi.cdrom_driverfs_dev.parent = 
+			&SCp->device->sdev_driverfs_dev;
+		SCp->cdi.cdrom_driverfs_dev.bus = &scsi_driverfs_bus_type;
+		SCp->cdi.cdrom_driverfs_dev.driver_data = 
+			(void *)__mkdev(MAJOR_NR, i);
+		device_register(&SCp->cdi.cdrom_driverfs_dev);
+		device_create_file(&SCp->cdi.cdrom_driverfs_dev,
+				&sr_device_type_file);
+		device_create_file(&SCp->cdi.cdrom_driverfs_dev,
+				&sr_device_kdev_file);
                 SCp->cdi.de = devfs_register(SCp->device->de, "cd",
                                     DEVFS_FL_DEFAULT, MAJOR_NR, i,
                                     S_IFBLK | S_IRUGO | S_IWUGO,
@@ -815,7 +855,14 @@
 
 static int __init init_sr(void)
 {
-	return scsi_register_device(&sr_template);
+	int rc;
+	rc = scsi_register_device(&sr_template);
+	if (!rc) {
+		sr_template.scsi_driverfs_driver.name = (char *)sr_template.tag;
+		sr_template.scsi_driverfs_driver.bus = &scsi_driverfs_bus_type;
+		driver_register(&sr_template.scsi_driverfs_driver);
+	}
+	return rc;
 }
 
 static void __exit exit_sr(void)
@@ -832,6 +879,7 @@
 	blk_clear(MAJOR_NR);
 
 	sr_template.dev_max = 0;
+	remove_driver(&sr_template.scsi_driverfs_driver);
 }
 
 module_init(init_sr);
diff -Naur linux-2.5.22.orig/drivers/scsi/st.c linux-2.5.22-driverfs/drivers/scsi/st.c
--- linux-2.5.22.orig/drivers/scsi/st.c	Sun Jun 16 21:31:34 2002
+++ linux-2.5.22-driverfs/drivers/scsi/st.c	Tue Jun 18 18:09:33 2002
@@ -3677,6 +3677,31 @@
 
 #endif
 
+/* Driverfs file support */
+static ssize_t st_device_kdev_read(struct device *driverfs_dev, 
+				   char *page, size_t count, loff_t off)
+{
+	kdev_t kdev; 
+	kdev.value=(int)driverfs_dev->driver_data;
+	return off ? 0 : sprintf(page, "%x\n",kdev.value);
+}
+static struct driver_file_entry st_device_kdev_file = {
+	name: "kdev",
+	mode: S_IRUGO,
+	show: st_device_kdev_read,
+};
+
+static ssize_t st_device_type_read(struct device *driverfs_dev, 
+				   char *page, size_t count, loff_t off) 
+{
+	return off ? 0 : sprintf (page, "CHR\n");
+}
+static struct driver_file_entry st_device_type_file = {
+	name: "type",
+	mode: S_IRUGO,
+	show: st_device_type_read,
+};
+
 
 static struct file_operations st_fops =
 {
@@ -3779,6 +3804,18 @@
 
 	    /*  Rewind entry  */
 	    sprintf (name, "mt%s", formats[mode]);
+	    sprintf(tpnt->driverfs_dev_r[mode].bus_id, "%s:%s", 
+		    SDp->sdev_driverfs_dev.name, name);
+	    sprintf(tpnt->driverfs_dev_r[mode].name, "%s%s", 
+		    SDp->sdev_driverfs_dev.name, name);
+	    tpnt->driverfs_dev_r[mode].parent = &SDp->sdev_driverfs_dev;
+	    tpnt->driverfs_dev_r[mode].bus = &scsi_driverfs_bus_type;
+	    tpnt->driverfs_dev_r[mode].driver_data =
+			(void *)__mkdev(MAJOR_NR, i + (mode << 5));
+	    device_register(&tpnt->driverfs_dev_r[mode]);
+	    device_create_file(&tpnt->driverfs_dev_r[mode], 
+			       &st_device_type_file);
+	    device_create_file(&tpnt->driverfs_dev_r[mode], &st_device_kdev_file);
 	    tpnt->de_r[mode] =
 		devfs_register (SDp->de, name, DEVFS_FL_DEFAULT,
 				MAJOR_NR, i + (mode << 5),
@@ -3786,6 +3823,19 @@
 				&st_fops, NULL);
 	    /*  No-rewind entry  */
 	    sprintf (name, "mt%sn", formats[mode]);
+	    sprintf(tpnt->driverfs_dev_n[mode].bus_id, "%s:%s", 
+		    SDp->sdev_driverfs_dev.name, name);
+	    sprintf(tpnt->driverfs_dev_n[mode].name, "%s%s", 
+		    SDp->sdev_driverfs_dev.name, name);
+	    tpnt->driverfs_dev_n[mode].parent= &SDp->sdev_driverfs_dev;
+	    tpnt->driverfs_dev_n[mode].bus = &scsi_driverfs_bus_type;
+	    tpnt->driverfs_dev_n[mode].driver_data =
+			(void *)__mkdev(MAJOR_NR, i + (mode << 5) + 128);
+	    device_register(&tpnt->driverfs_dev_n[mode]);
+	    device_create_file(&tpnt->driverfs_dev_n[mode], 
+			&st_device_type_file);
+	    device_create_file(&tpnt->driverfs_dev_n[mode], 
+			&st_device_kdev_file);
 	    tpnt->de_n[mode] =
 		devfs_register (SDp->de, name, DEVFS_FL_DEFAULT,
 				MAJOR_NR, i + (mode << 5) + 128,
@@ -3894,8 +3944,18 @@
 			for (mode = 0; mode < ST_NBR_MODES; ++mode) {
 				devfs_unregister (tpnt->de_r[mode]);
 				tpnt->de_r[mode] = NULL;
+				device_remove_file(&tpnt->driverfs_dev_r[mode],
+						   st_device_type_file.name);
+				device_remove_file(&tpnt->driverfs_dev_r[mode],
+						   st_device_kdev_file.name);
+				put_device(&tpnt->driverfs_dev_r[mode]);
 				devfs_unregister (tpnt->de_n[mode]);
 				tpnt->de_n[mode] = NULL;
+				device_remove_file(&tpnt->driverfs_dev_n[mode],
+						   st_device_type_file.name);
+				device_remove_file(&tpnt->driverfs_dev_n[mode],
+						   st_device_kdev_file.name);
+				put_device(&tpnt->driverfs_dev_n[mode]);
 			}
 			kfree(tpnt);
 			scsi_tapes[i] = 0;
@@ -3921,8 +3981,16 @@
 		verstr, st_buffer_size, st_write_threshold,
 		st_max_buffers, st_max_sg_segs);
 
-	if (devfs_register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops) >= 0)
-		return scsi_register_device(&st_template);
+	if (devfs_register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops) >= 0) {
+		if (scsi_register_device(&st_template) == 0) {
+			st_template.scsi_driverfs_driver.name = 
+				(char *)st_template.tag;
+			st_template.scsi_driverfs_driver.bus = 
+				&scsi_driverfs_bus_type;
+			driver_register(&st_template.scsi_driverfs_driver);
+			return 0;
+		}
+	}
 
 	printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", MAJOR_NR);
 	return 1;
@@ -3951,6 +4019,7 @@
 		}
 	}
 	st_template.dev_max = 0;
+	remove_driver(&st_template.scsi_driverfs_driver);
 	printk(KERN_INFO "st: Unloaded.\n");
 }
 
diff -Naur linux-2.5.22.orig/drivers/scsi/st.h linux-2.5.22-driverfs/drivers/scsi/st.h
--- linux-2.5.22.orig/drivers/scsi/st.h	Sun Jun 16 21:31:28 2002
+++ linux-2.5.22-driverfs/drivers/scsi/st.h	Mon Jun 17 21:14:07 2002
@@ -94,6 +94,8 @@
 	int current_mode;
 	devfs_handle_t de_r[ST_NBR_MODES];  /*  Rewind entries     */
 	devfs_handle_t de_n[ST_NBR_MODES];  /*  No-rewind entries  */
+	struct device driverfs_dev_r[ST_NBR_MODES];
+	struct device driverfs_dev_n[ST_NBR_MODES];
 
 	/* Status variables */
 	int partition;
diff -Naur linux-2.5.22.orig/fs/partitions/check.c linux-2.5.22-driverfs/fs/partitions/check.c
--- linux-2.5.22.orig/fs/partitions/check.c	Sun Jun 16 21:31:30 2002
+++ linux-2.5.22-driverfs/fs/partitions/check.c	Mon Jun 17 21:14:07 2002
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/raid/md.h>
 #include <linux/buffer_head.h>	/* for invalidate_bdev() */
+#include <linux/kmod.h>
 
 #include "check.h"
 
@@ -221,6 +222,136 @@
 #endif
 }
 
+/* Driverfs file support */
+static ssize_t partition_device_kdev_read(struct device *driverfs_dev, 
+			char *page, size_t count, loff_t off)
+{
+	kdev_t kdev; 
+	kdev.value=(int)driverfs_dev->driver_data;
+	return off ? 0 : sprintf (page, "%x\n",kdev.value);
+}
+static struct driver_file_entry partition_device_kdev_file = {
+	name: "kdev",
+	mode: S_IRUGO,
+	show: partition_device_kdev_read,
+};
+
+static ssize_t partition_device_type_read(struct device *driverfs_dev, 
+			char *page, size_t count, loff_t off) 
+{
+	return off ? 0 : sprintf (page, "BLK\n");
+}
+static struct driver_file_entry partition_device_type_file = {
+	name: "type",
+	mode: S_IRUGO,
+	show: partition_device_type_read,
+};
+
+void driverfs_create_partitions(struct gendisk *hd, int minor)
+{
+	int pos = -1;
+	int devnum = minor >> hd->minor_shift;
+	char dirname[256];
+	struct device *parent = 0;
+	int max_p;
+	int part;
+	devfs_handle_t dir = 0;
+	
+	/* get parent driverfs device structure */
+	if (hd->driverfs_dev_arr)
+		parent = hd->driverfs_dev_arr[devnum];
+	else /* if driverfs not supported by subsystem, skip partitions */
+		return;
+	
+	/* get parent device node directory name */
+	if (hd->de_arr) {
+		dir = hd->de_arr[devnum];
+		if (dir)
+			pos = devfs_generate_path (dir, dirname, 
+						   sizeof dirname);
+	}
+	
+	if (pos < 0) {
+		disk_name(hd, minor, dirname);
+		pos = 0;
+	}
+	
+	max_p = (1 << hd->minor_shift);
+	
+	/* for all partitions setup parents and device node names */
+	for(part=0; part < max_p; part++) {
+		if ((part == 0) || (hd->part[minor + part].nr_sects >= 1)) {
+			struct device * current_driverfs_dev = 
+				&hd->part[minor+part].hd_driverfs_dev;
+			current_driverfs_dev->parent = parent;
+			/* handle disc case */
+			current_driverfs_dev->driver_data =
+					(void *)__mkdev(hd->major, minor+part);
+			if (part == 0) {
+				if (parent)  {
+					sprintf(current_driverfs_dev->name,
+						"%sdisc", parent->name);
+					sprintf(current_driverfs_dev->bus_id,
+						"%s:disc", parent->bus_id);
+				} else {
+					sprintf(current_driverfs_dev->name, 
+						"disc");
+					sprintf(current_driverfs_dev->bus_id,
+						"disc");
+				}
+			} else { /* this is a partition */
+				if (parent) {
+					sprintf(current_driverfs_dev->name,
+						"%spart%d", parent->name, part);
+					sprintf(current_driverfs_dev->bus_id,
+						"%s:p%d", parent->bus_id, part);
+				} else {
+					sprintf(current_driverfs_dev->name, 
+						"part%d", part);
+					sprintf(current_driverfs_dev->bus_id, 
+						"p%d" ,part);
+				}
+			}
+			if (parent) current_driverfs_dev->bus = parent->bus;
+			device_register(current_driverfs_dev);
+			device_create_file(current_driverfs_dev,
+					&partition_device_type_file);
+			device_create_file(current_driverfs_dev,
+					&partition_device_kdev_file);
+		}
+	}
+	return;
+}
+
+void driverfs_remove_partitions(struct gendisk *hd, int minor)
+{
+	int max_p;
+	int part;
+	struct device * current_driverfs_dev;
+	
+	max_p=(1 << hd->minor_shift);
+	
+	/* for all parts setup parent relationships and device node names */
+	for(part=1; part < max_p; part++) {
+		if ((hd->part[minor + part].nr_sects >= 1)) {
+			current_driverfs_dev = 
+				&hd->part[minor + part].hd_driverfs_dev;
+			device_remove_file(current_driverfs_dev,
+					partition_device_type_file.name);
+			device_remove_file(current_driverfs_dev,
+					partition_device_kdev_file.name);
+			put_device(current_driverfs_dev);	
+		}
+	}
+	current_driverfs_dev = &hd->part[minor].hd_driverfs_dev;
+	device_remove_file(current_driverfs_dev, 
+				partition_device_type_file.name);
+	device_remove_file(current_driverfs_dev, 
+				partition_device_kdev_file.name);
+	put_device(current_driverfs_dev);	
+	return;
+}
+
 static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor)
 {
 	devfs_handle_t de = NULL;
@@ -281,6 +412,13 @@
 	truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
 	bdput(bdev);
 	i = first_part_minor - 1;
+
+	/* Setup driverfs tree */
+	if (hd->sizes)
+		driverfs_create_partitions(hd, i);
+	else
+		driverfs_remove_partitions(hd, i);
+
 	devfs_register_partitions (hd, i, hd->sizes ? 0 : 1);
 }
 
diff -Naur linux-2.5.22.orig/include/linux/cdrom.h linux-2.5.22-driverfs/include/linux/cdrom.h
--- linux-2.5.22.orig/include/linux/cdrom.h	Sun Jun 16 21:31:23 2002
+++ linux-2.5.22-driverfs/include/linux/cdrom.h	Mon Jun 17 21:14:07 2002
@@ -716,6 +716,7 @@
 
 #ifdef __KERNEL__
 #include <linux/devfs_fs_kernel.h>
+#include <linux/device.h>
 
 struct cdrom_write_settings {
 	unsigned char fpacket;		/* fixed/variable packets */
@@ -730,6 +731,7 @@
 	struct cdrom_device_info *next; /* next device_info for this major */
 	void *handle;		        /* driver-dependent data */
 	devfs_handle_t de;		/* real driver should create this  */
+	struct device cdrom_driverfs_dev; /* driverfs implementation */
 	int number;			/* generic driver updates this  */
 /* specifications */
         kdev_t dev;	                /* device number */
diff -Naur linux-2.5.22.orig/include/linux/genhd.h linux-2.5.22-driverfs/include/linux/genhd.h
--- linux-2.5.22.orig/include/linux/genhd.h	Sun Jun 16 21:31:26 2002
+++ linux-2.5.22-driverfs/include/linux/genhd.h	Mon Jun 17 21:14:07 2002
@@ -12,6 +12,7 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/major.h>
+#include <linux/device.h>
 
 enum {
 /* These three have identical behaviour; use the second one if DOS fdisk gets
@@ -62,6 +63,7 @@
 	unsigned long nr_sects;
 	devfs_handle_t de;              /* primary (master) devfs entry  */
 	int number;                     /* stupid old code wastes space  */
+	struct device hd_driverfs_dev;  /* support driverfs hiearchy     */
 };
 
 #define GENHD_FL_REMOVABLE  1
@@ -80,6 +82,7 @@
 	struct block_device_operations *fops;
 
 	devfs_handle_t *de_arr;         /* one per physical disc */
+	struct device **driverfs_dev_arr;/* support driverfs hierarchy */
 	char *flags;                    /* one per physical disc */
 };
 
@@ -241,6 +244,7 @@
 
 extern void devfs_register_partitions (struct gendisk *dev, int minor,
 				       int unregister);
+extern void driverfs_remove_partitions (struct gendisk *hd, int minor);
 
 static inline unsigned int disk_index (kdev_t dev)
 {
diff -Naur linux-2.5.22.orig/kernel/ksyms.c linux-2.5.22-driverfs/kernel/ksyms.c
--- linux-2.5.22.orig/kernel/ksyms.c	Sun Jun 16 21:31:23 2002
+++ linux-2.5.22-driverfs/kernel/ksyms.c	Mon Jun 17 21:14:07 2002
@@ -335,6 +335,7 @@
 EXPORT_SYMBOL(set_device_ro);
 EXPORT_SYMBOL(bmap);
 EXPORT_SYMBOL(devfs_register_partitions);
+EXPORT_SYMBOL(driverfs_remove_partitions);
 EXPORT_SYMBOL(blkdev_open);
 EXPORT_SYMBOL(blkdev_get);
 EXPORT_SYMBOL(blkdev_put);

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH][RFC] Driverfs support for SCSI devices (updated)
@ 2002-06-19 14:13 Tom Coughlan
  0 siblings, 0 replies; 2+ messages in thread
From: Tom Coughlan @ 2002-06-19 14:13 UTC (permalink / raw)
  To: sullivan, linux-scsi

Hello Mike,

Just one point on your scanning of Inquiry page 83.  As you know,
the page may contain many Identifiers.  Each Identifier has an
Association field.  This field indicates whether the Identifier is
associated with the logical unit, or with a port that is used to
access the logical unit.  You should only use an identifier that is
associated with the logical unit.

I don't think may vendors are putting port identifiers in Page 83,
so this may not be a big deal, but I'm worried that if they do, the
FC port IDs will show up as Type 3 Identifiers, and we will
incorrectly select a port ID instead of the Logical Unit ID.

Thanks.

-- 
Tom Coughlan
Red Hat
978-692-3113 ext. 23209

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2002-06-19 14:13 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-06-19 14:13 [PATCH][RFC] Driverfs support for SCSI devices (updated) Tom Coughlan
  -- strict thread matches above, loose matches on Subject: below --
2002-06-17 23:16 [PATCH][RFC] Driverfs support for SCSI devices James Bottomley
2002-06-18 21:56 ` [PATCH][RFC] Driverfs support for SCSI devices (updated) sullivan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox