aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/bcm/InterfaceInit.c
diff options
context:
space:
mode:
authorStephen Hemminger <stephen.hemminger@vyatta.com>2010-09-08 17:46:36 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-09-09 00:15:06 -0400
commitf8942e07a3db9d82e8fb11d3d494876b8bae9ff9 (patch)
tree2406636a4f9a4ac6b0bfc90e07aefa8b1b18b8ff /drivers/staging/bcm/InterfaceInit.c
parent2d2f03b022186e6d7520a758abdea9c04a2969fe (diff)
staging: Beeceem USB Wimax driver
The Sprint 4G network uses a Wimax dongle with Beecem chipset. The driver is typical of out of tree drivers, but maybe useful for people, and the hardware is readily available. Here is a staging ready version (i.e warts and all) 0. Started with Rel_5.2.7.3P1_USB from Sprint4GDeveloperPack-1.1 1. Consolidated files in staging 2. Remove Dos cr/lf 3. Remove unnecessary ioctl from usbbcm_fops Applied patches that were in the developer pack, surprising there were ones for 2.6.35 already. This is compile tested only, see TODO for what still needs to be done. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/bcm/InterfaceInit.c')
-rw-r--r--drivers/staging/bcm/InterfaceInit.c868
1 files changed, 868 insertions, 0 deletions
diff --git a/drivers/staging/bcm/InterfaceInit.c b/drivers/staging/bcm/InterfaceInit.c
new file mode 100644
index 00000000000..e06f168a52b
--- /dev/null
+++ b/drivers/staging/bcm/InterfaceInit.c
@@ -0,0 +1,868 @@
1#include "headers.h"
2
3static struct usb_device_id InterfaceUsbtable[] = {
4 { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3) },
5 { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3B) },
6 { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3L) },
7 { USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_226) },
8 { USB_DEVICE(BCM_USB_VENDOR_ID_FOXCONN, BCM_USB_PRODUCT_ID_1901) },
9 {}
10};
11
12VOID InterfaceAdapterFree(PS_INTERFACE_ADAPTER psIntfAdapter)
13{
14 INT i = 0;
15 // Wake up the wait_queue...
16 if(psIntfAdapter->psAdapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
17 {
18 psIntfAdapter->psAdapter->DriverState = DRIVER_HALT;
19 wake_up(&psIntfAdapter->psAdapter->LEDInfo.notify_led_event);
20 }
21 reset_card_proc(psIntfAdapter->psAdapter);
22
23 //worst case time taken by the RDM/WRM will be 5 sec. will check after every 100 ms
24 //to accertain the device is not being accessed. After this No RDM/WRM should be made.
25 while(psIntfAdapter->psAdapter->DeviceAccess)
26 {
27 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Device is being Accessed \n");
28 msleep(100);
29 }
30 /* Free interrupt URB */
31 //psIntfAdapter->psAdapter->device_removed = TRUE;
32 if(psIntfAdapter->psInterruptUrb)
33 {
34 usb_free_urb(psIntfAdapter->psInterruptUrb);
35 }
36
37 /* Free transmit URBs */
38 for(i = 0; i < MAXIMUM_USB_TCB; i++)
39 {
40 if(psIntfAdapter->asUsbTcb[i].urb != NULL)
41 {
42 usb_free_urb(psIntfAdapter->asUsbTcb[i].urb);
43 psIntfAdapter->asUsbTcb[i].urb = NULL;
44 }
45 }
46 /* Free receive URB and buffers */
47 for(i = 0; i < MAXIMUM_USB_RCB; i++)
48 {
49 if (psIntfAdapter->asUsbRcb[i].urb != NULL)
50 {
51 bcm_kfree(psIntfAdapter->asUsbRcb[i].urb->transfer_buffer);
52 usb_free_urb(psIntfAdapter->asUsbRcb[i].urb);
53 psIntfAdapter->asUsbRcb[i].urb = NULL;
54 }
55 }
56 AdapterFree(psIntfAdapter->psAdapter);
57}
58
59
60
61static int usbbcm_open(struct inode *inode, struct file *file)
62{
63 return 0;
64}
65
66static int usbbcm_release(struct inode *inode, struct file *file)
67{
68 return 0;
69}
70
71static ssize_t usbbcm_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
72{
73 return 0;
74}
75
76static ssize_t usbbcm_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos)
77{
78 return 0;
79}
80
81
82VOID ConfigureEndPointTypesThroughEEPROM(PMINI_ADAPTER Adapter)
83{
84 ULONG ulReg = 0;
85
86// Program EP2 MAX_PKT_SIZE
87 ulReg = ntohl(EP2_MPS_REG);
88 BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x128,4,TRUE);
89 ulReg = ntohl(EP2_MPS);
90 BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x12C,4,TRUE);
91
92 ulReg = ntohl(EP2_CFG_REG);
93 BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x132,4,TRUE);
94 if(((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter))->bHighSpeedDevice == TRUE)
95 {
96 ulReg = ntohl(EP2_CFG_INT);
97 BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x136,4,TRUE);
98 }
99 else
100 {
101// USE BULK EP as TX in FS mode.
102 ulReg = ntohl(EP2_CFG_BULK);
103 BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x136,4,TRUE);
104 }
105
106
107// Program EP4 MAX_PKT_SIZE.
108 ulReg = ntohl(EP4_MPS_REG);
109 BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x13C,4,TRUE);
110 ulReg = ntohl(EP4_MPS);
111 BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x140,4,TRUE);
112
113// Program TX EP as interrupt (Alternate Setting)
114 if( rdmalt(Adapter,0x0F0110F8, (PUINT)&ulReg,4))
115 {
116 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "reading of Tx EP is failing");
117 return ;
118 }
119 ulReg |= 0x6;
120
121 ulReg = ntohl(ulReg);
122 BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x1CC,4,TRUE);
123
124 ulReg = ntohl(EP4_CFG_REG);
125 BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x1C8,4,TRUE);
126// Program ISOCHRONOUS EP size to zero.
127 ulReg = ntohl(ISO_MPS_REG);
128 BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x1D2,4,TRUE);
129 ulReg = ntohl(ISO_MPS);
130 BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x1D6,4,TRUE);
131
132// Update EEPROM Version.
133// Read 4 bytes from 508 and modify 511 and 510.
134//
135 ReadBeceemEEPROM(Adapter,0x1FC,(PUINT)&ulReg);
136 ulReg &= 0x0101FFFF;
137 BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x1FC,4,TRUE);
138//
139//Update length field if required. Also make the string NULL terminated.
140//
141 ReadBeceemEEPROM(Adapter,0xA8,(PUINT)&ulReg);
142 if((ulReg&0x00FF0000)>>16 > 0x30)
143 {
144 ulReg = (ulReg&0xFF00FFFF)|(0x30<<16);
145 BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0xA8,4,TRUE);
146 }
147 ReadBeceemEEPROM(Adapter,0x148,(PUINT)&ulReg);
148 if((ulReg&0x00FF0000)>>16 > 0x30)
149 {
150 ulReg = (ulReg&0xFF00FFFF)|(0x30<<16);
151 BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x148,4,TRUE);
152 }
153 ulReg = 0;
154 BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x122,4,TRUE);
155 ulReg = 0;
156 BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x1C2,4,TRUE);
157
158}
159
160static struct file_operations usbbcm_fops = {
161 .open = usbbcm_open,
162 .release = usbbcm_release,
163 .read = usbbcm_read,
164 .write = usbbcm_write,
165 .owner = THIS_MODULE,
166};
167
168static struct usb_class_driver usbbcm_class = {
169 .name = "usbbcm",
170 .fops = &usbbcm_fops,
171 .minor_base = BCM_USB_MINOR_BASE,
172};
173
174static int
175usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id)
176{
177 int retval =0 ;
178 PMINI_ADAPTER psAdapter = NULL;
179 PS_INTERFACE_ADAPTER psIntfAdapter = NULL;
180 struct usb_device *udev = NULL;
181
182// BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Usbbcm probe!!");
183 if((intf == NULL) || (id == NULL))
184 {
185 // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "intf or id is NULL");
186 return -EINVAL;
187 }
188
189 /* Allocate Adapter structure */
190 if((psAdapter = kmalloc(sizeof(MINI_ADAPTER), GFP_KERNEL)) == NULL)
191 {
192 //BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0, "Out of memory");
193 return -ENOMEM;
194 }
195
196 memset(psAdapter, 0, sizeof(MINI_ADAPTER));
197
198 /* Init default driver debug state */
199
200 psAdapter->stDebugState.debug_level = DBG_LVL_CURR;
201 psAdapter->stDebugState.type = DBG_TYPE_INITEXIT;
202 memset (psAdapter->stDebugState.subtype, 0, sizeof (psAdapter->stDebugState.subtype));
203
204 /* Technically, one can start using BCM_DEBUG_PRINT after this point.
205 * However, realize that by default the Type/Subtype bitmaps are all zero now;
206 * so no prints will actually appear until the TestApp turns on debug paths via
207 * the ioctl(); so practically speaking, in early init, no logging happens.
208 *
209 * A solution (used below): we explicitly set the bitmaps to 1 for Type=DBG_TYPE_INITEXIT
210 * and ALL subtype's of the same. Now all bcm debug statements get logged, enabling debug
211 * during early init.
212 * Further, we turn this OFF once init_module() completes.
213 */
214
215 psAdapter->stDebugState.subtype[DBG_TYPE_INITEXIT] = 0xff;
216 BCM_SHOW_DEBUG_BITMAP(psAdapter);
217
218 retval = InitAdapter(psAdapter);
219 if(retval)
220 {
221 BCM_DEBUG_PRINT (psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "InitAdapter Failed\n");
222 AdapterFree(psAdapter);
223 return retval;
224 }
225
226 /* Allocate interface adapter structure */
227 if((psAdapter->pvInterfaceAdapter =
228 kmalloc(sizeof(S_INTERFACE_ADAPTER), GFP_KERNEL)) == NULL)
229 {
230 BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0, "Out of memory");
231 AdapterFree (psAdapter);
232 return -ENOMEM;
233 }
234 memset(psAdapter->pvInterfaceAdapter, 0, sizeof(S_INTERFACE_ADAPTER));
235
236 psIntfAdapter = InterfaceAdapterGet(psAdapter);
237 psIntfAdapter->psAdapter = psAdapter;
238
239 /* Store usb interface in Interface Adapter */
240 psIntfAdapter->interface = intf;
241 usb_set_intfdata(intf, psIntfAdapter);
242
243 BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "psIntfAdapter 0x%x",(unsigned int)psIntfAdapter);
244 retval = InterfaceAdapterInit(psIntfAdapter);
245 if(retval)
246 {
247 /* If the Firmware/Cfg File is not present
248 * then return success, let the application
249 * download the files.
250 */
251 if(-ENOENT == retval){
252 BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "File Not Found, Use App to Download\n");
253 return STATUS_SUCCESS;
254 }
255 BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "InterfaceAdapterInit Failed \n");
256 usb_set_intfdata(intf, NULL);
257 udev = interface_to_usbdev (intf);
258 usb_put_dev(udev);
259 if(psAdapter->bUsbClassDriverRegistered == TRUE)
260 usb_deregister_dev (intf, &usbbcm_class);
261 InterfaceAdapterFree(psIntfAdapter);
262 return retval ;
263 }
264 if(psAdapter->chip_id > T3)
265 {
266 uint32_t uiNackZeroLengthInt=4;
267 if(wrmalt(psAdapter, DISABLE_USB_ZERO_LEN_INT, &uiNackZeroLengthInt, sizeof(uiNackZeroLengthInt)))
268 {
269 return -EIO;;
270 }
271 }
272
273 udev = interface_to_usbdev (intf);
274 /* Check whether the USB-Device Supports remote Wake-Up */
275 if(USB_CONFIG_ATT_WAKEUP & udev->actconfig->desc.bmAttributes)
276 {
277 /* If Suspend then only support dynamic suspend */
278 if(psAdapter->bDoSuspend)
279 {
280 udev->autosuspend_delay = 0;
281 intf->needs_remote_wakeup = 1;
282#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
283 udev->autosuspend_disabled = 0;
284#else
285 usb_enable_autosuspend(udev);
286#endif
287 device_init_wakeup(&intf->dev,1);
288#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
289 usb_autopm_disable(intf);
290#endif
291 INIT_WORK(&psIntfAdapter->usbSuspendWork, putUsbSuspend);
292 BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Enabling USB Auto-Suspend\n");
293 }
294 else
295 {
296 intf->needs_remote_wakeup = 0;
297#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
298 udev->autosuspend_disabled = 1;
299#else
300 usb_disable_autosuspend(udev);
301#endif
302 }
303 }
304
305 psAdapter->stDebugState.subtype[DBG_TYPE_INITEXIT] = 0x0;
306 return retval;
307}
308
309static void usbbcm_disconnect (struct usb_interface *intf)
310{
311 PS_INTERFACE_ADAPTER psIntfAdapter = NULL;
312 PMINI_ADAPTER psAdapter = NULL;
313 struct usb_device *udev = NULL;
314 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
315
316 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Usb disconnected");
317 if(intf == NULL)
318 {
319 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "intf pointer is NULL");
320 return;
321 }
322 psIntfAdapter = usb_get_intfdata(intf);
323 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "psIntfAdapter 0x%x",(unsigned int)psIntfAdapter);
324 if(psIntfAdapter == NULL)
325 {
326 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "InterfaceAdapter pointer is NULL");
327 return;
328 }
329 psAdapter = psIntfAdapter->psAdapter;
330 if(psAdapter->bDoSuspend)
331 intf->needs_remote_wakeup = 0;
332
333 psAdapter->device_removed = TRUE ;
334 usb_set_intfdata(intf, NULL);
335 InterfaceAdapterFree(psIntfAdapter);
336 udev = interface_to_usbdev (intf);
337 usb_put_dev(udev);
338 usb_deregister_dev (intf, &usbbcm_class);
339}
340
341
342static __inline int AllocUsbCb(PS_INTERFACE_ADAPTER psIntfAdapter)
343{
344 int i = 0;
345 for(i = 0; i < MAXIMUM_USB_TCB; i++)
346 {
347 if((psIntfAdapter->asUsbTcb[i].urb =
348 usb_alloc_urb(0, GFP_KERNEL)) == NULL)
349 {
350 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cant allocate Tx urb for index %d", i);
351 return -ENOMEM;
352 }
353 }
354
355 for(i = 0; i < MAXIMUM_USB_RCB; i++)
356 {
357 if ((psIntfAdapter->asUsbRcb[i].urb =
358 usb_alloc_urb(0, GFP_KERNEL)) == NULL)
359 {
360 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cant allocate Rx urb for index %d", i);
361 return -ENOMEM;
362 }
363 if((psIntfAdapter->asUsbRcb[i].urb->transfer_buffer =
364 kmalloc(MAX_DATA_BUFFER_SIZE, GFP_KERNEL)) == NULL)
365 {
366 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cant allocate Rx buffer for index %d", i);
367 return -ENOMEM;
368 }
369 psIntfAdapter->asUsbRcb[i].urb->transfer_buffer_length = MAX_DATA_BUFFER_SIZE;
370 }
371 return 0;
372}
373
374
375
376static int device_run(PS_INTERFACE_ADAPTER psIntfAdapter)
377{
378 INT value = 0;
379 UINT status = STATUS_SUCCESS;
380
381 status = InitCardAndDownloadFirmware(psIntfAdapter->psAdapter);
382 if(status != STATUS_SUCCESS)
383 {
384 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "InitCardAndDownloadFirmware failed.\n");
385 return status;
386 }
387 if(TRUE == psIntfAdapter->psAdapter->fw_download_done)
388 {
389
390 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Sending first interrupt URB down......");
391 if(StartInterruptUrb(psIntfAdapter))
392 {
393 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Cannot send interrupt in URB");
394 }
395 //now register the cntrl interface.
396 //after downloading the f/w waiting for 5 sec to get the mailbox interrupt.
397
398 psIntfAdapter->psAdapter->waiting_to_fw_download_done = FALSE;
399 value = wait_event_timeout(psIntfAdapter->psAdapter->ioctl_fw_dnld_wait_queue,
400 psIntfAdapter->psAdapter->waiting_to_fw_download_done, 5*HZ);
401
402 if(value == 0)
403 {
404 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Mailbox Interrupt has not reached to Driver..");
405 }
406 else
407 {
408 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Got the mailbox interrupt ...Registering control interface...\n ");
409 }
410 if(register_control_device_interface(psIntfAdapter->psAdapter) < 0)
411 {
412 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Register Control Device failed...");
413 return -EIO;
414 }
415 }
416 return 0;
417}
418
419#if 0
420static void print_usb_interface_desc(struct usb_interface_descriptor *usb_intf_desc)
421{
422 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "**************** INTERFACE DESCRIPTOR *********************");
423 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bLength: %x", usb_intf_desc->bLength);
424 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bDescriptorType: %x", usb_intf_desc->bDescriptorType);
425 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterfaceNumber: %x", usb_intf_desc->bInterfaceNumber);
426 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bAlternateSetting: %x", usb_intf_desc->bAlternateSetting);
427 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bNumEndpoints: %x", usb_intf_desc->bNumEndpoints);
428 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterfaceClass: %x", usb_intf_desc->bInterfaceClass);
429 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterfaceSubClass: %x", usb_intf_desc->bInterfaceSubClass);
430 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterfaceProtocol: %x", usb_intf_desc->bInterfaceProtocol);
431 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "iInterface :%x\n",usb_intf_desc->iInterface);
432}
433static void print_usb_endpoint_descriptor(struct usb_endpoint_descriptor *usb_ep_desc)
434{
435 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "**************** ENDPOINT DESCRIPTOR *********************");
436 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bLength :%x ", usb_ep_desc->bLength);
437 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bDescriptorType :%x ", usb_ep_desc->bDescriptorType);
438 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bEndpointAddress :%x ", usb_ep_desc->bEndpointAddress);
439 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bmAttributes :%x ", usb_ep_desc->bmAttributes);
440 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "wMaxPacketSize :%x ",usb_ep_desc->wMaxPacketSize);
441 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterval :%x ",usb_ep_desc->bInterval);
442}
443
444#endif
445
446static inline int bcm_usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
447{
448 return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
449}
450
451static inline int bcm_usb_endpoint_type(const struct usb_endpoint_descriptor *epd)
452{
453 return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
454}
455
456static inline int bcm_usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
457{
458 return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
459}
460
461static inline int bcm_usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
462{
463 return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
464}
465
466static inline int bcm_usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
467{
468 return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
469 USB_ENDPOINT_XFER_BULK);
470}
471
472static inline int bcm_usb_endpoint_xfer_control(const struct usb_endpoint_descriptor *epd)
473{
474 return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
475 USB_ENDPOINT_XFER_CONTROL);
476}
477
478static inline int bcm_usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
479{
480 return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
481 USB_ENDPOINT_XFER_INT);
482}
483
484static inline int bcm_usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd)
485{
486 return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
487 USB_ENDPOINT_XFER_ISOC);
488}
489
490static inline int bcm_usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
491{
492 return (bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_in(epd));
493}
494
495static inline int bcm_usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
496{
497 return (bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_out(epd));
498}
499
500static inline int bcm_usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
501{
502 return (bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_in(epd));
503}
504
505static inline int bcm_usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
506{
507 return (bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_out(epd));
508}
509
510static inline int bcm_usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
511{
512 return (bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_in(epd));
513}
514
515static inline int bcm_usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
516{
517 return (bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_out(epd));
518}
519
520INT InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter)
521{
522 struct usb_host_interface *iface_desc;
523 struct usb_endpoint_descriptor *endpoint;
524 size_t buffer_size;
525 ULONG value;
526 INT retval = 0;
527 INT usedIntOutForBulkTransfer = 0 ;
528 BOOLEAN bBcm16 = FALSE;
529 UINT uiData = 0;
530
531 if(psIntfAdapter == NULL)
532 {
533 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Interface Adapter is NULL");
534 return -EINVAL;
535 }
536 /* Store the usb dev into interface adapter */
537 psIntfAdapter->udev = usb_get_dev(interface_to_usbdev(
538 psIntfAdapter->interface));
539
540 if((psIntfAdapter->udev->speed == USB_SPEED_HIGH))
541 {
542 psIntfAdapter->bHighSpeedDevice = TRUE ;
543 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "MODEM IS CONFIGURED TO HIGH_SPEED ");
544 }
545 else
546 {
547 psIntfAdapter->bHighSpeedDevice = FALSE ;
548 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "MODEM IS CONFIGURED TO FULL_SPEED ");
549 }
550
551 psIntfAdapter->psAdapter->interface_rdm = BcmRDM;
552 psIntfAdapter->psAdapter->interface_wrm = BcmWRM;
553
554 if(rdmalt(psIntfAdapter->psAdapter, CHIP_ID_REG, (PUINT)&(psIntfAdapter->psAdapter->chip_id), sizeof(UINT)) < 0)
555 {
556 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "CHIP ID Read Failed\n");
557 return STATUS_FAILURE;
558 }
559 if(0xbece3200==(psIntfAdapter->psAdapter->chip_id&~(0xF0)))
560 {
561 psIntfAdapter->psAdapter->chip_id=(psIntfAdapter->psAdapter->chip_id&~(0xF0));
562 }
563
564 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "First RDM Chip ID 0x%lx\n", psIntfAdapter->psAdapter->chip_id);
565
566 iface_desc = psIntfAdapter->interface->cur_altsetting;
567 //print_usb_interface_desc(&(iface_desc->desc));
568
569 if(psIntfAdapter->psAdapter->chip_id == T3B)
570 {
571
572 //
573 //T3B device will have EEPROM,check if EEPROM is proper and BCM16 can be done or not.
574 //
575 BeceemEEPROMBulkRead(psIntfAdapter->psAdapter,&uiData,0x0,4);
576 if(uiData == BECM)
577 {
578 bBcm16 = TRUE;
579 }
580 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Number of Altsetting aviailable for This Modem 0x%x\n", psIntfAdapter->interface->num_altsetting);
581 if(bBcm16 == TRUE)
582 {
583 //selecting alternate setting one as a default setting for High Speed modem.
584 if(psIntfAdapter->bHighSpeedDevice)
585 retval= usb_set_interface(psIntfAdapter->udev,DEFAULT_SETTING_0,ALTERNATE_SETTING_1);
586 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "BCM16 is Applicable on this dongle");
587 if(retval || (psIntfAdapter->bHighSpeedDevice == FALSE))
588 {
589 usedIntOutForBulkTransfer = EP2 ;
590 endpoint = &iface_desc->endpoint[EP2].desc;
591 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Interface altsetting got failed or Moemd is configured to FS.hence will work on default setting 0 \n");
592 /*
593 If Modem is high speed device EP2 should be INT OUT End point
594 If Mode is FS then EP2 should be bulk end point
595 */
596 if(((psIntfAdapter->bHighSpeedDevice ==TRUE ) && (bcm_usb_endpoint_is_int_out(endpoint)== FALSE))
597 ||((psIntfAdapter->bHighSpeedDevice == FALSE)&& (bcm_usb_endpoint_is_bulk_out(endpoint)== FALSE)))
598 {
599 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Configuring the EEPROM ");
600 //change the EP2, EP4 to INT OUT end point
601 ConfigureEndPointTypesThroughEEPROM(psIntfAdapter->psAdapter);
602
603 /*
604 It resets the device and if any thing gets changed in USB descriptor it will show fail and
605 re-enumerate the device
606 */
607 retval = usb_reset_device(psIntfAdapter->udev);
608 if(retval)
609 {
610 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "reset got failed. hence Re-enumerating the device \n");
611 return retval ;
612 }
613
614 }
615 if((psIntfAdapter->bHighSpeedDevice == FALSE) && bcm_usb_endpoint_is_bulk_out(endpoint))
616 {
617 // Once BULK is selected in FS mode. Revert it back to INT. Else USB_IF will fail.
618 UINT uiData = ntohl(EP2_CFG_INT);
619 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Reverting Bulk to INT as it is FS MODE");
620 BeceemEEPROMBulkWrite(psIntfAdapter->psAdapter,(PUCHAR)&uiData,0x136,4,TRUE);
621 }
622 }
623 else
624 {
625 usedIntOutForBulkTransfer = EP4 ;
626 endpoint = &iface_desc->endpoint[EP4].desc;
627 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Choosing AltSetting as a default setting");
628 if( bcm_usb_endpoint_is_int_out(endpoint) == FALSE)
629 {
630 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, " Dongle does not have BCM16 Fix");
631 //change the EP2, EP4 to INT OUT end point and use EP4 in altsetting
632 ConfigureEndPointTypesThroughEEPROM(psIntfAdapter->psAdapter);
633
634 /*
635 It resets the device and if any thing gets changed in USB descriptor it will show fail and
636 re-enumerate the device
637 */
638 retval = usb_reset_device(psIntfAdapter->udev);
639 if(retval)
640 {
641 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "reset got failed. hence Re-enumerating the device \n");
642 return retval ;
643 }
644
645 }
646 }
647 }
648 }
649
650 iface_desc = psIntfAdapter->interface->cur_altsetting;
651 //print_usb_interface_desc(&(iface_desc->desc));
652 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Current number of endpoints :%x \n", iface_desc->desc.bNumEndpoints);
653 for (value = 0; value < iface_desc->desc.bNumEndpoints; ++value)
654 {
655 endpoint = &iface_desc->endpoint[value].desc;
656 //print_usb_endpoint_descriptor(endpoint);
657
658 if (!psIntfAdapter->sBulkIn.bulk_in_endpointAddr && bcm_usb_endpoint_is_bulk_in(endpoint))
659 {
660 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
661 psIntfAdapter->sBulkIn.bulk_in_size = buffer_size;
662 psIntfAdapter->sBulkIn.bulk_in_endpointAddr =
663 endpoint->bEndpointAddress;
664 psIntfAdapter->sBulkIn.bulk_in_pipe =
665 usb_rcvbulkpipe(psIntfAdapter->udev,
666 psIntfAdapter->sBulkIn.bulk_in_endpointAddr);
667 }
668
669 if (!psIntfAdapter->sBulkOut.bulk_out_endpointAddr && bcm_usb_endpoint_is_bulk_out(endpoint))
670 {
671
672 psIntfAdapter->sBulkOut.bulk_out_endpointAddr =
673 endpoint->bEndpointAddress;
674 psIntfAdapter->sBulkOut.bulk_out_pipe =
675 usb_sndbulkpipe(psIntfAdapter->udev,
676 psIntfAdapter->sBulkOut.bulk_out_endpointAddr);
677 }
678
679 if (!psIntfAdapter->sIntrIn.int_in_endpointAddr && bcm_usb_endpoint_is_int_in(endpoint))
680 {
681 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
682 psIntfAdapter->sIntrIn.int_in_size = buffer_size;
683 psIntfAdapter->sIntrIn.int_in_endpointAddr =
684 endpoint->bEndpointAddress;
685 psIntfAdapter->sIntrIn.int_in_interval = endpoint->bInterval;
686 psIntfAdapter->sIntrIn.int_in_buffer =
687 kmalloc(buffer_size, GFP_KERNEL);
688 if (!psIntfAdapter->sIntrIn.int_in_buffer) {
689 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Could not allocate interrupt_in_buffer");
690 return -EINVAL;
691 }
692 //psIntfAdapter->sIntrIn.int_in_pipe =
693 }
694
695 if (!psIntfAdapter->sIntrOut.int_out_endpointAddr && bcm_usb_endpoint_is_int_out(endpoint))
696 {
697
698 if( !psIntfAdapter->sBulkOut.bulk_out_endpointAddr &&
699 (psIntfAdapter->psAdapter->chip_id == T3B) && (value == usedIntOutForBulkTransfer))
700 {
701 //use first intout end point as a bulk out end point
702 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
703 psIntfAdapter->sBulkOut.bulk_out_size = buffer_size;
704 //printk("\nINT OUT Endpoing buffer size :%x endpoint :%x\n", buffer_size, value +1);
705 psIntfAdapter->sBulkOut.bulk_out_endpointAddr =
706 endpoint->bEndpointAddress;
707 psIntfAdapter->sBulkOut.bulk_out_pipe =
708 usb_sndintpipe(psIntfAdapter->udev,
709 psIntfAdapter->sBulkOut.bulk_out_endpointAddr);
710 psIntfAdapter->sBulkOut.int_out_interval = endpoint->bInterval;
711
712 }
713 else if(value == EP6)
714 {
715 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
716 psIntfAdapter->sIntrOut.int_out_size = buffer_size;
717 psIntfAdapter->sIntrOut.int_out_endpointAddr =
718 endpoint->bEndpointAddress;
719 psIntfAdapter->sIntrOut.int_out_interval = endpoint->bInterval;
720 psIntfAdapter->sIntrOut.int_out_buffer= kmalloc(buffer_size,
721 GFP_KERNEL);
722 if (!psIntfAdapter->sIntrOut.int_out_buffer)
723 {
724 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Could not allocate interrupt_out_buffer");
725 return -EINVAL;
726 }
727 }
728 }
729 }
730 usb_set_intfdata(psIntfAdapter->interface, psIntfAdapter);
731 retval = usb_register_dev(psIntfAdapter->interface, &usbbcm_class);
732 if(retval)
733 {
734 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "usb register dev failed = %d", retval);
735 psIntfAdapter->psAdapter->bUsbClassDriverRegistered = FALSE;
736 return retval;
737 }
738 else
739 {
740 psIntfAdapter->psAdapter->bUsbClassDriverRegistered = TRUE;
741 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "usb dev registered");
742 }
743
744 psIntfAdapter->psAdapter->bcm_file_download = InterfaceFileDownload;
745 psIntfAdapter->psAdapter->bcm_file_readback_from_chip =
746 InterfaceFileReadbackFromChip;
747 psIntfAdapter->psAdapter->interface_transmit = InterfaceTransmitPacket;
748
749 retval = CreateInterruptUrb(psIntfAdapter);
750
751 if(retval)
752 {
753 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cannot create interrupt urb");
754 return retval;
755 }
756
757 retval = AllocUsbCb(psIntfAdapter);
758 if(retval)
759 {
760 return retval;
761 }
762
763
764 retval = device_run(psIntfAdapter);
765 if(retval)
766 {
767 return retval;
768 }
769
770
771 return 0;
772}
773int InterfaceSuspend (struct usb_interface *intf, pm_message_t message)
774{
775 PS_INTERFACE_ADAPTER psIntfAdapter = usb_get_intfdata(intf);
776 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "=================================\n");
777 //Bcm_kill_all_URBs(psIntfAdapter);
778 psIntfAdapter->bSuspended = TRUE;
779
780 if(TRUE == psIntfAdapter->bPreparingForBusSuspend)
781 {
782 psIntfAdapter->bPreparingForBusSuspend = FALSE;
783
784 if(psIntfAdapter->psAdapter->LinkStatus == LINKUP_DONE)
785 {
786 psIntfAdapter->psAdapter->IdleMode = TRUE ;
787 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Host Entered in PMU Idle Mode..");
788 }
789 else
790 {
791 psIntfAdapter->psAdapter->bShutStatus = TRUE;
792 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Host Entered in PMU Shutdown Mode..");
793 }
794 }
795 psIntfAdapter->psAdapter->bPreparingForLowPowerMode = FALSE;
796
797 //Signaling the control pkt path
798 wake_up(&psIntfAdapter->psAdapter->lowpower_mode_wait_queue);
799
800 return 0;
801}
802int InterfaceResume (struct usb_interface *intf)
803{
804 PS_INTERFACE_ADAPTER psIntfAdapter = usb_get_intfdata(intf);
805 printk("=================================\n");
806 mdelay(100);
807#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
808 intf->pm_usage_cnt =1 ;
809#endif
810 psIntfAdapter->bSuspended = FALSE;
811
812 StartInterruptUrb(psIntfAdapter);
813 InterfaceRx(psIntfAdapter);
814 return 0;
815}
816int InterfacePreReset(struct usb_interface *intf)
817{
818 printk("====================>");
819 return STATUS_SUCCESS;
820}
821int InterfacePostReset(struct usb_interface *intf)
822{
823 printk("Do Post chip reset setting here if it is required");
824 return STATUS_SUCCESS;
825}
826static struct usb_driver usbbcm_driver = {
827 .name = "usbbcm",
828 .probe = usbbcm_device_probe,
829 .disconnect = usbbcm_disconnect,
830 .suspend = InterfaceSuspend,
831 .resume = InterfaceResume,
832 .pre_reset=InterfacePreReset,
833 .post_reset=InterfacePostReset,
834 .id_table = InterfaceUsbtable,
835 .supports_autosuspend = 1,
836};
837
838
839/*
840Function: InterfaceInitialize
841
842Description: This is the hardware specific initialization Function.
843 Registering the driver with NDIS , other device specific NDIS
844 and hardware initializations are done here.
845
846Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context
847
848
849Return: BCM_STATUS_SUCCESS - If Initialization of the
850 HW Interface was successful.
851 Other - If an error occured.
852*/
853INT InterfaceInitialize(void)
854{
855// BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Registering Usb driver!!");
856 return usb_register(&usbbcm_driver);
857}
858
859INT InterfaceExit(void)
860{
861 //PMINI_ADAPTER psAdapter = NULL;
862 int status = 0;
863
864 //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Deregistering Usb driver!!");
865 usb_deregister(&usbbcm_driver);
866 return status;
867}
868MODULE_LICENSE ("GPL");