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 5b06f9240d05..ab173b30076e 100644 --- a/drivers/usb/storage/initializers.c +++ b/drivers/usb/storage/initializers.c | |||
@@ -45,6 +45,12 @@ | |||
45 | #include "debug.h" | 45 | #include "debug.h" |
46 | #include "transport.h" | 46 | #include "transport.h" |
47 | 47 | ||
48 | #define RIO_MSC 0x08 | ||
49 | #define RIOP_INIT "RIOP\x00\x01\x08" | ||
50 | #define RIOP_INIT_LEN 7 | ||
51 | #define RIO_SEND_LEN 40 | ||
52 | #define RIO_RECV_LEN 0x200 | ||
53 | |||
48 | /* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target | 54 | /* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target |
49 | * mode */ | 55 | * mode */ |
50 | int usb_stor_euscsi_init(struct us_data *us) | 56 | int usb_stor_euscsi_init(struct us_data *us) |
@@ -91,3 +97,70 @@ int usb_stor_ucr61s2b_init(struct us_data *us) | |||
91 | 97 | ||
92 | return (res ? -1 : 0); | 98 | return (res ? -1 : 0); |
93 | } | 99 | } |
100 | |||
101 | /* Place the Rio Karma into mass storage mode. | ||
102 | * | ||
103 | * The initialization begins by sending 40 bytes starting | ||
104 | * RIOP\x00\x01\x08\x00, which the device will ack with a 512-byte | ||
105 | * packet with the high four bits set and everything else null. | ||
106 | * | ||
107 | * Next, we send RIOP\x80\x00\x08\x00. Each time, a 512 byte response | ||
108 | * must be read, but we must loop until byte 5 in the response is 0x08, | ||
109 | * indicating success. */ | ||
110 | int rio_karma_init(struct us_data *us) | ||
111 | { | ||
112 | int result, partial; | ||
113 | char *recv; | ||
114 | unsigned long timeout; | ||
115 | |||
116 | // us->iobuf is big enough to hold cmd but not receive | ||
117 | if (!(recv = kmalloc(RIO_RECV_LEN, GFP_KERNEL))) | ||
118 | goto die_nomem; | ||
119 | |||
120 | US_DEBUGP("Initializing Karma...\n"); | ||
121 | |||
122 | memset(us->iobuf, 0, RIO_SEND_LEN); | ||
123 | memcpy(us->iobuf, RIOP_INIT, RIOP_INIT_LEN); | ||
124 | |||
125 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | ||
126 | us->iobuf, RIO_SEND_LEN, &partial); | ||
127 | if (result != USB_STOR_XFER_GOOD) | ||
128 | goto die; | ||
129 | |||
130 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | ||
131 | recv, RIO_RECV_LEN, &partial); | ||
132 | if (result != USB_STOR_XFER_GOOD) | ||
133 | goto die; | ||
134 | |||
135 | us->iobuf[4] = 0x80; | ||
136 | us->iobuf[5] = 0; | ||
137 | timeout = jiffies + msecs_to_jiffies(3000); | ||
138 | for (;;) { | ||
139 | US_DEBUGP("Sending init command\n"); | ||
140 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | ||
141 | us->iobuf, RIO_SEND_LEN, &partial); | ||
142 | if (result != USB_STOR_XFER_GOOD) | ||
143 | goto die; | ||
144 | |||
145 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | ||
146 | recv, RIO_RECV_LEN, &partial); | ||
147 | if (result != USB_STOR_XFER_GOOD) | ||
148 | goto die; | ||
149 | |||
150 | if (recv[5] == RIO_MSC) | ||
151 | break; | ||
152 | if (time_after(jiffies, timeout)) | ||
153 | goto die; | ||
154 | msleep(10); | ||
155 | } | ||
156 | US_DEBUGP("Karma initialized.\n"); | ||
157 | kfree(recv); | ||
158 | return 0; | ||
159 | |||
160 | die: | ||
161 | kfree(recv); | ||
162 | die_nomem: | ||
163 | US_DEBUGP("Could not initialize karma.\n"); | ||
164 | return USB_STOR_TRANSPORT_FAILED; | ||
165 | } | ||
166 | |||