Commit f7148255 authored by Oliver Neukum's avatar Oliver Neukum Committed by Greg Kroah-Hartman

USB hpusbscsi driver

Port changes from 2.4:
  We do request_sense ourselves to comply with
  the scanner command set
parent c32692c6
...@@ -129,6 +129,9 @@ hpusbscsi_usb_probe (struct usb_device *dev, unsigned int interface, ...@@ -129,6 +129,9 @@ hpusbscsi_usb_probe (struct usb_device *dev, unsigned int interface,
if (scsi_register_host(&new->ctempl)) if (scsi_register_host(&new->ctempl))
goto err_out; goto err_out;
new->sense_command[0] = REQUEST_SENSE;
new->sense_command[4] = HPUSBSCSI_SENSE_LENGTH;
/* adding to list for module unload */ /* adding to list for module unload */
list_add (&hpusbscsi_devices, &new->lh); list_add (&hpusbscsi_devices, &new->lh);
...@@ -379,6 +382,7 @@ static void handle_usb_error (struct hpusbscsi *hpusbscsi) ...@@ -379,6 +382,7 @@ static void handle_usb_error (struct hpusbscsi *hpusbscsi)
static void control_interrupt_callback (struct urb *u) static void control_interrupt_callback (struct urb *u)
{ {
struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context; struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
u8 scsi_state;
DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte); DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte);
if(unlikely(u->status < 0)) { if(unlikely(u->status < 0)) {
...@@ -386,10 +390,23 @@ DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte); ...@@ -386,10 +390,23 @@ DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte);
handle_usb_error(hpusbscsi); handle_usb_error(hpusbscsi);
return; return;
} }
scsi_state = hpusbscsi->scsi_state_byte;
if (hpusbscsi->state != HP_STATE_ERROR) {
hpusbscsi->srb->result &= SCSI_ERR_MASK; hpusbscsi->srb->result &= SCSI_ERR_MASK;
hpusbscsi->srb->result |= hpusbscsi->scsi_state_byte; hpusbscsi->srb->result |= scsi_state;
}
if (hpusbscsi->scallback != NULL && hpusbscsi->state == HP_STATE_WAIT) if (scsi_state == CHECK_CONDITION << 1) {
if (hpusbscsi->state == HP_STATE_WAIT) {
issue_request_sense(hpusbscsi);
} else {
/* we request sense after an eventual data transfer */
hpusbscsi->state = HP_STATE_ERROR;
}
}
if (hpusbscsi->scallback != NULL && hpusbscsi->state == HP_STATE_WAIT && scsi_state != CHECK_CONDITION <<1 )
/* we do a callback to the scsi layer if and only if all data has been transfered */ /* we do a callback to the scsi layer if and only if all data has been transfered */
hpusbscsi->scallback(hpusbscsi->srb); hpusbscsi->scallback(hpusbscsi->srb);
...@@ -404,6 +421,8 @@ DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte); ...@@ -404,6 +421,8 @@ DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte);
hpusbscsi->state = HP_STATE_PREMATURE; hpusbscsi->state = HP_STATE_PREMATURE;
TRACE_STATE; TRACE_STATE;
break; break;
case HP_STATE_ERROR:
break;
default: default:
printk(KERN_ERR"hpusbscsi: Unexpected status report.\n"); printk(KERN_ERR"hpusbscsi: Unexpected status report.\n");
TRACE_STATE; TRACE_STATE;
...@@ -432,32 +451,6 @@ static void simple_command_callback(struct urb *u) ...@@ -432,32 +451,6 @@ static void simple_command_callback(struct urb *u)
} }
} }
static void request_sense_callback (struct urb *u)
{
struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
if (unlikely(u->status<0)) {
handle_usb_error(hpusbscsi);
return;
}
FILL_BULK_URB(
u,
hpusbscsi->dev,
hpusbscsi->current_data_pipe,
hpusbscsi->srb->sense_buffer,
SCSI_SENSE_BUFFERSIZE,
simple_done,
hpusbscsi
);
if (unlikely(0 > usb_submit_urb(u, GFP_ATOMIC))) {
handle_usb_error(hpusbscsi);
return;
}
hpusbscsi->state = HP_STATE_WORKING;
}
static void scatter_gather_callback(struct urb *u) static void scatter_gather_callback(struct urb *u)
{ {
struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context; struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
...@@ -494,7 +487,7 @@ static void scatter_gather_callback(struct urb *u) ...@@ -494,7 +487,7 @@ static void scatter_gather_callback(struct urb *u)
res = usb_submit_urb(u, GFP_ATOMIC); res = usb_submit_urb(u, GFP_ATOMIC);
if (unlikely(res)) if (unlikely(res))
hpusbscsi->state = HP_STATE_ERROR; handle_usb_error(hpusbscsi);
TRACE_STATE; TRACE_STATE;
} }
...@@ -509,11 +502,15 @@ static void simple_done (struct urb *u) ...@@ -509,11 +502,15 @@ static void simple_done (struct urb *u)
DEBUG("Data transfer done\n"); DEBUG("Data transfer done\n");
TRACE_STATE; TRACE_STATE;
if (hpusbscsi->state != HP_STATE_PREMATURE) { if (hpusbscsi->state != HP_STATE_PREMATURE) {
if (unlikely(u->status < 0)) if (unlikely(u->status < 0)) {
hpusbscsi->state = HP_STATE_ERROR; handle_usb_error(hpusbscsi);
else } else {
if (hpusbscsi->state != HP_STATE_ERROR) {
hpusbscsi->state = HP_STATE_WAIT; hpusbscsi->state = HP_STATE_WAIT;
TRACE_STATE; } else {
issue_request_sense(hpusbscsi);
}
}
} else { } else {
if (likely(hpusbscsi->scallback != NULL)) if (likely(hpusbscsi->scallback != NULL))
hpusbscsi->scallback(hpusbscsi->srb); hpusbscsi->scallback(hpusbscsi->srb);
...@@ -550,12 +547,52 @@ static void simple_payload_callback (struct urb *u) ...@@ -550,12 +547,52 @@ static void simple_payload_callback (struct urb *u)
if (hpusbscsi->state != HP_STATE_PREMATURE) { if (hpusbscsi->state != HP_STATE_PREMATURE) {
hpusbscsi->state = HP_STATE_WORKING; hpusbscsi->state = HP_STATE_WORKING;
TRACE_STATE; TRACE_STATE;
} else {
if (likely(hpusbscsi->scallback != NULL))
hpusbscsi->scallback(hpusbscsi->srb);
hpusbscsi->state = HP_STATE_FREE;
TRACE_STATE;
} }
} }
static void request_sense_callback (struct urb *u)
{
struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
if (u->status<0) {
handle_usb_error(hpusbscsi);
return;
}
FILL_BULK_URB(
u,
hpusbscsi->dev,
hpusbscsi->current_data_pipe,
hpusbscsi->srb->sense_buffer,
SCSI_SENSE_BUFFERSIZE,
simple_done,
hpusbscsi
);
if (0 > usb_submit_urb(u, GFP_ATOMIC)) {
handle_usb_error(hpusbscsi);
return;
}
if (hpusbscsi->state != HP_STATE_PREMATURE && hpusbscsi->state != HP_STATE_ERROR)
hpusbscsi->state = HP_STATE_WORKING;
}
static void issue_request_sense (struct hpusbscsi *hpusbscsi)
{
FILL_BULK_URB(
hpusbscsi->dataurb,
hpusbscsi->dev,
usb_sndbulkpipe(hpusbscsi->dev, hpusbscsi->ep_out),
&hpusbscsi->sense_command,
SENSE_COMMAND_SIZE,
request_sense_callback,
hpusbscsi
);
hpusbscsi->current_data_pipe = usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in);
if (0 > usb_submit_urb(hpusbscsi->dataurb, GFP_ATOMIC)) {
handle_usb_error(hpusbscsi);
}
}
...@@ -4,9 +4,14 @@ ...@@ -4,9 +4,14 @@
/* large parts based on or taken from code by John Fremlin and Matt Dharm */ /* large parts based on or taken from code by John Fremlin and Matt Dharm */
/* this file is licensed under the GPL */ /* this file is licensed under the GPL */
/* A big thanks to Jose for untiring testing */
typedef void (*usb_urb_callback) (struct urb *); typedef void (*usb_urb_callback) (struct urb *);
typedef void (*scsi_callback)(Scsi_Cmnd *); typedef void (*scsi_callback)(Scsi_Cmnd *);
#define SENSE_COMMAND_SIZE 6
#define HPUSBSCSI_SENSE_LENGTH 0x16
struct hpusbscsi struct hpusbscsi
{ {
struct list_head lh; struct list_head lh;
...@@ -21,6 +26,7 @@ struct hpusbscsi ...@@ -21,6 +26,7 @@ struct hpusbscsi
int number; int number;
scsi_callback scallback; scsi_callback scallback;
Scsi_Cmnd *srb; Scsi_Cmnd *srb;
u8 sense_command[SENSE_COMMAND_SIZE];
int use_count; int use_count;
wait_queue_head_t pending; wait_queue_head_t pending;
...@@ -57,6 +63,7 @@ static void simple_done (struct urb *u); ...@@ -57,6 +63,7 @@ static void simple_done (struct urb *u);
static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback); static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback);
static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb); static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb);
static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb); static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb);
static void issue_request_sense (struct hpusbscsi *hpusbscsi);
static Scsi_Host_Template hpusbscsi_scsi_host_template = { static Scsi_Host_Template hpusbscsi_scsi_host_template = {
name: "hpusbscsi", name: "hpusbscsi",
...@@ -86,3 +93,4 @@ static Scsi_Host_Template hpusbscsi_scsi_host_template = { ...@@ -86,3 +93,4 @@ static Scsi_Host_Template hpusbscsi_scsi_host_template = {
#define HP_STATE_PREMATURE 5 /* status prematurely reported */ #define HP_STATE_PREMATURE 5 /* status prematurely reported */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment