patch-2.4.0-test9 linux/drivers/usb/storage/usb.c

Next file: linux/drivers/usb/storage/usb.h
Previous file: linux/drivers/usb/storage/transport.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test8/linux/drivers/usb/storage/usb.c linux/drivers/usb/storage/usb.c
@@ -1,6 +1,6 @@
 /* Driver for USB Mass Storage compliant devices
  *
- * $Id: usb.c,v 1.33 2000/08/25 00:13:51 mdharm Exp $
+ * $Id: usb.c,v 1.46 2000/09/25 23:25:12 mdharm Exp $
  *
  * Current development and maintenance by:
  *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -49,6 +49,7 @@
 #include "transport.h"
 #include "protocol.h"
 #include "debug.h"
+#include "initializers.h"
 #ifdef CONFIG_USB_STORAGE_HP8200e
 #include "shuttle_usbat.h"
 #endif
@@ -94,7 +95,7 @@
 
 static void * storage_probe(struct usb_device *dev, unsigned int ifnum);
 static void storage_disconnect(struct usb_device *dev, void *ptr);
-static struct usb_driver storage_driver = {
+struct usb_driver usb_storage_driver = {
 	name:		"usb-storage",
 	probe:		storage_probe,
 	disconnect:	storage_disconnect,
@@ -206,7 +207,7 @@
 			 */
 			if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) {
 				US_DEBUGP("UNKNOWN data direction\n");
-				us->srb->result = DID_ERROR;
+				us->srb->result = DID_ERROR << 16;
 				set_current_state(TASK_INTERRUPTIBLE);
 				us->srb->scsi_done(us->srb);
 				us->srb = NULL;
@@ -242,7 +243,7 @@
 			/* handle those devices which can't do a START_STOP */
 			if ((us->srb->cmnd[0] == START_STOP) &&
 			    (us->flags & US_FL_START_STOP)) {
-				us->srb->result = GOOD;
+				us->srb->result = GOOD << 1;
 
 				set_current_state(TASK_INTERRUPTIBLE);
 				us->srb->scsi_done(us->srb);
@@ -264,12 +265,12 @@
 					memcpy(us->srb->request_buffer, 
 					       usb_stor_sense_notready, 
 					       sizeof(usb_stor_sense_notready));
-					us->srb->result = GOOD;
+					us->srb->result = GOOD << 1;
 				} else {
 					memcpy(us->srb->sense_buffer, 
 					       usb_stor_sense_notready, 
 					       sizeof(usb_stor_sense_notready));
-					us->srb->result = CHECK_CONDITION;
+					us->srb->result = CHECK_CONDITION << 1;
 				}
 			} else { /* !us->pusb_dev */
 				/* we've got a command, let's do it! */
@@ -328,46 +329,34 @@
  * restriction. However, if the flag is not present, then you
  * are free to use as many characters as you like.
  */
-
-int euscsi_init(struct us_data *us)
-{
-	unsigned char bar = 0x1;
-	int result;
-
-	US_DEBUGP("Attempting to init eUSCSI bridge...\n");
-	result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
-			0x0C, USB_RECIP_INTERFACE | USB_TYPE_VENDOR,
-			0x01, 0x0, &bar, 0x1, 5*HZ);
-	US_DEBUGP("-- result is %d\n", result);
-	US_DEBUGP("-- bar afterwards is %d\n", bar);
-}
-
 static struct us_unusual_dev us_unusual_dev_list[] = {
 
+	{ 0x03ee, 0x0000, 0x0000, 0x0245, 
+		"Mitsumi",
+		"CD-R/RW Drive",
+		US_SC_8020, US_PR_CBI, NULL, 0}, 
+
 	{ 0x03f0, 0x0107, 0x0200, 0x0200, 
 		"HP",
 		"CD-Writer+",
-		US_SC_8070, US_PR_CB, NULL, 
-		0}, 
+		US_SC_8070, US_PR_CB, NULL, 0}, 
 
 #ifdef CONFIG_USB_STORAGE_HP8200e
 	{ 0x03f0, 0x0207, 0x0001, 0x0001, 
 		"HP",
 		"CD-Writer+ 8200e",
-		US_SC_8070, US_PR_SCM_ATAPI, init_8200e,
-		US_FL_SINGLE_LUN}, 
+		US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0}, 
 #endif
 
 	{ 0x04e6, 0x0001, 0x0200, 0x0200, 
 		"Matshita",
 		"LS-120",
-		US_SC_8020, US_PR_CB, NULL, 
-		US_FL_SINGLE_LUN},
+		US_SC_8020, US_PR_CB, NULL, 0},
 
 	{ 0x04e6, 0x0002, 0x0100, 0x0100, 
 		"Shuttle",
 		"eUSCSI Bridge",
-		US_SC_SCSI, US_PR_BULK, euscsi_init, 
+		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, 
 		US_FL_SCM_MULT_TARG }, 
 
 #ifdef CONFIG_USB_STORAGE_SDDR09
