3 * Common to all SDIO interface
5 * Copyright (C) 2012, Broadcom Corporation
8 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
9 * the contents of this file may not be disclosed to third parties, copied
10 * or duplicated in any form, in whole or in part, without the prior
11 * written permission of Broadcom Corporation.
13 * $Id: dbus_sdh.c 300516 2011-12-04 17:39:44Z $
22 #include <bcmendian.h>
35 #include <sbsdpcmdev.h>
38 #include <proto/ethernet.h>
39 #include <proto/802.1d.h>
40 #include <proto/802.11.h>
44 #if defined(BCM_DNGL_EMBEDIMAGE)
45 #ifdef EMBED_IMAGE_4325sd
46 #include "rtecdc_4325sd.h"
47 #endif /* EMBED_IMAGE_4325sd */
48 #ifdef EMBED_IMAGE_4319sd
49 #include "rtecdc_4319sd.h"
50 #endif /* EMBED_IMAGE_4319sd */
51 #ifdef EMBED_IMAGE_GENERIC
54 #endif /* BCM_DNGL_EMBEDIMAGE */
56 /* FIX: Some of these are brought in from dhdioctl.h. We'll move
57 * DHD-specific features/test code out of DBUS, but for now just don't
60 #define DHD_IOCTL_MAXLEN 8192
62 /* For pktgen iovar */
63 typedef struct dhd_pktgen
{
64 uint version
; /* To allow structure change tracking */
65 uint freq
; /* Max ticks between tx/rx attempts */
66 uint count
; /* Test packets to send/rcv each attempt */
67 uint print
; /* Print counts every <print> attempts */
68 uint total
; /* Total packets (or bursts) */
69 uint minlen
; /* Minimum length of packets to send */
70 uint maxlen
; /* Maximum length of packets to send */
71 uint numsent
; /* Count of test packets sent */
72 uint numrcvd
; /* Count of test packets received */
73 uint numfail
; /* Count of test send failures */
74 uint mode
; /* Test mode (type of test packets) */
75 uint stop
; /* Stop after this many tx failures */
78 /* Version in case structure changes */
79 #define DHD_PKTGEN_VERSION 2
81 /* Type of test packets to use */
82 #define DHD_PKTGEN_ECHO 1 /* Send echo requests */
83 #define DHD_PKTGEN_SEND 2 /* Send discard packets */
84 #define DHD_PKTGEN_RXBURST 3 /* Request dongle send N packets */
85 #define DHD_PKTGEN_RECV 4 /* Continuous rx from continuous tx dongle */
88 #define IDLE_IMMEDIATE (-1) /* Enter idle immediately (no timeout) */
89 /* Values for idleclock iovar: other values are the sd_divisor to use when idle */
90 #define IDLE_ACTIVE 0 /* Do not request any SD clock change when idle */
91 #define IDLE_STOP (-1) /* Request SD clock be stopped (and use SD1 mode) */
95 #define TXRETRIES 2 /* # of retries for tx frames */
97 #define DHD_RXBOUND 50 /* Default for max rx frames in one scheduling */
99 #define DHD_TXBOUND 20 /* Default for max tx frames in one scheduling */
100 #define DHD_TXMINMAX 1 /* Max tx frames if rx still pending */
102 #define MEMBLOCK 2048 /* Block size used for downloading of dongle image */
103 #define MAX_DATA_BUF (32 * 1024) /* which should be more than
104 * and to hold biggest glom possible
107 /* Packet alignment for most efficient SDIO (can change based on platform) */
111 #if !ISPOWEROF2(SDALIGN)
112 #error SDALIGN is not a power of 2!
115 /* Total length of frame header for dongle protocol */
116 #define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN)
118 #define SDPCM_RESERVE (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + SDALIGN)
120 #define SDPCM_RESERVE (SDPCM_HDRLEN + SDALIGN)
123 /* Space for header read, limit for data packets */
125 #define MAX_HDR_READ 32
126 #define MAX_RX_DATASZ 2048
128 /* Maximum milliseconds to wait for F2 to come up */
129 #define DHD_WAIT_F2RDY 4000
131 /* Value for ChipClockCSR during initial setup */
132 #define DHD_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ)
133 #define DHD_INIT_CLKCTL2 (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP)
135 /* Flags for SDH calls */
136 #define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
138 /* Packet free applicable unconditionally for sdio and sdspi. Contional if
139 * bufpool was present for gspi bus.
141 #define PKTFREE2() if ((sdio_info->bus != SPI_BUS) || sdio_info->usebufpool) \
142 dbus_sdcb_pktfree(sdio_info, pkt, FALSE);
165 dbus_pub_t
*pub
; /* Must be first */
168 dbus_intf_callbacks_t
*cbs
;
169 dbus_intf_t
*drvintf
;
172 /* FIX: Ported from dhd_info_t */
173 uint maxctl
; /* Max size rxctl request from proto to bus */
174 ulong rx_readahead_cnt
; /* Number of packets where header read-ahead was used. */
175 ulong tx_realloc
; /* Number of tx packets we had to realloc for headroom */
180 bool up
; /* Driver up/down (to OS) */
181 bool dongle_reset
; /* TRUE = DEVRESET put dongle into reset */
182 uint8 wme_dp
; /* wme discard priority */
184 sdctl_info_t rxctl_req
;
185 sdctl_info_t txctl_req
;
188 /* FIX: Ported from dhd_bus_t */
189 bcmsdh_info_t
*sdh
; /* Handle for BCMSDH calls */
190 si_t
*sih
; /* Handle for SI calls */
191 char *vars
; /* Variables (from CIS and/or other) */
192 uint varsz
; /* Size of variables buffer */
194 sdpcmd_regs_t
*regs
; /* Registers for SDIO core */
195 uint sdpcmrev
; /* SDIO core revision */
196 uint armrev
; /* CPU core revision */
197 uint ramrev
; /* SOCRAM core revision */
198 uint32 ramsize
; /* Size of RAM in SOCRAM (bytes) */
199 uint32 orig_ramsize
; /* Size of RAM in SOCRAM (bytes) */
201 uint32 bus
; /* gSPI or SDIO bus */
202 uint32 hostintmask
; /* Copy of Host Interrupt Mask */
203 uint32 intstatus
; /* Intstatus bits (events) pending */
204 bool dpc_sched
; /* Indicates DPC schedule (intrpt rcvd) */
205 bool fcstate
; /* State of dongle flow-control */
207 char *firmware_path
; /* module_param: path to firmware image */
208 char *nvram_path
; /* module_param: path to nvram vars file */
210 uint blocksize
; /* Block size of SDIO transfers */
211 uint roundup
; /* Max roundup limit */
213 struct pktq txq
; /* Queue length used for flow-control */
214 uint8 flowcontrol
; /* per prio flow control bitmask */
215 uint8 tx_seq
; /* Transmit sequence number (next) */
216 uint8 tx_max
; /* Maximum transmit sequence allowed */
218 uint8 hdrbuf
[MAX_HDR_READ
+ SDALIGN
];
219 uint8
*rxhdr
; /* Header of current rx frame (in hdrbuf) */
220 uint16 nextlen
; /* Next Read Len from last header */
221 uint8 rx_seq
; /* Receive sequence number (expected) */
222 bool rxskip
; /* Skip receive (awaiting NAK ACK) */
224 void *glomd
; /* Packet containing glomming descriptor */
225 void *glom
; /* Packet chain for glommed superframe */
226 uint glomerr
; /* Glom packet read errors */
228 uint8
*rxbuf
; /* Buffer for receiving control packets */
229 uint rxblen
; /* Allocated length of rxbuf */
230 uint8
*rxctl
; /* Aligned pointer into rxbuf */
231 uint8
*databuf
; /* Buffer for receiving big glom packet */
232 uint8
*dataptr
; /* Aligned pointer into databuf */
233 uint rxlen
; /* Length of valid data in buffer */
235 uint8 sdpcm_ver
; /* Bus protocol reported by dongle */
237 bool intr
; /* Use interrupts */
238 bool poll
; /* Use polling */
239 bool ipend
; /* Device interrupt is pending */
240 bool intdis
; /* Interrupts disabled by isr */
241 uint intrcount
; /* Count of device interrupt callbacks */
242 uint lastintrs
; /* Count as of last watchdog timer */
243 uint spurious
; /* Count of spurious interrupts */
244 uint pollrate
; /* Ticks between device polls */
245 uint polltick
; /* Tick counter */
246 uint pollcnt
; /* Count of active polls */
248 uint regfails
; /* Count of R_REG/W_REG failures */
250 uint clkstate
; /* State of sd and backplane clock(s) */
251 bool activity
; /* Activity flag for clock down */
252 int32 idletime
; /* Control for activity timeout */
253 uint32 idlecount
; /* Activity timeout counter */
254 int32 idleclock
; /* How to set bus driver when idle */
255 uint32 sd_divisor
; /* Speed control to bus driver */
256 uint32 sd_mode
; /* Mode control to bus driver */
257 uint32 sd_rxchain
; /* If bcmsdh api accepts PKT chains */
258 bool use_rxchain
; /* If dhd should use PKT chains */
259 bool sleeping
; /* Is SDIO bus sleeping? */
260 /* Field to decide if rx of control frames happen in rxbuf or lb-pool */
264 /* external loopback */
268 /* pktgen configuration */
269 uint pktgen_freq
; /* Ticks between bursts */
270 uint pktgen_count
; /* Packets to send each burst */
271 uint pktgen_print
; /* Bursts between count displays */
272 uint pktgen_total
; /* Stop after this many */
273 uint pktgen_minlen
; /* Minimum packet data len */
274 uint pktgen_maxlen
; /* Maximum packet data len */
275 uint pktgen_mode
; /* Configured mode: tx, rx, or echo */
276 uint pktgen_stop
; /* Number of tx failures causing stop */
278 /* active pktgen fields */
279 uint pktgen_tick
; /* Tick counter for bursts */
280 uint pktgen_ptick
; /* Burst counter for printing */
281 uint pktgen_sent
; /* Number of test packets generated */
282 uint pktgen_rcvd
; /* Number of test packets received */
283 uint pktgen_fail
; /* Number of failed send attempts */
284 uint16 pktgen_len
; /* Length of next packet to send */
287 /* Some additional counters */
288 uint tx_sderrs
; /* Count of tx attempts with sd errors */
289 uint fcqueued
; /* Tx packets that got queued */
290 uint rxrtx
; /* Count of rtx requests (NAK to dongle) */
291 uint rx_toolong
; /* Receive frames too long to receive */
292 uint rxc_errors
; /* SDIO errors when reading control frames */
293 uint rx_hdrfail
; /* SDIO errors on header reads */
294 uint rx_badhdr
; /* Bad received headers (roosync?) */
295 uint rx_badseq
; /* Mismatched rx sequence number */
296 uint fc_rcvd
; /* Number of flow-control events received */
297 uint fc_xoff
; /* Number which turned on flow-control */
298 uint fc_xon
; /* Number which turned off flow-control */
299 uint rxglomfail
; /* Failed deglom attempts */
300 uint rxglomframes
; /* Number of glom frames (superframes) */
301 uint rxglompkts
; /* Number of packets from glom frames */
302 uint f2rxhdrs
; /* Number of header reads */
303 uint f2rxdata
; /* Number of frame data reads */
304 uint f2txdata
; /* Number of f2 frame writes */
305 uint f1regdata
; /* Number of f1 register accesses */
310 sdio_info_t
*sdio_info
;
311 dbus_irb_tx_t
*txirb
;
317 sdio_info_t
*sdio_info
;
323 sdio_info_t
*sdio_info
;
333 #define CLK_PENDING 2 /* Not used yet */
336 #define DHD_NOPMU(dhd) (FALSE)
339 static int qcount
[NUMPRIO
];
343 uint dhd_txbound
= DHD_TXBOUND
;
344 uint dhd_rxbound
= DHD_RXBOUND
;
345 /* static uint dhd_txminmax = DHD_TXMINMAX; */
347 /* overrride the RAM size if possible */
348 #define DONGLE_MIN_MEMSIZE (128 *1024)
349 int dhd_dongle_memsize
= 0;
352 static bool dhd_alignctl
= TRUE
;
354 static bool sd1idle
= TRUE
;
356 static bool retrydata
= FALSE
;
357 #define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata)
360 /* At a watermark around 8 the spid hits underflow error. */
361 static const uint watermark
= 32;
363 static const uint watermark
= 8;
365 static const uint firstread
= 32;
368 /* Echo packet generator (SDIO), pkts/s */
369 extern uint dhd_pktgen
;
371 /* Echo packet len (0 => sawtooth, max 1800) */
372 extern uint dhd_pktgen_len
;
373 #define MAX_PKTGEN_LEN 1800
375 extern uint dhd_watchdog_ms
;
377 /* optionally set by a module_param_string() */
378 #define MOD_PARAM_PATHLEN 2048
379 char firmware_path
[MOD_PARAM_PATHLEN
];
380 char nvram_path
[MOD_PARAM_PATHLEN
];
383 extern uint dhd_intr
;
386 extern uint dhd_poll
;
388 /* Initial idletime behavior (immediate, never, or ticks) */
389 extern int dhd_idletime
;
390 #define DHD_IDLETIME_TICKS 1;
392 /* SDIO Drive Strength */
393 extern uint dhd_sdiod_drive_strength
;
395 /* Override to force tx queueing all the time */
396 extern uint dhd_force_tx_queueing
;
398 #define HDATLEN (firstread - (SDPCM_HDRLEN))
400 /* Retry count for register access failures */
401 static uint retry_limit
= 2;
403 /* Force even SD lengths (some host controllers mess up on odd bytes) */
405 static bool forcealign
= FALSE
;
407 static bool forcealign
= TRUE
;
411 * Default is to bring up eth1 immediately.
417 #define PKTALIGN(osh, p, len, align) \
421 datalign = (uintptr)PKTDATA((osh), (p)); \
422 datalign = ROUNDUP(datalign, (align)) - datalign; \
423 ASSERT(datalign < (align)); \
424 ASSERT(PKTLEN((osh), (p)) >= ((len) + datalign)); \
426 PKTPULL((osh), (p), (uint)datalign); \
427 PKTSETLEN((osh), (p), (len)); \
430 /* Limit on rounding up frames */
431 static uint max_roundup
= 512;
433 /* Try doing readahead */
434 static bool dhd_readahead
= TRUE
;
436 /* To check if there's window offered */
437 #define DATAOK(bus) \
438 (((uint8)(sdio_info->tx_max - sdio_info->tx_seq) != 0) && \
439 (((uint8)(sdio_info->tx_max - sdio_info->tx_seq) & 0x80) == 0))
441 /* Macros to get register read/write status */
442 /* NOTE: these assume a local dbus_sdio_bus_t *bus! */
444 #define R_SDREG(regvar, regaddr, retryvar) \
448 regvar = R_REG(sdio_info->pub->osh, regaddr); \
449 } while (bcmsdh_regfail(sdio_info->sdh) && (++retryvar <= retry_limit)); \
451 sdio_info->regfails += (retryvar-1); \
452 if (retryvar > retry_limit) { \
453 DBUSERR(("%s: FAILED" #regvar "READ, LINE %d\n", \
454 __FUNCTION__, __LINE__)); \
460 #define W_SDREG(regval, regaddr, retryvar) \
464 W_REG(sdio_info->pub->osh, regaddr, regval); \
465 } while (bcmsdh_regfail(sdio_info->sdh) && (++retryvar <= retry_limit)); \
467 sdio_info->regfails += (retryvar-1); \
468 if (retryvar > retry_limit) \
469 DBUSERR(("%s: FAILED REGISTER WRITE, LINE %d\n", \
470 __FUNCTION__, __LINE__)); \
476 #define SD_BUSTYPE SPI_BUS
478 /* check packet-available-interrupt in piggybacked dstatus */
479 #define PKT_AVAILABLE() (bcmsdh_get_dstatus(sdio_info->sdh) & STATUS_F2_PKT_AVAILABLE)
481 #define HOSTINTMASK (I_HMB_FC_CHANGE | I_HMB_HOST_INT)
483 #define GSPI_PR55150_BAILOUT \
485 uint32 dstatussw = bcmsdh_get_dstatus((void *)sdio_info->sdh); \
486 uint32 dstatushw = bcmsdh_cfg_read_word(sdio_info->sdh, \
487 SDIO_FUNC_0, SPID_STATUS_REG, NULL); \
488 uint32 intstatuserr = 0; \
491 R_SDREG(intstatuserr, &sdio_info->regs->intstatus, retries); \
492 printf("dstatussw = 0x%x, dstatushw = 0x%x, intstatus = 0x%x\n", \
493 dstatussw, dstatushw, intstatuserr); \
495 sdio_info->nextlen = 0; \
501 #define SD_BUSTYPE SDIO_BUS
503 #define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND)
505 #define HOSTINTMASK (I_TOHOSTMAIL | I_CHIPACTIVE)
507 #define GSPI_PR55150_BAILOUT
511 #define BUS_WAKE(sdio_info) \
513 if ((sdio_info)->sleeping) \
514 dbus_sdio_bussleep((sdio_info), FALSE); \
518 #define DBUSINTR DBUSTRACE
519 #define DBUSTIMER DBUSTRACE
520 #define DBUSGLOM DBUSTRACE
521 #define DBUSDATA DBUSTRACE
522 #define DBUSCTL DBUSTRACE
523 #define DBUSGLOM_ON() 0
534 IOV_SET_DOWNLOAD_STATE
,
556 static const bcm_iovar_t dbus_sdio_iovars
[] = {
557 {"intr", IOV_INTR
, 0, IOVT_BOOL
, 0 },
558 {"sleep", IOV_SLEEP
, 0, IOVT_BOOL
, 0 },
559 {"pollrate", IOV_POLLRATE
, 0, IOVT_UINT32
, 0 },
560 {"idletime", IOV_IDLETIME
, 0, IOVT_INT32
, 0 },
561 {"idleclock", IOV_IDLECLOCK
, 0, IOVT_INT32
, 0 },
562 {"sd1idle", IOV_SD1IDLE
, 0, IOVT_BOOL
, 0 },
563 {"membytes", IOV_MEMBYTES
, 0, IOVT_BUFFER
, 2 * sizeof(int) },
564 {"memsize", IOV_MEMSIZE
, 0, IOVT_UINT32
, 0 },
565 {"dwnldstate", IOV_SET_DOWNLOAD_STATE
, 0, IOVT_BOOL
, 0 },
566 {"vars", IOV_VARS
, 0, IOVT_BUFFER
, 0 },
567 {"sdiod_drive", IOV_SDIOD_DRIVE
, 0, IOVT_UINT32
, 0 },
568 {"readahead", IOV_READAHEAD
, 0, IOVT_BOOL
, 0 },
569 {"sdrxchain", IOV_SDRXCHAIN
, 0, IOVT_BOOL
, 0 },
570 {"alignctl", IOV_ALIGNCTL
, 0, IOVT_BOOL
, 0 },
571 {"sdalign", IOV_SDALIGN
, 0, IOVT_BOOL
, 0 },
572 {"devreset", IOV_DEVRESET
, 0, IOVT_BOOL
, 0 },
574 {"sdreg", IOV_SDREG
, 0, IOVT_BUFFER
, sizeof(sdreg_t
) },
575 {"sbreg", IOV_SBREG
, 0, IOVT_BUFFER
, sizeof(sdreg_t
) },
576 {"sd_cis", IOV_SDCIS
, 0, IOVT_BUFFER
, DHD_IOCTL_MAXLEN
},
577 {"forcealign", IOV_FORCEEVEN
, 0, IOVT_BOOL
, 0 },
578 {"txbound", IOV_TXBOUND
, 0, IOVT_UINT32
, 0 },
579 {"rxbound", IOV_RXBOUND
, 0, IOVT_UINT32
, 0 },
581 #if defined(BCMDBG) || defined(DHD_SPROM)
582 {"sprom", IOV_SPROM
, 0, IOVT_BUFFER
, 2 * sizeof(int) },
585 {"extloop", IOV_EXTLOOP
, 0, IOVT_BOOL
, 0 },
586 {"pktgen", IOV_PKTGEN
, 0, IOVT_BUFFER
, sizeof(dhd_pktgen_t
) },
594 sdpcmd_regs_t
*sdregs
;
598 /* This stores SD Host info during probe callback
599 * since attach() is not called yet at this point
609 osl_t
*osh
; /* Comes from SD Host */
612 bcmsdh_info_t
*sdh
; /* Handle for BCMSDH calls */
613 si_t
*sih
; /* Handle for SI calls */
615 uint32 ramsize
; /* Size of RAM in SOCRAM (bytes) */
616 uint32 orig_ramsize
; /* Size of RAM in SOCRAM (bytes) */
617 char *vars
; /* Variables (from CIS and/or other) */
618 uint varsz
; /* Size of variables buffer */
619 bool alp_only
; /* Don't use HT clock (ALP only) */
626 const chipinfo_t
*chinfo
;
629 static probe_sdh_info_t g_probe_info
;
632 * FIX: Basic information needed to prep dongle for download.
633 * The goal is to simplify probe setup before a valid
634 * image has been downloaded. Also, can we avoid si_attach() during
635 * probe setup since it brings in a lot of unnecessary dependencies?
638 /* 4325 and 4315 have the same address map */
639 static const chipinfo_t chipinfo_4325_15
= {
640 (chipcregs_t
*) 0x18000000,
641 (sdpcmd_regs_t
*) 0x18002000,
645 static const chipinfo_t chipinfo_4329
= {
646 (chipcregs_t
*) 0x18000000,
647 (sdpcmd_regs_t
*) 0x18011000,
651 static const chipinfo_t chipinfo_4336
= {
652 (chipcregs_t
*) 0x18000000,
653 (sdpcmd_regs_t
*) 0x18002000,
657 static const chipinfo_t chipinfo_4330
= {
658 (chipcregs_t
*) 0x18000000,
659 (sdpcmd_regs_t
*) 0x18002000,
663 static const chipinfo_t chipinfo_43237
= {
664 (chipcregs_t
*) 0x18000000,
665 (sdpcmd_regs_t
*) 0x18002000,
669 static const chipinfo_t chipinfo_4314
= {
670 (chipcregs_t
*) 0x18000000,
671 (sdpcmd_regs_t
*) 0x18003000,
675 static const chipinfo_t chipinfo_4334
= {
676 (chipcregs_t
*) 0x18000000,
677 (sdpcmd_regs_t
*) 0x18002000,
682 * SDH registration callbacks
684 static void * dbus_sdh_probe(uint16 venid
, uint16 devid
, uint16 bus_no
, uint16 slot
,
685 uint16 func
, uint bustype
, void *regsva
, osl_t
* osh
,
687 static void dbus_sdh_disconnect(void *ptr
);
688 static void dbus_sdh_isr(void *handle
);
691 * Local function prototypes
693 static void *dbus_sdio_probe_cb(void *handle
, const char *desc
, uint32 bustype
, uint32 hdrlen
);
694 static void dbus_sdio_disconnect_cb(void *handle
);
697 static void dbus_sdio_sdtest_set(sdio_info_t
*sdio_info
, bool start
);
698 static void dbus_sdio_testrcv(sdio_info_t
*sdio_info
, void *pkt
, uint seq
);
700 static bool dbus_sdio_attach_init(sdio_info_t
*sdio_info
, void *sdh
,
701 char *firmware_path
, char * nvram_path
);
702 static void dbus_sdio_release(sdio_info_t
*sdio_info
, osl_t
*osh
);
703 static void dbus_sdio_release_dongle(sdio_info_t
*sdio_info
, osl_t
*osh
);
704 static int dbus_sdio_rxctl(sdio_info_t
*sdio_info
, uchar
*msg
, uint msglen
);
705 static uint
dbus_sdio_sendfromq(sdio_info_t
*sdio_info
, uint maxframes
);
706 static int dbus_sdio_txctl(sdio_info_t
*sdio_info
, uchar
*msg
, uint msglen
);
707 static void dbus_sdio_txq_flush(sdio_info_t
*sdio_info
);
710 * NOTE: These functions can also be called before attach() occurs
711 * so do not access sdio_info from them. This is to support DBUS
712 * async probe callback to upper layer such as DHD/BMAC/etc. Another
713 * alternative was to modify SDH to do async probe callback only
714 * when a valid image is downloaded to the dongle.
716 static bool dbus_sdio_probe_init(probe_sdh_info_t
*pinfo
);
717 static void dbus_sdio_probe_deinit(probe_sdh_info_t
*pinfo
);
718 static int dbus_sdio_download_state(probe_sdh_info_t
*pinfo
, bool enter
);
719 static int dbus_sdio_membytes(probe_sdh_info_t
*pinfo
, bool write
,
720 uint32 address
, uint8
*data
, uint size
);
721 static int dbus_sdio_write_vars(probe_sdh_info_t
*pinfo
);
722 static int dbus_sdio_downloadvars(probe_sdh_info_t
*pinfo
, void *arg
, int len
);
723 #ifdef BCM_DNGL_EMBEDIMAGE
724 static int dhd_bus_download_nvram_file(probe_sdh_info_t
*pinfo
, char * nvram_path
);
725 static int dhd_bus_download_image_array(probe_sdh_info_t
*pinfo
,
726 char * nvram_path
, uint8
*fw
, int len
);
730 * Wrappers to interface functions in dbus_sdio_os.c
732 static void dbus_sdos_lock(sdio_info_t
*sdio_info
);
733 static void dbus_sdos_unlock(sdio_info_t
*sdio_info
);
734 static void * dbus_sdos_exec_txlock(sdio_info_t
*sdio_info
, exec_cb_t cb
, struct exec_parms
*args
);
735 static int dbus_sdos_sched_dpc(sdio_info_t
*sdio_info
);
736 #ifndef BCM_DNGL_EMBEDIMAGE
737 static int dbus_sdos_sched_probe_cb(void);
741 * Wrappers to callback functions in dbus.c
743 static void *dbus_sdcb_pktget(sdio_info_t
*sdio_info
, uint len
, bool send
);
744 static void dbus_sdcb_pktfree(sdio_info_t
*sdio_info
, void *p
, bool send
);
745 static dbus_irb_t
*dbus_sdcb_getirb(sdio_info_t
*sdio_info
, bool send
);
748 * Callbacks common to all SDIO
750 static void dbus_sdio_disconnect_cb(void *handle
);
751 static void dbus_sdio_send_irb_timeout(void *handle
, dbus_irb_tx_t
*txirb
);
752 static void dbus_sdio_send_irb_complete(void *handle
, dbus_irb_tx_t
*txirb
, int status
);
753 static void dbus_sdio_recv_irb_complete(void *handle
, dbus_irb_rx_t
*rxirb
, int status
);
754 static void dbus_sdio_errhandler(void *handle
, int err
);
755 static void dbus_sdio_ctl_complete(void *handle
, int type
, int status
);
756 static void dbus_sdio_state_change(void *handle
, int state
);
757 static bool dbus_sdio_isr(void *handle
, bool *wantdpc
);
758 static bool dbus_sdio_dpc(void *handle
, bool bounded
);
759 static void dbus_sdio_watchdog(void *handle
);
761 static dbus_intf_callbacks_t dbus_sdio_intf_cbs
= {
762 dbus_sdio_send_irb_timeout
,
763 dbus_sdio_send_irb_complete
,
764 dbus_sdio_recv_irb_complete
,
765 dbus_sdio_errhandler
,
766 dbus_sdio_ctl_complete
,
767 dbus_sdio_state_change
,
774 * Need global for probe() and disconnect() since
775 * attach() is not called at probe and detach()
776 * can be called inside disconnect()
778 static probe_cb_t probe_cb
= NULL
;
779 static disconnect_cb_t disconnect_cb
= NULL
;
780 static void *probe_arg
= NULL
;
781 static void *disc_arg
= NULL
;
784 * dbus_intf_t common to all SDIO
785 * These functions override dbus_sdio_os.c.
787 static void *dbus_sdif_attach(dbus_pub_t
*pub
, void *cbarg
, dbus_intf_callbacks_t
*cbs
);
788 static void dbus_sdif_detach(dbus_pub_t
*pub
, void *info
);
789 static int dbus_sdif_send_irb(void *bus
, dbus_irb_tx_t
*txirb
);
790 static int dbus_sdif_send_ctl(void *bus
, uint8
*buf
, int len
);
791 static int dbus_sdif_recv_ctl(void *bus
, uint8
*buf
, int len
);
792 static int dbus_sdif_up(void *bus
);
793 static int dbus_sdif_iovar_op(void *bus
, const char *name
,
794 void *params
, int plen
, void *arg
, int len
, bool set
);
795 static bool dbus_sdif_device_exists(void *bus
);
796 static bool dbus_sdif_dlneeded(void *bus
);
797 static int dbus_sdif_dlstart(void *bus
, uint8
*fw
, int len
);
798 static int dbus_sdif_dlrun(void *bus
);
799 static int dbus_sdif_stop(void *bus
);
800 static int dbus_sdif_down(void *bus
);
801 static int dbus_sdif_get_attrib(void *bus
, dbus_attrib_t
*attrib
);
803 static dbus_intf_t dbus_sdio_intf
;
804 static dbus_intf_t
*g_dbusintf
= NULL
;
806 /* Register/Unregister functions are called by the main DHD entry
807 * point (e.g. module insertion) to link with the bus driver, in
808 * order to look for or await the device.
811 bcmsdh_driver_t sdh_driver
= {
816 /* Functions shared between dbus_sdio.c/dbus_sdio_os.c */
817 extern int dbus_sdio_txq_sched(void *bus
);
818 extern int dbus_sdio_txq_stop(void *bus
);
819 extern int dbus_sdio_txq_process(void *bus
);
820 extern int probe_dlstart(void);
821 extern int probe_dlstop(void);
822 extern int probe_dlwrite(uint8
*buf
, int count
, bool isvars
);
823 extern int probe_iovar(const char *name
, void *params
, int plen
, void *arg
, int len
, bool set
,
824 void **val
, int *val_len
);
829 dbus_sdio_alpclk(bcmsdh_info_t
*sdh
)
837 * Request ALP clock; ALP is required before starting a download
839 bcmsdh_cfg_write(sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
, SBSDIO_ALP_AVAIL_REQ
, &err
);
841 DBUSERR(("%s: HT Avail request error: %d\n", __FUNCTION__
, err
));
846 /* Check current status */
847 clkctl
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
, &err
);
849 DBUSERR(("%s: HT Avail read error: %d\n", __FUNCTION__
, err
));
853 if (!SBSDIO_CLKAV(clkctl
, TRUE
)) {
854 SPINWAIT(((clkctl
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
,
855 SBSDIO_FUNC1_CHIPCLKCSR
, &err
)),
856 !SBSDIO_CLKAV(clkctl
, TRUE
)), PMU_MAX_TRANSITION_DLY
);
863 /* Turn backplane clock on or off */
865 dbus_sdio_htclk(sdio_info_t
*sdio_info
, bool on
, bool pendok
)
868 uint8 clkctl
, clkreq
, devctl
;
871 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
874 sdh
= sdio_info
->sdh
;
878 /* Request HT Avail */
879 clkreq
= g_probe_info
.alp_only
? SBSDIO_ALP_AVAIL_REQ
: SBSDIO_HT_AVAIL_REQ
;
882 bcmsdh_cfg_write(sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
, clkreq
, &err
);
884 DBUSERR(("%s: HT Avail request error: %d\n", __FUNCTION__
, err
));
889 ((sdio_info
->sih
->buscoretype
== PCMCIA_CORE_ID
) &&
890 (sdio_info
->sih
->buscorerev
== 9))) {
891 uint32 dummy
, retries
;
892 R_SDREG(dummy
, &sdio_info
->regs
->clockctlstatus
, retries
);
895 /* Check current status */
896 clkctl
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
, &err
);
898 DBUSERR(("%s: HT Avail read error: %d\n", __FUNCTION__
, err
));
902 /* Go to pending and await interrupt if appropriate */
903 if (!SBSDIO_CLKAV(clkctl
, g_probe_info
.alp_only
) && pendok
) {
904 DBUSINFO(("CLKCTL: set PENDING\n"));
905 sdio_info
->clkstate
= CLK_PENDING
;
907 /* Allow only clock-available interrupt */
908 devctl
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
, SBSDIO_DEVICE_CTL
, &err
);
910 DBUSERR(("%s: Devctl access error setting CA: %d\n",
915 devctl
|= SBSDIO_DEVCTL_CA_INT_ONLY
;
916 bcmsdh_cfg_write(sdh
, SDIO_FUNC_1
, SBSDIO_DEVICE_CTL
, devctl
, &err
);
918 } else if (sdio_info
->clkstate
== CLK_PENDING
) {
919 /* Cancel CA-only interrupt filter */
920 devctl
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
, SBSDIO_DEVICE_CTL
, &err
);
921 devctl
&= ~SBSDIO_DEVCTL_CA_INT_ONLY
;
922 bcmsdh_cfg_write(sdh
, SDIO_FUNC_1
, SBSDIO_DEVICE_CTL
, devctl
, &err
);
925 /* Otherwise, wait here (polling) for HT Avail */
926 if (!SBSDIO_CLKAV(clkctl
, g_probe_info
.alp_only
)) {
927 SPINWAIT(((clkctl
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
,
928 SBSDIO_FUNC1_CHIPCLKCSR
, &err
)),
929 !SBSDIO_CLKAV(clkctl
, g_probe_info
.alp_only
)),
930 PMU_MAX_TRANSITION_DLY
);
933 DBUSERR(("%s: HT Avail request error: %d\n", __FUNCTION__
, err
));
936 if (!SBSDIO_CLKAV(clkctl
, g_probe_info
.alp_only
)) {
937 DBUSERR(("%s: HT Avail timeout (%d): clkctl 0x%02x\n",
938 __FUNCTION__
, PMU_MAX_TRANSITION_DLY
, clkctl
));
942 /* Mark clock available */
943 sdio_info
->clkstate
= CLK_AVAIL
;
944 DBUSINFO(("CLKCTL: turned ON\n"));
947 if (g_probe_info
.alp_only
== TRUE
) {
948 if (!SBSDIO_ALPONLY(clkctl
)) {
949 DBUSERR(("%s: HT Clock, when ALP Only\n", __FUNCTION__
));
952 if (SBSDIO_ALPONLY(clkctl
)) {
953 DBUSERR(("%s: HT Clock should be on.\n", __FUNCTION__
));
956 #endif /* defined (BCMDBG) */
958 sdio_info
->activity
= TRUE
;
962 if (sdio_info
->clkstate
== CLK_PENDING
) {
963 /* Cancel CA-only interrupt filter */
964 devctl
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
, SBSDIO_DEVICE_CTL
, &err
);
965 devctl
&= ~SBSDIO_DEVCTL_CA_INT_ONLY
;
966 bcmsdh_cfg_write(sdh
, SDIO_FUNC_1
, SBSDIO_DEVICE_CTL
, devctl
, &err
);
969 sdio_info
->clkstate
= CLK_SDONLY
;
970 bcmsdh_cfg_write(sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
, clkreq
, &err
);
971 DBUSINFO(("CLKCTL: turned OFF\n"));
973 DBUSERR(("%s: Failed access turning clock off: %d\n",
981 /* Change idle/active SD state */
983 dbus_sdio_sdclk(sdio_info_t
*sdio_info
, bool on
)
988 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
991 if (sdio_info
->idleclock
== IDLE_STOP
) {
992 /* Turn on clock and restore mode */
994 err
= bcmsdh_iovar_op(sdio_info
->sdh
, "sd_clock", NULL
, 0,
995 &iovalue
, sizeof(iovalue
), TRUE
);
997 DBUSERR(("%s: error enabling sd_clock: %d\n",
1002 iovalue
= sdio_info
->sd_mode
;
1003 err
= bcmsdh_iovar_op(sdio_info
->sdh
, "sd_mode", NULL
, 0,
1004 &iovalue
, sizeof(iovalue
), TRUE
);
1006 DBUSERR(("%s: error changing sd_mode: %d\n",
1007 __FUNCTION__
, err
));
1010 } else if (sdio_info
->idleclock
!= IDLE_ACTIVE
) {
1011 /* Restore clock speed */
1012 iovalue
= sdio_info
->sd_divisor
;
1013 err
= bcmsdh_iovar_op(sdio_info
->sdh
, "sd_divisor", NULL
, 0,
1014 &iovalue
, sizeof(iovalue
), TRUE
);
1016 DBUSERR(("%s: error restoring sd_divisor: %d\n",
1017 __FUNCTION__
, err
));
1021 sdio_info
->clkstate
= CLK_SDONLY
;
1023 /* Stop or slow the SD clock itself */
1024 if ((sdio_info
->sd_divisor
== -1) || (sdio_info
->sd_mode
== -1)) {
1025 DBUSTRACE(("%s: can't idle clock, divisor %d mode %d\n",
1026 __FUNCTION__
, sdio_info
->sd_divisor
, sdio_info
->sd_mode
));
1029 if (sdio_info
->idleclock
== IDLE_STOP
) {
1031 /* Change to SD1 mode and turn off clock */
1033 err
= bcmsdh_iovar_op(sdio_info
->sdh
, "sd_mode", NULL
, 0,
1034 &iovalue
, sizeof(iovalue
), TRUE
);
1036 DBUSERR(("%s: error changing sd_clock: %d\n",
1037 __FUNCTION__
, err
));
1043 err
= bcmsdh_iovar_op(sdio_info
->sdh
, "sd_clock", NULL
, 0,
1044 &iovalue
, sizeof(iovalue
), TRUE
);
1046 DBUSERR(("%s: error disabling sd_clock: %d\n",
1047 __FUNCTION__
, err
));
1050 } else if (sdio_info
->idleclock
!= IDLE_ACTIVE
) {
1051 /* Set divisor to idle value */
1052 iovalue
= sdio_info
->idleclock
;
1053 err
= bcmsdh_iovar_op(sdio_info
->sdh
, "sd_divisor", NULL
, 0,
1054 &iovalue
, sizeof(iovalue
), TRUE
);
1056 DBUSERR(("%s: error changing sd_divisor: %d\n",
1057 __FUNCTION__
, err
));
1061 sdio_info
->clkstate
= CLK_NONE
;
1067 /* Transition SD and backplane clock readiness */
1069 dbus_sdio_clkctl(sdio_info_t
*sdio_info
, uint target
, bool pendok
)
1071 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
1073 /* Early exit if we're already there */
1074 if (sdio_info
->clkstate
== target
) {
1075 if (target
== CLK_AVAIL
)
1076 sdio_info
->activity
= TRUE
;
1082 /* Make sure SD clock is available */
1083 if (sdio_info
->clkstate
== CLK_NONE
)
1084 dbus_sdio_sdclk(sdio_info
, TRUE
);
1085 /* Now request HT Avail on the backplane */
1086 dbus_sdio_htclk(sdio_info
, TRUE
, pendok
);
1087 sdio_info
->activity
= TRUE
;
1091 /* Remove HT request, or bring up SD clock */
1092 if (sdio_info
->clkstate
== CLK_NONE
)
1093 dbus_sdio_sdclk(sdio_info
, TRUE
);
1094 else if (sdio_info
->clkstate
== CLK_AVAIL
)
1095 dbus_sdio_htclk(sdio_info
, FALSE
, FALSE
);
1097 DBUSERR(("dbus_sdio_clkctl: request for %d -> %d\n",
1098 sdio_info
->clkstate
, target
));
1102 /* Make sure to remove HT request */
1103 if (sdio_info
->clkstate
== CLK_AVAIL
)
1104 dbus_sdio_htclk(sdio_info
, FALSE
, FALSE
);
1105 /* Now remove the SD clock */
1106 dbus_sdio_sdclk(sdio_info
, FALSE
);
1109 DBUSINFO(("dbus_sdio_clkctl: %d -> %d\n", oldstate
, sdio_info
->clkstate
));
1115 dbus_sdio_bussleep(sdio_info_t
*sdio_info
, bool sleep
)
1117 bcmsdh_info_t
*sdh
= sdio_info
->sdh
;
1118 sdpcmd_regs_t
*regs
= sdio_info
->regs
;
1121 DBUSINFO(("dbus_sdio_bussleep: request %s (currently %s)\n",
1122 (sleep
? "SLEEP" : "WAKE"),
1123 (sdio_info
->sleeping
? "SLEEP" : "WAKE")));
1125 /* Done if we're already in the requested state */
1126 if (sleep
== sdio_info
->sleeping
)
1129 /* Going to sleep: set the alarm and turn off the lights... */
1131 /* Don't sleep if something is pending */
1132 if (sdio_info
->dpc_sched
|| sdio_info
->rxskip
|| pktq_len(&sdio_info
->txq
))
1136 /* Disable SDIO interrupts (no longer interested) */
1137 bcmsdh_intr_disable(sdio_info
->sdh
);
1139 /* Make sure the controller has the bus up */
1140 dbus_sdio_clkctl(sdio_info
, CLK_AVAIL
, FALSE
);
1142 /* Tell device to start using OOB wakeup */
1143 W_SDREG(SMB_USE_OOB
, ®s
->tosbmailbox
, retries
);
1144 if (retries
> retry_limit
)
1145 DBUSERR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
1147 /* Turn off our contribution to the HT clock request */
1148 dbus_sdio_clkctl(sdio_info
, CLK_SDONLY
, FALSE
);
1150 /* Isolate the bus */
1151 bcmsdh_cfg_write(sdh
, SDIO_FUNC_1
, SBSDIO_DEVICE_CTL
,
1152 SBSDIO_DEVCTL_PADS_ISO
, NULL
);
1155 sdio_info
->sleeping
= TRUE
;
1158 /* Waking up: bus power up is ok, set local state */
1160 /* Force pad isolation off if possible (in case power never toggled) */
1161 if ((sdio_info
->sih
->buscoretype
== PCMCIA_CORE_ID
) &&
1162 (sdio_info
->sih
->buscorerev
>= 10))
1163 bcmsdh_cfg_write(sdh
, SDIO_FUNC_1
, SBSDIO_DEVICE_CTL
, 0, NULL
);
1166 /* Make sure we have SD bus access */
1167 if (sdio_info
->clkstate
== CLK_NONE
)
1168 dbus_sdio_clkctl(sdio_info
, CLK_SDONLY
, FALSE
);
1170 /* Send misc interrupt to indicate OOB not needed */
1171 W_SDREG(0, ®s
->tosbmailboxdata
, retries
);
1172 if (retries
<= retry_limit
)
1173 W_SDREG(SMB_DEV_INT
, ®s
->tosbmailbox
, retries
);
1175 if (retries
> retry_limit
)
1176 DBUSERR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
1179 sdio_info
->sleeping
= FALSE
;
1181 /* Enable interrupts again */
1182 if (sdio_info
->intr
&& (sdio_info
->pub
->busstate
== DBUS_STATE_UP
)) {
1183 sdio_info
->intdis
= FALSE
;
1184 bcmsdh_intr_enable(sdio_info
->sdh
);
1191 /* Writes a HW/SW header into the packet and sends it. */
1192 /* Assumes: (a) header space already there, (b) caller holds lock */
1194 dbus_sdio_txpkt(sdio_info_t
*sdio_info
, void *pkt
, uint chan
)
1207 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
1209 sdh
= sdio_info
->sdh
;
1210 osh
= sdio_info
->pub
->osh
;
1212 if (sdio_info
->dongle_reset
) {
1213 ret
= BCME_NOTREADY
;
1217 frame
= (uint8
*)PKTDATA(osh
, pkt
);
1219 /* Add alignment padding, allocate new packet if needed */
1220 if ((pad
= ((uintptr
)frame
% SDALIGN
))) {
1221 if (PKTHEADROOM(osh
, pkt
) < pad
) {
1222 DBUSINFO(("%s: insufficient headroom %d for %d pad\n",
1223 __FUNCTION__
, (int)PKTHEADROOM(osh
, pkt
), pad
));
1224 sdio_info
->tx_realloc
++;
1225 new = dbus_sdcb_pktget(sdio_info
, (PKTLEN(osh
, pkt
) + SDALIGN
), TRUE
);
1227 DBUSERR(("%s: couldn't allocate new %d-byte packet\n",
1228 __FUNCTION__
, PKTLEN(osh
, pkt
) + SDALIGN
));
1233 PKTALIGN(osh
, new, PKTLEN(osh
, pkt
), SDALIGN
);
1234 bcopy(PKTDATA(osh
, pkt
), PKTDATA(osh
, new), PKTLEN(osh
, pkt
));
1236 *((pkttag_t
*)PKTTAG(new)) = *((pkttag_t
*)PKTTAG(pkt
));
1237 ((pkttag_t
*)PKTTAG(new))->txirb
->pkt
= new;
1238 ((pkttag_t
*)PKTTAG(new))->txirb
->info
= new;
1240 dbus_sdcb_pktfree(sdio_info
, pkt
, TRUE
);
1242 frame
= (uint8
*)PKTDATA(osh
, pkt
);
1243 ASSERT(((uintptr
)frame
% SDALIGN
) == 0);
1246 PKTPUSH(osh
, pkt
, pad
);
1247 frame
= (uint8
*)PKTDATA(osh
, pkt
);
1248 bzero(frame
, pad
+ SDPCM_HDRLEN
);
1251 ASSERT(pad
< SDALIGN
);
1253 /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
1254 len
= (uint16
)PKTLEN(osh
, pkt
);
1255 *(uint16
*)frame
= htol16(len
);
1256 *(((uint16
*)frame
) + 1) = htol16(~len
);
1258 /* Software tag: channel, sequence number, data offset */
1259 swheader
= ((chan
<< SDPCM_CHANNEL_SHIFT
) & SDPCM_CHANNEL_MASK
) | sdio_info
->tx_seq
|
1260 (((pad
+ SDPCM_HDRLEN
) << SDPCM_DOFFSET_SHIFT
) & SDPCM_DOFFSET_MASK
);
1261 htol32_ua_store(swheader
, frame
+ SDPCM_FRAMETAG_LEN
);
1262 htol32_ua_store(0, frame
+ SDPCM_FRAMETAG_LEN
+ sizeof(swheader
));
1263 sdio_info
->tx_seq
= (sdio_info
->tx_seq
+ 1) % SDPCM_SEQUENCE_WRAP
;
1265 /* Raise len to next SDIO block to eliminate tail command */
1266 if (sdio_info
->roundup
&& sdio_info
->blocksize
&& (len
> sdio_info
->blocksize
)) {
1267 pad
= sdio_info
->blocksize
- (len
% sdio_info
->blocksize
);
1268 if ((pad
<= sdio_info
->roundup
) && (pad
< sdio_info
->blocksize
))
1270 if (pad
<= PKTTAILROOM(osh
, pkt
))
1275 /* Some controllers have trouble with odd bytes -- round to even */
1276 if (forcealign
&& (len
& (ALIGNMENT
- 1))) {
1278 if (PKTTAILROOM(osh
, pkt
))
1280 len
= ROUNDUP(len
, ALIGNMENT
);
1283 DBUSERR(("%s: sending unrounded %d-byte packet\n", __FUNCTION__
, len
));
1288 ret
= bcmsdh_send_buf(sdh
, SI_ENUM_BASE
, SDIO_FUNC_2
, F2SYNC
,
1289 frame
, len
, pkt
, NULL
, NULL
);
1290 sdio_info
->f2txdata
++;
1291 ASSERT(ret
!= BCME_PENDING
);
1294 /* On failure, abort the command and terminate the frame */
1295 DBUSINFO(("%s: sdio error %d, abort command and terminate frame.\n",
1296 __FUNCTION__
, ret
));
1297 sdio_info
->tx_sderrs
++;
1299 ret
= bcmsdh_abort(sdh
, SDIO_FUNC_2
);
1300 if (ret
== BCME_NODEVICE
) {
1301 dbus_sdio_state_change(sdio_info
, DBUS_STATE_DISCONNECT
);
1305 DBUSERR(("%s: gSPI transmit error. Check Overflow or F2-fifo-not-ready"
1306 " counters.\n", __FUNCTION__
));
1308 bcmsdh_cfg_write(sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_FRAMECTRL
,
1310 sdio_info
->f1regdata
++;
1312 for (i
= 0; i
< 3; i
++) {
1314 hi
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
,
1315 SBSDIO_FUNC1_WFRAMEBCHI
, NULL
);
1316 lo
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
,
1317 SBSDIO_FUNC1_WFRAMEBCLO
, NULL
);
1318 sdio_info
->f1regdata
+= 2;
1319 if ((hi
== 0) && (lo
== 0))
1323 } while ((ret
< 0) && retrydata
&& retries
++ < TXRETRIES
);
1326 ASSERT(OSL_PKTTAG_SZ
>= sizeof(pkttag_t
));
1327 ptag
= (pkttag_t
*) PKTTAG(pkt
);
1329 dbus_sdio_send_irb_complete(sdio_info
, ptag
->txirb
, (ret
? DBUS_ERR_TXFAIL
: DBUS_OK
));
1331 dbus_sdcb_pktfree(sdio_info
, pkt
, TRUE
);
1336 dbus_prec_pkt_deq(sdio_info_t
*sdio_info
, int tx_prec_map
, int *prec_out
)
1338 return pktq_mdeq(&sdio_info
->txq
, tx_prec_map
, prec_out
);
1342 dbus_prec_pkt_deq_exec(struct exec_parms
*args
)
1344 return dbus_prec_pkt_deq(args
->pdeq
.sdio_info
, args
->pdeq
.tx_prec_map
,
1345 args
->pdeq
.prec_out
);
1349 * FIX: Move WMM pkt prioritization out of DBUS/SDIO to DHD so
1350 * USB can leverage the same logic
1353 dbus_prec_pkt_enq(sdio_info_t
*sdio_info
, void *pkt
, int prec
)
1356 int eprec
= -1; /* precedence to evict from */
1357 bool discard_oldest
;
1358 struct pktq
*q
= &sdio_info
->txq
;
1360 /* Fast case, precedence queue is not full and we are also not
1361 * exceeding total queue length
1363 if (!pktq_pfull(q
, prec
) && !pktq_full(q
)) {
1364 pktq_penq(q
, prec
, pkt
);
1368 /* Determine precedence from which to evict packet, if any */
1369 if (pktq_pfull(q
, prec
))
1371 else if (pktq_full(q
)) {
1372 p
= pktq_peek_tail(q
, &eprec
);
1378 /* Evict if needed */
1380 /* Detect queueing to unconfigured precedence */
1381 ASSERT(!pktq_pempty(q
, eprec
));
1382 discard_oldest
= AC_BITMAP_TST(sdio_info
->wme_dp
, eprec
);
1383 if (eprec
== prec
&& !discard_oldest
)
1384 goto err
; /* refuse newer (incoming) packet */
1385 /* Evict packet according to discard policy */
1386 p
= discard_oldest
? pktq_pdeq(q
, eprec
) : pktq_pdeq_tail(q
, eprec
);
1389 dbus_sdcb_pktfree(sdio_info
, p
, TRUE
);
1393 p
= pktq_penq(q
, prec
, pkt
);
1402 dbus_prec_pkt_enq_exec(struct exec_parms
*args
)
1404 return (void *) (uintptr
) dbus_prec_pkt_enq(args
->penq
.sdio_info
, args
->penq
.pkt
,
1409 dbus_sdio_txbuf_submit(sdio_info_t
*sdio_info
, dbus_irb_tx_t
*txirb
)
1417 struct exec_parms exec_args
;
1419 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
1421 osh
= sdio_info
->pub
->osh
;
1425 * For BMAC sdio high driver that uses send_buf,
1426 * we need to convert the buf into pkt for dbus.
1428 datalen
= txirb
->len
;
1429 DBUSTRACE(("%s: Converting buf(%d bytes) to pkt.\n", __FUNCTION__
, datalen
));
1430 pkt
= dbus_sdcb_pktget(sdio_info
, datalen
, TRUE
);
1432 DBUSERR(("%s: Out of Tx buf.\n", __FUNCTION__
));
1433 return DBUS_ERR_TXDROP
;
1437 bcopy(txirb
->buf
, PKTDATA(osh
, pkt
), datalen
);
1438 PKTLEN(osh
, pkt
) = datalen
;
1440 datalen
= PKTLEN(osh
, pkt
);
1442 ASSERT(OSL_PKTTAG_SZ
>= sizeof(pkttag_t
));
1443 ptag
= (pkttag_t
*) PKTTAG(pkt
);
1444 ptag
->sdio_info
= sdio_info
;
1445 ptag
->txirb
= txirb
;
1448 /* Push the test header if doing loopback */
1449 if (sdio_info
->ext_loop
) {
1451 PKTPUSH(osh
, pkt
, SDPCM_TEST_HDRLEN
);
1452 data
= PKTDATA(osh
, pkt
);
1453 *data
++ = SDPCM_TEST_ECHOREQ
;
1454 *data
++ = (uint8
)sdio_info
->loopid
++;
1455 *data
++ = (datalen
>> 0);
1456 *data
++ = (datalen
>> 8);
1457 datalen
+= SDPCM_TEST_HDRLEN
;
1461 ASSERT(PKTHEADROOM(osh
, pkt
) >= SDPCM_HDRLEN
);
1462 /* Add space for the header */
1463 PKTPUSH(osh
, pkt
, SDPCM_HDRLEN
);
1464 ASSERT(ISALIGNED(PKTDATA(osh
, pkt
), 2));
1466 prec
= PRIO2PREC((PKTPRIO(pkt
) & PRIOMASK
));
1468 sdio_info
->fcqueued
++;
1470 /* Priority based enq */
1471 exec_args
.penq
.sdio_info
= sdio_info
;
1472 exec_args
.penq
.pkt
= pkt
;
1473 exec_args
.penq
.prec
= prec
;
1474 berr
= dbus_sdos_exec_txlock(sdio_info
,
1475 (exec_cb_t
) dbus_prec_pkt_enq_exec
, &exec_args
);
1477 DBUSERR(("%s: Dropping pkt!\n", __FUNCTION__
));
1478 ASSERT(0); /* FIX: Should not be dropping pkts */
1479 ret
= DBUS_ERR_TXFAIL
;
1484 if (pktq_plen(&sdio_info
->txq
, prec
) > qcount
[prec
])
1485 qcount
[prec
] = pktq_plen(&sdio_info
->txq
, prec
);
1487 dbus_sdio_txq_sched(sdio_info
->sdos_info
);
1494 dbus_bus_stop(sdio_info_t
*sdio_info
)
1500 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
1502 BUS_WAKE(sdio_info
);
1504 dbus_sdio_txq_stop(sdio_info
->sdos_info
);
1506 /* Enable clock for device interrupts */
1507 dbus_sdio_clkctl(sdio_info
, CLK_AVAIL
, FALSE
);
1509 /* Disable and clear interrupts at the chip level also */
1510 W_SDREG(0, &sdio_info
->regs
->hostintmask
, retries
);
1511 W_SDREG(sdio_info
->hostintmask
, &sdio_info
->regs
->intstatus
, retries
);
1512 sdio_info
->hostintmask
= 0;
1514 /* Change our idea of bus state */
1515 sdio_info
->pub
->busstate
= DBUS_STATE_DOWN
;
1517 /* Force clocks on backplane to be sure F2 interrupt propagates */
1518 saveclk
= bcmsdh_cfg_read(sdio_info
->sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
, &err
);
1520 bcmsdh_cfg_write(sdio_info
->sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
,
1521 (saveclk
| SBSDIO_FORCE_HT
), &err
);
1524 DBUSERR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__
, err
));
1527 /* Turn off the bus (F2), free any pending packets */
1528 DBUSINTR(("%s: disable SDIO interrupts\n", __FUNCTION__
));
1529 bcmsdh_intr_disable(sdio_info
->sdh
);
1531 bcmsdh_cfg_write(sdio_info
->sdh
, SDIO_FUNC_0
, SDIOD_CCCR_IOEN
, SDIO_FUNC_ENABLE_1
, NULL
);
1532 #endif /* !BCMSPI */
1534 /* Turn off the backplane clock (only) */
1535 dbus_sdio_clkctl(sdio_info
, CLK_SDONLY
, FALSE
);
1537 dbus_sdio_txq_flush(sdio_info
);
1539 /* Clear any held glomming stuff */
1540 if (sdio_info
->glomd
) {
1541 dbus_sdcb_pktfree(sdio_info
, sdio_info
->glomd
, FALSE
);
1542 sdio_info
->glomd
= NULL
;
1545 if (sdio_info
->glom
) {
1546 dbus_sdcb_pktfree(sdio_info
, sdio_info
->glom
, FALSE
);
1547 sdio_info
->glom
= NULL
;
1550 /* Clear rx control and wake any waiters */
1551 sdio_info
->rxlen
= 0;
1553 /* Reset some F2 state stuff */
1554 sdio_info
->rxskip
= FALSE
;
1555 sdio_info
->tx_seq
= sdio_info
->rx_seq
= 0;
1559 dbus_sdio_init(sdio_info_t
*sdio_info
)
1563 uint8 ready
= 0, enable
;
1566 uint32 dstatus
= 0; /* gSPI device status bits of */
1571 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
1573 /* Make sure backplane clock is on, needed to generate F2 interrupt */
1574 dbus_sdio_clkctl(sdio_info
, CLK_AVAIL
, FALSE
);
1575 if (sdio_info
->clkstate
!= CLK_AVAIL
)
1579 /* fake "ready" for spi, wake-wlan would have already enabled F1 and F2 */
1580 ready
= (SDIO_FUNC_ENABLE_1
| SDIO_FUNC_ENABLE_2
);
1582 /* Give the dongle some time to do its thing and set IOR2 */
1583 retries
= WAIT_F2RXFIFORDY
;
1585 while (retries
-- && !enable
) {
1586 OSL_DELAY(WAIT_F2RXFIFORDY_DELAY
* 1000);
1587 dstatus
= bcmsdh_cfg_read_word(sdio_info
->sdh
, SDIO_FUNC_0
, SPID_STATUS_REG
, NULL
);
1588 if (dstatus
&& STATUS_F2_RX_READY
)
1592 DBUSERR(("Took %d retries before dongle is ready with delay %d(ms) in between\n",
1593 WAIT_F2RXFIFORDY
- retries
, WAIT_F2RXFIFORDY_DELAY
));
1597 DBUSERR(("dstatus when timed out on f2-fifo not ready = 0x%x\n", dstatus
));
1598 DBUSERR(("Waited %d retries, dongle is not ready with delay %d(ms) in between\n",
1599 WAIT_F2RXFIFORDY
, WAIT_F2RXFIFORDY_DELAY
));
1604 /* Force clocks on backplane to be sure F2 interrupt propagates */
1605 saveclk
= bcmsdh_cfg_read(sdio_info
->sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
, &err
);
1607 bcmsdh_cfg_write(sdio_info
->sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
,
1608 (saveclk
| SBSDIO_FORCE_HT
), &err
);
1611 DBUSERR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__
, err
));
1615 /* Enable function 2 (frame transfers) */
1616 W_SDREG((SDPCM_PROT_VERSION
<< SMB_DATA_VERSION_SHIFT
),
1617 &sdio_info
->regs
->tosbmailboxdata
, retries
);
1618 enable
= (SDIO_FUNC_ENABLE_1
| SDIO_FUNC_ENABLE_2
);
1620 bcmsdh_cfg_write(sdio_info
->sdh
, SDIO_FUNC_0
, SDIOD_CCCR_IOEN
, enable
, NULL
);
1623 /* Give the dongle some time to do its thing and set IOR2 */
1624 retries
= DHD_WAIT_F2RDY
;
1627 retries
*= htclkratio
;
1628 #endif /* BCMSLTGT */
1630 ((ready
= bcmsdh_cfg_read(sdio_info
->sdh
, SDIO_FUNC_0
, SDIOD_CCCR_IORDY
, NULL
)))) &&
1634 #endif /* !BCMSPI */
1638 DBUSERR(("%s: enable 0x%02x, ready 0x%02x\n", __FUNCTION__
, enable
, ready
));
1641 /* If F2 successfully enabled, set core and enable interrupts */
1642 if (ready
== enable
) {
1643 /* Make sure we're talking to the core. */
1644 if (!(sdio_info
->regs
= si_setcore(sdio_info
->sih
, PCMCIA_CORE_ID
, 0)))
1645 sdio_info
->regs
= si_setcore(sdio_info
->sih
, SDIOD_CORE_ID
, 0);
1647 bcmsdh_cfg_write(sdio_info
->sdh
, SDIO_FUNC_1
, SBSDIO_WATERMARK
,
1648 (uint8
)watermark
, &err
);
1650 /* bcmsdh_intr_unmask(sdio_info->sdh); */
1652 sdio_info
->pub
->busstate
= DBUS_STATE_UP
;
1653 sdio_info
->intdis
= FALSE
;
1654 if (sdio_info
->intr
) {
1655 DBUSINTR(("%s: enable SDIO device interrupts\n", __FUNCTION__
));
1656 bcmsdh_intr_enable(sdio_info
->sdh
);
1658 DBUSINTR(("%s: disable SDIO interrupts\n", __FUNCTION__
));
1659 bcmsdh_intr_disable(sdio_info
->sdh
);
1662 #ifdef DEBUG_LOST_INTERRUPTS
1666 uint8 devena
, devpend
;
1667 uint sdr_retries
= 0;
1669 hostpending
= bcmsdh_intr_pending(sdio_info
->sdh
);
1670 devena
= bcmsdh_cfg_read(sdio_info
->sdh
, SDIO_FUNC_0
,
1671 SDIOD_CCCR_INTEN
, NULL
);
1672 devpend
= bcmsdh_cfg_read(sdio_info
->sdh
, SDIO_FUNC_0
,
1673 SDIOD_CCCR_INTPEND
, NULL
);
1675 R_SDREG(intstatus
, &sdio_info
->regs
->intstatus
, sdr_retries
);
1676 intstatus
&= sdio_info
->hostintmask
;
1678 DBUSERR(("%s: interrupts -- host %s device ena/pend 0x%02x/0x%02x\n"
1679 "intstatus 0x%08x, hostmask 0x%08x\n", __FUNCTION__
,
1680 (hostpending
? "PENDING" : "NOT PENDING"),
1681 devena
, devpend
, intstatus
, sdio_info
->hostintmask
));
1683 #endif /* DEBUG_LOST_INTERRUPTS */
1691 /* Disable F2 again */
1692 enable
= SDIO_FUNC_ENABLE_1
;
1693 bcmsdh_cfg_write(sdio_info
->sdh
, SDIO_FUNC_0
, SDIOD_CCCR_IOEN
, enable
, NULL
);
1696 /* Restore previous clock setting */
1697 bcmsdh_cfg_write(sdio_info
->sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
, saveclk
, &err
);
1699 #endif /* !BCMSPI */
1701 /* If we didn't come up, turn off backplane clock */
1702 if (sdio_info
->pub
->busstate
!= DBUS_STATE_UP
) {
1703 DBUSERR(("Error: Not up yet!\n"));
1704 dbus_sdio_clkctl(sdio_info
, CLK_NONE
, FALSE
);
1711 dbus_sdio_rxfail(sdio_info_t
*sdio_info
, bool abort
, bool rtx
)
1713 bcmsdh_info_t
*sdh
= sdio_info
->sdh
;
1714 sdpcmd_regs_t
*regs
= sdio_info
->regs
;
1720 DBUSERR(("%s: %sterminate frame%s\n", __FUNCTION__
,
1721 (abort
? "abort command, " : ""), (rtx
? ", send NAK" : "")));
1724 err
= bcmsdh_abort(sdh
, SDIO_FUNC_2
);
1725 if (err
== BCME_NODEVICE
) {
1726 dbus_sdio_state_change(sdio_info
, DBUS_STATE_DISCONNECT
);
1731 bcmsdh_cfg_write(sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_FRAMECTRL
, SFC_RF_TERM
, &err
);
1732 sdio_info
->f1regdata
++;
1734 /* Wait until the packet has been flushed (device/FIFO stable) */
1735 for (lastrbc
= retries
= 0xffff; retries
> 0; retries
--) {
1736 hi
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_RFRAMEBCHI
, NULL
);
1737 lo
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_RFRAMEBCLO
, NULL
);
1738 sdio_info
->f1regdata
+= 2;
1740 if ((hi
== 0) && (lo
== 0))
1743 if ((hi
> (lastrbc
>> 8)) && (lo
> (lastrbc
& 0x00ff))) {
1744 DBUSERR(("%s: count growing: last 0x%04x now 0x%04x\n",
1745 __FUNCTION__
, lastrbc
, ((hi
<< 8) + lo
)));
1747 lastrbc
= (hi
<< 8) + lo
;
1751 DBUSERR(("%s: count never zeroed: last 0x%04x\n", __FUNCTION__
, lastrbc
));
1753 DBUSINFO(("%s: flush took %d iterations\n", __FUNCTION__
, (0xffff - retries
)));
1758 W_SDREG(SMB_NAK
, ®s
->tosbmailbox
, retries
);
1759 sdio_info
->f1regdata
++;
1760 if (retries
<= retry_limit
) {
1761 sdio_info
->rxskip
= TRUE
;
1765 /* Clear partial in any case */
1766 sdio_info
->nextlen
= 0;
1768 /* If we can't reach the device, signal failure */
1769 if (err
|| bcmsdh_regfail(sdh
))
1770 sdio_info
->pub
->busstate
= DBUS_STATE_DOWN
;
1774 dbus_sdio_read_control(sdio_info_t
*sdio_info
, uint8
*hdr
, uint len
, uint doff
)
1776 bcmsdh_info_t
*sdh
= sdio_info
->sdh
;
1781 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
1783 /* Control data already received in aligned rxctl */
1784 if ((sdio_info
->bus
== SPI_BUS
) && (!sdio_info
->usebufpool
))
1787 ASSERT(sdio_info
->rxbuf
);
1788 /* Set rxctl for frame (w/optional alignment) */
1789 sdio_info
->rxctl
= sdio_info
->rxbuf
;
1791 sdio_info
->rxctl
+= firstread
;
1792 if ((pad
= ((uintptr
)sdio_info
->rxctl
% SDALIGN
)))
1793 sdio_info
->rxctl
+= (SDALIGN
- pad
);
1794 sdio_info
->rxctl
-= firstread
;
1796 ASSERT(sdio_info
->rxctl
>= sdio_info
->rxbuf
);
1798 /* Copy the already-read portion over */
1799 bcopy(hdr
, sdio_info
->rxctl
, firstread
);
1800 if (len
<= firstread
)
1803 /* Copy the full data pkt in gSPI case and process ioctl. */
1804 if (sdio_info
->bus
== SPI_BUS
) {
1805 bcopy(hdr
, sdio_info
->rxctl
, len
);
1809 /* Raise rdlen to next SDIO block to avoid tail command */
1810 rdlen
= len
- firstread
;
1811 if (sdio_info
->roundup
&& sdio_info
->blocksize
&& (rdlen
> sdio_info
->blocksize
)) {
1812 pad
= sdio_info
->blocksize
- (rdlen
% sdio_info
->blocksize
);
1813 if ((pad
<= sdio_info
->roundup
) && (pad
< sdio_info
->blocksize
) &&
1814 ((len
+ pad
) < sdio_info
->maxctl
))
1818 /* Satisfy length-alignment requirements */
1819 if (forcealign
&& (rdlen
& (ALIGNMENT
- 1)))
1820 rdlen
= ROUNDUP(rdlen
, ALIGNMENT
);
1822 /* Drop if the read is too big or it exceeds our maximum */
1823 if ((rdlen
+ firstread
) > sdio_info
->maxctl
) {
1824 DBUSERR(("%s: %d-byte control read exceeds %d-byte buffer\n",
1825 __FUNCTION__
, rdlen
, sdio_info
->maxctl
));
1826 sdio_info
->pub
->stats
.rx_errors
++;
1827 dbus_sdio_rxfail(sdio_info
, FALSE
, FALSE
);
1831 if ((len
- doff
) > sdio_info
->maxctl
) {
1832 DBUSERR(("%s: %d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
1833 __FUNCTION__
, len
, (len
- doff
), sdio_info
->maxctl
));
1834 sdio_info
->pub
->stats
.rx_errors
++; sdio_info
->rx_toolong
++;
1835 dbus_sdio_rxfail(sdio_info
, FALSE
, FALSE
);
1840 /* Read remainder of frame body into the rxctl buffer */
1841 sdret
= bcmsdh_recv_buf(sdh
, SI_ENUM_BASE
, SDIO_FUNC_2
, F2SYNC
,
1842 (sdio_info
->rxctl
+ firstread
), rdlen
, NULL
, NULL
, NULL
);
1843 sdio_info
->f2rxdata
++;
1844 ASSERT(sdret
!= BCME_PENDING
);
1846 /* Control frame failures need retransmission */
1848 DBUSERR(("%s: read %d control bytes failed: %d\n", __FUNCTION__
, rdlen
, sdret
));
1849 sdio_info
->rxc_errors
++; /* dhd.rx_ctlerrs is higher level */
1850 dbus_sdio_rxfail(sdio_info
, TRUE
, TRUE
);
1855 /* Point to valid data and indicate its length */
1856 sdio_info
->rxctl
+= doff
;
1858 if (sdio_info
->rxlen
!= 0) {
1859 DBUSERR(("dropping previous recv ctl pkt\n"));
1861 sdio_info
->rxlen
= len
- doff
;
1863 if (sdio_info
->cbarg
&& sdio_info
->cbs
) {
1864 if (sdio_info
->rxctl_req
.pending
== TRUE
) {
1865 dbus_sdio_rxctl(sdio_info
, sdio_info
->rxctl_req
.ctl
.buf
,
1866 sdio_info
->rxctl_req
.ctl
.len
);
1867 bzero(&sdio_info
->rxctl_req
, sizeof(sdio_info
->rxctl_req
));
1868 dbus_sdio_ctl_complete(sdio_info
, DBUS_CBCTL_READ
, DBUS_OK
);
1870 /* If receive ctl pkt before user request, leave in cache
1871 * and retrieve it next time recv_ctl() is called.
1879 dbus_sdio_rxglom(sdio_info_t
*sdio_info
, uint8 rxseq
)
1881 uint16 dlen
, totlen
;
1882 uint8
*dptr
, num
= 0;
1884 uint16 sublen
, check
;
1885 void *pfirst
, *plast
, *pnext
, *save_pfirst
;
1886 osl_t
*osh
= sdio_info
->pub
->osh
;
1889 uint8 chan
, seq
, doff
, sfdoff
;
1892 bool usechain
= sdio_info
->use_rxchain
;
1894 /* If packets, issue read(s) and send up packet chain */
1895 /* Return sequence numbers consumed? */
1897 DBUSTRACE(("dbus_sdio_rxglom: start: glomd %p glom %p\n",
1898 sdio_info
->glomd
, sdio_info
->glom
));
1900 /* If there's a descriptor, generate the packet chain */
1901 if (sdio_info
->glomd
) {
1902 dlen
= (uint16
)PKTLEN(osh
, sdio_info
->glomd
);
1903 dptr
= PKTDATA(osh
, sdio_info
->glomd
);
1904 if (!dlen
|| (dlen
& 1)) {
1905 DBUSERR(("%s: bad glomd len (%d), toss descriptor\n",
1906 __FUNCTION__
, dlen
));
1907 dbus_sdcb_pktfree(sdio_info
, sdio_info
->glomd
, FALSE
);
1908 sdio_info
->glomd
= NULL
;
1909 sdio_info
->nextlen
= 0;
1913 pfirst
= plast
= pnext
= NULL
;
1915 for (totlen
= num
= 0; dlen
; num
++) {
1916 /* Get (and move past) next length */
1917 sublen
= ltoh16_ua(dptr
);
1918 dlen
-= sizeof(uint16
);
1919 dptr
+= sizeof(uint16
);
1920 if ((sublen
< SDPCM_HDRLEN
) ||
1921 ((num
== 0) && (sublen
< (2 * SDPCM_HDRLEN
)))) {
1922 DBUSERR(("%s: desciptor len %d bad: %d\n",
1923 __FUNCTION__
, num
, sublen
));
1927 if (sublen
% SDALIGN
) {
1928 DBUSERR(("%s: sublen %d not a multiple of %d\n",
1929 __FUNCTION__
, sublen
, SDALIGN
));
1934 /* For last frame, adjust read len so total is a block multiple */
1936 sublen
+= (ROUNDUP(totlen
, sdio_info
->blocksize
) - totlen
);
1937 totlen
= ROUNDUP(totlen
, sdio_info
->blocksize
);
1940 /* Allocate/chain packet for next subframe */
1941 if ((pnext
= dbus_sdcb_pktget(sdio_info
,
1942 sublen
+ SDALIGN
, FALSE
)) == NULL
) {
1943 DBUSERR(("%s: dbus_sdio_pktget failed, num %d len %d\n",
1944 __FUNCTION__
, num
, sublen
));
1947 ASSERT(!PKTLINK(pnext
));
1950 pfirst
= plast
= pnext
;
1953 PKTSETNEXT(osh
, plast
, pnext
);
1957 /* Adhere to start alignment requirements */
1958 PKTALIGN(osh
, pnext
, sublen
, SDALIGN
);
1961 /* If allocation failed, toss entirely and increment count */
1964 dbus_sdcb_pktfree(sdio_info
, pfirst
, FALSE
);
1965 dbus_sdcb_pktfree(sdio_info
, sdio_info
->glomd
, FALSE
);
1966 sdio_info
->glomd
= NULL
;
1967 sdio_info
->nextlen
= 0;
1971 /* Ok, we have a packet chain, save in bus structure */
1972 DBUSGLOM(("%s: allocated %d-byte packet chain for %d subframes\n",
1973 __FUNCTION__
, totlen
, num
));
1974 if (DBUSGLOM_ON() && sdio_info
->nextlen
) {
1975 if (totlen
!= sdio_info
->nextlen
) {
1976 DBUSGLOM(("%s: glomdesc mismatch: nextlen %d glomdesc %d "
1977 "rxseq %d\n", __FUNCTION__
, sdio_info
->nextlen
,
1981 sdio_info
->glom
= pfirst
;
1983 /* Done with descriptor packet */
1984 dbus_sdcb_pktfree(sdio_info
, sdio_info
->glomd
, FALSE
);
1985 sdio_info
->glomd
= NULL
;
1986 sdio_info
->nextlen
= 0;
1989 /* Ok -- either we just generated a packet chain, or had one from before */
1990 if (sdio_info
->glom
) {
1991 if (DBUSGLOM_ON()) {
1992 DBUSGLOM(("%s: attempt superframe read, packet chain:\n", __FUNCTION__
));
1993 for (pnext
= sdio_info
->glom
; pnext
; pnext
= PKTNEXT(osh
, pnext
)) {
1994 DBUSGLOM((" %p: %p len 0x%04x (%d)\n",
1995 pnext
, (uint8
*)PKTDATA(osh
, pnext
),
1996 PKTLEN(osh
, pnext
), PKTLEN(osh
, pnext
)));
2000 pfirst
= sdio_info
->glom
;
2001 dlen
= (uint16
)pkttotlen(osh
, pfirst
);
2003 /* Do an SDIO read for the superframe. Configurable iovar to
2004 * read directly into the chained packet, or allocate a large
2005 * packet and and copy into the chain.
2008 errcode
= bcmsdh_recv_buf(sdio_info
->sdh
, SI_ENUM_BASE
, SDIO_FUNC_2
,
2009 F2SYNC
, (uint8
*)PKTDATA(osh
, pfirst
),
2010 dlen
, pfirst
, NULL
, NULL
);
2011 } else if (sdio_info
->dataptr
) {
2012 errcode
= bcmsdh_recv_buf(sdio_info
->sdh
, SI_ENUM_BASE
, SDIO_FUNC_2
,
2013 F2SYNC
, sdio_info
->dataptr
,
2014 dlen
, NULL
, NULL
, NULL
);
2015 sublen
= (uint16
)pktfrombuf(osh
, pfirst
, 0, dlen
, sdio_info
->dataptr
);
2016 if (sublen
!= dlen
) {
2017 DBUSERR(("%s: FAILED TO COPY, dlen %d sublen %d\n",
2018 __FUNCTION__
, dlen
, sublen
));
2023 DBUSERR(("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n", dlen
));
2026 sdio_info
->f2rxdata
++;
2027 ASSERT(errcode
!= BCME_PENDING
);
2029 /* On failure, kill the superframe, allow a couple retries */
2031 DBUSERR(("%s: glom read of %d bytes failed: %d\n",
2032 __FUNCTION__
, dlen
, errcode
));
2033 sdio_info
->pub
->stats
.rx_errors
++;
2035 if (sdio_info
->glomerr
++ < 3) {
2036 dbus_sdio_rxfail(sdio_info
, TRUE
, TRUE
);
2038 sdio_info
->glomerr
= 0;
2039 dbus_sdio_rxfail(sdio_info
, TRUE
, FALSE
);
2040 dbus_sdcb_pktfree(sdio_info
, sdio_info
->glom
, FALSE
);
2041 sdio_info
->rxglomfail
++;
2042 sdio_info
->glom
= NULL
;
2044 OSL_DELAY(dlen
/128);
2049 if (DBUSGLOM_ON()) {
2050 prhex("SUPERFRAME", PKTDATA(osh
, pfirst
),
2051 MIN(PKTLEN(osh
, pfirst
), 48));
2056 /* Validate the superframe header */
2057 dptr
= (uint8
*)PKTDATA(osh
, pfirst
);
2058 sublen
= ltoh16_ua(dptr
);
2059 check
= ltoh16_ua(dptr
+ sizeof(uint16
));
2061 chan
= SDPCM_PACKET_CHANNEL(&dptr
[SDPCM_FRAMETAG_LEN
]);
2062 seq
= SDPCM_PACKET_SEQUENCE(&dptr
[SDPCM_FRAMETAG_LEN
]);
2063 sdio_info
->nextlen
= dptr
[SDPCM_FRAMETAG_LEN
+ SDPCM_NEXTLEN_OFFSET
];
2064 if ((sdio_info
->nextlen
<< 4) > MAX_RX_DATASZ
) {
2065 DBUSINFO(("%s: got frame w/nextlen too large (%d) seq %d\n",
2066 __FUNCTION__
, sdio_info
->nextlen
, seq
));
2067 sdio_info
->nextlen
= 0;
2069 doff
= SDPCM_DOFFSET_VALUE(&dptr
[SDPCM_FRAMETAG_LEN
]);
2070 txmax
= SDPCM_WINDOW_VALUE(&dptr
[SDPCM_FRAMETAG_LEN
]);
2073 if ((uint16
)~(sublen
^check
)) {
2074 DBUSERR(("%s (superframe): HW hdr error: len/check 0x%04x/0x%04x\n",
2075 __FUNCTION__
, sublen
, check
));
2077 } else if (ROUNDUP(sublen
, sdio_info
->blocksize
) != dlen
) {
2078 DBUSERR(("%s (superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n",
2079 __FUNCTION__
, sublen
,
2080 ROUNDUP(sublen
, sdio_info
->blocksize
), dlen
));
2082 } else if (SDPCM_PACKET_CHANNEL(&dptr
[SDPCM_FRAMETAG_LEN
]) != SDPCM_GLOM_CHANNEL
) {
2083 DBUSERR(("%s (superframe): bad channel %d\n", __FUNCTION__
,
2084 SDPCM_PACKET_CHANNEL(&dptr
[SDPCM_FRAMETAG_LEN
])));
2086 } else if (SDPCM_GLOMDESC(&dptr
[SDPCM_FRAMETAG_LEN
])) {
2087 DBUSERR(("%s (superframe): got second descriptor?\n", __FUNCTION__
));
2089 } else if ((doff
< SDPCM_HDRLEN
) ||
2090 (doff
> (PKTLEN(osh
, pfirst
) - SDPCM_HDRLEN
))) {
2091 DBUSERR(("%s (superframe): Bad data offset %d: HW %d pkt %d min %d\n",
2092 __FUNCTION__
, doff
, sublen
, PKTLEN(osh
, pfirst
), SDPCM_HDRLEN
));
2096 /* Check sequence number of superframe SW header */
2098 DBUSINFO(("%s: (superframe) rx_seq %d, expected %d\n",
2099 __FUNCTION__
, seq
, rxseq
));
2100 sdio_info
->rx_badseq
++;
2104 /* Check window for sanity */
2105 if ((uint8
)(txmax
- sdio_info
->tx_seq
) > 0x40) {
2106 DBUSERR(("%s: got unlikely tx max %d with tx_seq %d\n",
2107 __FUNCTION__
, txmax
, sdio_info
->tx_seq
));
2108 txmax
= sdio_info
->tx_seq
+ 2;
2110 sdio_info
->tx_max
= txmax
;
2112 /* Remove superframe header, remember offset */
2113 PKTPULL(osh
, pfirst
, doff
);
2116 /* Validate all the subframe headers */
2117 for (num
= 0, pnext
= pfirst
; pnext
&& !errcode
;
2118 num
++, pnext
= PKTNEXT(osh
, pnext
)) {
2119 dptr
= (uint8
*)PKTDATA(osh
, pnext
);
2120 dlen
= (uint16
)PKTLEN(osh
, pnext
);
2121 sublen
= ltoh16_ua(dptr
);
2122 check
= ltoh16_ua(dptr
+ sizeof(uint16
));
2123 chan
= SDPCM_PACKET_CHANNEL(&dptr
[SDPCM_FRAMETAG_LEN
]);
2124 doff
= SDPCM_DOFFSET_VALUE(&dptr
[SDPCM_FRAMETAG_LEN
]);
2126 if (DBUSGLOM_ON()) {
2127 prhex("subframe", dptr
, 32);
2131 if ((uint16
)~(sublen
^check
)) {
2132 DBUSERR(("%s (subframe %d): HW hdr error: "
2133 "len/check 0x%04x/0x%04x\n",
2134 __FUNCTION__
, num
, sublen
, check
));
2136 } else if ((sublen
> dlen
) || (sublen
< SDPCM_HDRLEN
)) {
2137 DBUSERR(("%s (subframe %d): length mismatch: "
2138 "len 0x%04x, expect 0x%04x\n",
2139 __FUNCTION__
, num
, sublen
, dlen
));
2141 } else if ((chan
!= SDPCM_DATA_CHANNEL
) &&
2142 (chan
!= SDPCM_EVENT_CHANNEL
)) {
2143 DBUSERR(("%s (subframe %d): bad channel %d\n",
2144 __FUNCTION__
, num
, chan
));
2146 } else if ((doff
< SDPCM_HDRLEN
) || (doff
> sublen
)) {
2147 DBUSERR(("%s (subframe %d): Bad data offset %d: HW %d min %d\n",
2148 __FUNCTION__
, num
, doff
, sublen
, SDPCM_HDRLEN
));
2154 /* Terminate frame on error, request a couple retries */
2155 if (sdio_info
->glomerr
++ < 3) {
2156 /* Restore superframe header space */
2157 PKTPUSH(osh
, pfirst
, sfdoff
);
2158 dbus_sdio_rxfail(sdio_info
, TRUE
, TRUE
);
2160 sdio_info
->glomerr
= 0;
2161 dbus_sdio_rxfail(sdio_info
, TRUE
, FALSE
);
2162 dbus_sdcb_pktfree(sdio_info
, sdio_info
->glom
, FALSE
);
2163 sdio_info
->rxglomfail
++;
2164 sdio_info
->glom
= NULL
;
2166 sdio_info
->nextlen
= 0;
2170 /* Basic SD framing looks ok - process each packet (header) */
2171 save_pfirst
= pfirst
;
2172 sdio_info
->glom
= NULL
;
2175 for (num
= 0; pfirst
; rxseq
++, pfirst
= pnext
) {
2176 pnext
= PKTNEXT(osh
, pfirst
);
2177 PKTSETNEXT(osh
, pfirst
, NULL
);
2179 dptr
= (uint8
*)PKTDATA(osh
, pfirst
);
2180 sublen
= ltoh16_ua(dptr
);
2181 chan
= SDPCM_PACKET_CHANNEL(&dptr
[SDPCM_FRAMETAG_LEN
]);
2182 seq
= SDPCM_PACKET_SEQUENCE(&dptr
[SDPCM_FRAMETAG_LEN
]);
2183 doff
= SDPCM_DOFFSET_VALUE(&dptr
[SDPCM_FRAMETAG_LEN
]);
2185 DBUSGLOM(("%s: Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n",
2186 __FUNCTION__
, num
, pfirst
, PKTDATA(osh
, pfirst
),
2187 PKTLEN(osh
, pfirst
), sublen
, chan
, seq
));
2189 ASSERT((chan
== SDPCM_DATA_CHANNEL
) || (chan
== SDPCM_EVENT_CHANNEL
));
2192 DBUSGLOM(("%s: rx_seq %d, expected %d\n",
2193 __FUNCTION__
, seq
, rxseq
));
2194 sdio_info
->rx_badseq
++;
2198 PKTSETLEN(osh
, pfirst
, sublen
);
2199 PKTPULL(osh
, pfirst
, doff
);
2201 if (PKTLEN(osh
, pfirst
) == 0) {
2202 dbus_sdcb_pktfree(sdio_info
, pfirst
, FALSE
);
2204 PKTSETNEXT(osh
, plast
, pnext
);
2206 ASSERT(save_pfirst
== pfirst
);
2207 save_pfirst
= pnext
;
2212 /* this packet will go up, link back into chain and count it */
2213 PKTSETNEXT(osh
, pfirst
, pnext
);
2218 if (DBUSGLOM_ON()) {
2219 DBUSGLOM(("%s subframe %d to stack, %p(%p/%d) nxt/lnk %p/%p\n",
2220 __FUNCTION__
, num
, pfirst
,
2221 PKTDATA(osh
, pfirst
), PKTLEN(osh
, pfirst
),
2222 PKTNEXT(osh
, pfirst
), PKTLINK(pfirst
)));
2223 prhex("", (uint8
*)PKTDATA(osh
, pfirst
),
2224 MIN(PKTLEN(osh
, pfirst
), 32));
2233 dbus_irb_rx_t
*rxirb
;
2235 plist
= save_pfirst
;
2236 for (i
= 0; plist
&& i
< num
; i
++, plist
= pnext
) {
2237 pnext
= PKTNEXT(osh
, plist
);
2238 PKTSETNEXT(osh
, plist
, NULL
);
2240 rxirb
= (dbus_irb_rx_t
*) dbus_sdcb_getirb(sdio_info
, FALSE
);
2241 if (rxirb
!= NULL
) {
2243 dbus_sdio_recv_irb_complete(sdio_info
, rxirb
, DBUS_OK
);
2245 ASSERT(0); /* FIX: Handle this case */
2250 sdio_info
->rxglomframes
++;
2251 sdio_info
->rxglompkts
+= num
;
2256 /* Return TRUE if there may be more frames to read */
2258 dbus_sdio_readframes(sdio_info_t
*sdio_info
, uint maxframes
, bool *finished
)
2260 bcmsdh_info_t
*sdh
= sdio_info
->sdh
;
2262 uint16 len
, check
; /* Extracted hardware header fields */
2263 uint8 chan
, seq
, doff
; /* Extracted software header fields */
2264 uint8 fcbits
; /* Extracted fcbits from software header */
2267 void *pkt
; /* Packet for event or data frames */
2268 uint16 pad
; /* Number of pad bytes to read */
2269 uint16 rdlen
; /* Total number of bytes to read */
2270 uint8 rxseq
; /* Next sequence number to expect */
2271 uint rxleft
= 0; /* Remaining number of frames allowed */
2272 int sdret
; /* Return code from bcmsdh calls */
2273 uint8 txmax
; /* Maximum tx sequence offered */
2274 uint32 dstatus
= 0; /* gSPI device status bits of */
2275 bool len_consistent
; /* Result of comparing readahead len and len from hw-hdr */
2277 dbus_irb_rx_t
*rxirb
;
2279 #if defined(BCMDBG) || defined(SDTEST)
2280 bool sdtest
= FALSE
; /* To limit message spew from test mode */
2283 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
2288 /* Allow pktgen to override maxframes */
2289 if (sdio_info
->pktgen_count
&& (sdio_info
->pktgen_mode
== DHD_PKTGEN_RECV
)) {
2290 maxframes
= sdio_info
->pktgen_count
;
2295 /* Not finished unless we encounter no more frames indication */
2299 /* Get pktlen from gSPI device F0 reg. */
2300 if (sdio_info
->bus
== SPI_BUS
) {
2301 /* Peek in dstatus bits and find out size to do rx-read. */
2302 dstatus
= bcmsdh_get_dstatus(sdio_info
->sdh
);
2303 DBUSTRACE(("Device status from regread = 0x%x\n", dstatus
));
2304 DBUSTRACE(("Device status from bit-reconstruction = 0x%x\n",
2305 bcmsdh_get_dstatus((void *)sdio_info
->sdh
)));
2307 if ((dstatus
& STATUS_F2_PKT_AVAILABLE
) && (((dstatus
& STATUS_UNDERFLOW
)) == 0)) {
2308 sdio_info
->nextlen
= (dstatus
& STATUS_F2_PKT_LEN
) >> STATUS_F2_PKT_SHIFT
;
2309 /* '0' size with pkt-available interrupt is eqvt to 2048 bytes */
2310 sdio_info
->nextlen
=
2311 (sdio_info
->nextlen
== 0) ? SPI_MAX_PKT_LEN
: sdio_info
->nextlen
;
2312 DBUSINFO(("Entering %s: length to be read from gSPI = %d\n",
2313 __FUNCTION__
, sdio_info
->nextlen
));
2315 if (dstatus
& STATUS_F2_PKT_AVAILABLE
)
2316 DBUSERR(("Underflow during %s.\n", __FUNCTION__
));
2318 DBUSERR(("False pkt-available intr.\n"));
2320 return (maxframes
- rxleft
);
2325 for (rxseq
= sdio_info
->rx_seq
, rxleft
= maxframes
;
2326 !sdio_info
->rxskip
&& rxleft
&& sdio_info
->pub
->busstate
!= DBUS_STATE_DOWN
;
2327 rxseq
++, rxleft
--) {
2329 /* Handle glomming separately */
2330 if (sdio_info
->glom
|| sdio_info
->glomd
) {
2332 DBUSGLOM(("%s: calling rxglom: glomd %p, glom %p\n",
2333 __FUNCTION__
, sdio_info
->glomd
, sdio_info
->glom
));
2335 cnt
= dbus_sdio_rxglom(sdio_info
, rxseq
);
2336 DBUSGLOM(("%s: rxglom returned %d\n", __FUNCTION__
, cnt
));
2338 rxleft
= (rxleft
> cnt
) ? (rxleft
- cnt
) : 1;
2342 /* Try doing single read if we can */
2343 if (dhd_readahead
&& sdio_info
->nextlen
) {
2344 uint16 nextlen
= sdio_info
->nextlen
;
2345 sdio_info
->nextlen
= 0;
2347 if (sdio_info
->bus
== SPI_BUS
) {
2348 rdlen
= len
= nextlen
;
2351 rdlen
= len
= nextlen
<< 4;
2353 /* Pad read to blocksize for efficiency */
2354 if (sdio_info
->roundup
&& sdio_info
->blocksize
&&
2355 (rdlen
> sdio_info
->blocksize
)) {
2356 pad
= sdio_info
->blocksize
- (rdlen
% sdio_info
->blocksize
);
2357 if ((pad
<= sdio_info
->roundup
) &&
2358 (pad
< sdio_info
->blocksize
) &&
2359 ((rdlen
+ pad
+ firstread
) < MAX_RX_DATASZ
))
2364 /* We use sdio_info->rxctl buffer in WinXP for initial control pkt receives.
2365 * Later we use buffer-poll for data as well as control packets.
2366 * This is required becuase dhd receives full frame in gSPI unlike SDIO.
2367 * After the frame is received we have to distinguish whether it is data
2368 * or non-data frame.
2370 /* Allocate a packet buffer */
2371 if (!(pkt
= dbus_sdcb_pktget(sdio_info
, rdlen
+ SDALIGN
, FALSE
))) {
2372 if (sdio_info
->bus
== SPI_BUS
) {
2373 sdio_info
->usebufpool
= FALSE
;
2374 sdio_info
->rxctl
= sdio_info
->rxbuf
;
2376 sdio_info
->rxctl
+= firstread
;
2377 if ((pad
= ((uintptr
)sdio_info
->rxctl
% SDALIGN
)))
2378 sdio_info
->rxctl
+= (SDALIGN
- pad
);
2379 sdio_info
->rxctl
-= firstread
;
2381 ASSERT(sdio_info
->rxctl
>= sdio_info
->rxbuf
);
2382 rxbuf
= sdio_info
->rxctl
;
2383 /* Read the entire frame */
2384 sdret
= bcmsdh_recv_buf(sdh
, SI_ENUM_BASE
, SDIO_FUNC_2
,
2385 F2SYNC
, rxbuf
, rdlen
, NULL
, NULL
, NULL
);
2386 sdio_info
->f2rxdata
++;
2387 ASSERT(sdret
!= BCME_PENDING
);
2390 if (bcmsdh_get_dstatus((void *)sdio_info
->sdh
) &
2392 sdio_info
->nextlen
= 0;
2394 DBUSERR(("%s: read %d control bytes failed "
2395 "due to spi underflow\n",
2396 __FUNCTION__
, rdlen
));
2397 /* dhd.rx_ctlerrs is higher level */
2398 sdio_info
->rxc_errors
++;
2403 /* Control frame failures need retransmission */
2405 DBUSERR(("%s: read %d control bytes failed: %d\n",
2406 __FUNCTION__
, rdlen
, sdret
));
2407 /* dhd.rx_ctlerrs is higher level */
2408 sdio_info
->rxc_errors
++;
2409 dbus_sdio_rxfail(sdio_info
, TRUE
,
2410 (sdio_info
->bus
== SPI_BUS
) ? FALSE
: TRUE
);
2414 /* Give up on data, request rtx of events */
2415 DBUSERR(("%s (nextlen): dbus_sdio_pktget failed: len %d rdlen %d "
2416 "expected rxseq %d\n",
2417 __FUNCTION__
, len
, rdlen
, rxseq
));
2418 /* Just go try again w/normal header read */
2422 if (sdio_info
->bus
== SPI_BUS
)
2423 sdio_info
->usebufpool
= TRUE
;
2425 ASSERT(!PKTLINK(pkt
));
2426 PKTALIGN(sdio_info
->pub
->osh
, pkt
, rdlen
, SDALIGN
);
2427 rxbuf
= (uint8
*)PKTDATA(sdio_info
->pub
->osh
, pkt
);
2428 /* Read the entire frame */
2429 sdret
= bcmsdh_recv_buf(sdh
, SI_ENUM_BASE
, SDIO_FUNC_2
, F2SYNC
,
2430 rxbuf
, rdlen
, pkt
, NULL
, NULL
);
2431 sdio_info
->f2rxdata
++;
2432 ASSERT(sdret
!= BCME_PENDING
);
2434 if (bcmsdh_get_dstatus((void *)sdio_info
->sdh
) & STATUS_UNDERFLOW
) {
2435 sdio_info
->nextlen
= 0;
2437 DBUSERR(("%s (nextlen): read %d bytes failed due "
2438 "to spi underflow\n",
2439 __FUNCTION__
, rdlen
));
2440 dbus_sdcb_pktfree(sdio_info
, pkt
, FALSE
);
2441 sdio_info
->pub
->stats
.rx_errors
++;
2446 DBUSERR(("%s (nextlen): read %d bytes failed: %d\n",
2447 __FUNCTION__
, rdlen
, sdret
));
2448 dbus_sdcb_pktfree(sdio_info
, pkt
, FALSE
);
2449 sdio_info
->pub
->stats
.rx_errors
++;
2450 /* Force retry w/normal header read. Don't attemp NAK for
2453 dbus_sdio_rxfail(sdio_info
, TRUE
,
2454 (sdio_info
->bus
== SPI_BUS
) ? FALSE
: TRUE
);
2459 /* Now check the header */
2460 bcopy(rxbuf
, sdio_info
->rxhdr
, SDPCM_HDRLEN
);
2462 /* Extract hardware header fields */
2463 len
= ltoh16_ua(sdio_info
->rxhdr
);
2464 check
= ltoh16_ua(sdio_info
->rxhdr
+ sizeof(uint16
));
2466 /* All zeros means readahead info was bad */
2468 DBUSINFO(("%s (nextlen): read zeros in HW header???\n",
2471 GSPI_PR55150_BAILOUT
;
2475 /* Validate check bytes */
2476 if ((uint16
)~(len
^check
)) {
2477 DBUSERR(("%s (nextlen): HW hdr error: nextlen/len/check"
2478 " 0x%04x/0x%04x/0x%04x\n", __FUNCTION__
, nextlen
,
2481 sdio_info
->rx_badhdr
++;
2482 dbus_sdio_rxfail(sdio_info
, FALSE
, FALSE
);
2483 GSPI_PR55150_BAILOUT
;
2487 /* Validate frame length */
2488 if (len
< SDPCM_HDRLEN
) {
2489 DBUSERR(("%s (nextlen): HW hdr length invalid: %d\n",
2490 __FUNCTION__
, len
));
2492 GSPI_PR55150_BAILOUT
;
2496 /* Check for consistency with readahead info */
2497 if (sdio_info
->bus
== SPI_BUS
)
2498 len_consistent
= (nextlen
!= len
);
2500 len_consistent
= (nextlen
!= (ROUNDUP(len
, 16) >> 4));
2501 if (len_consistent
) {
2502 /* Mismatch, force retry w/normal header (may be >4K) */
2503 DBUSERR(("%s (nextlen): mismatch, nextlen %d len %d rnd %d; "
2504 "expected rxseq %d\n",
2505 __FUNCTION__
, nextlen
, len
, ROUNDUP(len
, 16), rxseq
));
2507 dbus_sdio_rxfail(sdio_info
, TRUE
,
2508 (sdio_info
->bus
== SPI_BUS
) ? FALSE
: TRUE
);
2509 GSPI_PR55150_BAILOUT
;
2514 /* Extract software header fields */
2515 chan
= SDPCM_PACKET_CHANNEL(&sdio_info
->rxhdr
[SDPCM_FRAMETAG_LEN
]);
2516 seq
= SDPCM_PACKET_SEQUENCE(&sdio_info
->rxhdr
[SDPCM_FRAMETAG_LEN
]);
2517 doff
= SDPCM_DOFFSET_VALUE(&sdio_info
->rxhdr
[SDPCM_FRAMETAG_LEN
]);
2518 txmax
= SDPCM_WINDOW_VALUE(&sdio_info
->rxhdr
[SDPCM_FRAMETAG_LEN
]);
2521 /* Save the readahead length if there is one */
2522 if (sdio_info
->bus
== SPI_BUS
) {
2523 /* Use reconstructed dstatus bits and find out readahead size */
2524 dstatus
= bcmsdh_get_dstatus((void *)sdio_info
->sdh
);
2525 DBUSINFO(("Device status from bit-reconstruction = 0x%x\n",
2526 bcmsdh_get_dstatus((void *)sdio_info
->sdh
)));
2527 if (dstatus
& STATUS_F2_PKT_AVAILABLE
) {
2528 sdio_info
->nextlen
= (dstatus
& STATUS_F2_PKT_LEN
) >>
2529 STATUS_F2_PKT_SHIFT
;
2530 sdio_info
->nextlen
= (sdio_info
->nextlen
== 0) ?
2531 SPI_MAX_PKT_LEN
: sdio_info
->nextlen
;
2532 DBUSINFO(("readahead len from gSPI = %d \n",
2533 sdio_info
->nextlen
));
2534 sdio_info
->rx_readahead_cnt
++;
2536 sdio_info
->nextlen
= 0;
2541 sdio_info
->nextlen
=
2542 sdio_info
->rxhdr
[SDPCM_FRAMETAG_LEN
+ SDPCM_NEXTLEN_OFFSET
];
2543 if ((sdio_info
->nextlen
<< 4) > MAX_RX_DATASZ
) {
2544 DBUSINFO(("%s (nextlen): got frame w/nextlen too large"
2545 " (%d), seq %d\n", __FUNCTION__
, sdio_info
->nextlen
,
2547 sdio_info
->nextlen
= 0;
2550 sdio_info
->rx_readahead_cnt
++;
2555 /* Handle Flow Control - Brett */
2556 fcbits
= SDPCM_FCMASK_VALUE(&sdio_info
->rxhdr
[SDPCM_FRAMETAG_LEN
]);
2559 if (~sdio_info
->flowcontrol
& fcbits
) {
2560 sdio_info
->fc_xoff
++;
2563 if (sdio_info
->flowcontrol
& ~fcbits
) {
2564 sdio_info
->fc_xon
++;
2569 sdio_info
->fc_rcvd
++;
2570 sdio_info
->flowcontrol
= fcbits
;
2573 /* Check and update sequence number */
2575 DBUSINFO(("%s (nextlen): rx_seq %d, expected %d\n",
2576 __FUNCTION__
, seq
, rxseq
));
2577 sdio_info
->rx_badseq
++;
2581 /* Check window for sanity */
2582 if ((uint8
)(txmax
- sdio_info
->tx_seq
) > 0x40) {
2583 if ((sdio_info
->bus
== SPI_BUS
) &&
2584 !(dstatus
& STATUS_F2_RX_READY
)) {
2585 DBUSERR(("%s: got unlikely tx max %d with tx_seq %d\n",
2586 __FUNCTION__
, txmax
, sdio_info
->tx_seq
));
2587 txmax
= sdio_info
->tx_seq
+ 2;
2589 DBUSERR(("%s: got unlikely tx max %d with tx_seq %d\n",
2590 __FUNCTION__
, txmax
, sdio_info
->tx_seq
));
2591 txmax
= sdio_info
->tx_seq
+ 2;
2594 sdio_info
->tx_max
= txmax
;
2596 if (chan
== SDPCM_CONTROL_CHANNEL
) {
2597 if (sdio_info
->bus
== SPI_BUS
) {
2598 dbus_sdio_read_control(sdio_info
, rxbuf
, len
, doff
);
2599 if (sdio_info
->usebufpool
) {
2600 dbus_sdcb_pktfree(sdio_info
, pkt
, FALSE
);
2604 DBUSERR(("%s (nextlen): readahead on control"
2605 " packet %d?\n", __FUNCTION__
, seq
));
2606 /* Force retry w/normal header read */
2607 sdio_info
->nextlen
= 0;
2608 dbus_sdio_rxfail(sdio_info
, FALSE
, TRUE
);
2614 if ((sdio_info
->bus
== SPI_BUS
) && !sdio_info
->usebufpool
) {
2615 DBUSERR(("Received %d bytes on %d channel. Running out of "
2616 "rx pktbuf's or not yet malloced.\n", len
, chan
));
2620 /* Validate data offset */
2621 if ((doff
< SDPCM_HDRLEN
) || (doff
> len
)) {
2622 DBUSERR(("%s (nextlen): bad data offset %d: HW len %d min %d\n",
2623 __FUNCTION__
, doff
, len
, SDPCM_HDRLEN
));
2626 dbus_sdio_rxfail(sdio_info
, FALSE
, FALSE
);
2630 /* All done with this one -- now deliver the packet */
2633 /* gSPI frames should not be handled in fractions */
2634 if (sdio_info
->bus
== SPI_BUS
) {
2638 /* Read frame header (hardware and software) */
2639 sdret
= bcmsdh_recv_buf(sdio_info
->sdh
, SI_ENUM_BASE
, SDIO_FUNC_2
, F2SYNC
,
2640 sdio_info
->rxhdr
, firstread
, NULL
, NULL
, NULL
);
2641 sdio_info
->f2rxhdrs
++;
2642 ASSERT(sdret
!= BCME_PENDING
);
2645 DBUSERR(("%s: RXHEADER FAILED: %d\n", __FUNCTION__
, sdret
));
2646 sdio_info
->rx_hdrfail
++;
2647 dbus_sdio_rxfail(sdio_info
, TRUE
, TRUE
);
2651 /* Extract hardware header fields */
2652 len
= ltoh16_ua(sdio_info
->rxhdr
);
2653 check
= ltoh16_ua(sdio_info
->rxhdr
+ sizeof(uint16
));
2655 /* All zeros means no more frames */
2661 /* Validate check bytes */
2662 if ((uint16
)~(len
^check
)) {
2663 DBUSERR(("%s: HW hdr error: len/check 0x%04x/0x%04x\n",
2664 __FUNCTION__
, len
, check
));
2665 sdio_info
->rx_badhdr
++;
2666 dbus_sdio_rxfail(sdio_info
, FALSE
, FALSE
);
2670 /* Validate frame length */
2671 if (len
< SDPCM_HDRLEN
) {
2672 DBUSERR(("%s: HW hdr length invalid: %d\n", __FUNCTION__
, len
));
2676 /* Extract software header fields */
2677 chan
= SDPCM_PACKET_CHANNEL(&sdio_info
->rxhdr
[SDPCM_FRAMETAG_LEN
]);
2678 seq
= SDPCM_PACKET_SEQUENCE(&sdio_info
->rxhdr
[SDPCM_FRAMETAG_LEN
]);
2679 doff
= SDPCM_DOFFSET_VALUE(&sdio_info
->rxhdr
[SDPCM_FRAMETAG_LEN
]);
2680 txmax
= SDPCM_WINDOW_VALUE(&sdio_info
->rxhdr
[SDPCM_FRAMETAG_LEN
]);
2682 /* Validate data offset */
2683 if ((doff
< SDPCM_HDRLEN
) || (doff
> len
)) {
2684 DBUSERR(("%s: Bad data offset %d: HW len %d, min %d seq %d\n",
2685 __FUNCTION__
, doff
, len
, SDPCM_HDRLEN
, seq
));
2686 sdio_info
->rx_badhdr
++;
2688 dbus_sdio_rxfail(sdio_info
, FALSE
, FALSE
);
2692 /* Save the readahead length if there is one */
2693 sdio_info
->nextlen
= sdio_info
->rxhdr
[SDPCM_FRAMETAG_LEN
+ SDPCM_NEXTLEN_OFFSET
];
2694 if ((sdio_info
->nextlen
<< 4) > MAX_RX_DATASZ
) {
2695 DBUSINFO(("%s (nextlen): got frame w/nextlen too large (%d), seq %d\n",
2696 __FUNCTION__
, sdio_info
->nextlen
, seq
));
2697 sdio_info
->nextlen
= 0;
2700 /* Handle Flow Control */
2701 fcbits
= SDPCM_FCMASK_VALUE(&sdio_info
->rxhdr
[SDPCM_FRAMETAG_LEN
]);
2704 if (~sdio_info
->flowcontrol
& fcbits
) {
2705 sdio_info
->fc_xoff
++;
2708 if (sdio_info
->flowcontrol
& ~fcbits
) {
2709 sdio_info
->fc_xon
++;
2714 sdio_info
->fc_rcvd
++;
2715 sdio_info
->flowcontrol
= fcbits
;
2718 /* Check and update sequence number */
2720 DBUSINFO(("%s: rx_seq %d, expected %d\n", __FUNCTION__
, seq
, rxseq
));
2721 sdio_info
->rx_badseq
++;
2725 /* Check window for sanity */
2726 if ((uint8
)(txmax
- sdio_info
->tx_seq
) > 0x40) {
2727 DBUSERR(("%s: got unlikely tx max %d with tx_seq %d\n",
2728 __FUNCTION__
, txmax
, sdio_info
->tx_seq
));
2729 txmax
= sdio_info
->tx_seq
+ 2;
2731 sdio_info
->tx_max
= txmax
;
2733 /* Call a separate function for control frames */
2734 if (chan
== SDPCM_CONTROL_CHANNEL
) {
2735 dbus_sdio_read_control(sdio_info
, sdio_info
->rxhdr
, len
, doff
);
2739 ASSERT((chan
== SDPCM_DATA_CHANNEL
) || (chan
== SDPCM_EVENT_CHANNEL
) ||
2740 (chan
== SDPCM_TEST_CHANNEL
) || (chan
== SDPCM_GLOM_CHANNEL
));
2742 /* Length to read */
2743 rdlen
= (len
> firstread
) ? (len
- firstread
) : 0;
2745 /* May pad read to blocksize for efficiency */
2746 if (sdio_info
->roundup
&& sdio_info
->blocksize
&& (rdlen
> sdio_info
->blocksize
)) {
2747 pad
= sdio_info
->blocksize
- (rdlen
% sdio_info
->blocksize
);
2748 if ((pad
<= sdio_info
->roundup
) && (pad
< sdio_info
->blocksize
) &&
2749 ((rdlen
+ pad
+ firstread
) < MAX_RX_DATASZ
))
2753 /* Satisfy length-alignment requirements */
2754 if (forcealign
&& (rdlen
& (ALIGNMENT
- 1)))
2755 rdlen
= ROUNDUP(rdlen
, ALIGNMENT
);
2757 if ((rdlen
+ firstread
) > MAX_RX_DATASZ
) {
2758 /* Too long -- skip this frame */
2759 DBUSERR(("%s: too long: len %d rdlen %d\n", __FUNCTION__
, len
, rdlen
));
2760 sdio_info
->pub
->stats
.rx_errors
++; sdio_info
->rx_toolong
++;
2761 dbus_sdio_rxfail(sdio_info
, FALSE
, FALSE
);
2765 if (!(pkt
= dbus_sdcb_pktget(sdio_info
, (rdlen
+ firstread
+ SDALIGN
), FALSE
))) {
2766 /* Give up on data, request rtx of events */
2767 DBUSERR(("%s: dbus_sdio_pktget failed: rdlen %d chan %d\n",
2768 __FUNCTION__
, rdlen
, chan
));
2769 sdio_info
->pub
->stats
.rx_dropped
++;
2770 dbus_sdio_rxfail(sdio_info
, FALSE
, RETRYCHAN(chan
));
2774 ASSERT(!PKTLINK(pkt
));
2776 /* Leave room for what we already read, and align remainder */
2777 ASSERT(firstread
< (PKTLEN(sdio_info
->pub
->osh
, pkt
)));
2778 PKTPULL(sdio_info
->pub
->osh
, pkt
, firstread
);
2779 PKTALIGN(sdio_info
->pub
->osh
, pkt
, rdlen
, SDALIGN
);
2781 /* Read the remaining frame data */
2782 sdret
= bcmsdh_recv_buf(sdh
, SI_ENUM_BASE
, SDIO_FUNC_2
, F2SYNC
,
2783 ((uint8
*)PKTDATA(osh
, pkt
)), rdlen
, pkt
, NULL
, NULL
);
2784 sdio_info
->f2rxdata
++;
2785 ASSERT(sdret
!= BCME_PENDING
);
2788 DBUSERR(("%s: read %d %s bytes failed: %d\n", __FUNCTION__
, rdlen
,
2789 ((chan
== SDPCM_EVENT_CHANNEL
) ? "event" :
2790 ((chan
== SDPCM_DATA_CHANNEL
) ? "data" : "test")), sdret
));
2791 dbus_sdcb_pktfree(sdio_info
, pkt
, FALSE
);
2792 sdio_info
->pub
->stats
.rx_errors
++;
2793 dbus_sdio_rxfail(sdio_info
, TRUE
, RETRYCHAN(chan
));
2797 /* Copy the already-read portion */
2798 PKTPUSH(sdio_info
->pub
->osh
, pkt
, firstread
);
2799 bcopy(sdio_info
->rxhdr
, PKTDATA(sdio_info
->pub
->osh
, pkt
), firstread
);
2802 /* Save superframe descriptor and allocate packet frame */
2803 if (chan
== SDPCM_GLOM_CHANNEL
) {
2804 if (SDPCM_GLOMDESC(&sdio_info
->rxhdr
[SDPCM_FRAMETAG_LEN
])) {
2805 DBUSGLOM(("%s: got glom descriptor, %d bytes:\n",
2806 __FUNCTION__
, len
));
2808 if (DBUSGLOM_ON()) {
2809 prhex("Glom Data", PKTDATA(sdio_info
->pub
->osh
, pkt
), len
);
2812 PKTSETLEN(sdio_info
->pub
->osh
, pkt
, len
);
2813 ASSERT(doff
== SDPCM_HDRLEN
);
2814 PKTPULL(sdio_info
->pub
->osh
, pkt
, SDPCM_HDRLEN
);
2815 sdio_info
->glomd
= pkt
;
2817 DBUSERR(("%s: glom superframe w/o descriptor!\n", __FUNCTION__
));
2818 dbus_sdio_rxfail(sdio_info
, FALSE
, FALSE
);
2823 /* Fill in packet len and prio, deliver upward */
2824 PKTSETLEN(sdio_info
->pub
->osh
, pkt
, len
);
2825 PKTPULL(sdio_info
->pub
->osh
, pkt
, doff
);
2828 /* Test channel packets are processed separately */
2829 if (chan
== SDPCM_TEST_CHANNEL
) {
2830 dbus_sdio_testrcv(sdio_info
, pkt
, seq
);
2835 if (PKTLEN(sdio_info
->pub
->osh
, pkt
) == 0) {
2836 dbus_sdcb_pktfree(sdio_info
, pkt
, FALSE
);
2840 rxirb
= (dbus_irb_rx_t
*) dbus_sdcb_getirb(sdio_info
, FALSE
);
2841 if (rxirb
!= NULL
) {
2843 dbus_sdio_recv_irb_complete(sdio_info
, rxirb
, DBUS_OK
);
2845 DBUSERR(("ERROR: failed to get rx irb\n"));
2846 dbus_sdcb_pktfree(sdio_info
, pkt
, FALSE
);
2851 /* Message if we hit the limit */
2852 if (!rxleft
&& !sdtest
)
2853 DBUSERR(("%s: hit rx limit of %d frames\n", __FUNCTION__
, maxframes
));
2856 DBUSDATA(("%s: processed %d frames\n", __FUNCTION__
, (maxframes
- rxleft
)));
2858 /* Back off rxseq if awaiting rtx, upate rx_seq */
2859 if (sdio_info
->rxskip
)
2861 sdio_info
->rx_seq
= rxseq
;
2863 return (maxframes
- rxleft
);
2867 dbus_sdio_hostmail(sdio_info_t
*sdio_info
)
2869 sdpcmd_regs_t
*regs
= sdio_info
->regs
;
2870 uint32 intstatus
= 0;
2875 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
2877 /* Read mailbox data and ack that we did so */
2878 R_SDREG(hmb_data
, ®s
->tohostmailboxdata
, retries
);
2879 if (retries
<= retry_limit
)
2880 W_SDREG(SMB_INT_ACK
, ®s
->tosbmailbox
, retries
);
2881 sdio_info
->f1regdata
+= 2;
2883 /* Dongle recomposed rx frames, accept them again */
2884 if (hmb_data
& HMB_DATA_NAKHANDLED
) {
2885 DBUSINFO(("Dongle reports NAK handled, expect rtx of %d\n", sdio_info
->rx_seq
));
2886 if (!sdio_info
->rxskip
) {
2887 DBUSERR(("%s: unexpected NAKHANDLED!\n", __FUNCTION__
));
2889 sdio_info
->rxskip
= FALSE
;
2890 intstatus
|= I_HMB_FRAME_IND
;
2894 * Not using DEVREADY or FWREADY at the moment; just print.
2895 * DEVREADY does not occur with gSPI.
2897 if (hmb_data
& (HMB_DATA_DEVREADY
| HMB_DATA_FWREADY
)) {
2898 sdio_info
->sdpcm_ver
= (hmb_data
& HMB_DATA_VERSION_MASK
) >> HMB_DATA_VERSION_SHIFT
;
2899 if (sdio_info
->sdpcm_ver
!= SDPCM_PROT_VERSION
)
2900 DBUSERR(("Version mismatch, dongle reports %d, expecting %d\n",
2901 sdio_info
->sdpcm_ver
, SDPCM_PROT_VERSION
));
2903 DBUSINFO(("Dongle ready, protocol version %d\n", sdio_info
->sdpcm_ver
));
2907 * Flow Control has been moved into the RX headers and this out of band
2908 * method isn't used any more. Leae this here for possibly remaining backward
2909 * compatible with older dongles
2911 if (hmb_data
& HMB_DATA_FC
) {
2912 fcbits
= (hmb_data
& HMB_DATA_FCDATA_MASK
) >> HMB_DATA_FCDATA_SHIFT
;
2914 if (fcbits
& ~sdio_info
->flowcontrol
)
2915 sdio_info
->fc_xoff
++;
2916 if (sdio_info
->flowcontrol
& ~fcbits
)
2917 sdio_info
->fc_xon
++;
2919 sdio_info
->fc_rcvd
++;
2920 sdio_info
->flowcontrol
= fcbits
;
2923 /* Shouldn't be any others */
2924 if (hmb_data
& ~(HMB_DATA_DEVREADY
|
2925 HMB_DATA_NAKHANDLED
|
2928 HMB_DATA_FCDATA_MASK
|
2929 HMB_DATA_VERSION_MASK
)) {
2930 DBUSERR(("Unknown mailbox data content: 0x%02x\n", hmb_data
));
2936 #ifndef BCM_DNGL_EMBEDIMAGE
2938 dbus_sdh_devrdy_isr(void *handle
)
2940 probe_sdh_info_t
*pinfo
= handle
;
2941 bcmsdh_info_t
*sdh
= pinfo
->sdh
;
2942 uint32 intstatus
= 0, hmb_data
= 0;
2944 if (pinfo
->devready
== FALSE
) {
2945 intstatus
= R_REG(pinfo
->osh
, &pinfo
->chinfo
->sdregs
->intstatus
);
2946 if (intstatus
& I_HMB_HOST_INT
) {
2947 hmb_data
= R_REG(pinfo
->osh
, &pinfo
->chinfo
->sdregs
->tohostmailboxdata
);
2948 if (hmb_data
& (HMB_DATA_DEVREADY
|HMB_DATA_FWREADY
)) {
2949 bcmsdh_intr_disable(sdh
);
2950 pinfo
->devready
= TRUE
;
2951 dbus_sdos_sched_probe_cb();
2957 #endif /* BCM_DNGL_EMBEDIMAGE */
2960 dbus_sdh_isr(void *handle
)
2962 sdio_info_t
*sdio_info
= (sdio_info_t
*) handle
;
2966 ASSERT(sdio_info
->sdh
);
2968 if (dbus_sdio_isr(sdio_info
, &wantdpc
) == TRUE
) {
2969 bcmsdh_intr_disable(sdio_info
->sdh
);
2970 sdio_info
->intdis
= TRUE
;
2975 dbus_sdio_isr(void *handle
, bool *wantdpc
)
2977 sdio_info_t
*sdio_info
= (sdio_info_t
*) handle
;
2978 bool handle_int
= FALSE
;
2980 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
2986 * Do not use spinlock in isr() to share
2987 * resources with other lower priority functions
2988 * because isr() runs at DIRQL which can preempt
2989 * them and cause race condition/deadlock.
2990 * To share resources with isr() use NdisMSynchronizeWithInterrupt()
2991 * Functions that indirectly use spinlock bcmsdh_reg_read(),
2992 * bcmsdh_intr_disable(), etc.
2999 /* Count the interrupt call */
3000 sdio_info
->intrcount
++;
3001 sdio_info
->ipend
= TRUE
;
3003 /* Shouldn't get this interrupt if we're sleeping? */
3004 if (sdio_info
->sleeping
) {
3005 DBUSERR(("INTERRUPT WHILE SLEEPING??\n"));
3010 /* Disable additional interrupts (is this needed now)? */
3011 if (sdio_info
->intr
) {
3012 DBUSINTR(("%s: disable SDIO interrupts\n", __FUNCTION__
));
3014 DBUSERR(("dbus_sdio_isr() w/o interrupt configured!\n"));
3017 sdio_info
->intdis
= TRUE
;
3019 dbus_sdos_sched_dpc(sdio_info
);
3020 sdio_info
->dpc_sched
= TRUE
;
3030 dbus_sdio_pktgen_init(sdio_info_t
*sdio_info
)
3032 /* Default to specified length, or full range */
3033 if (dhd_pktgen_len
) {
3034 sdio_info
->pktgen_maxlen
= MIN(dhd_pktgen_len
, MAX_PKTGEN_LEN
);
3035 sdio_info
->pktgen_minlen
= sdio_info
->pktgen_maxlen
;
3037 sdio_info
->pktgen_maxlen
= MAX_PKTGEN_LEN
;
3038 sdio_info
->pktgen_minlen
= 0;
3040 sdio_info
->pktgen_len
= (uint16
)sdio_info
->pktgen_minlen
;
3042 /* Default to per-watchdog burst with 10s print time */
3043 sdio_info
->pktgen_freq
= 1;
3044 sdio_info
->pktgen_print
= 10000/dhd_watchdog_ms
;
3045 sdio_info
->pktgen_count
= (dhd_pktgen
* dhd_watchdog_ms
+ 999) / 1000;
3047 /* Default to echo mode */
3048 sdio_info
->pktgen_mode
= DHD_PKTGEN_ECHO
;
3049 sdio_info
->pktgen_stop
= 1;
3053 dbus_sdio_pktgen(sdio_info_t
*sdio_info
)
3061 /* Display current count if appropriate */
3062 if (sdio_info
->pktgen_print
&& (++sdio_info
->pktgen_ptick
>= sdio_info
->pktgen_print
)) {
3063 sdio_info
->pktgen_ptick
= 0;
3064 printf("%s: send attempts %d rcvd %d\n",
3065 __FUNCTION__
, sdio_info
->pktgen_sent
, sdio_info
->pktgen_rcvd
);
3068 /* For recv mode, just make sure dongle has started sending */
3069 if (sdio_info
->pktgen_mode
== DHD_PKTGEN_RECV
) {
3070 if (!sdio_info
->pktgen_rcvd
)
3071 dbus_sdio_sdtest_set(sdio_info
, TRUE
);
3075 /* Otherwise, generate or request the specified number of packets */
3076 for (pktcount
= 0; pktcount
< sdio_info
->pktgen_count
; pktcount
++) {
3077 /* Stop if total has been reached */
3078 if (sdio_info
->pktgen_total
&&
3079 (sdio_info
->pktgen_sent
>= sdio_info
->pktgen_total
)) {
3080 sdio_info
->pktgen_count
= 0;
3084 /* Allocate an appropriate-sized packet */
3085 len
= sdio_info
->pktgen_len
;
3086 if (!(pkt
= dbus_sdcb_pktget(sdio_info
,
3087 (len
+ SDPCM_HDRLEN
+ SDPCM_TEST_HDRLEN
+ SDALIGN
), TRUE
))) {
3088 DBUSERR(("%s: dbus_sdio_pktget failed!\n", __FUNCTION__
));
3091 PKTALIGN(sdio_info
->pub
->osh
, pkt
,
3092 (len
+ SDPCM_HDRLEN
+ SDPCM_TEST_HDRLEN
), SDALIGN
);
3093 data
= (uint8
*)PKTDATA(sdio_info
->pub
->osh
, pkt
) + SDPCM_HDRLEN
;
3095 /* Write test header cmd and extra based on mode */
3096 switch (sdio_info
->pktgen_mode
) {
3097 case DHD_PKTGEN_ECHO
:
3098 *data
++ = SDPCM_TEST_ECHOREQ
;
3099 *data
++ = (uint8
)sdio_info
->pktgen_sent
;
3102 case DHD_PKTGEN_SEND
:
3103 *data
++ = SDPCM_TEST_DISCARD
;
3104 *data
++ = (uint8
)sdio_info
->pktgen_sent
;
3107 case DHD_PKTGEN_RXBURST
:
3108 *data
++ = SDPCM_TEST_BURST
;
3109 *data
++ = (uint8
)sdio_info
->pktgen_count
;
3113 DBUSERR(("Unrecognized pktgen mode %d\n", sdio_info
->pktgen_mode
));
3114 dbus_sdcb_pktfree(sdio_info
, pkt
, TRUE
);
3115 sdio_info
->pktgen_count
= 0;
3119 /* Write test header length field */
3120 *data
++ = (len
>> 0);
3121 *data
++ = (len
>> 8);
3123 /* Then fill in the remainder -- N/A for burst, but who cares... */
3124 for (fillbyte
= 0; fillbyte
< len
; fillbyte
++)
3125 *data
++ = SDPCM_TEST_FILL(fillbyte
, (uint8
)sdio_info
->pktgen_sent
);
3128 if (dbus_sdio_txpkt(sdio_info
, pkt
, SDPCM_TEST_CHANNEL
)) {
3129 sdio_info
->pktgen_fail
++;
3130 if (sdio_info
->pktgen_stop
&&
3131 sdio_info
->pktgen_stop
== sdio_info
->pktgen_fail
)
3132 sdio_info
->pktgen_count
= 0;
3134 sdio_info
->pktgen_sent
++;
3136 /* Bump length if not fixed, wrap at max */
3137 if (++sdio_info
->pktgen_len
> sdio_info
->pktgen_maxlen
)
3138 sdio_info
->pktgen_len
= (uint16
)sdio_info
->pktgen_minlen
;
3140 /* Special case for burst mode: just send one request! */
3141 if (sdio_info
->pktgen_mode
== DHD_PKTGEN_RXBURST
)
3147 dbus_sdio_sdtest_set(sdio_info_t
*sdio_info
, bool start
)
3152 /* Allocate the packet */
3153 if (!(pkt
= dbus_sdcb_pktget(sdio_info
,
3154 SDPCM_HDRLEN
+ SDPCM_TEST_HDRLEN
+ SDALIGN
, TRUE
))) {
3155 DBUSERR(("%s: dbus_sdio_pktget failed!\n", __FUNCTION__
));
3158 PKTALIGN(sdio_info
->pub
->osh
, pkt
, (SDPCM_HDRLEN
+ SDPCM_TEST_HDRLEN
), SDALIGN
);
3159 data
= (uint8
*)PKTDATA(sdio_info
->pub
->osh
, pkt
) + SDPCM_HDRLEN
;
3161 /* Fill in the test header */
3162 *data
++ = SDPCM_TEST_SEND
;
3164 *data
++ = (sdio_info
->pktgen_maxlen
>> 0);
3165 *data
++ = (sdio_info
->pktgen_maxlen
>> 8);
3168 if (dbus_sdio_txpkt(sdio_info
, pkt
, SDPCM_TEST_CHANNEL
))
3169 sdio_info
->pktgen_fail
++;
3174 dbus_sdio_testrcv(sdio_info_t
*sdio_info
, void *pkt
, uint seq
)
3184 osh
= sdio_info
->pub
->osh
;
3186 /* Check for min length */
3187 if ((pktlen
= PKTLEN(sdio_info
->pub
->osh
, pkt
)) < SDPCM_TEST_HDRLEN
) {
3188 DBUSERR(("dbus_sdio_restrcv: toss runt frame, pktlen %d\n", pktlen
));
3189 dbus_sdcb_pktfree(sdio_info
, pkt
, FALSE
);
3193 /* Extract header fields */
3194 data
= PKTDATA(sdio_info
->pub
->osh
, pkt
);
3197 len
= *data
++; len
+= *data
++ << 8;
3199 /* Check length for relevant commands */
3200 if (cmd
== SDPCM_TEST_DISCARD
|| cmd
== SDPCM_TEST_ECHOREQ
|| cmd
== SDPCM_TEST_ECHORSP
) {
3201 if (pktlen
!= len
+ SDPCM_TEST_HDRLEN
) {
3202 DBUSERR(("dbus_sdio_testrcv: frame length mismatch, pktlen %d seq %d"
3203 " cmd %d extra %d len %d\n", pktlen
, seq
, cmd
, extra
, len
));
3204 dbus_sdcb_pktfree(sdio_info
, pkt
, FALSE
);
3209 /* Process as per command */
3211 case SDPCM_TEST_ECHOREQ
:
3212 /* Rx->Tx turnaround ok (even on NDIS w/current implementation) */
3213 *(uint8
*)(PKTDATA(sdio_info
->pub
->osh
, pkt
)) = SDPCM_TEST_ECHORSP
;
3214 if (dbus_sdio_txpkt(sdio_info
, pkt
, SDPCM_TEST_CHANNEL
) == 0) {
3215 sdio_info
->pktgen_sent
++;
3217 sdio_info
->pktgen_fail
++;
3218 dbus_sdcb_pktfree(sdio_info
, pkt
, FALSE
);
3220 sdio_info
->pktgen_rcvd
++;
3223 case SDPCM_TEST_ECHORSP
:
3224 if (sdio_info
->ext_loop
) {
3225 dbus_sdcb_pktfree(sdio_info
, pkt
, FALSE
);
3226 sdio_info
->pktgen_rcvd
++;
3230 for (offset
= 0; offset
< len
; offset
++, data
++) {
3231 if (*data
!= SDPCM_TEST_FILL(offset
, extra
)) {
3232 DBUSERR(("dbus_sdio_testrcv: echo data mismatch: "
3233 "offset %d (len %d) expect 0x%02x rcvd 0x%02x\n",
3234 offset
, len
, SDPCM_TEST_FILL(offset
, extra
), *data
));
3238 dbus_sdcb_pktfree(sdio_info
, pkt
, FALSE
);
3239 sdio_info
->pktgen_rcvd
++;
3242 case SDPCM_TEST_DISCARD
:
3243 dbus_sdcb_pktfree(sdio_info
, pkt
, FALSE
);
3244 sdio_info
->pktgen_rcvd
++;
3247 case SDPCM_TEST_BURST
:
3248 case SDPCM_TEST_SEND
:
3250 DBUSINFO(("dbus_sdio_testrcv: unsupported or unknown command, pktlen %d seq %d"
3251 " cmd %d extra %d len %d\n", pktlen
, seq
, cmd
, extra
, len
));
3252 dbus_sdcb_pktfree(sdio_info
, pkt
, FALSE
);
3256 /* For recv mode, stop at limie (and tell dongle to stop sending) */
3257 if (sdio_info
->pktgen_mode
== DHD_PKTGEN_RECV
) {
3258 if (sdio_info
->pktgen_total
&&
3259 (sdio_info
->pktgen_rcvd
>= sdio_info
->pktgen_total
)) {
3260 sdio_info
->pktgen_count
= 0;
3261 dbus_sdio_sdtest_set(sdio_info
, FALSE
);
3269 dbus_sdio_pktgen_get(sdio_info_t
*sdio_info
, uint8
*arg
)
3271 dhd_pktgen_t pktgen
;
3273 pktgen
.version
= DHD_PKTGEN_VERSION
;
3274 pktgen
.freq
= sdio_info
->pktgen_freq
;
3275 pktgen
.count
= sdio_info
->pktgen_count
;
3276 pktgen
.print
= sdio_info
->pktgen_print
;
3277 pktgen
.total
= sdio_info
->pktgen_total
;
3278 pktgen
.minlen
= sdio_info
->pktgen_minlen
;
3279 pktgen
.maxlen
= sdio_info
->pktgen_maxlen
;
3280 pktgen
.numsent
= sdio_info
->pktgen_sent
;
3281 pktgen
.numrcvd
= sdio_info
->pktgen_rcvd
;
3282 pktgen
.numfail
= sdio_info
->pktgen_fail
;
3283 pktgen
.mode
= sdio_info
->pktgen_mode
;
3284 pktgen
.stop
= sdio_info
->pktgen_stop
;
3286 bcopy(&pktgen
, arg
, sizeof(pktgen
));
3292 dbus_sdio_pktgen_set(sdio_info_t
*sdio_info
, uint8
*arg
)
3294 dhd_pktgen_t pktgen
;
3295 uint oldcnt
, oldmode
;
3297 bcopy(arg
, &pktgen
, sizeof(pktgen
));
3298 if (pktgen
.version
!= DHD_PKTGEN_VERSION
)
3301 oldcnt
= sdio_info
->pktgen_count
;
3302 oldmode
= sdio_info
->pktgen_mode
;
3304 sdio_info
->pktgen_freq
= pktgen
.freq
;
3305 sdio_info
->pktgen_count
= pktgen
.count
;
3306 sdio_info
->pktgen_print
= pktgen
.print
;
3307 sdio_info
->pktgen_total
= pktgen
.total
;
3308 sdio_info
->pktgen_minlen
= pktgen
.minlen
;
3309 sdio_info
->pktgen_maxlen
= pktgen
.maxlen
;
3310 sdio_info
->pktgen_mode
= pktgen
.mode
;
3311 sdio_info
->pktgen_stop
= pktgen
.stop
;
3313 sdio_info
->pktgen_tick
= sdio_info
->pktgen_ptick
= 0;
3314 sdio_info
->pktgen_len
= MAX(sdio_info
->pktgen_len
, sdio_info
->pktgen_minlen
);
3315 sdio_info
->pktgen_len
= MIN(sdio_info
->pktgen_len
, sdio_info
->pktgen_maxlen
);
3317 /* Clear counts for a new pktgen (mode change, or was stopped) */
3318 if (sdio_info
->pktgen_count
&& (!oldcnt
|| oldmode
!= sdio_info
->pktgen_mode
))
3319 sdio_info
->pktgen_sent
= sdio_info
->pktgen_rcvd
= sdio_info
->pktgen_fail
= 0;
3326 dbus_sdio_membytes(probe_sdh_info_t
*pinfo
, bool write
, uint32 address
, uint8
*data
, uint size
)
3336 /* Determine initial transfer parameters */
3337 sdaddr
= address
& SBSDIO_SB_OFT_ADDR_MASK
;
3338 if ((sdaddr
+ size
) & SBSDIO_SBWINDOW_MASK
)
3339 dsize
= (SBSDIO_SB_OFT_ADDR_LIMIT
- sdaddr
);
3343 /* Set the backplane window to include the start address */
3344 if ((bcmerror
= bcmsdhsdio_set_sbaddr_window(sdh
, address
, TRUE
))) {
3345 DBUSERR(("%s: window change failed\n", __FUNCTION__
));
3349 /* Do the transfer(s) */
3351 DBUSINFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n",
3352 __FUNCTION__
, (write
? "write" : "read"), dsize
, sdaddr
,
3353 (address
& SBSDIO_SBWINDOW_MASK
)));
3354 if ((bcmerror
= bcmsdh_rwdata(sdh
, write
, sdaddr
, data
, dsize
))) {
3355 DBUSERR(("%s: membytes transfer failed\n", __FUNCTION__
));
3359 /* Adjust for next transfer (if any) */
3360 if ((size
-= dsize
)) {
3363 if ((bcmerror
= bcmsdhsdio_set_sbaddr_window(sdh
, address
, FALSE
))) {
3364 DBUSERR(("%s: window change failed\n", __FUNCTION__
));
3368 dsize
= MIN(SBSDIO_SB_OFT_ADDR_LIMIT
, size
);
3373 /* Return the window to backplane enumeration space for core access */
3374 if (bcmsdhsdio_set_sbaddr_window(sdh
, SI_ENUM_BASE
, FALSE
)) {
3375 DBUSERR(("%s: FAILED to return to SI_ENUM_BASE\n", __FUNCTION__
));
3382 dbus_sdio_downloadvars(probe_sdh_info_t
*pinfo
, void *arg
, int len
)
3384 int bcmerror
= BCME_OK
;
3387 bcmerror
= BCME_BUFTOOSHORT
;
3392 MFREE(pinfo
->osh
, pinfo
->vars
, pinfo
->varsz
);
3396 pinfo
->vars
= MALLOC(pinfo
->osh
, len
);
3397 pinfo
->varsz
= pinfo
->vars
? len
: 0;
3398 if (pinfo
->vars
== NULL
) {
3400 bcmerror
= BCME_NOMEM
;
3403 bcopy(arg
, pinfo
->vars
, pinfo
->varsz
);
3409 dbus_sdio_doiovar(sdio_info_t
*sdio_info
, const bcm_iovar_t
*vi
, uint32 actionid
, const char *name
,
3410 void *params
, int plen
, void *arg
, int len
, int val_size
)
3416 DBUSTRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n",
3417 __FUNCTION__
, actionid
, name
, params
, plen
, arg
, len
, val_size
));
3419 if ((bcmerror
= bcm_iovar_lencheck(vi
, arg
, len
, IOV_ISSET(actionid
))) != 0)
3422 if (plen
>= (int)sizeof(int_val
))
3423 bcopy(params
, &int_val
, sizeof(int_val
));
3425 bool_val
= (int_val
!= 0) ? TRUE
: FALSE
;
3428 /* Some ioctls use the bus */
3429 /* Check if dongle is in reset. If so, only allow DEVRESET iovars */
3430 if (sdio_info
->dongle_reset
&& !(actionid
== IOV_SVAL(IOV_DEVRESET
) ||
3431 actionid
== IOV_GVAL(IOV_DEVRESET
))) {
3432 bcmerror
= BCME_NOTREADY
;
3436 /* Handle sleep stuff before any clock mucking */
3437 if (vi
->varid
== IOV_SLEEP
) {
3438 if (IOV_ISSET(actionid
)) {
3439 bcmerror
= dbus_sdio_bussleep(sdio_info
, bool_val
);
3441 int_val
= (int32
)sdio_info
->sleeping
;
3442 bcopy(&int_val
, arg
, val_size
);
3447 /* Request clock to allow SDIO accesses */
3448 if (!sdio_info
->dongle_reset
) {
3449 BUS_WAKE(sdio_info
);
3450 dbus_sdio_clkctl(sdio_info
, CLK_AVAIL
, FALSE
);
3454 case IOV_GVAL(IOV_INTR
):
3455 int_val
= (int32
)sdio_info
->intr
;
3456 bcopy(&int_val
, arg
, val_size
);
3459 case IOV_SVAL(IOV_INTR
):
3460 sdio_info
->intr
= bool_val
;
3461 sdio_info
->intdis
= FALSE
;
3463 /* FIX: Change to use busstate instead of up flag */
3464 if (sdio_info
->up
) {
3465 if (sdio_info
->intr
) {
3466 DBUSINTR(("%s: enable SDIO device interrupts\n", __FUNCTION__
));
3467 bcmsdh_intr_enable(sdio_info
->sdh
);
3469 DBUSINTR(("%s: disable SDIO interrupts\n", __FUNCTION__
));
3470 bcmsdh_intr_disable(sdio_info
->sdh
);
3475 case IOV_GVAL(IOV_POLLRATE
):
3476 int_val
= (int32
)sdio_info
->pollrate
;
3477 bcopy(&int_val
, arg
, val_size
);
3480 case IOV_SVAL(IOV_POLLRATE
):
3481 sdio_info
->pollrate
= (uint
)int_val
;
3482 sdio_info
->poll
= (sdio_info
->pollrate
!= 0);
3485 case IOV_GVAL(IOV_IDLETIME
):
3486 int_val
= sdio_info
->idletime
;
3487 bcopy(&int_val
, arg
, val_size
);
3490 case IOV_SVAL(IOV_IDLETIME
):
3491 if ((int_val
< 0) && (int_val
!= IDLE_IMMEDIATE
)) {
3492 bcmerror
= BCME_BADARG
;
3494 sdio_info
->idletime
= int_val
;
3498 case IOV_GVAL(IOV_IDLECLOCK
):
3499 int_val
= (int32
)sdio_info
->idleclock
;
3500 bcopy(&int_val
, arg
, val_size
);
3503 case IOV_SVAL(IOV_IDLECLOCK
):
3504 sdio_info
->idleclock
= int_val
;
3507 case IOV_GVAL(IOV_SD1IDLE
):
3508 int_val
= (int32
)sd1idle
;
3509 bcopy(&int_val
, arg
, val_size
);
3512 case IOV_SVAL(IOV_SD1IDLE
):
3516 case IOV_SVAL(IOV_MEMBYTES
):
3517 case IOV_GVAL(IOV_MEMBYTES
):
3523 bool set
= (actionid
== IOV_SVAL(IOV_MEMBYTES
));
3525 ASSERT(plen
>= 2*sizeof(int));
3527 address
= (uint32
)int_val
;
3528 bcopy((char *)params
+ sizeof(int_val
), &int_val
, sizeof(int_val
));
3529 size
= (uint
)int_val
;
3531 /* Do some validation */
3532 dsize
= set
? plen
- (2 * sizeof(int)) : len
;
3534 DBUSERR(("%s: error on %s membytes, addr 0x%08x size %d dsize %d\n",
3535 __FUNCTION__
, (set
? "set" : "get"), address
, size
, dsize
));
3536 bcmerror
= BCME_BADARG
;
3540 DBUSINFO(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__
,
3541 (set
? "write" : "read"), size
, address
));
3543 /* If we know about SOCRAM, check for a fit */
3544 if ((sdio_info
->orig_ramsize
) &&
3545 ((address
> sdio_info
->orig_ramsize
) ||
3546 (address
+ size
> sdio_info
->orig_ramsize
))) {
3547 DBUSERR(("%s: ramsize 0x%08x doesn't have %d bytes at 0x%08x\n",
3548 __FUNCTION__
, sdio_info
->orig_ramsize
, size
, address
));
3549 bcmerror
= BCME_BADARG
;
3553 /* Generate the actual data pointer */
3554 data
= set
? (uint8
*)params
+ 2 * sizeof(int): (uint8
*)arg
;
3556 /* Call to do the transfer */
3557 bcmerror
= dbus_sdio_membytes(&g_probe_info
, set
, address
, data
, size
);
3562 case IOV_GVAL(IOV_MEMSIZE
):
3563 int_val
= (int32
)sdio_info
->ramsize
;
3564 bcopy(&int_val
, arg
, val_size
);
3567 case IOV_GVAL(IOV_SDIOD_DRIVE
):
3568 int_val
= (int32
)dhd_sdiod_drive_strength
;
3569 bcopy(&int_val
, arg
, val_size
);
3572 case IOV_SVAL(IOV_SDIOD_DRIVE
):
3573 dhd_sdiod_drive_strength
= int_val
;
3574 si_sdiod_drive_strength_init(sdio_info
->sih
,
3575 sdio_info
->pub
->osh
, dhd_sdiod_drive_strength
);
3578 case IOV_SVAL(IOV_SET_DOWNLOAD_STATE
):
3579 bcmerror
= dbus_sdio_download_state(&g_probe_info
, bool_val
);
3581 #ifndef BCM_DNGL_EMBEDIMAGE
3582 if ((bool_val
== FALSE
) && (delay_eth
== 0)) {
3583 g_probe_info
.devready
= TRUE
;
3584 sdio_info
->pub
->busstate
= DBUS_STATE_DL_DONE
;
3589 case IOV_SVAL(IOV_VARS
):
3590 bcmerror
= dbus_sdio_downloadvars(&g_probe_info
, arg
, len
);
3593 case IOV_GVAL(IOV_READAHEAD
):
3594 int_val
= (int32
)dhd_readahead
;
3595 bcopy(&int_val
, arg
, val_size
);
3598 case IOV_SVAL(IOV_READAHEAD
):
3599 if (bool_val
&& !dhd_readahead
)
3600 sdio_info
->nextlen
= 0;
3601 dhd_readahead
= bool_val
;
3604 case IOV_GVAL(IOV_SDRXCHAIN
):
3605 int_val
= (int32
)sdio_info
->use_rxchain
;
3606 bcopy(&int_val
, arg
, val_size
);
3609 case IOV_SVAL(IOV_SDRXCHAIN
):
3610 if (bool_val
&& !sdio_info
->sd_rxchain
)
3611 bcmerror
= BCME_UNSUPPORTED
;
3613 sdio_info
->use_rxchain
= bool_val
;
3616 case IOV_GVAL(IOV_ALIGNCTL
):
3617 int_val
= (int32
)dhd_alignctl
;
3618 bcopy(&int_val
, arg
, val_size
);
3621 case IOV_SVAL(IOV_ALIGNCTL
):
3622 dhd_alignctl
= bool_val
;
3625 case IOV_GVAL(IOV_SDALIGN
):
3627 bcopy(&int_val
, arg
, val_size
);
3631 case IOV_GVAL(IOV_VARS
):
3632 if (sdio_info
->varsz
< (uint
)len
)
3633 bcopy(sdio_info
->vars
, arg
, sdio_info
->varsz
);
3635 bcmerror
= BCME_BUFTOOSHORT
;
3640 case IOV_GVAL(IOV_SDREG
):
3645 sd_ptr
= (sdreg_t
*)params
;
3647 addr
= (uintptr
)sdio_info
->regs
+ sd_ptr
->offset
;
3648 size
= sd_ptr
->func
;
3649 int_val
= (int32
)bcmsdh_reg_read(sdio_info
->sdh
, addr
, size
);
3650 if (bcmsdh_regfail(sdio_info
->sdh
))
3651 bcmerror
= BCME_SDIO_ERROR
;
3652 bcopy(&int_val
, arg
, sizeof(int32
));
3656 case IOV_SVAL(IOV_SDREG
):
3661 sd_ptr
= (sdreg_t
*)params
;
3663 addr
= (uintptr
)sdio_info
->regs
+ sd_ptr
->offset
;
3664 size
= sd_ptr
->func
;
3665 bcmsdh_reg_write(sdio_info
->sdh
, addr
, size
, sd_ptr
->value
);
3666 if (bcmsdh_regfail(sdio_info
->sdh
))
3667 bcmerror
= BCME_SDIO_ERROR
;
3671 /* Same as above, but offset is not backplane (not SDIO core) */
3672 case IOV_GVAL(IOV_SBREG
):
3677 sd_ptr
= (sdreg_t
*)params
;
3679 addr
= SI_ENUM_BASE
+ sd_ptr
->offset
;
3680 size
= sd_ptr
->func
;
3681 int_val
= (int32
)bcmsdh_reg_read(sdio_info
->sdh
, addr
, size
);
3682 if (bcmsdh_regfail(sdio_info
->sdh
))
3683 bcmerror
= BCME_SDIO_ERROR
;
3684 bcopy(&int_val
, arg
, sizeof(int32
));
3688 case IOV_SVAL(IOV_SBREG
):
3693 sd_ptr
= (sdreg_t
*)params
;
3695 addr
= SI_ENUM_BASE
+ sd_ptr
->offset
;
3696 size
= sd_ptr
->func
;
3697 bcmsdh_reg_write(sdio_info
->sdh
, addr
, size
, sd_ptr
->value
);
3698 if (bcmsdh_regfail(sdio_info
->sdh
))
3699 bcmerror
= BCME_SDIO_ERROR
;
3703 case IOV_GVAL(IOV_SDCIS
):
3707 bcmstrcat(arg
, "\nFunc 0\n");
3708 bcmsdh_cis_read(sdio_info
->sdh
, 0x10, (char *)arg
+ strlen(arg
), 49 * 32);
3709 bcmstrcat(arg
, "\nFunc 1\n");
3710 bcmsdh_cis_read(sdio_info
->sdh
, 0x11, (char *)arg
+ strlen(arg
), 49 * 32);
3711 bcmstrcat(arg
, "\nFunc 2\n");
3712 bcmsdh_cis_read(sdio_info
->sdh
, 0x12, (char *)arg
+ strlen(arg
), 49 * 32);
3716 case IOV_GVAL(IOV_FORCEEVEN
):
3717 int_val
= (int32
)forcealign
;
3718 bcopy(&int_val
, arg
, val_size
);
3721 case IOV_SVAL(IOV_FORCEEVEN
):
3722 forcealign
= bool_val
;
3725 case IOV_GVAL(IOV_TXBOUND
):
3726 int_val
= (int32
)dhd_txbound
;
3727 bcopy(&int_val
, arg
, val_size
);
3730 case IOV_SVAL(IOV_TXBOUND
):
3731 dhd_txbound
= (uint
)int_val
;
3734 case IOV_GVAL(IOV_RXBOUND
):
3735 int_val
= (int32
)dhd_rxbound
;
3736 bcopy(&int_val
, arg
, val_size
);
3739 case IOV_SVAL(IOV_RXBOUND
):
3740 dhd_rxbound
= (uint
)int_val
;
3744 #if defined(BCMDBG) || defined(DHD_SPROM)
3745 case IOV_SVAL(IOV_SPROM
):
3746 case IOV_GVAL(IOV_SPROM
):
3751 bool set
= (actionid
== IOV_SVAL(IOV_SPROM
));
3753 ASSERT(plen
>= 2*sizeof(int));
3755 offset
= (uint32
)int_val
;
3756 bcopy((char *)params
+ sizeof(int_val
), &int_val
, sizeof(int_val
));
3757 size
= (uint
)int_val
;
3759 /* Avoid bigger size of srom reads that may be requested from app.
3760 * gSPI has only F1 OTP visible from CC. There is no CIS in gSPI.
3762 if (sdio_info
->bus
== SPI_BUS
)
3763 size
= SBSDIO_CIS_SIZE_LIMIT
;
3765 /* Do some validation */
3766 dsize
= set
? plen
- (2 * sizeof(int)) : len
;
3768 DBUSERR(("%s: error on srom %s, addr 0x%08x size %d dsize %d\n",
3769 __FUNCTION__
, (set
? "write" : "read"), offset
, size
, dsize
));
3770 bcmerror
= BCME_BADARG
;
3774 if ((offset
> SROM_MAX
) || ((offset
+ size
) > SROM_MAX
)) {
3775 DBUSERR(("%s: error on srom %s, offset %d size %d exceeds limit %d\n",
3776 __FUNCTION__
, (set
? "write" : "read"), offset
, size
, SROM_MAX
));
3777 bcmerror
= BCME_BADARG
;
3782 if (!ISALIGNED(arg
, sizeof(uint16
))) {
3783 DBUSERR(("%s: srom data pointer %p not word-aligned\n",
3784 __FUNCTION__
, arg
));
3785 bcmerror
= BCME_BADARG
;
3788 bcmerror
= srom_read(sdio_info
->sih
, SD_BUSTYPE
,
3789 (void*)sdio_info
->regs
, sdio_info
->pub
->osh
,
3790 offset
, size
, (uint16
*)arg
, FALSE
);
3793 arg
= (void*)((uintptr
)arg
+ 2 * sizeof(int));
3794 if (!ISALIGNED(arg
, sizeof(uint16
))) {
3795 DBUSERR(("%s: srom data pointer %p not word-aligned\n",
3796 __FUNCTION__
, arg
));
3797 bcmerror
= BCME_BADARG
;
3800 bcmerror
= srom_write(sdio_info
->sih
, SD_BUSTYPE
,
3801 (void*)sdio_info
->regs
, sdio_info
->pub
->osh
,
3802 offset
, size
, (uint16
*)arg
);
3809 case IOV_GVAL(IOV_EXTLOOP
):
3810 int_val
= (int32
)sdio_info
->ext_loop
;
3811 bcopy(&int_val
, arg
, val_size
);
3814 case IOV_SVAL(IOV_EXTLOOP
):
3815 sdio_info
->ext_loop
= bool_val
;
3818 case IOV_GVAL(IOV_PKTGEN
):
3819 bcmerror
= dbus_sdio_pktgen_get(sdio_info
, arg
);
3822 case IOV_SVAL(IOV_PKTGEN
):
3823 bcmerror
= dbus_sdio_pktgen_set(sdio_info
, arg
);
3828 case IOV_SVAL(IOV_DEVRESET
):
3829 DBUSTRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d busstate=%d\n",
3830 __FUNCTION__
, bool_val
, sdio_info
->dongle_reset
,
3831 sdio_info
->pub
->busstate
));
3833 ASSERT(sdio_info
->pub
->osh
);
3835 /* FIX: Need to change to support async probe callback.
3837 DBUSERR(("DEVRESET unsupported for async probe callback \n"));
3840 if (bool_val
== TRUE
) {
3841 if (sdio_info
->dongle_reset
)
3843 /* Expect app to have torn down any connection before calling */
3844 /* Stop the bus, disable F2 */
3845 dbus_bus_stop(sdio_info
);
3847 /* Release tx/rx buffer, detach from the dongle */
3848 dbus_sdio_release_dongle(sdio_info
, sdio_info
->pub
->osh
);
3849 dbus_sdio_probe_deinit(&g_probe_info
);
3851 sdio_info
->dongle_reset
= TRUE
;
3852 sdio_info
->up
= FALSE
;
3854 DBUSTRACE(("%s: WLAN OFF DONE\n", __FUNCTION__
));
3855 /* App can now remove power from device */
3857 /* App must have restored power to device before calling */
3859 DBUSTRACE(("\n\n%s: == WLAN ON ==\n", __FUNCTION__
));
3861 if (!sdio_info
->dongle_reset
) {
3862 bcmerror
= BCME_NOTDOWN
;
3863 DBUSERR(("%s: Set DEVRESET=FALSE invoked when device is on\n",
3869 /* Reset SD client */
3870 bcmsdh_reset(sdio_info
->sdh
);
3872 /* Attempt to re-attach & download */
3873 if (dbus_sdio_probe_init(&g_probe_info
)) {
3874 /* Attempt to download binary to the dongle */
3875 if ((dbus_sdio_attach_init(sdio_info
, sdio_info
->sdh
,
3876 sdio_info
->firmware_path
, sdio_info
->nvram_path
))) {
3877 /* Re-init bus, enable F2 transfer */
3878 dbus_sdio_init(sdio_info
);
3880 sdio_info
->dongle_reset
= FALSE
;
3881 sdio_info
->up
= TRUE
;
3882 DBUSTRACE(("%s: == WLAN ON DONE ===\n",
3885 bcmerror
= BCME_SDIO_ERROR
;
3887 bcmerror
= BCME_SDIO_ERROR
;
3891 case IOV_GVAL(IOV_DEVRESET
):
3892 DBUSTRACE(("%s: Called get IOV_DEVRESET\n", __FUNCTION__
));
3894 /* Get its status */
3895 int_val
= (bool) sdio_info
->dongle_reset
;
3896 bcopy(&int_val
, arg
, val_size
);
3901 bcmerror
= BCME_UNSUPPORTED
;
3906 if ((sdio_info
->idletime
== IDLE_IMMEDIATE
) && !sdio_info
->dpc_sched
) {
3907 sdio_info
->activity
= FALSE
;
3908 dbus_sdio_clkctl(sdio_info
, CLK_NONE
, TRUE
);
3915 dbus_sdio_write_vars(probe_sdh_info_t
*pinfo
)
3923 if (!pinfo
->varsz
|| !pinfo
->vars
)
3926 varsize
= ROUNDUP(pinfo
->varsz
, 4);
3927 varaddr
= (pinfo
->ramsize
- 4) - varsize
;
3929 vbuffer
= (char*)MALLOC(pinfo
->osh
, varsize
);
3933 bzero(vbuffer
, varsize
);
3934 bcopy(pinfo
->vars
, vbuffer
, pinfo
->varsz
);
3936 /* Write the vars list */
3937 bcmerror
= dbus_sdio_membytes(pinfo
, TRUE
, varaddr
, vbuffer
, varsize
);
3939 MFREE(pinfo
->osh
, vbuffer
, varsize
);
3941 /* adjust to the user specified RAM */
3942 DBUSINFO(("origram size is %d and used ramsize is %d, vars are at %d, orig varsize is %d\n",
3943 pinfo
->orig_ramsize
, pinfo
->ramsize
, varaddr
, varsize
));
3944 varsize
= ((pinfo
->orig_ramsize
- 4) - varaddr
);
3945 varsizew
= varsize
>> 2;
3946 DBUSINFO(("new varsize is %d, varsizew is %d\n", varsize
, varsizew
));
3948 /* Write the length to the last word */
3951 DBUSINFO(("bcmerror : Varsizew is being written as %d\n", varsizew
));
3952 dbus_sdio_membytes(pinfo
, TRUE
, (pinfo
->orig_ramsize
- 4), (uint8
*)&varsizew
, 4);
3954 DBUSINFO(("Varsize is %d and varsizew is %d\n", varsize
, varsizew
));
3955 varsizew
= (~varsizew
<< 16) | (varsizew
& 0x0000FFFF);
3956 varsizew
= htol32(varsizew
);
3957 DBUSINFO(("Varsizew is 0x%x and htol is 0x%x\n", varsizew
, htol32(varsizew
)));
3958 bcmerror
= dbus_sdio_membytes(pinfo
, TRUE
, (pinfo
->orig_ramsize
- 4),
3959 (uint8
*)&varsizew
, 4);
3966 dbus_sdio_download_state(probe_sdh_info_t
*pinfo
, bool enter
)
3976 /* To enter download state, disable ARM and reset SOCRAM.
3977 * To exit download state, simply reset ARM (default is RAM boot).
3981 pinfo
->alp_only
= TRUE
;
3983 if (!(si_setcore(sih
, ARM7S_CORE_ID
, 0)) &&
3984 !(si_setcore(sih
, ARMCM3_CORE_ID
, 0))) {
3985 DBUSERR(("%s: Failed to find ARM core!\n", __FUNCTION__
));
3986 bcmerror
= BCME_ERROR
;
3990 si_core_disable(sih
, 0);
3991 if (bcmsdh_regfail(pinfo
->sdh
)) {
3992 DBUSERR(("%s: Failed to disable ARM core!\n", __FUNCTION__
));
3993 bcmerror
= BCME_SDIO_ERROR
;
3997 if (!(si_setcore(sih
, SOCRAM_CORE_ID
, 0))) {
3998 DBUSERR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__
));
3999 bcmerror
= BCME_ERROR
;
4003 si_core_reset(sih
, 0, 0);
4004 if (bcmsdh_regfail(pinfo
->sdh
)) {
4005 DBUSERR(("%s: Failure trying reset SOCRAM core?\n", __FUNCTION__
));
4006 bcmerror
= BCME_SDIO_ERROR
;
4010 /* Clear the top bit of memory */
4011 if (pinfo
->ramsize
) {
4013 dbus_sdio_membytes(pinfo
, TRUE
, pinfo
->ramsize
- 4, (uint8
*)&zeros
, 4);
4016 if (!(si_setcore(sih
, SOCRAM_CORE_ID
, 0))) {
4017 DBUSERR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__
));
4018 bcmerror
= BCME_ERROR
;
4022 if (!si_iscoreup(sih
)) {
4023 DBUSERR(("%s: SOCRAM core is down after reset?\n", __FUNCTION__
));
4024 bcmerror
= BCME_ERROR
;
4028 if ((bcmerror
= dbus_sdio_write_vars(pinfo
))) {
4029 DBUSERR(("%s: could not write vars to ram\n", __FUNCTION__
));
4033 if (!si_setcore(sih
, PCMCIA_CORE_ID
, 0) &&
4034 !si_setcore(sih
, SDIOD_CORE_ID
, 0)) {
4035 DBUSERR(("%s: Can't change back to SDIO core?\n", __FUNCTION__
));
4036 bcmerror
= BCME_ERROR
;
4039 W_REG(pinfo
->osh
, &pinfo
->chinfo
->sdregs
->intstatus
, 0xFFFFFFFF);
4042 if (!(si_setcore(sih
, ARM7S_CORE_ID
, 0)) &&
4043 !(si_setcore(sih
, ARMCM3_CORE_ID
, 0))) {
4044 DBUSERR(("%s: Failed to find ARM core!\n", __FUNCTION__
));
4045 bcmerror
= BCME_ERROR
;
4049 si_core_reset(sih
, 0, 0);
4050 if (bcmsdh_regfail(pinfo
->sdh
)) {
4051 DBUSERR(("%s: Failure trying to reset ARM core?\n", __FUNCTION__
));
4052 bcmerror
= BCME_SDIO_ERROR
;
4056 /* Allow HT Clock now that the ARM is running. */
4057 pinfo
->alp_only
= FALSE
;
4061 /* Always return to SDIOD core */
4062 if (!si_setcore(sih
, PCMCIA_CORE_ID
, 0))
4063 si_setcore(sih
, SDIOD_CORE_ID
, 0);
4069 dbus_iovar_process(sdio_info_t
*sdio_info
, const char *name
,
4070 void *params
, int plen
, void *arg
, int len
, bool set
)
4072 const bcm_iovar_t
*vi
= NULL
;
4077 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
4082 /* Get MUST have return space */
4083 ASSERT(set
|| (arg
&& len
));
4085 /* Set does NOT take qualifiers */
4086 ASSERT(!set
|| (!params
&& !plen
));
4088 /* Look up var locally; if not found pass to host driver */
4089 if ((vi
= bcm_iovar_lookup(dbus_sdio_iovars
, name
)) == NULL
) {
4090 BUS_WAKE(sdio_info
);
4092 /* Turn on clock in case SD command needs backplane */
4093 dbus_sdio_clkctl(sdio_info
, CLK_AVAIL
, FALSE
);
4095 bcmerror
= bcmsdh_iovar_op(sdio_info
->sdh
, name
, params
, plen
, arg
, len
, set
);
4097 /* Check for bus configuration changes of interest */
4099 /* If it was divisor change, read the new one */
4100 if (set
&& strcmp(name
, "sd_divisor") == 0) {
4101 if (bcmsdh_iovar_op(sdio_info
->sdh
, "sd_divisor", NULL
, 0,
4102 &sdio_info
->sd_divisor
, sizeof(int32
), FALSE
) != BCME_OK
) {
4103 sdio_info
->sd_divisor
= -1;
4104 DBUSERR(("%s: fail on %s get\n", __FUNCTION__
, name
));
4106 DBUSINFO(("%s: noted %s update, value now %d\n",
4107 __FUNCTION__
, name
, sdio_info
->sd_divisor
));
4110 /* If it was a mode change, read the new one */
4111 if (set
&& strcmp(name
, "sd_mode") == 0) {
4112 if (bcmsdh_iovar_op(sdio_info
->sdh
, "sd_mode", NULL
, 0,
4113 &sdio_info
->sd_mode
, sizeof(int32
), FALSE
) != BCME_OK
) {
4114 sdio_info
->sd_mode
= -1;
4115 DBUSERR(("%s: fail on %s get\n", __FUNCTION__
, name
));
4117 DBUSINFO(("%s: noted %s update, value now %d\n",
4118 __FUNCTION__
, name
, sdio_info
->sd_mode
));
4121 /* Similar check for blocksize change */
4122 if (set
&& strcmp(name
, "sd_blocksize") == 0) {
4124 if (bcmsdh_iovar_op(sdio_info
->sdh
, "sd_blocksize", &fnum
, sizeof(int32
),
4125 &sdio_info
->blocksize
, sizeof(int32
), FALSE
) != BCME_OK
) {
4126 sdio_info
->blocksize
= 0;
4127 DBUSERR(("%s: fail on %s get\n", __FUNCTION__
, "sd_blocksize"));
4129 DBUSINFO(("%s: noted %s update, value now %d\n",
4130 __FUNCTION__
, "sd_blocksize", sdio_info
->blocksize
));
4133 sdio_info
->roundup
= MIN(max_roundup
, sdio_info
->blocksize
);
4135 if ((sdio_info
->idletime
== IDLE_IMMEDIATE
) && !sdio_info
->dpc_sched
) {
4136 sdio_info
->activity
= FALSE
;
4137 dbus_sdio_clkctl(sdio_info
, CLK_NONE
, TRUE
);
4143 DBUSCTL(("%s: %s %s, len %d plen %d\n", __FUNCTION__
,
4144 name
, (set
? "set" : "get"), len
, plen
));
4146 /* set up 'params' pointer in case this is a set command so that
4147 * the convenience int and bool code can be common to set and get
4149 if (params
== NULL
) {
4154 if (vi
->type
== IOVT_VOID
)
4156 else if (vi
->type
== IOVT_BUFFER
)
4159 /* all other types are integer sized */
4160 val_size
= sizeof(int);
4162 actionid
= set
? IOV_SVAL(vi
->varid
) : IOV_GVAL(vi
->varid
);
4163 bcmerror
= dbus_sdio_doiovar(sdio_info
, vi
, actionid
,
4164 name
, params
, plen
, arg
, len
, val_size
);
4171 dbus_sdio_txctlq_process(void *bus
)
4173 sdio_info_t
*sdio_info
= bus
;
4176 if (sdio_info
->txctl_req
.pending
== TRUE
) {
4177 if (sdio_info
->txctl_req
.is_iovar
== FALSE
) {
4178 ASSERT(sdio_info
->txctl_req
.ctl
.buf
);
4179 ASSERT(sdio_info
->txctl_req
.ctl
.len
);
4181 err
= dbus_sdio_txctl(sdio_info
, sdio_info
->txctl_req
.ctl
.buf
,
4182 sdio_info
->txctl_req
.ctl
.len
);
4184 err
= dbus_iovar_process(sdio_info
,
4185 sdio_info
->txctl_req
.iovar
.name
,
4186 sdio_info
->txctl_req
.iovar
.params
,
4187 sdio_info
->txctl_req
.iovar
.plen
,
4188 sdio_info
->txctl_req
.iovar
.arg
,
4189 sdio_info
->txctl_req
.iovar
.len
,
4190 sdio_info
->txctl_req
.iovar
.set
);
4193 bzero(&sdio_info
->txctl_req
, sizeof(sdio_info
->txctl_req
));
4194 dbus_sdio_ctl_complete(sdio_info
, DBUS_CBCTL_WRITE
, err
);
4201 dbus_sdio_txq_flush(sdio_info_t
*sdio_info
)
4204 struct exec_parms exec_args
;
4208 exec_args
.pdeq
.sdio_info
= sdio_info
;
4209 exec_args
.pdeq
.tx_prec_map
= ALLPRIO
;
4210 exec_args
.pdeq
.prec_out
= &prec_out
;
4212 /* Cancel all pending pkts */
4213 while ((pkt
= dbus_sdos_exec_txlock(sdio_info
,
4214 (exec_cb_t
) dbus_prec_pkt_deq_exec
, &exec_args
)) != NULL
) {
4215 ptag
= (pkttag_t
*) PKTTAG(pkt
);
4218 dbus_sdio_send_irb_complete(sdio_info
, ptag
->txirb
, DBUS_STATUS_CANCELLED
);
4219 dbus_sdcb_pktfree(sdio_info
, pkt
, TRUE
);
4224 dbus_sdio_txq_process(void *bus
)
4226 sdio_info_t
*sdio_info
= bus
;
4228 uint framecnt
= 0; /* Temporary counter of tx/rx frames */
4229 uint txlimit
= dhd_txbound
; /* Tx frames to send before resched */
4231 dbus_sdos_lock(sdio_info
);
4233 sdh
= sdio_info
->sdh
;
4235 if (sdio_info
->pub
->busstate
== DBUS_STATE_DOWN
) {
4236 dbus_sdio_txq_flush(sdio_info
);
4240 /* Send ctl requests first */
4241 dbus_sdio_txctlq_process(sdio_info
);
4243 /* If waiting for HTAVAIL, check status */
4244 if (sdio_info
->clkstate
== CLK_PENDING
) {
4246 uint8 clkctl
, devctl
= 0;
4248 /* Read CSR, if clock on switch to AVAIL, else ignore */
4249 clkctl
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
, &err
);
4251 DBUSERR(("%s: error reading CSR: %d\n", __FUNCTION__
, err
));
4252 sdio_info
->pub
->busstate
= DBUS_STATE_DOWN
;
4255 DBUSINFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", devctl
, clkctl
));
4257 if (SBSDIO_HTAV(clkctl
)) {
4258 devctl
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
, SBSDIO_DEVICE_CTL
, &err
);
4260 DBUSERR(("%s: error reading DEVCTL: %d\n",
4261 __FUNCTION__
, err
));
4262 sdio_info
->pub
->busstate
= DBUS_STATE_DOWN
;
4264 devctl
&= ~SBSDIO_DEVCTL_CA_INT_ONLY
;
4265 bcmsdh_cfg_write(sdh
, SDIO_FUNC_1
, SBSDIO_DEVICE_CTL
, devctl
, &err
);
4267 DBUSERR(("%s: error writing DEVCTL: %d\n",
4268 __FUNCTION__
, err
));
4269 sdio_info
->pub
->busstate
= DBUS_STATE_DOWN
;
4271 sdio_info
->clkstate
= CLK_AVAIL
;
4278 BUS_WAKE(sdio_info
);
4280 /* Make sure backplane clock is on */
4281 dbus_sdio_clkctl(sdio_info
, CLK_AVAIL
, TRUE
);
4282 if (sdio_info
->clkstate
== CLK_PENDING
)
4285 /* Send queued frames (limit 1 if rx may still be pending) */
4286 if ((sdio_info
->clkstate
!= CLK_PENDING
) && !sdio_info
->fcstate
&&
4287 pktq_mlen(&sdio_info
->txq
, ~sdio_info
->flowcontrol
) && txlimit
&& DATAOK(sdio_info
)) {
4288 framecnt
= dbus_sdio_sendfromq(sdio_info
, txlimit
);
4291 /* FIX: Check ctl requests again
4292 * It's possible to have ctl request while dbus_sdio_sendfromq()
4293 * is active. Possibly check for pending ctl requests before sending
4296 dbus_sdio_txctlq_process(sdio_info
);
4299 /* Generate packets if configured */
4300 if (sdio_info
->pktgen_count
&& (++sdio_info
->pktgen_tick
>= sdio_info
->pktgen_freq
)) {
4301 /* Make sure backplane clock is on */
4302 dbus_sdio_clkctl(sdio_info
, CLK_AVAIL
, FALSE
);
4303 sdio_info
->pktgen_tick
= 0;
4304 dbus_sdio_pktgen(sdio_info
);
4309 dbus_sdos_unlock(sdio_info
);
4315 probe_htclk(probe_sdh_info_t
*pinfo
)
4323 bcmsdh_cfg_write(sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
,
4324 (SBSDIO_ALP_AVAIL_REQ
| SBSDIO_HT_AVAIL_REQ
), &err
);
4326 DBUSERR(("%s: HT Avail request error: %d\n", __FUNCTION__
, err
));
4330 clkctl
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
, &err
);
4332 DBUSERR(("%s: HT Avail read error: %d\n", __FUNCTION__
, err
));
4336 if (!SBSDIO_HTAV(clkctl
)) {
4337 SPINWAIT(((clkctl
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
,
4338 SBSDIO_FUNC1_CHIPCLKCSR
, &err
)),
4339 !SBSDIO_HTAV(clkctl
)), PMU_MAX_TRANSITION_DLY
);
4351 /* Need at least ALP */
4352 clkctl
= bcmsdh_cfg_read(g_probe_info
.sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
, &err
);
4353 if (!SBSDIO_ALPAV(clkctl
))
4354 err
= probe_htclk(&g_probe_info
);
4356 dbus_sdio_download_state(&g_probe_info
, TRUE
);
4357 g_probe_info
.dl_addr
= 0;
4364 dbus_sdio_download_state(&g_probe_info
, FALSE
);
4365 g_probe_info
.dl_addr
= 0;
4370 probe_dlwrite(uint8
*buf
, int count
, bool isvars
)
4373 dbus_sdio_downloadvars(&g_probe_info
, buf
, count
);
4375 dbus_sdio_membytes(&g_probe_info
, TRUE
, g_probe_info
.dl_addr
, buf
, count
);
4376 g_probe_info
.dl_addr
+= count
;
4385 * This handles iovars before dbus_attach() and
4386 * before bringing up eth interface
4389 probe_iovar(const char *name
, void *params
, int plen
, void *arg
, int len
, bool set
,
4390 void **val
, int *val_len
)
4392 int actionid
, err
= 0;
4396 const bcm_iovar_t
*vi
= NULL
;
4399 vi
= bcm_iovar_lookup(dbus_sdio_iovars
, (char *) name
);
4402 DBUSERR(("Unsupported probe iovar: %s\n", name
));
4406 bcopy(params
, &int_val
, sizeof(int_val
));
4407 bool_val
= (int_val
!= 0) ? TRUE
: FALSE
;
4409 actionid
= set
? IOV_SVAL(vi
->varid
) : IOV_GVAL(vi
->varid
);
4411 /* Need at least ALP */
4412 clkctl
= bcmsdh_cfg_read(g_probe_info
.sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
, &err
);
4413 if (!SBSDIO_ALPAV(clkctl
))
4414 err
= probe_htclk(&g_probe_info
);
4416 /* Handle pre-attach() requests */
4418 case IOV_SVAL(IOV_SET_DOWNLOAD_STATE
):
4419 err
= dbus_sdio_download_state(&g_probe_info
, bool_val
);
4420 g_probe_info
.dl_addr
= 0;
4422 case IOV_SVAL(IOV_MEMBYTES
): {
4427 address
= (uint32
)int_val
;
4428 g_probe_info
.dl_addr
= address
;
4430 bcopy((char *)params
+ sizeof(int_val
), &int_val
, sizeof(int_val
));
4431 size
= (uint
)int_val
; /* in 2048 (2K) chunks */
4433 image
= (char *)params
+ sizeof(int_val
) + sizeof(int_val
);
4434 dbus_sdio_membytes(&g_probe_info
, TRUE
, address
, image
, size
);
4436 case IOV_SVAL(IOV_VARS
):
4437 /* FIX: Need vars len in iovar string */
4439 case IOV_GVAL(IOV_MEMSIZE
):
4440 *val
= (void *)&g_probe_info
.ramsize
;
4441 *val_len
= sizeof(uint32
);
4444 DBUSERR(("Pre-attach probe actionid (%d) unsupported\n", actionid
));
4453 dbus_sdio_sendfromq(sdio_info_t
*sdio_info
, uint maxframes
)
4456 int ret
= 0, prec_out
;
4460 struct exec_parms exec_args
;
4462 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
4464 tx_prec_map
= ~sdio_info
->flowcontrol
;
4466 /* Send frames until the limit or some other event */
4467 for (cnt
= 0; (cnt
< maxframes
) && DATAOK(sdio_info
); cnt
++) {
4468 exec_args
.pdeq
.sdio_info
= sdio_info
;
4469 exec_args
.pdeq
.tx_prec_map
= tx_prec_map
;
4470 exec_args
.pdeq
.prec_out
= &prec_out
;
4471 pkt
= dbus_sdos_exec_txlock(sdio_info
,
4472 (exec_cb_t
) dbus_prec_pkt_deq_exec
, &exec_args
);
4476 datalen
= PKTLEN(sdio_info
->pub
->osh
, pkt
) - SDPCM_HDRLEN
;
4479 ret
= dbus_sdio_txpkt(sdio_info
, pkt
, SDPCM_DATA_CHANNEL
);
4481 ret
= dbus_sdio_txpkt(sdio_info
, pkt
,
4482 (sdio_info
->ext_loop
? SDPCM_TEST_CHANNEL
: SDPCM_DATA_CHANNEL
));
4485 sdio_info
->pub
->stats
.tx_errors
++;
4486 if (sdio_info
->pub
->busstate
== DBUS_STATE_DOWN
)
4495 dbus_sdio_txctl(sdio_info_t
*sdio_info
, uchar
*msg
, uint msglen
)
4501 bcmsdh_info_t
*sdh
= sdio_info
->sdh
;
4506 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
4508 if (sdio_info
->dongle_reset
)
4511 /* Back the pointer to make a room for bus header */
4512 frame
= msg
- SDPCM_HDRLEN
;
4513 len
= (msglen
+= SDPCM_HDRLEN
);
4515 /* Add alignment padding (optional for ctl frames) */
4517 if ((doff
= ((uintptr
)frame
% SDALIGN
))) {
4521 bzero(frame
, doff
+ SDPCM_HDRLEN
);
4523 ASSERT(doff
< SDALIGN
);
4525 doff
+= SDPCM_HDRLEN
;
4527 /* Round send length to next SDIO block */
4528 if (sdio_info
->roundup
&& sdio_info
->blocksize
&& (len
> sdio_info
->blocksize
)) {
4529 pad
= sdio_info
->blocksize
- (len
% sdio_info
->blocksize
);
4530 if ((pad
<= sdio_info
->roundup
) && (pad
< sdio_info
->blocksize
))
4534 /* Satisfy length-alignment requirements */
4535 if (forcealign
&& (len
& (ALIGNMENT
- 1)))
4536 len
= ROUNDUP(len
, ALIGNMENT
);
4538 ASSERT(ISALIGNED(frame
, 2));
4540 /* Need to lock here to protect txseq and SDIO tx calls */
4541 BUS_WAKE(sdio_info
);
4543 /* Make sure backplane clock is on */
4544 dbus_sdio_clkctl(sdio_info
, CLK_AVAIL
, FALSE
);
4546 /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
4547 *(uint16
*)frame
= htol16((uint16
)msglen
);
4548 *(((uint16
*)frame
) + 1) = htol16(~msglen
);
4550 /* Software tag: channel, sequence number, data offset */
4551 swheader
= ((SDPCM_CONTROL_CHANNEL
<< SDPCM_CHANNEL_SHIFT
) & SDPCM_CHANNEL_MASK
)
4552 | sdio_info
->tx_seq
| ((doff
<< SDPCM_DOFFSET_SHIFT
) & SDPCM_DOFFSET_MASK
);
4553 htol32_ua_store(swheader
, frame
+ SDPCM_FRAMETAG_LEN
);
4554 htol32_ua_store(0, frame
+ SDPCM_FRAMETAG_LEN
+ sizeof(swheader
));
4555 sdio_info
->tx_seq
= (sdio_info
->tx_seq
+ 1) % SDPCM_SEQUENCE_WRAP
;
4558 ret
= bcmsdh_send_buf(sdh
, SI_ENUM_BASE
, SDIO_FUNC_2
, F2SYNC
,
4559 frame
, len
, NULL
, NULL
, NULL
);
4560 ASSERT(ret
!= BCME_PENDING
);
4563 /* On failure, abort the command and terminate the frame */
4564 DBUSINFO(("%s: sdio error %d, abort command and terminate frame.\n",
4565 __FUNCTION__
, ret
));
4566 sdio_info
->tx_sderrs
++;
4568 ret
= bcmsdh_abort(sdh
, SDIO_FUNC_2
);
4569 if (ret
== BCME_NODEVICE
) {
4570 dbus_sdio_state_change(sdio_info
, DBUS_STATE_DISCONNECT
);
4575 DBUSERR(("%s: Check Overflow or F2-fifo-not-ready counters."
4576 " gSPI transmit error on control channel.\n", __FUNCTION__
));
4578 bcmsdh_cfg_write(sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_FRAMECTRL
,
4580 sdio_info
->f1regdata
++;
4582 for (i
= 0; i
< 3; i
++) {
4584 hi
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
,
4585 SBSDIO_FUNC1_WFRAMEBCHI
, NULL
);
4586 lo
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
,
4587 SBSDIO_FUNC1_WFRAMEBCLO
, NULL
);
4588 sdio_info
->f1regdata
+= 2;
4589 if ((hi
== 0) && (lo
== 0))
4593 } while ((ret
< 0) && retries
++ < TXRETRIES
);
4595 if ((sdio_info
->idletime
== IDLE_IMMEDIATE
) && !sdio_info
->dpc_sched
) {
4596 sdio_info
->activity
= FALSE
;
4597 dbus_sdio_clkctl(sdio_info
, CLK_NONE
, TRUE
);
4601 sdio_info
->tx_ctlerrs
++;
4603 sdio_info
->tx_ctlpkts
++;
4605 return ret
? DBUS_ERR
: DBUS_OK
;
4609 dbus_sdio_rxctl(sdio_info_t
*sdio_info
, uchar
*msg
, uint msglen
)
4613 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
4615 if (sdio_info
->dongle_reset
)
4618 /* FIX: Since rxctl() is async, need to fix case where ctl pkt is recevied
4619 * before this function is called. We need to buffer incoming ctl pkts.
4621 rxlen
= sdio_info
->rxlen
;
4622 bcopy(sdio_info
->rxctl
, msg
, MIN(msglen
, rxlen
));
4623 sdio_info
->rxlen
= 0;
4632 dbus_sdh_probe(uint16 venid
, uint16 devid
, uint16 bus_no
, uint16 slot
,
4633 uint16 func
, uint bustype
, void *regsva
, osl_t
* osh
,
4640 #endif /* !BCMSPI */
4642 DBUSTRACE(("%s\n", __FUNCTION__
));
4645 /* We make assumptions about address window mappings */
4646 ASSERT((uintptr
)regsva
== SI_ENUM_BASE
);
4648 /* BCMSDH passes venid and devid based on CIS parsing -- but low-power start
4649 * means early parse could fail, so here we should get either an ID
4650 * we recognize OR (-1) indicating we must request power first.
4652 /* Check the Vendor ID */
4655 case VENDOR_BROADCOM
:
4658 DBUSERR(("%s: unknown vendor: 0x%04x\n",
4659 __FUNCTION__
, venid
));
4665 devid
= bcmsdh_reg_read(sdh
, SI_ENUM_BASE
, 4) & CID_ID_MASK
;
4667 /* Check the Device ID and make sure it's one that we support */
4669 case BCM4325_CHIP_ID
:
4670 case BCM4325_D11DUAL_ID
: /* 4325 802.11a/g id */
4671 case BCM4325_D11G_ID
: /* 4325 802.11g 2.4Ghz band id */
4672 case BCM4325_D11A_ID
: /* 4325 802.11a 5Ghz band id */
4673 DBUSERR(("%s: found 4325 Dongle\n", __FUNCTION__
));
4674 g_probe_info
.chinfo
= &chipinfo_4325_15
;
4676 case BCM4329_D11N_ID
: /* 4329 802.11n dualband device */
4677 case BCM4329_D11N2G_ID
: /* 4329 802.11n 2.4G device */
4678 case BCM4329_D11N5G_ID
: /* 4329 802.11n 5G device */
4679 case BCM4321_D11N2G_ID
:
4680 DBUSERR(("%s: found 4329 Dongle\n", __FUNCTION__
));
4681 g_probe_info
.chinfo
= &chipinfo_4329
;
4683 case BCM4315_CHIP_ID
:
4684 case BCM4315_D11G_ID
: /* 4315 802.11g id */
4685 case BCM4315_D11A_ID
: /* 4315 802.11a id */
4686 DBUSINFO(("%s: found 4315 Dongle\n", __FUNCTION__
));
4687 g_probe_info
.chinfo
= &chipinfo_4325_15
;
4689 case BCM4336_D11N_ID
:
4690 DBUSINFO(("%s: found 4336 Dongle\n", __FUNCTION__
));
4691 g_probe_info
.chinfo
= &chipinfo_4336
;
4694 case BCM4330_D11N_ID
:
4695 DBUSINFO(("%s: found 4330 Dongle\n", __FUNCTION__
));
4696 g_probe_info
.chinfo
= &chipinfo_4330
;
4699 case BCM43237_D11N_ID
:
4700 DBUSINFO(("%s: found 43237 Dongle\n", __FUNCTION__
));
4701 g_probe_info
.chinfo
= &chipinfo_43237
;
4704 case BCM4314_CHIP_ID
:
4705 DBUSINFO(("%s: found 4314 Dongle\n", __FUNCTION__
));
4706 g_probe_info
.chinfo
= &chipinfo_4314
;
4709 case BCM4334_CHIP_ID
:
4710 DBUSINFO(("%s: found 4334 Dongle\n", __FUNCTION__
));
4711 g_probe_info
.chinfo
= &chipinfo_4334
;
4715 DBUSINFO(("%s: allow device id 0, will check chip internals\n",
4717 /* FIX: Need to query chip */
4718 g_probe_info
.chinfo
= &chipinfo_4325_15
;
4722 DBUSERR(("%s: skipping 0x%04x/0x%04x, not a dongle\n",
4723 __FUNCTION__
, venid
, devid
));
4729 /* FIX: This osh is needed for si_attach() and R_REG()
4730 * If we simplify and do away with si_attach() at this stage,
4731 * then remove this as well.
4733 /* FIX: Linux needs this, but not NDIS
4734 * Remove this LINUX define; Don't put
4735 * OS defines in this file.
4736 * Have DBUS maintain it's own osh and remove it from
4737 * dbus_attach() as an argument.
4739 osh
= osl_attach(NULL
, SD_BUSTYPE
, TRUE
);
4740 g_probe_info
.free_probe_osh
= TRUE
;
4744 g_probe_info
.venid
= venid
;
4745 g_probe_info
.devid
= devid
;
4746 g_probe_info
.bus_no
= bus_no
;
4747 g_probe_info
.slot
= slot
;
4748 g_probe_info
.func
= func
;
4749 g_probe_info
.bustype
= bustype
;
4750 g_probe_info
.regsva
= regsva
;
4751 g_probe_info
.osh
= osh
;
4752 g_probe_info
.sdh
= sdh
;
4753 g_probe_info
.firmware_file
= NULL
;
4754 g_probe_info
.nvram_file
= NULL
;
4756 ASSERT(g_probe_info
.chinfo
);
4757 g_probe_info
.ramsize
= g_probe_info
.orig_ramsize
= g_probe_info
.chinfo
->socram_size
;
4759 #ifndef BCMSPI /* wake-wlan in gSPI will bring up the htavail/alpavail clocks. */
4760 /* Force PLL off until si_attach() programs PLL control regs */
4764 bcmsdh_cfg_write(sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
, DHD_INIT_CLKCTL1
, &err
);
4766 clkctl
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
, &err
);
4768 if (err
|| ((clkctl
& ~SBSDIO_AVBITS
) != DHD_INIT_CLKCTL1
)) {
4769 DBUSERR(("dbus_sdio_probe: ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n",
4770 err
, DHD_INIT_CLKCTL1
, clkctl
));
4773 #endif /* !BCMSPI */
4775 /* The si_attach() will provide an SI handle, scan the
4776 * backplane, and initialize the PLL.
4778 if (!(g_probe_info
.sih
= si_attach((uint
)devid
, osh
, regsva
, SD_BUSTYPE
, sdh
,
4779 &g_probe_info
.vars
, &g_probe_info
.varsz
))) {
4780 DBUSERR(("%s: si_attach failed!\n", __FUNCTION__
));
4784 ASSERT(g_probe_info
.orig_ramsize
== si_socram_size(g_probe_info
.sih
));
4786 /* FIX: this is needed on some boards for download. If not, it can
4787 * cause data errors if drive strength is not correct.
4788 * Default is 10mA, but 6mA is optimal.
4790 si_sdiod_drive_strength_init(g_probe_info
.sih
, osh
, dhd_sdiod_drive_strength
);
4793 /* prepare dongle for download */
4794 if (!(dbus_sdio_probe_init(&g_probe_info
))) {
4795 DBUSERR(("%s: dbus_sdio_probe_init failed\n", __FUNCTION__
));
4799 /* Set up the interrupt mask */
4800 W_REG(osh
, &g_probe_info
.chinfo
->sdregs
->hostintmask
, HOSTINTMASK
);
4802 #ifdef BCM_DNGL_EMBEDIMAGE
4803 prarg
= dbus_sdio_probe_cb(&g_probe_info
, "", SD_BUSTYPE
, SDPCM_RESERVE
);
4806 return &g_probe_info
;
4810 dbus_sdio_alpclk(sdh
);
4812 if (delay_eth
== 0) {
4813 dbus_sdio_probe_cb(&g_probe_info
, "", SD_BUSTYPE
, SDPCM_RESERVE
);
4815 DBUSERR(("Delay eth1 bringup\n"));
4817 * Enable interrupt for DEVREADY when a valid image is downloaded
4819 bcmsdh_intr_disable(sdh
);
4821 if ((err
= bcmsdh_intr_reg(sdh
, dbus_sdh_devrdy_isr
, &g_probe_info
)) != 0) {
4822 DBUSERR(("%s: FAILED: bcmsdh_intr_reg returned %d\n",
4823 __FUNCTION__
, err
));
4826 bcmsdh_intr_enable(sdh
);
4829 return &g_probe_info
;
4830 #endif /* BCM_DNGL_EMBEDIMAGE */
4834 dbus_sdh_disconnect(void *ptr
)
4836 probe_sdh_info_t
*pinfo
= (probe_sdh_info_t
*)ptr
;
4838 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
4840 if (pinfo
== NULL
) {
4841 DBUSERR(("%s: pinfo is NULL\n", __FUNCTION__
));
4844 dbus_sdio_disconnect_cb(NULL
);
4846 /* After this point, sdio_info is free'd;
4847 * Clean up stuff from dbus_sdh_probe()
4849 dbus_sdio_probe_deinit(pinfo
);
4852 si_detach(pinfo
->sih
);
4853 if (pinfo
->vars
&& pinfo
->varsz
) {
4854 MFREE(pinfo
->osh
, pinfo
->vars
, pinfo
->varsz
);
4858 if (pinfo
->osh
&& (pinfo
->free_probe_osh
== TRUE
)) {
4859 if (MALLOCED(pinfo
->osh
)) {
4860 DBUSERR(("%s: PROBE MEMORY LEAK %d bytes\n", __FUNCTION__
,
4861 MALLOCED(pinfo
->osh
)));
4863 osl_detach(pinfo
->osh
);
4868 dbus_sdio_probe_init(probe_sdh_info_t
*pinfo
)
4870 bcmsdh_info_t
*sdh
; /* Handle for BCMSDH calls */
4873 DBUSTRACE(("%s\n", __FUNCTION__
));
4882 pinfo
->alp_only
= TRUE
;
4883 pinfo
->devready
= FALSE
;
4886 /* Return the window to backplane enumeration space for core access */
4887 if (bcmsdhsdio_set_sbaddr_window(sdh
, SI_ENUM_BASE
, TRUE
)) {
4888 DBUSERR(("%s: FAILED to return to SI_ENUM_BASE\n", __FUNCTION__
));
4892 if (CHIPTYPE(pinfo
->sih
->socitype
) != SOCI_AI
) {
4893 printf("F1 signature read @0x18000ffc=0x%4x\n",
4894 bcmsdh_reg_read(sdh
, SI_ENUM_BASE
+ 0xffc, 4));
4897 printf("F1 signature read @0x18000000=0x%4x\n",
4898 bcmsdh_reg_read(sdh
, SI_ENUM_BASE
, 4));
4902 /* Set core control so an SDIO reset does a backplane reset */
4903 OR_REG(osh
, &pinfo
->chinfo
->sdregs
->corecontrol
, CC_BPRESEN
);
4914 dbus_sdio_probe_deinit(probe_sdh_info_t
*pinfo
)
4919 /* FIX: Not consolidating this with dbus_sdh_disconnect
4920 * because it's used during DEVRESET. Need to resolve.
4923 bcmsdh_cfg_write(pinfo
->sdh
, SDIO_FUNC_1
,
4924 SBSDIO_FUNC1_CHIPCLKCSR
, SBSDIO_HT_AVAIL_REQ
, &err
);
4925 si_watchdog(pinfo
->sih
, 4);
4926 bcmsdh_cfg_write(pinfo
->sdh
, SDIO_FUNC_1
,
4927 SBSDIO_FUNC1_CHIPCLKCSR
, 0, &err
);
4933 dbus_sdio_attach_init(sdio_info_t
*sdio_info
, void *sdh
, char *firmware_path
,
4939 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
4942 dbus_sdio_pktgen_init(sdio_info
);
4946 /* Disable F2 to clear any intermediate frame state on the dongle */
4947 bcmsdh_cfg_write(sdh
, SDIO_FUNC_0
, SDIOD_CCCR_IOEN
, SDIO_FUNC_ENABLE_1
, NULL
);
4948 #endif /* !BCMSPI */
4951 /* Done with backplane-dependent accesses, can drop clock... */
4952 bcmsdh_cfg_write(sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
, 0, NULL
);
4953 sdio_info
->clkstate
= CLK_SDONLY
;
4954 #endif /* !BCMSPI */
4956 /* Query the SD clock speed */
4957 if (bcmsdh_iovar_op(sdh
, "sd_divisor", NULL
, 0,
4958 &sdio_info
->sd_divisor
, sizeof(int32
), FALSE
) != BCME_OK
) {
4959 DBUSERR(("%s: fail on %s get\n", __FUNCTION__
, "sd_divisor"));
4960 sdio_info
->sd_divisor
= -1;
4962 DBUSINFO(("%s: Initial value for %s is %d\n",
4963 __FUNCTION__
, "sd_divisor", sdio_info
->sd_divisor
));
4966 /* Query the SD bus mode */
4967 if (bcmsdh_iovar_op(sdh
, "sd_mode", NULL
, 0,
4968 &sdio_info
->sd_mode
, sizeof(int32
), FALSE
) != BCME_OK
) {
4969 DBUSERR(("%s: fail on %s get\n", __FUNCTION__
, "sd_mode"));
4970 sdio_info
->sd_mode
= -1;
4972 DBUSINFO(("%s: Initial value for %s is %d\n",
4973 __FUNCTION__
, "sd_mode", sdio_info
->sd_mode
));
4976 /* Query the F2 block size, set roundup accordingly */
4978 if (bcmsdh_iovar_op(sdh
, "sd_blocksize", &fnum
, sizeof(int32
),
4979 &sdio_info
->blocksize
, sizeof(int32
), FALSE
) != BCME_OK
) {
4980 sdio_info
->blocksize
= 0;
4981 DBUSERR(("%s: fail on %s get\n", __FUNCTION__
, "sd_blocksize"));
4983 DBUSINFO(("%s: Initial value for %s is %d\n",
4984 __FUNCTION__
, "sd_blocksize", sdio_info
->blocksize
));
4986 sdio_info
->roundup
= MIN(max_roundup
, sdio_info
->blocksize
);
4988 /* Query if bus module supports packet chaining, default to use if supported */
4989 if (bcmsdh_iovar_op(sdh
, "sd_rxchain", NULL
, 0,
4990 &sdio_info
->sd_rxchain
, sizeof(int32
), FALSE
) != BCME_OK
) {
4991 sdio_info
->sd_rxchain
= FALSE
;
4993 DBUSINFO(("%s: bus module (through bcmsdh API) %s chaining\n",
4994 __FUNCTION__
, (sdio_info
->sd_rxchain
? "supports" : "does not support")));
4996 sdio_info
->use_rxchain
= (bool)sdio_info
->sd_rxchain
;
4998 /* Register interrupt callback, but mask it (not operational yet). */
4999 DBUSINTR(("%s: disable SDIO interrupts (not interested yet)\n", __FUNCTION__
));
5000 bcmsdh_intr_disable(sdh
);
5001 if ((ret
= bcmsdh_intr_reg(sdh
, dbus_sdh_isr
, sdio_info
)) != 0) {
5002 DBUSERR(("%s: FAILED: bcmsdh_intr_reg returned %d\n",
5003 __FUNCTION__
, ret
));
5006 DBUSINTR(("%s: registered SDIO interrupt function ok\n", __FUNCTION__
));
5015 dbus_sdio_release(sdio_info_t
*sdio_info
, osl_t
*osh
)
5017 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
5021 dbus_sdio_release_dongle(sdio_info
, osh
);
5026 dbus_sdio_release_dongle(sdio_info_t
*sdio_info
, osl_t
*osh
)
5028 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
5030 if (sdio_info
->dongle_reset
)
5033 if (sdio_info
->rxbuf
) {
5034 MFREE(osh
, sdio_info
->rxbuf
, sdio_info
->rxblen
);
5035 sdio_info
->rxctl
= sdio_info
->rxbuf
= NULL
;
5036 sdio_info
->rxlen
= 0;
5039 if (sdio_info
->databuf
) {
5040 MFREE(osh
, sdio_info
->databuf
, MAX_DATA_BUF
);
5041 sdio_info
->databuf
= NULL
;
5045 #ifdef BCM_DNGL_EMBEDIMAGE
5047 dhd_bus_download_image_array(probe_sdh_info_t
*pinfo
, char * nvram_path
, uint8
*fw
, int len
)
5052 /* Download image */
5053 while ((offset
+ MEMBLOCK
) < len
) {
5054 bcmerror
= dbus_sdio_membytes(pinfo
, TRUE
,
5055 offset
, fw
+ offset
, MEMBLOCK
);
5057 DBUSERR(("%s: error %d on writing %d membytes at 0x%08x\n",
5058 __FUNCTION__
, bcmerror
, MEMBLOCK
, offset
));
5066 bcmerror
= dbus_sdio_membytes(pinfo
, TRUE
, offset
,
5067 fw
+ offset
, len
- offset
);
5069 DBUSERR(("%s: error %d on writing %d membytes at 0x%08x\n",
5070 __FUNCTION__
, bcmerror
, len
- offset
, offset
));
5075 /* Download SROM if provided externally through file */
5076 dhd_bus_download_nvram_file(pinfo
, nvram_path
);
5080 #endif /* BCM_DNGL_EMBEDIMAGE */
5084 * ProcessVars:Takes a buffer of "<var>=<value>\n" lines read from a file and ending in a NUL.
5085 * Removes carriage returns, empty lines, comment lines, and converts newlines to NULs.
5086 * Shortens buffer as needed and pads with NULs. End of buffer is marked by two NULs.
5089 #if defined(BCM_DNGL_EMBEDIMAGE)
5091 dhd_bus_download_nvram_file(probe_sdh_info_t
*pinfo
, char * nvram_path
)
5095 void * image
= NULL
;
5096 uint8
* memblock
= NULL
;
5102 /* FIX: Need to implement dhd_os_open_image() */
5103 /* image = dhd_os_open_image(nvram_path); */
5107 memblock
= MALLOC(pinfo
->osh
, MEMBLOCK
);
5108 if (memblock
== NULL
) {
5109 DBUSERR(("%s: Failed to allocate memory %d bytes\n",
5110 __FUNCTION__
, MEMBLOCK
));
5114 /* Download variables */
5115 /* FIX: Need to implement dhd_os_get_image_block() */
5116 /* len = dhd_os_get_image_block(memblock, MEMBLOCK, image); */
5118 if (len
!= MEMBLOCK
&& len
> 0) {
5119 bufp
= (char *)memblock
;
5120 len
= process_nvram_vars(bufp
, len
);
5122 len
+= (4 - len
% 4);
5126 bcmerror
= dbus_sdio_downloadvars(pinfo
, memblock
, len
+ 1);
5128 DBUSERR(("%s: error downloading vars: %d\n",
5129 __FUNCTION__
, bcmerror
));
5132 DBUSERR(("%s: error reading nvram file: %d\n",
5133 __FUNCTION__
, len
));
5134 bcmerror
= BCME_SDIO_ERROR
;
5139 MFREE(pinfo
->osh
, memblock
, MEMBLOCK
);
5141 /* FIX: Need to implement dhd_os_close_image() */
5145 #endif /* BCM_DNGL_EMBEDIMAGE */
5148 dbus_sdos_lock(sdio_info_t
*sdio_info
)
5150 if (sdio_info
== NULL
)
5153 if (sdio_info
->drvintf
&& sdio_info
->drvintf
->lock
)
5154 sdio_info
->drvintf
->lock(sdio_info
->sdos_info
);
5158 ASSERT(sdio_info
->sdlocked
== FALSE
);
5159 sdio_info
->sdlocked
= TRUE
;
5163 dbus_sdos_unlock(sdio_info_t
*sdio_info
)
5165 ASSERT(sdio_info
->sdlocked
== TRUE
);
5166 sdio_info
->sdlocked
= FALSE
;
5168 if (sdio_info
->drvintf
&& sdio_info
->drvintf
->unlock
)
5169 sdio_info
->drvintf
->unlock(sdio_info
->sdos_info
);
5175 dbus_sdos_exec_txlock(sdio_info_t
*sdio_info
, exec_cb_t cb
, struct exec_parms
*args
)
5178 if (sdio_info
->drvintf
&& sdio_info
->drvintf
->exec_txlock
)
5179 return sdio_info
->drvintf
->exec_txlock(sdio_info
->sdos_info
, cb
, args
);
5185 dbus_sdcb_pktget(sdio_info_t
*sdio_info
, uint len
, bool send
)
5189 DBUSTRACE(("%s\n", __FUNCTION__
));
5191 if (sdio_info
== NULL
)
5194 if (sdio_info
->cbs
&& sdio_info
->cbs
->pktget
)
5195 p
= sdio_info
->cbs
->pktget(sdio_info
->cbarg
, len
, send
);
5201 dbus_sdcb_pktfree(sdio_info_t
*sdio_info
, void *p
, bool send
)
5203 DBUSTRACE(("%s\n", __FUNCTION__
));
5205 if (sdio_info
== NULL
)
5208 if (sdio_info
->cbs
&& sdio_info
->cbs
->pktfree
)
5209 sdio_info
->cbs
->pktfree(sdio_info
->cbarg
, p
, send
);
5213 dbus_sdcb_getirb(sdio_info_t
*sdio_info
, bool send
)
5215 DBUSTRACE(("%s\n", __FUNCTION__
));
5217 if (sdio_info
== NULL
)
5220 if (sdio_info
->cbs
&& sdio_info
->cbs
->getirb
)
5221 return sdio_info
->cbs
->getirb(sdio_info
->cbarg
, send
);
5227 * Interface functions
5230 dbus_sdif_send_irb(void *bus
, dbus_irb_tx_t
*txirb
)
5232 sdio_info_t
*sdio_info
= BUS_INFO(bus
, sdio_info_t
);
5235 if (sdio_info
== NULL
)
5238 err
= dbus_sdio_txbuf_submit(sdio_info
, txirb
);
5239 if (err
!= DBUS_OK
) {
5240 err
= DBUS_ERR_TXFAIL
;
5247 dbus_sdif_send_ctl(void *bus
, uint8
*buf
, int len
)
5249 sdio_info_t
*sdio_info
= BUS_INFO(bus
, sdio_info_t
);
5252 if (sdio_info
== NULL
)
5255 if (sdio_info
->txctl_req
.pending
== TRUE
) {
5256 DBUSERR(("%s: ctl is pending!\n", __FUNCTION__
));
5257 return DBUS_ERR_PENDING
;
5260 sdio_info
->txctl_req
.ctl
.buf
= buf
;
5261 sdio_info
->txctl_req
.ctl
.len
= len
;
5262 sdio_info
->txctl_req
.is_iovar
= FALSE
;
5263 sdio_info
->txctl_req
.pending
= TRUE
;
5264 dbus_sdio_txq_sched(sdio_info
->sdos_info
);
5269 dbus_sdif_recv_ctl(void *bus
, uint8
*buf
, int len
)
5271 sdio_info_t
*sdio_info
= BUS_INFO(bus
, sdio_info_t
);
5273 if (sdio_info
== NULL
)
5276 if (sdio_info
->rxctl_req
.pending
== TRUE
) {
5277 DBUSERR(("%s: ctl is pending!\n", __FUNCTION__
));
5278 return DBUS_ERR_PENDING
;
5281 /* Do have a rxctl pkt available? */
5282 if (sdio_info
->rxlen
> 0) {
5283 dbus_sdio_rxctl(sdio_info
, buf
, len
);
5284 dbus_sdio_ctl_complete(sdio_info
, DBUS_CBCTL_READ
, DBUS_OK
);
5286 sdio_info
->rxctl_req
.ctl
.buf
= buf
;
5287 sdio_info
->rxctl_req
.ctl
.len
= len
;
5288 sdio_info
->rxctl_req
.pending
= TRUE
;
5294 dbus_sdif_up(void *bus
)
5296 sdio_info_t
*sdio_info
= BUS_INFO(bus
, sdio_info_t
);
5299 if (sdio_info
== NULL
)
5302 if (sdio_info
->drvintf
&& sdio_info
->drvintf
->up
) {
5303 err
= sdio_info
->drvintf
->up(sdio_info
->sdos_info
);
5306 dbus_sdos_lock(sdio_info
);
5307 err
= dbus_sdio_init(sdio_info
);
5310 dbus_sdos_unlock(sdio_info
);
5316 dbus_sdif_iovar_op(void *bus
, const char *name
,
5317 void *params
, int plen
, void *arg
, int len
, bool set
)
5319 sdio_info_t
*sdio_info
= BUS_INFO(bus
, sdio_info_t
);
5322 if (sdio_info
== NULL
)
5325 err
= dbus_iovar_process(sdio_info
, name
, params
, plen
, arg
, len
, set
);
5330 dbus_sdif_device_exists(void *bus
)
5336 dbus_sdif_dlneeded(void *bus
)
5338 sdio_info_t
*sdio_info
= BUS_INFO(bus
, sdio_info_t
);
5340 if (sdio_info
== NULL
)
5343 #ifdef BCM_DNGL_EMBEDIMAGE
5344 return (g_probe_info
.devready
== FALSE
);
5351 dbus_sdif_dlstart(void *bus
, uint8
*fw
, int len
)
5353 sdio_info_t
*sdio_info
= BUS_INFO(bus
, sdio_info_t
);
5356 if (sdio_info
== NULL
)
5359 dbus_sdio_alpclk(g_probe_info
.sdh
);
5360 sdio_info
->clkstate
= CLK_AVAIL
;
5362 /* Put ARM in reset for download */
5363 err
= dbus_sdio_download_state(&g_probe_info
, TRUE
);
5365 DBUSERR(("%s: error placing ARM core in reset\n", __FUNCTION__
));
5370 /* FIX: Which embedded image has priority?
5372 #ifdef BCM_DNGL_EMBEDIMAGE
5373 if (dhd_bus_download_image_array(&g_probe_info
, nvram_path
, fw
, len
)) {
5374 DBUSERR(("%s: dongle image download failed\n", __FUNCTION__
));
5378 #endif /* BCM_DNGL_EMBEDIMAGE */
5380 /* FIX: Skip this for now
5381 * If above succeeds, do we still download this one?
5385 g_probe_info
.devready
= TRUE
;
5386 sdio_info
->pub
->busstate
= DBUS_STATE_DL_DONE
;
5392 dbus_sdif_dlrun(void *bus
)
5394 sdio_info_t
*sdio_info
;
5397 sdio_info
= BUS_INFO(bus
, sdio_info_t
);
5399 /* Take ARM out of reset */
5400 err
= dbus_sdio_download_state(&g_probe_info
, FALSE
);
5402 DBUSERR(("%s: error getting out of ARM reset\n", __FUNCTION__
));
5411 dbus_sdif_stop(void *bus
)
5413 sdio_info_t
*sdio_info
= BUS_INFO(bus
, sdio_info_t
);
5416 if (sdio_info
->drvintf
&& sdio_info
->drvintf
->stop
)
5417 err
= sdio_info
->drvintf
->stop(sdio_info
->sdos_info
);
5419 dbus_bus_stop(sdio_info
);
5424 dbus_sdif_down(void *bus
)
5426 sdio_info_t
*sdio_info
= BUS_INFO(bus
, sdio_info_t
);
5429 if (sdio_info
->drvintf
&& sdio_info
->drvintf
->down
)
5430 err
= sdio_info
->drvintf
->down(sdio_info
->sdos_info
);
5432 dbus_bus_stop(sdio_info
);
5437 dbus_sdif_get_attrib(void *bus
, dbus_attrib_t
*attrib
)
5439 sdio_info_t
*sdio_info
= BUS_INFO(bus
, sdio_info_t
);
5441 if ((sdio_info
== NULL
) || (attrib
== NULL
))
5444 attrib
->bustype
= DBUS_SDIO
;
5445 attrib
->vid
= g_probe_info
.venid
;
5447 attrib
->devid
= g_probe_info
.devid
;
5455 dbus_sdos_sched_dpc(sdio_info_t
*sdio_info
)
5457 if (sdio_info
->pub
->busstate
== DBUS_STATE_DOWN
) {
5458 DBUSERR(("Bus down. Do not sched dpc\n"));
5462 if (sdio_info
&& sdio_info
->drvintf
&& sdio_info
->drvintf
->sched_dpc
)
5463 return sdio_info
->drvintf
->sched_dpc(sdio_info
->sdos_info
);
5468 #ifndef BCM_DNGL_EMBEDIMAGE
5470 dbus_sdos_sched_probe_cb()
5472 if (g_dbusintf
&& g_dbusintf
->sched_probe_cb
)
5473 return g_dbusintf
->sched_probe_cb(NULL
);
5480 /* This callback is overloaded to also handle pre-attach() requests
5481 * such as downloading an image to the dongle.
5482 * Before attach(), we're limited to what can be done since
5483 * sdio_info handle is not available yet:
5484 * - Reading/writing registers
5485 * - Querying cores using si handle
5488 dbus_sdio_probe_cb(void *handle
, const char *desc
, uint32 bustype
, uint32 hdrlen
)
5490 DBUSTRACE(("%s\n", __FUNCTION__
));
5492 if (handle
== &g_probe_info
) {
5494 if (g_dbusintf
!= NULL
) {
5496 /* First, initialize all lower-level functions as default
5497 * so that dbus.c simply calls directly to dbus_sdio_os.c.
5499 bcopy(g_dbusintf
, &dbus_sdio_intf
, sizeof(dbus_intf_t
));
5501 /* Second, selectively override functions we need.
5503 dbus_sdio_intf
.attach
= dbus_sdif_attach
;
5504 dbus_sdio_intf
.detach
= dbus_sdif_detach
;
5505 dbus_sdio_intf
.send_irb
= dbus_sdif_send_irb
;
5506 /* SDIO does not need pre-submitted IRBs like USB
5507 * so set recv_irb() to NULL so dbus.c would not call
5510 dbus_sdio_intf
.recv_irb
= NULL
;
5511 dbus_sdio_intf
.send_ctl
= dbus_sdif_send_ctl
;
5512 dbus_sdio_intf
.recv_ctl
= dbus_sdif_recv_ctl
;
5513 dbus_sdio_intf
.up
= dbus_sdif_up
;
5514 dbus_sdio_intf
.iovar_op
= dbus_sdif_iovar_op
;
5515 dbus_sdio_intf
.device_exists
= dbus_sdif_device_exists
;
5516 dbus_sdio_intf
.dlneeded
= dbus_sdif_dlneeded
;
5517 dbus_sdio_intf
.dlstart
= dbus_sdif_dlstart
;
5518 dbus_sdio_intf
.dlrun
= dbus_sdif_dlrun
;
5519 dbus_sdio_intf
.stop
= dbus_sdif_stop
;
5520 dbus_sdio_intf
.down
= dbus_sdif_down
;
5521 dbus_sdio_intf
.get_attrib
= dbus_sdif_get_attrib
;
5524 /* Assume a valid image has been downloaded when
5525 * the handle matches ours so propagate probe callback to upper
5529 disc_arg
= probe_cb(probe_arg
, "DBUS SDIO", SD_BUSTYPE
, SDPCM_RESERVE
);
5538 dbus_sdio_disconnect_cb(void *handle
)
5540 DBUSTRACE(("%s\n", __FUNCTION__
));
5543 disconnect_cb(disc_arg
);
5547 dbus_bus_register(int vid
, int pid
, probe_cb_t prcb
,
5548 disconnect_cb_t discb
, void *prarg
, dbus_intf_t
**intf
, void *param1
, void *param2
)
5553 disconnect_cb
= discb
;
5556 DBUSTRACE(("%s\n", __FUNCTION__
));
5558 bzero(&g_probe_info
, sizeof(probe_sdh_info_t
));
5559 *intf
= &dbus_sdio_intf
;
5561 err
= dbus_bus_osl_register(vid
, pid
, dbus_sdio_probe_cb
,
5562 dbus_sdio_disconnect_cb
, &g_probe_info
, &g_dbusintf
, param1
, param2
);
5570 dbus_bus_deregister()
5572 dbus_bus_osl_deregister();
5577 dbus_sdif_attach(dbus_pub_t
*pub
, void *cbarg
, dbus_intf_callbacks_t
*cbs
)
5579 sdio_info_t
*sdio_info
;
5581 DBUSTRACE(("%s\n", __FUNCTION__
));
5582 if ((g_dbusintf
== NULL
) || (g_dbusintf
->attach
== NULL
))
5585 /* Sanity check for BUS_INFO() */
5586 ASSERT(OFFSETOF(sdio_info_t
, pub
) == 0);
5588 sdio_info
= MALLOC(pub
->osh
, sizeof(sdio_info_t
));
5589 if (sdio_info
== NULL
)
5592 bzero(sdio_info
, sizeof(sdio_info_t
));
5594 sdio_info
->pub
= pub
;
5595 sdio_info
->cbarg
= cbarg
;
5596 sdio_info
->cbs
= cbs
;
5597 sdio_info
->bus
= SD_BUSTYPE
;
5598 /* Use bufpool if allocated, else use locally malloced rxbuf */
5599 sdio_info
->usebufpool
= FALSE
;
5601 /* Update sdio_info with probe info */
5602 sdio_info
->sdh
= g_probe_info
.sdh
;
5603 sdio_info
->sih
= g_probe_info
.sih
;
5604 sdio_info
->ramsize
= g_probe_info
.ramsize
;
5605 sdio_info
->orig_ramsize
= g_probe_info
.orig_ramsize
;
5607 ASSERT(g_probe_info
.chinfo
);
5608 sdio_info
->regs
= g_probe_info
.chinfo
->sdregs
;
5609 sdio_info
->vars
= g_probe_info
.vars
;
5610 sdio_info
->varsz
= g_probe_info
.varsz
;
5611 sdio_info
->hostintmask
= HOSTINTMASK
;
5613 if (g_probe_info
.firmware_file
)
5614 sdio_info
->firmware_path
= g_probe_info
.firmware_file
;
5616 sdio_info
->firmware_path
= firmware_path
;
5618 if (g_probe_info
.nvram_file
)
5619 sdio_info
->nvram_path
= g_probe_info
.nvram_file
;
5621 sdio_info
->nvram_path
= nvram_path
;
5623 /* FIX: Need to redo this maxctl stuff since we don't want cdc and IOCTL
5624 * info in DBUS. maxctl is used by rxbuf for static allocation.
5626 * sdio_info->maxctl = WLC_IOCTL_MAXLEN + sizeof(cdc_ioctl_t) + ROUND_UP_MARGIN;
5628 sdio_info
->maxctl
= 8192 + 16 + 2048;
5629 if (sdio_info
->maxctl
) {
5631 ROUNDUP((sdio_info
->maxctl
+ SDPCM_HDRLEN
), ALIGNMENT
) + SDALIGN
;
5632 if (!(sdio_info
->rxbuf
= MALLOC(pub
->osh
, sdio_info
->rxblen
))) {
5633 DBUSERR(("%s: MALLOC of %d-byte rxbuf failed\n",
5634 __FUNCTION__
, sdio_info
->rxblen
));
5639 /* Allocate buffer to receive glomed packet */
5640 if (!(sdio_info
->databuf
= MALLOC(pub
->osh
, MAX_DATA_BUF
))) {
5641 DBUSERR(("%s: MALLOC of %d-byte databuf failed\n",
5642 __FUNCTION__
, MAX_DATA_BUF
));
5646 /* Align the buffer */
5647 if ((uintptr
)sdio_info
->databuf
% SDALIGN
)
5648 sdio_info
->dataptr
=
5649 sdio_info
->databuf
+ (SDALIGN
- ((uintptr
)sdio_info
->databuf
% SDALIGN
));
5651 sdio_info
->dataptr
= sdio_info
->databuf
;
5653 /* ...and initialize clock/power states */
5654 sdio_info
->sleeping
= FALSE
;
5655 sdio_info
->idletime
= (int32
)dhd_idletime
;
5656 sdio_info
->idleclock
= IDLE_ACTIVE
;
5658 if (!(dbus_sdio_attach_init(sdio_info
, sdio_info
->sdh
,
5659 sdio_info
->firmware_path
, sdio_info
->nvram_path
))) {
5660 DBUSERR(("%s: dbus_sdio_attach_init failed\n", __FUNCTION__
));
5664 ASSERT(sdio_info
->pub
->ntxq
> 0);
5665 pktq_init(&sdio_info
->txq
, (PRIOMASK
+1), sdio_info
->pub
->ntxq
);
5667 /* Locate an appropriately-aligned portion of hdrbuf */
5668 sdio_info
->rxhdr
= (uint8
*)ROUNDUP((uintptr
)&sdio_info
->hdrbuf
[0], SDALIGN
);
5670 /* Set the poll and/or interrupt flags */
5671 sdio_info
->intr
= (bool)dhd_intr
;
5672 if ((sdio_info
->poll
= (bool)dhd_poll
))
5673 sdio_info
->pollrate
= 1;
5675 sdio_info
->sdos_info
= (dbus_pub_t
*)g_dbusintf
->attach(pub
,
5676 sdio_info
, &dbus_sdio_intf_cbs
);
5677 if (sdio_info
->sdos_info
== NULL
)
5680 /* Save SDIO OS-specific driver entry points */
5681 sdio_info
->drvintf
= g_dbusintf
;
5683 if (g_probe_info
.devready
== TRUE
)
5684 sdio_info
->pub
->busstate
= DBUS_STATE_DL_DONE
;
5686 pub
->bus
= sdio_info
;
5688 return (void *) sdio_info
->sdos_info
; /* Return Lower layer info */
5691 MFREE(pub
->osh
, sdio_info
, sizeof(sdio_info_t
));
5698 dbus_sdif_detach(dbus_pub_t
*pub
, void *info
)
5700 sdio_info_t
*sdio_info
= pub
->bus
;
5701 osl_t
*osh
= pub
->osh
;
5703 dbus_bus_stop(sdio_info
);
5705 if (sdio_info
->drvintf
&& sdio_info
->drvintf
->detach
)
5706 sdio_info
->drvintf
->detach(pub
, sdio_info
->sdos_info
);
5708 dbus_sdio_release(sdio_info
, sdio_info
->pub
->osh
);
5709 MFREE(osh
, sdio_info
, sizeof(sdio_info_t
));
5713 dbus_sdio_send_irb_timeout(void *handle
, dbus_irb_tx_t
*txirb
)
5715 sdio_info_t
*sdio_info
= (sdio_info_t
*) handle
;
5717 DBUSTRACE(("%s\n", __FUNCTION__
));
5719 if (sdio_info
== NULL
)
5722 if (sdio_info
->cbs
&& sdio_info
->cbs
->send_irb_timeout
)
5723 sdio_info
->cbs
->send_irb_timeout(sdio_info
->cbarg
, txirb
);
5727 dbus_sdio_send_irb_complete(void *handle
, dbus_irb_tx_t
*txirb
, int status
)
5729 sdio_info_t
*sdio_info
= (sdio_info_t
*) handle
;
5731 if (sdio_info
== NULL
)
5734 if (sdio_info
->cbs
&& sdio_info
->cbs
->send_irb_complete
)
5735 sdio_info
->cbs
->send_irb_complete(sdio_info
->cbarg
, txirb
, status
);
5739 dbus_sdio_recv_irb_complete(void *handle
, dbus_irb_rx_t
*rxirb
, int status
)
5741 sdio_info_t
*sdio_info
= (sdio_info_t
*) handle
;
5743 if (sdio_info
== NULL
)
5746 if (sdio_info
->cbs
&& sdio_info
->cbs
->recv_irb_complete
)
5747 sdio_info
->cbs
->recv_irb_complete(sdio_info
->cbarg
, rxirb
, status
);
5751 dbus_sdio_errhandler(void *handle
, int err
)
5753 sdio_info_t
*sdio_info
= (sdio_info_t
*) handle
;
5755 if (sdio_info
== NULL
)
5758 if (sdio_info
->cbs
&& sdio_info
->cbs
->errhandler
)
5759 sdio_info
->cbs
->errhandler(sdio_info
->cbarg
, err
);
5763 dbus_sdio_ctl_complete(void *handle
, int type
, int status
)
5765 sdio_info_t
*sdio_info
= (sdio_info_t
*) handle
;
5767 if (sdio_info
== NULL
)
5770 if (sdio_info
->cbs
&& sdio_info
->cbs
->ctl_complete
)
5771 sdio_info
->cbs
->ctl_complete(sdio_info
->cbarg
, type
, status
);
5775 dbus_sdio_state_change(void *handle
, int state
)
5777 sdio_info_t
*sdio_info
= (sdio_info_t
*) handle
;
5779 if (sdio_info
== NULL
)
5782 if (sdio_info
->cbs
&& sdio_info
->cbs
->state_change
)
5783 sdio_info
->cbs
->state_change(sdio_info
->cbarg
, state
);
5785 if (state
== DBUS_STATE_DISCONNECT
) {
5786 if (sdio_info
->drvintf
&& sdio_info
->drvintf
->remove
)
5787 sdio_info
->drvintf
->remove(sdio_info
->sdos_info
);
5789 sdio_info
->pub
->busstate
= DBUS_STATE_DOWN
;
5795 dbus_sdio_dpc(void *handle
, bool bounded
)
5797 sdio_info_t
*sdio_info
= (sdio_info_t
*) handle
;
5799 sdpcmd_regs_t
*regs
;
5800 uint32 intstatus
, newstatus
= 0;
5803 uint rxlimit
= dhd_rxbound
; /* Rx frames to read before resched */
5804 uint framecnt
= 0; /* Temporary counter of tx/rx frames */
5805 bool rxdone
= TRUE
; /* Flag for no more read data */
5806 bool resched
= FALSE
; /* Flag indicating resched wanted */
5808 DBUSTRACE(("%s: Enter\n", __FUNCTION__
));
5810 if (sdio_info
== NULL
) {
5811 DBUSERR(("%s: sdio_info == NULL!\n", __FUNCTION__
));
5815 dbus_sdos_lock(sdio_info
);
5817 sdh
= sdio_info
->sdh
;
5818 regs
= sdio_info
->regs
;
5820 /* Start with leftover status bits */
5821 intstatus
= sdio_info
->intstatus
;
5823 /* If waiting for HTAVAIL, check status */
5824 if (sdio_info
->clkstate
== CLK_PENDING
) {
5826 uint8 clkctl
, devctl
= 0;
5829 /* Check for inconsistent device control */
5830 devctl
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
, SBSDIO_DEVICE_CTL
, &err
);
5832 DBUSERR(("%s: error reading DEVCTL: %d\n", __FUNCTION__
, err
));
5833 sdio_info
->pub
->busstate
= DBUS_STATE_DOWN
;
5835 ASSERT(devctl
& SBSDIO_DEVCTL_CA_INT_ONLY
);
5838 /* Read CSR, if clock on switch to AVAIL, else ignore */
5839 clkctl
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
, &err
);
5841 DBUSERR(("%s: error reading CSR: %d\n", __FUNCTION__
, err
));
5842 sdio_info
->pub
->busstate
= DBUS_STATE_DOWN
;
5845 DBUSINFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", devctl
, clkctl
));
5847 if (SBSDIO_HTAV(clkctl
)) {
5848 devctl
= bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
, SBSDIO_DEVICE_CTL
, &err
);
5850 DBUSERR(("%s: error reading DEVCTL: %d\n",
5851 __FUNCTION__
, err
));
5852 sdio_info
->pub
->busstate
= DBUS_STATE_DOWN
;
5854 devctl
&= ~SBSDIO_DEVCTL_CA_INT_ONLY
;
5855 bcmsdh_cfg_write(sdh
, SDIO_FUNC_1
, SBSDIO_DEVICE_CTL
, devctl
, &err
);
5857 DBUSERR(("%s: error writing DEVCTL: %d\n",
5858 __FUNCTION__
, err
));
5859 sdio_info
->pub
->busstate
= DBUS_STATE_DOWN
;
5861 sdio_info
->clkstate
= CLK_AVAIL
;
5867 BUS_WAKE(sdio_info
);
5869 /* Make sure backplane clock is on */
5870 dbus_sdio_clkctl(sdio_info
, CLK_AVAIL
, TRUE
);
5871 if (sdio_info
->clkstate
== CLK_PENDING
)
5874 /* Pending interrupt indicates new device status */
5875 if (sdio_info
->ipend
) {
5876 sdio_info
->ipend
= FALSE
;
5877 R_SDREG(newstatus
, ®s
->intstatus
, retries
);
5878 sdio_info
->f1regdata
++;
5879 if (bcmsdh_regfail(sdio_info
->sdh
))
5881 newstatus
&= sdio_info
->hostintmask
;
5882 sdio_info
->fcstate
= !!(newstatus
& I_HMB_FC_STATE
);
5884 W_SDREG(newstatus
, ®s
->intstatus
, retries
);
5885 sdio_info
->f1regdata
++;
5889 /* Merge new bits with previous */
5890 intstatus
|= newstatus
;
5891 sdio_info
->intstatus
= 0;
5893 /* Handle flow-control change: read new state in case our ack
5894 * crossed another change interrupt. If change still set, assume
5895 * FC ON for safety, let next loop through do the debounce.
5897 if (intstatus
& I_HMB_FC_CHANGE
) {
5898 intstatus
&= ~I_HMB_FC_CHANGE
;
5899 W_SDREG(I_HMB_FC_CHANGE
, ®s
->intstatus
, retries
);
5900 R_SDREG(newstatus
, ®s
->intstatus
, retries
);
5901 sdio_info
->f1regdata
+= 2;
5902 sdio_info
->fcstate
= !!(newstatus
& (I_HMB_FC_STATE
| I_HMB_FC_CHANGE
));
5903 intstatus
|= (newstatus
& sdio_info
->hostintmask
);
5906 /* Just being here means nothing more to do for chipactive */
5907 if (intstatus
& I_CHIPACTIVE
) {
5908 /* ASSERT(sdio_info->clkstate == CLK_AVAIL); */
5909 intstatus
&= ~I_CHIPACTIVE
;
5912 /* Handle host mailbox indication */
5913 if (intstatus
& I_HMB_HOST_INT
) {
5914 intstatus
&= ~I_HMB_HOST_INT
;
5915 intstatus
|= dbus_sdio_hostmail(sdio_info
);
5918 /* Generally don't ask for these, can get CRC errors... */
5919 if (intstatus
& I_WR_OOSYNC
) {
5920 DBUSERR(("Dongle reports WR_OOSYNC\n"));
5921 intstatus
&= ~I_WR_OOSYNC
;
5924 if (intstatus
& I_RD_OOSYNC
) {
5925 DBUSERR(("Dongle reports RD_OOSYNC\n"));
5926 intstatus
&= ~I_RD_OOSYNC
;
5929 if (intstatus
& I_SBINT
) {
5930 DBUSERR(("Dongle reports SBINT\n"));
5931 intstatus
&= ~I_SBINT
;
5934 /* Would be active due to wake-wlan in gSPI */
5935 if (intstatus
& I_CHIPACTIVE
) {
5936 DBUSERR(("Dongle reports CHIPACTIVE\n"));
5937 intstatus
&= ~I_CHIPACTIVE
;
5940 /* Ignore frame indications if rxskip is set */
5941 if (sdio_info
->rxskip
)
5942 intstatus
&= ~I_HMB_FRAME_IND
;
5944 /* On frame indication, read available frames */
5945 if (PKT_AVAILABLE()) {
5946 framecnt
= dbus_sdio_readframes(sdio_info
, rxlimit
, &rxdone
);
5947 if (rxdone
|| sdio_info
->rxskip
)
5948 intstatus
&= ~I_HMB_FRAME_IND
;
5949 rxlimit
-= MIN(framecnt
, rxlimit
);
5952 if (pktq_mlen(&sdio_info
->txq
, ~sdio_info
->flowcontrol
) > 0) {
5953 /* reschedule txq */
5954 dbus_sdio_txq_sched(sdio_info
->sdos_info
);
5957 /* Keep still-pending events for next scheduling */
5958 sdio_info
->intstatus
= intstatus
;
5961 /* Re-enable interrupts to detect new device events (mailbox, rx frame)
5962 * or clock availability. (Allows tx loop to check ipend if desired.)
5963 * (Unless register access seems hosed, as we may not be able to ACK...)
5965 if (sdio_info
->intr
&& sdio_info
->intdis
&& !bcmsdh_regfail(sdh
)) {
5966 DBUSINTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n",
5967 __FUNCTION__
, rxdone
, framecnt
));
5968 sdio_info
->intdis
= FALSE
;
5969 bcmsdh_intr_enable(sdh
);
5972 /* Resched if events or tx frames are pending, else await next interrupt */
5973 /* On failed register access, all bets are off: no resched or interrupts */
5974 if ((sdio_info
->pub
->busstate
== DBUS_STATE_DOWN
) || bcmsdh_regfail(sdh
)) {
5975 DBUSERR(("%s: failed backplane access over SDIO, halting operation\n",
5977 dbus_sdio_state_change(sdio_info
, DBUS_STATE_DISCONNECT
);
5978 sdio_info
->intstatus
= 0;
5979 dbus_bus_stop(sdio_info
);
5980 } else if (sdio_info
->clkstate
== CLK_PENDING
) {
5981 /* Awaiting I_CHIP_ACTIVE, don't resched */
5982 } else if (sdio_info
->intstatus
|| sdio_info
->ipend
|| PKT_AVAILABLE()) {
5986 /* If we're done for now, turn off clock request. */
5987 if (sdio_info
->idletime
== IDLE_IMMEDIATE
) {
5988 sdio_info
->activity
= FALSE
;
5989 dbus_sdio_clkctl(sdio_info
, CLK_NONE
, FALSE
);
5992 sdio_info
->dpc_sched
= resched
;
5993 dbus_sdos_unlock(sdio_info
);
5999 dbus_sdio_watchdog(void *handle
)
6004 dbus_bus_fw_get(void *bus
, uint8
**fw
, int *fwlen
, int *decomp
)
6006 sdio_info_t
*sdio_info
= BUS_INFO(bus
, sdio_info_t
);
6010 devid
= sdio_info
->pub
->attrib
.devid
;
6011 crev
= sdio_info
->pub
->attrib
.chiprev
;
6017 case BCM4319_CHIP_ID
:
6018 #if defined(EMBED_IMAGE_4319sd)
6019 *fw
= (uint8
*)dlarray_4319sd
;
6020 *fwlen
= sizeof(dlarray_4319sd
);
6023 case BCM4325_CHIP_ID
:
6024 #ifdef EMBED_IMAGE_4325sd
6025 *fw
= (uint8
*)dlarray_4325sd
;
6026 *fwlen
= sizeof(dlarray_4325sd
);
6030 #ifdef EMBED_IMAGE_GENERIC
6031 *fw
= (uint8
*)dlarray
;
6032 *fwlen
= sizeof(dlarray
);