# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.851   -> 1.852  
#	drivers/usb/hpusbscsi.c	1.5     -> 1.6    
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/08/14	oliver@oenone.homelinux.org	1.852
# [PATCH] USB: hpusbscsi driver updates
# 
# --------------------------------------------
#
diff -Nru a/drivers/usb/hpusbscsi.c b/drivers/usb/hpusbscsi.c
--- a/drivers/usb/hpusbscsi.c	Wed Aug 14 23:17:35 2002
+++ b/drivers/usb/hpusbscsi.c	Wed Aug 14 23:17:35 2002
@@ -1,3 +1,51 @@
+/*
+ * hpusbscsi
+ * (C) Copyright 2001 Oliver Neukum 
+ * Sponsored by the Linux Usb Project
+ * Large parts based on or taken from code by John Fremlin and Matt Dharm
+ * 
+ * This driver is known to work with the following scanners (VID, PID)
+ *    (0x03f0, 0x0701)  HP 53xx 
+ *    (0x03f0, 0x0801)  HP 7400 
+ *    (0x0638, 0x026a)  Minolta Scan Dual II
+ *    (0x0686, 0x4004)  Minolta Elite II
+ * To load with full debugging load with "insmod hpusbscsi debug=2"
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Contributors:
+ *   Oliver Neukum
+ *   John Fremlin
+ *   Matt Dharm
+ *   .
+ *   .
+ *   Timothy Jedlicka <bonzo@lucent.com>
+ *
+ * History
+ *
+ * 22-Apr-2002
+ *
+ * - Added Elite II scanner - bonzo
+ * - Cleaned up the debug statements and made them optional at load time - bonzo
+ *
+ * 20020618
+ *
+ * - Confirm to stupid 2.4 rules on io_request_lock
+ *
+ */
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -16,12 +64,28 @@
 
 #include "hpusbscsi.h"
 
-#define DEBUG(x...) \
-	printk( KERN_DEBUG x )
-
 static char *states[]={"FREE", "BEGINNING", "WORKING", "ERROR", "WAIT", "PREMATURE"};
 
-#define TRACE_STATE printk(KERN_DEBUG"hpusbscsi->state = %s at line %d\n", states[hpusbscsi->state], __LINE__)
+/* DEBUG related parts */
+#define HPUSBSCSI_DEBUG
+
+#ifdef HPUSBSCSI_DEBUG
+#  define PDEBUG(level, fmt, args...) \
+          if (debug >= (level)) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , \
+                 ## args)
+#else
+#  define PDEBUG(level, fmt, args...) do {} while(0)
+#endif
+
+
+/* 0=no debug messages
+ * 1=everything but trace states
+ * 2=trace states
+ */
+static int debug; /* = 0 */
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug level: 0=none, 1=no trace states, 2=trace states");
 
 /* global variables */
 
@@ -54,7 +118,7 @@
 					      GFP_KERNEL);
 	if (new == NULL)
 		return NULL;
-	DEBUG ("Allocated memory\n");
+	PDEBUG (1, "Allocated memory");
 	memset (new, 0, sizeof (struct hpusbscsi));
 	spin_lock_init (&new->dataurb.lock);
 	spin_lock_init (&new->controlurb.lock);
@@ -167,7 +231,8 @@
 	int result;
 
 	INIT_LIST_HEAD (&hpusbscsi_devices);
-
+	PDEBUG(0, "driver loaded, DebugLvel=%d", debug);
+ 
 	if ((result = usb_register (&hpusbscsi_usb_driver)) < 0) {
 		printk (KERN_ERR "hpusbscsi: driver registration failed\n");
 		return -1;
@@ -210,6 +275,7 @@
 	/* What a hideous hack! */
 
 	char local_name[48];
+	spin_unlock_irq(&io_request_lock);
 
 
 	/* set up the name of our subdirectory under /proc/scsi/ */
@@ -218,6 +284,7 @@
 	/* FIXME: where is this freed ? */
 
 	if (!sht->proc_name) {
+		spin_lock_irq(&io_request_lock);
 		return 0;
 	}
 
@@ -238,6 +305,7 @@
 
 	if ( 0  >  usb_submit_urb(&desc->controlurb)) {
 		kfree(sht->proc_name);
+		spin_lock_irq(&io_request_lock);
 		return 0;
 	}
 
@@ -246,10 +314,11 @@
 	if (desc->host == NULL) {
 		kfree (sht->proc_name);
 		usb_unlink_urb(&desc->controlurb);
+		spin_lock_irq(&io_request_lock);
 		return 0;
 	}
 	desc->host->hostdata[0] = (unsigned long) desc;
-
+	spin_lock_irq(&io_request_lock);
 
 	return 1;
 }
@@ -297,7 +366,7 @@
 	}
 
 
