2 * Dongle BUS interface for USB, OS independent
4 * Copyright (C) 1999-2016, Broadcom Corporation
6 * Unless you and Broadcom execute a separate written software license
7 * agreement governing use of this software, this software is licensed to you
8 * under the terms of the GNU General Public License version 2 (the "GPL"),
9 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10 * following added to such license:
12 * As a special exception, the copyright holders of this software give you
13 * permission to link this software with independent modules, and to copy and
14 * distribute the resulting executable under terms of your choice, provided that
15 * you also meet, for each linked independent module, the terms and conditions of
16 * the license of that module. An independent module is a module which is not
17 * derived from this software. The special exception does not apply to any
18 * modifications of the software.
20 * Notwithstanding the above, under no circumstances may you combine this
21 * software in any way with any other Broadcom software provided under a license
22 * other than the GPL, without Broadcom's express prior written consent.
25 * <<Broadcom-WL-IPTag/Open:>>
27 * $Id: dbus_usb.c 565557 2015-06-22 19:29:44Z $
32 * This file contains DBUS code that is USB, but not OS specific. DBUS is a Broadcom proprietary
33 * host specific abstraction layer.
42 #include <bcmendian.h>
44 uint dbus_msglevel
= DBUS_ERROR_VAL
;
45 module_param(dbus_msglevel
, int, 0);
48 #define USB_DLIMAGE_RETRY_TIMEOUT 3000 /* retry Timeout */
49 #define USB_SFLASH_DLIMAGE_SPINWAIT 150 /* in unit of ms */
50 #define USB_SFLASH_DLIMAGE_LIMIT 2000 /* spinwait limit (ms) */
51 #define POSTBOOT_ID 0xA123 /* ID to detect if dongle has boot up */
52 #define USB_RESETCFG_SPINWAIT 1 /* wait after resetcfg (ms) */
53 #define USB_DEV_ISBAD(u) (u->pub->attrib.devid == 0xDEAD)
54 #define USB_DLGO_SPINWAIT 100 /* wait after DL_GO (ms) */
55 #define TEST_CHIP 0x4328
61 dbus_intf_callbacks_t
*cbs
; /** callbacks into higher DBUS level (dbus.c) */
64 uint32 rdlram_base_addr
;
69 * Callbacks common to all USB
71 static void dbus_usb_disconnect(void *handle
);
72 static void dbus_usb_send_irb_timeout(void *handle
, dbus_irb_tx_t
*txirb
);
73 static void dbus_usb_send_irb_complete(void *handle
, dbus_irb_tx_t
*txirb
, int status
);
74 static void dbus_usb_recv_irb_complete(void *handle
, dbus_irb_rx_t
*rxirb
, int status
);
75 static void dbus_usb_errhandler(void *handle
, int err
);
76 static void dbus_usb_ctl_complete(void *handle
, int type
, int status
);
77 static void dbus_usb_state_change(void *handle
, int state
);
78 static struct dbus_irb
* dbus_usb_getirb(void *handle
, bool send
);
79 static void dbus_usb_rxerr_indicate(void *handle
, bool on
);
80 #if !defined(BCM_REQUEST_FW)
81 static int dbus_usb_resetcfg(usb_info_t
*usbinfo
);
83 static int dbus_usb_iovar_op(void *bus
, const char *name
,
84 void *params
, int plen
, void *arg
, int len
, bool set
);
85 static int dbus_iovar_process(usb_info_t
* usbinfo
, const char *name
,
86 void *params
, int plen
, void *arg
, int len
, bool set
);
87 static int dbus_usb_doiovar(usb_info_t
*bus
, const bcm_iovar_t
*vi
, uint32 actionid
,
88 const char *name
, void *params
, int plen
, void *arg
, int len
, int val_size
);
89 static int dhdusb_downloadvars(usb_info_t
*bus
, void *arg
, int len
);
91 static int dbus_usb_dl_writeimage(usb_info_t
*usbinfo
, uint8
*fw
, int fwlen
);
92 static int dbus_usb_dlstart(void *bus
, uint8
*fw
, int len
);
93 static int dbus_usb_dlneeded(void *bus
);
94 static int dbus_usb_dlrun(void *bus
);
95 static int dbus_usb_rdl_dwnld_state(usb_info_t
*usbinfo
);
99 extern bool dbus_usbos_dl_cmd(void *info
, uint8 cmd
, void *buffer
, int buflen
);
100 extern int dbus_usbos_wait(void *info
, uint16 ms
);
101 extern int dbus_write_membytes(usb_info_t
*usbinfo
, bool set
, uint32 address
,
102 uint8
*data
, uint size
);
103 extern bool dbus_usbos_dl_send_bulk(void *info
, void *buffer
, int len
);
104 extern int dbus_usbos_loopback_tx(void *usbos_info_ptr
, int cnt
, int size
);
107 * These functions are called by the lower DBUS level (dbus_usb_os.c) to notify this DBUS level
108 * (dbus_usb.c) of an event.
110 static dbus_intf_callbacks_t dbus_usb_intf_cbs
= {
111 dbus_usb_send_irb_timeout
,
112 dbus_usb_send_irb_complete
,
113 dbus_usb_recv_irb_complete
,
115 dbus_usb_ctl_complete
,
116 dbus_usb_state_change
,
120 NULL
, /* dbus_if_pktget */
121 NULL
, /* dbus_if_pktfree */
123 dbus_usb_rxerr_indicate
128 IOV_SET_DOWNLOAD_STATE
= 1,
135 const bcm_iovar_t dhdusb_iovars
[] = {
136 {"vars", IOV_VARS
, 0, IOVT_BUFFER
, 0 },
137 {"dbus_msglevel", IOV_DBUS_MSGLEVEL
, 0, IOVT_UINT32
, 0 },
138 {"dwnldstate", IOV_SET_DOWNLOAD_STATE
, 0, IOVT_BOOL
, 0 },
139 {"membytes", IOV_MEMBYTES
, 0, IOVT_BUFFER
, 2 * sizeof(int) },
140 {"usb_lb_txfer", IOV_LOOPBACK_TX
, 0, IOVT_BUFFER
, 2 * sizeof(int) },
145 * Need global for probe() and disconnect() since
146 * attach() is not called at probe and detach()
147 * can be called inside disconnect()
149 static probe_cb_t probe_cb
= NULL
;
150 static disconnect_cb_t disconnect_cb
= NULL
;
151 static void *probe_arg
= NULL
;
152 static void *disc_arg
= NULL
;
153 static dbus_intf_t
*g_dbusintf
= NULL
;
154 static dbus_intf_t dbus_usb_intf
; /** functions called by higher layer DBUS into lower layer */
157 * dbus_intf_t common to all USB
158 * These functions override dbus_usb_<os>.c.
160 static void *dbus_usb_attach(dbus_pub_t
*pub
, void *cbarg
, dbus_intf_callbacks_t
*cbs
);
161 static void dbus_usb_detach(dbus_pub_t
*pub
, void *info
);
162 static void * dbus_usb_probe(void *arg
, const char *desc
, uint32 bustype
,
163 uint16 bus_no
, uint16 slot
, uint32 hdrlen
);
168 * As part of DBUS initialization/registration, the higher level DBUS (dbus.c) needs to know what
169 * lower level DBUS functions to call (in both dbus_usb.c and dbus_usb_os.c).
172 dbus_usb_probe(void *arg
, const char *desc
, uint32 bustype
, uint16 bus_no
,
173 uint16 slot
, uint32 hdrlen
)
175 DBUSTRACE(("%s(): \n", __FUNCTION__
));
178 if (g_dbusintf
!= NULL
) {
179 /* First, initialize all lower-level functions as default
180 * so that dbus.c simply calls directly to dbus_usb_os.c.
182 bcopy(g_dbusintf
, &dbus_usb_intf
, sizeof(dbus_intf_t
));
184 /* Second, selectively override functions we need, if any. */
185 dbus_usb_intf
.attach
= dbus_usb_attach
;
186 dbus_usb_intf
.detach
= dbus_usb_detach
;
187 dbus_usb_intf
.iovar_op
= dbus_usb_iovar_op
;
188 dbus_usb_intf
.dlstart
= dbus_usb_dlstart
;
189 dbus_usb_intf
.dlneeded
= dbus_usb_dlneeded
;
190 dbus_usb_intf
.dlrun
= dbus_usb_dlrun
;
193 disc_arg
= probe_cb(probe_arg
, "DBUS USB", USB_BUS
, bus_no
, slot
, hdrlen
);
201 * On return, *intf contains this or lower-level DBUS functions to be called by higher
205 dbus_bus_register(int vid
, int pid
, probe_cb_t prcb
,
206 disconnect_cb_t discb
, void *prarg
, dbus_intf_t
**intf
, void *param1
, void *param2
)
210 DBUSTRACE(("%s(): \n", __FUNCTION__
));
212 disconnect_cb
= discb
;
215 *intf
= &dbus_usb_intf
;
217 err
= dbus_bus_osl_register(vid
, pid
, dbus_usb_probe
,
218 dbus_usb_disconnect
, NULL
, &g_dbusintf
, param1
, param2
);
225 dbus_bus_deregister()
227 DBUSTRACE(("%s(): \n", __FUNCTION__
));
228 return dbus_bus_osl_deregister();
231 /** initialization consists of registration followed by 'attach'. */
233 dbus_usb_attach(dbus_pub_t
*pub
, void *cbarg
, dbus_intf_callbacks_t
*cbs
)
235 usb_info_t
*usb_info
;
237 DBUSTRACE(("%s(): \n", __FUNCTION__
));
239 if ((g_dbusintf
== NULL
) || (g_dbusintf
->attach
== NULL
))
242 /* Sanity check for BUS_INFO() */
243 ASSERT(OFFSETOF(usb_info_t
, pub
) == 0);
245 usb_info
= MALLOC(pub
->osh
, sizeof(usb_info_t
));
246 if (usb_info
== NULL
)
249 bzero(usb_info
, sizeof(usb_info_t
));
252 usb_info
->cbarg
= cbarg
;
255 usb_info
->usbosl_info
= (dbus_pub_t
*)g_dbusintf
->attach(pub
,
256 usb_info
, &dbus_usb_intf_cbs
);
257 if (usb_info
->usbosl_info
== NULL
) {
258 MFREE(pub
->osh
, usb_info
, sizeof(usb_info_t
));
262 /* Save USB OS-specific driver entry points */
263 usb_info
->drvintf
= g_dbusintf
;
266 #if !defined(BCM_REQUEST_FW)
267 if (!dbus_usb_resetcfg(usb_info
)) {
268 usb_info
->pub
->busstate
= DBUS_STATE_DL_DONE
;
271 /* Return Lower layer info */
272 return (void *) usb_info
->usbosl_info
;
276 dbus_usb_detach(dbus_pub_t
*pub
, void *info
)
278 usb_info_t
*usb_info
= (usb_info_t
*) pub
->bus
;
279 osl_t
*osh
= pub
->osh
;
281 if (usb_info
== NULL
)
284 if (usb_info
->drvintf
&& usb_info
->drvintf
->detach
)
285 usb_info
->drvintf
->detach(pub
, usb_info
->usbosl_info
);
287 MFREE(osh
, usb_info
, sizeof(usb_info_t
));
291 dbus_usb_disconnect(void *handle
)
293 DBUSTRACE(("%s(): \n", __FUNCTION__
));
295 disconnect_cb(disc_arg
);
299 * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
303 dbus_usb_send_irb_timeout(void *handle
, dbus_irb_tx_t
*txirb
)
305 usb_info_t
*usb_info
= (usb_info_t
*) handle
;
307 DBUSTRACE(("%s\n", __FUNCTION__
));
309 if (usb_info
== NULL
)
312 if (usb_info
->cbs
&& usb_info
->cbs
->send_irb_timeout
)
313 usb_info
->cbs
->send_irb_timeout(usb_info
->cbarg
, txirb
);
317 * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
321 dbus_usb_send_irb_complete(void *handle
, dbus_irb_tx_t
*txirb
, int status
)
323 usb_info_t
*usb_info
= (usb_info_t
*) handle
;
325 if (usb_info
== NULL
)
328 if (usb_info
->cbs
&& usb_info
->cbs
->send_irb_complete
)
329 usb_info
->cbs
->send_irb_complete(usb_info
->cbarg
, txirb
, status
);
333 * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
337 dbus_usb_recv_irb_complete(void *handle
, dbus_irb_rx_t
*rxirb
, int status
)
339 usb_info_t
*usb_info
= (usb_info_t
*) handle
;
341 if (usb_info
== NULL
)
344 if (usb_info
->cbs
&& usb_info
->cbs
->recv_irb_complete
)
345 usb_info
->cbs
->recv_irb_complete(usb_info
->cbarg
, rxirb
, status
);
348 /** Lower DBUS level (dbus_usb_os.c) requests a free IRB. Pass this on to the higher DBUS level. */
349 static struct dbus_irb
*
350 dbus_usb_getirb(void *handle
, bool send
)
352 usb_info_t
*usb_info
= (usb_info_t
*) handle
;
354 if (usb_info
== NULL
)
357 if (usb_info
->cbs
&& usb_info
->cbs
->getirb
)
358 return usb_info
->cbs
->getirb(usb_info
->cbarg
, send
);
364 * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
368 dbus_usb_rxerr_indicate(void *handle
, bool on
)
370 usb_info_t
*usb_info
= (usb_info_t
*) handle
;
372 if (usb_info
== NULL
)
375 if (usb_info
->cbs
&& usb_info
->cbs
->rxerr_indicate
)
376 usb_info
->cbs
->rxerr_indicate(usb_info
->cbarg
, on
);
380 * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
384 dbus_usb_errhandler(void *handle
, int err
)
386 usb_info_t
*usb_info
= (usb_info_t
*) handle
;
388 if (usb_info
== NULL
)
391 if (usb_info
->cbs
&& usb_info
->cbs
->errhandler
)
392 usb_info
->cbs
->errhandler(usb_info
->cbarg
, err
);
396 * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
400 dbus_usb_ctl_complete(void *handle
, int type
, int status
)
402 usb_info_t
*usb_info
= (usb_info_t
*) handle
;
404 DBUSTRACE(("%s\n", __FUNCTION__
));
406 if (usb_info
== NULL
) {
407 DBUSERR(("%s: usb_info is NULL\n", __FUNCTION__
));
411 if (usb_info
->cbs
&& usb_info
->cbs
->ctl_complete
)
412 usb_info
->cbs
->ctl_complete(usb_info
->cbarg
, type
, status
);
416 * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
420 dbus_usb_state_change(void *handle
, int state
)
422 usb_info_t
*usb_info
= (usb_info_t
*) handle
;
424 if (usb_info
== NULL
)
427 if (usb_info
->cbs
&& usb_info
->cbs
->state_change
)
428 usb_info
->cbs
->state_change(usb_info
->cbarg
, state
);
431 /** called by higher DBUS level (dbus.c) */
433 dbus_usb_iovar_op(void *bus
, const char *name
,
434 void *params
, int plen
, void *arg
, int len
, bool set
)
438 err
= dbus_iovar_process((usb_info_t
*)bus
, name
, params
, plen
, arg
, len
, set
);
442 /** process iovar request from higher DBUS level */
444 dbus_iovar_process(usb_info_t
* usbinfo
, const char *name
,
445 void *params
, int plen
, void *arg
, int len
, bool set
)
447 const bcm_iovar_t
*vi
= NULL
;
452 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
457 /* Get MUST have return space */
458 ASSERT(set
|| (arg
&& len
));
460 /* Set does NOT take qualifiers */
461 ASSERT(!set
|| (!params
&& !plen
));
463 /* Look up var locally; if not found pass to host driver */
464 if ((vi
= bcm_iovar_lookup(dhdusb_iovars
, name
)) == NULL
) {
466 bcmerror
= BCME_UNSUPPORTED
;
467 DBUSTRACE(("%s: IOVAR %s is not supported\n", name
, __FUNCTION__
));
472 DBUSTRACE(("%s: %s %s, len %d plen %d\n", __FUNCTION__
,
473 name
, (set
? "set" : "get"), len
, plen
));
475 /* set up 'params' pointer in case this is a set command so that
476 * the convenience int and bool code can be common to set and get
478 if (params
== NULL
) {
483 if (vi
->type
== IOVT_VOID
)
485 else if (vi
->type
== IOVT_BUFFER
)
488 /* all other types are integer sized */
489 val_size
= sizeof(int);
491 actionid
= set
? IOV_SVAL(vi
->varid
) : IOV_GVAL(vi
->varid
);
492 bcmerror
= dbus_usb_doiovar(usbinfo
, vi
, actionid
,
493 name
, params
, plen
, arg
, len
, val_size
);
497 } /* dbus_iovar_process */
500 dbus_usb_doiovar(usb_info_t
*bus
, const bcm_iovar_t
*vi
, uint32 actionid
, const char *name
,
501 void *params
, int plen
, void *arg
, int len
, int val_size
)
508 DBUSTRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n",
509 __FUNCTION__
, actionid
, name
, params
, plen
, arg
, len
, val_size
));
511 if ((bcmerror
= bcm_iovar_lencheck(vi
, arg
, len
, IOV_ISSET(actionid
))) != 0)
514 if (plen
>= (int)sizeof(int_val
))
515 bcopy(params
, &int_val
, sizeof(int_val
));
517 if (plen
>= (int)sizeof(int_val
) * 2)
518 bcopy((void*)((uintptr
)params
+ sizeof(int_val
)), &int_val2
, sizeof(int_val2
));
520 bool_val
= (int_val
!= 0) ? TRUE
: FALSE
;
524 case IOV_SVAL(IOV_MEMBYTES
):
525 case IOV_GVAL(IOV_MEMBYTES
):
531 bool set
= (actionid
== IOV_SVAL(IOV_MEMBYTES
));
533 ASSERT(plen
>= 2*sizeof(int));
535 address
= (uint32
)int_val
;
536 BCM_REFERENCE(address
);
537 bcopy((char *)params
+ sizeof(int_val
), &int_val
, sizeof(int_val
));
538 size
= (uint
)int_val
;
540 /* Do some validation */
541 dsize
= set
? plen
- (2 * sizeof(int)) : len
;
543 DBUSTRACE(("%s: error on %s membytes, addr 0x%08x size %d dsize %d\n",
544 __FUNCTION__
, (set
? "set" : "get"), address
, size
, dsize
));
545 bcmerror
= BCME_BADARG
;
548 DBUSTRACE(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__
,
549 (set
? "write" : "read"), size
, address
));
551 /* Generate the actual data pointer */
552 data
= set
? (uint8
*)params
+ 2 * sizeof(int): (uint8
*)arg
;
554 /* Call to do the transfer */
555 bcmerror
= dbus_usb_dl_writeimage(BUS_INFO(bus
, usb_info_t
), data
, size
);
560 case IOV_SVAL(IOV_SET_DOWNLOAD_STATE
):
562 if (bool_val
== TRUE
) {
563 bcmerror
= dbus_usb_dlneeded(bus
);
564 dbus_usb_rdl_dwnld_state(BUS_INFO(bus
, usb_info_t
));
566 usb_info_t
*usbinfo
= BUS_INFO(bus
, usb_info_t
);
567 bcmerror
= dbus_usb_dlrun(bus
);
568 usbinfo
->pub
->busstate
= DBUS_STATE_DL_DONE
;
572 case IOV_SVAL(IOV_VARS
):
573 bcmerror
= dhdusb_downloadvars(BUS_INFO(bus
, usb_info_t
), arg
, len
);
576 case IOV_GVAL(IOV_DBUS_MSGLEVEL
):
577 int_val
= (int32
)dbus_msglevel
;
578 bcopy(&int_val
, arg
, val_size
);
581 case IOV_SVAL(IOV_DBUS_MSGLEVEL
):
582 dbus_msglevel
= int_val
;
585 #ifdef DBUS_USB_LOOPBACK
586 case IOV_SVAL(IOV_LOOPBACK_TX
):
587 bcmerror
= dbus_usbos_loopback_tx(BUS_INFO(bus
, usb_info_t
), int_val
,
592 bcmerror
= BCME_UNSUPPORTED
;
598 } /* dbus_usb_doiovar */
600 /** higher DBUS level (dbus.c) wants to set NVRAM variables in dongle */
602 dhdusb_downloadvars(usb_info_t
*bus
, void *arg
, int len
)
610 bcmerror
= BCME_BUFTOOSHORT
;
614 /* RAM size is not set. Set it at dbus_usb_dlneeded */
615 if (!bus
->rdlram_size
)
616 bcmerror
= BCME_ERROR
;
618 /* Even if there are no vars are to be written, we still need to set the ramsize. */
619 varsize
= len
? ROUNDUP(len
, 4) : 0;
620 varaddr
= (bus
->rdlram_size
- 4) - varsize
;
622 /* Write the vars list */
623 DBUSTRACE(("WriteVars: @%x varsize=%d\n", varaddr
, varsize
));
624 bcmerror
= dbus_write_membytes(bus
->usbosl_info
, TRUE
, (varaddr
+ bus
->rdlram_base_addr
),
627 /* adjust to the user specified RAM */
628 DBUSTRACE(("Usable memory size: %d\n", bus
->rdlram_size
));
629 DBUSTRACE(("Vars are at %d, orig varsize is %d\n", varaddr
, varsize
));
631 varsize
= ((bus
->rdlram_size
- 4) - varaddr
);
634 * Determine the length token:
635 * Varsize, converted to words, in lower 16-bits, checksum in upper 16-bits.
640 varsizew
= varsize
/ 4;
641 varsizew
= (~varsizew
<< 16) | (varsizew
& 0x0000FFFF);
642 varsizew
= htol32(varsizew
);
645 DBUSTRACE(("New varsize is %d, length token=0x%08x\n", varsize
, varsizew
));
647 /* Write the length token to the last word */
648 bcmerror
= dbus_write_membytes(bus
->usbosl_info
, TRUE
, ((bus
->rdlram_size
- 4) +
649 bus
->rdlram_base_addr
), (uint8
*)&varsizew
, 4);
652 } /* dbus_usb_doiovar */
654 #if !defined(BCM_REQUEST_FW)
656 * After downloading firmware into dongle and starting it, we need to know if the firmware is
657 * indeed up and running.
660 dbus_usb_resetcfg(usb_info_t
*usbinfo
)
666 uint32 starttime
= 0;
669 DBUSTRACE(("%s\n", __FUNCTION__
));
674 osinfo
= usbinfo
->usbosl_info
;
677 /* Give dongle chance to boot */
678 dbus_usbos_wait(osinfo
, USB_SFLASH_DLIMAGE_SPINWAIT
);
679 waittime
= USB_SFLASH_DLIMAGE_SPINWAIT
;
680 while (waittime
< USB_DLIMAGE_RETRY_TIMEOUT
) {
682 starttime
= OSL_SYSUPTIME();
684 id
.chip
= 0xDEAD; /* Get the ID */
685 dbus_usbos_dl_cmd(osinfo
, DL_GETVER
, &id
, sizeof(bootrom_id_t
));
686 id
.chip
= ltoh32(id
.chip
);
688 endtime
= OSL_SYSUPTIME();
689 waittime
+= (endtime
- starttime
);
691 if (id
.chip
== POSTBOOT_ID
)
695 if (id
.chip
== POSTBOOT_ID
) {
696 DBUSERR(("%s: download done. Bootup time = %d ms postboot chip 0x%x/rev 0x%x\n",
697 __FUNCTION__
, waittime
, id
.chip
, id
.chiprev
));
699 dbus_usbos_dl_cmd(osinfo
, DL_RESETCFG
, &id
, sizeof(bootrom_id_t
));
701 dbus_usbos_wait(osinfo
, USB_RESETCFG_SPINWAIT
);
704 DBUSERR(("%s: Cannot talk to Dongle. Wait time = %d ms. Firmware is not UP \n",
705 __FUNCTION__
, waittime
));
713 /** before firmware download, the dongle has to be prepared to receive the fw image */
715 dbus_usb_rdl_dwnld_state(usb_info_t
*usbinfo
)
717 void *osinfo
= usbinfo
->usbosl_info
;
721 /* 1) Prepare USB boot loader for runtime image */
722 dbus_usbos_dl_cmd(osinfo
, DL_START
, &state
, sizeof(rdl_state_t
));
724 state
.state
= ltoh32(state
.state
);
725 state
.bytes
= ltoh32(state
.bytes
);
727 /* 2) Check we are in the Waiting state */
728 if (state
.state
!= DL_WAITING
) {
729 DBUSERR(("%s: Failed to DL_START\n", __FUNCTION__
));
739 * Dongle contains bootcode in ROM but firmware is (partially) contained in dongle RAM. Therefore,
740 * firmware has to be downloaded into dongle RAM.
743 dbus_usb_dl_writeimage(usb_info_t
*usbinfo
, uint8
*fw
, int fwlen
)
745 osl_t
*osh
= usbinfo
->pub
->osh
;
746 void *osinfo
= usbinfo
->usbosl_info
;
747 unsigned int sendlen
, sent
, dllen
;
748 char *bulkchunk
= NULL
, *dlpos
;
752 uint16 wait
, wait_time
;
753 uint32 dl_trunk_size
= RDL_CHUNK
;
755 if (BCM4350_CHIP(usbinfo
->pub
->attrib
.devid
))
756 dl_trunk_size
= RDL_CHUNK_MAX
;
759 bulkchunk
= MALLOC(osh
, dl_trunk_size
);
760 if (dl_trunk_size
== RDL_CHUNK
)
764 if (dl_trunk_size
< RDL_CHUNK
)
765 dl_trunk_size
= RDL_CHUNK
;
769 if (bulkchunk
== NULL
) {
778 /* Get chip id and rev */
779 id
.chip
= usbinfo
->pub
->attrib
.devid
;
780 id
.chiprev
= usbinfo
->pub
->attrib
.chiprev
;
782 DBUSTRACE(("enter %s: fwlen=%d\n", __FUNCTION__
, fwlen
));
784 dbus_usbos_dl_cmd(osinfo
, DL_GETSTATE
, &state
, sizeof(rdl_state_t
));
786 /* 3) Load the image */
787 while ((sent
< dllen
)) {
788 /* Wait until the usb device reports it received all the bytes we sent */
791 if ((dllen
-sent
) < dl_trunk_size
)
792 sendlen
= dllen
-sent
;
794 sendlen
= dl_trunk_size
;
796 /* simply avoid having to send a ZLP by ensuring we never have an even
803 memcpy(bulkchunk
, dlpos
, sendlen
);
804 if (!dbus_usbos_dl_send_bulk(osinfo
, bulkchunk
, sendlen
)) {
811 DBUSTRACE(("%s: sendlen %d\n", __FUNCTION__
, sendlen
));
815 wait_time
= USB_SFLASH_DLIMAGE_SPINWAIT
;
816 while (!dbus_usbos_dl_cmd(osinfo
, DL_GETSTATE
, &state
,
817 sizeof(rdl_state_t
))) {
818 if ((id
.chip
== 43236) && (id
.chiprev
== 0)) {
819 DBUSERR(("%s: 43236a0 SFlash delay, waiting for dongle crc check "
820 "completion!!!\n", __FUNCTION__
));
821 dbus_usbos_wait(osinfo
, wait_time
);
823 if (wait
>= USB_SFLASH_DLIMAGE_LIMIT
) {
824 DBUSERR(("%s: DL_GETSTATE Failed xxxx\n", __FUNCTION__
));
830 DBUSERR(("%s: DL_GETSTATE Failed xxxx\n", __FUNCTION__
));
836 state
.state
= ltoh32(state
.state
);
837 state
.bytes
= ltoh32(state
.bytes
);
839 /* restart if an error is reported */
840 if ((state
.state
== DL_BAD_HDR
) || (state
.state
== DL_BAD_CRC
)) {
841 DBUSERR(("%s: Bad Hdr or Bad CRC\n", __FUNCTION__
));
849 MFREE(osh
, bulkchunk
, dl_trunk_size
);
852 } /* dbus_usb_dl_writeimage */
854 /** Higher level DBUS layer (dbus.c) requests this layer to download image into dongle */
856 dbus_usb_dlstart(void *bus
, uint8
*fw
, int len
)
858 usb_info_t
*usbinfo
= BUS_INFO(bus
, usb_info_t
);
861 DBUSTRACE(("%s\n", __FUNCTION__
));
866 if (USB_DEV_ISBAD(usbinfo
))
869 err
= dbus_usb_rdl_dwnld_state(usbinfo
);
871 if (DBUS_OK
== err
) {
872 err
= dbus_usb_dl_writeimage(usbinfo
, fw
, len
);
874 usbinfo
->pub
->busstate
= DBUS_STATE_DL_DONE
;
876 usbinfo
->pub
->busstate
= DBUS_STATE_DL_PENDING
;
878 usbinfo
->pub
->busstate
= DBUS_STATE_DL_PENDING
;
884 dbus_usb_update_chipinfo(usb_info_t
*usbinfo
, uint32 chip
)
887 /* based on the CHIP Id, store the ram size which is needed for NVRAM download. */
891 usbinfo
->rdlram_size
= RDL_RAM_SIZE_4319
;
892 usbinfo
->rdlram_base_addr
= RDL_RAM_BASE_4319
;
896 usbinfo
->rdlram_size
= RDL_RAM_SIZE_4329
;
897 usbinfo
->rdlram_base_addr
= RDL_RAM_BASE_4329
;
903 usbinfo
->rdlram_size
= RDL_RAM_SIZE_43236
;
904 usbinfo
->rdlram_base_addr
= RDL_RAM_BASE_43236
;
908 usbinfo
->rdlram_size
= RDL_RAM_SIZE_4328
;
909 usbinfo
->rdlram_base_addr
= RDL_RAM_BASE_4328
;
913 usbinfo
->rdlram_size
= RDL_RAM_SIZE_4322
;
914 usbinfo
->rdlram_base_addr
= RDL_RAM_BASE_4322
;
919 usbinfo
->rdlram_size
= RDL_RAM_SIZE_4360
;
920 usbinfo
->rdlram_base_addr
= RDL_RAM_BASE_4360
;
925 usbinfo
->rdlram_size
= RDL_RAM_SIZE_43242
;
926 usbinfo
->rdlram_base_addr
= RDL_RAM_BASE_43242
;
930 usbinfo
->rdlram_size
= RDL_RAM_SIZE_43143
;
931 usbinfo
->rdlram_base_addr
= RDL_RAM_BASE_43143
;
938 usbinfo
->rdlram_size
= RDL_RAM_SIZE_4350
;
939 usbinfo
->rdlram_base_addr
= RDL_RAM_BASE_4350
;
946 DBUSERR(("%s: Chip 0x%x Ram size is not known\n", __FUNCTION__
, chip
));
953 } /* dbus_usb_update_chipinfo */
955 /** higher DBUS level (dbus.c) wants to know if firmware download is required. */
957 dbus_usb_dlneeded(void *bus
)
959 usb_info_t
*usbinfo
= BUS_INFO(bus
, usb_info_t
);
964 DBUSTRACE(("%s\n", __FUNCTION__
));
969 osinfo
= usbinfo
->usbosl_info
;
972 /* Check if firmware downloaded already by querying runtime ID */
974 dbus_usbos_dl_cmd(osinfo
, DL_GETVER
, &id
, sizeof(bootrom_id_t
));
976 id
.chip
= ltoh32(id
.chip
);
977 id
.chiprev
= ltoh32(id
.chiprev
);
979 if (FALSE
== dbus_usb_update_chipinfo(usbinfo
, id
.chip
)) {
980 dl_needed
= DBUS_ERR
;
984 DBUSERR(("%s: chip 0x%x rev 0x%x\n", __FUNCTION__
, id
.chip
, id
.chiprev
));
985 if (id
.chip
== POSTBOOT_ID
) {
986 /* This code is needed to support two enumerations on USB1.1 scenario */
987 DBUSERR(("%s: Firmware already downloaded\n", __FUNCTION__
));
989 dbus_usbos_dl_cmd(osinfo
, DL_RESETCFG
, &id
, sizeof(bootrom_id_t
));
991 if (usbinfo
->pub
->busstate
== DBUS_STATE_DL_PENDING
)
992 usbinfo
->pub
->busstate
= DBUS_STATE_DL_DONE
;
994 usbinfo
->pub
->attrib
.devid
= id
.chip
;
995 usbinfo
->pub
->attrib
.chiprev
= id
.chiprev
;
1002 /** After issuing firmware download, higher DBUS level (dbus.c) wants to start the firmware. */
1004 dbus_usb_dlrun(void *bus
)
1006 usb_info_t
*usbinfo
= BUS_INFO(bus
, usb_info_t
);
1011 DBUSTRACE(("%s\n", __FUNCTION__
));
1013 if (usbinfo
== NULL
)
1016 if (USB_DEV_ISBAD(usbinfo
))
1019 osinfo
= usbinfo
->usbosl_info
;
1022 /* Check we are runnable */
1023 dbus_usbos_dl_cmd(osinfo
, DL_GETSTATE
, &state
, sizeof(rdl_state_t
));
1025 state
.state
= ltoh32(state
.state
);
1026 state
.bytes
= ltoh32(state
.bytes
);
1028 /* Start the image */
1029 if (state
.state
== DL_RUNNABLE
) {
1030 DBUSTRACE(("%s: Issue DL_GO\n", __FUNCTION__
));
1031 dbus_usbos_dl_cmd(osinfo
, DL_GO
, &state
, sizeof(rdl_state_t
));
1033 if (usbinfo
->pub
->attrib
.devid
== TEST_CHIP
)
1034 dbus_usbos_wait(osinfo
, USB_DLGO_SPINWAIT
);
1036 // dbus_usb_resetcfg(usbinfo);
1037 /* The Donlge may go for re-enumeration. */
1039 DBUSERR(("%s: Dongle not runnable\n", __FUNCTION__
));
1047 * As preparation for firmware download, higher DBUS level (dbus.c) requests the firmware image
1048 * to be used for the type of dongle detected. Directly called by dbus.c (so not via a callback
1052 dbus_bus_fw_get(void *bus
, uint8
**fw
, int *fwlen
, int *decomp
)
1054 usb_info_t
*usbinfo
= BUS_INFO(bus
, usb_info_t
);
1058 devid
= usbinfo
->pub
->attrib
.devid
;
1059 crev
= usbinfo
->pub
->attrib
.chiprev
;
1065 case BCM43236_CHIP_ID
:
1066 case BCM43235_CHIP_ID
:
1067 case BCM43234_CHIP_ID
:
1068 case BCM43238_CHIP_ID
: {
1069 if (crev
== 3 || crev
== 2 || crev
== 1) {
1070 #ifdef EMBED_IMAGE_43236b
1071 *fw
= (uint8
*)dlarray_43236b
;
1072 *fwlen
= sizeof(dlarray_43236b
);
1077 case BCM4360_CHIP_ID
:
1078 case BCM4352_CHIP_ID
:
1079 case BCM43526_CHIP_ID
:
1080 #ifdef EMBED_IMAGE_43526a
1082 *fw
= (uint8
*)dlarray_43526a
;
1083 *fwlen
= sizeof(dlarray_43526a
);
1086 #ifdef EMBED_IMAGE_43526b
1088 *fw
= (uint8
*)dlarray_43526b
;
1089 *fwlen
= sizeof(dlarray_43526b
);
1094 case BCM43242_CHIP_ID
:
1095 #ifdef EMBED_IMAGE_43242a0
1096 *fw
= (uint8
*)dlarray_43242a0
;
1097 *fwlen
= sizeof(dlarray_43242a0
);
1101 case BCM43143_CHIP_ID
:
1102 #ifdef EMBED_IMAGE_43143a0
1103 *fw
= (uint8
*)dlarray_43143a0
;
1104 *fwlen
= sizeof(dlarray_43143a0
);
1106 #ifdef EMBED_IMAGE_43143b0
1107 *fw
= (uint8
*)dlarray_43143b0
;
1108 *fwlen
= sizeof(dlarray_43143b0
);
1112 case BCM4350_CHIP_ID
:
1113 case BCM4354_CHIP_ID
:
1114 case BCM43556_CHIP_ID
:
1115 case BCM43558_CHIP_ID
:
1116 case BCM43566_CHIP_ID
:
1117 case BCM43568_CHIP_ID
:
1118 case BCM43570_CHIP_ID
:
1119 case BCM4358_CHIP_ID
:
1120 #ifdef EMBED_IMAGE_4350a0
1122 *fw
= (uint8
*)dlarray_4350a0
;
1123 *fwlen
= sizeof(dlarray_4350a0
);
1126 #ifdef EMBED_IMAGE_4350b0
1128 *fw
= (uint8
*)dlarray_4350b0
;
1129 *fwlen
= sizeof(dlarray_4350b0
);
1132 #ifdef EMBED_IMAGE_4350b1
1134 *fw
= (uint8
*)dlarray_4350b1
;
1135 *fwlen
= sizeof(dlarray_4350b1
);
1138 #ifdef EMBED_IMAGE_43556b1
1140 *fw
= (uint8
*)dlarray_43556b1
;
1141 *fwlen
= sizeof(dlarray_43556b1
);
1144 #ifdef EMBED_IMAGE_4350c0
1146 *fw
= (uint8
*)dlarray_4350c0
;
1147 *fwlen
= sizeof(dlarray_4350c0
);
1149 #endif /* EMBED_IMAGE_4350c0 */
1150 #ifdef EMBED_IMAGE_4350c1
1152 *fw
= (uint8
*)dlarray_4350c1
;
1153 *fwlen
= sizeof(dlarray_4350c1
);
1155 #endif /* EMBED_IMAGE_4350c1 */
1157 case BCM43569_CHIP_ID
:
1158 #ifdef EMBED_IMAGE_43569a0
1160 *fw
= (uint8
*)dlarray_43569a0
;
1161 *fwlen
= sizeof(dlarray_43569a0
);
1163 #endif /* EMBED_IMAGE_43569a0 */
1166 #ifdef EMBED_IMAGE_GENERIC
1167 *fw
= (uint8
*)dlarray
;
1168 *fwlen
= sizeof(dlarray
);
1172 } /* dbus_bus_fw_get */