diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-16 18:19:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-16 18:19:35 -0400 |
commit | 6445ced8670f37cfc2c5e24a9de9b413dbfc788d (patch) | |
tree | 7c98481159008a4080cda929ea8c7bc7598a2c39 /drivers/usb | |
parent | e6bee325e49f17c65c1fd66e9e8b348c85788341 (diff) | |
parent | 12bb12fac06d6212be9a5ed282c5670d4e90747f (diff) |
Merge branch 'staging-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6
* 'staging-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6: (961 commits)
staging: hv: fix memory leaks
staging: hv: Remove NULL check before kfree
Staging: hv: Get rid of vmbus_child_dev_add()
Staging: hv: Change the signature for vmbus_child_device_register()
Staging: hv: Get rid of vmbus_cleanup() function
Staging: hv: Get rid of vmbus_dev_rm() function
Staging: hv: Change the signature for vmbus_on_isr()
Staging: hv: Eliminate vmbus_event_dpc()
Staging: hv: Get rid of the function vmbus_msg_dpc()
Staging: hv: Change the signature for vmbus_cleanup()
Staging: hv: Simplify root device management
staging: rtl8192e: Don't copy dev pointer to skb
staging: rtl8192e: Pass priv to cmdpkt functions
staging: rtl8192e: Pass priv to firmware download functions
staging: rtl8192e: Pass priv to rtl8192_interrupt
staging: rtl8192e: Pass rtl8192_priv to dm functions
staging: rtl8192e: Pass ieee80211_device to callbacks
staging: rtl8192e: Pass ieee80211_device to callbacks
staging: rtl8192e: Pass ieee80211_device to callbacks
staging: rtl8192e: Pass ieee80211_device to callbacks
...
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/storage/Kconfig | 15 | ||||
-rw-r--r-- | drivers/usb/storage/Makefile | 2 | ||||
-rw-r--r-- | drivers/usb/storage/ene_ub6250.c | 803 | ||||
-rw-r--r-- | drivers/usb/storage/unusual_ene_ub6250.h | 26 | ||||
-rw-r--r-- | drivers/usb/storage/usual-tables.c | 1 |
5 files changed, 847 insertions, 0 deletions
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 353aeb44da6a..97987255be75 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig | |||
@@ -182,6 +182,21 @@ config USB_STORAGE_CYPRESS_ATACB | |||
182 | 182 | ||
183 | If this driver is compiled as a module, it will be named ums-cypress. | 183 | If this driver is compiled as a module, it will be named ums-cypress. |
184 | 184 | ||
185 | config USB_STORAGE_ENE_UB6250 | ||
186 | tristate "USB ENE card reader support" | ||
187 | depends on USB && SCSI | ||
188 | depends on USB_STORAGE | ||
189 | ---help--- | ||
190 | Say Y here if you wish to control a ENE SD Card reader. | ||
191 | To use SM/MS card, please build driver/staging/keucr/keucr.ko | ||
192 | |||
193 | This option depends on 'SCSI' support being enabled, but you | ||
194 | probably also need 'SCSI device support: SCSI disk support' | ||
195 | (BLK_DEV_SD) for most USB storage devices. | ||
196 | |||
197 | To compile this driver as a module, choose M here: the | ||
198 | module will be called ums-eneub6250. | ||
199 | |||
185 | config USB_UAS | 200 | config USB_UAS |
186 | tristate "USB Attached SCSI" | 201 | tristate "USB Attached SCSI" |
187 | depends on USB && SCSI | 202 | depends on USB && SCSI |
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 0d2de971bd91..82e6416a2d47 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile | |||
@@ -25,6 +25,7 @@ endif | |||
25 | obj-$(CONFIG_USB_STORAGE_ALAUDA) += ums-alauda.o | 25 | obj-$(CONFIG_USB_STORAGE_ALAUDA) += ums-alauda.o |
26 | obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o | 26 | obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o |
27 | obj-$(CONFIG_USB_STORAGE_DATAFAB) += ums-datafab.o | 27 | obj-$(CONFIG_USB_STORAGE_DATAFAB) += ums-datafab.o |
28 | obj-$(CONFIG_USB_STORAGE_ENE_UB6250) += ums-eneub6250.o | ||
28 | obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o | 29 | obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o |
29 | obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o | 30 | obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o |
30 | obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += ums-jumpshot.o | 31 | obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += ums-jumpshot.o |
@@ -38,6 +39,7 @@ obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o | |||
38 | ums-alauda-y := alauda.o | 39 | ums-alauda-y := alauda.o |
39 | ums-cypress-y := cypress_atacb.o | 40 | ums-cypress-y := cypress_atacb.o |
40 | ums-datafab-y := datafab.o | 41 | ums-datafab-y := datafab.o |
42 | ums-eneub6250-y := ene_ub6250.o | ||
41 | ums-freecom-y := freecom.o | 43 | ums-freecom-y := freecom.o |
42 | ums-isd200-y := isd200.o | 44 | ums-isd200-y := isd200.o |
43 | ums-jumpshot-y := jumpshot.o | 45 | ums-jumpshot-y := jumpshot.o |
diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c new file mode 100644 index 000000000000..08e03745e251 --- /dev/null +++ b/drivers/usb/storage/ene_ub6250.c | |||
@@ -0,0 +1,803 @@ | |||
1 | /* | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify it | ||
4 | * under the terms of the GNU General Public License as published by the | ||
5 | * Free Software Foundation; either version 2, or (at your option) any | ||
6 | * later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | * General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License along | ||
14 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
15 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
16 | */ | ||
17 | #include <linux/jiffies.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | #include <scsi/scsi.h> | ||
23 | #include <scsi/scsi_cmnd.h> | ||
24 | |||
25 | #include <linux/firmware.h> | ||
26 | |||
27 | #include "usb.h" | ||
28 | #include "transport.h" | ||
29 | #include "protocol.h" | ||
30 | #include "debug.h" | ||
31 | |||
32 | MODULE_DESCRIPTION("Driver for ENE UB6250 reader"); | ||
33 | MODULE_LICENSE("GPL"); | ||
34 | |||
35 | |||
36 | /* | ||
37 | * The table of devices | ||
38 | */ | ||
39 | #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ | ||
40 | vendorName, productName, useProtocol, useTransport, \ | ||
41 | initFunction, flags) \ | ||
42 | { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ | ||
43 | .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } | ||
44 | |||
45 | struct usb_device_id ene_ub6250_usb_ids[] = { | ||
46 | # include "unusual_ene_ub6250.h" | ||
47 | { } /* Terminating entry */ | ||
48 | }; | ||
49 | MODULE_DEVICE_TABLE(usb, ene_ub6250_usb_ids); | ||
50 | |||
51 | #undef UNUSUAL_DEV | ||
52 | |||
53 | /* | ||
54 | * The flags table | ||
55 | */ | ||
56 | #define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ | ||
57 | vendor_name, product_name, use_protocol, use_transport, \ | ||
58 | init_function, Flags) \ | ||
59 | { \ | ||
60 | .vendorName = vendor_name, \ | ||
61 | .productName = product_name, \ | ||
62 | .useProtocol = use_protocol, \ | ||
63 | .useTransport = use_transport, \ | ||
64 | .initFunction = init_function, \ | ||
65 | } | ||
66 | |||
67 | static struct us_unusual_dev ene_ub6250_unusual_dev_list[] = { | ||
68 | # include "unusual_ene_ub6250.h" | ||
69 | { } /* Terminating entry */ | ||
70 | }; | ||
71 | |||
72 | #undef UNUSUAL_DEV | ||
73 | |||
74 | |||
75 | |||
76 | /* ENE bin code len */ | ||
77 | #define ENE_BIN_CODE_LEN 0x800 | ||
78 | /* EnE HW Register */ | ||
79 | #define REG_CARD_STATUS 0xFF83 | ||
80 | #define REG_HW_TRAP1 0xFF89 | ||
81 | |||
82 | /* SRB Status */ | ||
83 | #define SS_SUCCESS 0x00 /* No Sense */ | ||
84 | #define SS_NOT_READY 0x02 | ||
85 | #define SS_MEDIUM_ERR 0x03 | ||
86 | #define SS_HW_ERR 0x04 | ||
87 | #define SS_ILLEGAL_REQUEST 0x05 | ||
88 | #define SS_UNIT_ATTENTION 0x06 | ||
89 | |||
90 | /* ENE Load FW Pattern */ | ||
91 | #define SD_INIT1_PATTERN 1 | ||
92 | #define SD_INIT2_PATTERN 2 | ||
93 | #define SD_RW_PATTERN 3 | ||
94 | #define MS_INIT_PATTERN 4 | ||
95 | #define MSP_RW_PATTERN 5 | ||
96 | #define MS_RW_PATTERN 6 | ||
97 | #define SM_INIT_PATTERN 7 | ||
98 | #define SM_RW_PATTERN 8 | ||
99 | |||
100 | #define FDIR_WRITE 0 | ||
101 | #define FDIR_READ 1 | ||
102 | |||
103 | |||
104 | struct SD_STATUS { | ||
105 | u8 Insert:1; | ||
106 | u8 Ready:1; | ||
107 | u8 MediaChange:1; | ||
108 | u8 IsMMC:1; | ||
109 | u8 HiCapacity:1; | ||
110 | u8 HiSpeed:1; | ||
111 | u8 WtP:1; | ||
112 | u8 Reserved:1; | ||
113 | }; | ||
114 | |||
115 | struct MS_STATUS { | ||
116 | u8 Insert:1; | ||
117 | u8 Ready:1; | ||
118 | u8 MediaChange:1; | ||
119 | u8 IsMSPro:1; | ||
120 | u8 IsMSPHG:1; | ||
121 | u8 Reserved1:1; | ||
122 | u8 WtP:1; | ||
123 | u8 Reserved2:1; | ||
124 | }; | ||
125 | |||
126 | struct SM_STATUS { | ||
127 | u8 Insert:1; | ||
128 | u8 Ready:1; | ||
129 | u8 MediaChange:1; | ||
130 | u8 Reserved:3; | ||
131 | u8 WtP:1; | ||
132 | u8 IsMS:1; | ||
133 | }; | ||
134 | |||
135 | |||
136 | /* SD Block Length */ | ||
137 | /* 2^9 = 512 Bytes, The HW maximum read/write data length */ | ||
138 | #define SD_BLOCK_LEN 9 | ||
139 | |||
140 | struct ene_ub6250_info { | ||
141 | /* for 6250 code */ | ||
142 | struct SD_STATUS SD_Status; | ||
143 | struct MS_STATUS MS_Status; | ||
144 | struct SM_STATUS SM_Status; | ||
145 | |||
146 | /* ----- SD Control Data ---------------- */ | ||
147 | /*SD_REGISTER SD_Regs; */ | ||
148 | u16 SD_Block_Mult; | ||
149 | u8 SD_READ_BL_LEN; | ||
150 | u16 SD_C_SIZE; | ||
151 | u8 SD_C_SIZE_MULT; | ||
152 | |||
153 | /* SD/MMC New spec. */ | ||
154 | u8 SD_SPEC_VER; | ||
155 | u8 SD_CSD_VER; | ||
156 | u8 SD20_HIGH_CAPACITY; | ||
157 | u32 HC_C_SIZE; | ||
158 | u8 MMC_SPEC_VER; | ||
159 | u8 MMC_BusWidth; | ||
160 | u8 MMC_HIGH_CAPACITY; | ||
161 | |||
162 | /*----- MS Control Data ---------------- */ | ||
163 | bool MS_SWWP; | ||
164 | u32 MSP_TotalBlock; | ||
165 | /*MS_LibControl MS_Lib;*/ | ||
166 | bool MS_IsRWPage; | ||
167 | u16 MS_Model; | ||
168 | |||
169 | /*----- SM Control Data ---------------- */ | ||
170 | u8 SM_DeviceID; | ||
171 | u8 SM_CardID; | ||
172 | |||
173 | unsigned char *testbuf; | ||
174 | u8 BIN_FLAG; | ||
175 | u32 bl_num; | ||
176 | int SrbStatus; | ||
177 | |||
178 | /*------Power Managerment ---------------*/ | ||
179 | bool Power_IsResum; | ||
180 | }; | ||
181 | |||
182 | static int ene_sd_init(struct us_data *us); | ||
183 | static int ene_load_bincode(struct us_data *us, unsigned char flag); | ||
184 | |||
185 | static void ene_ub6250_info_destructor(void *extra) | ||
186 | { | ||
187 | if (!extra) | ||
188 | return; | ||
189 | } | ||
190 | |||
191 | static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg) | ||
192 | { | ||
193 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | ||
194 | struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf; | ||
195 | |||
196 | int result; | ||
197 | unsigned int residue; | ||
198 | unsigned int cswlen = 0, partial = 0; | ||
199 | unsigned int transfer_length = bcb->DataTransferLength; | ||
200 | |||
201 | /* US_DEBUGP("transport --- ene_send_scsi_cmd\n"); */ | ||
202 | /* send cmd to out endpoint */ | ||
203 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | ||
204 | bcb, US_BULK_CB_WRAP_LEN, NULL); | ||
205 | if (result != USB_STOR_XFER_GOOD) { | ||
206 | US_DEBUGP("send cmd to out endpoint fail ---\n"); | ||
207 | return USB_STOR_TRANSPORT_ERROR; | ||
208 | } | ||
209 | |||
210 | if (buf) { | ||
211 | unsigned int pipe = fDir; | ||
212 | |||
213 | if (fDir == FDIR_READ) | ||
214 | pipe = us->recv_bulk_pipe; | ||
215 | else | ||
216 | pipe = us->send_bulk_pipe; | ||
217 | |||
218 | /* Bulk */ | ||
219 | if (use_sg) { | ||
220 | result = usb_stor_bulk_srb(us, pipe, us->srb); | ||
221 | } else { | ||
222 | result = usb_stor_bulk_transfer_sg(us, pipe, buf, | ||
223 | transfer_length, 0, &partial); | ||
224 | } | ||
225 | if (result != USB_STOR_XFER_GOOD) { | ||
226 | US_DEBUGP("data transfer fail ---\n"); | ||
227 | return USB_STOR_TRANSPORT_ERROR; | ||
228 | } | ||
229 | } | ||
230 | |||
231 | /* Get CSW for device status */ | ||
232 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, | ||
233 | US_BULK_CS_WRAP_LEN, &cswlen); | ||
234 | |||
235 | if (result == USB_STOR_XFER_SHORT && cswlen == 0) { | ||
236 | US_DEBUGP("Received 0-length CSW; retrying...\n"); | ||
237 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | ||
238 | bcs, US_BULK_CS_WRAP_LEN, &cswlen); | ||
239 | } | ||
240 | |||
241 | if (result == USB_STOR_XFER_STALLED) { | ||
242 | /* get the status again */ | ||
243 | US_DEBUGP("Attempting to get CSW (2nd try)...\n"); | ||
244 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | ||
245 | bcs, US_BULK_CS_WRAP_LEN, NULL); | ||
246 | } | ||
247 | |||
248 | if (result != USB_STOR_XFER_GOOD) | ||
249 | return USB_STOR_TRANSPORT_ERROR; | ||
250 | |||
251 | /* check bulk status */ | ||
252 | residue = le32_to_cpu(bcs->Residue); | ||
253 | |||
254 | /* try to compute the actual residue, based on how much data | ||
255 | * was really transferred and what the device tells us */ | ||
256 | if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) { | ||
257 | residue = min(residue, transfer_length); | ||
258 | if (us->srb != NULL) | ||
259 | scsi_set_resid(us->srb, max(scsi_get_resid(us->srb), | ||
260 | (int)residue)); | ||
261 | } | ||
262 | |||
263 | if (bcs->Status != US_BULK_STAT_OK) | ||
264 | return USB_STOR_TRANSPORT_ERROR; | ||
265 | |||
266 | return USB_STOR_TRANSPORT_GOOD; | ||
267 | } | ||
268 | |||
269 | static int sd_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb) | ||
270 | { | ||
271 | struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; | ||
272 | |||
273 | if (info->SD_Status.Insert && info->SD_Status.Ready) | ||
274 | return USB_STOR_TRANSPORT_GOOD; | ||
275 | else { | ||
276 | ene_sd_init(us); | ||
277 | return USB_STOR_TRANSPORT_GOOD; | ||
278 | } | ||
279 | |||
280 | return USB_STOR_TRANSPORT_GOOD; | ||
281 | } | ||
282 | |||
283 | static int sd_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb) | ||
284 | { | ||
285 | unsigned char data_ptr[36] = { | ||
286 | 0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55, | ||
287 | 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61, | ||
288 | 0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, | ||
289 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30 }; | ||
290 | |||
291 | usb_stor_set_xfer_buf(data_ptr, 36, srb); | ||
292 | return USB_STOR_TRANSPORT_GOOD; | ||
293 | } | ||
294 | |||
295 | static int sd_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb) | ||
296 | { | ||
297 | struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; | ||
298 | unsigned char mediaNoWP[12] = { | ||
299 | 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, | ||
300 | 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 }; | ||
301 | unsigned char mediaWP[12] = { | ||
302 | 0x0b, 0x00, 0x80, 0x08, 0x00, 0x00, | ||
303 | 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 }; | ||
304 | |||
305 | if (info->SD_Status.WtP) | ||
306 | usb_stor_set_xfer_buf(mediaWP, 12, srb); | ||
307 | else | ||
308 | usb_stor_set_xfer_buf(mediaNoWP, 12, srb); | ||
309 | |||
310 | |||
311 | return USB_STOR_TRANSPORT_GOOD; | ||
312 | } | ||
313 | |||
314 | static int sd_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb) | ||
315 | { | ||
316 | u32 bl_num; | ||
317 | u16 bl_len; | ||
318 | unsigned int offset = 0; | ||
319 | unsigned char buf[8]; | ||
320 | struct scatterlist *sg = NULL; | ||
321 | struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; | ||
322 | |||
323 | US_DEBUGP("sd_scsi_read_capacity\n"); | ||
324 | if (info->SD_Status.HiCapacity) { | ||
325 | bl_len = 0x200; | ||
326 | if (info->SD_Status.IsMMC) | ||
327 | bl_num = info->HC_C_SIZE-1; | ||
328 | else | ||
329 | bl_num = (info->HC_C_SIZE + 1) * 1024 - 1; | ||
330 | } else { | ||
331 | bl_len = 1<<(info->SD_READ_BL_LEN); | ||
332 | bl_num = info->SD_Block_Mult * (info->SD_C_SIZE + 1) | ||
333 | * (1 << (info->SD_C_SIZE_MULT + 2)) - 1; | ||
334 | } | ||
335 | info->bl_num = bl_num; | ||
336 | US_DEBUGP("bl_len = %x\n", bl_len); | ||
337 | US_DEBUGP("bl_num = %x\n", bl_num); | ||
338 | |||
339 | /*srb->request_bufflen = 8; */ | ||
340 | buf[0] = (bl_num >> 24) & 0xff; | ||
341 | buf[1] = (bl_num >> 16) & 0xff; | ||
342 | buf[2] = (bl_num >> 8) & 0xff; | ||
343 | buf[3] = (bl_num >> 0) & 0xff; | ||
344 | buf[4] = (bl_len >> 24) & 0xff; | ||
345 | buf[5] = (bl_len >> 16) & 0xff; | ||
346 | buf[6] = (bl_len >> 8) & 0xff; | ||
347 | buf[7] = (bl_len >> 0) & 0xff; | ||
348 | |||
349 | usb_stor_access_xfer_buf(buf, 8, srb, &sg, &offset, TO_XFER_BUF); | ||
350 | |||
351 | return USB_STOR_TRANSPORT_GOOD; | ||
352 | } | ||
353 | |||
354 | static int sd_scsi_read(struct us_data *us, struct scsi_cmnd *srb) | ||
355 | { | ||
356 | int result; | ||
357 | unsigned char *cdb = srb->cmnd; | ||
358 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | ||
359 | struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; | ||
360 | |||
361 | u32 bn = ((cdb[2] << 24) & 0xff000000) | ((cdb[3] << 16) & 0x00ff0000) | | ||
362 | ((cdb[4] << 8) & 0x0000ff00) | ((cdb[5] << 0) & 0x000000ff); | ||
363 | u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff); | ||
364 | u32 bnByte = bn * 0x200; | ||
365 | u32 blenByte = blen * 0x200; | ||
366 | |||
367 | if (bn > info->bl_num) | ||
368 | return USB_STOR_TRANSPORT_ERROR; | ||
369 | |||
370 | result = ene_load_bincode(us, SD_RW_PATTERN); | ||
371 | if (result != USB_STOR_XFER_GOOD) { | ||
372 | US_DEBUGP("Load SD RW pattern Fail !!\n"); | ||
373 | return USB_STOR_TRANSPORT_ERROR; | ||
374 | } | ||
375 | |||
376 | if (info->SD_Status.HiCapacity) | ||
377 | bnByte = bn; | ||
378 | |||
379 | /* set up the command wrapper */ | ||
380 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); | ||
381 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); | ||
382 | bcb->DataTransferLength = blenByte; | ||
383 | bcb->Flags = 0x80; | ||
384 | bcb->CDB[0] = 0xF1; | ||
385 | bcb->CDB[5] = (unsigned char)(bnByte); | ||
386 | bcb->CDB[4] = (unsigned char)(bnByte>>8); | ||
387 | bcb->CDB[3] = (unsigned char)(bnByte>>16); | ||
388 | bcb->CDB[2] = (unsigned char)(bnByte>>24); | ||
389 | |||
390 | result = ene_send_scsi_cmd(us, FDIR_READ, scsi_sglist(srb), 1); | ||
391 | return result; | ||
392 | } | ||
393 | |||
394 | static int sd_scsi_write(struct us_data *us, struct scsi_cmnd *srb) | ||
395 | { | ||
396 | int result; | ||
397 | unsigned char *cdb = srb->cmnd; | ||
398 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | ||
399 | struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; | ||
400 | |||
401 | u32 bn = ((cdb[2] << 24) & 0xff000000) | ((cdb[3] << 16) & 0x00ff0000) | | ||
402 | ((cdb[4] << 8) & 0x0000ff00) | ((cdb[5] << 0) & 0x000000ff); | ||
403 | u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff); | ||
404 | u32 bnByte = bn * 0x200; | ||
405 | u32 blenByte = blen * 0x200; | ||
406 | |||
407 | if (bn > info->bl_num) | ||
408 | return USB_STOR_TRANSPORT_ERROR; | ||
409 | |||
410 | result = ene_load_bincode(us, SD_RW_PATTERN); | ||
411 | if (result != USB_STOR_XFER_GOOD) { | ||
412 | US_DEBUGP("Load SD RW pattern Fail !!\n"); | ||
413 | return USB_STOR_TRANSPORT_ERROR; | ||
414 | } | ||
415 | |||
416 | if (info->SD_Status.HiCapacity) | ||
417 | bnByte = bn; | ||
418 | |||
419 | /* set up the command wrapper */ | ||
420 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); | ||
421 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); | ||
422 | bcb->DataTransferLength = blenByte; | ||
423 | bcb->Flags = 0x00; | ||
424 | bcb->CDB[0] = 0xF0; | ||
425 | bcb->CDB[5] = (unsigned char)(bnByte); | ||
426 | bcb->CDB[4] = (unsigned char)(bnByte>>8); | ||
427 | bcb->CDB[3] = (unsigned char)(bnByte>>16); | ||
428 | bcb->CDB[2] = (unsigned char)(bnByte>>24); | ||
429 | |||
430 | result = ene_send_scsi_cmd(us, FDIR_WRITE, scsi_sglist(srb), 1); | ||
431 | return result; | ||
432 | } | ||
433 | |||
434 | static int ene_get_card_type(struct us_data *us, u16 index, void *buf) | ||
435 | { | ||
436 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | ||
437 | int result; | ||
438 | |||
439 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); | ||
440 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); | ||
441 | bcb->DataTransferLength = 0x01; | ||
442 | bcb->Flags = 0x80; | ||
443 | bcb->CDB[0] = 0xED; | ||
444 | bcb->CDB[2] = (unsigned char)(index>>8); | ||
445 | bcb->CDB[3] = (unsigned char)index; | ||
446 | |||
447 | result = ene_send_scsi_cmd(us, FDIR_READ, buf, 0); | ||
448 | return result; | ||
449 | } | ||
450 | |||
451 | static int ene_get_card_status(struct us_data *us, u8 *buf) | ||
452 | { | ||
453 | u16 tmpreg; | ||
454 | u32 reg4b; | ||
455 | struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; | ||
456 | |||
457 | /*US_DEBUGP("transport --- ENE_ReadSDReg\n");*/ | ||
458 | reg4b = *(u32 *)&buf[0x18]; | ||
459 | info->SD_READ_BL_LEN = (u8)((reg4b >> 8) & 0x0f); | ||
460 | |||
461 | tmpreg = (u16) reg4b; | ||
462 | reg4b = *(u32 *)(&buf[0x14]); | ||
463 | if (info->SD_Status.HiCapacity && !info->SD_Status.IsMMC) | ||
464 | info->HC_C_SIZE = (reg4b >> 8) & 0x3fffff; | ||
465 | |||
466 | info->SD_C_SIZE = ((tmpreg & 0x03) << 10) | (u16)(reg4b >> 22); | ||
467 | info->SD_C_SIZE_MULT = (u8)(reg4b >> 7) & 0x07; | ||
468 | if (info->SD_Status.HiCapacity && info->SD_Status.IsMMC) | ||
469 | info->HC_C_SIZE = *(u32 *)(&buf[0x100]); | ||
470 | |||
471 | if (info->SD_READ_BL_LEN > SD_BLOCK_LEN) { | ||
472 | info->SD_Block_Mult = 1 << (info->SD_READ_BL_LEN-SD_BLOCK_LEN); | ||
473 | info->SD_READ_BL_LEN = SD_BLOCK_LEN; | ||
474 | } else { | ||
475 | info->SD_Block_Mult = 1; | ||
476 | } | ||
477 | |||
478 | return USB_STOR_TRANSPORT_GOOD; | ||
479 | } | ||
480 | |||
481 | static int ene_load_bincode(struct us_data *us, unsigned char flag) | ||
482 | { | ||
483 | int err; | ||
484 | char *fw_name = NULL; | ||
485 | unsigned char *buf = NULL; | ||
486 | const struct firmware *sd_fw = NULL; | ||
487 | int result = USB_STOR_TRANSPORT_ERROR; | ||
488 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | ||
489 | struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; | ||
490 | |||
491 | if (info->BIN_FLAG == flag) | ||
492 | return USB_STOR_TRANSPORT_GOOD; | ||
493 | |||
494 | switch (flag) { | ||
495 | /* For SD */ | ||
496 | case SD_INIT1_PATTERN: | ||
497 | US_DEBUGP("SD_INIT1_PATTERN\n"); | ||
498 | fw_name = "ene-ub6250/sd_init1.bin"; | ||
499 | break; | ||
500 | case SD_INIT2_PATTERN: | ||
501 | US_DEBUGP("SD_INIT2_PATTERN\n"); | ||
502 | fw_name = "ene-ub6250/sd_init2.bin"; | ||
503 | break; | ||
504 | case SD_RW_PATTERN: | ||
505 | US_DEBUGP("SD_RDWR_PATTERN\n"); | ||
506 | fw_name = "ene-ub6250/sd_rdwr.bin"; | ||
507 | break; | ||
508 | default: | ||
509 | US_DEBUGP("----------- Unknown PATTERN ----------\n"); | ||
510 | goto nofw; | ||
511 | } | ||
512 | |||
513 | err = request_firmware(&sd_fw, fw_name, &us->pusb_dev->dev); | ||
514 | if (err) { | ||
515 | US_DEBUGP("load firmware %s failed\n", fw_name); | ||
516 | goto nofw; | ||
517 | } | ||
518 | buf = kmalloc(sd_fw->size, GFP_KERNEL); | ||
519 | if (buf == NULL) { | ||
520 | US_DEBUGP("Malloc memory for fireware failed!\n"); | ||
521 | goto nofw; | ||
522 | } | ||
523 | memcpy(buf, sd_fw->data, sd_fw->size); | ||
524 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); | ||
525 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); | ||
526 | bcb->DataTransferLength = sd_fw->size; | ||
527 | bcb->Flags = 0x00; | ||
528 | bcb->CDB[0] = 0xEF; | ||
529 | |||
530 | result = ene_send_scsi_cmd(us, FDIR_WRITE, buf, 0); | ||
531 | info->BIN_FLAG = flag; | ||
532 | kfree(buf); | ||
533 | |||
534 | nofw: | ||
535 | if (sd_fw != NULL) { | ||
536 | release_firmware(sd_fw); | ||
537 | sd_fw = NULL; | ||
538 | } | ||
539 | |||
540 | return result; | ||
541 | } | ||
542 | |||
543 | static int ene_sd_init(struct us_data *us) | ||
544 | { | ||
545 | int result; | ||
546 | u8 buf[0x200]; | ||
547 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | ||
548 | struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; | ||
549 | |||
550 | US_DEBUGP("transport --- ENE_SDInit\n"); | ||
551 | /* SD Init Part-1 */ | ||
552 | result = ene_load_bincode(us, SD_INIT1_PATTERN); | ||
553 | if (result != USB_STOR_XFER_GOOD) { | ||
554 | US_DEBUGP("Load SD Init Code Part-1 Fail !!\n"); | ||
555 | return USB_STOR_TRANSPORT_ERROR; | ||
556 | } | ||
557 | |||
558 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); | ||
559 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); | ||
560 | bcb->Flags = 0x80; | ||
561 | bcb->CDB[0] = 0xF2; | ||
562 | |||
563 | result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0); | ||
564 | if (result != USB_STOR_XFER_GOOD) { | ||
565 | US_DEBUGP("Exection SD Init Code Fail !!\n"); | ||
566 | return USB_STOR_TRANSPORT_ERROR; | ||
567 | } | ||
568 | |||
569 | /* SD Init Part-2 */ | ||
570 | result = ene_load_bincode(us, SD_INIT2_PATTERN); | ||
571 | if (result != USB_STOR_XFER_GOOD) { | ||
572 | US_DEBUGP("Load SD Init Code Part-2 Fail !!\n"); | ||
573 | return USB_STOR_TRANSPORT_ERROR; | ||
574 | } | ||
575 | |||
576 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); | ||
577 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); | ||
578 | bcb->DataTransferLength = 0x200; | ||
579 | bcb->Flags = 0x80; | ||
580 | bcb->CDB[0] = 0xF1; | ||
581 | |||
582 | result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0); | ||
583 | if (result != USB_STOR_XFER_GOOD) { | ||
584 | US_DEBUGP("Exection SD Init Code Fail !!\n"); | ||
585 | return USB_STOR_TRANSPORT_ERROR; | ||
586 | } | ||
587 | |||
588 | info->SD_Status = *(struct SD_STATUS *)&buf[0]; | ||
589 | if (info->SD_Status.Insert && info->SD_Status.Ready) { | ||
590 | ene_get_card_status(us, (unsigned char *)&buf); | ||
591 | US_DEBUGP("Insert = %x\n", info->SD_Status.Insert); | ||
592 | US_DEBUGP("Ready = %x\n", info->SD_Status.Ready); | ||
593 | US_DEBUGP("IsMMC = %x\n", info->SD_Status.IsMMC); | ||
594 | US_DEBUGP("HiCapacity = %x\n", info->SD_Status.HiCapacity); | ||
595 | US_DEBUGP("HiSpeed = %x\n", info->SD_Status.HiSpeed); | ||
596 | US_DEBUGP("WtP = %x\n", info->SD_Status.WtP); | ||
597 | } else { | ||
598 | US_DEBUGP("SD Card Not Ready --- %x\n", buf[0]); | ||
599 | return USB_STOR_TRANSPORT_ERROR; | ||
600 | } | ||
601 | return USB_STOR_TRANSPORT_GOOD; | ||
602 | } | ||
603 | |||
604 | |||
605 | static int ene_init(struct us_data *us) | ||
606 | { | ||
607 | int result; | ||
608 | u8 misc_reg03 = 0; | ||
609 | struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); | ||
610 | |||
611 | result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03); | ||
612 | if (result != USB_STOR_XFER_GOOD) | ||
613 | return USB_STOR_TRANSPORT_ERROR; | ||
614 | |||
615 | if (misc_reg03 & 0x01) { | ||
616 | if (!info->SD_Status.Ready) { | ||
617 | result = ene_sd_init(us); | ||
618 | if (result != USB_STOR_XFER_GOOD) | ||
619 | return USB_STOR_TRANSPORT_ERROR; | ||
620 | } | ||
621 | } | ||
622 | |||
623 | return result; | ||
624 | } | ||
625 | |||
626 | /*----- sd_scsi_irp() ---------*/ | ||
627 | static int sd_scsi_irp(struct us_data *us, struct scsi_cmnd *srb) | ||
628 | { | ||
629 | int result; | ||
630 | struct ene_ub6250_info *info = (struct ene_ub6250_info *)us->extra; | ||
631 | |||
632 | info->SrbStatus = SS_SUCCESS; | ||
633 | switch (srb->cmnd[0]) { | ||
634 | case TEST_UNIT_READY: | ||
635 | result = sd_scsi_test_unit_ready(us, srb); | ||
636 | break; /* 0x00 */ | ||
637 | case INQUIRY: | ||
638 | result = sd_scsi_inquiry(us, srb); | ||
639 | break; /* 0x12 */ | ||
640 | case MODE_SENSE: | ||
641 | result = sd_scsi_mode_sense(us, srb); | ||
642 | break; /* 0x1A */ | ||
643 | /* | ||
644 | case START_STOP: | ||
645 | result = SD_SCSI_Start_Stop(us, srb); | ||
646 | break; //0x1B | ||
647 | */ | ||
648 | case READ_CAPACITY: | ||
649 | result = sd_scsi_read_capacity(us, srb); | ||
650 | break; /* 0x25 */ | ||
651 | case READ_10: | ||
652 | result = sd_scsi_read(us, srb); | ||
653 | break; /* 0x28 */ | ||
654 | case WRITE_10: | ||
655 | result = sd_scsi_write(us, srb); | ||
656 | break; /* 0x2A */ | ||
657 | default: | ||
658 | info->SrbStatus = SS_ILLEGAL_REQUEST; | ||
659 | result = USB_STOR_TRANSPORT_FAILED; | ||
660 | break; | ||
661 | } | ||
662 | return result; | ||
663 | } | ||
664 | |||
665 | static int ene_transport(struct scsi_cmnd *srb, struct us_data *us) | ||
666 | { | ||
667 | int result = 0; | ||
668 | struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); | ||
669 | |||
670 | /*US_DEBUG(usb_stor_show_command(srb)); */ | ||
671 | scsi_set_resid(srb, 0); | ||
672 | if (unlikely(!info->SD_Status.Ready)) | ||
673 | result = ene_init(us); | ||
674 | else | ||
675 | result = sd_scsi_irp(us, srb); | ||
676 | |||
677 | return 0; | ||
678 | } | ||
679 | |||
680 | |||
681 | static int ene_ub6250_probe(struct usb_interface *intf, | ||
682 | const struct usb_device_id *id) | ||
683 | { | ||
684 | int result; | ||
685 | u8 misc_reg03 = 0; | ||
686 | struct us_data *us; | ||
687 | |||
688 | result = usb_stor_probe1(&us, intf, id, | ||
689 | (id - ene_ub6250_usb_ids) + ene_ub6250_unusual_dev_list); | ||
690 | if (result) | ||
691 | return result; | ||
692 | |||
693 | /* FIXME: where should the code alloc extra buf ? */ | ||
694 | if (!us->extra) { | ||
695 | us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL); | ||
696 | if (!us->extra) | ||
697 | return -ENOMEM; | ||
698 | us->extra_destructor = ene_ub6250_info_destructor; | ||
699 | } | ||
700 | |||
701 | us->transport_name = "ene_ub6250"; | ||
702 | us->transport = ene_transport; | ||
703 | us->max_lun = 0; | ||
704 | |||
705 | result = usb_stor_probe2(us); | ||
706 | if (result) | ||
707 | return result; | ||
708 | |||
709 | /* probe card type */ | ||
710 | result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03); | ||
711 | if (result != USB_STOR_XFER_GOOD) { | ||
712 | usb_stor_disconnect(intf); | ||
713 | return USB_STOR_TRANSPORT_ERROR; | ||
714 | } | ||
715 | |||
716 | if (!(misc_reg03 & 0x01)) { | ||
717 | result = -ENODEV; | ||
718 | printk(KERN_NOTICE "ums_eneub6250: The driver only supports SD\ | ||
719 | card. To use SM/MS card, please build driver/stagging/keucr\n"); | ||
720 | usb_stor_disconnect(intf); | ||
721 | } | ||
722 | |||
723 | return result; | ||
724 | } | ||
725 | |||
726 | |||
727 | #ifdef CONFIG_PM | ||
728 | |||
729 | static int ene_ub6250_resume(struct usb_interface *iface) | ||
730 | { | ||
731 | u8 tmp = 0; | ||
732 | struct us_data *us = usb_get_intfdata(iface); | ||
733 | struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); | ||
734 | |||
735 | mutex_lock(&us->dev_mutex); | ||
736 | |||
737 | US_DEBUGP("%s\n", __func__); | ||
738 | if (us->suspend_resume_hook) | ||
739 | (us->suspend_resume_hook)(us, US_RESUME); | ||
740 | |||
741 | mutex_unlock(&us->dev_mutex); | ||
742 | |||
743 | info->Power_IsResum = true; | ||
744 | /*info->SD_Status.Ready = 0; */ | ||
745 | info->SD_Status = *(struct SD_STATUS *)&tmp; | ||
746 | info->MS_Status = *(struct MS_STATUS *)&tmp; | ||
747 | info->SM_Status = *(struct SM_STATUS *)&tmp; | ||
748 | |||
749 | return 0; | ||
750 | } | ||
751 | |||
752 | static int ene_ub6250_reset_resume(struct usb_interface *iface) | ||
753 | { | ||
754 | u8 tmp = 0; | ||
755 | struct us_data *us = usb_get_intfdata(iface); | ||
756 | struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); | ||
757 | US_DEBUGP("%s\n", __func__); | ||
758 | /* Report the reset to the SCSI core */ | ||
759 | usb_stor_reset_resume(iface); | ||
760 | |||
761 | /* FIXME: Notify the subdrivers that they need to reinitialize | ||
762 | * the device */ | ||
763 | info->Power_IsResum = true; | ||
764 | /*info->SD_Status.Ready = 0; */ | ||
765 | info->SD_Status = *(struct SD_STATUS *)&tmp; | ||
766 | info->MS_Status = *(struct MS_STATUS *)&tmp; | ||
767 | info->SM_Status = *(struct SM_STATUS *)&tmp; | ||
768 | |||
769 | return 0; | ||
770 | } | ||
771 | |||
772 | #else | ||
773 | |||
774 | #define ene_ub6250_resume NULL | ||
775 | #define ene_ub6250_reset_resume NULL | ||
776 | |||
777 | #endif | ||
778 | |||
779 | static struct usb_driver ene_ub6250_driver = { | ||
780 | .name = "ums_eneub6250", | ||
781 | .probe = ene_ub6250_probe, | ||
782 | .disconnect = usb_stor_disconnect, | ||
783 | .suspend = usb_stor_suspend, | ||
784 | .resume = ene_ub6250_resume, | ||
785 | .reset_resume = ene_ub6250_reset_resume, | ||
786 | .pre_reset = usb_stor_pre_reset, | ||
787 | .post_reset = usb_stor_post_reset, | ||
788 | .id_table = ene_ub6250_usb_ids, | ||
789 | .soft_unbind = 1, | ||
790 | }; | ||
791 | |||
792 | static int __init ene_ub6250_init(void) | ||
793 | { | ||
794 | return usb_register(&ene_ub6250_driver); | ||
795 | } | ||
796 | |||
797 | static void __exit ene_ub6250_exit(void) | ||
798 | { | ||
799 | usb_deregister(&ene_ub6250_driver); | ||
800 | } | ||
801 | |||
802 | module_init(ene_ub6250_init); | ||
803 | module_exit(ene_ub6250_exit); | ||
diff --git a/drivers/usb/storage/unusual_ene_ub6250.h b/drivers/usb/storage/unusual_ene_ub6250.h new file mode 100644 index 000000000000..5667f5d365c6 --- /dev/null +++ b/drivers/usb/storage/unusual_ene_ub6250.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify it | ||
4 | * under the terms of the GNU General Public License as published by the | ||
5 | * Free Software Foundation; either version 2, or (at your option) any | ||
6 | * later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | * General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License along | ||
14 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
15 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
16 | */ | ||
17 | |||
18 | #if defined(CONFIG_USB_STORAGE_ENE_UB6250) || \ | ||
19 | defined(CONFIG_USB_STORAGE_ENE_UB6250_MODULE) | ||
20 | |||
21 | UNUSUAL_DEV(0x0cf2, 0x6250, 0x0000, 0x9999, | ||
22 | "ENE", | ||
23 | "ENE UB6250 reader", | ||
24 | USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0), | ||
25 | |||
26 | #endif /* defined(CONFIG_USB_STORAGE_ENE_UB6250) || ... */ | ||
diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index 4293077c01aa..b96927914f89 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c | |||
@@ -80,6 +80,7 @@ static struct ignore_entry ignore_ids[] = { | |||
80 | # include "unusual_alauda.h" | 80 | # include "unusual_alauda.h" |
81 | # include "unusual_cypress.h" | 81 | # include "unusual_cypress.h" |
82 | # include "unusual_datafab.h" | 82 | # include "unusual_datafab.h" |
83 | # include "unusual_ene_ub6250.h" | ||
83 | # include "unusual_freecom.h" | 84 | # include "unusual_freecom.h" |
84 | # include "unusual_isd200.h" | 85 | # include "unusual_isd200.h" |
85 | # include "unusual_jumpshot.h" | 86 | # include "unusual_jumpshot.h" |