1 /* 2 * DHD Bus Module for SDIO 3 * 4 * Copyright (C) 1999-2010, Broadcom Corporation 5 * 6 * Unless you and Broadcom execute a separate written software license 7 * agreement governing use of this software, this software is licensed to you 8 * under the terms of the GNU General Public License version 2 (the "GPL"), 9 * available at http://www.broadcom.com/licenses/GPLv2.php, with the 10 * following added to such license: 11 * 12 * As a special exception, the copyright holders of this software give you 13 * permission to link this software with independent modules, and to copy and 14 * distribute the resulting executable under terms of your choice, provided that 15 * you also meet, for each linked independent module, the terms and conditions of 16 * the license of that module. An independent module is a module which is not 17 * derived from this software. The special exception does not apply to any 18 * modifications of the software. 19 * 20 * Notwithstanding the above, under no circumstances may you combine this 21 * software in any way with any other Broadcom software provided under a license 22 * other than the GPL, without Broadcom's express prior written consent. 23 * 24 * $Id: dhd_sdio.c,v 1.157.2.27.2.33.2.109 2010/04/22 05:52:46 Exp $ 25 */ 26 27 #include <typedefs.h> 28 #include <osl.h> 29 #include <bcmsdh.h> 30 31 #ifdef BCMEMBEDIMAGE 32 #include BCMEMBEDIMAGE 33 #endif /* BCMEMBEDIMAGE */ 34 35 #include <bcmdefs.h> 36 #include <bcmutils.h> 37 #include <bcmendian.h> 38 #include <bcmdevs.h> 39 40 #include <siutils.h> 41 #include <hndpmu.h> 42 #include <hndsoc.h> 43 #include <sbchipc.h> 44 #include <sbhnddma.h> 45 46 #include <sdio.h> 47 #include <sbsdio.h> 48 #include <sbsdpcmdev.h> 49 #include <bcmsdpcm.h> 50 51 #include <proto/ethernet.h> 52 #include <proto/802.1d.h> 53 #include <proto/802.11.h> 54 55 #include <dngl_stats.h> 56 #include <dhd.h> 57 #include <dhd_bus.h> 58 #include <dhd_proto.h> 59 #include <dhd_dbg.h> 60 #include <dhdioctl.h> 61 #include <sdiovar.h> 62 63 #define QLEN 256 /* bulk rx and tx queue lengths */ 64 #define FCHI (QLEN - 10) 65 #define FCLOW (FCHI / 2) 66 #define PRIOMASK 7 67 68 #define TXRETRIES 2 /* # of retries for tx frames */ 69 70 #if defined(CONFIG_MACH_SANDGATE2G) 71 #define DHD_RXBOUND 250 /* Default for max rx frames in one scheduling */ 72 #else 73 #define DHD_RXBOUND 50 /* Default for max rx frames in one scheduling */ 74 #endif /* defined(CONFIG_MACH_SANDGATE2G) */ 75 76 #define DHD_TXBOUND 20 /* Default for max tx frames in one scheduling */ 77 78 #define DHD_TXMINMAX 1 /* Max tx frames if rx still pending */ 79 80 #define MEMBLOCK 2048 /* Block size used for downloading of dongle image */ 81 #define MAX_DATA_BUF (32 * 1024) /* Must be large enough to hold biggest possible glom */ 82 83 /* Packet alignment for most efficient SDIO (can change based on platform) */ 84 #ifndef DHD_SDALIGN 85 #define DHD_SDALIGN 32 86 #endif 87 #if !ISPOWEROF2(DHD_SDALIGN) 88 #error DHD_SDALIGN is not a power of 2! 89 #endif 90 91 #ifndef DHD_FIRSTREAD 92 #define DHD_FIRSTREAD 32 93 #endif 94 #if !ISPOWEROF2(DHD_FIRSTREAD) 95 #error DHD_FIRSTREAD is not a power of 2! 96 #endif 97 98 /* Total length of frame header for dongle protocol */ 99 #define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN) 100 #ifdef SDTEST 101 #define SDPCM_RESERVE (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN) 102 #else 103 #define SDPCM_RESERVE (SDPCM_HDRLEN + DHD_SDALIGN) 104 #endif 105 106 /* Space for header read, limit for data packets */ 107 #ifndef MAX_HDR_READ 108 #define MAX_HDR_READ 32 109 #endif 110 #if !ISPOWEROF2(MAX_HDR_READ) 111 #error MAX_HDR_READ is not a power of 2! 112 #endif 113 114 #define MAX_RX_DATASZ 2048 115 116 /* Maximum milliseconds to wait for F2 to come up */ 117 #define DHD_WAIT_F2RDY 3000 118 119 /* Bump up limit on waiting for HT to account for first startup; 120 * if the image is doing a CRC calculation before programming the PMU 121 * for HT availability, it could take a couple hundred ms more, so 122 * max out at a half second (500000us). 123 */ 124 #if (PMU_MAX_TRANSITION_DLY <= 500000) 125 #undef PMU_MAX_TRANSITION_DLY 126 #define PMU_MAX_TRANSITION_DLY 500000 127 #endif 128 129 /* Value for ChipClockCSR during initial setup */ 130 #define DHD_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ) 131 #define DHD_INIT_CLKCTL2 (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP) 132 133 /* Flags for SDH calls */ 134 #define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED) 135 136 /* Packet free applicable unconditionally for sdio and sdspi. Conditional if 137 * bufpool was present for gspi bus. 138 */ 139 #define PKTFREE2() if ((bus->bus != SPI_BUS) || bus->usebufpool) \ 140 PKTFREE(bus->dhd->osh, pkt, FALSE); 141 DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep); 142 extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len); 143 144 145 /* Private data for SDIO bus interaction */ 146 typedef struct dhd_bus { 147 dhd_pub_t *dhd; 148 149 bcmsdh_info_t *sdh; /* Handle for BCMSDH calls */ 150 si_t *sih; /* Handle for SI calls */ 151 char *vars; /* Variables (from CIS and/or other) */ 152 uint varsz; /* Size of variables buffer */ 153 uint32 sbaddr; /* Current SB window pointer (-1, invalid) */ 154 155 sdpcmd_regs_t *regs; /* Registers for SDIO core */ 156 uint sdpcmrev; /* SDIO core revision */ 157 uint armrev; /* CPU core revision */ 158 uint ramrev; /* SOCRAM core revision */ 159 uint32 ramsize; /* Size of RAM in SOCRAM (bytes) */ 160 uint32 orig_ramsize; /* Size of RAM in SOCRAM (bytes) */ 161 162 uint32 bus; /* gSPI or SDIO bus */ 163 uint32 hostintmask; /* Copy of Host Interrupt Mask */ 164 uint32 intstatus; /* Intstatus bits (events) pending */ 165 bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */ 166 bool fcstate; /* State of dongle flow-control */ 167 168 uint16 cl_devid; /* cached devid for dhdsdio_probe_attach() */ 169 char *fw_path; /* module_param: path to firmware image */ 170 char *nv_path; /* module_param: path to nvram vars file */ 171 const char *nvram_params; /* user specified nvram params. */ 172 173 uint blocksize; /* Block size of SDIO transfers */ 174 uint roundup; /* Max roundup limit */ 175 176 struct pktq txq; /* Queue length used for flow-control */ 177 uint8 flowcontrol; /* per prio flow control bitmask */ 178 uint8 tx_seq; /* Transmit sequence number (next) */ 179 uint8 tx_max; /* Maximum transmit sequence allowed */ 180 181 uint8 hdrbuf[MAX_HDR_READ + DHD_SDALIGN]; 182 uint8 *rxhdr; /* Header of current rx frame (in hdrbuf) */ 183 uint16 nextlen; /* Next Read Len from last header */ 184 uint8 rx_seq; /* Receive sequence number (expected) */ 185 bool rxskip; /* Skip receive (awaiting NAK ACK) */ 186 187 void *glomd; /* Packet containing glomming descriptor */ 188 void *glom; /* Packet chain for glommed superframe */ 189 uint glomerr; /* Glom packet read errors */ 190 191 uint8 *rxbuf; /* Buffer for receiving control packets */ 192 uint rxblen; /* Allocated length of rxbuf */ 193 uint8 *rxctl; /* Aligned pointer into rxbuf */ 194 uint8 *databuf; /* Buffer for receiving big glom packet */ 195 uint8 *dataptr; /* Aligned pointer into databuf */ 196 uint rxlen; /* Length of valid data in buffer */ 197 198 uint8 sdpcm_ver; /* Bus protocol reported by dongle */ 199 200 bool intr; /* Use interrupts */ 201 bool poll; /* Use polling */ 202 bool ipend; /* Device interrupt is pending */ 203 bool intdis; /* Interrupts disabled by isr */ 204 uint intrcount; /* Count of device interrupt callbacks */ 205 uint lastintrs; /* Count as of last watchdog timer */ 206 uint spurious; /* Count of spurious interrupts */ 207 uint pollrate; /* Ticks between device polls */ 208 uint polltick; /* Tick counter */ 209 uint pollcnt; /* Count of active polls */ 210 211 212 uint regfails; /* Count of R_REG/W_REG failures */ 213 214 uint clkstate; /* State of sd and backplane clock(s) */ 215 bool activity; /* Activity flag for clock down */ 216 int32 idletime; /* Control for activity timeout */ 217 int32 idlecount; /* Activity timeout counter */ 218 int32 idleclock; /* How to set bus driver when idle */ 219 int32 sd_divisor; /* Speed control to bus driver */ 220 int32 sd_mode; /* Mode control to bus driver */ 221 int32 sd_rxchain; /* If bcmsdh api accepts PKT chains */ 222 bool use_rxchain; /* If dhd should use PKT chains */ 223 bool sleeping; /* Is SDIO bus sleeping? */ 224 bool rxflow_mode; /* Rx flow control mode */ 225 bool rxflow; /* Is rx flow control on */ 226 uint prev_rxlim_hit; /* Is prev rx limit exceeded (per dpc schedule) */ 227 bool alp_only; /* Don't use HT clock (ALP only) */ 228 /* Field to decide if rx of control frames happen in rxbuf or lb-pool */ 229 bool usebufpool; 230 231 #ifdef SDTEST 232 /* external loopback */ 233 bool ext_loop; 234 uint8 loopid; 235 236 /* pktgen configuration */ 237 uint pktgen_freq; /* Ticks between bursts */ 238 uint pktgen_count; /* Packets to send each burst */ 239 uint pktgen_print; /* Bursts between count displays */ 240 uint pktgen_total; /* Stop after this many */ 241 uint pktgen_minlen; /* Minimum packet data len */ 242 uint pktgen_maxlen; /* Maximum packet data len */ 243 uint pktgen_mode; /* Configured mode: tx, rx, or echo */ 244 uint pktgen_stop; /* Number of tx failures causing stop */ 245 246 /* active pktgen fields */ 247 uint pktgen_tick; /* Tick counter for bursts */ 248 uint pktgen_ptick; /* Burst counter for printing */ 249 uint pktgen_sent; /* Number of test packets generated */ 250 uint pktgen_rcvd; /* Number of test packets received */ 251 uint pktgen_fail; /* Number of failed send attempts */ 252 uint16 pktgen_len; /* Length of next packet to send */ 253 #endif /* SDTEST */ 254 255 /* Some additional counters */ 256 uint tx_sderrs; /* Count of tx attempts with sd errors */ 257 uint fcqueued; /* Tx packets that got queued */ 258 uint rxrtx; /* Count of rtx requests (NAK to dongle) */ 259 uint rx_toolong; /* Receive frames too long to receive */ 260 uint rxc_errors; /* SDIO errors when reading control frames */ 261 uint rx_hdrfail; /* SDIO errors on header reads */ 262 uint rx_badhdr; /* Bad received headers (roosync?) */ 263 uint rx_badseq; /* Mismatched rx sequence number */ 264 uint fc_rcvd; /* Number of flow-control events received */ 265 uint fc_xoff; /* Number which turned on flow-control */ 266 uint fc_xon; /* Number which turned off flow-control */ 267 uint rxglomfail; /* Failed deglom attempts */ 268 uint rxglomframes; /* Number of glom frames (superframes) */ 269 uint rxglompkts; /* Number of packets from glom frames */ 270 uint f2rxhdrs; /* Number of header reads */ 271 uint f2rxdata; /* Number of frame data reads */ 272 uint f2txdata; /* Number of f2 frame writes */ 273 uint f1regdata; /* Number of f1 register accesses */ 274 275 uint8 *ctrl_frame_buf; 276 uint32 ctrl_frame_len; 277 bool ctrl_frame_stat; 278 } dhd_bus_t; 279 280 /* clkstate */ 281 #define CLK_NONE 0 282 #define CLK_SDONLY 1 283 #define CLK_PENDING 2 /* Not used yet */ 284 #define CLK_AVAIL 3 285 286 #define DHD_NOPMU(dhd) (FALSE) 287 288 #ifdef DHD_DEBUG 289 static int qcount[NUMPRIO]; 290 static int tx_packets[NUMPRIO]; 291 #endif /* DHD_DEBUG */ 292 293 /* Deferred transmit */ 294 const uint dhd_deferred_tx = 1; 295 296 extern uint dhd_watchdog_ms; 297 extern void dhd_os_wd_timer(void *bus, uint wdtick); 298 299 /* Tx/Rx bounds */ 300 uint dhd_txbound; 301 uint dhd_rxbound; 302 uint dhd_txminmax; 303 304 /* override the RAM size if possible */ 305 #define DONGLE_MIN_MEMSIZE (128 *1024) 306 int dhd_dongle_memsize; 307 308 static bool dhd_doflow; 309 static bool dhd_alignctl; 310 311 static bool sd1idle; 312 313 static bool retrydata; 314 #define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata) 315 316 static const uint watermark = 8; 317 static const uint firstread = DHD_FIRSTREAD; 318 319 #define HDATLEN (firstread - (SDPCM_HDRLEN)) 320 321 /* Retry count for register access failures */ 322 static const uint retry_limit = 2; 323 324 /* Force even SD lengths (some host controllers mess up on odd bytes) */ 325 static bool forcealign; 326 327 #define ALIGNMENT 4 328 329 #if defined(OOB_INTR_ONLY) && defined(HW_OOB) 330 extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable); 331 #endif 332 333 #if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) 334 #error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD 335 #endif /* defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) */ 336 #define PKTALIGN(osh, p, len, align) \ 337 do { \ 338 uint datalign; \ 339 datalign = (uintptr)PKTDATA((osh), (p)); \ 340 datalign = ROUNDUP(datalign, (align)) - datalign; \ 341 ASSERT(datalign < (align)); \ 342 ASSERT(PKTLEN((osh), (p)) >= ((len) + datalign)); \ 343 if (datalign) \ 344 PKTPULL((osh), (p), datalign); \ 345 PKTSETLEN((osh), (p), (len)); \ 346 } while (0) 347 348 /* Limit on rounding up frames */ 349 static const uint max_roundup = 512; 350 351 /* Try doing readahead */ 352 static bool dhd_readahead; 353 354 355 /* To check if there's window offered */ 356 #define DATAOK(bus) \ 357 (((uint8)(bus->tx_max - bus->tx_seq) != 0) && \ 358 (((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0)) 359 360 /* Macros to get register read/write status */ 361 /* NOTE: these assume a local dhdsdio_bus_t *bus! */ 362 #define R_SDREG(regvar, regaddr, retryvar) \ 363 do { \ 364 retryvar = 0; \ 365 do { \ 366 regvar = R_REG(bus->dhd->osh, regaddr); \ 367 } while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \ 368 if (retryvar) { \ 369 bus->regfails += (retryvar-1); \ 370 if (retryvar > retry_limit) { \ 371 DHD_ERROR(("%s: FAILED" #regvar "READ, LINE %d\n", \ 372 __FUNCTION__, __LINE__)); \ 373 regvar = 0; \ 374 } \ 375 } \ 376 } while (0) 377 378 #define W_SDREG(regval, regaddr, retryvar) \ 379 do { \ 380 retryvar = 0; \ 381 do { \ 382 W_REG(bus->dhd->osh, regaddr, regval); \ 383 } while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \ 384 if (retryvar) { \ 385 bus->regfails += (retryvar-1); \ 386 if (retryvar > retry_limit) \ 387 DHD_ERROR(("%s: FAILED REGISTER WRITE, LINE %d\n", \ 388 __FUNCTION__, __LINE__)); \ 389 } \ 390 } while (0) 391 392 393 #define DHD_BUS SDIO_BUS 394 395 #define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND) 396 397 #define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE) 398 399 #define GSPI_PR55150_BAILOUT 400 401 402 #ifdef SDTEST 403 static void dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq); 404 static void dhdsdio_sdtest_set(dhd_bus_t *bus, bool start); 405 #endif 406 407 static int dhdsdio_download_state(dhd_bus_t *bus, bool enter); 408 409 static void dhdsdio_release(dhd_bus_t *bus, osl_t *osh); 410 static void dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh); 411 static void dhdsdio_disconnect(void *ptr); 412 static bool dhdsdio_chipmatch(uint16 chipid); 413 static bool dhdsdio_probe_attach(dhd_bus_t *bus, osl_t *osh, void *sdh, 414 void * regsva, uint16 devid); 415 static bool dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh); 416 static bool dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh); 417 static void dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh); 418 419 static uint process_nvram_vars(char *varbuf, uint len); 420 421 static void dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size); 422 static int dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, 423 uint8 *buf, uint nbytes, 424 void *pkt, bcmsdh_cmplt_fn_t complete, void *handle); 425 static int dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, 426 uint8 *buf, uint nbytes, 427 void *pkt, bcmsdh_cmplt_fn_t complete, void *handle); 428 429 static bool dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh); 430 static int _dhdsdio_download_firmware(struct dhd_bus *bus); 431 432 static int dhdsdio_download_code_file(struct dhd_bus *bus, char *image_path); 433 static int dhdsdio_download_nvram(struct dhd_bus *bus); 434 #ifdef BCMEMBEDIMAGE 435 static int dhdsdio_download_code_array(struct dhd_bus *bus); 436 #endif 437 438 439 static void 440 dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size) 441 { 442 int32 min_size = DONGLE_MIN_MEMSIZE; 443 /* Restrict the memsize to user specified limit */ 444 DHD_ERROR(("user: Restrict the dongle ram size to %d, min accepted %d\n", 445 dhd_dongle_memsize, min_size)); 446 if ((dhd_dongle_memsize > min_size) && 447 (dhd_dongle_memsize < (int32)bus->orig_ramsize)) 448 bus->ramsize = dhd_dongle_memsize; 449 } 450 451 static int 452 dhdsdio_set_siaddr_window(dhd_bus_t *bus, uint32 address) 453 { 454 int err = 0; 455 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, 456 (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err); 457 if (!err) 458 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID, 459 (address >> 16) & SBSDIO_SBADDRMID_MASK, &err); 460 if (!err) 461 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH, 462 (address >> 24) & SBSDIO_SBADDRHIGH_MASK, &err); 463 return err; 464 } 465 466 467 /* Turn backplane clock on or off */ 468 static int 469 dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) 470 { 471 int err; 472 uint8 clkctl, clkreq, devctl; 473 bcmsdh_info_t *sdh; 474 475 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 476 477 #if defined(OOB_INTR_ONLY) 478 pendok = FALSE; 479 #endif 480 clkctl = 0; 481 sdh = bus->sdh; 482 483 484 if (on) { 485 /* Request HT Avail */ 486 clkreq = bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ; 487 488 if ((bus->sih->chip == BCM4329_CHIP_ID) && (bus->sih->chiprev == 0)) 489 clkreq |= SBSDIO_FORCE_ALP; 490 491 492 493 494 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); 495 if (err) { 496 DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err)); 497 return BCME_ERROR; 498 } 499 500 if (pendok && 501 ((bus->sih->buscoretype == PCMCIA_CORE_ID) && (bus->sih->buscorerev == 9))) { 502 uint32 dummy, retries; 503 R_SDREG(dummy, &bus->regs->clockctlstatus, retries); 504 } 505 506 /* Check current status */ 507 clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); 508 if (err) { 509 DHD_ERROR(("%s: HT Avail read error: %d\n", __FUNCTION__, err)); 510 return BCME_ERROR; 511 } 512 513 /* Go to pending and await interrupt if appropriate */ 514 if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) { 515 /* Allow only clock-available interrupt */ 516 devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); 517 if (err) { 518 DHD_ERROR(("%s: Devctl access error setting CA: %d\n", 519 __FUNCTION__, err)); 520 return BCME_ERROR; 521 } 522 523 devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; 524 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); 525 DHD_INFO(("CLKCTL: set PENDING\n")); 526 bus->clkstate = CLK_PENDING; 527 return BCME_OK; 528 } else if (bus->clkstate == CLK_PENDING) { 529 /* Cancel CA-only interrupt filter */ 530 devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); 531 devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; 532 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); 533 } 534 535 /* Otherwise, wait here (polling) for HT Avail */ 536 if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { 537 SPINWAIT_SLEEP(sdioh_spinwait_sleep, 538 ((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, 539 SBSDIO_FUNC1_CHIPCLKCSR, &err)), 540 !SBSDIO_CLKAV(clkctl, bus->alp_only)), PMU_MAX_TRANSITION_DLY); 541 } 542 if (err) { 543 DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err)); 544 return BCME_ERROR; 545 } 546 if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { 547 DHD_ERROR(("%s: HT Avail timeout (%d): clkctl 0x%02x\n", 548 __FUNCTION__, PMU_MAX_TRANSITION_DLY, clkctl)); 549 return BCME_ERROR; 550 } 551 552 553 /* Mark clock available */ 554 bus->clkstate = CLK_AVAIL; 555 DHD_INFO(("CLKCTL: turned ON\n")); 556 557 #if defined(DHD_DEBUG) 558 if (bus->alp_only == TRUE) { 559 #if !defined(BCMLXSDMMC) 560 if (!SBSDIO_ALPONLY(clkctl)) { 561 DHD_ERROR(("%s: HT Clock, when ALP Only\n", __FUNCTION__)); 562 } 563 #endif /* !defined(BCMLXSDMMC) */ 564 } else { 565 if (SBSDIO_ALPONLY(clkctl)) { 566 DHD_ERROR(("%s: HT Clock should be on.\n", __FUNCTION__)); 567 } 568 } 569 #endif /* defined (DHD_DEBUG) */ 570 571 bus->activity = TRUE; 572 } else { 573 clkreq = 0; 574 575 if (bus->clkstate == CLK_PENDING) { 576 /* Cancel CA-only interrupt filter */ 577 devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); 578 devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; 579 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); 580 } 581 582 bus->clkstate = CLK_SDONLY; 583 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); 584 DHD_INFO(("CLKCTL: turned OFF\n")); 585 if (err) { 586 DHD_ERROR(("%s: Failed access turning clock off: %d\n", 587 __FUNCTION__, err)); 588 return BCME_ERROR; 589 } 590 } 591 return BCME_OK; 592 } 593 594 /* Change idle/active SD state */ 595 static int 596 dhdsdio_sdclk(dhd_bus_t *bus, bool on) 597 { 598 int err; 599 int32 iovalue; 600 601 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 602 603 if (on) { 604 if (bus->idleclock == DHD_IDLE_STOP) { 605 /* Turn on clock and restore mode */ 606 iovalue = 1; 607 err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0, 608 &iovalue, sizeof(iovalue), TRUE); 609 if (err) { 610 DHD_ERROR(("%s: error enabling sd_clock: %d\n", 611 __FUNCTION__, err)); 612 return BCME_ERROR; 613 } 614 615 iovalue = bus->sd_mode; 616 err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0, 617 &iovalue, sizeof(iovalue), TRUE); 618 if (err) { 619 DHD_ERROR(("%s: error changing sd_mode: %d\n", 620 __FUNCTION__, err)); 621 return BCME_ERROR; 622 } 623 } else if (bus->idleclock != DHD_IDLE_ACTIVE) { 624 /* Restore clock speed */ 625 iovalue = bus->sd_divisor; 626 err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0, 627 &iovalue, sizeof(iovalue), TRUE); 628 if (err) { 629 DHD_ERROR(("%s: error restoring sd_divisor: %d\n", 630 __FUNCTION__, err)); 631 return BCME_ERROR; 632 } 633 } 634 bus->clkstate = CLK_SDONLY; 635 } else { 636 /* Stop or slow the SD clock itself */ 637 if ((bus->sd_divisor == -1) || (bus->sd_mode == -1)) { 638 DHD_TRACE(("%s: can't idle clock, divisor %d mode %d\n", 639 __FUNCTION__, bus->sd_divisor, bus->sd_mode)); 640 return BCME_ERROR; 641 } 642 if (bus->idleclock == DHD_IDLE_STOP) { 643 if (sd1idle) { 644 /* Change to SD1 mode and turn off clock */ 645 iovalue = 1; 646 err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0, 647 &iovalue, sizeof(iovalue), TRUE); 648 if (err) { 649 DHD_ERROR(("%s: error changing sd_clock: %d\n", 650 __FUNCTION__, err)); 651 return BCME_ERROR; 652 } 653 } 654 655 iovalue = 0; 656 err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0, 657 &iovalue, sizeof(iovalue), TRUE); 658 if (err) { 659 DHD_ERROR(("%s: error disabling sd_clock: %d\n", 660 __FUNCTION__, err)); 661 return BCME_ERROR; 662 } 663 } else if (bus->idleclock != DHD_IDLE_ACTIVE) { 664 /* Set divisor to idle value */ 665 iovalue = bus->idleclock; 666 err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0, 667 &iovalue, sizeof(iovalue), TRUE); 668 if (err) { 669 DHD_ERROR(("%s: error changing sd_divisor: %d\n", 670 __FUNCTION__, err)); 671 return BCME_ERROR; 672 } 673 } 674 bus->clkstate = CLK_NONE; 675 } 676 677 return BCME_OK; 678 } 679 680 /* Transition SD and backplane clock readiness */ 681 static int 682 dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok) 683 { 684 #ifdef DHD_DEBUG 685 uint oldstate = bus->clkstate; 686 #endif /* DHD_DEBUG */ 687 688 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 689 690 /* Early exit if we're already there */ 691 if (bus->clkstate == target) { 692 if (target == CLK_AVAIL) { 693 dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms); 694 bus->activity = TRUE; 695 } 696 return BCME_OK; 697 } 698 699 switch (target) { 700 case CLK_AVAIL: 701 /* Make sure SD clock is available */ 702 if (bus->clkstate == CLK_NONE) 703 dhdsdio_sdclk(bus, TRUE); 704 /* Now request HT Avail on the backplane */ 705 dhdsdio_htclk(bus, TRUE, pendok); 706 dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms); 707 bus->activity = TRUE; 708 break; 709 710 case CLK_SDONLY: 711 /* Remove HT request, or bring up SD clock */ 712 if (bus->clkstate == CLK_NONE) 713 dhdsdio_sdclk(bus, TRUE); 714 else if (bus->clkstate == CLK_AVAIL) 715 dhdsdio_htclk(bus, FALSE, FALSE); 716 else 717 DHD_ERROR(("dhdsdio_clkctl: request for %d -> %d\n", 718 bus->clkstate, target)); 719 dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms); 720 break; 721 722 case CLK_NONE: 723 /* Make sure to remove HT request */ 724 if (bus->clkstate == CLK_AVAIL) 725 dhdsdio_htclk(bus, FALSE, FALSE); 726 /* Now remove the SD clock */ 727 dhdsdio_sdclk(bus, FALSE); 728 dhd_os_wd_timer(bus->dhd, 0); 729 break; 730 } 731 #ifdef DHD_DEBUG 732 DHD_INFO(("dhdsdio_clkctl: %d -> %d\n", oldstate, bus->clkstate)); 733 #endif /* DHD_DEBUG */ 734 735 return BCME_OK; 736 } 737 738 int 739 dhdsdio_bussleep(dhd_bus_t *bus, bool sleep) 740 { 741 bcmsdh_info_t *sdh = bus->sdh; 742 sdpcmd_regs_t *regs = bus->regs; 743 uint retries = 0; 744 745 DHD_INFO(("dhdsdio_bussleep: request %s (currently %s)\n", 746 (sleep ? "SLEEP" : "WAKE"), 747 (bus->sleeping ? "SLEEP" : "WAKE"))); 748 749 /* Done if we're already in the requested state */ 750 if (sleep == bus->sleeping) 751 return BCME_OK; 752 753 /* Going to sleep: set the alarm and turn off the lights... */ 754 if (sleep) { 755 /* Don't sleep if something is pending */ 756 if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq)) 757 return BCME_BUSY; 758 759 760 /* Disable SDIO interrupts (no longer interested) */ 761 bcmsdh_intr_disable(bus->sdh); 762 763 /* Make sure the controller has the bus up */ 764 dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); 765 766 /* Tell device to start using OOB wakeup */ 767 W_SDREG(SMB_USE_OOB, ®s->tosbmailbox, retries); 768 if (retries > retry_limit) 769 DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n")); 770 771 /* Turn off our contribution to the HT clock request */ 772 dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); 773 774 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 775 SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); 776 777 /* Isolate the bus */ 778 if (bus->sih->chip != BCM4329_CHIP_ID && bus->sih->chip != BCM4319_CHIP_ID) { 779 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 780 SBSDIO_DEVCTL_PADS_ISO, NULL); 781 } 782 783 /* Change state */ 784 bus->sleeping = TRUE; 785 786 } else { 787 /* Waking up: bus power up is ok, set local state */ 788 789 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 790 0, NULL); 791 792 /* Force pad isolation off if possible (in case power never toggled) */ 793 if ((bus->sih->buscoretype == PCMCIA_CORE_ID) && (bus->sih->buscorerev >= 10)) 794 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0, NULL); 795 796 797 /* Make sure the controller has the bus up */ 798 dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); 799 800 /* Send misc interrupt to indicate OOB not needed */ 801 W_SDREG(0, ®s->tosbmailboxdata, retries); 802 if (retries <= retry_limit) 803 W_SDREG(SMB_DEV_INT, ®s->tosbmailbox, retries); 804 805 if (retries > retry_limit) 806 DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n")); 807 808 /* Make sure we have SD bus access */ 809 dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); 810 811 /* Change state */ 812 bus->sleeping = FALSE; 813 814 /* Enable interrupts again */ 815 if (bus->intr && (bus->dhd->busstate == DHD_BUS_DATA)) { 816 bus->intdis = FALSE; 817 bcmsdh_intr_enable(bus->sdh); 818 } 819 } 820 821 return BCME_OK; 822 } 823 #if defined(OOB_INTR_ONLY) 824 void 825 dhd_enable_oob_intr(struct dhd_bus *bus, bool enable) 826 { 827 #if defined(HW_OOB) 828 bcmsdh_enable_hw_oob_intr(bus->sdh, enable); 829 #else 830 sdpcmd_regs_t *regs = bus->regs; 831 uint retries = 0; 832 833 dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); 834 if (enable == TRUE) { 835 836 /* Tell device to start using OOB wakeup */ 837 W_SDREG(SMB_USE_OOB, ®s->tosbmailbox, retries); 838 if (retries > retry_limit) 839 DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n")); 840 841 } else { 842 /* Send misc interrupt to indicate OOB not needed */ 843 W_SDREG(0, ®s->tosbmailboxdata, retries); 844 if (retries <= retry_limit) 845 W_SDREG(SMB_DEV_INT, ®s->tosbmailbox, retries); 846 } 847 848 /* Turn off our contribution to the HT clock request */ 849 dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); 850 #endif /* !defined(HW_OOB) */ 851 } 852 #endif /* defined(OOB_INTR_ONLY) */ 853 854 #define BUS_WAKE(bus) \ 855 do { \ 856 if ((bus)->sleeping) \ 857 dhdsdio_bussleep((bus), FALSE); \ 858 } while (0); 859 860 861 /* Writes a HW/SW header into the packet and sends it. */ 862 /* Assumes: (a) header space already there, (b) caller holds lock */ 863 static int 864 dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt) 865 { 866 int ret; 867 osl_t *osh; 868 uint8 *frame; 869 uint16 len, pad = 0; 870 uint32 swheader; 871 uint retries = 0; 872 bcmsdh_info_t *sdh; 873 void *new; 874 int i; 875 876 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 877 878 sdh = bus->sdh; 879 osh = bus->dhd->osh; 880 881 if (bus->dhd->dongle_reset) { 882 ret = BCME_NOTREADY; 883 goto done; 884 } 885 886 frame = (uint8*)PKTDATA(osh, pkt); 887 888 /* Add alignment padding, allocate new packet if needed */ 889 if ((pad = ((uintptr)frame % DHD_SDALIGN))) { 890 if (PKTHEADROOM(osh, pkt) < pad) { 891 DHD_INFO(("%s: insufficient headroom %d for %d pad\n", 892 __FUNCTION__, (int)PKTHEADROOM(osh, pkt), pad)); 893 bus->dhd->tx_realloc++; 894 new = PKTGET(osh, (PKTLEN(osh, pkt) + DHD_SDALIGN), TRUE); 895 if (!new) { 896 DHD_ERROR(("%s: couldn't allocate new %d-byte packet\n", 897 __FUNCTION__, PKTLEN(osh, pkt) + DHD_SDALIGN)); 898 ret = BCME_NOMEM; 899 goto done; 900 } 901 902 PKTALIGN(osh, new, PKTLEN(osh, pkt), DHD_SDALIGN); 903 bcopy(PKTDATA(osh, pkt), PKTDATA(osh, new), PKTLEN(osh, pkt)); 904 if (free_pkt) 905 PKTFREE(osh, pkt, TRUE); 906 /* free the pkt if canned one is not used */ 907 free_pkt = TRUE; 908 pkt = new; 909 frame = (uint8*)PKTDATA(osh, pkt); 910 ASSERT(((uintptr)frame % DHD_SDALIGN) == 0); 911 pad = 0; 912 } else { 913 PKTPUSH(osh, pkt, pad); 914 frame = (uint8*)PKTDATA(osh, pkt); 915 916 ASSERT((pad + SDPCM_HDRLEN) <= (int) PKTLEN(osh, pkt)); 917 bzero(frame, pad + SDPCM_HDRLEN); 918 } 919 } 920 ASSERT(pad < DHD_SDALIGN); 921 922 /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ 923 len = (uint16)PKTLEN(osh, pkt); 924 *(uint16*)frame = htol16(len); 925 *(((uint16*)frame) + 1) = htol16(~len); 926 927 /* Software tag: channel, sequence number, data offset */ 928 swheader = ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq | 929 (((pad + SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK); 930 htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN); 931 htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader)); 932 bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; 933 934 #ifdef DHD_DEBUG 935 tx_packets[PKTPRIO(pkt)]++; 936 if (DHD_BYTES_ON() && 937 (((DHD_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) || 938 (DHD_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) { 939 prhex("Tx Frame", frame, len); 940 } else if (DHD_HDRS_ON()) { 941 prhex("TxHdr", frame, MIN(len, 16)); 942 } 943 #endif 944 945 /* Raise len to next SDIO block to eliminate tail command */ 946 if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { 947 uint16 pad = bus->blocksize - (len % bus->blocksize); 948 if ((pad <= bus->roundup) && (pad < bus->blocksize)) 949 #ifdef NOTUSED 950 if (pad <= PKTTAILROOM(osh, pkt)) 951 #endif /* NOTUSED */ 952 len += pad; 953 } else if (len % DHD_SDALIGN) { 954 len += DHD_SDALIGN - (len % DHD_SDALIGN); 955 } 956 957 /* Some controllers have trouble with odd bytes -- round to even */ 958 if (forcealign && (len & (ALIGNMENT - 1))) { 959 #ifdef NOTUSED 960 if (PKTTAILROOM(osh, pkt)) 961 #endif 962 len = ROUNDUP(len, ALIGNMENT); 963 #ifdef NOTUSED 964 else 965 DHD_ERROR(("%s: sending unrounded %d-byte packet\n", __FUNCTION__, len)); 966 #endif 967 } 968 969 do { 970 ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, 971 frame, len, pkt, NULL, NULL); 972 bus->f2txdata++; 973 ASSERT(ret != BCME_PENDING); 974 975 if (ret < 0) { 976 /* On failure, abort the command and terminate the frame */ 977 DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n", 978 __FUNCTION__, ret)); 979 bus->tx_sderrs++; 980 981 bcmsdh_abort(sdh, SDIO_FUNC_2); 982 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, 983 SFC_WF_TERM, NULL); 984 bus->f1regdata++; 985 986 for (i = 0; i < 3; i++) { 987 uint8 hi, lo; 988 hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, 989 SBSDIO_FUNC1_WFRAMEBCHI, NULL); 990 lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, 991 SBSDIO_FUNC1_WFRAMEBCLO, NULL); 992 bus->f1regdata += 2; 993 if ((hi == 0) && (lo == 0)) 994 break; 995 } 996 997 } 998 } while ((ret < 0) && retrydata && retries++ < TXRETRIES); 999 1000 done: 1001 /* restore pkt buffer pointer before calling tx complete routine */ 1002 PKTPULL(osh, pkt, SDPCM_HDRLEN + pad); 1003 dhd_os_sdunlock(bus->dhd); 1004 dhd_txcomplete(bus->dhd, pkt, ret != 0); 1005 dhd_os_sdlock(bus->dhd); 1006 1007 if (free_pkt) 1008 PKTFREE(osh, pkt, TRUE); 1009 1010 return ret; 1011 } 1012 1013 int 1014 dhd_bus_txdata(struct dhd_bus *bus, void *pkt) 1015 { 1016 int ret = BCME_ERROR; 1017 osl_t *osh; 1018 uint datalen, prec; 1019 1020 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 1021 1022 osh = bus->dhd->osh; 1023 datalen = PKTLEN(osh, pkt); 1024 1025 #ifdef SDTEST 1026 /* Push the test header if doing loopback */ 1027 if (bus->ext_loop) { 1028 uint8* data; 1029 PKTPUSH(osh, pkt, SDPCM_TEST_HDRLEN); 1030 data = PKTDATA(osh, pkt); 1031 *data++ = SDPCM_TEST_ECHOREQ; 1032 *data++ = (uint8)bus->loopid++; 1033 *data++ = (datalen >> 0); 1034 *data++ = (datalen >> 8); 1035 datalen += SDPCM_TEST_HDRLEN; 1036 } 1037 #endif /* SDTEST */ 1038 1039 /* Add space for the header */ 1040 PKTPUSH(osh, pkt, SDPCM_HDRLEN); 1041 ASSERT(ISALIGNED((uintptr)PKTDATA(osh, pkt), 2)); 1042 1043 prec = PRIO2PREC((PKTPRIO(pkt) & PRIOMASK)); 1044 1045 1046 /* Check for existing queue, current flow-control, pending event, or pending clock */ 1047 if (dhd_deferred_tx || bus->fcstate || pktq_len(&bus->txq) || bus->dpc_sched || 1048 (!DATAOK(bus)) || (bus->flowcontrol & NBITVAL(prec)) || 1049 (bus->clkstate == CLK_PENDING)) { 1050 DHD_TRACE(("%s: deferring pktq len %d\n", __FUNCTION__, 1051 pktq_len(&bus->txq))); 1052 bus->fcqueued++; 1053 1054 /* Priority based enq */ 1055 dhd_os_sdlock_txq(bus->dhd); 1056 if (dhd_prec_enq(bus->dhd, &bus->txq, pkt, prec) == FALSE) { 1057 PKTPULL(osh, pkt, SDPCM_HDRLEN); 1058 dhd_txcomplete(bus->dhd, pkt, FALSE); 1059 PKTFREE(osh, pkt, TRUE); 1060 DHD_ERROR(("%s: out of bus->txq !!!\n", __FUNCTION__)); 1061 ret = BCME_NORESOURCE; 1062 } else { 1063 ret = BCME_OK; 1064 } 1065 dhd_os_sdunlock_txq(bus->dhd); 1066 1067 if ((pktq_len(&bus->txq) >= FCHI) && dhd_doflow) 1068 dhd_txflowcontrol(bus->dhd, 0, ON); 1069 1070 #ifdef DHD_DEBUG 1071 if (pktq_plen(&bus->txq, prec) > qcount[prec]) 1072 qcount[prec] = pktq_plen(&bus->txq, prec); 1073 #endif 1074 /* Schedule DPC if needed to send queued packet(s) */ 1075 if (dhd_deferred_tx && !bus->dpc_sched) { 1076 bus->dpc_sched = TRUE; 1077 dhd_sched_dpc(bus->dhd); 1078 } 1079 } else { 1080 /* Lock: we're about to use shared data/code (and SDIO) */ 1081 dhd_os_sdlock(bus->dhd); 1082 1083 /* Otherwise, send it now */ 1084 BUS_WAKE(bus); 1085 dhdsdio_clkctl(bus, CLK_AVAIL, TRUE); 1086 1087 #ifndef SDTEST 1088 DHD_TRACE(("%s: calling txpkt\n", __FUNCTION__)); 1089 ret = dhdsdio_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, TRUE); 1090 #else 1091 ret = dhdsdio_txpkt(bus, pkt, 1092 (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL), TRUE); 1093 #endif 1094 if (ret) 1095 bus->dhd->tx_errors++; 1096 else 1097 bus->dhd->dstats.tx_bytes += datalen; 1098 1099 if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) { 1100 bus->activity = FALSE; 1101 dhdsdio_clkctl(bus, CLK_NONE, TRUE); 1102 } 1103 1104 dhd_os_sdunlock(bus->dhd); 1105 } 1106 1107 1108 return ret; 1109 } 1110 1111 static uint 1112 dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes) 1113 { 1114 void *pkt; 1115 uint32 intstatus = 0; 1116 uint retries = 0; 1117 int ret = 0, prec_out; 1118 uint cnt = 0; 1119 uint datalen; 1120 uint8 tx_prec_map; 1121 1122 dhd_pub_t *dhd = bus->dhd; 1123 sdpcmd_regs_t *regs = bus->regs; 1124 1125 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 1126 1127 tx_prec_map = ~bus->flowcontrol; 1128 1129 /* Send frames until the limit or some other event */ 1130 for (cnt = 0; (cnt < maxframes) && DATAOK(bus); cnt++) { 1131 dhd_os_sdlock_txq(bus->dhd); 1132 if ((pkt = pktq_mdeq(&bus->txq, tx_prec_map, &prec_out)) == NULL) { 1133 dhd_os_sdunlock_txq(bus->dhd); 1134 break; 1135 } 1136 dhd_os_sdunlock_txq(bus->dhd); 1137 datalen = PKTLEN(bus->dhd->osh, pkt) - SDPCM_HDRLEN; 1138 1139 #ifndef SDTEST 1140 ret = dhdsdio_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, TRUE); 1141 #else 1142 ret = dhdsdio_txpkt(bus, pkt, 1143 (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL), TRUE); 1144 #endif 1145 if (ret) 1146 bus->dhd->tx_errors++; 1147 else 1148 bus->dhd->dstats.tx_bytes += datalen; 1149 1150 /* In poll mode, need to check for other events */ 1151 if (!bus->intr && cnt) 1152 { 1153 /* Check device status, signal pending interrupt */ 1154 R_SDREG(intstatus, ®s->intstatus, retries); 1155 bus->f2txdata++; 1156 if (bcmsdh_regfail(bus->sdh)) 1157 break; 1158 if (intstatus & bus->hostintmask) 1159 bus->ipend = TRUE; 1160 } 1161 } 1162 1163 /* Deflow-control stack if needed */ 1164 if (dhd_doflow && dhd->up && (dhd->busstate == DHD_BUS_DATA) && 1165 dhd->txoff && (pktq_len(&bus->txq) < FCLOW)) 1166 dhd_txflowcontrol(dhd, 0, OFF); 1167 1168 return cnt; 1169 } 1170 1171 int 1172 dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) 1173 { 1174 uint8 *frame; 1175 uint16 len; 1176 uint32 swheader; 1177 uint retries = 0; 1178 bcmsdh_info_t *sdh = bus->sdh; 1179 uint8 doff = 0; 1180 int ret = -1; 1181 int i; 1182 1183 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 1184 1185 if (bus->dhd->dongle_reset) 1186 return -EIO; 1187 1188 /* Back the pointer to make a room for bus header */ 1189 frame = msg - SDPCM_HDRLEN; 1190 len = (msglen += SDPCM_HDRLEN); 1191 1192 /* Add alignment padding (optional for ctl frames) */ 1193 if (dhd_alignctl) { 1194 if ((doff = ((uintptr)frame % DHD_SDALIGN))) { 1195 frame -= doff; 1196 len += doff; 1197 msglen += doff; 1198 bzero(frame, doff + SDPCM_HDRLEN); 1199 } 1200 ASSERT(doff < DHD_SDALIGN); 1201 } 1202 doff += SDPCM_HDRLEN; 1203 1204 /* Round send length to next SDIO block */ 1205 if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { 1206 uint16 pad = bus->blocksize - (len % bus->blocksize); 1207 if ((pad <= bus->roundup) && (pad < bus->blocksize)) 1208 len += pad; 1209 } else if (len % DHD_SDALIGN) { 1210 len += DHD_SDALIGN - (len % DHD_SDALIGN); 1211 } 1212 1213 /* Satisfy length-alignment requirements */ 1214 if (forcealign && (len & (ALIGNMENT - 1))) 1215 len = ROUNDUP(len, ALIGNMENT); 1216 1217 ASSERT(ISALIGNED((uintptr)frame, 2)); 1218 1219 1220 /* Need to lock here to protect txseq and SDIO tx calls */ 1221 dhd_os_sdlock(bus->dhd); 1222 1223 BUS_WAKE(bus); 1224 1225 /* Make sure backplane clock is on */ 1226 dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); 1227 1228 /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ 1229 *(uint16*)frame = htol16((uint16)msglen); 1230 *(((uint16*)frame) + 1) = htol16(~msglen); 1231 1232 /* Software tag: channel, sequence number, data offset */ 1233 swheader = ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) 1234 | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK); 1235 htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN); 1236 htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader)); 1237 1238 if (!DATAOK(bus)) { 1239 bus->ctrl_frame_stat = TRUE; 1240 /* Send from dpc */ 1241 bus->ctrl_frame_buf = frame; 1242 bus->ctrl_frame_len = len; 1243 1244 dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat); 1245 1246 if (bus->ctrl_frame_stat == FALSE) 1247 ret = 0; 1248 else 1249 ret = -1; 1250 } 1251 1252 if (ret == -1) { 1253 bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; 1254 1255 #ifdef DHD_DEBUG 1256 if (DHD_BYTES_ON() && DHD_CTL_ON()) { 1257 prhex("Tx Frame", frame, len); 1258 } else if (DHD_HDRS_ON()) { 1259 prhex("TxHdr", frame, MIN(len, 16)); 1260 } 1261 #endif 1262 1263 do { 1264 ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, 1265 frame, len, NULL, NULL, NULL); 1266 ASSERT(ret != BCME_PENDING); 1267 1268 if (ret < 0) { 1269 /* On failure, abort the command and terminate the frame */ 1270 DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n", 1271 __FUNCTION__, ret)); 1272 bus->tx_sderrs++; 1273 1274 bcmsdh_abort(sdh, SDIO_FUNC_2); 1275 1276 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, 1277 SFC_WF_TERM, NULL); 1278 bus->f1regdata++; 1279 1280 for (i = 0; i < 3; i++) { 1281 uint8 hi, lo; 1282 hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, 1283 SBSDIO_FUNC1_WFRAMEBCHI, NULL); 1284 lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, 1285 SBSDIO_FUNC1_WFRAMEBCLO, NULL); 1286 bus->f1regdata += 2; 1287 if ((hi == 0) && (lo == 0)) 1288 break; 1289 } 1290 1291 } 1292 } while ((ret < 0) && retries++ < TXRETRIES); 1293 } 1294 1295 if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) { 1296 bus->activity = FALSE; 1297 dhdsdio_clkctl(bus, CLK_NONE, TRUE); 1298 } 1299 1300 dhd_os_sdunlock(bus->dhd); 1301 1302 if (ret) 1303 bus->dhd->tx_ctlerrs++; 1304 else 1305 bus->dhd->tx_ctlpkts++; 1306 1307 return ret ? -EIO : 0; 1308 } 1309 1310 int 1311 dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen) 1312 { 1313 int timeleft; 1314 uint rxlen = 0; 1315 bool pending; 1316 1317 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 1318 1319 if (bus->dhd->dongle_reset) 1320 return -EIO; 1321 1322 /* Wait until control frame is available */ 1323 timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen, &pending); 1324 1325 dhd_os_sdlock(bus->dhd); 1326 rxlen = bus->rxlen; 1327 bcopy(bus->rxctl, msg, MIN(msglen, rxlen)); 1328 bus->rxlen = 0; 1329 dhd_os_sdunlock(bus->dhd); 1330 1331 if (rxlen) { 1332 DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n", 1333 __FUNCTION__, rxlen, msglen)); 1334 } else if (timeleft == 0) { 1335 DHD_ERROR(("%s: resumed on timeout\n", __FUNCTION__)); 1336 } else if (pending == TRUE) { 1337 DHD_CTL(("%s: cancelled\n", __FUNCTION__)); 1338 return -ERESTARTSYS; 1339 } else { 1340 DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__)); 1341 } 1342 1343 if (rxlen) 1344 bus->dhd->rx_ctlpkts++; 1345 else 1346 bus->dhd->rx_ctlerrs++; 1347 1348 return rxlen ? (int)rxlen : -ETIMEDOUT; 1349 } 1350 1351 /* IOVar table */ 1352 enum { 1353 IOV_INTR = 1, 1354 IOV_POLLRATE, 1355 IOV_SDREG, 1356 IOV_SBREG, 1357 IOV_SDCIS, 1358 IOV_MEMBYTES, 1359 IOV_MEMSIZE, 1360 IOV_DOWNLOAD, 1361 IOV_FORCEEVEN, 1362 IOV_SDIOD_DRIVE, 1363 IOV_READAHEAD, 1364 IOV_SDRXCHAIN, 1365 IOV_ALIGNCTL, 1366 IOV_SDALIGN, 1367 IOV_DEVRESET, 1368 IOV_CPU, 1369 #ifdef SDTEST 1370 IOV_PKTGEN, 1371 IOV_EXTLOOP, 1372 #endif /* SDTEST */ 1373 IOV_SPROM, 1374 IOV_TXBOUND, 1375 IOV_RXBOUND, 1376 IOV_TXMINMAX, 1377 IOV_IDLETIME, 1378 IOV_IDLECLOCK, 1379 IOV_SD1IDLE, 1380 IOV_SLEEP, 1381 IOV_VARS 1382 }; 1383 1384 const bcm_iovar_t dhdsdio_iovars[] = { 1385 {"intr", IOV_INTR, 0, IOVT_BOOL, 0 }, 1386 {"sleep", IOV_SLEEP, 0, IOVT_BOOL, 0 }, 1387 {"pollrate", IOV_POLLRATE, 0, IOVT_UINT32, 0 }, 1388 {"idletime", IOV_IDLETIME, 0, IOVT_INT32, 0 }, 1389 {"idleclock", IOV_IDLECLOCK, 0, IOVT_INT32, 0 }, 1390 {"sd1idle", IOV_SD1IDLE, 0, IOVT_BOOL, 0 }, 1391 {"membytes", IOV_MEMBYTES, 0, IOVT_BUFFER, 2 * sizeof(int) }, 1392 {"memsize", IOV_MEMSIZE, 0, IOVT_UINT32, 0 }, 1393 {"download", IOV_DOWNLOAD, 0, IOVT_BOOL, 0 }, 1394 {"vars", IOV_VARS, 0, IOVT_BUFFER, 0 }, 1395 {"sdiod_drive", IOV_SDIOD_DRIVE, 0, IOVT_UINT32, 0 }, 1396 {"readahead", IOV_READAHEAD, 0, IOVT_BOOL, 0 }, 1397 {"sdrxchain", IOV_SDRXCHAIN, 0, IOVT_BOOL, 0 }, 1398 {"alignctl", IOV_ALIGNCTL, 0, IOVT_BOOL, 0 }, 1399 {"sdalign", IOV_SDALIGN, 0, IOVT_BOOL, 0 }, 1400 {"devreset", IOV_DEVRESET, 0, IOVT_BOOL, 0 }, 1401 #ifdef DHD_DEBUG 1402 {"sdreg", IOV_SDREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, 1403 {"sbreg", IOV_SBREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, 1404 {"sd_cis", IOV_SDCIS, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN }, 1405 {"forcealign", IOV_FORCEEVEN, 0, IOVT_BOOL, 0 }, 1406 {"txbound", IOV_TXBOUND, 0, IOVT_UINT32, 0 }, 1407 {"rxbound", IOV_RXBOUND, 0, IOVT_UINT32, 0 }, 1408 {"txminmax", IOV_TXMINMAX, 0, IOVT_UINT32, 0 }, 1409 {"cpu", IOV_CPU, 0, IOVT_BOOL, 0 }, 1410 #endif /* DHD_DEBUG */ 1411 #ifdef SDTEST 1412 {"extloop", IOV_EXTLOOP, 0, IOVT_BOOL, 0 }, 1413 {"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(dhd_pktgen_t) }, 1414 #endif /* SDTEST */ 1415 1416 {NULL, 0, 0, 0, 0 } 1417 }; 1418 1419 static void 1420 dhd_dump_pct(struct bcmstrbuf *strbuf, char *desc, uint num, uint div) 1421 { 1422 uint q1, q2; 1423 1424 if (!div) { 1425 bcm_bprintf(strbuf, "%s N/A", desc); 1426 } else { 1427 q1 = num / div; 1428 q2 = (100 * (num - (q1 * div))) / div; 1429 bcm_bprintf(strbuf, "%s %d.%02d", desc, q1, q2); 1430 } 1431 } 1432 1433 void 1434 dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) 1435 { 1436 dhd_bus_t *bus = dhdp->bus; 1437 1438 bcm_bprintf(strbuf, "Bus SDIO structure:\n"); 1439 bcm_bprintf(strbuf, "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n", 1440 bus->hostintmask, bus->intstatus, bus->sdpcm_ver); 1441 bcm_bprintf(strbuf, "fcstate %d qlen %d tx_seq %d, max %d, rxskip %d rxlen %d rx_seq %d\n", 1442 bus->fcstate, pktq_len(&bus->txq), bus->tx_seq, bus->tx_max, bus->rxskip, 1443 bus->rxlen, bus->rx_seq); 1444 bcm_bprintf(strbuf, "intr %d intrcount %d lastintrs %d spurious %d\n", 1445 bus->intr, bus->intrcount, bus->lastintrs, bus->spurious); 1446 bcm_bprintf(strbuf, "pollrate %d pollcnt %d regfails %d\n", 1447 bus->pollrate, bus->pollcnt, bus->regfails); 1448 1449 bcm_bprintf(strbuf, "\nAdditional counters:\n"); 1450 bcm_bprintf(strbuf, "tx_sderrs %d fcqueued %d rxrtx %d rx_toolong %d rxc_errors %d\n", 1451 bus->tx_sderrs, bus->fcqueued, bus->rxrtx, bus->rx_toolong, 1452 bus->rxc_errors); 1453 bcm_bprintf(strbuf, "rx_hdrfail %d badhdr %d badseq %d\n", 1454 bus->rx_hdrfail, bus->rx_badhdr, bus->rx_badseq); 1455 bcm_bprintf(strbuf, "fc_rcvd %d, fc_xoff %d, fc_xon %d\n", 1456 bus->fc_rcvd, bus->fc_xoff, bus->fc_xon); 1457 bcm_bprintf(strbuf, "rxglomfail %d, rxglomframes %d, rxglompkts %d\n", 1458 bus->rxglomfail, bus->rxglomframes, bus->rxglompkts); 1459 bcm_bprintf(strbuf, "f2rx (hdrs/data) %d (%d/%d), f2tx %d f1regs %d\n", 1460 (bus->f2rxhdrs + bus->f2rxdata), bus->f2rxhdrs, bus->f2rxdata, 1461 bus->f2txdata, bus->f1regdata); 1462 { 1463 dhd_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->dhd->rx_packets, 1464 (bus->f2rxhdrs + bus->f2rxdata)); 1465 dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->rx_packets, bus->f1regdata); 1466 dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->rx_packets, 1467 (bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata)); 1468 dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->rx_packets, bus->intrcount); 1469 bcm_bprintf(strbuf, "\n"); 1470 1471 dhd_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts), 1472 bus->dhd->rx_packets); 1473 dhd_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts, bus->rxglomframes); 1474 bcm_bprintf(strbuf, "\n"); 1475 1476 dhd_dump_pct(strbuf, "Tx: pkts/f2wr", bus->dhd->tx_packets, bus->f2txdata); 1477 dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->tx_packets, bus->f1regdata); 1478 dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->tx_packets, 1479 (bus->f2txdata + bus->f1regdata)); 1480 dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->tx_packets, bus->intrcount); 1481 bcm_bprintf(strbuf, "\n"); 1482 1483 dhd_dump_pct(strbuf, "Total: pkts/f2rw", 1484 (bus->dhd->tx_packets + bus->dhd->rx_packets), 1485 (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata)); 1486 dhd_dump_pct(strbuf, ", pkts/f1sd", 1487 (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->f1regdata); 1488 dhd_dump_pct(strbuf, ", pkts/sd", 1489 (bus->dhd->tx_packets + bus->dhd->rx_packets), 1490 (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata)); 1491 dhd_dump_pct(strbuf, ", pkts/int", 1492 (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->intrcount); 1493 bcm_bprintf(strbuf, "\n\n"); 1494 } 1495 1496 #ifdef SDTEST 1497 if (bus->pktgen_count) { 1498 bcm_bprintf(strbuf, "pktgen config and count:\n"); 1499 bcm_bprintf(strbuf, "freq %d count %d print %d total %d min %d len %d\n", 1500 bus->pktgen_freq, bus->pktgen_count, bus->pktgen_print, 1501 bus->pktgen_total, bus->pktgen_minlen, bus->pktgen_maxlen); 1502 bcm_bprintf(strbuf, "send attempts %d rcvd %d fail %d\n", 1503 bus->pktgen_sent, bus->pktgen_rcvd, bus->pktgen_fail); 1504 } 1505 #endif /* SDTEST */ 1506 #ifdef DHD_DEBUG 1507 bcm_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n", 1508 bus->dpc_sched, (bcmsdh_intr_pending(bus->sdh) ? " " : " not ")); 1509 bcm_bprintf(strbuf, "blocksize %d roundup %d\n", bus->blocksize, bus->roundup); 1510 #endif /* DHD_DEBUG */ 1511 bcm_bprintf(strbuf, "clkstate %d activity %d idletime %d idlecount %d sleeping %d\n", 1512 bus->clkstate, bus->activity, bus->idletime, bus->idlecount, bus->sleeping); 1513 } 1514 1515 void 1516 dhd_bus_clearcounts(dhd_pub_t *dhdp) 1517 { 1518 dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus; 1519 1520 bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0; 1521 bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0; 1522 bus->rx_hdrfail = bus->rx_badhdr = bus->rx_badseq = 0; 1523 bus->tx_sderrs = bus->fc_rcvd = bus->fc_xoff = bus->fc_xon = 0; 1524 bus->rxglomfail = bus->rxglomframes = bus->rxglompkts = 0; 1525 bus->f2rxhdrs = bus->f2rxdata = bus->f2txdata = bus->f1regdata = 0; 1526 } 1527 1528 #ifdef SDTEST 1529 static int 1530 dhdsdio_pktgen_get(dhd_bus_t *bus, uint8 *arg) 1531 { 1532 dhd_pktgen_t pktgen; 1533 1534 pktgen.version = DHD_PKTGEN_VERSION; 1535 pktgen.freq = bus->pktgen_freq; 1536 pktgen.count = bus->pktgen_count; 1537 pktgen.print = bus->pktgen_print; 1538 pktgen.total = bus->pktgen_total; 1539 pktgen.minlen = bus->pktgen_minlen; 1540 pktgen.maxlen = bus->pktgen_maxlen; 1541 pktgen.numsent = bus->pktgen_sent; 1542 pktgen.numrcvd = bus->pktgen_rcvd; 1543 pktgen.numfail = bus->pktgen_fail; 1544 pktgen.mode = bus->pktgen_mode; 1545 pktgen.stop = bus->pktgen_stop; 1546 1547 bcopy(&pktgen, arg, sizeof(pktgen)); 1548 1549 return 0; 1550 } 1551 1552 static int 1553 dhdsdio_pktgen_set(dhd_bus_t *bus, uint8 *arg) 1554 { 1555 dhd_pktgen_t pktgen; 1556 uint oldcnt, oldmode; 1557 1558 bcopy(arg, &pktgen, sizeof(pktgen)); 1559 if (pktgen.version != DHD_PKTGEN_VERSION) 1560 return BCME_BADARG; 1561 1562 oldcnt = bus->pktgen_count; 1563 oldmode = bus->pktgen_mode; 1564 1565 bus->pktgen_freq = pktgen.freq; 1566 bus->pktgen_count = pktgen.count; 1567 bus->pktgen_print = pktgen.print; 1568 bus->pktgen_total = pktgen.total; 1569 bus->pktgen_minlen = pktgen.minlen; 1570 bus->pktgen_maxlen = pktgen.maxlen; 1571 bus->pktgen_mode = pktgen.mode; 1572 bus->pktgen_stop = pktgen.stop; 1573 1574 bus->pktgen_tick = bus->pktgen_ptick = 0; 1575 bus->pktgen_len = MAX(bus->pktgen_len, bus->pktgen_minlen); 1576 bus->pktgen_len = MIN(bus->pktgen_len, bus->pktgen_maxlen); 1577 1578 /* Clear counts for a new pktgen (mode change, or was stopped) */ 1579 if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode)) 1580 bus->pktgen_sent = bus->pktgen_rcvd = bus->pktgen_fail = 0; 1581 1582 return 0; 1583 } 1584 #endif /* SDTEST */ 1585 1586 static int 1587 dhdsdio_membytes(dhd_bus_t *bus, bool write, uint32 address, uint8 *data, uint size) 1588 { 1589 int bcmerror = 0; 1590 uint32 sdaddr; 1591 uint dsize; 1592 1593 /* Determine initial transfer parameters */ 1594 sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK; 1595 if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK) 1596 dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr); 1597 else 1598 dsize = size; 1599 1600 /* Set the backplane window to include the start address */ 1601 if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) { 1602 DHD_ERROR(("%s: window change failed\n", __FUNCTION__)); 1603 goto xfer_done; 1604 } 1605 1606 /* Do the transfer(s) */ 1607 while (size) { 1608 DHD_INFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n", 1609 __FUNCTION__, (write ? "write" : "read"), dsize, sdaddr, 1610 (address & SBSDIO_SBWINDOW_MASK))); 1611 if ((bcmerror = bcmsdh_rwdata(bus->sdh, write, sdaddr, data, dsize))) { 1612 DHD_ERROR(("%s: membytes transfer failed\n", __FUNCTION__)); 1613 break; 1614 } 1615 1616 /* Adjust for next transfer (if any) */ 1617 if ((size -= dsize)) { 1618 data += dsize; 1619 address += dsize; 1620 if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) { 1621 DHD_ERROR(("%s: window change failed\n", __FUNCTION__)); 1622 break; 1623 } 1624 sdaddr = 0; 1625 dsize = MIN(SBSDIO_SB_OFT_ADDR_LIMIT, size); 1626 } 1627 } 1628 1629 xfer_done: 1630 /* Return the window to backplane enumeration space for core access */ 1631 if (dhdsdio_set_siaddr_window(bus, bcmsdh_cur_sbwad(bus->sdh))) { 1632 DHD_ERROR(("%s: FAILED to set window back to 0x%x\n", __FUNCTION__, 1633 bcmsdh_cur_sbwad(bus->sdh))); 1634 } 1635 1636 return bcmerror; 1637 } 1638 1639 1640 int 1641 dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len) 1642 { 1643 int bcmerror = BCME_OK; 1644 1645 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 1646 1647 /* Basic sanity checks */ 1648 if (bus->dhd->up) { 1649 bcmerror = BCME_NOTDOWN; 1650 goto err; 1651 } 1652 if (!len) { 1653 bcmerror = BCME_BUFTOOSHORT; 1654 goto err; 1655 } 1656 1657 /* Free the old ones and replace with passed variables */ 1658 if (bus->vars) 1659 MFREE(bus->dhd->osh, bus->vars, bus->varsz); 1660 1661 bus->vars = MALLOC(bus->dhd->osh, len); 1662 bus->varsz = bus->vars ? len : 0; 1663 if (bus->vars == NULL) { 1664 bcmerror = BCME_NOMEM; 1665 goto err; 1666 } 1667 1668 /* Copy the passed variables, which should include the terminating double-null */ 1669 bcopy(arg, bus->vars, bus->varsz); 1670 err: 1671 return bcmerror; 1672 } 1673 1674 static int 1675 dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name, 1676 void *params, int plen, void *arg, int len, int val_size) 1677 { 1678 int bcmerror = 0; 1679 int32 int_val = 0; 1680 bool bool_val = 0; 1681 1682 DHD_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n", 1683 __FUNCTION__, actionid, name, params, plen, arg, len, val_size)); 1684 1685 if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0) 1686 goto exit; 1687 1688 if (plen >= (int)sizeof(int_val)) 1689 bcopy(params, &int_val, sizeof(int_val)); 1690 1691 bool_val = (int_val != 0) ? TRUE : FALSE; 1692 1693 1694 /* Some ioctls use the bus */ 1695 dhd_os_sdlock(bus->dhd); 1696 1697 /* Check if dongle is in reset. If so, only allow DEVRESET iovars */ 1698 if (bus->dhd->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) || 1699 actionid == IOV_GVAL(IOV_DEVRESET))) { 1700 bcmerror = BCME_NOTREADY; 1701 goto exit; 1702 } 1703 1704 /* Handle sleep stuff before any clock mucking */ 1705 if (vi->varid == IOV_SLEEP) { 1706 if (IOV_ISSET(actionid)) { 1707 bcmerror = dhdsdio_bussleep(bus, bool_val); 1708 } else { 1709 int_val = (int32)bus->sleeping; 1710 bcopy(&int_val, arg, val_size); 1711 } 1712 goto exit; 1713 } 1714 1715 /* Request clock to allow SDIO accesses */ 1716 if (!bus->dhd->dongle_reset) { 1717 BUS_WAKE(bus); 1718 dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); 1719 } 1720 1721 switch (actionid) { 1722 case IOV_GVAL(IOV_INTR): 1723 int_val = (int32)bus->intr; 1724 bcopy(&int_val, arg, val_size); 1725 break; 1726 1727 case IOV_SVAL(IOV_INTR): 1728 bus->intr = bool_val; 1729 bus->intdis = FALSE; 1730 if (bus->dhd->up) { 1731 if (bus->intr) { 1732 DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__)); 1733 bcmsdh_intr_enable(bus->sdh); 1734 } else { 1735 DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); 1736 bcmsdh_intr_disable(bus->sdh); 1737 } 1738 } 1739 break; 1740 1741 case IOV_GVAL(IOV_POLLRATE): 1742 int_val = (int32)bus->pollrate; 1743 bcopy(&int_val, arg, val_size); 1744 break; 1745 1746 case IOV_SVAL(IOV_POLLRATE): 1747 bus->pollrate = (uint)int_val; 1748 bus->poll = (bus->pollrate != 0); 1749 break; 1750 1751 case IOV_GVAL(IOV_IDLETIME): 1752 int_val = bus->idletime; 1753 bcopy(&int_val, arg, val_size); 1754 break; 1755 1756 case IOV_SVAL(IOV_IDLETIME): 1757 if ((int_val < 0) && (int_val != DHD_IDLE_IMMEDIATE)) { 1758 bcmerror = BCME_BADARG; 1759 } else { 1760 bus->idletime = int_val; 1761 } 1762 break; 1763 1764 case IOV_GVAL(IOV_IDLECLOCK): 1765 int_val = (int32)bus->idleclock; 1766 bcopy(&int_val, arg, val_size); 1767 break; 1768 1769 case IOV_SVAL(IOV_IDLECLOCK): 1770 bus->idleclock = int_val; 1771 break; 1772 1773 case IOV_GVAL(IOV_SD1IDLE): 1774 int_val = (int32)sd1idle; 1775 bcopy(&int_val, arg, val_size); 1776 break; 1777 1778 case IOV_SVAL(IOV_SD1IDLE): 1779 sd1idle = bool_val; 1780 break; 1781 1782 1783 case IOV_SVAL(IOV_MEMBYTES): 1784 case IOV_GVAL(IOV_MEMBYTES): 1785 { 1786 uint32 address; 1787 uint size, dsize; 1788 uint8 *data; 1789 1790 bool set = (actionid == IOV_SVAL(IOV_MEMBYTES)); 1791 1792 ASSERT(plen >= 2*sizeof(int)); 1793 1794 address = (uint32)int_val; 1795 bcopy((char *)params + sizeof(int_val), &int_val, sizeof(int_val)); 1796 size = (uint)int_val; 1797 1798 /* Do some validation */ 1799 dsize = set ? plen - (2 * sizeof(int)) : len; 1800 if (dsize < size) { 1801 DHD_ERROR(("%s: error on %s membytes, addr 0x%08x size %d dsize %d\n", 1802 __FUNCTION__, (set ? "set" : "get"), address, size, dsize)); 1803 bcmerror = BCME_BADARG; 1804 break; 1805 } 1806 1807 DHD_INFO(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__, 1808 (set ? "write" : "read"), size, address)); 1809 1810 /* If we know about SOCRAM, check for a fit */ 1811 if ((bus->orig_ramsize) && 1812 ((address > bus->orig_ramsize) || (address + size > bus->orig_ramsize))) { 1813 DHD_ERROR(("%s: ramsize 0x%08x doesn't have %d bytes at 0x%08x\n", 1814 __FUNCTION__, bus->orig_ramsize, size, address)); 1815 bcmerror = BCME_BADARG; 1816 break; 1817 } 1818 1819 /* Generate the actual data pointer */ 1820 data = set ? (uint8*)params + 2 * sizeof(int): (uint8*)arg; 1821 1822 /* Call to do the transfer */ 1823 bcmerror = dhdsdio_membytes(bus, set, address, data, size); 1824 1825 break; 1826 } 1827 1828 case IOV_GVAL(IOV_MEMSIZE): 1829 int_val = (int32)bus->ramsize; 1830 bcopy(&int_val, arg, val_size); 1831 break; 1832 1833 case IOV_GVAL(IOV_SDIOD_DRIVE): 1834 int_val = (int32)dhd_sdiod_drive_strength; 1835 bcopy(&int_val, arg, val_size); 1836 break; 1837 1838 case IOV_SVAL(IOV_SDIOD_DRIVE): 1839 dhd_sdiod_drive_strength = int_val; 1840 si_sdiod_drive_strength_init(bus->sih, bus->dhd->osh, dhd_sdiod_drive_strength); 1841 break; 1842 1843 case IOV_SVAL(IOV_DOWNLOAD): 1844 bcmerror = dhdsdio_download_state(bus, bool_val); 1845 break; 1846 1847 case IOV_SVAL(IOV_VARS): 1848 bcmerror = dhdsdio_downloadvars(bus, arg, len); 1849 break; 1850 1851 case IOV_GVAL(IOV_READAHEAD): 1852 int_val = (int32)dhd_readahead; 1853 bcopy(&int_val, arg, val_size); 1854 break; 1855 1856 case IOV_SVAL(IOV_READAHEAD): 1857 if (bool_val && !dhd_readahead) 1858 bus->nextlen = 0; 1859 dhd_readahead = bool_val; 1860 break; 1861 1862 case IOV_GVAL(IOV_SDRXCHAIN): 1863 int_val = (int32)bus->use_rxchain; 1864 bcopy(&int_val, arg, val_size); 1865 break; 1866 1867 case IOV_SVAL(IOV_SDRXCHAIN): 1868 if (bool_val && !bus->sd_rxchain) 1869 bcmerror = BCME_UNSUPPORTED; 1870 else 1871 bus->use_rxchain = bool_val; 1872 break; 1873 case IOV_GVAL(IOV_ALIGNCTL): 1874 int_val = (int32)dhd_alignctl; 1875 bcopy(&int_val, arg, val_size); 1876 break; 1877 1878 case IOV_SVAL(IOV_ALIGNCTL): 1879 dhd_alignctl = bool_val; 1880 break; 1881 1882 case IOV_GVAL(IOV_SDALIGN): 1883 int_val = DHD_SDALIGN; 1884 bcopy(&int_val, arg, val_size); 1885 break; 1886 1887 #ifdef DHD_DEBUG 1888 case IOV_GVAL(IOV_VARS): 1889 if (bus->varsz < (uint)len) 1890 bcopy(bus->vars, arg, bus->varsz); 1891 else 1892 bcmerror = BCME_BUFTOOSHORT; 1893 break; 1894 #endif /* DHD_DEBUG */ 1895 1896 #ifdef DHD_DEBUG 1897 case IOV_GVAL(IOV_SDREG): 1898 { 1899 sdreg_t *sd_ptr; 1900 uint32 addr, size; 1901 1902 sd_ptr = (sdreg_t *)params; 1903 1904 addr = (uintptr)bus->regs + sd_ptr->offset; 1905 size = sd_ptr->func; 1906 int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size); 1907 if (bcmsdh_regfail(bus->sdh)) 1908 bcmerror = BCME_SDIO_ERROR; 1909 bcopy(&int_val, arg, sizeof(int32)); 1910 break; 1911 } 1912 1913 case IOV_SVAL(IOV_SDREG): 1914 { 1915 sdreg_t *sd_ptr; 1916 uint32 addr, size; 1917 1918 sd_ptr = (sdreg_t *)params; 1919 1920 addr = (uintptr)bus->regs + sd_ptr->offset; 1921 size = sd_ptr->func; 1922 bcmsdh_reg_write(bus->sdh, addr, size, sd_ptr->value); 1923 if (bcmsdh_regfail(bus->sdh)) 1924 bcmerror = BCME_SDIO_ERROR; 1925 break; 1926 } 1927 1928 /* Same as above, but offset is not backplane (not SDIO core) */ 1929 case IOV_GVAL(IOV_SBREG): 1930 { 1931 sdreg_t sdreg; 1932 uint32 addr, size; 1933 1934 bcopy(params, &sdreg, sizeof(sdreg)); 1935 1936 addr = SI_ENUM_BASE + sdreg.offset; 1937 size = sdreg.func; 1938 int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size); 1939 if (bcmsdh_regfail(bus->sdh)) 1940 bcmerror = BCME_SDIO_ERROR; 1941 bcopy(&int_val, arg, sizeof(int32)); 1942 break; 1943 } 1944 1945 case IOV_SVAL(IOV_SBREG): 1946 { 1947 sdreg_t sdreg; 1948 uint32 addr, size; 1949 1950 bcopy(params, &sdreg, sizeof(sdreg)); 1951 1952 addr = SI_ENUM_BASE + sdreg.offset; 1953 size = sdreg.func; 1954 bcmsdh_reg_write(bus->sdh, addr, size, sdreg.value); 1955 if (bcmsdh_regfail(bus->sdh)) 1956 bcmerror = BCME_SDIO_ERROR; 1957 break; 1958 } 1959 1960 case IOV_GVAL(IOV_SDCIS): 1961 { 1962 *(char *)arg = 0; 1963 1964 bcmstrcat(arg, "\nFunc 0\n"); 1965 bcmsdh_cis_read(bus->sdh, 0x10, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT); 1966 bcmstrcat(arg, "\nFunc 1\n"); 1967 bcmsdh_cis_read(bus->sdh, 0x11, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT); 1968 bcmstrcat(arg, "\nFunc 2\n"); 1969 bcmsdh_cis_read(bus->sdh, 0x12, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT); 1970 break; 1971 } 1972 1973 case IOV_GVAL(IOV_FORCEEVEN): 1974 int_val = (int32)forcealign; 1975 bcopy(&int_val, arg, val_size); 1976 break; 1977 1978 case IOV_SVAL(IOV_FORCEEVEN): 1979 forcealign = bool_val; 1980 break; 1981 1982 case IOV_GVAL(IOV_TXBOUND): 1983 int_val = (int32)dhd_txbound; 1984 bcopy(&int_val, arg, val_size); 1985 break; 1986 1987 case IOV_SVAL(IOV_TXBOUND): 1988 dhd_txbound = (uint)int_val; 1989 break; 1990 1991 case IOV_GVAL(IOV_RXBOUND): 1992 int_val = (int32)dhd_rxbound; 1993 bcopy(&int_val, arg, val_size); 1994 break; 1995 1996 case IOV_SVAL(IOV_RXBOUND): 1997 dhd_rxbound = (uint)int_val; 1998 break; 1999 2000 case IOV_GVAL(IOV_TXMINMAX): 2001 int_val = (int32)dhd_txminmax; 2002 bcopy(&int_val, arg, val_size); 2003 break; 2004 2005 case IOV_SVAL(IOV_TXMINMAX): 2006 dhd_txminmax = (uint)int_val; 2007 break; 2008 2009 2010 2011 #endif /* DHD_DEBUG */ 2012 2013 2014 #ifdef SDTEST 2015 case IOV_GVAL(IOV_EXTLOOP): 2016 int_val = (int32)bus->ext_loop; 2017 bcopy(&int_val, arg, val_size); 2018 break; 2019 2020 case IOV_SVAL(IOV_EXTLOOP): 2021 bus->ext_loop = bool_val; 2022 break; 2023 2024 case IOV_GVAL(IOV_PKTGEN): 2025 bcmerror = dhdsdio_pktgen_get(bus, arg); 2026 break; 2027 2028 case IOV_SVAL(IOV_PKTGEN): 2029 bcmerror = dhdsdio_pktgen_set(bus, arg); 2030 break; 2031 #endif /* SDTEST */ 2032 2033 2034 case IOV_SVAL(IOV_DEVRESET): 2035 DHD_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d busstate=%d\n", 2036 __FUNCTION__, bool_val, bus->dhd->dongle_reset, 2037 bus->dhd->busstate)); 2038 2039 ASSERT(bus->dhd->osh); 2040 /* ASSERT(bus->cl_devid); */ 2041 2042 dhd_bus_devreset(bus->dhd, (uint8)bool_val); 2043 2044 break; 2045 2046 case IOV_GVAL(IOV_DEVRESET): 2047 DHD_TRACE(("%s: Called get IOV_DEVRESET\n", __FUNCTION__)); 2048 2049 /* Get its status */ 2050 int_val = (bool) bus->dhd->dongle_reset; 2051 bcopy(&int_val, arg, val_size); 2052 2053 break; 2054 2055 default: 2056 bcmerror = BCME_UNSUPPORTED; 2057 break; 2058 } 2059 2060 exit: 2061 if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) { 2062 bus->activity = FALSE; 2063 dhdsdio_clkctl(bus, CLK_NONE, TRUE); 2064 } 2065 2066 dhd_os_sdunlock(bus->dhd); 2067 2068 if (actionid == IOV_SVAL(IOV_DEVRESET) && bool_val == FALSE) 2069 dhd_preinit_ioctls((dhd_pub_t *) bus->dhd); 2070 2071 return bcmerror; 2072 } 2073 2074 static int 2075 dhdsdio_write_vars(dhd_bus_t *bus) 2076 { 2077 int bcmerror = 0; 2078 uint32 varsize; 2079 uint32 varaddr; 2080 uint8 *vbuffer; 2081 uint32 varsizew; 2082 #ifdef DHD_DEBUG 2083 char *nvram_ularray; 2084 #endif /* DHD_DEBUG */ 2085 2086 /* Even if there are no vars are to be written, we still need to set the ramsize. */ 2087 varsize = bus->varsz ? ROUNDUP(bus->varsz, 4) : 0; 2088 varaddr = (bus->ramsize - 4) - varsize; 2089 2090 if (bus->vars) { 2091 vbuffer = (uint8 *)MALLOC(bus->dhd->osh, varsize); 2092 if (!vbuffer) 2093 return BCME_NOMEM; 2094 2095 bzero(vbuffer, varsize); 2096 bcopy(bus->vars, vbuffer, bus->varsz); 2097 2098 /* Write the vars list */ 2099 bcmerror = dhdsdio_membytes(bus, TRUE, varaddr, vbuffer, varsize); 2100 #ifdef DHD_DEBUG 2101 /* Verify NVRAM bytes */ 2102 DHD_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize)); 2103 nvram_ularray = (char*)MALLOC(bus->dhd->osh, varsize); 2104 if (!nvram_ularray) 2105 return BCME_NOMEM; 2106 2107 /* Upload image to verify downloaded contents. */ 2108 memset(nvram_ularray, 0xaa, varsize); 2109 2110 /* Read the vars list to temp buffer for comparison */ 2111 bcmerror = dhdsdio_membytes(bus, FALSE, varaddr, nvram_ularray, varsize); 2112 if (bcmerror) { 2113 DHD_ERROR(("%s: error %d on reading %d nvram bytes at 0x%08x\n", 2114 __FUNCTION__, bcmerror, varsize, varaddr)); 2115 } 2116 /* Compare the org NVRAM with the one read from RAM */ 2117 if (memcmp(vbuffer, nvram_ularray, varsize)) { 2118 DHD_ERROR(("%s: Downloaded NVRAM image is corrupted.\n", __FUNCTION__)); 2119 } else 2120 DHD_ERROR(("%s: Download, Upload and compare of NVRAM succeeded.\n", 2121 __FUNCTION__)); 2122 2123 MFREE(bus->dhd->osh, nvram_ularray, varsize); 2124 #endif /* DHD_DEBUG */ 2125 2126 MFREE(bus->dhd->osh, vbuffer, varsize); 2127 } 2128 2129 /* adjust to the user specified RAM */ 2130 DHD_INFO(("Physical memory size: %d, usable memory size: %d\n", 2131 bus->orig_ramsize, bus->ramsize)); 2132 DHD_INFO(("Vars are at %d, orig varsize is %d\n", 2133 varaddr, varsize)); 2134 varsize = ((bus->orig_ramsize - 4) - varaddr); 2135 2136 /* 2137 * Determine the length token: 2138 * Varsize, converted to words, in lower 16-bits, checksum in upper 16-bits. 2139 */ 2140 if (bcmerror) { 2141 varsizew = 0; 2142 } else { 2143 varsizew = varsize / 4; 2144 varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF); 2145 varsizew = htol32(varsizew); 2146 } 2147 2148 DHD_INFO(("New varsize is %d, length token=0x%08x\n", varsize, varsizew)); 2149 2150 /* Write the length token to the last word */ 2151 bcmerror = dhdsdio_membytes(bus, TRUE, (bus->orig_ramsize - 4), 2152 (uint8*)&varsizew, 4); 2153 2154 return bcmerror; 2155 } 2156 2157 static int 2158 dhdsdio_download_state(dhd_bus_t *bus, bool enter) 2159 { 2160 uint retries; 2161 int bcmerror = 0; 2162 2163 /* To enter download state, disable ARM and reset SOCRAM. 2164 * To exit download state, simply reset ARM (default is RAM boot). 2165 */ 2166 if (enter) { 2167 2168 bus->alp_only = TRUE; 2169 2170 if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) && 2171 !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) { 2172 DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__)); 2173 bcmerror = BCME_ERROR; 2174 goto fail; 2175 } 2176 2177 si_core_disable(bus->sih, 0); 2178 if (bcmsdh_regfail(bus->sdh)) { 2179 bcmerror = BCME_SDIO_ERROR; 2180 goto fail; 2181 } 2182 2183 if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) { 2184 DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__)); 2185 bcmerror = BCME_ERROR; 2186 goto fail; 2187 } 2188 2189 si_core_reset(bus->sih, 0, 0); 2190 if (bcmsdh_regfail(bus->sdh)) { 2191 DHD_ERROR(("%s: Failure trying reset SOCRAM core?\n", __FUNCTION__)); 2192 bcmerror = BCME_SDIO_ERROR; 2193 goto fail; 2194 } 2195 2196 /* Clear the top bit of memory */ 2197 if (bus->ramsize) { 2198 uint32 zeros = 0; 2199 dhdsdio_membytes(bus, TRUE, bus->ramsize - 4, (uint8*)&zeros, 4); 2200 } 2201 } else { 2202 if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) { 2203 DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__)); 2204 bcmerror = BCME_ERROR; 2205 goto fail; 2206 } 2207 2208 if (!si_iscoreup(bus->sih)) { 2209 DHD_ERROR(("%s: SOCRAM core is down after reset?\n", __FUNCTION__)); 2210 bcmerror = BCME_ERROR; 2211 goto fail; 2212 } 2213 2214 if ((bcmerror = dhdsdio_write_vars(bus))) { 2215 DHD_ERROR(("%s: no vars written to RAM\n", __FUNCTION__)); 2216 bcmerror = 0; 2217 } 2218 2219 if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) && 2220 !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) { 2221 DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__)); 2222 bcmerror = BCME_ERROR; 2223 goto fail; 2224 } 2225 W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries); 2226 2227 2228 if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) && 2229 !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) { 2230 DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__)); 2231 bcmerror = BCME_ERROR; 2232 goto fail; 2233 } 2234 2235 si_core_reset(bus->sih, 0, 0); 2236 if (bcmsdh_regfail(bus->sdh)) { 2237 DHD_ERROR(("%s: Failure trying to reset ARM core?\n", __FUNCTION__)); 2238 bcmerror = BCME_SDIO_ERROR; 2239 goto fail; 2240 } 2241 2242 /* Allow HT Clock now that the ARM is running. */ 2243 bus->alp_only = FALSE; 2244 2245 bus->dhd->busstate = DHD_BUS_LOAD; 2246 } 2247 2248 fail: 2249 /* Always return to SDIOD core */ 2250 if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0)) 2251 si_setcore(bus->sih, SDIOD_CORE_ID, 0); 2252 2253 return bcmerror; 2254 } 2255 2256 int 2257 dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name, 2258 void *params, int plen, void *arg, int len, bool set) 2259 { 2260 dhd_bus_t *bus = dhdp->bus; 2261 const bcm_iovar_t *vi = NULL; 2262 int bcmerror = 0; 2263 int val_size; 2264 uint32 actionid; 2265 2266 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 2267 2268 ASSERT(name); 2269 ASSERT(len >= 0); 2270 2271 /* Get MUST have return space */ 2272 ASSERT(set || (arg && len)); 2273 2274 /* Set does NOT take qualifiers */ 2275 ASSERT(!set || (!params && !plen)); 2276 2277 /* Look up var locally; if not found pass to host driver */ 2278 if ((vi = bcm_iovar_lookup(dhdsdio_iovars, name)) == NULL) { 2279 dhd_os_sdlock(bus->dhd); 2280 2281 BUS_WAKE(bus); 2282 2283 /* Turn on clock in case SD command needs backplane */ 2284 dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); 2285 2286 bcmerror = bcmsdh_iovar_op(bus->sdh, name, params, plen, arg, len, set); 2287 2288 /* Check for bus configuration changes of interest */ 2289 2290 /* If it was divisor change, read the new one */ 2291 if (set && strcmp(name, "sd_divisor") == 0) { 2292 if (bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0, 2293 &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) { 2294 bus->sd_divisor = -1; 2295 DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, name)); 2296 } else { 2297 DHD_INFO(("%s: noted %s update, value now %d\n", 2298 __FUNCTION__, name, bus->sd_divisor)); 2299 } 2300 } 2301 /* If it was a mode change, read the new one */ 2302 if (set && strcmp(name, "sd_mode") == 0) { 2303 if (bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0, 2304 &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) { 2305 bus->sd_mode = -1; 2306 DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, name)); 2307 } else { 2308 DHD_INFO(("%s: noted %s update, value now %d\n", 2309 __FUNCTION__, name, bus->sd_mode)); 2310 } 2311 } 2312 /* Similar check for blocksize change */ 2313 if (set && strcmp(name, "sd_blocksize") == 0) { 2314 int32 fnum = 2; 2315 if (bcmsdh_iovar_op(bus->sdh, "sd_blocksize", &fnum, sizeof(int32), 2316 &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) { 2317 bus->blocksize = 0; 2318 DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize")); 2319 } else { 2320 DHD_INFO(("%s: noted %s update, value now %d\n", 2321 __FUNCTION__, "sd_blocksize", bus->blocksize)); 2322 } 2323 } 2324 bus->roundup = MIN(max_roundup, bus->blocksize); 2325 2326 if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) { 2327 bus->activity = FALSE; 2328 dhdsdio_clkctl(bus, CLK_NONE, TRUE); 2329 } 2330 2331 dhd_os_sdunlock(bus->dhd); 2332 goto exit; 2333 } 2334 2335 DHD_CTL(("%s: %s %s, len %d plen %d\n", __FUNCTION__, 2336 name, (set ? "set" : "get"), len, plen)); 2337 2338 /* set up 'params' pointer in case this is a set command so that 2339 * the convenience int and bool code can be common to set and get 2340 */ 2341 if (params == NULL) { 2342 params = arg; 2343 plen = len; 2344 } 2345 2346 if (vi->type == IOVT_VOID) 2347 val_size = 0; 2348 else if (vi->type == IOVT_BUFFER) 2349 val_size = len; 2350 else 2351 /* all other types are integer sized */ 2352 val_size = sizeof(int); 2353 2354 actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid); 2355 bcmerror = dhdsdio_doiovar(bus, vi, actionid, name, params, plen, arg, len, val_size); 2356 2357 exit: 2358 return bcmerror; 2359 } 2360 2361 void 2362 dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) 2363 { 2364 osl_t *osh = bus->dhd->osh; 2365 uint32 local_hostintmask; 2366 uint8 saveclk; 2367 uint retries; 2368 int err; 2369 2370 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 2371 2372 if (enforce_mutex) 2373 dhd_os_sdlock(bus->dhd); 2374 2375 BUS_WAKE(bus); 2376 2377 /* Enable clock for device interrupts */ 2378 dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); 2379 2380 /* Disable and clear interrupts at the chip level also */ 2381 W_SDREG(0, &bus->regs->hostintmask, retries); 2382 local_hostintmask = bus->hostintmask; 2383 bus->hostintmask = 0; 2384 2385 /* Change our idea of bus state */ 2386 bus->dhd->busstate = DHD_BUS_DOWN; 2387 2388 /* Force clocks on backplane to be sure F2 interrupt propagates */ 2389 saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); 2390 if (!err) { 2391 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 2392 (saveclk | SBSDIO_FORCE_HT), &err); 2393 } 2394 if (err) { 2395 DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err)); 2396 } 2397 2398 /* Turn off the bus (F2), free any pending packets */ 2399 DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); 2400 bcmsdh_intr_disable(bus->sdh); 2401 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL); 2402 2403 /* Clear any pending interrupts now that F2 is disabled */ 2404 W_SDREG(local_hostintmask, &bus->regs->intstatus, retries); 2405 2406 /* Turn off the backplane clock (only) */ 2407 dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); 2408 2409 /* Clear the data packet queues */ 2410 pktq_flush(osh, &bus->txq, TRUE); 2411 2412 /* Clear any held glomming stuff */ 2413 if (bus->glomd) 2414 PKTFREE(osh, bus->glomd, FALSE); 2415 2416 if (bus->glom) 2417 PKTFREE(osh, bus->glom, FALSE); 2418 2419 bus->glom = bus->glomd = NULL; 2420 2421 /* Clear rx control and wake any waiters */ 2422 bus->rxlen = 0; 2423 dhd_os_ioctl_resp_wake(bus->dhd); 2424 2425 /* Reset some F2 state stuff */ 2426 bus->rxskip = FALSE; 2427 bus->tx_seq = bus->rx_seq = 0; 2428 2429 if (enforce_mutex) 2430 dhd_os_sdunlock(bus->dhd); 2431 } 2432 2433 int 2434 dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex) 2435 { 2436 dhd_bus_t *bus = dhdp->bus; 2437 dhd_timeout_t tmo; 2438 uint retries = 0; 2439 uint8 ready, enable; 2440 int err, ret = 0; 2441 uint8 saveclk; 2442 2443 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 2444 2445 ASSERT(bus->dhd); 2446 if (!bus->dhd) 2447 return 0; 2448 2449 if (enforce_mutex) 2450 dhd_os_sdlock(bus->dhd); 2451 2452 /* Make sure backplane clock is on, needed to generate F2 interrupt */ 2453 dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); 2454 if (bus->clkstate != CLK_AVAIL) 2455 goto exit; 2456 2457 2458 /* Force clocks on backplane to be sure F2 interrupt propagates */ 2459 saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); 2460 if (!err) { 2461 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 2462 (saveclk | SBSDIO_FORCE_HT), &err); 2463 } 2464 if (err) { 2465 DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err)); 2466 goto exit; 2467 } 2468 2469 /* Enable function 2 (frame transfers) */ 2470 W_SDREG((SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT), 2471 &bus->regs->tosbmailboxdata, retries); 2472 enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2); 2473 2474 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL); 2475 2476 /* Give the dongle some time to do its thing and set IOR2 */ 2477 dhd_timeout_start(&tmo, DHD_WAIT_F2RDY * 1000); 2478 2479 ready = 0; 2480 while (ready != enable && !dhd_timeout_expired(&tmo)) 2481 ready = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL); 2482 2483 2484 DHD_INFO(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n", 2485 __FUNCTION__, enable, ready, tmo.elapsed)); 2486 2487 2488 /* If F2 successfully enabled, set core and enable interrupts */ 2489 if (ready == enable) { 2490 /* Make sure we're talking to the core. */ 2491 if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0))) 2492 bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0); 2493 2494 /* Set up the interrupt mask and enable interrupts */ 2495 bus->hostintmask = HOSTINTMASK; 2496 W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries); 2497 2498 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, (uint8)watermark, &err); 2499 2500 /* Set bus state according to enable result */ 2501 dhdp->busstate = DHD_BUS_DATA; 2502 2503 /* bcmsdh_intr_unmask(bus->sdh); */ 2504 2505 bus->intdis = FALSE; 2506 if (bus->intr) { 2507 DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__)); 2508 bcmsdh_intr_enable(bus->sdh); 2509 } else { 2510 DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); 2511 bcmsdh_intr_disable(bus->sdh); 2512 } 2513 2514 } 2515 2516 2517 else { 2518 /* Disable F2 again */ 2519 enable = SDIO_FUNC_ENABLE_1; 2520 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL); 2521 } 2522 2523 /* Restore previous clock setting */ 2524 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); 2525 2526 2527 /* If we didn't come up, turn off backplane clock */ 2528 if (dhdp->busstate != DHD_BUS_DATA) 2529 dhdsdio_clkctl(bus, CLK_NONE, FALSE); 2530 2531 exit: 2532 if (enforce_mutex) 2533 dhd_os_sdunlock(bus->dhd); 2534 2535 return ret; 2536 } 2537 2538 static void 2539 dhdsdio_rxfail(dhd_bus_t *bus, bool abort, bool rtx) 2540 { 2541 bcmsdh_info_t *sdh = bus->sdh; 2542 sdpcmd_regs_t *regs = bus->regs; 2543 uint retries = 0; 2544 uint16 lastrbc; 2545 uint8 hi, lo; 2546 int err; 2547 2548 DHD_ERROR(("%s: %sterminate frame%s\n", __FUNCTION__, 2549 (abort ? "abort command, " : ""), (rtx ? ", send NAK" : ""))); 2550 2551 if (abort) { 2552 bcmsdh_abort(sdh, SDIO_FUNC_2); 2553 } 2554 2555 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM, &err); 2556 bus->f1regdata++; 2557 2558 /* Wait until the packet has been flushed (device/FIFO stable) */ 2559 for (lastrbc = retries = 0xffff; retries > 0; retries--) { 2560 hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCHI, NULL); 2561 lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCLO, NULL); 2562 bus->f1regdata += 2; 2563 2564 if ((hi == 0) && (lo == 0)) 2565 break; 2566 2567 if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) { 2568 DHD_ERROR(("%s: count growing: last 0x%04x now 0x%04x\n", 2569 __FUNCTION__, lastrbc, ((hi << 8) + lo))); 2570 } 2571 lastrbc = (hi << 8) + lo; 2572 } 2573 2574 if (!retries) { 2575 DHD_ERROR(("%s: count never zeroed: last 0x%04x\n", __FUNCTION__, lastrbc)); 2576 } else { 2577 DHD_INFO(("%s: flush took %d iterations\n", __FUNCTION__, (0xffff - retries))); 2578 } 2579 2580 if (rtx) { 2581 bus->rxrtx++; 2582 W_SDREG(SMB_NAK, ®s->tosbmailbox, retries); 2583 bus->f1regdata++; 2584 if (retries <= retry_limit) { 2585 bus->rxskip = TRUE; 2586 } 2587 } 2588 2589 /* Clear partial in any case */ 2590 bus->nextlen = 0; 2591 2592 /* If we can't reach the device, signal failure */ 2593 if (err || bcmsdh_regfail(sdh)) 2594 bus->dhd->busstate = DHD_BUS_DOWN; 2595 } 2596 2597 static void 2598 dhdsdio_read_control(dhd_bus_t *bus, uint8 *hdr, uint len, uint doff) 2599 { 2600 bcmsdh_info_t *sdh = bus->sdh; 2601 uint rdlen, pad; 2602 2603 int sdret; 2604 2605 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 2606 2607 /* Control data already received in aligned rxctl */ 2608 if ((bus->bus == SPI_BUS) && (!bus->usebufpool)) 2609 goto gotpkt; 2610 2611 ASSERT(bus->rxbuf); 2612 /* Set rxctl for frame (w/optional alignment) */ 2613 bus->rxctl = bus->rxbuf; 2614 if (dhd_alignctl) { 2615 bus->rxctl += firstread; 2616 if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN))) 2617 bus->rxctl += (DHD_SDALIGN - pad); 2618 bus->rxctl -= firstread; 2619 } 2620 ASSERT(bus->rxctl >= bus->rxbuf); 2621 2622 /* Copy the already-read portion over */ 2623 bcopy(hdr, bus->rxctl, firstread); 2624 if (len <= firstread) 2625 goto gotpkt; 2626 2627 /* Copy the full data pkt in gSPI case and process ioctl. */ 2628 if (bus->bus == SPI_BUS) { 2629 bcopy(hdr, bus->rxctl, len); 2630 goto gotpkt; 2631 } 2632 2633 /* Raise rdlen to next SDIO block to avoid tail command */ 2634 rdlen = len - firstread; 2635 if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) { 2636 pad = bus->blocksize - (rdlen % bus->blocksize); 2637 if ((pad <= bus->roundup) && (pad < bus->blocksize) && 2638 ((len + pad) < bus->dhd->maxctl)) 2639 rdlen += pad; 2640 } else if (rdlen % DHD_SDALIGN) { 2641 rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN); 2642 } 2643 2644 /* Satisfy length-alignment requirements */ 2645 if (forcealign && (rdlen & (ALIGNMENT - 1))) 2646 rdlen = ROUNDUP(rdlen, ALIGNMENT); 2647 2648 /* Drop if the read is too big or it exceeds our maximum */ 2649 if ((rdlen + firstread) > bus->dhd->maxctl) { 2650 DHD_ERROR(("%s: %d-byte control read exceeds %d-byte buffer\n", 2651 __FUNCTION__, rdlen, bus->dhd->maxctl)); 2652 bus->dhd->rx_errors++; 2653 dhdsdio_rxfail(bus, FALSE, FALSE); 2654 goto done; 2655 } 2656 2657 if ((len - doff) > bus->dhd->maxctl) { 2658 DHD_ERROR(("%s: %d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n", 2659 __FUNCTION__, len, (len - doff), bus->dhd->maxctl)); 2660 bus->dhd->rx_errors++; bus->rx_toolong++; 2661 dhdsdio_rxfail(bus, FALSE, FALSE); 2662 goto done; 2663 } 2664 2665 2666 /* Read remainder of frame body into the rxctl buffer */ 2667 sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, 2668 (bus->rxctl + firstread), rdlen, NULL, NULL, NULL); 2669 bus->f2rxdata++; 2670 ASSERT(sdret != BCME_PENDING); 2671 2672 /* Control frame failures need retransmission */ 2673 if (sdret < 0) { 2674 DHD_ERROR(("%s: read %d control bytes failed: %d\n", __FUNCTION__, rdlen, sdret)); 2675 bus->rxc_errors++; /* dhd.rx_ctlerrs is higher level */ 2676 dhdsdio_rxfail(bus, TRUE, TRUE); 2677 goto done; 2678 } 2679 2680 gotpkt: 2681 2682 #ifdef DHD_DEBUG 2683 if (DHD_BYTES_ON() && DHD_CTL_ON()) { 2684 prhex("RxCtrl", bus->rxctl, len); 2685 } 2686 #endif 2687 2688 /* Point to valid data and indicate its length */ 2689 bus->rxctl += doff; 2690 bus->rxlen = len - doff; 2691 2692 done: 2693 /* Awake any waiters */ 2694 dhd_os_ioctl_resp_wake(bus->dhd); 2695 } 2696 2697 static uint8 2698 dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) 2699 { 2700 uint16 dlen, totlen; 2701 uint8 *dptr, num = 0; 2702 2703 uint16 sublen, check; 2704 void *pfirst, *plast, *pnext, *save_pfirst; 2705 osl_t *osh = bus->dhd->osh; 2706 2707 int errcode; 2708 uint8 chan, seq, doff, sfdoff; 2709 uint8 txmax; 2710 2711 int ifidx = 0; 2712 bool usechain = bus->use_rxchain; 2713 2714 /* If packets, issue read(s) and send up packet chain */ 2715 /* Return sequence numbers consumed? */ 2716 2717 DHD_TRACE(("dhdsdio_rxglom: start: glomd %p glom %p\n", bus->glomd, bus->glom)); 2718 2719 /* If there's a descriptor, generate the packet chain */ 2720 if (bus->glomd) { 2721 dhd_os_sdlock_rxq(bus->dhd); 2722 2723 pfirst = plast = pnext = NULL; 2724 dlen = (uint16)PKTLEN(osh, bus->glomd); 2725 dptr = PKTDATA(osh, bus->glomd); 2726 if (!dlen || (dlen & 1)) { 2727 DHD_ERROR(("%s: bad glomd len (%d), ignore descriptor\n", 2728 __FUNCTION__, dlen)); 2729 dlen = 0; 2730 } 2731 2732 for (totlen = num = 0; dlen; num++) { 2733 /* Get (and move past) next length */ 2734 sublen = ltoh16_ua(dptr); 2735 dlen -= sizeof(uint16); 2736 dptr += sizeof(uint16); 2737 if ((sublen < SDPCM_HDRLEN) || 2738 ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) { 2739 DHD_ERROR(("%s: descriptor len %d bad: %d\n", 2740 __FUNCTION__, num, sublen)); 2741 pnext = NULL; 2742 break; 2743 } 2744 if (sublen % DHD_SDALIGN) { 2745 DHD_ERROR(("%s: sublen %d not a multiple of %d\n", 2746 __FUNCTION__, sublen, DHD_SDALIGN)); 2747 usechain = FALSE; 2748 } 2749 totlen += sublen; 2750 2751 /* For last frame, adjust read len so total is a block multiple */ 2752 if (!dlen) { 2753 sublen += (ROUNDUP(totlen, bus->blocksize) - totlen); 2754 totlen = ROUNDUP(totlen, bus->blocksize); 2755 } 2756 2757 /* Allocate/chain packet for next subframe */ 2758 if ((pnext = PKTGET(osh, sublen + DHD_SDALIGN, FALSE)) == NULL) { 2759 DHD_ERROR(("%s: PKTGET failed, num %d len %d\n", 2760 __FUNCTION__, num, sublen)); 2761 break; 2762 } 2763 ASSERT(!PKTLINK(pnext)); 2764 if (!pfirst) { 2765 ASSERT(!plast); 2766 pfirst = plast = pnext; 2767 } else { 2768 ASSERT(plast); 2769 PKTSETNEXT(osh, plast, pnext); 2770 plast = pnext; 2771 } 2772 2773 /* Adhere to start alignment requirements */ 2774 PKTALIGN(osh, pnext, sublen, DHD_SDALIGN); 2775 } 2776 2777 /* If all allocations succeeded, save packet chain in bus structure */ 2778 if (pnext) { 2779 DHD_GLOM(("%s: allocated %d-byte packet chain for %d subframes\n", 2780 __FUNCTION__, totlen, num)); 2781 if (DHD_GLOM_ON() && bus->nextlen) { 2782 if (totlen != bus->nextlen) { 2783 DHD_GLOM(("%s: glomdesc mismatch: nextlen %d glomdesc %d " 2784 "rxseq %d\n", __FUNCTION__, bus->nextlen, 2785 totlen, rxseq)); 2786 } 2787 } 2788 bus->glom = pfirst; 2789 pfirst = pnext = NULL; 2790 } else { 2791 if (pfirst) 2792 PKTFREE(osh, pfirst, FALSE); 2793 bus->glom = NULL; 2794 num = 0; 2795 } 2796 2797 /* Done with descriptor packet */ 2798 PKTFREE(osh, bus->glomd, FALSE); 2799 bus->glomd = NULL; 2800 bus->nextlen = 0; 2801 2802 dhd_os_sdunlock_rxq(bus->dhd); 2803 } 2804 2805 /* Ok -- either we just generated a packet chain, or had one from before */ 2806 if (bus->glom) { 2807 if (DHD_GLOM_ON()) { 2808 DHD_GLOM(("%s: attempt superframe read, packet chain:\n", __FUNCTION__)); 2809 for (pnext = bus->glom; pnext; pnext = PKTNEXT(osh, pnext)) { 2810 DHD_GLOM((" %p: %p len 0x%04x (%d)\n", 2811 pnext, (uint8*)PKTDATA(osh, pnext), 2812 PKTLEN(osh, pnext), PKTLEN(osh, pnext))); 2813 } 2814 } 2815 2816 pfirst = bus->glom; 2817 dlen = (uint16)pkttotlen(osh, pfirst); 2818 2819 /* Do an SDIO read for the superframe. Configurable iovar to 2820 * read directly into the chained packet, or allocate a large 2821 * packet and and copy into the chain. 2822 */ 2823 if (usechain) { 2824 errcode = dhd_bcmsdh_recv_buf(bus, 2825 bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2, 2826 F2SYNC, (uint8*)PKTDATA(osh, pfirst), 2827 dlen, pfirst, NULL, NULL); 2828 } else if (bus->dataptr) { 2829 errcode = dhd_bcmsdh_recv_buf(bus, 2830 bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2, 2831 F2SYNC, bus->dataptr, 2832 dlen, NULL, NULL, NULL); 2833 sublen = (uint16)pktfrombuf(osh, pfirst, 0, dlen, bus->dataptr); 2834 if (sublen != dlen) { 2835 DHD_ERROR(("%s: FAILED TO COPY, dlen %d sublen %d\n", 2836 __FUNCTION__, dlen, sublen)); 2837 errcode = -1; 2838 } 2839 pnext = NULL; 2840 } else { 2841 DHD_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n", dlen)); 2842 errcode = -1; 2843 } 2844 bus->f2rxdata++; 2845 ASSERT(errcode != BCME_PENDING); 2846 2847 /* On failure, kill the superframe, allow a couple retries */ 2848 if (errcode < 0) { 2849 DHD_ERROR(("%s: glom read of %d bytes failed: %d\n", 2850 __FUNCTION__, dlen, errcode)); 2851 bus->dhd->rx_errors++; 2852 2853 if (bus->glomerr++ < 3) { 2854 dhdsdio_rxfail(bus, TRUE, TRUE); 2855 } else { 2856 bus->glomerr = 0; 2857 dhdsdio_rxfail(bus, TRUE, FALSE); 2858 dhd_os_sdlock_rxq(bus->dhd); 2859 PKTFREE(osh, bus->glom, FALSE); 2860 dhd_os_sdunlock_rxq(bus->dhd); 2861 bus->rxglomfail++; 2862 bus->glom = NULL; 2863 } 2864 return 0; 2865 } 2866 2867 #ifdef DHD_DEBUG 2868 if (DHD_GLOM_ON()) { 2869 prhex("SUPERFRAME", PKTDATA(osh, pfirst), 2870 MIN(PKTLEN(osh, pfirst), 48)); 2871 } 2872 #endif 2873 2874 2875 /* Validate the superframe header */ 2876 dptr = (uint8 *)PKTDATA(osh, pfirst); 2877 sublen = ltoh16_ua(dptr); 2878 check = ltoh16_ua(dptr + sizeof(uint16)); 2879 2880 chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); 2881 seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); 2882 bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; 2883 if ((bus->nextlen << 4) > MAX_RX_DATASZ) { 2884 DHD_INFO(("%s: got frame w/nextlen too large (%d) seq %d\n", 2885 __FUNCTION__, bus->nextlen, seq)); 2886 bus->nextlen = 0; 2887 } 2888 doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); 2889 txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); 2890 2891 errcode = 0; 2892 if ((uint16)~(sublen^check)) { 2893 DHD_ERROR(("%s (superframe): HW hdr error: len/check 0x%04x/0x%04x\n", 2894 __FUNCTION__, sublen, check)); 2895 errcode = -1; 2896 } else if (ROUNDUP(sublen, bus->blocksize) != dlen) { 2897 DHD_ERROR(("%s (superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n", 2898 __FUNCTION__, sublen, ROUNDUP(sublen, bus->blocksize), dlen)); 2899 errcode = -1; 2900 } else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) != SDPCM_GLOM_CHANNEL) { 2901 DHD_ERROR(("%s (superframe): bad channel %d\n", __FUNCTION__, 2902 SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]))); 2903 errcode = -1; 2904 } else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) { 2905 DHD_ERROR(("%s (superframe): got second descriptor?\n", __FUNCTION__)); 2906 errcode = -1; 2907 } else if ((doff < SDPCM_HDRLEN) || 2908 (doff > (PKTLEN(osh, pfirst) - SDPCM_HDRLEN))) { 2909 DHD_ERROR(("%s (superframe): Bad data offset %d: HW %d pkt %d min %d\n", 2910 __FUNCTION__, doff, sublen, PKTLEN(osh, pfirst), SDPCM_HDRLEN)); 2911 errcode = -1; 2912 } 2913 2914 /* Check sequence number of superframe SW header */ 2915 if (rxseq != seq) { 2916 DHD_INFO(("%s: (superframe) rx_seq %d, expected %d\n", 2917 __FUNCTION__, seq, rxseq)); 2918 bus->rx_badseq++; 2919 rxseq = seq; 2920 } 2921 2922 /* Check window for sanity */ 2923 if ((uint8)(txmax - bus->tx_seq) > 0x40) { 2924 DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", 2925 __FUNCTION__, txmax, bus->tx_seq)); 2926 txmax = bus->tx_seq + 2; 2927 } 2928 bus->tx_max = txmax; 2929 2930 /* Remove superframe header, remember offset */ 2931 PKTPULL(osh, pfirst, doff); 2932 sfdoff = doff; 2933 2934 /* Validate all the subframe headers */ 2935 for (num = 0, pnext = pfirst; pnext && !errcode; 2936 num++, pnext = PKTNEXT(osh, pnext)) { 2937 dptr = (uint8 *)PKTDATA(osh, pnext); 2938 dlen = (uint16)PKTLEN(osh, pnext); 2939 sublen = ltoh16_ua(dptr); 2940 check = ltoh16_ua(dptr + sizeof(uint16)); 2941 chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); 2942 doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); 2943 #ifdef DHD_DEBUG 2944 if (DHD_GLOM_ON()) { 2945 prhex("subframe", dptr, 32); 2946 } 2947 #endif 2948 2949 if ((uint16)~(sublen^check)) { 2950 DHD_ERROR(("%s (subframe %d): HW hdr error: " 2951 "len/check 0x%04x/0x%04x\n", 2952 __FUNCTION__, num, sublen, check)); 2953 errcode = -1; 2954 } else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) { 2955 DHD_ERROR(("%s (subframe %d): length mismatch: " 2956 "len 0x%04x, expect 0x%04x\n", 2957 __FUNCTION__, num, sublen, dlen)); 2958 errcode = -1; 2959 } else if ((chan != SDPCM_DATA_CHANNEL) && 2960 (chan != SDPCM_EVENT_CHANNEL)) { 2961 DHD_ERROR(("%s (subframe %d): bad channel %d\n", 2962 __FUNCTION__, num, chan)); 2963 errcode = -1; 2964 } else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) { 2965 DHD_ERROR(("%s (subframe %d): Bad data offset %d: HW %d min %d\n", 2966 __FUNCTION__, num, doff, sublen, SDPCM_HDRLEN)); 2967 errcode = -1; 2968 } 2969 } 2970 2971 if (errcode) { 2972 /* Terminate frame on error, request a couple retries */ 2973 if (bus->glomerr++ < 3) { 2974 /* Restore superframe header space */ 2975 PKTPUSH(osh, pfirst, sfdoff); 2976 dhdsdio_rxfail(bus, TRUE, TRUE); 2977 } else { 2978 bus->glomerr = 0; 2979 dhdsdio_rxfail(bus, TRUE, FALSE); 2980 dhd_os_sdlock_rxq(bus->dhd); 2981 PKTFREE(osh, bus->glom, FALSE); 2982 dhd_os_sdunlock_rxq(bus->dhd); 2983 bus->rxglomfail++; 2984 bus->glom = NULL; 2985 } 2986 bus->nextlen = 0; 2987 return 0; 2988 } 2989 2990 /* Basic SD framing looks ok - process each packet (header) */ 2991 save_pfirst = pfirst; 2992 bus->glom = NULL; 2993 plast = NULL; 2994 2995 dhd_os_sdlock_rxq(bus->dhd); 2996 for (num = 0; pfirst; rxseq++, pfirst = pnext) { 2997 pnext = PKTNEXT(osh, pfirst); 2998 PKTSETNEXT(osh, pfirst, NULL); 2999 3000 dptr = (uint8 *)PKTDATA(osh, pfirst); 3001 sublen = ltoh16_ua(dptr); 3002 chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); 3003 seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); 3004 doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); 3005 3006 DHD_GLOM(("%s: Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n", 3007 __FUNCTION__, num, pfirst, PKTDATA(osh, pfirst), 3008 PKTLEN(osh, pfirst), sublen, chan, seq)); 3009 3010 ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL)); 3011 3012 if (rxseq != seq) { 3013 DHD_GLOM(("%s: rx_seq %d, expected %d\n", 3014 __FUNCTION__, seq, rxseq)); 3015 bus->rx_badseq++; 3016 rxseq = seq; 3017 } 3018 3019 #ifdef DHD_DEBUG 3020 if (DHD_BYTES_ON() && DHD_DATA_ON()) { 3021 prhex("Rx Subframe Data", dptr, dlen); 3022 } 3023 #endif 3024 3025 PKTSETLEN(osh, pfirst, sublen); 3026 PKTPULL(osh, pfirst, doff); 3027 3028 if (PKTLEN(osh, pfirst) == 0) { 3029 PKTFREE(bus->dhd->osh, pfirst, FALSE); 3030 if (plast) { 3031 PKTSETNEXT(osh, plast, pnext); 3032 } else { 3033 ASSERT(save_pfirst == pfirst); 3034 save_pfirst = pnext; 3035 } 3036 continue; 3037 } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pfirst) != 0) { 3038 DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__)); 3039 bus->dhd->rx_errors++; 3040 PKTFREE(osh, pfirst, FALSE); 3041 if (plast) { 3042 PKTSETNEXT(osh, plast, pnext); 3043 } else { 3044 ASSERT(save_pfirst == pfirst); 3045 save_pfirst = pnext; 3046 } 3047 continue; 3048 } 3049 3050 /* this packet will go up, link back into chain and count it */ 3051 PKTSETNEXT(osh, pfirst, pnext); 3052 plast = pfirst; 3053 num++; 3054 3055 #ifdef DHD_DEBUG 3056 if (DHD_GLOM_ON()) { 3057 DHD_GLOM(("%s subframe %d to stack, %p(%p/%d) nxt/lnk %p/%p\n", 3058 __FUNCTION__, num, pfirst, 3059 PKTDATA(osh, pfirst), PKTLEN(osh, pfirst), 3060 PKTNEXT(osh, pfirst), PKTLINK(pfirst))); 3061 prhex("", (uint8 *)PKTDATA(osh, pfirst), 3062 MIN(PKTLEN(osh, pfirst), 32)); 3063 } 3064 #endif /* DHD_DEBUG */ 3065 } 3066 dhd_os_sdunlock_rxq(bus->dhd); 3067 if (num) { 3068 dhd_os_sdunlock(bus->dhd); 3069 dhd_rx_frame(bus->dhd, ifidx, save_pfirst, num); 3070 dhd_os_sdlock(bus->dhd); 3071 } 3072 3073 bus->rxglomframes++; 3074 bus->rxglompkts += num; 3075 } 3076 return num; 3077 } 3078 3079 /* Return TRUE if there may be more frames to read */ 3080 static uint 3081 dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) 3082 { 3083 osl_t *osh = bus->dhd->osh; 3084 bcmsdh_info_t *sdh = bus->sdh; 3085 3086 uint16 len, check; /* Extracted hardware header fields */ 3087 uint8 chan, seq, doff; /* Extracted software header fields */ 3088 uint8 fcbits; /* Extracted fcbits from software header */ 3089 uint8 delta; 3090 3091 void *pkt; /* Packet for event or data frames */ 3092 uint16 pad; /* Number of pad bytes to read */ 3093 uint16 rdlen; /* Total number of bytes to read */ 3094 uint8 rxseq; /* Next sequence number to expect */ 3095 uint rxleft = 0; /* Remaining number of frames allowed */ 3096 int sdret; /* Return code from bcmsdh calls */ 3097 uint8 txmax; /* Maximum tx sequence offered */ 3098 bool len_consistent; /* Result of comparing readahead len and len from hw-hdr */ 3099 uint8 *rxbuf; 3100 int ifidx = 0; 3101 uint rxcount = 0; /* Total frames read */ 3102 3103 #if defined(DHD_DEBUG) || defined(SDTEST) 3104 bool sdtest = FALSE; /* To limit message spew from test mode */ 3105 #endif 3106 3107 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 3108 3109 ASSERT(maxframes); 3110 3111 #ifdef SDTEST 3112 /* Allow pktgen to override maxframes */ 3113 if (bus->pktgen_count && (bus->pktgen_mode == DHD_PKTGEN_RECV)) { 3114 maxframes = bus->pktgen_count; 3115 sdtest = TRUE; 3116 } 3117 #endif 3118 3119 /* Not finished unless we encounter no more frames indication */ 3120 *finished = FALSE; 3121 3122 3123 for (rxseq = bus->rx_seq, rxleft = maxframes; 3124 !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN; 3125 rxseq++, rxleft--) { 3126 3127 /* Handle glomming separately */ 3128 if (bus->glom || bus->glomd) { 3129 uint8 cnt; 3130 DHD_GLOM(("%s: calling rxglom: glomd %p, glom %p\n", 3131 __FUNCTION__, bus->glomd, bus->glom)); 3132 cnt = dhdsdio_rxglom(bus, rxseq); 3133 DHD_GLOM(("%s: rxglom returned %d\n", __FUNCTION__, cnt)); 3134 rxseq += cnt - 1; 3135 rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1; 3136 continue; 3137 } 3138 3139 /* Try doing single read if we can */ 3140 if (dhd_readahead && bus->nextlen) { 3141 uint16 nextlen = bus->nextlen; 3142 bus->nextlen = 0; 3143 3144 if (bus->bus == SPI_BUS) { 3145 rdlen = len = nextlen; 3146 } 3147 else { 3148 rdlen = len = nextlen << 4; 3149 3150 /* Pad read to blocksize for efficiency */ 3151 if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) { 3152 pad = bus->blocksize - (rdlen % bus->blocksize); 3153 if ((pad <= bus->roundup) && (pad < bus->blocksize) && 3154 ((rdlen + pad + firstread) < MAX_RX_DATASZ)) 3155 rdlen += pad; 3156 } else if (rdlen % DHD_SDALIGN) { 3157 rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN); 3158 } 3159 } 3160 3161 /* We use bus->rxctl buffer in WinXP for initial control pkt receives. 3162 * Later we use buffer-poll for data as well as control packets. 3163 * This is required becuase dhd receives full frame in gSPI unlike SDIO. 3164 * After the frame is received we have to distinguish whether it is data 3165 * or non-data frame. 3166 */ 3167 /* Allocate a packet buffer */ 3168 dhd_os_sdlock_rxq(bus->dhd); 3169 if (!(pkt = PKTGET(osh, rdlen + DHD_SDALIGN, FALSE))) { 3170 if (bus->bus == SPI_BUS) { 3171 bus->usebufpool = FALSE; 3172 bus->rxctl = bus->rxbuf; 3173 if (dhd_alignctl) { 3174 bus->rxctl += firstread; 3175 if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN))) 3176 bus->rxctl += (DHD_SDALIGN - pad); 3177 bus->rxctl -= firstread; 3178 } 3179 ASSERT(bus->rxctl >= bus->rxbuf); 3180 rxbuf = bus->rxctl; 3181 /* Read the entire frame */ 3182 sdret = dhd_bcmsdh_recv_buf(bus, 3183 bcmsdh_cur_sbwad(sdh), 3184 SDIO_FUNC_2, 3185 F2SYNC, rxbuf, rdlen, 3186 NULL, NULL, NULL); 3187 bus->f2rxdata++; 3188 ASSERT(sdret != BCME_PENDING); 3189 3190 3191 /* Control frame failures need retransmission */ 3192 if (sdret < 0) { 3193 DHD_ERROR(("%s: read %d control bytes failed: %d\n", 3194 __FUNCTION__, rdlen, sdret)); 3195 /* dhd.rx_ctlerrs is higher level */ 3196 bus->rxc_errors++; 3197 dhd_os_sdunlock_rxq(bus->dhd); 3198 dhdsdio_rxfail(bus, TRUE, 3199 (bus->bus == SPI_BUS) ? FALSE : TRUE); 3200 continue; 3201 } 3202 } else { 3203 /* Give up on data, request rtx of events */ 3204 DHD_ERROR(("%s (nextlen): PKTGET failed: len %d rdlen %d " 3205 "expected rxseq %d\n", 3206 __FUNCTION__, len, rdlen, rxseq)); 3207 /* Just go try again w/normal header read */ 3208 dhd_os_sdunlock_rxq(bus->dhd); 3209 continue; 3210 } 3211 } else { 3212 if (bus->bus == SPI_BUS) 3213 bus->usebufpool = TRUE; 3214 3215 ASSERT(!PKTLINK(pkt)); 3216 PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN); 3217 rxbuf = (uint8 *)PKTDATA(osh, pkt); 3218 /* Read the entire frame */ 3219 sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), 3220 SDIO_FUNC_2, 3221 F2SYNC, rxbuf, rdlen, 3222 pkt, NULL, NULL); 3223 bus->f2rxdata++; 3224 ASSERT(sdret != BCME_PENDING); 3225 3226 if (sdret < 0) { 3227 DHD_ERROR(("%s (nextlen): read %d bytes failed: %d\n", 3228 __FUNCTION__, rdlen, sdret)); 3229 PKTFREE(bus->dhd->osh, pkt, FALSE); 3230 bus->dhd->rx_errors++; 3231 dhd_os_sdunlock_rxq(bus->dhd); 3232 /* Force retry w/normal header read. Don't attemp NAK for 3233 * gSPI 3234 */ 3235 dhdsdio_rxfail(bus, TRUE, 3236 (bus->bus == SPI_BUS) ? FALSE : TRUE); 3237 continue; 3238 } 3239 } 3240 dhd_os_sdunlock_rxq(bus->dhd); 3241 3242 /* Now check the header */ 3243 bcopy(rxbuf, bus->rxhdr, SDPCM_HDRLEN); 3244 3245 /* Extract hardware header fields */ 3246 len = ltoh16_ua(bus->rxhdr); 3247 check = ltoh16_ua(bus->rxhdr + sizeof(uint16)); 3248 3249 /* All zeros means readahead info was bad */ 3250 if (!(len|check)) { 3251 DHD_INFO(("%s (nextlen): read zeros in HW header???\n", 3252 __FUNCTION__)); 3253 dhd_os_sdlock_rxq(bus->dhd); 3254 PKTFREE2(); 3255 dhd_os_sdunlock_rxq(bus->dhd); 3256 GSPI_PR55150_BAILOUT; 3257 continue; 3258 } 3259 3260 /* Validate check bytes */ 3261 if ((uint16)~(len^check)) { 3262 DHD_ERROR(("%s (nextlen): HW hdr error: nextlen/len/check" 3263 " 0x%04x/0x%04x/0x%04x\n", __FUNCTION__, nextlen, 3264 len, check)); 3265 dhd_os_sdlock_rxq(bus->dhd); 3266 PKTFREE2(); 3267 dhd_os_sdunlock_rxq(bus->dhd); 3268 bus->rx_badhdr++; 3269 dhdsdio_rxfail(bus, FALSE, FALSE); 3270 GSPI_PR55150_BAILOUT; 3271 continue; 3272 } 3273 3274 /* Validate frame length */ 3275 if (len < SDPCM_HDRLEN) { 3276 DHD_ERROR(("%s (nextlen): HW hdr length invalid: %d\n", 3277 __FUNCTION__, len)); 3278 dhd_os_sdlock_rxq(bus->dhd); 3279 PKTFREE2(); 3280 dhd_os_sdunlock_rxq(bus->dhd); 3281 GSPI_PR55150_BAILOUT; 3282 continue; 3283 } 3284 3285 /* Check for consistency with readahead info */ 3286 len_consistent = (nextlen != (ROUNDUP(len, 16) >> 4)); 3287 if (len_consistent) { 3288 /* Mismatch, force retry w/normal header (may be >4K) */ 3289 DHD_ERROR(("%s (nextlen): mismatch, nextlen %d len %d rnd %d; " 3290 "expected rxseq %d\n", 3291 __FUNCTION__, nextlen, len, ROUNDUP(len, 16), rxseq)); 3292 dhd_os_sdlock_rxq(bus->dhd); 3293 PKTFREE2(); 3294 dhd_os_sdunlock_rxq(bus->dhd); 3295 dhdsdio_rxfail(bus, TRUE, (bus->bus == SPI_BUS) ? FALSE : TRUE); 3296 GSPI_PR55150_BAILOUT; 3297 continue; 3298 } 3299 3300 3301 /* Extract software header fields */ 3302 chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); 3303 seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); 3304 doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); 3305 txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); 3306 3307 bus->nextlen = 3308 bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; 3309 if ((bus->nextlen << 4) > MAX_RX_DATASZ) { 3310 DHD_INFO(("%s (nextlen): got frame w/nextlen too large" 3311 " (%d), seq %d\n", __FUNCTION__, bus->nextlen, 3312 seq)); 3313 bus->nextlen = 0; 3314 } 3315 3316 bus->dhd->rx_readahead_cnt ++; 3317 /* Handle Flow Control */ 3318 fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); 3319 3320 delta = 0; 3321 if (~bus->flowcontrol & fcbits) { 3322 bus->fc_xoff++; 3323 delta = 1; 3324 } 3325 if (bus->flowcontrol & ~fcbits) { 3326 bus->fc_xon++; 3327 delta = 1; 3328 } 3329 3330 if (delta) { 3331 bus->fc_rcvd++; 3332 bus->flowcontrol = fcbits; 3333 } 3334 3335 /* Check and update sequence number */ 3336 if (rxseq != seq) { 3337 DHD_INFO(("%s (nextlen): rx_seq %d, expected %d\n", 3338 __FUNCTION__, seq, rxseq)); 3339 bus->rx_badseq++; 3340 rxseq = seq; 3341 } 3342 3343 /* Check window for sanity */ 3344 if ((uint8)(txmax - bus->tx_seq) > 0x40) { 3345 DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", 3346 __FUNCTION__, txmax, bus->tx_seq)); 3347 txmax = bus->tx_seq + 2; 3348 } 3349 bus->tx_max = txmax; 3350 3351 #ifdef DHD_DEBUG 3352 if (DHD_BYTES_ON() && DHD_DATA_ON()) { 3353 prhex("Rx Data", rxbuf, len); 3354 } else if (DHD_HDRS_ON()) { 3355 prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN); 3356 } 3357 #endif 3358 3359 if (chan == SDPCM_CONTROL_CHANNEL) { 3360 if (bus->bus == SPI_BUS) { 3361 dhdsdio_read_control(bus, rxbuf, len, doff); 3362 if (bus->usebufpool) { 3363 dhd_os_sdlock_rxq(bus->dhd); 3364 PKTFREE(bus->dhd->osh, pkt, FALSE); 3365 dhd_os_sdunlock_rxq(bus->dhd); 3366 } 3367 continue; 3368 } else { 3369 DHD_ERROR(("%s (nextlen): readahead on control" 3370 " packet %d?\n", __FUNCTION__, seq)); 3371 /* Force retry w/normal header read */ 3372 bus->nextlen = 0; 3373 dhdsdio_rxfail(bus, FALSE, TRUE); 3374 dhd_os_sdlock_rxq(bus->dhd); 3375 PKTFREE2(); 3376 dhd_os_sdunlock_rxq(bus->dhd); 3377 continue; 3378 } 3379 } 3380 3381 if ((bus->bus == SPI_BUS) && !bus->usebufpool) { 3382 DHD_ERROR(("Received %d bytes on %d channel. Running out of " 3383 "rx pktbuf's or not yet malloced.\n", len, chan)); 3384 continue; 3385 } 3386 3387 /* Validate data offset */ 3388 if ((doff < SDPCM_HDRLEN) || (doff > len)) { 3389 DHD_ERROR(("%s (nextlen): bad data offset %d: HW len %d min %d\n", 3390 __FUNCTION__, doff, len, SDPCM_HDRLEN)); 3391 dhd_os_sdlock_rxq(bus->dhd); 3392 PKTFREE2(); 3393 dhd_os_sdunlock_rxq(bus->dhd); 3394 ASSERT(0); 3395 dhdsdio_rxfail(bus, FALSE, FALSE); 3396 continue; 3397 } 3398 3399 /* All done with this one -- now deliver the packet */ 3400 goto deliver; 3401 } 3402 /* gSPI frames should not be handled in fractions */ 3403 if (bus->bus == SPI_BUS) { 3404 break; 3405 } 3406 3407 /* Read frame header (hardware and software) */ 3408 sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, 3409 bus->rxhdr, firstread, NULL, NULL, NULL); 3410 bus->f2rxhdrs++; 3411 ASSERT(sdret != BCME_PENDING); 3412 3413 if (sdret < 0) { 3414 DHD_ERROR(("%s: RXHEADER FAILED: %d\n", __FUNCTION__, sdret)); 3415 bus->rx_hdrfail++; 3416 dhdsdio_rxfail(bus, TRUE, TRUE); 3417 continue; 3418 } 3419 3420 #ifdef DHD_DEBUG 3421 if (DHD_BYTES_ON() || DHD_HDRS_ON()) { 3422 prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN); 3423 } 3424 #endif 3425 3426 /* Extract hardware header fields */ 3427 len = ltoh16_ua(bus->rxhdr); 3428 check = ltoh16_ua(bus->rxhdr + sizeof(uint16)); 3429 3430 /* All zeros means no more frames */ 3431 if (!(len|check)) { 3432 *finished = TRUE; 3433 break; 3434 } 3435 3436 /* Validate check bytes */ 3437 if ((uint16)~(len^check)) { 3438 DHD_ERROR(("%s: HW hdr error: len/check 0x%04x/0x%04x\n", 3439 __FUNCTION__, len, check)); 3440 bus->rx_badhdr++; 3441 dhdsdio_rxfail(bus, FALSE, FALSE); 3442 continue; 3443 } 3444 3445 /* Validate frame length */ 3446 if (len < SDPCM_HDRLEN) { 3447 DHD_ERROR(("%s: HW hdr length invalid: %d\n", __FUNCTION__, len)); 3448 continue; 3449 } 3450 3451 /* Extract software header fields */ 3452 chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); 3453 seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); 3454 doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); 3455 txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); 3456 3457 /* Validate data offset */ 3458 if ((doff < SDPCM_HDRLEN) || (doff > len)) { 3459 DHD_ERROR(("%s: Bad data offset %d: HW len %d, min %d seq %d\n", 3460 __FUNCTION__, doff, len, SDPCM_HDRLEN, seq)); 3461 bus->rx_badhdr++; 3462 ASSERT(0); 3463 dhdsdio_rxfail(bus, FALSE, FALSE); 3464 continue; 3465 } 3466 3467 /* Save the readahead length if there is one */ 3468 bus->nextlen = bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; 3469 if ((bus->nextlen << 4) > MAX_RX_DATASZ) { 3470 DHD_INFO(("%s (nextlen): got frame w/nextlen too large (%d), seq %d\n", 3471 __FUNCTION__, bus->nextlen, seq)); 3472 bus->nextlen = 0; 3473 } 3474 3475 /* Handle Flow Control */ 3476 fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); 3477 3478 delta = 0; 3479 if (~bus->flowcontrol & fcbits) { 3480 bus->fc_xoff++; 3481 delta = 1; 3482 } 3483 if (bus->flowcontrol & ~fcbits) { 3484 bus->fc_xon++; 3485 delta = 1; 3486 } 3487 3488 if (delta) { 3489 bus->fc_rcvd++; 3490 bus->flowcontrol = fcbits; 3491 } 3492 3493 /* Check and update sequence number */ 3494 if (rxseq != seq) { 3495 DHD_INFO(("%s: rx_seq %d, expected %d\n", __FUNCTION__, seq, rxseq)); 3496 bus->rx_badseq++; 3497 rxseq = seq; 3498 } 3499 3500 /* Check window for sanity */ 3501 if ((uint8)(txmax - bus->tx_seq) > 0x40) { 3502 DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", 3503 __FUNCTION__, txmax, bus->tx_seq)); 3504 txmax = bus->tx_seq + 2; 3505 } 3506 bus->tx_max = txmax; 3507 3508 /* Call a separate function for control frames */ 3509 if (chan == SDPCM_CONTROL_CHANNEL) { 3510 dhdsdio_read_control(bus, bus->rxhdr, len, doff); 3511 continue; 3512 } 3513 3514 ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL) || 3515 (chan == SDPCM_TEST_CHANNEL) || (chan == SDPCM_GLOM_CHANNEL)); 3516 3517 /* Length to read */ 3518 rdlen = (len > firstread) ? (len - firstread) : 0; 3519 3520 /* May pad read to blocksize for efficiency */ 3521 if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) { 3522 pad = bus->blocksize - (rdlen % bus->blocksize); 3523 if ((pad <= bus->roundup) && (pad < bus->blocksize) && 3524 ((rdlen + pad + firstread) < MAX_RX_DATASZ)) 3525 rdlen += pad; 3526 } else if (rdlen % DHD_SDALIGN) { 3527 rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN); 3528 } 3529 3530 /* Satisfy length-alignment requirements */ 3531 if (forcealign && (rdlen & (ALIGNMENT - 1))) 3532 rdlen = ROUNDUP(rdlen, ALIGNMENT); 3533 3534 if ((rdlen + firstread) > MAX_RX_DATASZ) { 3535 /* Too long -- skip this frame */ 3536 DHD_ERROR(("%s: too long: len %d rdlen %d\n", __FUNCTION__, len, rdlen)); 3537 bus->dhd->rx_errors++; bus->rx_toolong++; 3538 dhdsdio_rxfail(bus, FALSE, FALSE); 3539 continue; 3540 } 3541 3542 dhd_os_sdlock_rxq(bus->dhd); 3543 if (!(pkt = PKTGET(osh, (rdlen + firstread + DHD_SDALIGN), FALSE))) { 3544 /* Give up on data, request rtx of events */ 3545 DHD_ERROR(("%s: PKTGET failed: rdlen %d chan %d\n", 3546 __FUNCTION__, rdlen, chan)); 3547 bus->dhd->rx_dropped++; 3548 dhd_os_sdunlock_rxq(bus->dhd); 3549 dhdsdio_rxfail(bus, FALSE, RETRYCHAN(chan)); 3550 continue; 3551 } 3552 dhd_os_sdunlock_rxq(bus->dhd); 3553 3554 ASSERT(!PKTLINK(pkt)); 3555 3556 /* Leave room for what we already read, and align remainder */ 3557 ASSERT(firstread < (PKTLEN(osh, pkt))); 3558 PKTPULL(osh, pkt, firstread); 3559 PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN); 3560 3561 /* Read the remaining frame data */ 3562 sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, 3563 ((uint8 *)PKTDATA(osh, pkt)), rdlen, pkt, NULL, NULL); 3564 bus->f2rxdata++; 3565 ASSERT(sdret != BCME_PENDING); 3566 3567 if (sdret < 0) { 3568 DHD_ERROR(("%s: read %d %s bytes failed: %d\n", __FUNCTION__, rdlen, 3569 ((chan == SDPCM_EVENT_CHANNEL) ? "event" : 3570 ((chan == SDPCM_DATA_CHANNEL) ? "data" : "test")), sdret)); 3571 dhd_os_sdlock_rxq(bus->dhd); 3572 PKTFREE(bus->dhd->osh, pkt, FALSE); 3573 dhd_os_sdunlock_rxq(bus->dhd); 3574 bus->dhd->rx_errors++; 3575 dhdsdio_rxfail(bus, TRUE, RETRYCHAN(chan)); 3576 continue; 3577 } 3578 3579 /* Copy the already-read portion */ 3580 PKTPUSH(osh, pkt, firstread); 3581 bcopy(bus->rxhdr, PKTDATA(osh, pkt), firstread); 3582 3583 #ifdef DHD_DEBUG 3584 if (DHD_BYTES_ON() && DHD_DATA_ON()) { 3585 prhex("Rx Data", PKTDATA(osh, pkt), len); 3586 } 3587 #endif 3588 3589 deliver: 3590 /* Save superframe descriptor and allocate packet frame */ 3591 if (chan == SDPCM_GLOM_CHANNEL) { 3592 if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) { 3593 DHD_GLOM(("%s: got glom descriptor, %d bytes:\n", 3594 __FUNCTION__, len)); 3595 #ifdef DHD_DEBUG 3596 if (DHD_GLOM_ON()) { 3597 prhex("Glom Data", PKTDATA(osh, pkt), len); 3598 } 3599 #endif 3600 PKTSETLEN(osh, pkt, len); 3601 ASSERT(doff == SDPCM_HDRLEN); 3602 PKTPULL(osh, pkt, SDPCM_HDRLEN); 3603 bus->glomd = pkt; 3604 } else { 3605 DHD_ERROR(("%s: glom superframe w/o descriptor!\n", __FUNCTION__)); 3606 dhdsdio_rxfail(bus, FALSE, FALSE); 3607 } 3608 continue; 3609 } 3610 3611 /* Fill in packet len and prio, deliver upward */ 3612 PKTSETLEN(osh, pkt, len); 3613 PKTPULL(osh, pkt, doff); 3614 3615 #ifdef SDTEST 3616 /* Test channel packets are processed separately */ 3617 if (chan == SDPCM_TEST_CHANNEL) { 3618 dhdsdio_testrcv(bus, pkt, seq); 3619 continue; 3620 } 3621 #endif /* SDTEST */ 3622 3623 if (PKTLEN(osh, pkt) == 0) { 3624 dhd_os_sdlock_rxq(bus->dhd); 3625 PKTFREE(bus->dhd->osh, pkt, FALSE); 3626 dhd_os_sdunlock_rxq(bus->dhd); 3627 continue; 3628 } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pkt) != 0) { 3629 DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__)); 3630 dhd_os_sdlock_rxq(bus->dhd); 3631 PKTFREE(bus->dhd->osh, pkt, FALSE); 3632 dhd_os_sdunlock_rxq(bus->dhd); 3633 bus->dhd->rx_errors++; 3634 continue; 3635 } 3636 3637 3638 /* Unlock during rx call */ 3639 dhd_os_sdunlock(bus->dhd); 3640 dhd_rx_frame(bus->dhd, ifidx, pkt, 1); 3641 dhd_os_sdlock(bus->dhd); 3642 } 3643 rxcount = maxframes - rxleft; 3644 #ifdef DHD_DEBUG 3645 /* Message if we hit the limit */ 3646 if (!rxleft && !sdtest) 3647 DHD_DATA(("%s: hit rx limit of %d frames\n", __FUNCTION__, maxframes)); 3648 else 3649 #endif /* DHD_DEBUG */ 3650 DHD_DATA(("%s: processed %d frames\n", __FUNCTION__, rxcount)); 3651 /* Back off rxseq if awaiting rtx, update rx_seq */ 3652 if (bus->rxskip) 3653 rxseq--; 3654 bus->rx_seq = rxseq; 3655 3656 return rxcount; 3657 } 3658 3659 static uint32 3660 dhdsdio_hostmail(dhd_bus_t *bus) 3661 { 3662 sdpcmd_regs_t *regs = bus->regs; 3663 uint32 intstatus = 0; 3664 uint32 hmb_data; 3665 uint8 fcbits; 3666 uint retries = 0; 3667 3668 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 3669 3670 /* Read mailbox data and ack that we did so */ 3671 R_SDREG(hmb_data, ®s->tohostmailboxdata, retries); 3672 if (retries <= retry_limit) 3673 W_SDREG(SMB_INT_ACK, ®s->tosbmailbox, retries); 3674 bus->f1regdata += 2; 3675 3676 /* Dongle recomposed rx frames, accept them again */ 3677 if (hmb_data & HMB_DATA_NAKHANDLED) { 3678 DHD_INFO(("Dongle reports NAK handled, expect rtx of %d\n", bus->rx_seq)); 3679 if (!bus->rxskip) { 3680 DHD_ERROR(("%s: unexpected NAKHANDLED!\n", __FUNCTION__)); 3681 } 3682 bus->rxskip = FALSE; 3683 intstatus |= I_HMB_FRAME_IND; 3684 } 3685 3686 /* 3687 * DEVREADY does not occur with gSPI. 3688 */ 3689 if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) { 3690 bus->sdpcm_ver = (hmb_data & HMB_DATA_VERSION_MASK) >> HMB_DATA_VERSION_SHIFT; 3691 if (bus->sdpcm_ver != SDPCM_PROT_VERSION) 3692 DHD_ERROR(("Version mismatch, dongle reports %d, expecting %d\n", 3693 bus->sdpcm_ver, SDPCM_PROT_VERSION)); 3694 else 3695 DHD_INFO(("Dongle ready, protocol version %d\n", bus->sdpcm_ver)); 3696 } 3697 3698 /* 3699 * Flow Control has been moved into the RX headers and this out of band 3700 * method isn't used any more. Leae this here for possibly remaining backward 3701 * compatible with older dongles 3702 */ 3703 if (hmb_data & HMB_DATA_FC) { 3704 fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >> HMB_DATA_FCDATA_SHIFT; 3705 3706 if (fcbits & ~bus->flowcontrol) 3707 bus->fc_xoff++; 3708 if (bus->flowcontrol & ~fcbits) 3709 bus->fc_xon++; 3710 3711 bus->fc_rcvd++; 3712 bus->flowcontrol = fcbits; 3713 } 3714 3715 /* Shouldn't be any others */ 3716 if (hmb_data & ~(HMB_DATA_DEVREADY | 3717 HMB_DATA_NAKHANDLED | 3718 HMB_DATA_FC | 3719 HMB_DATA_FWREADY | 3720 HMB_DATA_FCDATA_MASK | 3721 HMB_DATA_VERSION_MASK)) { 3722 DHD_ERROR(("Unknown mailbox data content: 0x%02x\n", hmb_data)); 3723 } 3724 3725 return intstatus; 3726 } 3727 3728 bool 3729 dhdsdio_dpc(dhd_bus_t *bus) 3730 { 3731 bcmsdh_info_t *sdh = bus->sdh; 3732 sdpcmd_regs_t *regs = bus->regs; 3733 uint32 intstatus, newstatus = 0; 3734 uint retries = 0; 3735 uint rxlimit = dhd_rxbound; /* Rx frames to read before resched */ 3736 uint txlimit = dhd_txbound; /* Tx frames to send before resched */ 3737 uint framecnt = 0; /* Temporary counter of tx/rx frames */ 3738 bool rxdone = TRUE; /* Flag for no more read data */ 3739 bool resched = FALSE; /* Flag indicating resched wanted */ 3740 3741 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 3742 3743 /* Start with leftover status bits */ 3744 intstatus = bus->intstatus; 3745 3746 dhd_os_sdlock(bus->dhd); 3747 3748 /* If waiting for HTAVAIL, check status */ 3749 if (bus->clkstate == CLK_PENDING) { 3750 int err; 3751 uint8 clkctl, devctl = 0; 3752 3753 #ifdef DHD_DEBUG 3754 /* Check for inconsistent device control */ 3755 devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); 3756 if (err) { 3757 DHD_ERROR(("%s: error reading DEVCTL: %d\n", __FUNCTION__, err)); 3758 bus->dhd->busstate = DHD_BUS_DOWN; 3759 } else { 3760 ASSERT(devctl & SBSDIO_DEVCTL_CA_INT_ONLY); 3761 } 3762 #endif /* DHD_DEBUG */ 3763 3764 /* Read CSR, if clock on switch to AVAIL, else ignore */ 3765 clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); 3766 if (err) { 3767 DHD_ERROR(("%s: error reading CSR: %d\n", __FUNCTION__, err)); 3768 bus->dhd->busstate = DHD_BUS_DOWN; 3769 } 3770 3771 DHD_INFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", devctl, clkctl)); 3772 3773 if (SBSDIO_HTAV(clkctl)) { 3774 devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); 3775 if (err) { 3776 DHD_ERROR(("%s: error reading DEVCTL: %d\n", 3777 __FUNCTION__, err)); 3778 bus->dhd->busstate = DHD_BUS_DOWN; 3779 } 3780 devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; 3781 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); 3782 if (err) { 3783 DHD_ERROR(("%s: error writing DEVCTL: %d\n", 3784 __FUNCTION__, err)); 3785 bus->dhd->busstate = DHD_BUS_DOWN; 3786 } 3787 bus->clkstate = CLK_AVAIL; 3788 } else { 3789 goto clkwait; 3790 } 3791 } 3792 3793 BUS_WAKE(bus); 3794 3795 /* Make sure backplane clock is on */ 3796 dhdsdio_clkctl(bus, CLK_AVAIL, TRUE); 3797 if (bus->clkstate == CLK_PENDING) 3798 goto clkwait; 3799 3800 /* Pending interrupt indicates new device status */ 3801 if (bus->ipend) { 3802 bus->ipend = FALSE; 3803 R_SDREG(newstatus, ®s->intstatus, retries); 3804 bus->f1regdata++; 3805 if (bcmsdh_regfail(bus->sdh)) 3806 newstatus = 0; 3807 newstatus &= bus->hostintmask; 3808 bus->fcstate = !!(newstatus & I_HMB_FC_STATE); 3809 if (newstatus) { 3810 W_SDREG(newstatus, ®s->intstatus, retries); 3811 bus->f1regdata++; 3812 } 3813 } 3814 3815 /* Merge new bits with previous */ 3816 intstatus |= newstatus; 3817 bus->intstatus = 0; 3818 3819 /* Handle flow-control change: read new state in case our ack 3820 * crossed another change interrupt. If change still set, assume 3821 * FC ON for safety, let next loop through do the debounce. 3822 */ 3823 if (intstatus & I_HMB_FC_CHANGE) { 3824 intstatus &= ~I_HMB_FC_CHANGE; 3825 W_SDREG(I_HMB_FC_CHANGE, ®s->intstatus, retries); 3826 R_SDREG(newstatus, ®s->intstatus, retries); 3827 bus->f1regdata += 2; 3828 bus->fcstate = !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)); 3829 intstatus |= (newstatus & bus->hostintmask); 3830 } 3831 3832 /* Handle host mailbox indication */ 3833 if (intstatus & I_HMB_HOST_INT) { 3834 intstatus &= ~I_HMB_HOST_INT; 3835 intstatus |= dhdsdio_hostmail(bus); 3836 } 3837 3838 /* Generally don't ask for these, can get CRC errors... */ 3839 if (intstatus & I_WR_OOSYNC) { 3840 DHD_ERROR(("Dongle reports WR_OOSYNC\n")); 3841 intstatus &= ~I_WR_OOSYNC; 3842 } 3843 3844 if (intstatus & I_RD_OOSYNC) { 3845 DHD_ERROR(("Dongle reports RD_OOSYNC\n")); 3846 intstatus &= ~I_RD_OOSYNC; 3847 } 3848 3849 if (intstatus & I_SBINT) { 3850 DHD_ERROR(("Dongle reports SBINT\n")); 3851 intstatus &= ~I_SBINT; 3852 } 3853 3854 /* Would be active due to wake-wlan in gSPI */ 3855 if (intstatus & I_CHIPACTIVE) { 3856 DHD_INFO(("Dongle reports CHIPACTIVE\n")); 3857 intstatus &= ~I_CHIPACTIVE; 3858 } 3859 3860 /* Ignore frame indications if rxskip is set */ 3861 if (bus->rxskip) 3862 intstatus &= ~I_HMB_FRAME_IND; 3863 3864 /* On frame indication, read available frames */ 3865 if (PKT_AVAILABLE()) { 3866 framecnt = dhdsdio_readframes(bus, rxlimit, &rxdone); 3867 if (rxdone || bus->rxskip) 3868 intstatus &= ~I_HMB_FRAME_IND; 3869 rxlimit -= MIN(framecnt, rxlimit); 3870 } 3871 3872 /* Keep still-pending events for next scheduling */ 3873 bus->intstatus = intstatus; 3874 3875 clkwait: 3876 /* Re-enable interrupts to detect new device events (mailbox, rx frame) 3877 * or clock availability. (Allows tx loop to check ipend if desired.) 3878 * (Unless register access seems hosed, as we may not be able to ACK...) 3879 */ 3880 if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh)) { 3881 DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n", 3882 __FUNCTION__, rxdone, framecnt)); 3883 bus->intdis = FALSE; 3884 bcmsdh_intr_enable(sdh); 3885 } 3886 3887 if (DATAOK(bus) && bus->ctrl_frame_stat) { 3888 int ret, i; 3889 3890 ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, 3891 (uint8 *)bus->ctrl_frame_buf, (uint32)bus->ctrl_frame_len, 3892 NULL, NULL, NULL); 3893 ASSERT(ret != BCME_PENDING); 3894 3895 if (ret < 0) { 3896 /* On failure, abort the command and terminate the frame */ 3897 DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n", 3898 __FUNCTION__, ret)); 3899 bus->tx_sderrs++; 3900 3901 bcmsdh_abort(sdh, SDIO_FUNC_2); 3902 3903 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, 3904 SFC_WF_TERM, NULL); 3905 bus->f1regdata++; 3906 3907 for (i = 0; i < 3; i++) { 3908 uint8 hi, lo; 3909 hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, 3910 SBSDIO_FUNC1_WFRAMEBCHI, NULL); 3911 lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, 3912 SBSDIO_FUNC1_WFRAMEBCLO, NULL); 3913 bus->f1regdata += 2; 3914 if ((hi == 0) && (lo == 0)) 3915 break; 3916 } 3917 3918 } 3919 printf("Return_dpc value is : %d\n", ret); 3920 bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; 3921 bus->ctrl_frame_stat = FALSE; 3922 dhd_wait_event_wakeup(bus->dhd); 3923 } 3924 /* Send queued frames (limit 1 if rx may still be pending) */ 3925 else if ((bus->clkstate != CLK_PENDING) && !bus->fcstate && 3926 pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit && DATAOK(bus)) { 3927 framecnt = rxdone ? txlimit : MIN(txlimit, dhd_txminmax); 3928 framecnt = dhdsdio_sendfromq(bus, framecnt); 3929 txlimit -= framecnt; 3930 } 3931 3932 /* Resched if events or tx frames are pending, else await next interrupt */ 3933 /* On failed register access, all bets are off: no resched or interrupts */ 3934 if ((bus->dhd->busstate == DHD_BUS_DOWN) || bcmsdh_regfail(sdh)) { 3935 DHD_ERROR(("%s: failed backplane access over SDIO, halting operation %d \n", 3936 __FUNCTION__, bcmsdh_regfail(sdh))); 3937 bus->dhd->busstate = DHD_BUS_DOWN; 3938 bus->intstatus = 0; 3939 } else if (bus->clkstate == CLK_PENDING) { 3940 /* Awaiting I_CHIPACTIVE; don't resched */ 3941 } else if (bus->intstatus || bus->ipend || 3942 (!bus->fcstate && pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) || 3943 PKT_AVAILABLE()) { /* Read multiple frames */ 3944 resched = TRUE; 3945 } 3946 3947 3948 bus->dpc_sched = resched; 3949 3950 /* If we're done for now, turn off clock request. */ 3951 if ((bus->clkstate != CLK_PENDING) && bus->idletime == DHD_IDLE_IMMEDIATE) { 3952 bus->activity = FALSE; 3953 dhdsdio_clkctl(bus, CLK_NONE, FALSE); 3954 } 3955 3956 dhd_os_sdunlock(bus->dhd); 3957 3958 return resched; 3959 } 3960 3961 bool 3962 dhd_bus_dpc(struct dhd_bus *bus) 3963 { 3964 #ifdef SDIO_ISR_THREAD 3965 bool resched; 3966 3967 /* Call the DPC directly. */ 3968 DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__)); 3969 resched = dhdsdio_dpc(bus); 3970 3971 return resched; 3972 #else 3973 return dhdsdio_dpc(bus); 3974 #endif /* SDIO_ISR_THREAD */ 3975 } 3976 3977 void 3978 dhdsdio_isr(void *arg) 3979 { 3980 dhd_bus_t *bus = (dhd_bus_t*)arg; 3981 bcmsdh_info_t *sdh; 3982 3983 if (!bus) { 3984 DHD_ERROR(("%s : bus is null pointer , exit \n", __FUNCTION__)); 3985 return; 3986 } 3987 sdh = bus->sdh; 3988 3989 if (bus->dhd->busstate == DHD_BUS_DOWN) { 3990 DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__)); 3991 return; 3992 } 3993 3994 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 3995 3996 /* Count the interrupt call */ 3997 bus->intrcount++; 3998 bus->ipend = TRUE; 3999 4000 /* Shouldn't get this interrupt if we're sleeping? */ 4001 if (bus->sleeping) { 4002 DHD_ERROR(("INTERRUPT WHILE SLEEPING??\n")); 4003 return; 4004 } 4005 4006 /* Disable additional interrupts (is this needed now)? */ 4007 if (bus->intr) { 4008 DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); 4009 } else { 4010 DHD_ERROR(("dhdsdio_isr() w/o interrupt configured!\n")); 4011 } 4012 4013 bcmsdh_intr_disable(sdh); 4014 bus->intdis = TRUE; 4015 4016 #if defined(SDIO_ISR_THREAD) 4017 DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__)); 4018 dhd_os_wake_lock(bus->dhd); 4019 while (dhdsdio_dpc(bus)); 4020 dhd_os_wake_unlock(bus->dhd); 4021 #else 4022 bus->dpc_sched = TRUE; 4023 dhd_sched_dpc(bus->dhd); 4024 #endif 4025 4026 } 4027 4028 #ifdef SDTEST 4029 static void 4030 dhdsdio_pktgen_init(dhd_bus_t *bus) 4031 { 4032 /* Default to specified length, or full range */ 4033 if (dhd_pktgen_len) { 4034 bus->pktgen_maxlen = MIN(dhd_pktgen_len, MAX_PKTGEN_LEN); 4035 bus->pktgen_minlen = bus->pktgen_maxlen; 4036 } else { 4037 bus->pktgen_maxlen = MAX_PKTGEN_LEN; 4038 bus->pktgen_minlen = 0; 4039 } 4040 bus->pktgen_len = (uint16)bus->pktgen_minlen; 4041 4042 /* Default to per-watchdog burst with 10s print time */ 4043 bus->pktgen_freq = 1; 4044 bus->pktgen_print = 10000 / dhd_watchdog_ms; 4045 bus->pktgen_count = (dhd_pktgen * dhd_watchdog_ms + 999) / 1000; 4046 4047 /* Default to echo mode */ 4048 bus->pktgen_mode = DHD_PKTGEN_ECHO; 4049 bus->pktgen_stop = 1; 4050 } 4051 4052 static void 4053 dhdsdio_pktgen(dhd_bus_t *bus) 4054 { 4055 void *pkt; 4056 uint8 *data; 4057 uint pktcount; 4058 uint fillbyte; 4059 osl_t *osh = bus->dhd->osh; 4060 uint16 len; 4061 4062 /* Display current count if appropriate */ 4063 if (bus->pktgen_print && (++bus->pktgen_ptick >= bus->pktgen_print)) { 4064 bus->pktgen_ptick = 0; 4065 printf("%s: send attempts %d rcvd %d\n", 4066 __FUNCTION__, bus->pktgen_sent, bus->pktgen_rcvd); 4067 } 4068 4069 /* For recv mode, just make sure dongle has started sending */ 4070 if (bus->pktgen_mode == DHD_PKTGEN_RECV) { 4071 if (!bus->pktgen_rcvd) 4072 dhdsdio_sdtest_set(bus, TRUE); 4073 return; 4074 } 4075 4076 /* Otherwise, generate or request the specified number of packets */ 4077 for (pktcount = 0; pktcount < bus->pktgen_count; pktcount++) { 4078 /* Stop if total has been reached */ 4079 if (bus->pktgen_total && (bus->pktgen_sent >= bus->pktgen_total)) { 4080 bus->pktgen_count = 0; 4081 break; 4082 } 4083 4084 /* Allocate an appropriate-sized packet */ 4085 len = bus->pktgen_len; 4086 if (!(pkt = PKTGET(osh, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN), 4087 TRUE))) {; 4088 DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__)); 4089 break; 4090 } 4091 PKTALIGN(osh, pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN); 4092 data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN; 4093 4094 /* Write test header cmd and extra based on mode */ 4095 switch (bus->pktgen_mode) { 4096 case DHD_PKTGEN_ECHO: 4097 *data++ = SDPCM_TEST_ECHOREQ; 4098 *data++ = (uint8)bus->pktgen_sent; 4099 break; 4100 4101 case DHD_PKTGEN_SEND: 4102 *data++ = SDPCM_TEST_DISCARD; 4103 *data++ = (uint8)bus->pktgen_sent; 4104 break; 4105 4106 case DHD_PKTGEN_RXBURST: 4107 *data++ = SDPCM_TEST_BURST; 4108 *data++ = (uint8)bus->pktgen_count; 4109 break; 4110 4111 default: 4112 DHD_ERROR(("Unrecognized pktgen mode %d\n", bus->pktgen_mode)); 4113 PKTFREE(osh, pkt, TRUE); 4114 bus->pktgen_count = 0; 4115 return; 4116 } 4117 4118 /* Write test header length field */ 4119 *data++ = (len >> 0); 4120 *data++ = (len >> 8); 4121 4122 /* Then fill in the remainder -- N/A for burst, but who cares... */ 4123 for (fillbyte = 0; fillbyte < len; fillbyte++) 4124 *data++ = SDPCM_TEST_FILL(fillbyte, (uint8)bus->pktgen_sent); 4125 4126 #ifdef DHD_DEBUG 4127 if (DHD_BYTES_ON() && DHD_DATA_ON()) { 4128 data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN; 4129 prhex("dhdsdio_pktgen: Tx Data", data, PKTLEN(osh, pkt) - SDPCM_HDRLEN); 4130 } 4131 #endif 4132 4133 /* Send it */ 4134 if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, TRUE)) { 4135 bus->pktgen_fail++; 4136 if (bus->pktgen_stop && bus->pktgen_stop == bus->pktgen_fail) 4137 bus->pktgen_count = 0; 4138 } 4139 bus->pktgen_sent++; 4140 4141 /* Bump length if not fixed, wrap at max */ 4142 if (++bus->pktgen_len > bus->pktgen_maxlen) 4143 bus->pktgen_len = (uint16)bus->pktgen_minlen; 4144 4145 /* Special case for burst mode: just send one request! */ 4146 if (bus->pktgen_mode == DHD_PKTGEN_RXBURST) 4147 break; 4148 } 4149 } 4150 4151 static void 4152 dhdsdio_sdtest_set(dhd_bus_t *bus, bool start) 4153 { 4154 void *pkt; 4155 uint8 *data; 4156 osl_t *osh = bus->dhd->osh; 4157 4158 /* Allocate the packet */ 4159 if (!(pkt = PKTGET(osh, SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN, TRUE))) { 4160 DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__)); 4161 return; 4162 } 4163 PKTALIGN(osh, pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN); 4164 data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN; 4165 4166 /* Fill in the test header */ 4167 *data++ = SDPCM_TEST_SEND; 4168 *data++ = start; 4169 *data++ = (bus->pktgen_maxlen >> 0); 4170 *data++ = (bus->pktgen_maxlen >> 8); 4171 4172 /* Send it */ 4173 if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, TRUE)) 4174 bus->pktgen_fail++; 4175 } 4176 4177 4178 static void 4179 dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq) 4180 { 4181 osl_t *osh = bus->dhd->osh; 4182 uint8 *data; 4183 uint pktlen; 4184 4185 uint8 cmd; 4186 uint8 extra; 4187 uint16 len; 4188 uint16 offset; 4189 4190 /* Check for min length */ 4191 if ((pktlen = PKTLEN(osh, pkt)) < SDPCM_TEST_HDRLEN) { 4192 DHD_ERROR(("dhdsdio_restrcv: toss runt frame, pktlen %d\n", pktlen)); 4193 PKTFREE(osh, pkt, FALSE); 4194 return; 4195 } 4196 4197 /* Extract header fields */ 4198 data = PKTDATA(osh, pkt); 4199 cmd = *data++; 4200 extra = *data++; 4201 len = *data++; len += *data++ << 8; 4202 4203 /* Check length for relevant commands */ 4204 if (cmd == SDPCM_TEST_DISCARD || cmd == SDPCM_TEST_ECHOREQ || cmd == SDPCM_TEST_ECHORSP) { 4205 if (pktlen != len + SDPCM_TEST_HDRLEN) { 4206 DHD_ERROR(("dhdsdio_testrcv: frame length mismatch, pktlen %d seq %d" 4207 " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len)); 4208 PKTFREE(osh, pkt, FALSE); 4209 return; 4210 } 4211 } 4212 4213 /* Process as per command */ 4214 switch (cmd) { 4215 case SDPCM_TEST_ECHOREQ: 4216 /* Rx->Tx turnaround ok (even on NDIS w/current implementation) */ 4217 *(uint8 *)(PKTDATA(osh, pkt)) = SDPCM_TEST_ECHORSP; 4218 if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, TRUE) == 0) { 4219 bus->pktgen_sent++; 4220 } else { 4221 bus->pktgen_fail++; 4222 PKTFREE(osh, pkt, FALSE); 4223 } 4224 bus->pktgen_rcvd++; 4225 break; 4226 4227 case SDPCM_TEST_ECHORSP: 4228 if (bus->ext_loop) { 4229 PKTFREE(osh, pkt, FALSE); 4230 bus->pktgen_rcvd++; 4231 break; 4232 } 4233 4234 for (offset = 0; offset < len; offset++, data++) { 4235 if (*data != SDPCM_TEST_FILL(offset, extra)) { 4236 DHD_ERROR(("dhdsdio_testrcv: echo data mismatch: " 4237 "offset %d (len %d) expect 0x%02x rcvd 0x%02x\n", 4238 offset, len, SDPCM_TEST_FILL(offset, extra), *data)); 4239 break; 4240 } 4241 } 4242 PKTFREE(osh, pkt, FALSE); 4243 bus->pktgen_rcvd++; 4244 break; 4245 4246 case SDPCM_TEST_DISCARD: 4247 PKTFREE(osh, pkt, FALSE); 4248 bus->pktgen_rcvd++; 4249 break; 4250 4251 case SDPCM_TEST_BURST: 4252 case SDPCM_TEST_SEND: 4253 default: 4254 DHD_INFO(("dhdsdio_testrcv: unsupported or unknown command, pktlen %d seq %d" 4255 " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len)); 4256 PKTFREE(osh, pkt, FALSE); 4257 break; 4258 } 4259 4260 /* For recv mode, stop at limie (and tell dongle to stop sending) */ 4261 if (bus->pktgen_mode == DHD_PKTGEN_RECV) { 4262 if (bus->pktgen_total && (bus->pktgen_rcvd >= bus->pktgen_total)) { 4263 bus->pktgen_count = 0; 4264 dhdsdio_sdtest_set(bus, FALSE); 4265 } 4266 } 4267 } 4268 #endif /* SDTEST */ 4269 4270 extern bool 4271 dhd_bus_watchdog(dhd_pub_t *dhdp) 4272 { 4273 dhd_bus_t *bus; 4274 4275 DHD_TIMER(("%s: Enter\n", __FUNCTION__)); 4276 4277 bus = dhdp->bus; 4278 4279 if (bus->dhd->dongle_reset) 4280 return FALSE; 4281 4282 /* Ignore the timer if simulating bus down */ 4283 if (bus->sleeping) 4284 return FALSE; 4285 4286 dhd_os_sdlock(bus->dhd); 4287 4288 /* Poll period: check device if appropriate. */ 4289 if (bus->poll && (++bus->polltick >= bus->pollrate)) { 4290 uint32 intstatus = 0; 4291 4292 /* Reset poll tick */ 4293 bus->polltick = 0; 4294 4295 /* Check device if no interrupts */ 4296 if (!bus->intr || (bus->intrcount == bus->lastintrs)) { 4297 4298 if (!bus->dpc_sched) { 4299 uint8 devpend; 4300 devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, 4301 SDIOD_CCCR_INTPEND, NULL); 4302 intstatus = devpend & (INTR_STATUS_FUNC1 | INTR_STATUS_FUNC2); 4303 } 4304 4305 /* If there is something, make like the ISR and schedule the DPC */ 4306 if (intstatus) { 4307 bus->pollcnt++; 4308 bus->ipend = TRUE; 4309 if (bus->intr) { 4310 bcmsdh_intr_disable(bus->sdh); 4311 } 4312 bus->dpc_sched = TRUE; 4313 dhd_sched_dpc(bus->dhd); 4314 4315 } 4316 } 4317 4318 /* Update interrupt tracking */ 4319 bus->lastintrs = bus->intrcount; 4320 } 4321 4322 4323 #ifdef SDTEST 4324 /* Generate packets if configured */ 4325 if (bus->pktgen_count && (++bus->pktgen_tick >= bus->pktgen_freq)) { 4326 /* Make sure backplane clock is on */ 4327 dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); 4328 bus->pktgen_tick = 0; 4329 dhdsdio_pktgen(bus); 4330 } 4331 #endif 4332 4333 /* On idle timeout clear activity flag and/or turn off clock */ 4334 if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) { 4335 if (++bus->idlecount >= bus->idletime) { 4336 bus->idlecount = 0; 4337 if (bus->activity) { 4338 bus->activity = FALSE; 4339 } else { 4340 dhdsdio_clkctl(bus, CLK_NONE, FALSE); 4341 } 4342 } 4343 } 4344 4345 dhd_os_sdunlock(bus->dhd); 4346 4347 return bus->ipend; 4348 } 4349 4350 4351 #ifdef DHD_DEBUG 4352 static void 4353 dhd_dump_cis(uint fn, uint8 *cis) 4354 { 4355 uint byte, tag, tdata; 4356 DHD_INFO(("Function %d CIS:\n", fn)); 4357 4358 for (tdata = byte = 0; byte < SBSDIO_CIS_SIZE_LIMIT; byte++) { 4359 if ((byte % 16) == 0) 4360 DHD_INFO((" ")); 4361 DHD_INFO(("%02x ", cis[byte])); 4362 if ((byte % 16) == 15) 4363 DHD_INFO(("\n")); 4364 if (!tdata--) { 4365 tag = cis[byte]; 4366 if (tag == 0xff) 4367 break; 4368 else if (!tag) 4369 tdata = 0; 4370 else if ((byte + 1) < SBSDIO_CIS_SIZE_LIMIT) 4371 tdata = cis[byte + 1] + 1; 4372 else 4373 DHD_INFO(("]")); 4374 } 4375 } 4376 if ((byte % 16) != 15) 4377 DHD_INFO(("\n")); 4378 } 4379 #endif /* DHD_DEBUG */ 4380 4381 static bool 4382 dhdsdio_chipmatch(uint16 chipid) 4383 { 4384 if (chipid == BCM4325_CHIP_ID) 4385 return TRUE; 4386 if (chipid == BCM4329_CHIP_ID) 4387 return TRUE; 4388 if (chipid == BCM4315_CHIP_ID) 4389 return TRUE; 4390 if (chipid == BCM4319_CHIP_ID) 4391 return TRUE; 4392 return FALSE; 4393 } 4394 4395 static void * 4396 dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, 4397 uint16 func, uint bustype, void *regsva, osl_t * osh, void *sdh) 4398 { 4399 int ret; 4400 dhd_bus_t *bus; 4401 4402 /* Init global variables at run-time, not as part of the declaration. 4403 * This is required to support init/de-init of the driver. Initialization 4404 * of globals as part of the declaration results in non-deterministic 4405 * behavior since the value of the globals may be different on the 4406 * first time that the driver is initialized vs subsequent initializations. 4407 */ 4408 dhd_txbound = DHD_TXBOUND; 4409 dhd_rxbound = DHD_RXBOUND; 4410 dhd_alignctl = TRUE; 4411 sd1idle = TRUE; 4412 dhd_readahead = TRUE; 4413 retrydata = FALSE; 4414 dhd_doflow = FALSE; 4415 dhd_dongle_memsize = 0; 4416 dhd_txminmax = DHD_TXMINMAX; 4417 4418 forcealign = TRUE; 4419 4420 4421 dhd_common_init(); 4422 4423 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 4424 DHD_INFO(("%s: venid 0x%04x devid 0x%04x\n", __FUNCTION__, venid, devid)); 4425 4426 /* We make assumptions about address window mappings */ 4427 ASSERT((uintptr)regsva == SI_ENUM_BASE); 4428 4429 /* BCMSDH passes venid and devid based on CIS parsing -- but low-power start 4430 * means early parse could fail, so here we should get either an ID 4431 * we recognize OR (-1) indicating we must request power first. 4432 */ 4433 /* Check the Vendor ID */ 4434 switch (venid) { 4435 case 0x0000: 4436 case VENDOR_BROADCOM: 4437 break; 4438 default: 4439 DHD_ERROR(("%s: unknown vendor: 0x%04x\n", 4440 __FUNCTION__, venid)); 4441 return NULL; 4442 } 4443 4444 /* Check the Device ID and make sure it's one that we support */ 4445 switch (devid) { 4446 case BCM4325_D11DUAL_ID: /* 4325 802.11a/g id */ 4447 case BCM4325_D11G_ID: /* 4325 802.11g 2.4Ghz band id */ 4448 case BCM4325_D11A_ID: /* 4325 802.11a 5Ghz band id */ 4449 DHD_INFO(("%s: found 4325 Dongle\n", __FUNCTION__)); 4450 break; 4451 case BCM4329_D11NDUAL_ID: /* 4329 802.11n dualband device */ 4452 case BCM4329_D11N2G_ID: /* 4329 802.11n 2.4G device */ 4453 case BCM4329_D11N5G_ID: /* 4329 802.11n 5G device */ 4454 case 0x4329: 4455 DHD_INFO(("%s: found 4329 Dongle\n", __FUNCTION__)); 4456 break; 4457 case BCM4315_D11DUAL_ID: /* 4315 802.11a/g id */ 4458 case BCM4315_D11G_ID: /* 4315 802.11g id */ 4459 case BCM4315_D11A_ID: /* 4315 802.11a id */ 4460 DHD_INFO(("%s: found 4315 Dongle\n", __FUNCTION__)); 4461 break; 4462 case BCM4319_D11N_ID: /* 4319 802.11n id */ 4463 case BCM4319_D11N2G_ID: /* 4319 802.11n2g id */ 4464 case BCM4319_D11N5G_ID: /* 4319 802.11n5g id */ 4465 DHD_INFO(("%s: found 4319 Dongle\n", __FUNCTION__)); 4466 break; 4467 case 0: 4468 DHD_INFO(("%s: allow device id 0, will check chip internals\n", 4469 __FUNCTION__)); 4470 break; 4471 4472 default: 4473 DHD_ERROR(("%s: skipping 0x%04x/0x%04x, not a dongle\n", 4474 __FUNCTION__, venid, devid)); 4475 return NULL; 4476 } 4477 4478 if (osh == NULL) { 4479 /* Ask the OS interface part for an OSL handle */ 4480 if (!(osh = dhd_osl_attach(sdh, DHD_BUS))) { 4481 DHD_ERROR(("%s: osl_attach failed!\n", __FUNCTION__)); 4482 return NULL; 4483 } 4484 } 4485 4486 /* Allocate private bus interface state */ 4487 if (!(bus = MALLOC(osh, sizeof(dhd_bus_t)))) { 4488 DHD_ERROR(("%s: MALLOC of dhd_bus_t failed\n", __FUNCTION__)); 4489 goto fail; 4490 } 4491 bzero(bus, sizeof(dhd_bus_t)); 4492 bus->sdh = sdh; 4493 bus->cl_devid = (uint16)devid; 4494 bus->bus = DHD_BUS; 4495 bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1; 4496 bus->usebufpool = FALSE; /* Use bufpool if allocated, else use locally malloced rxbuf */ 4497 4498 /* attempt to attach to the dongle */ 4499 if (!(dhdsdio_probe_attach(bus, osh, sdh, regsva, devid))) { 4500 DHD_ERROR(("%s: dhdsdio_probe_attach failed\n", __FUNCTION__)); 4501 goto fail; 4502 } 4503 4504 /* Attach to the dhd/OS/network interface */ 4505 if (!(bus->dhd = dhd_attach(osh, bus, SDPCM_RESERVE))) { 4506 DHD_ERROR(("%s: dhd_attach failed\n", __FUNCTION__)); 4507 goto fail; 4508 } 4509 4510 /* Allocate buffers */ 4511 if (!(dhdsdio_probe_malloc(bus, osh, sdh))) { 4512 DHD_ERROR(("%s: dhdsdio_probe_malloc failed\n", __FUNCTION__)); 4513 goto fail; 4514 } 4515 4516 if (!(dhdsdio_probe_init(bus, osh, sdh))) { 4517 DHD_ERROR(("%s: dhdsdio_probe_init failed\n", __FUNCTION__)); 4518 goto fail; 4519 } 4520 4521 /* Register interrupt callback, but mask it (not operational yet). */ 4522 DHD_INTR(("%s: disable SDIO interrupts (not interested yet)\n", __FUNCTION__)); 4523 bcmsdh_intr_disable(sdh); 4524 if ((ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus)) != 0) { 4525 DHD_ERROR(("%s: FAILED: bcmsdh_intr_reg returned %d\n", 4526 __FUNCTION__, ret)); 4527 goto fail; 4528 } 4529 DHD_INTR(("%s: registered SDIO interrupt function ok\n", __FUNCTION__)); 4530 4531 DHD_INFO(("%s: completed!!\n", __FUNCTION__)); 4532 4533 4534 /* if firmware path present try to download and bring up bus */ 4535 if ((ret = dhd_bus_start(bus->dhd)) != 0) { 4536 #if 1 4537 DHD_ERROR(("%s: failed\n", __FUNCTION__)); 4538 goto fail; 4539 #else 4540 if (ret == BCME_NOTUP) { 4541 DHD_ERROR(("%s: dongle is not responding\n", __FUNCTION__)); 4542 goto fail; 4543 } 4544 #endif 4545 } 4546 /* Ok, have the per-port tell the stack we're open for business */ 4547 if (dhd_net_attach(bus->dhd, 0) != 0) { 4548 DHD_ERROR(("%s: Net attach failed!!\n", __FUNCTION__)); 4549 goto fail; 4550 } 4551 4552 return bus; 4553 4554 fail: 4555 dhdsdio_release(bus, osh); 4556 return NULL; 4557 } 4558 4559 4560 static bool 4561 dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, 4562 uint16 devid) 4563 { 4564 uint8 clkctl = 0; 4565 int err = 0; 4566 4567 bus->alp_only = TRUE; 4568 4569 /* Return the window to backplane enumeration space for core access */ 4570 if (dhdsdio_set_siaddr_window(bus, SI_ENUM_BASE)) { 4571 DHD_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n", __FUNCTION__)); 4572 } 4573 4574 #ifdef DHD_DEBUG 4575 printf("F1 signature read @0x18000000=0x%4x\n", 4576 bcmsdh_reg_read(bus->sdh, SI_ENUM_BASE, 4)); 4577 4578 4579 #endif /* DHD_DEBUG */ 4580 4581 4582 /* Force PLL off until si_attach() programs PLL control regs */ 4583 4584 4585 4586 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, DHD_INIT_CLKCTL1, &err); 4587 if (!err) 4588 clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); 4589 4590 if (err || ((clkctl & ~SBSDIO_AVBITS) != DHD_INIT_CLKCTL1)) { 4591 DHD_ERROR(("dhdsdio_probe: ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n", 4592 err, DHD_INIT_CLKCTL1, clkctl)); 4593 goto fail; 4594 } 4595 4596 4597 #ifdef DHD_DEBUG 4598 if (DHD_INFO_ON()) { 4599 uint fn, numfn; 4600 uint8 *cis[SDIOD_MAX_IOFUNCS]; 4601 int err = 0; 4602 4603 numfn = bcmsdh_query_iofnum(sdh); 4604 ASSERT(numfn <= SDIOD_MAX_IOFUNCS); 4605 4606 /* Make sure ALP is available before trying to read CIS */ 4607 SPINWAIT(((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, 4608 SBSDIO_FUNC1_CHIPCLKCSR, NULL)), 4609 !SBSDIO_ALPAV(clkctl)), PMU_MAX_TRANSITION_DLY); 4610 4611 /* Now request ALP be put on the bus */ 4612 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 4613 DHD_INIT_CLKCTL2, &err); 4614 OSL_DELAY(65); 4615 4616 for (fn = 0; fn <= numfn; fn++) { 4617 if (!(cis[fn] = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT))) { 4618 DHD_INFO(("dhdsdio_probe: fn %d cis malloc failed\n", fn)); 4619 break; 4620 } 4621 bzero(cis[fn], SBSDIO_CIS_SIZE_LIMIT); 4622 4623 if ((err = bcmsdh_cis_read(sdh, fn, cis[fn], SBSDIO_CIS_SIZE_LIMIT))) { 4624 DHD_INFO(("dhdsdio_probe: fn %d cis read err %d\n", fn, err)); 4625 MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT); 4626 break; 4627 } 4628 dhd_dump_cis(fn, cis[fn]); 4629 } 4630 4631 while (fn-- > 0) { 4632 ASSERT(cis[fn]); 4633 MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT); 4634 } 4635 4636 if (err) { 4637 DHD_ERROR(("dhdsdio_probe: failure reading or parsing CIS\n")); 4638 goto fail; 4639 } 4640 } 4641 #endif /* DHD_DEBUG */ 4642 4643 /* si_attach() will provide an SI handle and scan the backplane */ 4644 if (!(bus->sih = si_attach((uint)devid, osh, regsva, DHD_BUS, sdh, 4645 &bus->vars, &bus->varsz))) { 4646 DHD_ERROR(("%s: si_attach failed!\n", __FUNCTION__)); 4647 goto fail; 4648 } 4649 4650 bcmsdh_chipinfo(sdh, bus->sih->chip, bus->sih->chiprev); 4651 4652 if (!dhdsdio_chipmatch((uint16)bus->sih->chip)) { 4653 DHD_ERROR(("%s: unsupported chip: 0x%04x\n", 4654 __FUNCTION__, bus->sih->chip)); 4655 goto fail; 4656 } 4657 4658 si_sdiod_drive_strength_init(bus->sih, osh, dhd_sdiod_drive_strength); 4659 4660 4661 /* Get info on the ARM and SOCRAM cores... */ 4662 if (!DHD_NOPMU(bus)) { 4663 if ((si_setcore(bus->sih, ARM7S_CORE_ID, 0)) || 4664 (si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) { 4665 bus->armrev = si_corerev(bus->sih); 4666 } else { 4667 DHD_ERROR(("%s: failed to find ARM core!\n", __FUNCTION__)); 4668 goto fail; 4669 } 4670 if (!(bus->orig_ramsize = si_socram_size(bus->sih))) { 4671 DHD_ERROR(("%s: failed to find SOCRAM memory!\n", __FUNCTION__)); 4672 goto fail; 4673 } 4674 bus->ramsize = bus->orig_ramsize; 4675 if (dhd_dongle_memsize) 4676 dhd_dongle_setmemsize(bus, dhd_dongle_memsize); 4677 4678 DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d)\n", 4679 bus->ramsize, bus->orig_ramsize)); 4680 } 4681 4682 /* ...but normally deal with the SDPCMDEV core */ 4683 if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)) && 4684 !(bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0))) { 4685 DHD_ERROR(("%s: failed to find SDIODEV core!\n", __FUNCTION__)); 4686 goto fail; 4687 } 4688 bus->sdpcmrev = si_corerev(bus->sih); 4689 4690 /* Set core control so an SDIO reset does a backplane reset */ 4691 OR_REG(osh, &bus->regs->corecontrol, CC_BPRESEN); 4692 4693 pktq_init(&bus->txq, (PRIOMASK + 1), QLEN); 4694 4695 /* Locate an appropriately-aligned portion of hdrbuf */ 4696 bus->rxhdr = (uint8 *)ROUNDUP((uintptr)&bus->hdrbuf[0], DHD_SDALIGN); 4697 4698 /* Set the poll and/or interrupt flags */ 4699 bus->intr = (bool)dhd_intr; 4700 if ((bus->poll = (bool)dhd_poll)) 4701 bus->pollrate = 1; 4702 4703 return TRUE; 4704 4705 fail: 4706 return FALSE; 4707 } 4708 4709 static bool 4710 dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh) 4711 { 4712 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 4713 4714 #ifndef DHD_USE_STATIC_BUF 4715 if (bus->dhd->maxctl) { 4716 bus->rxblen = ROUNDUP((bus->dhd->maxctl + SDPCM_HDRLEN), ALIGNMENT) + DHD_SDALIGN; 4717 if (!(bus->rxbuf = MALLOC(osh, bus->rxblen))) { 4718 DHD_ERROR(("%s: MALLOC of %d-byte rxbuf failed\n", 4719 __FUNCTION__, bus->rxblen)); 4720 goto fail; 4721 } 4722 } 4723 4724 /* Allocate buffer to receive glomed packet */ 4725 if (!(bus->databuf = MALLOC(osh, MAX_DATA_BUF))) { 4726 DHD_ERROR(("%s: MALLOC of %d-byte databuf failed\n", 4727 __FUNCTION__, MAX_DATA_BUF)); 4728 /* release rxbuf which was already located as above */ 4729 if (!bus->rxblen) MFREE(osh, bus->rxbuf, bus->rxblen); 4730 goto fail; 4731 } 4732 #else 4733 if (bus->dhd->maxctl) { 4734 bus->rxblen = ROUNDUP((bus->dhd->maxctl + SDPCM_HDRLEN), ALIGNMENT) + DHD_SDALIGN; 4735 if (!(bus->rxbuf = dhd_os_prealloc(DHD_PREALLOC_RXBUF, bus->rxblen))) { 4736 DHD_ERROR(("%s: MALLOC of %d-byte rxbuf failed\n", 4737 __FUNCTION__, bus->rxblen)); 4738 goto fail; 4739 } 4740 } 4741 /* Allocate buffer to receive glomed packet */ 4742 if (!(bus->databuf = dhd_os_prealloc(DHD_PREALLOC_DATABUF, MAX_DATA_BUF))) { 4743 DHD_ERROR(("%s: MALLOC of %d-byte databuf failed\n", 4744 __FUNCTION__, MAX_DATA_BUF)); 4745 goto fail; 4746 } 4747 #endif /* DHD_USE_STATIC_BUF */ 4748 4749 /* Align the buffer */ 4750 if ((uintptr)bus->databuf % DHD_SDALIGN) 4751 bus->dataptr = bus->databuf + (DHD_SDALIGN - ((uintptr)bus->databuf % DHD_SDALIGN)); 4752 else 4753 bus->dataptr = bus->databuf; 4754 4755 return TRUE; 4756 4757 fail: 4758 return FALSE; 4759 } 4760 4761 4762 static bool 4763 dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh) 4764 { 4765 int32 fnum; 4766 4767 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 4768 4769 #ifdef SDTEST 4770 dhdsdio_pktgen_init(bus); 4771 #endif /* SDTEST */ 4772 4773 /* Disable F2 to clear any intermediate frame state on the dongle */ 4774 bcmsdh_cfg_write(sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL); 4775 4776 bus->dhd->busstate = DHD_BUS_DOWN; 4777 bus->sleeping = FALSE; 4778 bus->rxflow = FALSE; 4779 bus->prev_rxlim_hit = 0; 4780 4781 4782 /* Done with backplane-dependent accesses, can drop clock... */ 4783 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); 4784 4785 /* ...and initialize clock/power states */ 4786 bus->clkstate = CLK_SDONLY; 4787 bus->idletime = (int32)dhd_idletime; 4788 bus->idleclock = DHD_IDLE_ACTIVE; 4789 4790 /* Query the SD clock speed */ 4791 if (bcmsdh_iovar_op(sdh, "sd_divisor", NULL, 0, 4792 &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) { 4793 DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_divisor")); 4794 bus->sd_divisor = -1; 4795 } else { 4796 DHD_INFO(("%s: Initial value for %s is %d\n", 4797 __FUNCTION__, "sd_divisor", bus->sd_divisor)); 4798 } 4799 4800 /* Query the SD bus mode */ 4801 if (bcmsdh_iovar_op(sdh, "sd_mode", NULL, 0, 4802 &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) { 4803 DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_mode")); 4804 bus->sd_mode = -1; 4805 } else { 4806 DHD_INFO(("%s: Initial value for %s is %d\n", 4807 __FUNCTION__, "sd_mode", bus->sd_mode)); 4808 } 4809 4810 /* Query the F2 block size, set roundup accordingly */ 4811 fnum = 2; 4812 if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fnum, sizeof(int32), 4813 &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) { 4814 bus->blocksize = 0; 4815 DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize")); 4816 } else { 4817 DHD_INFO(("%s: Initial value for %s is %d\n", 4818 __FUNCTION__, "sd_blocksize", bus->blocksize)); 4819 } 4820 bus->roundup = MIN(max_roundup, bus->blocksize); 4821 4822 /* Query if bus module supports packet chaining, default to use if supported */ 4823 if (bcmsdh_iovar_op(sdh, "sd_rxchain", NULL, 0, 4824 &bus->sd_rxchain, sizeof(int32), FALSE) != BCME_OK) { 4825 bus->sd_rxchain = FALSE; 4826 } else { 4827 DHD_INFO(("%s: bus module (through bcmsdh API) %s chaining\n", 4828 __FUNCTION__, (bus->sd_rxchain ? "supports" : "does not support"))); 4829 } 4830 bus->use_rxchain = (bool)bus->sd_rxchain; 4831 4832 return TRUE; 4833 } 4834 4835 bool 4836 dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh, 4837 char *fw_path, char *nv_path) 4838 { 4839 bool ret; 4840 bus->fw_path = fw_path; 4841 bus->nv_path = nv_path; 4842 4843 ret = dhdsdio_download_firmware(bus, osh, bus->sdh); 4844 4845 return ret; 4846 } 4847 4848 static bool 4849 dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh) 4850 { 4851 bool ret; 4852 4853 /* Download the firmware */ 4854 dhd_os_wake_lock(bus->dhd); 4855 dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); 4856 4857 ret = _dhdsdio_download_firmware(bus) == 0; 4858 4859 dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); 4860 dhd_os_wake_unlock(bus->dhd); 4861 return ret; 4862 } 4863 4864 /* Detach and free everything */ 4865 static void 4866 dhdsdio_release(dhd_bus_t *bus, osl_t *osh) 4867 { 4868 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 4869 4870 if (bus) { 4871 ASSERT(osh); 4872 4873 4874 /* De-register interrupt handler */ 4875 bcmsdh_intr_disable(bus->sdh); 4876 bcmsdh_intr_dereg(bus->sdh); 4877 4878 if (bus->dhd) { 4879 4880 dhdsdio_release_dongle(bus, osh); 4881 4882 dhd_detach(bus->dhd); 4883 bus->dhd = NULL; 4884 } 4885 4886 dhdsdio_release_malloc(bus, osh); 4887 4888 4889 MFREE(osh, bus, sizeof(dhd_bus_t)); 4890 } 4891 4892 if (osh) 4893 dhd_osl_detach(osh); 4894 4895 DHD_TRACE(("%s: Disconnected\n", __FUNCTION__)); 4896 } 4897 4898 static void 4899 dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh) 4900 { 4901 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 4902 4903 if (bus->dhd && bus->dhd->dongle_reset) 4904 return; 4905 4906 if (bus->rxbuf) { 4907 #ifndef DHD_USE_STATIC_BUF 4908 MFREE(osh, bus->rxbuf, bus->rxblen); 4909 #endif 4910 bus->rxctl = bus->rxbuf = NULL; 4911 bus->rxlen = 0; 4912 } 4913 4914 if (bus->databuf) { 4915 #ifndef DHD_USE_STATIC_BUF 4916 MFREE(osh, bus->databuf, MAX_DATA_BUF); 4917 #endif 4918 bus->databuf = NULL; 4919 } 4920 } 4921 4922 4923 static void 4924 dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh) 4925 { 4926 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 4927 4928 if (bus->dhd && bus->dhd->dongle_reset) 4929 return; 4930 4931 if (bus->sih) { 4932 dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); 4933 #if !defined(BCMLXSDMMC) 4934 si_watchdog(bus->sih, 4); 4935 #endif /* !defined(BCMLXSDMMC) */ 4936 dhdsdio_clkctl(bus, CLK_NONE, FALSE); 4937 si_detach(bus->sih); 4938 if (bus->vars && bus->varsz) 4939 MFREE(osh, bus->vars, bus->varsz); 4940 bus->vars = NULL; 4941 } 4942 4943 DHD_TRACE(("%s: Disconnected\n", __FUNCTION__)); 4944 } 4945 4946 static void 4947 dhdsdio_disconnect(void *ptr) 4948 { 4949 dhd_bus_t *bus = (dhd_bus_t *)ptr; 4950 4951 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 4952 4953 if (bus) { 4954 ASSERT(bus->dhd); 4955 dhdsdio_release(bus, bus->dhd->osh); 4956 } 4957 4958 DHD_TRACE(("%s: Disconnected\n", __FUNCTION__)); 4959 } 4960 4961 4962 /* Register/Unregister functions are called by the main DHD entry 4963 * point (e.g. module insertion) to link with the bus driver, in 4964 * order to look for or await the device. 4965 */ 4966 4967 static bcmsdh_driver_t dhd_sdio = { 4968 dhdsdio_probe, 4969 dhdsdio_disconnect 4970 }; 4971 4972 int 4973 dhd_bus_register(void) 4974 { 4975 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 4976 4977 return bcmsdh_register(&dhd_sdio); 4978 } 4979 4980 void 4981 dhd_bus_unregister(void) 4982 { 4983 DHD_TRACE(("%s: Enter\n", __FUNCTION__)); 4984 4985 bcmsdh_unregister(); 4986 } 4987 4988 #ifdef BCMEMBEDIMAGE 4989 static int 4990 dhdsdio_download_code_array(struct dhd_bus *bus) 4991 { 4992 int bcmerror = -1; 4993 int offset = 0; 4994 4995 DHD_INFO(("%s: download embedded firmware...\n", __FUNCTION__)); 4996 4997 /* Download image */ 4998 while ((offset + MEMBLOCK) < sizeof(dlarray)) { 4999 bcmerror = dhdsdio_membytes(bus, TRUE, offset, dlarray + offset, MEMBLOCK); 5000 if (bcmerror) { 5001 DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n", 5002 __FUNCTION__, bcmerror, MEMBLOCK, offset)); 5003 goto err; 5004 } 5005 5006 offset += MEMBLOCK; 5007 } 5008 5009 if (offset < sizeof(dlarray)) { 5010 bcmerror = dhdsdio_membytes(bus, TRUE, offset, 5011 dlarray + offset, sizeof(dlarray) - offset); 5012 if (bcmerror) { 5013 DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n", 5014 __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset)); 5015 goto err; 5016 } 5017 } 5018 5019 #ifdef DHD_DEBUG 5020 /* Upload and compare the downloaded code */ 5021 { 5022 unsigned char *ularray; 5023 5024 ularray = MALLOC(bus->dhd->osh, bus->ramsize); 5025 /* Upload image to verify downloaded contents. */ 5026 offset = 0; 5027 memset(ularray, 0xaa, bus->ramsize); 5028 while ((offset + MEMBLOCK) < sizeof(dlarray)) { 5029 bcmerror = dhdsdio_membytes(bus, FALSE, offset, ularray + offset, MEMBLOCK); 5030 if (bcmerror) { 5031 DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n", 5032 __FUNCTION__, bcmerror, MEMBLOCK, offset)); 5033 goto err; 5034 } 5035 5036 offset += MEMBLOCK; 5037 } 5038 5039 if (offset < sizeof(dlarray)) { 5040 bcmerror = dhdsdio_membytes(bus, FALSE, offset, 5041 ularray + offset, sizeof(dlarray) - offset); 5042 if (bcmerror) { 5043 DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n", 5044 __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset)); 5045 goto err; 5046 } 5047 } 5048 5049 if (memcmp(dlarray, ularray, sizeof(dlarray))) { 5050 DHD_ERROR(("%s: Downloaded image is corrupted.\n", __FUNCTION__)); 5051 ASSERT(0); 5052 goto err; 5053 } else 5054 DHD_ERROR(("%s: Download, Upload and compare succeeded.\n", __FUNCTION__)); 5055 5056 MFREE(bus->dhd->osh, ularray, bus->ramsize); 5057 } 5058 #endif /* DHD_DEBUG */ 5059 5060 err: 5061 return bcmerror; 5062 } 5063 #endif /* BCMEMBEDIMAGE */ 5064 5065 static int 5066 dhdsdio_download_code_file(struct dhd_bus *bus, char *fw_path) 5067 { 5068 int bcmerror = -1; 5069 int offset = 0; 5070 uint len; 5071 void *image = NULL; 5072 uint8 *memblock = NULL, *memptr; 5073 5074 DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, fw_path)); 5075 5076 image = dhd_os_open_image(fw_path); 5077 if (image == NULL) 5078 goto err; 5079 5080 memptr = memblock = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN); 5081 if (memblock == NULL) { 5082 DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK)); 5083 goto err; 5084 } 5085 if ((uint32)(uintptr)memblock % DHD_SDALIGN) 5086 memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN)); 5087 5088 /* Download image */ 5089 while ((len = dhd_os_get_image_block((char*)memptr, MEMBLOCK, image))) { 5090 bcmerror = dhdsdio_membytes(bus, TRUE, offset, memptr, len); 5091 if (bcmerror) { 5092 DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n", 5093 __FUNCTION__, bcmerror, MEMBLOCK, offset)); 5094 goto err; 5095 } 5096 5097 offset += MEMBLOCK; 5098 } 5099 5100 err: 5101 if (memblock) 5102 MFREE(bus->dhd->osh, memblock, MEMBLOCK + DHD_SDALIGN); 5103 5104 if (image) 5105 dhd_os_close_image(image); 5106 5107 return bcmerror; 5108 } 5109 5110 /* 5111 * ProcessVars:Takes a buffer of "<var>=<value>\n" lines read from a file and ending in a NUL. 5112 * Removes carriage returns, empty lines, comment lines, and converts newlines to NULs. 5113 * Shortens buffer as needed and pads with NULs. End of buffer is marked by two NULs. 5114 */ 5115 5116 static uint 5117 process_nvram_vars(char *varbuf, uint len) 5118 { 5119 char *dp; 5120 bool findNewline; 5121 int column; 5122 uint buf_len, n; 5123 5124 dp = varbuf; 5125 5126 findNewline = FALSE; 5127 column = 0; 5128 5129 for (n = 0; n < len; n++) { 5130 if (varbuf[n] == 0) 5131 break; 5132 if (varbuf[n] == '\r') 5133 continue; 5134 if (findNewline && varbuf[n] != '\n') 5135 continue; 5136 findNewline = FALSE; 5137 if (varbuf[n] == '#') { 5138 findNewline = TRUE; 5139 continue; 5140 } 5141 if (varbuf[n] == '\n') { 5142 if (column == 0) 5143 continue; 5144 *dp++ = 0; 5145 column = 0; 5146 continue; 5147 } 5148 *dp++ = varbuf[n]; 5149 column++; 5150 } 5151 buf_len = dp - varbuf; 5152 5153 while (dp < varbuf + n) 5154 *dp++ = 0; 5155 5156 return buf_len; 5157 } 5158 5159 /* 5160 EXAMPLE: nvram_array 5161 nvram_arry format: 5162 name=value 5163 Use carriage return at the end of each assignment, and an empty string with 5164 carriage return at the end of array. 5165 5166 For example: 5167 unsigned char nvram_array[] = {"name1=value1\n", "name2=value2\n", "\n"}; 5168 Hex values start with 0x, and mac addr format: xx:xx:xx:xx:xx:xx. 5169 5170 Search "EXAMPLE: nvram_array" to see how the array is activated. 5171 */ 5172 5173 void 5174 dhd_bus_set_nvram_params(struct dhd_bus * bus, const char *nvram_params) 5175 { 5176 bus->nvram_params = nvram_params; 5177 } 5178 5179 static int 5180 dhdsdio_download_nvram(struct dhd_bus *bus) 5181 { 5182 int bcmerror = -1; 5183 uint len; 5184 void * image = NULL; 5185 char * memblock = NULL; 5186 char *bufp; 5187 char *nv_path; 5188 bool nvram_file_exists; 5189 5190 nv_path = bus->nv_path; 5191 5192 nvram_file_exists = ((nv_path != NULL) && (nv_path[0] != '\0')); 5193 if (!nvram_file_exists && (bus->nvram_params == NULL)) 5194 return (0); 5195 5196 if (nvram_file_exists) { 5197 image = dhd_os_open_image(nv_path); 5198 if (image == NULL) 5199 goto err; 5200 } 5201 5202 memblock = MALLOC(bus->dhd->osh, MEMBLOCK); 5203 if (memblock == NULL) { 5204 DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", 5205 __FUNCTION__, MEMBLOCK)); 5206 goto err; 5207 } 5208 5209 /* Download variables */ 5210 if (nvram_file_exists) { 5211 len = dhd_os_get_image_block(memblock, MEMBLOCK, image); 5212 } 5213 else { 5214 len = strlen(bus->nvram_params); 5215 ASSERT(len <= MEMBLOCK); 5216 if (len > MEMBLOCK) 5217 len = MEMBLOCK; 5218 memcpy(memblock, bus->nvram_params, len); 5219 } 5220 5221 if (len > 0 && len < MEMBLOCK) { 5222 bufp = (char *)memblock; 5223 bufp[len] = 0; 5224 len = process_nvram_vars(bufp, len); 5225 bufp += len; 5226 *bufp++ = 0; 5227 if (len) 5228 bcmerror = dhdsdio_downloadvars(bus, memblock, len + 1); 5229 if (bcmerror) { 5230 DHD_ERROR(("%s: error downloading vars: %d\n", 5231 __FUNCTION__, bcmerror)); 5232 } 5233 } 5234 else { 5235 DHD_ERROR(("%s: error reading nvram file: %d\n", 5236 __FUNCTION__, len)); 5237 bcmerror = BCME_SDIO_ERROR; 5238 } 5239 5240 err: 5241 if (memblock) 5242 MFREE(bus->dhd->osh, memblock, MEMBLOCK); 5243 5244 if (image) 5245 dhd_os_close_image(image); 5246 5247 return bcmerror; 5248 } 5249 5250 static int 5251 _dhdsdio_download_firmware(struct dhd_bus *bus) 5252 { 5253 int bcmerror = -1; 5254 5255 bool embed = FALSE; /* download embedded firmware */ 5256 bool dlok = FALSE; /* download firmware succeeded */ 5257 5258 /* Out immediately if no image to download */ 5259 if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) { 5260 #ifdef BCMEMBEDIMAGE 5261 embed = TRUE; 5262 #else 5263 return bcmerror; 5264 #endif 5265 } 5266 5267 /* Keep arm in reset */ 5268 if (dhdsdio_download_state(bus, TRUE)) { 5269 DHD_ERROR(("%s: error placing ARM core in reset\n", __FUNCTION__)); 5270 goto err; 5271 } 5272 5273 /* External image takes precedence if specified */ 5274 if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) { 5275 if (dhdsdio_download_code_file(bus, bus->fw_path)) { 5276 DHD_ERROR(("%s: dongle image file download failed\n", __FUNCTION__)); 5277 #ifdef BCMEMBEDIMAGE 5278 embed = TRUE; 5279 #else 5280 goto err; 5281 #endif 5282 } 5283 else { 5284 embed = FALSE; 5285 dlok = TRUE; 5286 } 5287 } 5288 #ifdef BCMEMBEDIMAGE 5289 if (embed) { 5290 if (dhdsdio_download_code_array(bus)) { 5291 DHD_ERROR(("%s: dongle image array download failed\n", __FUNCTION__)); 5292 goto err; 5293 } 5294 else { 5295 dlok = TRUE; 5296 } 5297 } 5298 #endif 5299 if (!dlok) { 5300 DHD_ERROR(("%s: dongle image download failed\n", __FUNCTION__)); 5301 goto err; 5302 } 5303 5304 /* EXAMPLE: nvram_array */ 5305 /* If a valid nvram_arry is specified as above, it can be passed down to dongle */ 5306 /* dhd_bus_set_nvram_params(bus, (char *)&nvram_array); */ 5307 5308 /* External nvram takes precedence if specified */ 5309 if (dhdsdio_download_nvram(bus)) { 5310 DHD_ERROR(("%s: dongle nvram file download failed\n", __FUNCTION__)); 5311 } 5312 5313 /* Take arm out of reset */ 5314 if (dhdsdio_download_state(bus, FALSE)) { 5315 DHD_ERROR(("%s: error getting out of ARM core reset\n", __FUNCTION__)); 5316 goto err; 5317 } 5318 5319 bcmerror = 0; 5320 5321 err: 5322 return bcmerror; 5323 } 5324 5325 static int 5326 dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes, 5327 void *pkt, bcmsdh_cmplt_fn_t complete, void *handle) 5328 { 5329 int status; 5330 5331 /* 4329: GSPI check */ 5332 status = bcmsdh_recv_buf(bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete, handle); 5333 return status; 5334 } 5335 5336 static int 5337 dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes, 5338 void *pkt, bcmsdh_cmplt_fn_t complete, void *handle) 5339 { 5340 return (bcmsdh_send_buf(bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete, handle)); 5341 } 5342 5343 uint 5344 dhd_bus_chip(struct dhd_bus *bus) 5345 { 5346 ASSERT(bus->sih != NULL); 5347 return bus->sih->chip; 5348 } 5349 5350 void * 5351 dhd_bus_pub(struct dhd_bus *bus) 5352 { 5353 return bus->dhd; 5354 } 5355 5356 void * 5357 dhd_bus_txq(struct dhd_bus *bus) 5358 { 5359 return &bus->txq; 5360 } 5361 5362 uint 5363 dhd_bus_hdrlen(struct dhd_bus *bus) 5364 { 5365 return SDPCM_HDRLEN; 5366 } 5367 5368 int 5369 dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) 5370 { 5371 int bcmerror = 0; 5372 dhd_bus_t *bus; 5373 5374 bus = dhdp->bus; 5375 5376 if (flag == TRUE) { 5377 if (!bus->dhd->dongle_reset) { 5378 #if !defined(IGNORE_ETH0_DOWN) 5379 /* Force flow control as protection when stop come before ifconfig_down */ 5380 dhd_txflowcontrol(bus->dhd, 0, ON); 5381 #endif /* !defined(IGNORE_ETH0_DOWN) */ 5382 /* save country settinng if was pre-setup with priv ioctl */ 5383 dhd_os_proto_block(dhdp); 5384 dhdcdc_query_ioctl(bus->dhd, 0, WLC_GET_COUNTRY, 5385 bus->dhd->country_code, sizeof(bus->dhd->country_code)); 5386 dhd_os_proto_unblock(dhdp); 5387 /* Expect app to have torn down any connection before calling */ 5388 /* Stop the bus, disable F2 */ 5389 dhd_bus_stop(bus, FALSE); 5390 5391 /* Clean tx/rx buffer pointers, detach from the dongle */ 5392 dhdsdio_release_dongle(bus, bus->dhd->osh); 5393 5394 bus->dhd->dongle_reset = TRUE; 5395 bus->dhd->up = FALSE; 5396 5397 DHD_TRACE(("%s: WLAN OFF DONE\n", __FUNCTION__)); 5398 /* App can now remove power from device */ 5399 } else 5400 bcmerror = BCME_SDIO_ERROR; 5401 } else { 5402 /* App must have restored power to device before calling */ 5403 5404 DHD_TRACE(("\n\n%s: == WLAN ON ==\n", __FUNCTION__)); 5405 5406 if (bus->dhd->dongle_reset) { 5407 /* Turn on WLAN */ 5408 /* Reset SD client */ 5409 bcmsdh_reset(bus->sdh); 5410 5411 /* Attempt to re-attach & download */ 5412 if (dhdsdio_probe_attach(bus, bus->dhd->osh, bus->sdh, 5413 (uint32 *)SI_ENUM_BASE, 5414 bus->cl_devid)) { 5415 /* Attempt to download binary to the dongle */ 5416 if (dhdsdio_probe_init(bus, bus->dhd->osh, bus->sdh) && 5417 dhdsdio_download_firmware(bus, bus->dhd->osh, bus->sdh)) { 5418 5419 /* Re-init bus, enable F2 transfer */ 5420 dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE); 5421 5422 #if defined(OOB_INTR_ONLY) 5423 dhd_enable_oob_intr(bus, TRUE); 5424 #endif /* defined(OOB_INTR_ONLY) */ 5425 5426 bus->dhd->dongle_reset = FALSE; 5427 bus->dhd->up = TRUE; 5428 5429 #if !defined(IGNORE_ETH0_DOWN) 5430 /* Restore flow control */ 5431 dhd_txflowcontrol(bus->dhd, 0, OFF); 5432 #endif 5433 5434 DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__)); 5435 } else 5436 bcmerror = BCME_SDIO_ERROR; 5437 } else 5438 bcmerror = BCME_SDIO_ERROR; 5439 } else { 5440 bcmerror = BCME_NOTDOWN; 5441 DHD_ERROR(("%s: Set DEVRESET=FALSE invoked when device is on\n", 5442 __FUNCTION__)); 5443 bcmerror = BCME_SDIO_ERROR; 5444 } 5445 } 5446 return bcmerror; 5447 } 5448