2 * Dongle BUS interface for USB, OS independent
4 * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved.
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * $Id: dbus_usb.c 408461 2013-06-19 06:50:14Z $
27 #include <bcmendian.h>
29 #if defined(BCM_DNGL_EMBEDIMAGE)
30 #ifdef EMBED_IMAGE_43236b
31 #include "rtecdc_43236b.h"
32 #endif /* EMBED_IMAGE_43236b */
33 #ifdef EMBED_IMAGE_43238b
34 #include "rtecdc_43238b.h"
35 #endif /* EMBED_IMAGE_43238b */
36 #ifdef EMBED_IMAGE_43526a
37 #include "rtecdc_43526a.h"
38 #endif /* EMBED_IMAGE_43526a */
39 #ifdef EMBED_IMAGE_43526b
40 #include "rtecdc_43526b.h"
41 #endif /* EMBED_IMAGE_43526b */
42 #ifdef EMBED_IMAGE_4360b
43 #include "rtecdc_4360b.h"
44 #endif /* EMBED_IMAGE_4360b */
45 #ifdef EMBED_IMAGE_43242a0
46 #include "rtecdc_43242a0.h"
47 #endif /* EMBED_IMAGE_43242a0 */
48 #ifdef EMBED_IMAGE_43242a1
49 #include "rtecdc_43242a1.h"
50 #endif /* EMBED_IMAGE_43242a1 */
51 #ifdef EMBED_IMAGE_43143a0
52 #include "rtecdc_43143a0.h"
53 #endif /* EMBED_IMAGE_43143a0 */
54 #ifdef EMBED_IMAGE_43143b0
55 #include "rtecdc_43143b0.h"
56 #endif /* EMBED_IMAGE_43143b0 */
57 #ifdef EMBED_IMAGE_4350a0
58 #include "rtecdc_4350a0.h"
59 #endif /* EMBED_IMAGE_4350a0 */
60 #ifdef EMBED_IMAGE_4350b0
61 #include "rtecdc_4350b0.h"
62 #endif /* EMBED_IMAGE_4350b0 */
63 #ifdef EMBED_IMAGE_4350b1
64 #include "rtecdc_4350b1.h"
65 #endif /* EMBED_IMAGE_4350b1 */
66 #ifdef EMBED_IMAGE_GENERIC
69 #endif /* BCM_DNGL_EMBEDIMAGE */
71 #define USB_DLIMAGE_SPINWAIT 10 /* in unit of ms */
72 #define USB_DLIMAGE_LIMIT 500 /* spinwait limit (ms) */
73 #define USB_SFLASH_DLIMAGE_SPINWAIT 200 /* in unit of ms */
74 #define USB_SFLASH_DLIMAGE_LIMIT 2000 /* spinwait limit (ms) */
75 #define POSTBOOT_ID 0xA123 /* ID to detect if dongle has boot up */
76 #define USB_RESETCFG_SPINWAIT 1 /* wait after resetcfg (ms) */
77 #define USB_DEV_ISBAD(u) (u->pub->attrib.devid == 0xDEAD)
78 #define USB_DLGO_SPINWAIT 100 /* wait after DL_GO (ms) */
79 #define TEST_CHIP 0x4328
85 dbus_intf_callbacks_t
*cbs
;
88 uint32 rdlram_base_addr
;
93 * Callbacks common to all USB
95 static void dbus_usb_disconnect(void *handle
);
96 static void dbus_usb_send_irb_timeout(void *handle
, dbus_irb_tx_t
*txirb
);
97 static void dbus_usb_send_irb_complete(void *handle
, dbus_irb_tx_t
*txirb
, int status
);
98 static void dbus_usb_recv_irb_complete(void *handle
, dbus_irb_rx_t
*rxirb
, int status
);
99 static void dbus_usb_errhandler(void *handle
, int err
);
100 static void dbus_usb_ctl_complete(void *handle
, int type
, int status
);
101 static void dbus_usb_state_change(void *handle
, int state
);
102 static struct dbus_irb
* dbus_usb_getirb(void *handle
, bool send
);
103 static void dbus_usb_rxerr_indicate(void *handle
, bool on
);
104 static int dbus_usb_resetcfg(usb_info_t
*usbinfo
);
105 static int dbus_usb_iovar_op(void *bus
, const char *name
,
106 void *params
, int plen
, void *arg
, int len
, bool set
);
107 static int dbus_iovar_process(usb_info_t
* usbinfo
, const char *name
,
108 void *params
, int plen
, void *arg
, int len
, bool set
);
109 static int dbus_usb_doiovar(usb_info_t
*bus
, const bcm_iovar_t
*vi
, uint32 actionid
,
110 const char *name
, void *params
, int plen
, void *arg
, int len
, int val_size
);
111 static int dhdusb_downloadvars(usb_info_t
*bus
, void *arg
, int len
);
113 static int dbus_usb_dl_writeimage(usb_info_t
*usbinfo
, uint8
*fw
, int fwlen
);
114 static int dbus_usb_dlstart(void *bus
, uint8
*fw
, int len
);
115 static bool dbus_usb_dlneeded(void *bus
);
116 static int dbus_usb_dlrun(void *bus
);
117 static int dbus_usb_rdl_dwnld_state(usb_info_t
*usbinfo
);
119 #ifdef BCM_DNGL_EMBEDIMAGE
120 static bool dbus_usb_device_exists(void *bus
);
124 extern bool dbus_usbos_dl_cmd(void *info
, uint8 cmd
, void *buffer
, int buflen
);
125 extern int dbus_usbos_wait(void *info
, uint16 ms
);
126 extern int dbus_write_membytes(usb_info_t
*usbinfo
, bool set
, uint32 address
,
127 uint8
*data
, uint size
);
128 extern bool dbus_usbos_dl_send_bulk(void *info
, void *buffer
, int len
);
130 static dbus_intf_callbacks_t dbus_usb_intf_cbs
= {
131 dbus_usb_send_irb_timeout
,
132 dbus_usb_send_irb_complete
,
133 dbus_usb_recv_irb_complete
,
135 dbus_usb_ctl_complete
,
136 dbus_usb_state_change
,
140 NULL
, /* dbus_if_pktget */
141 NULL
, /* dbus_if_pktfree */
143 dbus_usb_rxerr_indicate
148 IOV_SET_DOWNLOAD_STATE
= 1,
153 const bcm_iovar_t dhdusb_iovars
[] = {
154 {"vars", IOV_VARS
, 0, IOVT_BUFFER
, 0 },
155 {"dwnldstate", IOV_SET_DOWNLOAD_STATE
, 0, IOVT_BOOL
, 0 },
156 {"membytes", IOV_MEMBYTES
, 0, IOVT_BUFFER
, 2 * sizeof(int) },
161 * Need global for probe() and disconnect() since
162 * attach() is not called at probe and detach()
163 * can be called inside disconnect()
165 static probe_cb_t probe_cb
= NULL
;
166 static disconnect_cb_t disconnect_cb
= NULL
;
167 static void *probe_arg
= NULL
;
168 static void *disc_arg
= NULL
;
169 static dbus_intf_t
*g_dbusintf
= NULL
;
170 static dbus_intf_t dbus_usb_intf
;
173 * dbus_intf_t common to all USB
174 * These functions override dbus_usb_<os>.c.
176 static void *dbus_usb_attach(dbus_pub_t
*pub
, void *cbarg
, dbus_intf_callbacks_t
*cbs
);
177 static void dbus_usb_detach(dbus_pub_t
*pub
, void *info
);
178 static void * dbus_usb_probe(void *arg
, const char *desc
, uint32 bustype
, uint32 hdrlen
);
183 * As part of DBUS initialization/registration, the higher level DBUS (dbus.c) needs to know what
184 * lower level DBUS functions to call (in both dbus_usb.c and dbus_usb_os.c).
187 dbus_usb_probe(void *arg
, const char *desc
, uint32 bustype
, uint32 hdrlen
)
191 if (g_dbusintf
!= NULL
) {
192 /* First, initialize all lower-level functions as default
193 * so that dbus.c simply calls directly to dbus_usb_os.c.
195 bcopy(g_dbusintf
, &dbus_usb_intf
, sizeof(dbus_intf_t
));
197 /* Second, selectively override functions we need, if any. */
198 dbus_usb_intf
.attach
= dbus_usb_attach
;
199 dbus_usb_intf
.detach
= dbus_usb_detach
;
200 dbus_usb_intf
.iovar_op
= dbus_usb_iovar_op
;
201 dbus_usb_intf
.dlstart
= dbus_usb_dlstart
;
202 dbus_usb_intf
.dlneeded
= dbus_usb_dlneeded
;
203 dbus_usb_intf
.dlrun
= dbus_usb_dlrun
;
204 #ifdef BCM_DNGL_EMBEDIMAGE
205 dbus_usb_intf
.device_exists
= dbus_usb_device_exists
;
209 disc_arg
= probe_cb(probe_arg
, "DBUS USB", USB_BUS
, hdrlen
);
217 * On return, *intf contains this or lower-level DBUS functions to be called by higher
221 dbus_bus_register(int vid
, int pid
, probe_cb_t prcb
,
222 disconnect_cb_t discb
, void *prarg
, dbus_intf_t
**intf
, void *param1
, void *param2
)
227 disconnect_cb
= discb
;
230 *intf
= &dbus_usb_intf
;
232 err
= dbus_bus_osl_register(vid
, pid
, dbus_usb_probe
,
233 dbus_usb_disconnect
, NULL
, &g_dbusintf
, param1
, param2
);
240 dbus_bus_deregister()
242 return dbus_bus_osl_deregister();
245 /** initialization consists of registration followed by 'attach'. */
247 dbus_usb_attach(dbus_pub_t
*pub
, void *cbarg
, dbus_intf_callbacks_t
*cbs
)
249 usb_info_t
*usb_info
;
251 if ((g_dbusintf
== NULL
) || (g_dbusintf
->attach
== NULL
))
254 /* Sanity check for BUS_INFO() */
255 ASSERT(OFFSETOF(usb_info_t
, pub
) == 0);
257 usb_info
= MALLOC(pub
->osh
, sizeof(usb_info_t
));
258 if (usb_info
== NULL
)
261 bzero(usb_info
, sizeof(usb_info_t
));
264 usb_info
->cbarg
= cbarg
;
267 usb_info
->usbosl_info
= (dbus_pub_t
*)g_dbusintf
->attach(pub
,
268 usb_info
, &dbus_usb_intf_cbs
);
269 if (usb_info
->usbosl_info
== NULL
) {
270 MFREE(pub
->osh
, usb_info
, sizeof(usb_info_t
));
274 /* Save USB OS-specific driver entry points */
275 usb_info
->drvintf
= g_dbusintf
;
278 #if !defined(BCM_DNGL_EMBEDIMAGE) && !defined(BCM_REQUEST_FW)
280 if (!dbus_usb_resetcfg(usb_info
)) {
281 usb_info
->pub
->busstate
= DBUS_STATE_DL_DONE
;
284 /* Return Lower layer info */
285 return (void *) usb_info
->usbosl_info
;
289 dbus_usb_detach(dbus_pub_t
*pub
, void *info
)
291 usb_info_t
*usb_info
= (usb_info_t
*) pub
->bus
;
292 osl_t
*osh
= pub
->osh
;
294 if (usb_info
== NULL
)
297 if (usb_info
->drvintf
&& usb_info
->drvintf
->detach
)
298 usb_info
->drvintf
->detach(pub
, usb_info
->usbosl_info
);
300 MFREE(osh
, usb_info
, sizeof(usb_info_t
));
304 dbus_usb_disconnect(void *handle
)
307 disconnect_cb(disc_arg
);
311 * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
315 dbus_usb_send_irb_timeout(void *handle
, dbus_irb_tx_t
*txirb
)
317 usb_info_t
*usb_info
= (usb_info_t
*) handle
;
319 DBUSTRACE(("%s\n", __FUNCTION__
));
321 if (usb_info
== NULL
)
324 if (usb_info
->cbs
&& usb_info
->cbs
->send_irb_timeout
)
325 usb_info
->cbs
->send_irb_timeout(usb_info
->cbarg
, txirb
);
329 * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
333 dbus_usb_send_irb_complete(void *handle
, dbus_irb_tx_t
*txirb
, int status
)
335 usb_info_t
*usb_info
= (usb_info_t
*) handle
;
337 if (usb_info
== NULL
)
340 if (usb_info
->cbs
&& usb_info
->cbs
->send_irb_complete
)
341 usb_info
->cbs
->send_irb_complete(usb_info
->cbarg
, txirb
, status
);
345 * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
349 dbus_usb_recv_irb_complete(void *handle
, dbus_irb_rx_t
*rxirb
, int status
)
351 usb_info_t
*usb_info
= (usb_info_t
*) handle
;
353 if (usb_info
== NULL
)
356 if (usb_info
->cbs
&& usb_info
->cbs
->recv_irb_complete
)
357 usb_info
->cbs
->recv_irb_complete(usb_info
->cbarg
, rxirb
, status
);
360 /** Lower DBUS level (dbus_usb_os.c) requests a free IRB. Pass this on to the higher DBUS level. */
361 static struct dbus_irb
*
362 dbus_usb_getirb(void *handle
, bool send
)
364 usb_info_t
*usb_info
= (usb_info_t
*) handle
;
366 if (usb_info
== NULL
)
369 if (usb_info
->cbs
&& usb_info
->cbs
->getirb
)
370 return usb_info
->cbs
->getirb(usb_info
->cbarg
, send
);
376 * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
380 dbus_usb_rxerr_indicate(void *handle
, bool on
)
382 usb_info_t
*usb_info
= (usb_info_t
*) handle
;
384 if (usb_info
== NULL
)
387 if (usb_info
->cbs
&& usb_info
->cbs
->rxerr_indicate
)
388 usb_info
->cbs
->rxerr_indicate(usb_info
->cbarg
, on
);
392 * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
396 dbus_usb_errhandler(void *handle
, int err
)
398 usb_info_t
*usb_info
= (usb_info_t
*) handle
;
400 if (usb_info
== NULL
)
403 if (usb_info
->cbs
&& usb_info
->cbs
->errhandler
)
404 usb_info
->cbs
->errhandler(usb_info
->cbarg
, err
);
408 * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
412 dbus_usb_ctl_complete(void *handle
, int type
, int status
)
414 usb_info_t
*usb_info
= (usb_info_t
*) handle
;
416 if (usb_info
== NULL
)
419 if (usb_info
->cbs
&& usb_info
->cbs
->ctl_complete
)
420 usb_info
->cbs
->ctl_complete(usb_info
->cbarg
, type
, status
);
424 * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
428 dbus_usb_state_change(void *handle
, int state
)
430 usb_info_t
*usb_info
= (usb_info_t
*) handle
;
432 if (usb_info
== NULL
)
435 if (usb_info
->cbs
&& usb_info
->cbs
->state_change
)
436 usb_info
->cbs
->state_change(usb_info
->cbarg
, state
);
439 /** called by higher DBUS level (dbus.c) */
441 dbus_usb_iovar_op(void *bus
, const char *name
,
442 void *params
, int plen
, void *arg
, int len
, bool set
)
446 err
= dbus_iovar_process((usb_info_t
*)bus
, name
, params
, plen
, arg
, len
, set
);
450 /** process iovar request from higher DBUS level */
452 dbus_iovar_process(usb_info_t
* usbinfo
, const char *name
,
453 void *params
, int plen
, void *arg
, int len
, bool set
)
455 const bcm_iovar_t
*vi
= NULL
;
460 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
465 /* Get MUST have return space */
466 ASSERT(set
|| (arg
&& len
));
468 /* Set does NOT take qualifiers */
469 ASSERT(!set
|| (!params
&& !plen
));
471 /* Look up var locally; if not found pass to host driver */
472 if ((vi
= bcm_iovar_lookup(dhdusb_iovars
, name
)) == NULL
) {
474 bcmerror
= BCME_UNSUPPORTED
;
475 DBUSTRACE(("%s: IOVAR %s is not supported\n", name
, __FUNCTION__
));
480 DBUSTRACE(("%s: %s %s, len %d plen %d\n", __FUNCTION__
,
481 name
, (set
? "set" : "get"), len
, plen
));
483 /* set up 'params' pointer in case this is a set command so that
484 * the convenience int and bool code can be common to set and get
486 if (params
== NULL
) {
491 if (vi
->type
== IOVT_VOID
)
493 else if (vi
->type
== IOVT_BUFFER
)
496 /* all other types are integer sized */
497 val_size
= sizeof(int);
499 actionid
= set
? IOV_SVAL(vi
->varid
) : IOV_GVAL(vi
->varid
);
500 bcmerror
= dbus_usb_doiovar(usbinfo
, vi
, actionid
,
501 name
, params
, plen
, arg
, len
, val_size
);
508 dbus_usb_doiovar(usb_info_t
*bus
, const bcm_iovar_t
*vi
, uint32 actionid
, const char *name
,
509 void *params
, int plen
, void *arg
, int len
, int val_size
)
515 DBUSTRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n",
516 __FUNCTION__
, actionid
, name
, params
, plen
, arg
, len
, val_size
));
518 if ((bcmerror
= bcm_iovar_lencheck(vi
, arg
, len
, IOV_ISSET(actionid
))) != 0)
521 if (plen
>= (int)sizeof(int_val
))
522 bcopy(params
, &int_val
, sizeof(int_val
));
524 bool_val
= (int_val
!= 0) ? TRUE
: FALSE
;
528 case IOV_SVAL(IOV_MEMBYTES
):
529 case IOV_GVAL(IOV_MEMBYTES
):
535 bool set
= (actionid
== IOV_SVAL(IOV_MEMBYTES
));
537 ASSERT(plen
>= 2*sizeof(int));
539 address
= (uint32
)int_val
;
540 BCM_REFERENCE(address
);
541 bcopy((char *)params
+ sizeof(int_val
), &int_val
, sizeof(int_val
));
542 size
= (uint
)int_val
;
544 /* Do some validation */
545 dsize
= set
? plen
- (2 * sizeof(int)) : len
;
547 DBUSTRACE(("%s: error on %s membytes, addr 0x%08x size %d dsize %d\n",
548 __FUNCTION__
, (set
? "set" : "get"), address
, size
, dsize
));
549 bcmerror
= BCME_BADARG
;
552 DBUSTRACE(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__
,
553 (set
? "write" : "read"), size
, address
));
555 /* Generate the actual data pointer */
556 data
= set
? (uint8
*)params
+ 2 * sizeof(int): (uint8
*)arg
;
558 /* Call to do the transfer */
559 bcmerror
= dbus_usb_dl_writeimage(BUS_INFO(bus
, usb_info_t
), data
, size
);
564 case IOV_SVAL(IOV_SET_DOWNLOAD_STATE
):
566 if (bool_val
== TRUE
) {
567 bcmerror
= dbus_usb_dlneeded(bus
);
568 dbus_usb_rdl_dwnld_state(BUS_INFO(bus
, usb_info_t
));
570 usb_info_t
*usbinfo
= BUS_INFO(bus
, usb_info_t
);
571 bcmerror
= dbus_usb_dlrun(bus
);
572 usbinfo
->pub
->busstate
= DBUS_STATE_DL_DONE
;
576 case IOV_SVAL(IOV_VARS
):
577 bcmerror
= dhdusb_downloadvars(BUS_INFO(bus
, usb_info_t
), arg
, len
);
581 bcmerror
= BCME_UNSUPPORTED
;
589 /** higher DBUS level (dbus.c) wants to set NVRAM variables in dongle */
591 dhdusb_downloadvars(usb_info_t
*bus
, void *arg
, int len
)
599 bcmerror
= BCME_BUFTOOSHORT
;
603 /* RAM size is not set. Set it at dbus_usb_dlneeded */
604 if (!bus
->rdlram_size
)
605 bcmerror
= BCME_ERROR
;
607 /* Even if there are no vars are to be written, we still need to set the ramsize. */
608 varsize
= len
? ROUNDUP(len
, 4) : 0;
609 varaddr
= (bus
->rdlram_size
- 4) - varsize
;
611 /* Write the vars list */
612 DBUSTRACE(("WriteVars: @%x varsize=%d\n", varaddr
, varsize
));
613 bcmerror
= dbus_write_membytes(bus
->usbosl_info
, TRUE
, (varaddr
+ bus
->rdlram_base_addr
),
616 /* adjust to the user specified RAM */
617 DBUSTRACE(("Usable memory size: %d\n", bus
->rdlram_size
));
618 DBUSTRACE(("Vars are at %d, orig varsize is %d\n", varaddr
, varsize
));
620 varsize
= ((bus
->rdlram_size
- 4) - varaddr
);
623 * Determine the length token:
624 * Varsize, converted to words, in lower 16-bits, checksum in upper 16-bits.
629 varsizew
= varsize
/ 4;
630 varsizew
= (~varsizew
<< 16) | (varsizew
& 0x0000FFFF);
631 varsizew
= htol32(varsizew
);
634 DBUSTRACE(("New varsize is %d, length token=0x%08x\n", varsize
, varsizew
));
636 /* Write the length token to the last word */
637 bcmerror
= dbus_write_membytes(bus
->usbosl_info
, TRUE
, ((bus
->rdlram_size
- 4) +
638 bus
->rdlram_base_addr
), (uint8
*)&varsizew
, 4);
644 * After downloading firmware into dongle and starting it, we need to know if the firmware is
645 * indeed up and running.
648 dbus_usb_resetcfg(usb_info_t
*usbinfo
)
652 uint16 wait
= 0, wait_time
;
654 DBUSTRACE(("%s\n", __FUNCTION__
));
659 osinfo
= usbinfo
->usbosl_info
;
662 /* Give dongle chance to boot */
663 wait_time
= USB_SFLASH_DLIMAGE_SPINWAIT
;
664 while (wait
< USB_SFLASH_DLIMAGE_LIMIT
) {
665 dbus_usbos_wait(osinfo
, wait_time
);
669 id
.chip
= 0xDEAD; /* Get the ID */
670 dbus_usbos_dl_cmd(osinfo
, DL_GETVER
, &id
, sizeof(bootrom_id_t
));
671 id
.chip
= ltoh32(id
.chip
);
673 if (id
.chip
== POSTBOOT_ID
)
677 if (id
.chip
== POSTBOOT_ID
) {
678 DBUSERR(("%s: download done %d ms postboot chip 0x%x/rev 0x%x\n",
679 __FUNCTION__
, wait
, id
.chip
, id
.chiprev
));
681 dbus_usbos_dl_cmd(osinfo
, DL_RESETCFG
, &id
, sizeof(bootrom_id_t
));
683 dbus_usbos_wait(osinfo
, USB_RESETCFG_SPINWAIT
);
686 DBUSERR(("%s: Cannot talk to Dongle. Firmware is not UP, %d ms \n",
687 __FUNCTION__
, wait
));
694 /** before firmware download, the dongle has to be prepared to receive the fw image */
696 dbus_usb_rdl_dwnld_state(usb_info_t
*usbinfo
)
698 void *osinfo
= usbinfo
->usbosl_info
;
702 /* 1) Prepare USB boot loader for runtime image */
703 dbus_usbos_dl_cmd(osinfo
, DL_START
, &state
, sizeof(rdl_state_t
));
705 state
.state
= ltoh32(state
.state
);
706 state
.bytes
= ltoh32(state
.bytes
);
708 /* 2) Check we are in the Waiting state */
709 if (state
.state
!= DL_WAITING
) {
710 DBUSERR(("%s: Failed to DL_START\n", __FUNCTION__
));
720 * Dongle contains bootcode in ROM but firmware is (partially) contained in dongle RAM. Therefore,
721 * firmware has to be downloaded into dongle RAM.
724 dbus_usb_dl_writeimage(usb_info_t
*usbinfo
, uint8
*fw
, int fwlen
)
726 osl_t
*osh
= usbinfo
->pub
->osh
;
727 void *osinfo
= usbinfo
->usbosl_info
;
728 unsigned int sendlen
, sent
, dllen
, pktlen
;
729 char *bulkchunk
= NULL
, *dlpos
;
733 uint16 wait
, wait_time
;
735 bulkchunk
= MALLOC(osh
, RDL_CHUNK
);
736 if (bulkchunk
== NULL
) {
747 /* for SuperSpeed with non-disconnect target, need to make sure */
748 /* bulk out write times can divided by 32 to keep SeqN is 0 */
749 pktlen
= (fwlen
+ RDL_CHUNK
- 1)/RDL_CHUNK
;
751 pktlen
= (pktlen
/32 + 1)*32;
753 pktlen
= (dllen
+ pktlen
- 1)/pktlen
;
754 #endif /* BCM_USB30 */
756 /* Get chip id and rev */
757 id
.chip
= usbinfo
->pub
->attrib
.devid
;
758 id
.chiprev
= usbinfo
->pub
->attrib
.chiprev
;
760 DBUSTRACE(("enter %s: fwlen=%d\n", __FUNCTION__
, fwlen
));
762 dbus_usbos_dl_cmd(osinfo
, DL_GETSTATE
, &state
, sizeof(rdl_state_t
));
764 /* 3) Load the image */
765 while ((sent
< dllen
)) {
766 /* Wait until the usb device reports it received all the bytes we sent */
769 if ((dllen
-sent
) < pktlen
)
770 sendlen
= dllen
-sent
;
775 /* simply avoid having to send a ZLP by ensuring we never have an even
780 #endif /* BCM_USB30 */
782 memcpy(bulkchunk
, dlpos
, sendlen
);
783 if (!dbus_usbos_dl_send_bulk(osinfo
, bulkchunk
, sendlen
)) {
790 DBUSTRACE(("%s: sendlen %d\n", __FUNCTION__
, sendlen
));
794 wait_time
= USB_SFLASH_DLIMAGE_SPINWAIT
;
795 while (!dbus_usbos_dl_cmd(osinfo
, DL_GETSTATE
, &state
,
796 sizeof(rdl_state_t
))) {
797 if ((id
.chip
== 43236) && (id
.chiprev
== 0)) {
798 DBUSERR(("%s: 43236a0 SFlash delay, waiting for dongle crc check "
799 "completion!!!\n", __FUNCTION__
));
800 dbus_usbos_wait(osinfo
, wait_time
);
802 if (wait
>= USB_SFLASH_DLIMAGE_LIMIT
) {
803 DBUSERR(("%s: DL_GETSTATE Failed xxxx\n", __FUNCTION__
));
809 DBUSERR(("%s: DL_GETSTATE Failed xxxx\n", __FUNCTION__
));
815 state
.state
= ltoh32(state
.state
);
816 state
.bytes
= ltoh32(state
.bytes
);
818 /* restart if an error is reported */
819 if ((state
.state
== DL_BAD_HDR
) || (state
.state
== DL_BAD_CRC
)) {
820 DBUSERR(("%s: Bad Hdr or Bad CRC\n", __FUNCTION__
));
828 MFREE(osh
, bulkchunk
, RDL_CHUNK
);
833 /** Higher level DBUS layer (dbus.c) requests this layer to download image into dongle */
835 dbus_usb_dlstart(void *bus
, uint8
*fw
, int len
)
837 usb_info_t
*usbinfo
= BUS_INFO(bus
, usb_info_t
);
840 DBUSTRACE(("%s\n", __FUNCTION__
));
845 if (USB_DEV_ISBAD(usbinfo
))
848 err
= dbus_usb_rdl_dwnld_state(usbinfo
);
850 if (DBUS_OK
== err
) {
851 err
= dbus_usb_dl_writeimage(usbinfo
, fw
, len
);
853 usbinfo
->pub
->busstate
= DBUS_STATE_DL_DONE
;
855 usbinfo
->pub
->busstate
= DBUS_STATE_DL_PENDING
;
857 usbinfo
->pub
->busstate
= DBUS_STATE_DL_PENDING
;
862 dbus_usb_update_chipinfo(usb_info_t
*usbinfo
, uint32 chip
)
865 /* based on the CHIP Id, store the ram size which is needed for NVRAM download. */
869 usbinfo
->rdlram_size
= RDL_RAM_SIZE_4319
;
870 usbinfo
->rdlram_base_addr
= RDL_RAM_BASE_4319
;
874 usbinfo
->rdlram_size
= RDL_RAM_SIZE_4329
;
875 usbinfo
->rdlram_base_addr
= RDL_RAM_BASE_4329
;
882 usbinfo
->rdlram_size
= RDL_RAM_SIZE_43236
;
883 usbinfo
->rdlram_base_addr
= RDL_RAM_BASE_43236
;
887 usbinfo
->rdlram_size
= RDL_RAM_SIZE_4328
;
888 usbinfo
->rdlram_base_addr
= RDL_RAM_BASE_4328
;
892 usbinfo
->rdlram_size
= RDL_RAM_SIZE_4322
;
893 usbinfo
->rdlram_base_addr
= RDL_RAM_BASE_4322
;
898 usbinfo
->rdlram_size
= RDL_RAM_SIZE_4360
;
899 usbinfo
->rdlram_base_addr
= RDL_RAM_BASE_4360
;
903 usbinfo
->rdlram_size
= RDL_RAM_SIZE_43242
;
904 usbinfo
->rdlram_base_addr
= RDL_RAM_BASE_43242
;
908 usbinfo
->rdlram_size
= RDL_RAM_SIZE_43143
;
909 usbinfo
->rdlram_base_addr
= RDL_RAM_BASE_43143
;
913 usbinfo
->rdlram_size
= RDL_RAM_SIZE_4350
;
914 usbinfo
->rdlram_base_addr
= RDL_RAM_BASE_4350
;
921 DBUSERR(("%s: Chip 0x%x Ram size is not known\n", __FUNCTION__
, chip
));
930 /** higher DBUS level (dbus.c) wants to know if firmware download is required. */
932 dbus_usb_dlneeded(void *bus
)
934 usb_info_t
*usbinfo
= BUS_INFO(bus
, usb_info_t
);
937 bool dl_needed
= TRUE
;
939 DBUSTRACE(("%s\n", __FUNCTION__
));
944 osinfo
= usbinfo
->usbosl_info
;
947 /* Check if firmware downloaded already by querying runtime ID */
949 dbus_usbos_dl_cmd(osinfo
, DL_GETVER
, &id
, sizeof(bootrom_id_t
));
951 id
.chip
= ltoh32(id
.chip
);
952 id
.chiprev
= ltoh32(id
.chiprev
);
954 if (FALSE
== dbus_usb_update_chipinfo(usbinfo
, id
.chip
)) {
959 DBUSERR(("%s: chip 0x%x rev 0x%x\n", __FUNCTION__
, id
.chip
, id
.chiprev
));
960 if (id
.chip
== POSTBOOT_ID
) {
961 /* This code is needed to support two enumerations on USB1.1 scenario */
962 DBUSERR(("%s: Firmware already downloaded\n", __FUNCTION__
));
964 dbus_usbos_dl_cmd(osinfo
, DL_RESETCFG
, &id
, sizeof(bootrom_id_t
));
966 if (usbinfo
->pub
->busstate
== DBUS_STATE_DL_PENDING
)
967 usbinfo
->pub
->busstate
= DBUS_STATE_DL_DONE
;
969 usbinfo
->pub
->attrib
.devid
= id
.chip
;
970 usbinfo
->pub
->attrib
.chiprev
= id
.chiprev
;
977 /** After issuing firmware download, higher DBUS level (dbus.c) wants to start the firmware. */
979 dbus_usb_dlrun(void *bus
)
981 usb_info_t
*usbinfo
= BUS_INFO(bus
, usb_info_t
);
986 DBUSTRACE(("%s\n", __FUNCTION__
));
991 if (USB_DEV_ISBAD(usbinfo
))
994 osinfo
= usbinfo
->usbosl_info
;
997 /* Check we are runnable */
998 dbus_usbos_dl_cmd(osinfo
, DL_GETSTATE
, &state
, sizeof(rdl_state_t
));
1000 state
.state
= ltoh32(state
.state
);
1001 state
.bytes
= ltoh32(state
.bytes
);
1003 /* Start the image */
1004 if (state
.state
== DL_RUNNABLE
) {
1005 DBUSTRACE(("%s: Issue DL_GO\n", __FUNCTION__
));
1006 dbus_usbos_dl_cmd(osinfo
, DL_GO
, &state
, sizeof(rdl_state_t
));
1008 if (usbinfo
->pub
->attrib
.devid
== TEST_CHIP
)
1009 dbus_usbos_wait(osinfo
, USB_DLGO_SPINWAIT
);
1011 dbus_usb_resetcfg(usbinfo
);
1012 /* The Donlge may go for re-enumeration. */
1014 DBUSERR(("%s: Dongle not runnable\n", __FUNCTION__
));
1022 * As preparation for firmware download, higher DBUS level (dbus.c) requests the firmware image
1023 * to be used for the type of dongle detected. Directly called by dbus.c (so not via a callback
1027 dbus_bus_fw_get(void *bus
, uint8
**fw
, int *fwlen
, int *decomp
)
1029 usb_info_t
*usbinfo
= BUS_INFO(bus
, usb_info_t
);
1033 devid
= usbinfo
->pub
->attrib
.devid
;
1034 crev
= usbinfo
->pub
->attrib
.chiprev
;
1040 case BCM43236_CHIP_ID
:
1041 case BCM43235_CHIP_ID
:
1042 case BCM43234_CHIP_ID
:
1043 case BCM43238_CHIP_ID
: {
1044 if (crev
== 3 || crev
== 2 || crev
== 1) {
1045 #ifdef EMBED_IMAGE_43236b
1046 *fw
= (uint8
*)dlarray_43236b
;
1047 *fwlen
= sizeof(dlarray_43236b
);
1049 #ifdef EMBED_IMAGE_43238b
1050 *fw
= (uint8
*)dlarray_43238b
;
1051 *fwlen
= sizeof(dlarray_43238b
);
1056 case BCM4360_CHIP_ID
:
1057 #ifdef EMBED_IMAGE_4360b
1059 *fw
= (uint8
*)dlarray_4360b
;
1060 *fwlen
= sizeof(dlarray_4360b
);
1064 case BCM4352_CHIP_ID
:
1065 case BCM43526_CHIP_ID
:
1066 #ifdef EMBED_IMAGE_43526a
1068 *fw
= (uint8
*)dlarray_43526a
;
1069 *fwlen
= sizeof(dlarray_43526a
);
1072 #ifdef EMBED_IMAGE_43526b
1074 *fw
= (uint8
*)dlarray_43526b
;
1075 *fwlen
= sizeof(dlarray_43526b
);
1080 case BCM43242_CHIP_ID
:
1081 #ifdef EMBED_IMAGE_43242a0
1082 *fw
= (uint8
*)dlarray_43242a0
;
1083 *fwlen
= sizeof(dlarray_43242a0
);
1084 #elif defined(EMBED_IMAGE_43242a1)
1085 *fw
= (uint8
*)dlarray_43242a1
;
1086 *fwlen
= sizeof(dlarray_43242a1
);
1090 case BCM43143_CHIP_ID
:
1091 #ifdef EMBED_IMAGE_43143a0
1092 *fw
= (uint8
*)dlarray_43143a0
;
1093 *fwlen
= sizeof(dlarray_43143a0
);
1094 #elif defined(EMBED_IMAGE_43143b0)
1095 *fw
= (uint8
*)dlarray_43143b0
;
1096 *fwlen
= sizeof(dlarray_43143b0
);
1100 case BCM4350_CHIP_ID
:
1101 #ifdef EMBED_IMAGE_4350a0
1103 *fw
= (uint8
*)dlarray_4350a0
;
1104 *fwlen
= sizeof(dlarray_4350a0
);
1107 #ifdef EMBED_IMAGE_4350b0
1109 *fw
= (uint8
*)dlarray_4350b0
;
1110 *fwlen
= sizeof(dlarray_4350b0
);
1113 #ifdef EMBED_IMAGE_4350b1
1115 *fw
= (uint8
*)dlarray_4350b1
;
1116 *fwlen
= sizeof(dlarray_4350b1
);
1122 #ifdef EMBED_IMAGE_GENERIC
1123 *fw
= (uint8
*)dlarray
;
1124 *fwlen
= sizeof(dlarray
);
1130 #ifdef BCM_DNGL_EMBEDIMAGE
1132 dbus_usb_device_exists(void *bus
)
1134 usb_info_t
*usbinfo
= BUS_INFO(bus
, usb_info_t
);
1138 DBUSTRACE(("%s\n", __FUNCTION__
));
1140 if (usbinfo
== NULL
)
1143 osinfo
= usbinfo
->usbosl_info
;
1147 /* Query device to see if we get a response */
1148 dbus_usbos_dl_cmd(osinfo
, DL_GETVER
, &id
, sizeof(bootrom_id_t
));
1150 usbinfo
->pub
->attrib
.devid
= id
.chip
;
1151 if (id
.chip
== 0xDEAD)
1156 #endif /* BCM_DNGL_EMBEDIMAGE */