Merge branch 'perf/urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic...
[pandora-kernel.git] / drivers / staging / bcm / InterfaceInit.c
1 #include "headers.h"
2
3 static 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
12 VOID 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
61 static int usbbcm_open(struct inode *inode, struct file *file)
62 {
63         return 0;
64 }
65
66 static int usbbcm_release(struct inode *inode, struct file *file)
67 {
68         return 0;
69 }
70
71 static ssize_t usbbcm_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
72 {
73         return 0;
74 }
75
76 static ssize_t usbbcm_write(struct file *file, const char __user *user_buffer, size_t count, loff_t *ppos)
77 {
78         return 0;
79 }
80
81
82 VOID 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
160 static 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         .llseek = no_llseek,
167 };
168
169 static struct usb_class_driver usbbcm_class = {
170     .name =             "usbbcm",
171     .fops =             &usbbcm_fops,
172     .minor_base =   BCM_USB_MINOR_BASE,
173 };
174
175 static int
176 usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id)
177 {
178         int retval =0 ;
179         PMINI_ADAPTER psAdapter = NULL;
180         PS_INTERFACE_ADAPTER psIntfAdapter = NULL;
181         struct usb_device      *udev = NULL;
182
183 //      BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Usbbcm probe!!");
184         if((intf == NULL) || (id == NULL))
185         {
186         //      BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "intf or id is NULL");
187                 return -EINVAL;
188         }
189
190         /* Allocate Adapter structure */
191         if((psAdapter = kzalloc(sizeof(MINI_ADAPTER), GFP_KERNEL)) == NULL)
192         {
193                 BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0, "Out of memory");
194                 return -ENOMEM;
195         }
196
197     /* Init default driver debug state */
198
199     psAdapter->stDebugState.debug_level = DBG_LVL_CURR;
200         psAdapter->stDebugState.type = DBG_TYPE_INITEXIT;
201         memset (psAdapter->stDebugState.subtype, 0, sizeof (psAdapter->stDebugState.subtype));
202
203     /* Technically, one can start using BCM_DEBUG_PRINT after this point.
204          * However, realize that by default the Type/Subtype bitmaps are all zero now;
205          * so no prints will actually appear until the TestApp turns on debug paths via
206          * the ioctl(); so practically speaking, in early init, no logging happens.
207          *
208          * A solution (used below): we explicitly set the bitmaps to 1 for Type=DBG_TYPE_INITEXIT
209          * and ALL subtype's of the same. Now all bcm debug statements get logged, enabling debug
210          * during early init.
211          * Further, we turn this OFF once init_module() completes.
212          */
213
214     psAdapter->stDebugState.subtype[DBG_TYPE_INITEXIT] = 0xff;
215         BCM_SHOW_DEBUG_BITMAP(psAdapter);
216
217         retval = InitAdapter(psAdapter);
218         if(retval)
219         {
220                 BCM_DEBUG_PRINT (psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "InitAdapter Failed\n");
221                 AdapterFree(psAdapter);
222                 return retval;
223         }
224
225         /* Allocate interface adapter structure */
226         if((psAdapter->pvInterfaceAdapter =
227                 kmalloc(sizeof(S_INTERFACE_ADAPTER), GFP_KERNEL)) == NULL)
228         {
229                 BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0, "Out of memory");
230                 AdapterFree (psAdapter);
231                 return -ENOMEM;
232         }
233         memset(psAdapter->pvInterfaceAdapter, 0, sizeof(S_INTERFACE_ADAPTER));
234
235         psIntfAdapter = InterfaceAdapterGet(psAdapter);
236         psIntfAdapter->psAdapter = psAdapter;
237
238         /* Store usb interface in Interface Adapter */
239         psIntfAdapter->interface = intf;
240         usb_set_intfdata(intf, psIntfAdapter);
241
242         BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "psIntfAdapter 0x%p",psIntfAdapter);
243         retval = InterfaceAdapterInit(psIntfAdapter);
244         if(retval)
245         {
246                 /* If the Firmware/Cfg File is not present
247                  * then return success, let the application
248                  * download the files.
249                  */
250                 if(-ENOENT == retval){
251                         BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "File Not Found, Use App to Download\n");
252                         return STATUS_SUCCESS;
253                 }
254                 BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "InterfaceAdapterInit Failed \n");
255                 usb_set_intfdata(intf, NULL);
256                 udev = interface_to_usbdev (intf);
257                 usb_put_dev(udev);
258                 if(psAdapter->bUsbClassDriverRegistered == TRUE)
259                                 usb_deregister_dev (intf, &usbbcm_class);
260                 InterfaceAdapterFree(psIntfAdapter);
261                 return retval ;
262         }
263         if(psAdapter->chip_id > T3)
264         {
265                 uint32_t uiNackZeroLengthInt=4;
266                 if(wrmalt(psAdapter, DISABLE_USB_ZERO_LEN_INT, &uiNackZeroLengthInt, sizeof(uiNackZeroLengthInt)))
267                 {
268                         return -EIO;;
269                 }
270         }
271
272         udev = interface_to_usbdev (intf);
273         /* Check whether the USB-Device Supports remote Wake-Up */
274         if(USB_CONFIG_ATT_WAKEUP & udev->actconfig->desc.bmAttributes)
275         {
276                 /* If Suspend then only support dynamic suspend */
277                 if(psAdapter->bDoSuspend)
278                 {
279 #ifdef CONFIG_PM
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 #endif
294                 }
295                 else
296                 {
297                         intf->needs_remote_wakeup = 0;
298 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
299                         udev->autosuspend_disabled = 1;
300 #else
301                         usb_disable_autosuspend(udev);
302 #endif
303                 }
304         }
305
306     psAdapter->stDebugState.subtype[DBG_TYPE_INITEXIT] = 0x0;
307     return retval;
308 }
309
310 static void usbbcm_disconnect (struct usb_interface *intf)
311 {
312         PS_INTERFACE_ADAPTER psIntfAdapter = NULL;
313         PMINI_ADAPTER psAdapter = NULL;
314         struct usb_device       *udev = NULL;
315     PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
316
317         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Usb disconnected");
318         if(intf == NULL)
319         {
320                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "intf pointer is NULL");
321                 return;
322         }
323         psIntfAdapter = usb_get_intfdata(intf);
324         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "psIntfAdapter 0x%p",psIntfAdapter);
325         if(psIntfAdapter == NULL)
326         {
327                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "InterfaceAdapter pointer is NULL");
328                 return;
329         }
330         psAdapter = psIntfAdapter->psAdapter;
331         if(psAdapter->bDoSuspend)
332                 intf->needs_remote_wakeup = 0;
333
334         psAdapter->device_removed = TRUE ;
335         usb_set_intfdata(intf, NULL);
336         InterfaceAdapterFree(psIntfAdapter);
337         udev = interface_to_usbdev (intf);
338         usb_put_dev(udev);
339         usb_deregister_dev (intf, &usbbcm_class);
340 }
341
342
343 static __inline int AllocUsbCb(PS_INTERFACE_ADAPTER psIntfAdapter)
344 {
345         int i = 0;
346         for(i = 0; i < MAXIMUM_USB_TCB; i++)
347         {
348                 if((psIntfAdapter->asUsbTcb[i].urb =
349                                 usb_alloc_urb(0, GFP_KERNEL)) == NULL)
350                 {
351                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cant allocate Tx urb for index %d", i);
352                         return -ENOMEM;
353                 }
354         }
355
356         for(i = 0; i < MAXIMUM_USB_RCB; i++)
357         {
358                 if ((psIntfAdapter->asUsbRcb[i].urb =
359                                 usb_alloc_urb(0, GFP_KERNEL)) == NULL)
360                 {
361                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cant allocate Rx urb for index %d", i);
362                         return -ENOMEM;
363                 }
364                 if((psIntfAdapter->asUsbRcb[i].urb->transfer_buffer =
365                         kmalloc(MAX_DATA_BUFFER_SIZE, GFP_KERNEL)) == NULL)
366                 {
367                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cant allocate Rx buffer for index %d", i);
368                         return -ENOMEM;
369                 }
370                 psIntfAdapter->asUsbRcb[i].urb->transfer_buffer_length = MAX_DATA_BUFFER_SIZE;
371         }
372         return 0;
373 }
374
375
376
377 static int device_run(PS_INTERFACE_ADAPTER psIntfAdapter)
378 {
379         INT value = 0;
380         UINT status = STATUS_SUCCESS;
381
382         status = InitCardAndDownloadFirmware(psIntfAdapter->psAdapter);
383         if(status != STATUS_SUCCESS)
384         {
385                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "InitCardAndDownloadFirmware failed.\n");
386                 return status;
387         }
388         if(TRUE == psIntfAdapter->psAdapter->fw_download_done)
389         {
390
391                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Sending first interrupt URB down......");
392                 if(StartInterruptUrb(psIntfAdapter))
393                 {
394                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Cannot send interrupt in URB");
395                 }
396                 //now register the cntrl interface.
397                 //after downloading the f/w waiting for 5 sec to get the mailbox interrupt.
398
399                 psIntfAdapter->psAdapter->waiting_to_fw_download_done = FALSE;
400                 value = wait_event_timeout(psIntfAdapter->psAdapter->ioctl_fw_dnld_wait_queue,
401                                         psIntfAdapter->psAdapter->waiting_to_fw_download_done, 5*HZ);
402
403                 if(value == 0)
404                 {
405                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Mailbox Interrupt has not reached to Driver..");
406                 }
407                 else
408                 {
409                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Got the mailbox interrupt ...Registering control interface...\n ");
410                 }
411                 if(register_control_device_interface(psIntfAdapter->psAdapter) < 0)
412                 {
413                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Register Control Device failed...");
414                         return -EIO;
415                 }
416         }
417         return 0;
418 }
419
420 #if 0
421 static void     print_usb_interface_desc(struct usb_interface_descriptor *usb_intf_desc)
422 {
423                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "**************** INTERFACE DESCRIPTOR *********************");
424                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bLength: %x", usb_intf_desc->bLength);
425                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bDescriptorType: %x", usb_intf_desc->bDescriptorType);
426                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterfaceNumber: %x", usb_intf_desc->bInterfaceNumber);
427                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bAlternateSetting: %x", usb_intf_desc->bAlternateSetting);
428                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bNumEndpoints: %x", usb_intf_desc->bNumEndpoints);
429                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterfaceClass: %x", usb_intf_desc->bInterfaceClass);
430                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterfaceSubClass: %x", usb_intf_desc->bInterfaceSubClass);
431                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterfaceProtocol: %x", usb_intf_desc->bInterfaceProtocol);
432                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "iInterface :%x\n",usb_intf_desc->iInterface);
433 }
434 static void     print_usb_endpoint_descriptor(struct usb_endpoint_descriptor *usb_ep_desc)
435 {
436                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "**************** ENDPOINT DESCRIPTOR *********************");
437                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bLength  :%x ", usb_ep_desc->bLength);
438                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bDescriptorType  :%x ", usb_ep_desc->bDescriptorType);
439                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bEndpointAddress  :%x ", usb_ep_desc->bEndpointAddress);
440                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bmAttributes  :%x ", usb_ep_desc->bmAttributes);
441                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "wMaxPacketSize  :%x ",usb_ep_desc->wMaxPacketSize);
442                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterval  :%x ",usb_ep_desc->bInterval);
443 }
444
445 #endif
446
447 static inline int bcm_usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
448 {
449         return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
450 }
451
452 static inline int bcm_usb_endpoint_type(const struct usb_endpoint_descriptor *epd)
453 {
454         return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
455 }
456
457 static inline int bcm_usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
458 {
459         return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
460 }
461
462 static inline int bcm_usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
463 {
464         return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
465 }
466
467 static inline int bcm_usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
468 {
469         return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
470                 USB_ENDPOINT_XFER_BULK);
471 }
472
473 static inline int bcm_usb_endpoint_xfer_control(const struct usb_endpoint_descriptor *epd)
474 {
475         return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
476                 USB_ENDPOINT_XFER_CONTROL);
477 }
478
479 static inline int bcm_usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
480 {
481         return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
482                 USB_ENDPOINT_XFER_INT);
483 }
484
485 static inline int bcm_usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd)
486 {
487         return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
488                 USB_ENDPOINT_XFER_ISOC);
489 }
490
491 static inline int bcm_usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
492 {
493         return (bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_in(epd));
494 }
495
496 static inline int bcm_usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
497 {
498         return (bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_out(epd));
499 }
500
501 static inline int bcm_usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
502 {
503         return (bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_in(epd));
504 }
505
506 static inline int bcm_usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
507 {
508         return (bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_out(epd));
509 }
510
511 static inline int bcm_usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
512 {
513         return (bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_in(epd));
514 }
515
516 static inline int bcm_usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
517 {
518         return (bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_out(epd));
519 }
520
521 INT InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter)
522 {
523         struct usb_host_interface *iface_desc;
524         struct usb_endpoint_descriptor *endpoint;
525         size_t buffer_size;
526         ULONG value;
527         INT retval = 0;
528         INT usedIntOutForBulkTransfer = 0 ;
529         BOOLEAN bBcm16 = FALSE;
530         UINT uiData = 0;
531
532         /* Store the usb dev into interface adapter */
533         psIntfAdapter->udev = usb_get_dev(interface_to_usbdev(
534                                                                 psIntfAdapter->interface));
535
536         if((psIntfAdapter->udev->speed == USB_SPEED_HIGH))
537         {
538                 psIntfAdapter->bHighSpeedDevice = TRUE ;
539                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "MODEM IS CONFIGURED TO HIGH_SPEED ");
540         }
541         else
542         {
543                 psIntfAdapter->bHighSpeedDevice = FALSE ;
544                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "MODEM IS CONFIGURED TO FULL_SPEED ");
545         }
546
547         psIntfAdapter->psAdapter->interface_rdm = BcmRDM;
548         psIntfAdapter->psAdapter->interface_wrm = BcmWRM;
549
550         if(rdmalt(psIntfAdapter->psAdapter, CHIP_ID_REG, (PUINT)&(psIntfAdapter->psAdapter->chip_id), sizeof(UINT)) < 0)
551         {
552                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "CHIP ID Read Failed\n");
553                 return STATUS_FAILURE;
554         }
555     if(0xbece3200==(psIntfAdapter->psAdapter->chip_id&~(0xF0)))
556         {
557                 psIntfAdapter->psAdapter->chip_id=(psIntfAdapter->psAdapter->chip_id&~(0xF0));
558         }
559
560         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "First RDM Chip ID 0x%lx\n", psIntfAdapter->psAdapter->chip_id);
561
562     iface_desc = psIntfAdapter->interface->cur_altsetting;
563         //print_usb_interface_desc(&(iface_desc->desc));
564
565         if(psIntfAdapter->psAdapter->chip_id == T3B)
566         {
567
568                 //
569                 //T3B device will have EEPROM,check if EEPROM is proper and BCM16 can be done or not.
570                 //
571                 BeceemEEPROMBulkRead(psIntfAdapter->psAdapter,&uiData,0x0,4);
572                 if(uiData == BECM)
573                 {
574                         bBcm16 = TRUE;
575                 }
576                 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);
577                 if(bBcm16 == TRUE)
578                 {
579                         //selecting alternate setting one as a default setting for High Speed  modem.
580                         if(psIntfAdapter->bHighSpeedDevice)
581                                 retval= usb_set_interface(psIntfAdapter->udev,DEFAULT_SETTING_0,ALTERNATE_SETTING_1);
582                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "BCM16 is Applicable on this dongle");
583                         if(retval || (psIntfAdapter->bHighSpeedDevice == FALSE))
584                         {
585                                 usedIntOutForBulkTransfer = EP2 ;
586                                 endpoint = &iface_desc->endpoint[EP2].desc;
587                                 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");
588                                 /*
589                                 If Modem is high speed device EP2 should be INT OUT End point
590                                 If Mode is FS then EP2 should be bulk end point
591                                 */
592                                 if(((psIntfAdapter->bHighSpeedDevice ==TRUE ) && (bcm_usb_endpoint_is_int_out(endpoint)== FALSE))
593                                         ||((psIntfAdapter->bHighSpeedDevice == FALSE)&& (bcm_usb_endpoint_is_bulk_out(endpoint)== FALSE)))
594                                 {
595                                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Configuring the EEPROM ");
596                                         //change the EP2, EP4 to INT OUT end point
597                                         ConfigureEndPointTypesThroughEEPROM(psIntfAdapter->psAdapter);
598
599                                         /*
600                                         It resets the device and if any thing gets changed in USB descriptor it will show fail and
601                                         re-enumerate the device
602                                         */
603                                         retval = usb_reset_device(psIntfAdapter->udev);
604                                         if(retval)
605                                         {
606                                                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "reset got failed. hence Re-enumerating the device \n");
607                                                 return retval ;
608                                         }
609
610                                 }
611                                 if((psIntfAdapter->bHighSpeedDevice == FALSE) && bcm_usb_endpoint_is_bulk_out(endpoint))
612                                 {
613                                         // Once BULK is selected in FS mode. Revert it back to INT. Else USB_IF will fail.
614                                         UINT _uiData = ntohl(EP2_CFG_INT);
615                                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Reverting Bulk to INT as it is FS MODE");
616                                         BeceemEEPROMBulkWrite(psIntfAdapter->psAdapter,(PUCHAR)&_uiData,0x136,4,TRUE);
617                                 }
618                         }
619                         else
620                         {
621                                 usedIntOutForBulkTransfer = EP4 ;
622                                 endpoint = &iface_desc->endpoint[EP4].desc;
623                                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Choosing AltSetting as a default setting");
624                                 if( bcm_usb_endpoint_is_int_out(endpoint) == FALSE)
625                                 {
626                                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, " Dongle does not have BCM16 Fix");
627                                         //change the EP2, EP4 to INT OUT end point and use EP4 in altsetting
628                                         ConfigureEndPointTypesThroughEEPROM(psIntfAdapter->psAdapter);
629
630                                         /*
631                                         It resets the device and if any thing gets changed in USB descriptor it will show fail and
632                                         re-enumerate the device
633                                         */
634                                         retval = usb_reset_device(psIntfAdapter->udev);
635                                         if(retval)
636                                         {
637                                                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "reset got failed. hence Re-enumerating the device \n");
638                                                 return retval ;
639                                         }
640
641                                 }
642                         }
643                 }
644         }
645
646         iface_desc = psIntfAdapter->interface->cur_altsetting;
647         //print_usb_interface_desc(&(iface_desc->desc));
648         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Current number of endpoints :%x \n", iface_desc->desc.bNumEndpoints);
649     for (value = 0; value < iface_desc->desc.bNumEndpoints; ++value)
650         {
651         endpoint = &iface_desc->endpoint[value].desc;
652                 //print_usb_endpoint_descriptor(endpoint);
653
654         if (!psIntfAdapter->sBulkIn.bulk_in_endpointAddr && bcm_usb_endpoint_is_bulk_in(endpoint))
655         {
656             buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
657             psIntfAdapter->sBulkIn.bulk_in_size = buffer_size;
658             psIntfAdapter->sBulkIn.bulk_in_endpointAddr =
659                                                                 endpoint->bEndpointAddress;
660                 psIntfAdapter->sBulkIn.bulk_in_pipe =
661                                         usb_rcvbulkpipe(psIntfAdapter->udev,
662                                                                 psIntfAdapter->sBulkIn.bulk_in_endpointAddr);
663         }
664
665         if (!psIntfAdapter->sBulkOut.bulk_out_endpointAddr && bcm_usb_endpoint_is_bulk_out(endpoint))
666         {
667
668                         psIntfAdapter->sBulkOut.bulk_out_endpointAddr =
669                                                                                 endpoint->bEndpointAddress;
670                 psIntfAdapter->sBulkOut.bulk_out_pipe =
671                         usb_sndbulkpipe(psIntfAdapter->udev,
672                                         psIntfAdapter->sBulkOut.bulk_out_endpointAddr);
673         }
674
675         if (!psIntfAdapter->sIntrIn.int_in_endpointAddr && bcm_usb_endpoint_is_int_in(endpoint))
676         {
677             buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
678             psIntfAdapter->sIntrIn.int_in_size = buffer_size;
679             psIntfAdapter->sIntrIn.int_in_endpointAddr =
680                                                                 endpoint->bEndpointAddress;
681             psIntfAdapter->sIntrIn.int_in_interval = endpoint->bInterval;
682             psIntfAdapter->sIntrIn.int_in_buffer =
683                                                 kmalloc(buffer_size, GFP_KERNEL);
684             if (!psIntfAdapter->sIntrIn.int_in_buffer) {
685                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Could not allocate interrupt_in_buffer");
686                 return -EINVAL;
687             }
688                         //psIntfAdapter->sIntrIn.int_in_pipe =
689         }
690
691         if (!psIntfAdapter->sIntrOut.int_out_endpointAddr && bcm_usb_endpoint_is_int_out(endpoint))
692         {
693
694                         if( !psIntfAdapter->sBulkOut.bulk_out_endpointAddr &&
695                                 (psIntfAdapter->psAdapter->chip_id == T3B) && (value == usedIntOutForBulkTransfer))
696                         {
697                                 //use first intout end point as a bulk out end point
698                 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
699                 psIntfAdapter->sBulkOut.bulk_out_size = buffer_size;
700                                 //printk("\nINT OUT Endpoing buffer size :%x endpoint :%x\n", buffer_size, value +1);
701                                 psIntfAdapter->sBulkOut.bulk_out_endpointAddr =
702                                                                                 endpoint->bEndpointAddress;
703                         psIntfAdapter->sBulkOut.bulk_out_pipe =
704                                 usb_sndintpipe(psIntfAdapter->udev,
705                                         psIntfAdapter->sBulkOut.bulk_out_endpointAddr);
706                         psIntfAdapter->sBulkOut.int_out_interval = endpoint->bInterval;
707
708                         }
709                         else if(value == EP6)
710                         {
711                     buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
712                     psIntfAdapter->sIntrOut.int_out_size = buffer_size;
713                     psIntfAdapter->sIntrOut.int_out_endpointAddr =
714                                                                                 endpoint->bEndpointAddress;
715                     psIntfAdapter->sIntrOut.int_out_interval = endpoint->bInterval;
716                     psIntfAdapter->sIntrOut.int_out_buffer= kmalloc(buffer_size,
717                                                                                                                 GFP_KERNEL);
718                         if (!psIntfAdapter->sIntrOut.int_out_buffer)
719                                         {
720                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Could not allocate interrupt_out_buffer");
721                         return -EINVAL;
722             }
723         }
724     }
725         }
726     usb_set_intfdata(psIntfAdapter->interface, psIntfAdapter);
727     retval = usb_register_dev(psIntfAdapter->interface, &usbbcm_class);
728         if(retval)
729         {
730                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "usb register dev failed = %d", retval);
731                 psIntfAdapter->psAdapter->bUsbClassDriverRegistered = FALSE;
732                 return retval;
733         }
734         else
735         {
736                 psIntfAdapter->psAdapter->bUsbClassDriverRegistered = TRUE;
737                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "usb dev registered");
738         }
739
740         psIntfAdapter->psAdapter->bcm_file_download = InterfaceFileDownload;
741         psIntfAdapter->psAdapter->bcm_file_readback_from_chip =
742                                 InterfaceFileReadbackFromChip;
743         psIntfAdapter->psAdapter->interface_transmit = InterfaceTransmitPacket;
744
745         retval = CreateInterruptUrb(psIntfAdapter);
746
747         if(retval)
748         {
749                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cannot create interrupt urb");
750                 return retval;
751         }
752
753         retval = AllocUsbCb(psIntfAdapter);
754         if(retval)
755         {
756                 return retval;
757         }
758
759
760         retval = device_run(psIntfAdapter);
761         if(retval)
762         {
763                 return retval;
764         }
765
766
767         return 0;
768 }
769
770 static int InterfaceSuspend (struct usb_interface *intf, pm_message_t message)
771 {
772         PS_INTERFACE_ADAPTER  psIntfAdapter = usb_get_intfdata(intf);
773         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "=================================\n");
774         //Bcm_kill_all_URBs(psIntfAdapter);
775         psIntfAdapter->bSuspended = TRUE;
776
777         if(TRUE == psIntfAdapter->bPreparingForBusSuspend)
778         {
779                 psIntfAdapter->bPreparingForBusSuspend = FALSE;
780
781                 if(psIntfAdapter->psAdapter->LinkStatus == LINKUP_DONE)
782                 {
783                         psIntfAdapter->psAdapter->IdleMode = TRUE ;
784                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Host Entered in PMU Idle Mode..");
785                 }
786                 else
787                 {
788                         psIntfAdapter->psAdapter->bShutStatus = TRUE;
789                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Host Entered in PMU Shutdown Mode..");
790                 }
791         }
792         psIntfAdapter->psAdapter->bPreparingForLowPowerMode = FALSE;
793
794         //Signaling the control pkt path
795         wake_up(&psIntfAdapter->psAdapter->lowpower_mode_wait_queue);
796
797         return 0;
798 }
799
800 static int InterfaceResume (struct usb_interface *intf)
801 {
802     PS_INTERFACE_ADAPTER  psIntfAdapter = usb_get_intfdata(intf);
803         printk("=================================\n");
804         mdelay(100);
805 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
806         intf->pm_usage_cnt =1 ;
807 #endif
808         psIntfAdapter->bSuspended = FALSE;
809
810         StartInterruptUrb(psIntfAdapter);
811         InterfaceRx(psIntfAdapter);
812         return 0;
813 }
814
815 static int InterfacePreReset(struct usb_interface *intf)
816 {
817     printk("====================>");
818         return STATUS_SUCCESS;
819 }
820
821 static int InterfacePostReset(struct usb_interface *intf)
822 {
823     printk("Do Post chip reset setting here if it is required");
824         return STATUS_SUCCESS;
825 }
826 static 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 /*
840 Function:                               InterfaceInitialize
841
842 Description:                    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
846 Input parameters:               IN PMINI_ADAPTER Adapter   - Miniport Adapter Context
847
848
849 Return:                                 BCM_STATUS_SUCCESS - If Initialization of the
850                                                 HW Interface was successful.
851                                                 Other           - If an error occured.
852 */
853 INT 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
859 INT 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 }
868 MODULE_LICENSE ("GPL");