patch-2.4.20 linux-2.4.20/drivers/usb/hpusbscsi.c
Next file: linux-2.4.20/drivers/usb/hub.c
Previous file: linux-2.4.20/drivers/usb/hid.h
Back to the patch index
Back to the overall index
- Lines: 389
- Date:
Thu Nov 28 15:53:14 2002
- Orig file:
linux-2.4.19/drivers/usb/hpusbscsi.c
- Orig date:
Fri Aug 2 17:39:44 2002
diff -urN linux-2.4.19/drivers/usb/hpusbscsi.c linux-2.4.20/drivers/usb/hpusbscsi.c
@@ -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);
@@ -136,14 +200,26 @@
static void
hpusbscsi_usb_disconnect (struct usb_device *dev, void *ptr)
{
- usb_unlink_urb(&(((struct hpusbscsi *) ptr)->controlurb));
- ((struct hpusbscsi *) ptr)->dev = NULL;
+ struct hpusbscsi *hp = (struct hpusbscsi *)ptr;
+
+ usb_unlink_urb(&hp->controlurb);
+ usb_unlink_urb(&hp->dataurb);
+
+ spin_lock_irq(&io_request_lock);
+ hp->dev = NULL;
+ spin_unlock_irq(&io_request_lock);
}
static struct usb_device_id hpusbscsi_usb_ids[] = {
{USB_DEVICE (0x03f0, 0x0701)}, /* HP 53xx */
{USB_DEVICE (0x03f0, 0x0801)}, /* HP 7400 */
+ {USB_DEVICE (0x0638, 0x0268)}, /*iVina 1200U */
{USB_DEVICE (0x0638, 0x026a)}, /*Scan Dual II */
+ {USB_DEVICE (0x0638, 0x0A13)}, /*Avision AV600U */
+ {USB_DEVICE (0x0638, 0x0A16)}, /*Avision DS610CU Scancopier */
+ {USB_DEVICE (0x0638, 0x0A18)}, /*Avision AV600U Plus */
+ {USB_DEVICE (0x0638, 0x0A23)}, /*Avision AV220 */
+ {USB_DEVICE (0x0638, 0x0A24)}, /*Avision AV210 */
{USB_DEVICE (0x0686, 0x4004)}, /*Minolta Elite II */
{} /* Terminating entry */
};
@@ -167,7 +243,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 +287,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 +296,7 @@
/* FIXME: where is this freed ? */
if (!sht->proc_name) {
+ spin_lock_irq(&io_request_lock);
return 0;
}
@@ -238,6 +317,7 @@
if ( 0 > usb_submit_urb(&desc->controlurb)) {
kfree(sht->proc_name);
+ spin_lock_irq(&io_request_lock);
return 0;
}
@@ -246,10 +326,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;
}
@@ -260,15 +341,13 @@
usb_urb_callback usb_callback;
int res;
- hpusbscsi->use_count++;
+ spin_unlock_irq(&io_request_lock);
/* we don't answer for anything but our single device on any faked host controller */
if ( srb->device->lun || srb->device->id || srb->device->channel ) {
- if (callback) {
- srb->result = DID_BAD_TARGET;
- callback(srb);
- }
- goto out;
+ srb->result = DID_BAD_TARGET;
+ callback(srb);
+ goto out;
}
/* Now we need to decide which callback to give to the urb we send the command with */
@@ -297,7 +376,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 +386,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(
@@ -321,19 +400,24 @@
);
hpusbscsi->scallback = callback;
hpusbscsi->srb = srb;
+
+ if (hpusbscsi->dev == NULL) {
+ srb->result = DID_ERROR;
+ callback(srb);
+ goto out;
+ }
res = usb_submit_urb(&hpusbscsi->dataurb);
if (res) {
hpusbscsi->state = HP_STATE_FREE;
- TRACE_STATE;
- if (callback) {
- srb->result = DID_ERROR;
- callback(srb);
- }
+ PDEBUG(2, "state= %s", states[hpusbscsi->state]);
+ srb->result = DID_ERROR;
+ callback(srb);
+
}
out:
- hpusbscsi->use_count--;
+ spin_lock_irq(&io_request_lock);
return 0;
}
@@ -341,9 +425,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,11 +436,14 @@
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 +463,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 +489,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 +518,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 +537,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 +548,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 +566,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 +577,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 +588,7 @@
} else {
issue_request_sense(hpusbscsi);
}
- TRACE_STATE;
+ PDEBUG(2, "state= %s", states[hpusbscsi->state]);
}
} else {
if (hpusbscsi->scallback != NULL)
@@ -535,10 +622,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]);
}
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)