xref: /OK3568_Linux_fs/external/rkwifibt/drivers/bcmdhd/dbus_usb.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Dongle BUS interface for USB, OS independent
3  *
4  * Copyright (C) 1999-2016, Broadcom Corporation
5  *
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:
11  *
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.
19  *
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.
23  *
24  *
25  * <<Broadcom-WL-IPTag/Open:>>
26  *
27  * $Id: dbus_usb.c 565557 2015-06-22 19:29:44Z $
28  */
29 
30 /**
31  * @file @brief
32  * This file contains DBUS code that is USB, but not OS specific. DBUS is a Broadcom proprietary
33  * host specific abstraction layer.
34  */
35 
36 #include <osl.h>
37 #include <bcmdefs.h>
38 #include <bcmutils.h>
39 #include <dbus.h>
40 #include <usbrdl.h>
41 #include <bcmdevs_legacy.h>
42 #include <bcmdevs.h>
43 #include <bcmendian.h>
44 
45 uint dbus_msglevel = DBUS_ERROR_VAL;
46 module_param(dbus_msglevel, int, 0);
47 
48 
49 #define USB_DLIMAGE_RETRY_TIMEOUT    3000    /* retry Timeout */
50 #define USB_SFLASH_DLIMAGE_SPINWAIT  150     /* in unit of ms */
51 #define USB_SFLASH_DLIMAGE_LIMIT     2000    /* spinwait limit (ms) */
52 #define POSTBOOT_ID                  0xA123  /* ID to detect if dongle has boot up */
53 #define USB_RESETCFG_SPINWAIT        1       /* wait after resetcfg (ms) */
54 #define USB_DEV_ISBAD(u)             (u->pub->attrib.devid == 0xDEAD)
55 #define USB_DLGO_SPINWAIT            100     /* wait after DL_GO (ms) */
56 #define TEST_CHIP                    0x4328
57 
58 /* driver info, initialized when bcmsdh_register is called */
59 static dbus_driver_t drvinfo = {NULL, NULL, NULL, NULL};
60 
61 typedef struct {
62 	dbus_pub_t  *pub;
63 
64 	void        *cbarg;
65 	dbus_intf_callbacks_t *cbs;  /** callbacks into higher DBUS level (dbus.c) */
66 	dbus_intf_t *drvintf;
67 	void        *usbosl_info;
68 	uint32      rdlram_base_addr;
69 	uint32      rdlram_size;
70 } usb_info_t;
71 
72 /*
73  * Callbacks common to all USB
74  */
75 static void dbus_usb_disconnect(void *handle);
76 static void dbus_usb_send_irb_timeout(void *handle, dbus_irb_tx_t *txirb);
77 static void dbus_usb_send_irb_complete(void *handle, dbus_irb_tx_t *txirb, int status);
78 static void dbus_usb_recv_irb_complete(void *handle, dbus_irb_rx_t *rxirb, int status);
79 static void dbus_usb_errhandler(void *handle, int err);
80 static void dbus_usb_ctl_complete(void *handle, int type, int status);
81 static void dbus_usb_state_change(void *handle, int state);
82 static struct dbus_irb* dbus_usb_getirb(void *handle, bool send);
83 static void dbus_usb_rxerr_indicate(void *handle, bool on);
84 #if !defined(BCM_REQUEST_FW)
85 static int dbus_usb_resetcfg(usb_info_t *usbinfo);
86 #endif
87 static int dbus_usb_iovar_op(void *bus, const char *name,
88 	void *params, int plen, void *arg, int len, bool set);
89 static int dbus_iovar_process(usb_info_t* usbinfo, const char *name,
90                  void *params, int plen, void *arg, int len, bool set);
91 static int dbus_usb_doiovar(usb_info_t *bus, const bcm_iovar_t *vi, uint32 actionid,
92 	const char *name, void *params, int plen, void *arg, int len, int val_size);
93 static int dhdusb_downloadvars(usb_info_t *bus, void *arg, int len);
94 
95 static int dbus_usb_dl_writeimage(usb_info_t *usbinfo, uint8 *fw, int fwlen);
96 static int dbus_usb_dlstart(void *bus, uint8 *fw, int len);
97 static int dbus_usb_dlneeded(void *bus);
98 static int dbus_usb_dlrun(void *bus);
99 static int dbus_usb_rdl_dwnld_state(usb_info_t *usbinfo);
100 
101 
102 /* OS specific */
103 extern bool dbus_usbos_dl_cmd(void *info, uint8 cmd, void *buffer, int buflen);
104 extern int dbus_usbos_wait(void *info, uint16 ms);
105 extern int dbus_write_membytes(usb_info_t *usbinfo, bool set, uint32 address,
106 	uint8 *data, uint size);
107 extern bool dbus_usbos_dl_send_bulk(void *info, void *buffer, int len);
108 extern int dbus_usbos_loopback_tx(void *usbos_info_ptr, int cnt, int size);
109 
110 /**
111  * These functions are called by the lower DBUS level (dbus_usb_os.c) to notify this DBUS level
112  * (dbus_usb.c) of an event.
113  */
114 static dbus_intf_callbacks_t dbus_usb_intf_cbs = {
115 	dbus_usb_send_irb_timeout,
116 	dbus_usb_send_irb_complete,
117 	dbus_usb_recv_irb_complete,
118 	dbus_usb_errhandler,
119 	dbus_usb_ctl_complete,
120 	dbus_usb_state_change,
121 	NULL,			/* isr */
122 	NULL,			/* dpc */
123 	NULL,			/* watchdog */
124 	NULL,			/* dbus_if_pktget */
125 	NULL, 			/* dbus_if_pktfree */
126 	dbus_usb_getirb,
127 	dbus_usb_rxerr_indicate
128 };
129 
130 /* IOVar table */
131 enum {
132 	IOV_SET_DOWNLOAD_STATE = 1,
133 	IOV_DBUS_MSGLEVEL,
134 	IOV_MEMBYTES,
135 	IOV_VARS,
136 	IOV_LOOPBACK_TX
137 };
138 
139 const bcm_iovar_t dhdusb_iovars[] = {
140 	{"vars",	IOV_VARS,	0,	IOVT_BUFFER,	0 },
141 	{"dbus_msglevel",	IOV_DBUS_MSGLEVEL,	0,	IOVT_UINT32,	0 },
142 	{"dwnldstate",	IOV_SET_DOWNLOAD_STATE,	0,	IOVT_BOOL,	0 },
143 	{"membytes",	IOV_MEMBYTES,	0,	IOVT_BUFFER,	2 * sizeof(int) },
144 	{"usb_lb_txfer", IOV_LOOPBACK_TX, 0,    IOVT_BUFFER,    2 * sizeof(int) },
145 	{NULL, 0, 0, 0, 0 }
146 };
147 
148 /*
149  * Need global for probe() and disconnect() since
150  * attach() is not called at probe and detach()
151  * can be called inside disconnect()
152  */
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 */
155 
156 /*
157  * dbus_intf_t common to all USB
158  * These functions override dbus_usb_<os>.c.
159  */
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(uint16 bus_no, uint16 slot, uint32 hdrlen);
163 
164 /* functions */
165 
166 /**
167  * As part of DBUS initialization/registration, the higher level DBUS (dbus.c) needs to know what
168  * lower level DBUS functions to call (in both dbus_usb.c and dbus_usb_os.c).
169  */
170 static void *
dbus_usb_probe(uint16 bus_no,uint16 slot,uint32 hdrlen)171 dbus_usb_probe(uint16 bus_no, uint16 slot, uint32 hdrlen)
172 {
173 	DBUSTRACE(("%s(): \n", __FUNCTION__));
174 	if (drvinfo.probe) {
175 		if (g_dbusintf != NULL) {
176 			/* First, initialize all lower-level functions as default
177 			 * so that dbus.c simply calls directly to dbus_usb_os.c.
178 			 */
179 			bcopy(g_dbusintf, &dbus_usb_intf, sizeof(dbus_intf_t));
180 
181 			/* Second, selectively override functions we need, if any. */
182 			dbus_usb_intf.attach = dbus_usb_attach;
183 			dbus_usb_intf.detach = dbus_usb_detach;
184 			dbus_usb_intf.iovar_op = dbus_usb_iovar_op;
185 			dbus_usb_intf.dlstart = dbus_usb_dlstart;
186 			dbus_usb_intf.dlneeded = dbus_usb_dlneeded;
187 			dbus_usb_intf.dlrun = dbus_usb_dlrun;
188 		}
189 
190 		return drvinfo.probe(bus_no, slot, hdrlen);
191 	}
192 
193 	return NULL;
194 }
195 
196 static int
dbus_usb_suspend(void * handle)197 dbus_usb_suspend(void *handle)
198 {
199 	DBUSTRACE(("%s(): \n", __FUNCTION__));
200 
201 	if (drvinfo.suspend)
202 		return drvinfo.suspend(handle);
203 
204 	return BCME_OK;
205 }
206 
207 static int
dbus_usb_resume(void * handle)208 dbus_usb_resume(void *handle)
209 {
210 	DBUSTRACE(("%s(): \n", __FUNCTION__));
211 
212 	if (drvinfo.resume)
213 		drvinfo.resume(handle);
214 
215 	return 0;
216 }
217 
218 static dbus_driver_t dhd_usb_dbus = {
219 	dbus_usb_probe,
220 	dbus_usb_disconnect,
221 	dbus_usb_suspend,
222 	dbus_usb_resume
223 };
224 
225 /**
226  * On return, *intf contains this or lower-level DBUS functions to be called by higher
227  * level (dbus.c)
228  */
229 int
dbus_bus_register(dbus_driver_t * driver,dbus_intf_t ** intf)230 dbus_bus_register(dbus_driver_t *driver, dbus_intf_t **intf)
231 {
232 	int err;
233 
234 	DBUSTRACE(("%s(): \n", __FUNCTION__));
235 	drvinfo = *driver;
236 	*intf = &dbus_usb_intf;
237 
238 	err = dbus_bus_osl_register(&dhd_usb_dbus, &g_dbusintf);
239 
240 	ASSERT(g_dbusintf);
241 	return err;
242 }
243 
244 int
dbus_bus_deregister()245 dbus_bus_deregister()
246 {
247 	DBUSTRACE(("%s(): \n", __FUNCTION__));
248 	return dbus_bus_osl_deregister();
249 }
250 
251 /** initialization consists of registration followed by 'attach'. */
252 void *
dbus_usb_attach(dbus_pub_t * pub,void * cbarg,dbus_intf_callbacks_t * cbs)253 dbus_usb_attach(dbus_pub_t *pub, void *cbarg, dbus_intf_callbacks_t *cbs)
254 {
255 	usb_info_t *usb_info;
256 
257 	DBUSTRACE(("%s(): \n", __FUNCTION__));
258 
259 	if ((g_dbusintf == NULL) || (g_dbusintf->attach == NULL))
260 		return NULL;
261 
262 	/* Sanity check for BUS_INFO() */
263 	ASSERT(OFFSETOF(usb_info_t, pub) == 0);
264 
265 	usb_info = MALLOC(pub->osh, sizeof(usb_info_t));
266 	if (usb_info == NULL)
267 		return NULL;
268 
269 	bzero(usb_info, sizeof(usb_info_t));
270 
271 	usb_info->pub = pub;
272 	usb_info->cbarg = cbarg;
273 	usb_info->cbs = cbs;
274 
275 	usb_info->usbosl_info = (dbus_pub_t *)g_dbusintf->attach(pub,
276 		usb_info, &dbus_usb_intf_cbs);
277 	if (usb_info->usbosl_info == NULL) {
278 		MFREE(pub->osh, usb_info, sizeof(usb_info_t));
279 		return NULL;
280 	}
281 
282 	/* Save USB OS-specific driver entry points */
283 	usb_info->drvintf = g_dbusintf;
284 
285 	pub->bus = usb_info;
286 #if !defined(BCM_REQUEST_FW)
287 	if (!dbus_usb_resetcfg(usb_info)) {
288 		usb_info->pub->busstate = DBUS_STATE_DL_DONE;
289 	}
290 #endif
291 	/* Return Lower layer info */
292 	return (void *) usb_info->usbosl_info;
293 }
294 
295 void
dbus_usb_detach(dbus_pub_t * pub,void * info)296 dbus_usb_detach(dbus_pub_t *pub, void *info)
297 {
298 	usb_info_t *usb_info = (usb_info_t *) pub->bus;
299 	osl_t *osh = pub->osh;
300 
301 	if (usb_info == NULL)
302 		return;
303 
304 	if (usb_info->drvintf && usb_info->drvintf->detach)
305 		usb_info->drvintf->detach(pub, usb_info->usbosl_info);
306 
307 	MFREE(osh, usb_info, sizeof(usb_info_t));
308 }
309 
310 void
dbus_usb_disconnect(void * handle)311 dbus_usb_disconnect(void *handle)
312 {
313 	DBUSTRACE(("%s(): \n", __FUNCTION__));
314 	if (drvinfo.remove)
315 		drvinfo.remove(handle);
316 }
317 
318 /**
319  * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
320  * notified.
321  */
322 static void
dbus_usb_send_irb_timeout(void * handle,dbus_irb_tx_t * txirb)323 dbus_usb_send_irb_timeout(void *handle, dbus_irb_tx_t *txirb)
324 {
325 	usb_info_t *usb_info = (usb_info_t *) handle;
326 
327 	DBUSTRACE(("%s\n", __FUNCTION__));
328 
329 	if (usb_info == NULL)
330 		return;
331 
332 	if (usb_info->cbs && usb_info->cbs->send_irb_timeout)
333 		usb_info->cbs->send_irb_timeout(usb_info->cbarg, txirb);
334 }
335 
336 /**
337  * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
338  * notified.
339  */
340 static void
dbus_usb_send_irb_complete(void * handle,dbus_irb_tx_t * txirb,int status)341 dbus_usb_send_irb_complete(void *handle, dbus_irb_tx_t *txirb, int status)
342 {
343 	usb_info_t *usb_info = (usb_info_t *) handle;
344 
345 	if (usb_info == NULL)
346 		return;
347 
348 	if (usb_info->cbs && usb_info->cbs->send_irb_complete)
349 		usb_info->cbs->send_irb_complete(usb_info->cbarg, txirb, status);
350 }
351 
352 /**
353  * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
354  * notified.
355  */
356 static void
dbus_usb_recv_irb_complete(void * handle,dbus_irb_rx_t * rxirb,int status)357 dbus_usb_recv_irb_complete(void *handle, dbus_irb_rx_t *rxirb, int status)
358 {
359 	usb_info_t *usb_info = (usb_info_t *) handle;
360 
361 	if (usb_info == NULL)
362 		return;
363 
364 	if (usb_info->cbs && usb_info->cbs->recv_irb_complete)
365 		usb_info->cbs->recv_irb_complete(usb_info->cbarg, rxirb, status);
366 }
367 
368 /** Lower DBUS level (dbus_usb_os.c) requests a free IRB. Pass this on to the higher DBUS level. */
369 static struct dbus_irb*
dbus_usb_getirb(void * handle,bool send)370 dbus_usb_getirb(void *handle, bool send)
371 {
372 	usb_info_t *usb_info = (usb_info_t *) handle;
373 
374 	if (usb_info == NULL)
375 		return NULL;
376 
377 	if (usb_info->cbs && usb_info->cbs->getirb)
378 		return usb_info->cbs->getirb(usb_info->cbarg, send);
379 
380 	return NULL;
381 }
382 
383 /**
384  * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
385  * notified.
386  */
387 static void
dbus_usb_rxerr_indicate(void * handle,bool on)388 dbus_usb_rxerr_indicate(void *handle, bool on)
389 {
390 	usb_info_t *usb_info = (usb_info_t *) handle;
391 
392 	if (usb_info == NULL)
393 		return;
394 
395 	if (usb_info->cbs && usb_info->cbs->rxerr_indicate)
396 		usb_info->cbs->rxerr_indicate(usb_info->cbarg, on);
397 }
398 
399 /**
400  * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
401  * notified.
402  */
403 static void
dbus_usb_errhandler(void * handle,int err)404 dbus_usb_errhandler(void *handle, int err)
405 {
406 	usb_info_t *usb_info = (usb_info_t *) handle;
407 
408 	if (usb_info == NULL)
409 		return;
410 
411 	if (usb_info->cbs && usb_info->cbs->errhandler)
412 		usb_info->cbs->errhandler(usb_info->cbarg, err);
413 }
414 
415 /**
416  * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
417  * notified.
418  */
419 static void
dbus_usb_ctl_complete(void * handle,int type,int status)420 dbus_usb_ctl_complete(void *handle, int type, int status)
421 {
422 	usb_info_t *usb_info = (usb_info_t *) handle;
423 
424 	DBUSTRACE(("%s\n", __FUNCTION__));
425 
426 	if (usb_info == NULL) {
427 		DBUSERR(("%s: usb_info is NULL\n", __FUNCTION__));
428 		return;
429 	}
430 
431 	if (usb_info->cbs && usb_info->cbs->ctl_complete)
432 		usb_info->cbs->ctl_complete(usb_info->cbarg, type, status);
433 }
434 
435 /**
436  * When the lower DBUS level (dbus_usb_os.c) signals this event, the higher DBUS level has to be
437  * notified.
438  */
439 static void
dbus_usb_state_change(void * handle,int state)440 dbus_usb_state_change(void *handle, int state)
441 {
442 	usb_info_t *usb_info = (usb_info_t *) handle;
443 
444 	if (usb_info == NULL)
445 		return;
446 
447 	if (usb_info->cbs && usb_info->cbs->state_change)
448 		usb_info->cbs->state_change(usb_info->cbarg, state);
449 }
450 
451 /** called by higher DBUS level (dbus.c) */
452 static int
dbus_usb_iovar_op(void * bus,const char * name,void * params,int plen,void * arg,int len,bool set)453 dbus_usb_iovar_op(void *bus, const char *name,
454 	void *params, int plen, void *arg, int len, bool set)
455 {
456 	int err = DBUS_OK;
457 
458 	err = dbus_iovar_process((usb_info_t*)bus, name, params, plen, arg, len, set);
459 	return err;
460 }
461 
462 /** process iovar request from higher DBUS level */
463 static int
dbus_iovar_process(usb_info_t * usbinfo,const char * name,void * params,int plen,void * arg,int len,bool set)464 dbus_iovar_process(usb_info_t* usbinfo, const char *name,
465                  void *params, int plen, void *arg, int len, bool set)
466 {
467 	const bcm_iovar_t *vi = NULL;
468 	int bcmerror = 0;
469 	int val_size;
470 	uint32 actionid;
471 
472 	DBUSTRACE(("%s: Enter\n", __FUNCTION__));
473 
474 	ASSERT(name);
475 	ASSERT(len >= 0);
476 
477 	/* Get MUST have return space */
478 	ASSERT(set || (arg && len));
479 
480 	/* Set does NOT take qualifiers */
481 	ASSERT(!set || (!params && !plen));
482 
483 	/* Look up var locally; if not found pass to host driver */
484 	if ((vi = bcm_iovar_lookup(dhdusb_iovars, name)) == NULL) {
485 		/* Not Supported */
486 		bcmerror = BCME_UNSUPPORTED;
487 		DBUSTRACE(("%s: IOVAR %s is not supported\n", name, __FUNCTION__));
488 		goto exit;
489 
490 	}
491 
492 	DBUSTRACE(("%s: %s %s, len %d plen %d\n", __FUNCTION__,
493 	         name, (set ? "set" : "get"), len, plen));
494 
495 	/* set up 'params' pointer in case this is a set command so that
496 	 * the convenience int and bool code can be common to set and get
497 	 */
498 	if (params == NULL) {
499 		params = arg;
500 		plen = len;
501 	}
502 
503 	if (vi->type == IOVT_VOID)
504 		val_size = 0;
505 	else if (vi->type == IOVT_BUFFER)
506 		val_size = len;
507 	else
508 		/* all other types are integer sized */
509 		val_size = sizeof(int);
510 
511 	actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
512 	bcmerror = dbus_usb_doiovar(usbinfo, vi, actionid,
513 		name, params, plen, arg, len, val_size);
514 
515 exit:
516 	return bcmerror;
517 } /* dbus_iovar_process */
518 
519 static int
dbus_usb_doiovar(usb_info_t * bus,const bcm_iovar_t * vi,uint32 actionid,const char * name,void * params,int plen,void * arg,int len,int val_size)520 dbus_usb_doiovar(usb_info_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name,
521                 void *params, int plen, void *arg, int len, int val_size)
522 {
523 	int bcmerror = 0;
524 	int32 int_val = 0;
525 	int32 int_val2 = 0;
526 	bool bool_val = 0;
527 
528 	DBUSTRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n",
529 	           __FUNCTION__, actionid, name, params, plen, arg, len, val_size));
530 
531 	if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0)
532 		goto exit;
533 
534 	if (plen >= (int)sizeof(int_val))
535 		bcopy(params, &int_val, sizeof(int_val));
536 
537 	if (plen >= (int)sizeof(int_val) * 2)
538 		bcopy((void*)((uintptr)params + sizeof(int_val)), &int_val2, sizeof(int_val2));
539 
540 	bool_val = (int_val != 0) ? TRUE : FALSE;
541 
542 	switch (actionid) {
543 
544 	case IOV_SVAL(IOV_MEMBYTES):
545 	case IOV_GVAL(IOV_MEMBYTES):
546 	{
547 		uint32 address;
548 		uint size, dsize;
549 		uint8 *data;
550 
551 		bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));
552 
553 		ASSERT(plen >= 2*sizeof(int));
554 
555 		address = (uint32)int_val;
556 		BCM_REFERENCE(address);
557 		bcopy((char *)params + sizeof(int_val), &int_val, sizeof(int_val));
558 		size = (uint)int_val;
559 
560 		/* Do some validation */
561 		dsize = set ? plen - (2 * sizeof(int)) : len;
562 		if (dsize < size) {
563 			DBUSTRACE(("%s: error on %s membytes, addr 0x%08x size %d dsize %d\n",
564 			           __FUNCTION__, (set ? "set" : "get"), address, size, dsize));
565 			bcmerror = BCME_BADARG;
566 			break;
567 		}
568 		DBUSTRACE(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__,
569 		          (set ? "write" : "read"), size, address));
570 
571 		/* Generate the actual data pointer */
572 		data = set ? (uint8*)params + 2 * sizeof(int): (uint8*)arg;
573 
574 		/* Call to do the transfer */
575 		bcmerror = dbus_usb_dl_writeimage(BUS_INFO(bus, usb_info_t), data, size);
576 	}
577 		break;
578 
579 
580 	case IOV_SVAL(IOV_SET_DOWNLOAD_STATE):
581 
582 		if (bool_val == TRUE) {
583 			bcmerror = dbus_usb_dlneeded(bus);
584 			dbus_usb_rdl_dwnld_state(BUS_INFO(bus, usb_info_t));
585 		} else {
586 			usb_info_t *usbinfo = BUS_INFO(bus, usb_info_t);
587 			bcmerror = dbus_usb_dlrun(bus);
588 			usbinfo->pub->busstate = DBUS_STATE_DL_DONE;
589 		}
590 		break;
591 
592 	case IOV_SVAL(IOV_VARS):
593 		bcmerror = dhdusb_downloadvars(BUS_INFO(bus, usb_info_t), arg, len);
594 		break;
595 
596 	case IOV_GVAL(IOV_DBUS_MSGLEVEL):
597 		int_val = (int32)dbus_msglevel;
598 		bcopy(&int_val, arg, val_size);
599 		break;
600 
601 	case IOV_SVAL(IOV_DBUS_MSGLEVEL):
602 		dbus_msglevel = int_val;
603 		break;
604 
605 #ifdef DBUS_USB_LOOPBACK
606 	case IOV_SVAL(IOV_LOOPBACK_TX):
607 			bcmerror = dbus_usbos_loopback_tx(BUS_INFO(bus, usb_info_t), int_val,
608 			  int_val2);
609 			break;
610 #endif
611 	default:
612 		bcmerror = BCME_UNSUPPORTED;
613 		break;
614 	}
615 
616 exit:
617 	return bcmerror;
618 } /* dbus_usb_doiovar */
619 
620 /** higher DBUS level (dbus.c) wants to set NVRAM variables in dongle */
621 static int
dhdusb_downloadvars(usb_info_t * bus,void * arg,int len)622 dhdusb_downloadvars(usb_info_t *bus, void *arg, int len)
623 {
624 	int bcmerror = 0;
625 	uint32 varsize;
626 	uint32 varaddr;
627 	uint32 varsizew;
628 
629 	if (!len) {
630 		bcmerror = BCME_BUFTOOSHORT;
631 		goto err;
632 	}
633 
634 	/* RAM size is not set. Set it at dbus_usb_dlneeded */
635 	if (!bus->rdlram_size)
636 		bcmerror = BCME_ERROR;
637 
638 	/* Even if there are no vars are to be written, we still need to set the ramsize. */
639 	varsize = len ? ROUNDUP(len, 4) : 0;
640 	varaddr = (bus->rdlram_size - 4) - varsize;
641 
642 	/* Write the vars list */
643 	DBUSTRACE(("WriteVars: @%x varsize=%d\n", varaddr, varsize));
644 	bcmerror = dbus_write_membytes(bus->usbosl_info, TRUE, (varaddr + bus->rdlram_base_addr),
645 		arg, varsize);
646 
647 	/* adjust to the user specified RAM */
648 	DBUSTRACE(("Usable memory size: %d\n", bus->rdlram_size));
649 	DBUSTRACE(("Vars are at %d, orig varsize is %d\n", varaddr, varsize));
650 
651 	varsize = ((bus->rdlram_size - 4) - varaddr);
652 
653 	/*
654 	 * Determine the length token:
655 	 * Varsize, converted to words, in lower 16-bits, checksum in upper 16-bits.
656 	 */
657 	if (bcmerror) {
658 		varsizew = 0;
659 	} else {
660 		varsizew = varsize / 4;
661 		varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
662 		varsizew = htol32(varsizew);
663 	}
664 
665 	DBUSTRACE(("New varsize is %d, length token=0x%08x\n", varsize, varsizew));
666 
667 	/* Write the length token to the last word */
668 	bcmerror = dbus_write_membytes(bus->usbosl_info, TRUE, ((bus->rdlram_size - 4) +
669 		bus->rdlram_base_addr), (uint8*)&varsizew, 4);
670 err:
671 	return bcmerror;
672 } /* dbus_usb_doiovar */
673 
674 #if !defined(BCM_REQUEST_FW)
675 /**
676  * After downloading firmware into dongle and starting it, we need to know if the firmware is
677  * indeed up and running.
678  */
679 static int
dbus_usb_resetcfg(usb_info_t * usbinfo)680 dbus_usb_resetcfg(usb_info_t *usbinfo)
681 {
682 	void *osinfo;
683 	bootrom_id_t id;
684 	uint16 waittime = 0;
685 
686 	uint32 starttime = 0;
687 	uint32 endtime = 0;
688 
689 	DBUSTRACE(("%s\n", __FUNCTION__));
690 
691 	if (usbinfo == NULL)
692 		return DBUS_ERR;
693 
694 	osinfo = usbinfo->usbosl_info;
695 	ASSERT(osinfo);
696 
697 	/* Give dongle chance to boot */
698 	dbus_usbos_wait(osinfo, USB_SFLASH_DLIMAGE_SPINWAIT);
699 	waittime = USB_SFLASH_DLIMAGE_SPINWAIT;
700 	while (waittime < USB_DLIMAGE_RETRY_TIMEOUT) {
701 
702 		starttime = OSL_SYSUPTIME();
703 
704 		id.chip = 0xDEAD;       /* Get the ID */
705 		dbus_usbos_dl_cmd(osinfo, DL_GETVER, &id, sizeof(bootrom_id_t));
706 		id.chip = ltoh32(id.chip);
707 
708 		endtime = OSL_SYSUPTIME();
709 		waittime += (endtime - starttime);
710 
711 		if (id.chip == POSTBOOT_ID)
712 			break;
713 	}
714 
715 	if (id.chip == POSTBOOT_ID) {
716 		DBUSERR(("%s: download done. Bootup time = %d ms postboot chip 0x%x/rev 0x%x\n",
717 			__FUNCTION__, waittime, id.chip, id.chiprev));
718 
719 		dbus_usbos_dl_cmd(osinfo, DL_RESETCFG, &id, sizeof(bootrom_id_t));
720 
721 		dbus_usbos_wait(osinfo, USB_RESETCFG_SPINWAIT);
722 		return DBUS_OK;
723 	} else {
724 		DBUSERR(("%s: Cannot talk to Dongle. Wait time = %d ms. Firmware is not UP \n",
725 			__FUNCTION__, waittime));
726 		return DBUS_ERR;
727 	}
728 
729 	return DBUS_OK;
730 }
731 #endif
732 
733 /** before firmware download, the dongle has to be prepared to receive the fw image */
734 static int
dbus_usb_rdl_dwnld_state(usb_info_t * usbinfo)735 dbus_usb_rdl_dwnld_state(usb_info_t *usbinfo)
736 {
737 	void *osinfo = usbinfo->usbosl_info;
738 	rdl_state_t state;
739 	int err = DBUS_OK;
740 
741 	/* 1) Prepare USB boot loader for runtime image */
742 	dbus_usbos_dl_cmd(osinfo, DL_START, &state, sizeof(rdl_state_t));
743 
744 	state.state = ltoh32(state.state);
745 	state.bytes = ltoh32(state.bytes);
746 
747 	/* 2) Check we are in the Waiting state */
748 	if (state.state != DL_WAITING) {
749 		DBUSERR(("%s: Failed to DL_START\n", __FUNCTION__));
750 		err = DBUS_ERR;
751 		goto fail;
752 	}
753 
754 fail:
755 	return err;
756 }
757 
758 /**
759  * Dongle contains bootcode in ROM but firmware is (partially) contained in dongle RAM. Therefore,
760  * firmware has to be downloaded into dongle RAM.
761  */
762 static int
dbus_usb_dl_writeimage(usb_info_t * usbinfo,uint8 * fw,int fwlen)763 dbus_usb_dl_writeimage(usb_info_t *usbinfo, uint8 *fw, int fwlen)
764 {
765 	osl_t *osh = usbinfo->pub->osh;
766 	void *osinfo = usbinfo->usbosl_info;
767 	unsigned int sendlen, sent, dllen;
768 	char *bulkchunk = NULL, *dlpos;
769 	rdl_state_t state;
770 	int err = DBUS_OK;
771 	bootrom_id_t id;
772 	uint16 wait, wait_time;
773 	uint32 dl_trunk_size = RDL_CHUNK;
774 
775 	if (BCM4350_CHIP(usbinfo->pub->attrib.devid))
776 		dl_trunk_size = RDL_CHUNK_MAX;
777 
778 	while (!bulkchunk) {
779 		bulkchunk = MALLOC(osh, dl_trunk_size);
780 		if (dl_trunk_size == RDL_CHUNK)
781 			break;
782 		if (!bulkchunk) {
783 			dl_trunk_size /= 2;
784 			if (dl_trunk_size < RDL_CHUNK)
785 				dl_trunk_size = RDL_CHUNK;
786 		}
787 	}
788 
789 	if (bulkchunk == NULL) {
790 		err = DBUS_ERR;
791 		goto fail;
792 	}
793 
794 	sent = 0;
795 	dlpos = fw;
796 	dllen = fwlen;
797 
798 	/* Get chip id and rev */
799 	id.chip = usbinfo->pub->attrib.devid;
800 	id.chiprev = usbinfo->pub->attrib.chiprev;
801 
802 	DBUSTRACE(("enter %s: fwlen=%d\n", __FUNCTION__, fwlen));
803 
804 	dbus_usbos_dl_cmd(osinfo, DL_GETSTATE, &state, sizeof(rdl_state_t));
805 
806 	/* 3) Load the image */
807 	while ((sent < dllen)) {
808 		/* Wait until the usb device reports it received all the bytes we sent */
809 
810 		if (sent < dllen) {
811 			if ((dllen-sent) < dl_trunk_size)
812 				sendlen = dllen-sent;
813 			else
814 				sendlen = dl_trunk_size;
815 
816 			/* simply avoid having to send a ZLP by ensuring we never have an even
817 			 * multiple of 64
818 			 */
819 			if (!(sendlen % 64))
820 				sendlen -= 4;
821 
822 			/* send data */
823 			memcpy(bulkchunk, dlpos, sendlen);
824 			if (!dbus_usbos_dl_send_bulk(osinfo, bulkchunk, sendlen)) {
825 				err = DBUS_ERR;
826 				goto fail;
827 			}
828 
829 			dlpos += sendlen;
830 			sent += sendlen;
831 			DBUSTRACE(("%s: sendlen %d\n", __FUNCTION__, sendlen));
832 		}
833 
834 		wait = 0;
835 		wait_time = USB_SFLASH_DLIMAGE_SPINWAIT;
836 		while (!dbus_usbos_dl_cmd(osinfo, DL_GETSTATE, &state,
837 			sizeof(rdl_state_t))) {
838 			if ((id.chip == 43236) && (id.chiprev == 0)) {
839 				DBUSERR(("%s: 43236a0 SFlash delay, waiting for dongle crc check "
840 					 "completion!!!\n", __FUNCTION__));
841 				dbus_usbos_wait(osinfo, wait_time);
842 				wait += wait_time;
843 				if (wait >= USB_SFLASH_DLIMAGE_LIMIT) {
844 					DBUSERR(("%s: DL_GETSTATE Failed xxxx\n", __FUNCTION__));
845 					err = DBUS_ERR;
846 					goto fail;
847 					break;
848 				}
849 			} else {
850 				DBUSERR(("%s: DL_GETSTATE Failed xxxx\n", __FUNCTION__));
851 				err = DBUS_ERR;
852 				goto fail;
853 			}
854 		}
855 
856 		state.state = ltoh32(state.state);
857 		state.bytes = ltoh32(state.bytes);
858 
859 		/* restart if an error is reported */
860 		if ((state.state == DL_BAD_HDR) || (state.state == DL_BAD_CRC)) {
861 			DBUSERR(("%s: Bad Hdr or Bad CRC\n", __FUNCTION__));
862 			err = DBUS_ERR;
863 			goto fail;
864 		}
865 
866 	}
867 fail:
868 	if (bulkchunk)
869 		MFREE(osh, bulkchunk, dl_trunk_size);
870 
871 	return err;
872 } /* dbus_usb_dl_writeimage */
873 
874 /** Higher level DBUS layer (dbus.c) requests this layer to download image into dongle */
875 static int
dbus_usb_dlstart(void * bus,uint8 * fw,int len)876 dbus_usb_dlstart(void *bus, uint8 *fw, int len)
877 {
878 	usb_info_t *usbinfo = BUS_INFO(bus, usb_info_t);
879 	int err;
880 
881 	DBUSTRACE(("%s\n", __FUNCTION__));
882 
883 	if (usbinfo == NULL)
884 		return DBUS_ERR;
885 
886 	if (USB_DEV_ISBAD(usbinfo))
887 		return DBUS_ERR;
888 
889 	err = dbus_usb_rdl_dwnld_state(usbinfo);
890 
891 	if (DBUS_OK == err) {
892 		err = dbus_usb_dl_writeimage(usbinfo, fw, len);
893 		if (err == DBUS_OK)
894 			usbinfo->pub->busstate = DBUS_STATE_DL_DONE;
895 		else
896 			usbinfo->pub->busstate = DBUS_STATE_DL_PENDING;
897 	} else
898 		usbinfo->pub->busstate = DBUS_STATE_DL_PENDING;
899 
900 	return err;
901 }
902 
903 static bool
dbus_usb_update_chipinfo(usb_info_t * usbinfo,uint32 chip)904 dbus_usb_update_chipinfo(usb_info_t *usbinfo, uint32 chip)
905 {
906 	bool retval = TRUE;
907 	/* based on the CHIP Id, store the ram size which is needed for NVRAM download. */
908 	switch (chip) {
909 
910 		case 0x4319:
911 			usbinfo->rdlram_size = RDL_RAM_SIZE_4319;
912 			usbinfo->rdlram_base_addr = RDL_RAM_BASE_4319;
913 			break;
914 
915 		case 0x4329:
916 			usbinfo->rdlram_size = RDL_RAM_SIZE_4329;
917 			usbinfo->rdlram_base_addr = RDL_RAM_BASE_4329;
918 			break;
919 
920 		case 43234:
921 		case 43235:
922 		case 43236:
923 			usbinfo->rdlram_size = RDL_RAM_SIZE_43236;
924 			usbinfo->rdlram_base_addr = RDL_RAM_BASE_43236;
925 			break;
926 
927 		case 0x4328:
928 			usbinfo->rdlram_size = RDL_RAM_SIZE_4328;
929 			usbinfo->rdlram_base_addr = RDL_RAM_BASE_4328;
930 			break;
931 
932 		case 0x4322:
933 			usbinfo->rdlram_size = RDL_RAM_SIZE_4322;
934 			usbinfo->rdlram_base_addr = RDL_RAM_BASE_4322;
935 			break;
936 
937 		case 0x4360:
938 		case 0xAA06:
939 			usbinfo->rdlram_size = RDL_RAM_SIZE_4360;
940 			usbinfo->rdlram_base_addr = RDL_RAM_BASE_4360;
941 			break;
942 
943 		case 43242:
944 		case 43243:
945 			usbinfo->rdlram_size = RDL_RAM_SIZE_43242;
946 			usbinfo->rdlram_base_addr = RDL_RAM_BASE_43242;
947 			break;
948 
949 		case 43143:
950 			usbinfo->rdlram_size = RDL_RAM_SIZE_43143;
951 			usbinfo->rdlram_base_addr = RDL_RAM_BASE_43143;
952 			break;
953 
954 		case 0x4350:
955 		case 43556:
956 		case 43558:
957 		case 43569:
958 			usbinfo->rdlram_size = RDL_RAM_SIZE_4350;
959 			usbinfo->rdlram_base_addr = RDL_RAM_BASE_4350;
960 			break;
961 
962 		case POSTBOOT_ID:
963 			break;
964 
965 		default:
966 			DBUSERR(("%s: Chip 0x%x Ram size is not known\n", __FUNCTION__, chip));
967 			retval = FALSE;
968 			break;
969 
970 	}
971 
972 	return retval;
973 } /* dbus_usb_update_chipinfo */
974 
975 /** higher DBUS level (dbus.c) wants to know if firmware download is required. */
976 static int
dbus_usb_dlneeded(void * bus)977 dbus_usb_dlneeded(void *bus)
978 {
979 	usb_info_t *usbinfo = BUS_INFO(bus, usb_info_t);
980 	void *osinfo;
981 	bootrom_id_t id;
982 	int dl_needed = 1;
983 
984 	DBUSTRACE(("%s\n", __FUNCTION__));
985 
986 	if (usbinfo == NULL)
987 		return DBUS_ERR;
988 
989 	osinfo = usbinfo->usbosl_info;
990 	ASSERT(osinfo);
991 
992 	/* Check if firmware downloaded already by querying runtime ID */
993 	id.chip = 0xDEAD;
994 	dbus_usbos_dl_cmd(osinfo, DL_GETVER, &id, sizeof(bootrom_id_t));
995 
996 	id.chip = ltoh32(id.chip);
997 	id.chiprev = ltoh32(id.chiprev);
998 
999 	if (FALSE == dbus_usb_update_chipinfo(usbinfo, id.chip)) {
1000 		dl_needed = DBUS_ERR;
1001 		goto exit;
1002 	}
1003 
1004 	DBUSERR(("%s: chip 0x%x rev 0x%x\n", __FUNCTION__, id.chip, id.chiprev));
1005 	if (id.chip == POSTBOOT_ID) {
1006 		/* This code is  needed to support two enumerations on USB1.1 scenario */
1007 		DBUSERR(("%s: Firmware already downloaded\n", __FUNCTION__));
1008 
1009 		dbus_usbos_dl_cmd(osinfo, DL_RESETCFG, &id, sizeof(bootrom_id_t));
1010 		dl_needed = DBUS_OK;
1011 		if (usbinfo->pub->busstate == DBUS_STATE_DL_PENDING)
1012 			usbinfo->pub->busstate = DBUS_STATE_DL_DONE;
1013 	} else {
1014 		usbinfo->pub->attrib.devid = id.chip;
1015 		usbinfo->pub->attrib.chiprev = id.chiprev;
1016 	}
1017 
1018 exit:
1019 	return dl_needed;
1020 }
1021 
1022 /** After issuing firmware download, higher DBUS level (dbus.c) wants to start the firmware. */
1023 static int
dbus_usb_dlrun(void * bus)1024 dbus_usb_dlrun(void *bus)
1025 {
1026 	usb_info_t *usbinfo = BUS_INFO(bus, usb_info_t);
1027 	void *osinfo;
1028 	rdl_state_t state;
1029 	int err = DBUS_OK;
1030 
1031 	DBUSTRACE(("%s\n", __FUNCTION__));
1032 
1033 	if (usbinfo == NULL)
1034 		return DBUS_ERR;
1035 
1036 	if (USB_DEV_ISBAD(usbinfo))
1037 		return DBUS_ERR;
1038 
1039 	osinfo = usbinfo->usbosl_info;
1040 	ASSERT(osinfo);
1041 
1042 	/* Check we are runnable */
1043 	dbus_usbos_dl_cmd(osinfo, DL_GETSTATE, &state, sizeof(rdl_state_t));
1044 
1045 	state.state = ltoh32(state.state);
1046 	state.bytes = ltoh32(state.bytes);
1047 
1048 	/* Start the image */
1049 	if (state.state == DL_RUNNABLE) {
1050 		DBUSTRACE(("%s: Issue DL_GO\n", __FUNCTION__));
1051 		dbus_usbos_dl_cmd(osinfo, DL_GO, &state, sizeof(rdl_state_t));
1052 
1053 		if (usbinfo->pub->attrib.devid == TEST_CHIP)
1054 			dbus_usbos_wait(osinfo, USB_DLGO_SPINWAIT);
1055 
1056 //		dbus_usb_resetcfg(usbinfo);
1057 		/* The Donlge may go for re-enumeration. */
1058 	} else {
1059 		DBUSERR(("%s: Dongle not runnable\n", __FUNCTION__));
1060 		err = DBUS_ERR;
1061 	}
1062 
1063 	return err;
1064 }
1065 
1066 /**
1067  * As preparation for firmware download, higher DBUS level (dbus.c) requests the firmware image
1068  * to be used for the type of dongle detected. Directly called by dbus.c (so not via a callback
1069  * construction)
1070  */
1071 void
dbus_bus_fw_get(void * bus,uint8 ** fw,int * fwlen,int * decomp)1072 dbus_bus_fw_get(void *bus, uint8 **fw, int *fwlen, int *decomp)
1073 {
1074 	usb_info_t *usbinfo = BUS_INFO(bus, usb_info_t);
1075 	unsigned int devid;
1076 	unsigned int crev;
1077 
1078 	devid = usbinfo->pub->attrib.devid;
1079 	crev = usbinfo->pub->attrib.chiprev;
1080 
1081 	*fw = NULL;
1082 	*fwlen = 0;
1083 
1084 	switch (devid) {
1085 	case BCM43236_CHIP_ID:
1086 	case BCM43235_CHIP_ID:
1087 	case BCM43234_CHIP_ID:
1088 	case BCM43238_CHIP_ID: {
1089 		if (crev == 3 || crev == 2 || crev == 1) {
1090 #ifdef EMBED_IMAGE_43236b
1091 			*fw = (uint8 *)dlarray_43236b;
1092 			*fwlen = sizeof(dlarray_43236b);
1093 
1094 #endif
1095 		}
1096 		} break;
1097 	case BCM4360_CHIP_ID:
1098 	case BCM4352_CHIP_ID:
1099 	case BCM43526_CHIP_ID:
1100 #ifdef EMBED_IMAGE_43526a
1101 		if (crev <= 2) {
1102 			*fw = (uint8 *)dlarray_43526a;
1103 			*fwlen = sizeof(dlarray_43526a);
1104 		}
1105 #endif
1106 #ifdef EMBED_IMAGE_43526b
1107 		if (crev > 2) {
1108 			*fw = (uint8 *)dlarray_43526b;
1109 			*fwlen = sizeof(dlarray_43526b);
1110 		}
1111 #endif
1112 		break;
1113 
1114 	case BCM43242_CHIP_ID:
1115 #ifdef EMBED_IMAGE_43242a0
1116 		*fw = (uint8 *)dlarray_43242a0;
1117 		*fwlen = sizeof(dlarray_43242a0);
1118 #endif
1119 		break;
1120 
1121 	case BCM43143_CHIP_ID:
1122 #ifdef EMBED_IMAGE_43143a0
1123 		*fw = (uint8 *)dlarray_43143a0;
1124 		*fwlen = sizeof(dlarray_43143a0);
1125 #endif
1126 #ifdef EMBED_IMAGE_43143b0
1127 		*fw = (uint8 *)dlarray_43143b0;
1128 		*fwlen = sizeof(dlarray_43143b0);
1129 #endif
1130 		break;
1131 
1132 	case BCM4350_CHIP_ID:
1133 	case BCM4354_CHIP_ID:
1134 	case BCM43556_CHIP_ID:
1135 	case BCM43558_CHIP_ID:
1136 	case BCM43566_CHIP_ID:
1137 	case BCM43568_CHIP_ID:
1138 	case BCM43570_CHIP_ID:
1139 	case BCM4358_CHIP_ID:
1140 #ifdef EMBED_IMAGE_4350a0
1141 		if (crev == 0) {
1142 			*fw = (uint8 *)dlarray_4350a0;
1143 			*fwlen = sizeof(dlarray_4350a0);
1144 		}
1145 #endif
1146 #ifdef EMBED_IMAGE_4350b0
1147 		if (crev == 1) {
1148 			*fw = (uint8 *)dlarray_4350b0;
1149 			*fwlen = sizeof(dlarray_4350b0);
1150 		}
1151 #endif
1152 #ifdef EMBED_IMAGE_4350b1
1153 		if (crev == 2) {
1154 			*fw = (uint8 *)dlarray_4350b1;
1155 			*fwlen = sizeof(dlarray_4350b1);
1156 		}
1157 #endif
1158 #ifdef EMBED_IMAGE_43556b1
1159 		if (crev == 2) {
1160 			*fw = (uint8 *)dlarray_43556b1;
1161 			*fwlen = sizeof(dlarray_43556b1);
1162 		}
1163 #endif
1164 #ifdef EMBED_IMAGE_4350c0
1165 		if (crev == 3) {
1166 			*fw = (uint8 *)dlarray_4350c0;
1167 			*fwlen = sizeof(dlarray_4350c0);
1168 		}
1169 #endif /* EMBED_IMAGE_4350c0 */
1170 #ifdef EMBED_IMAGE_4350c1
1171 		if (crev == 4) {
1172 			*fw = (uint8 *)dlarray_4350c1;
1173 			*fwlen = sizeof(dlarray_4350c1);
1174 		}
1175 #endif /* EMBED_IMAGE_4350c1 */
1176 		break;
1177 	case BCM43569_CHIP_ID:
1178 #ifdef EMBED_IMAGE_43569a0
1179 		if (crev == 0) {
1180 			*fw = (uint8 *)dlarray_43569a0;
1181 			*fwlen = sizeof(dlarray_43569a0);
1182 		}
1183 #endif /* EMBED_IMAGE_43569a0 */
1184 		break;
1185 	default:
1186 #ifdef EMBED_IMAGE_GENERIC
1187 		*fw = (uint8 *)dlarray;
1188 		*fwlen = sizeof(dlarray);
1189 #endif
1190 		break;
1191 	}
1192 } /* dbus_bus_fw_get */
1193