@@ -392,39 +381,42 @@
 		US_SC_SCSI, US_PR_CB, NULL, 
 		US_FL_SINGLE_LUN}, 
 
+	{ 0x04e6, 0x0007, 0x0100, 0x0200, 
+		"Sony",
+		"Hifd",
+		US_SC_SCSI, US_PR_CB, NULL, 
+		US_FL_SINGLE_LUN}, 
+
 	{ 0x04e6, 0x0009, 0x0200, 0x0200, 
 		"Shuttle",
-		"ATA/ATAPI Bridge",
-		US_SC_8020, US_PR_CB, NULL, 
-		US_FL_SINGLE_LUN},
+		"eUSB ATA/ATAPI Adapter",
+		US_SC_8020, US_PR_CB, NULL, 0},
 
-	{ 0x04e6, 0x000A, 0x0200, 0x0200, 
+	{ 0x04e6, 0x000a, 0x0200, 0x0200, 
 		"Shuttle",
-		"Compact Flash Reader",
-		US_SC_8020, US_PR_CB, NULL, 
-		US_FL_SINGLE_LUN},
+		"eUSB CompactFlash Adapter",
+		US_SC_8020, US_PR_CB, NULL, 0},
 
 	{ 0x04e6, 0x000B, 0x0100, 0x0100, 
 		"Shuttle",
 		"eUSCSI Bridge",
-		US_SC_SCSI, US_PR_BULK, euscsi_init, 
+		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, 
 		US_FL_SCM_MULT_TARG }, 
 
 	{ 0x04e6, 0x000C, 0x0100, 0x0100, 
 		"Shuttle",
 		"eUSCSI Bridge",
-		US_SC_SCSI, US_PR_BULK, euscsi_init, 
+		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, 
 		US_FL_SCM_MULT_TARG }, 
 
 	{ 0x04e6, 0x0101, 0x0200, 0x0200, 
 		"Shuttle",
 		"CD-RW Device",
-		US_SC_8020, US_PR_CB, NULL, 
-		US_FL_SINGLE_LUN},
+		US_SC_8020, US_PR_CB, NULL, 0},
 
-	{ 0x054c, 0x0010, 0x0210, 0x0210, 
+	{ 0x054c, 0x0010, 0x0106, 0x0210, 
 		"Sony",
-		"DSC-S30/S70", 
+		"DSC-S30/S70/505V/F505", 
 		US_SC_SCSI, US_PR_CB, NULL,
 		US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE },
 
@@ -449,26 +441,35 @@
 	{ 0x059f, 0xa601, 0x0200, 0x0200, 
 		"LaCie",
 		"USB Hard Disk",
-		US_SC_RBC, US_PR_CB, NULL,
-		0 }, 
+		US_SC_RBC, US_PR_CB, NULL, 0 }, 
 
 	{ 0x05ab, 0x0031, 0x0100, 0x0100, 
 		"In-System",
-		"USB/IDE Bridge",
-		US_SC_8070, US_PR_BULK, NULL,
-		0 }, 
+		"USB/IDE Bridge (ATAPI ONLY!)",
+		US_SC_8070, US_PR_BULK, NULL, 0 }, 
 
