diff options
Diffstat (limited to 'drivers/usb/storage/initializers.c')
| -rw-r--r-- | drivers/usb/storage/initializers.c | 73 | 
1 files changed, 73 insertions, 0 deletions
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c index 5b06f9240d0..ab173b30076 100644 --- a/drivers/usb/storage/initializers.c +++ b/drivers/usb/storage/initializers.c @@ -45,6 +45,12 @@  #include "debug.h"  #include "transport.h" +#define RIO_MSC 0x08 +#define RIOP_INIT "RIOP\x00\x01\x08" +#define RIOP_INIT_LEN 7 +#define RIO_SEND_LEN 40 +#define RIO_RECV_LEN 0x200 +  /* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target   * mode */  int usb_stor_euscsi_init(struct us_data *us) @@ -91,3 +97,70 @@ int usb_stor_ucr61s2b_init(struct us_data *us)  	return (res ? -1 : 0);  } + +/* Place the Rio Karma into mass storage mode. + * + * The initialization begins by sending 40 bytes starting + * RIOP\x00\x01\x08\x00, which the device will ack with a 512-byte + * packet with the high four bits set and everything else null. + * + * Next, we send RIOP\x80\x00\x08\x00.  Each time, a 512 byte response + * must be read, but we must loop until byte 5 in the response is 0x08, + * indicating success.  */ +int rio_karma_init(struct us_data *us) +{ +	int result, partial; +	char *recv; +	unsigned long timeout; + +	// us->iobuf is big enough to hold cmd but not receive +	if (!(recv = kmalloc(RIO_RECV_LEN, GFP_KERNEL))) +		goto die_nomem; + +	US_DEBUGP("Initializing Karma...\n"); + +	memset(us->iobuf, 0, RIO_SEND_LEN); +	memcpy(us->iobuf, RIOP_INIT, RIOP_INIT_LEN); + +	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, +		us->iobuf, RIO_SEND_LEN, &partial); +	if (result != USB_STOR_XFER_GOOD) +		goto die; + +	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, +		recv, RIO_RECV_LEN, &partial); +	if (result != USB_STOR_XFER_GOOD) +		goto die; + +	us->iobuf[4] = 0x80; +	us->iobuf[5] = 0; +	timeout = jiffies + msecs_to_jiffies(3000); +	for (;;) { +		US_DEBUGP("Sending init command\n"); +		result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, +			us->iobuf, RIO_SEND_LEN, &partial); +		if (result != USB_STOR_XFER_GOOD) +			goto die; + +		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, +			recv, RIO_RECV_LEN, &partial); +		if (result != USB_STOR_XFER_GOOD) +			goto die; + +		if (recv[5] == RIO_MSC) +			break; +		if (time_after(jiffies, timeout)) +			goto die; +		msleep(10); +	} +	US_DEBUGP("Karma initialized.\n"); +	kfree(recv); +	return 0; + +die: +	kfree(recv); +die_nomem: +	US_DEBUGP("Could not initialize karma.\n"); +	return USB_STOR_TRANSPORT_FAILED; +} +  |