]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/bcm/InterfaceInit.c
staging: Beeceem USB Wimax driver
[net-next-2.6.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 *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_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 };
167
168 static struct usb_class_driver usbbcm_class = {
169     .name =             "usbbcm",
170     .fops =             &usbbcm_fops,
171     .minor_base =   BCM_USB_MINOR_BASE,
172 };
173
174 static int
175 usbbcm_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
309 static 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
342 static __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
376 static 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
420 static 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 }
433 static 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
446 static inline int bcm_usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
447 {
448         return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
449 }
450
451 static inline int bcm_usb_endpoint_type(const struct usb_endpoint_descriptor *epd)
452 {
453         return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
454 }
455
456 static 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
461 static 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
466 static 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
472 static 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
478 static 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
484 static 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
490 static 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
495 static 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
500 static 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
505 static 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
510 static 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
515 static 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
520 INT 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 }
773 int 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 }
802 int 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 }
816 int InterfacePreReset(struct usb_interface *intf)
817 {
818     printk("====================>");
819         return STATUS_SUCCESS;
820 }
821 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");