-	TRACE_STATE;
+	PDEBUG(2, "state= %s", states[hpusbscsi->state]);
 	if (hpusbscsi->state != HP_STATE_FREE) {
 		printk(KERN_CRIT"hpusbscsi - Ouch: queueing violation!\n");
 		return 1; /* This must not happen */
@@ -307,7 +376,7 @@
         memset(srb->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
 
 	hpusbscsi->state = HP_STATE_BEGINNING;
-	TRACE_STATE;
+	PDEBUG(2, "state= %s", states[hpusbscsi->state]);
 
 	/* We prepare the urb for writing out the scsi command */
 	FILL_BULK_URB(
@@ -325,7 +394,7 @@
 	res = usb_submit_urb(&hpusbscsi->dataurb);
 	if (res) {
 		hpusbscsi->state = HP_STATE_FREE;
-		TRACE_STATE;
+		PDEBUG(2, "state= %s", states[hpusbscsi->state]);
 		if (callback) {
 			srb->result = DID_ERROR;
 			callback(srb);
@@ -341,9 +410,9 @@
 {
 	struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]);
 
-	printk(KERN_DEBUG"SCSI reset requested.\n");
+	PDEBUG(1, "SCSI reset requested");
 	//usb_reset_device(hpusbscsi->dev);
-	//printk(KERN_DEBUG"SCSI reset completed.\n");
+	//PDEBUG(1, "SCSI reset completed");
 	hpusbscsi->state = HP_STATE_FREE;
 
 	return 0;
@@ -352,10 +421,13 @@
 static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb)
 {
 	struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]);
-	printk(KERN_DEBUG"Request is canceled.\n");
+	PDEBUG(1, "Request is canceled");
 
+	spin_unlock_irq(&io_request_lock);
 	usb_unlink_urb(&hpusbscsi->dataurb);
 	hpusbscsi->state = HP_STATE_FREE;
+	
+	spin_lock_irq(&io_request_lock);
 
 	return SCSI_ABORT_PENDING;
 }
@@ -376,7 +448,7 @@
 	struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
 	u8 scsi_state;
 
-DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte);
+	PDEBUG(1, "Getting status byte %d",hpusbscsi->scsi_state_byte);
 	if(u->status < 0) {
                 if (hpusbscsi->state != HP_STATE_FREE)
                         handle_usb_error(hpusbscsi);
@@ -402,24 +474,24 @@
 		/* we do a callback to the scsi layer if and only if all data has been transfered */
 		hpusbscsi->scallback(hpusbscsi->srb);
 
-	TRACE_STATE;
+	PDEBUG(2, "state= %s", states[hpusbscsi->state]);
 	switch (hpusbscsi->state) {
 	case HP_STATE_WAIT:
 		hpusbscsi->state = HP_STATE_FREE;
-	TRACE_STATE;
+	PDEBUG(2, "state= %s", states[hpusbscsi->state]);
 		break;
 	case HP_STATE_WORKING:
 	case HP_STATE_BEGINNING:
 		hpusbscsi->state = HP_STATE_PREMATURE;
-	TRACE_STATE;
+	PDEBUG(2, "state= %s", states[hpusbscsi->state]);
 		break;
 	case HP_STATE_ERROR:
 		break;
 	default:
 		printk(KERN_ERR"hpusbscsi: Unexpected status report.\n");
-	TRACE_STATE;
+	PDEBUG(2, "state= %s", states[hpusbscsi->state]);
 		hpusbscsi->state = HP_STATE_FREE;
-	TRACE_STATE;
+	PDEBUG(2, "state= %s", states[hpusbscsi->state]);
 		break;
 	}
 }
@@ -431,15 +503,15 @@
 		handle_usb_error(hpusbscsi);
 		return;
         }
-	TRACE_STATE;
+	PDEBUG(2, "state= %s", states[hpusbscsi->state]);
 	if (hpusbscsi->state != HP_STATE_PREMATURE) {
-	        TRACE_STATE;
+	        PDEBUG(2, "state= %s", states[hpusbscsi->state]);
 		hpusbscsi->state = HP_STATE_WAIT;
 	} else {
 		if (hpusbscsi->scallback != NULL)
 			hpusbscsi->scallback(hpusbscsi->srb);
 		hpusbscsi->state = HP_STATE_FREE;
-	TRACE_STATE;
+	PDEBUG(2, "state= %s", states[hpusbscsi->state]);
 	}
 }
 
@@ -450,7 +522,7 @@
         usb_urb_callback callback;
         int res;
 
-        DEBUG("Going through scatter/gather\n");
+        PDEBUG(1, "Going through scatter/gather"); // bonzo - this gets hit a lot - maybe make it a 2
         if (u->status < 0) {
                 handle_usb_error(hpusbscsi);
                 return;
@@ -461,10 +533,10 @@
         else
                 callback = simple_done;
 
-	TRACE_STATE;
+	PDEBUG(2, "state= %s", states[hpusbscsi->state]);
         if (hpusbscsi->state != HP_STATE_PREMATURE)
 		hpusbscsi->state = HP_STATE_WORKING;
-	TRACE_STATE;
+	PDEBUG(2, "state= %s", states[hpusbscsi->state]);
 
         FILL_BULK_URB(
                 u,
@@ -479,7 +551,7 @@
         res = usb_submit_urb(u);
         if (res)
         	handle_usb_error(hpusbscsi);
-	TRACE_STATE;
+	PDEBUG(2, "state= %s", states[hpusbscsi->state]);
 }
 
 static void simple_done (struct urb *u)
@@ -490,8 +562,8 @@
                 handle_usb_error(hpusbscsi);
                 return;
         }
-        DEBUG("Data transfer done\n");
-	TRACE_STATE;
+	PDEBUG(1, "Data transfer done");
+	PDEBUG(2, "state= %s", states[hpusbscsi->state]);
 	if (hpusbscsi->state != HP_STATE_PREMATURE) {
 		if (u->status < 0) {
 			handle_usb_error(hpusbscsi);
@@ -501,7 +573,7 @@
 			} else {
 				issue_request_sense(hpusbscsi);
 			}
-		TRACE_STATE;
+		PDEBUG(2, "state= %s", states[hpusbscsi->state]);
 		}
 	} else {
 		if (hpusbscsi->scallback != NULL)
@@ -535,10 +607,10 @@
                 handle_usb_error(hpusbscsi);
 		return;
         }
-	TRACE_STATE;
+	PDEBUG(2, "state= %s", states[hpusbscsi->state]);
 	if (hpusbscsi->state != HP_STATE_PREMATURE) {
 		hpusbscsi->state = HP_STATE_WORKING;
-	TRACE_STATE;
+	PDEBUG(2, "state= %s", states[hpusbscsi->state]);
 	}
 }
 