-	{ 0x0693, 0x0005, 0x0100, 0x0100,
-		"Hagiwara",
-		"Flashgate",
-		US_SC_SCSI, US_PR_BULK, NULL,
-		0 }, 
+	{ 0x0644, 0x0000, 0x0100, 0x0100, 
+		"TEAC",
+		"Floppy Drive",
+		US_SC_UFI, US_PR_CB, NULL, 0 }, 
+
+#ifdef CONFIG_USB_STORAGE_SDDR09
+	{ 0x066b, 0x0105, 0x0100, 0x0100, 
+		"Olympus",
+		"Camedia MAUSB-2",
+		US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
+		US_FL_SINGLE_LUN | US_FL_START_STOP },
+#endif
 
 	{ 0x0693, 0x0002, 0x0100, 0x0100, 
 		"Hagiwara",
 		"FlashGate SmartMedia",
-		US_SC_SCSI, US_PR_BULK, NULL,
-		0 },
+		US_SC_SCSI, US_PR_BULK, NULL, 0 },
+
+	{ 0x0693, 0x0005, 0x0100, 0x0100,
+		"Hagiwara",
+		"Flashgate",
+		US_SC_SCSI, US_PR_BULK, NULL, 0 }, 
 
 	{ 0x0781, 0x0001, 0x0200, 0x0200, 
 		"Sandisk",
@@ -493,20 +494,20 @@
 	{ 0x07af, 0x0004, 0x0100, 0x0100, 
 		"Microtech",
 		"USB-SCSI-DB25",
-		US_SC_SCSI, US_PR_BULK, euscsi_init,
+		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
 		US_FL_SCM_MULT_TARG }, 
 
 #ifdef CONFIG_USB_STORAGE_FREECOM
         { 0x07ab, 0xfc01, 0x0921, 0x0921,
                 "Freecom",
                 "USB-IDE",
-                US_SC_8070, US_PR_FREECOM, NULL, US_FL_SINGLE_LUN },
+                US_SC_QIC, US_PR_FREECOM, freecom_init, 0},
 #endif
 
 	{ 0x07af, 0x0005, 0x0100, 0x0100, 
 		"Microtech",
 		"USB-SCSI-HD50",
-		US_SC_SCSI, US_PR_BULK, euscsi_init,
+		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
 		US_FL_SCM_MULT_TARG }, 
 
 #ifdef CONFIG_USB_STORAGE_DPCM
@@ -613,7 +614,9 @@
 	unsigned int flags;
 	struct us_unusual_dev *unusual_dev;
 	struct us_data *ss = NULL;
+#ifdef CONFIG_USB_STORAGE_SDDR09
 	int result;
+#endif
 
 	/* these are temporary copies -- we test on these, then put them
 	 * in the us-data structure 
@@ -716,6 +719,7 @@
 	}
 
 	/* At this point, we're committed to using the device */
+	usb_inc_dev_use(dev);
 
 	/* clear the GUID and fetch the strings */
 	GUID_CLEAR(guid);
@@ -740,9 +744,6 @@
 			  dev->descriptor.idProduct, "0");
 	}
 
-	/* lock access to the data structures */
-	down(&us_list_semaphore);
-
 	/*
 	 * Now check if we have seen this GUID before
 	 * We're looking for a device with a matching GUID that isn't
@@ -775,8 +776,14 @@
 		if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss))
 			return NULL;
 
-                /* Re-Initialize the device if it needs it */
+		/* allocate the URB we're going to use */
+		ss->current_urb = usb_alloc_urb(0);
+		if (!ss->current_urb) {
+			kfree(ss);
+			return NULL;
+		}
 
+                /* Re-Initialize the device if it needs it */
 		if (unusual_dev && unusual_dev->initFunction)
 			(unusual_dev->initFunction)(ss);
 
@@ -787,7 +794,6 @@
 		if ((ss = (struct us_data *)kmalloc(sizeof(struct us_data), 
 						    GFP_KERNEL)) == NULL) {
 			printk(KERN_WARNING USB_STORAGE "Out of memory\n");
-			up(&us_list_semaphore);
 			return NULL;
 		}
 		memset(ss, 0, sizeof(struct us_data));
@@ -892,7 +898,7 @@
 			ss->transport_name = "EUSB/SDDR09";
 			ss->transport = sddr09_transport;
 			ss->transport_reset = usb_stor_CB_reset;
-			ss->max_lun = 1;
+			ss->max_lun = 0;
 			break;
 #endif
 
@@ -916,7 +922,6 @@
 			
 		default:
 			ss->transport_name = "Unknown";
-			up(&us_list_semaphore);
 			kfree(ss->current_urb);
 			kfree(ss);
 			return NULL;
@@ -937,16 +942,19 @@
 		case US_SC_8020:
 			ss->protocol_name = "8020i";
 			ss->proto_handler = usb_stor_ATAPI_command;
+			ss->max_lun = 0;
 			break;
 
 		case US_SC_QIC:
 			ss->protocol_name = "QIC-157";
 			ss->proto_handler = usb_stor_qic157_command;
+			ss->max_lun = 0;
 			break;
 
 		case US_SC_8070:
 			ss->protocol_name = "8070i";
 			ss->proto_handler = usb_stor_ATAPI_command;
+			ss->max_lun = 0;
 			break;
 
 		case US_SC_SCSI:
@@ -961,7 +969,6 @@
 
 		default:
 			ss->protocol_name = "Unknown";
-			up(&us_list_semaphore);
 			kfree(ss->current_urb);
 			kfree(ss);
 			return NULL;
@@ -994,7 +1001,7 @@
 		/* Just before we start our control thread, initialize
 		 * the device if it needs initialization */
 		if (unusual_dev && unusual_dev->initFunction)
-			(unusual_dev->initFunction)(ss);
+			unusual_dev->initFunction(ss);
 		
 		/* start up our control thread */
 		ss->pid = kernel_thread(usb_stor_control_thread, ss,
@@ -1014,13 +1021,16 @@
 		ss->htmplt.module = THIS_MODULE;
 		scsi_register_module(MODULE_SCSI_HA, &(ss->htmplt));
 		
+		/* lock access to the data structures */
+		down(&us_list_semaphore);
+
 		/* put us in the list */
 		ss->next = us_list;
 		us_list = ss;
-	}
 
-	/* release the data structure lock */
-	up(&us_list_semaphore);
+		/* release the data structure lock */
+		up(&us_list_semaphore);
+	}
 
 	printk(KERN_DEBUG 
 	       "WARNING: USB Mass Storage data integrity not assured\n");
@@ -1051,18 +1061,26 @@
 	/* release the IRQ, if we have one */
 	down(&(ss->irq_urb_sem));
 	if (ss->irq_urb) {
-		US_DEBUGP("-- releasing irq handle\n");
+		US_DEBUGP("-- releasing irq URB\n");
 		result = usb_unlink_urb(ss->irq_urb);
-		ss->irq_urb = NULL;
 		US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
 		usb_free_urb(ss->irq_urb);
+		ss->irq_urb = NULL;
 	}
 	up(&(ss->irq_urb_sem));
 
+	/* free up the main URB for this device */
+	US_DEBUGP("-- releasing main URB\n");
+	result = usb_unlink_urb(ss->current_urb);
+	US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
+	usb_free_urb(ss->current_urb);
+	ss->current_urb = NULL;
+
 	/* mark the device as gone */
+	usb_dec_dev_use(ss->pusb_dev);
 	ss->pusb_dev = NULL;
 
-	/* lock access to the device data structure */
+	/* unlock access to the device data structure */
 	up(&(ss->dev_semaphore));
 }
 
@@ -1078,7 +1096,7 @@
 	my_host_number = 0;
 
 	/* register the driver, return -1 if error */
-	if (usb_register(&storage_driver) < 0)
+	if (usb_register(&usb_storage_driver) < 0)
 		return -1;
 
 	/* we're all set */
@@ -1096,46 +1114,47 @@
 	 * This eliminates races with probes and disconnects 
 	 */
 	US_DEBUGP("-- calling usb_deregister()\n");
-	usb_deregister(&storage_driver) ;
+	usb_deregister(&usb_storage_driver) ;
 	
-	/* lock access to the data structures */
-	down(&us_list_semaphore);
-
 	/* While there are still virtual hosts, unregister them
-	 *
-	 * Note that the us_release() routine will destroy the local data
-	 * structure.  So we have to peel these off the top of the list
-	 * and keep updating the head pointer as we go.
+	 * Note that it's important to do this completely before removing
+	 * the structures because of possible races with the /proc
+	 * interface
+	 */
+	for (next = us_list; next; next = next->next) {
+		US_DEBUGP("-- calling scsi_unregister_module()\n");
+		scsi_unregister_module(MODULE_SCSI_HA, &(next->htmplt));
+	}
+	
+	/* While there are still structures, free them.  Note that we are
+	 * now race-free, since these structures can no longer be accessed
+	 * from either the SCSI command layer or the /proc interface
 	 */
 	while (us_list) {
 		/* keep track of where the next one is */
 		next = us_list->next;
 
-		US_DEBUGP("-- calling scsi_unregister_module()\n");
-		scsi_unregister_module(MODULE_SCSI_HA, &(us_list->htmplt));
-
-                /* Now that scsi_unregister_module is done with the host
-                 * template, we can free the us_data structure (the host
-                 * template is inline in this structure). */
-
 		/* If there's extra data in the us_data structure then
 		 * free that first */
-
 		if (us_list->extra) {
-			if (us_list->extra_destructor)
-				(*us_list->extra_destructor)(
-					us_list->extra);
+			/* call the destructor routine, if it exists */
+			if (us_list->extra_destructor) {
+				US_DEBUGP("-- calling extra_destructor()\n");
+				us_list->extra_destructor(us_list->extra);
+			}
+
+			/* destroy the extra data */
+			US_DEBUGP("-- freeing the data structure\n");
 			kfree(us_list->extra);
 		}
+
+		/* free the structure itself */
                 kfree (us_list);
 
 		/* advance the list pointer */
 		us_list = next;
 	}
-	
-	/* unlock the data structures */
-	up(&us_list_semaphore);
 }
 
-module_init(usb_stor_init) ;
-module_exit(usb_stor_exit) ;
+module_init(usb_stor_init);
+module_exit(usb_stor_exit);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)