Home | History | Annotate | Download | only in sys
      1 /*
      2  *  BCMSDH interface glue
      3  *  implement bcmsdh API for SDIOH driver
      4  *
      5  * Copyright (C) 1999-2010, Broadcom Corporation
      6  *
      7  *      Unless you and Broadcom execute a separate written software license
      8  * agreement governing use of this software, this software is licensed to you
      9  * under the terms of the GNU General Public License version 2 (the "GPL"),
     10  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
     11  * following added to such license:
     12  *
     13  *      As a special exception, the copyright holders of this software give you
     14  * permission to link this software with independent modules, and to copy and
     15  * distribute the resulting executable under terms of your choice, provided that
     16  * you also meet, for each linked independent module, the terms and conditions of
     17  * the license of that module.  An independent module is a module which is not
     18  * derived from this software.  The special exception does not apply to any
     19  * modifications of the software.
     20  *
     21  *      Notwithstanding the above, under no circumstances may you combine this
     22  * software in any way with any other Broadcom software provided under a license
     23  * other than the GPL, without Broadcom's express prior written consent.
     24  *
     25  * $Id: bcmsdh.c,v 1.35.2.1.4.8.6.13 2010/04/06 03:26:57 Exp $
     26  */
     27 /* ****************** BCMSDH Interface Functions *************************** */
     28 
     29 #include <typedefs.h>
     30 #include <bcmdevs.h>
     31 #include <bcmendian.h>
     32 #include <bcmutils.h>
     33 #include <hndsoc.h>
     34 #include <siutils.h>
     35 #include <osl.h>
     36 
     37 #include <bcmsdh.h>	/* BRCM API for SDIO clients (such as wl, dhd) */
     38 #include <bcmsdbus.h>	/* common SDIO/controller interface */
     39 #include <sbsdio.h>	/* BRCM sdio device core */
     40 
     41 #include <sdio.h>	/* sdio spec */
     42 
     43 #define SDIOH_API_ACCESS_RETRY_LIMIT	2
     44 const uint bcmsdh_msglevel = BCMSDH_ERROR_VAL;
     45 
     46 
     47 struct bcmsdh_info
     48 {
     49 	bool	init_success;	/* underlying driver successfully attached */
     50 	void	*sdioh;		/* handler for sdioh */
     51 	uint32  vendevid;	/* Target Vendor and Device ID on SD bus */
     52 	osl_t   *osh;
     53 	bool	regfail;	/* Save status of last reg_read/reg_write call */
     54 	uint32	sbwad;		/* Save backplane window address */
     55 };
     56 /* local copy of bcm sd handler */
     57 bcmsdh_info_t * l_bcmsdh = NULL;
     58 
     59 #if defined(OOB_INTR_ONLY) && defined(HW_OOB)
     60 extern int
     61 sdioh_enable_hw_oob_intr(void *sdioh, bool enable);
     62 
     63 void
     64 bcmsdh_enable_hw_oob_intr(bcmsdh_info_t *sdh, bool enable)
     65 {
     66 	sdioh_enable_hw_oob_intr(sdh->sdioh, enable);
     67 }
     68 #endif
     69 
     70 bcmsdh_info_t *
     71 bcmsdh_attach(osl_t *osh, void *cfghdl, void **regsva, uint irq)
     72 {
     73 	bcmsdh_info_t *bcmsdh;
     74 
     75 	if ((bcmsdh = (bcmsdh_info_t *)MALLOC(osh, sizeof(bcmsdh_info_t))) == NULL) {
     76 		BCMSDH_ERROR(("bcmsdh_attach: out of memory, malloced %d bytes\n", MALLOCED(osh)));
     77 		return NULL;
     78 	}
     79 	bzero((char *)bcmsdh, sizeof(bcmsdh_info_t));
     80 
     81 	/* save the handler locally */
     82 	l_bcmsdh = bcmsdh;
     83 
     84 	if (!(bcmsdh->sdioh = sdioh_attach(osh, cfghdl, irq))) {
     85 		bcmsdh_detach(osh, bcmsdh);
     86 		return NULL;
     87 	}
     88 
     89 	bcmsdh->osh = osh;
     90 	bcmsdh->init_success = TRUE;
     91 
     92 	*regsva = (uint32 *)SI_ENUM_BASE;
     93 
     94 	/* Report the BAR, to fix if needed */
     95 	bcmsdh->sbwad = SI_ENUM_BASE;
     96 	return bcmsdh;
     97 }
     98 
     99 int
    100 bcmsdh_detach(osl_t *osh, void *sdh)
    101 {
    102 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    103 
    104 	if (bcmsdh != NULL) {
    105 		if (bcmsdh->sdioh) {
    106 			sdioh_detach(osh, bcmsdh->sdioh);
    107 			bcmsdh->sdioh = NULL;
    108 		}
    109 		MFREE(osh, bcmsdh, sizeof(bcmsdh_info_t));
    110 	}
    111 
    112 	l_bcmsdh = NULL;
    113 	return 0;
    114 }
    115 
    116 int
    117 bcmsdh_iovar_op(void *sdh, const char *name,
    118                 void *params, int plen, void *arg, int len, bool set)
    119 {
    120 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    121 	return sdioh_iovar_op(bcmsdh->sdioh, name, params, plen, arg, len, set);
    122 }
    123 
    124 bool
    125 bcmsdh_intr_query(void *sdh)
    126 {
    127 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    128 	SDIOH_API_RC status;
    129 	bool on;
    130 
    131 	ASSERT(bcmsdh);
    132 	status = sdioh_interrupt_query(bcmsdh->sdioh, &on);
    133 	if (SDIOH_API_SUCCESS(status))
    134 		return FALSE;
    135 	else
    136 		return on;
    137 }
    138 
    139 int
    140 bcmsdh_intr_enable(void *sdh)
    141 {
    142 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    143 	SDIOH_API_RC status;
    144 	ASSERT(bcmsdh);
    145 
    146 	status = sdioh_interrupt_set(bcmsdh->sdioh, TRUE);
    147 	return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
    148 }
    149 
    150 int
    151 bcmsdh_intr_disable(void *sdh)
    152 {
    153 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    154 	SDIOH_API_RC status;
    155 	ASSERT(bcmsdh);
    156 
    157 	status = sdioh_interrupt_set(bcmsdh->sdioh, FALSE);
    158 	return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
    159 }
    160 
    161 int
    162 bcmsdh_intr_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh)
    163 {
    164 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    165 	SDIOH_API_RC status;
    166 	ASSERT(bcmsdh);
    167 
    168 	status = sdioh_interrupt_register(bcmsdh->sdioh, fn, argh);
    169 	return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
    170 }
    171 
    172 int
    173 bcmsdh_intr_dereg(void *sdh)
    174 {
    175 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    176 	SDIOH_API_RC status;
    177 	ASSERT(bcmsdh);
    178 
    179 	status = sdioh_interrupt_deregister(bcmsdh->sdioh);
    180 	return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
    181 }
    182 
    183 #if defined(DHD_DEBUG)
    184 bool
    185 bcmsdh_intr_pending(void *sdh)
    186 {
    187 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    188 
    189 	ASSERT(sdh);
    190 	return sdioh_interrupt_pending(bcmsdh->sdioh);
    191 }
    192 #endif
    193 
    194 
    195 int
    196 bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh)
    197 {
    198 	ASSERT(sdh);
    199 
    200 	/* don't support yet */
    201 	return BCME_UNSUPPORTED;
    202 }
    203 
    204 uint8
    205 bcmsdh_cfg_read(void *sdh, uint fnc_num, uint32 addr, int *err)
    206 {
    207 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    208 	SDIOH_API_RC status;
    209 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
    210 	int32 retry = 0;
    211 #endif
    212 	uint8 data = 0;
    213 
    214 	if (!bcmsdh)
    215 		bcmsdh = l_bcmsdh;
    216 
    217 	ASSERT(bcmsdh->init_success);
    218 
    219 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
    220 	do {
    221 		if (retry)	/* wait for 1 ms till bus get settled down */
    222 			OSL_DELAY(1000);
    223 #endif
    224 	status = sdioh_cfg_read(bcmsdh->sdioh, fnc_num, addr, (uint8 *)&data);
    225 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
    226 	} while (!SDIOH_API_SUCCESS(status) && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
    227 #endif
    228 	if (err)
    229 		*err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR);
    230 
    231 	BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint8data = 0x%x\n", __FUNCTION__,
    232 	            fnc_num, addr, data));
    233 
    234 	return data;
    235 }
    236 
    237 void
    238 bcmsdh_cfg_write(void *sdh, uint fnc_num, uint32 addr, uint8 data, int *err)
    239 {
    240 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    241 	SDIOH_API_RC status;
    242 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
    243 	int32 retry = 0;
    244 #endif
    245 
    246 	if (!bcmsdh)
    247 		bcmsdh = l_bcmsdh;
    248 
    249 	ASSERT(bcmsdh->init_success);
    250 
    251 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
    252 	do {
    253 		if (retry)	/* wait for 1 ms till bus get settled down */
    254 			OSL_DELAY(1000);
    255 #endif
    256 	status = sdioh_cfg_write(bcmsdh->sdioh, fnc_num, addr, (uint8 *)&data);
    257 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
    258 	} while (!SDIOH_API_SUCCESS(status) && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
    259 #endif
    260 	if (err)
    261 		*err = SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR;
    262 
    263 	BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint8data = 0x%x\n", __FUNCTION__,
    264 	            fnc_num, addr, data));
    265 }
    266 
    267 uint32
    268 bcmsdh_cfg_read_word(void *sdh, uint fnc_num, uint32 addr, int *err)
    269 {
    270 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    271 	SDIOH_API_RC status;
    272 	uint32 data = 0;
    273 
    274 	if (!bcmsdh)
    275 		bcmsdh = l_bcmsdh;
    276 
    277 	ASSERT(bcmsdh->init_success);
    278 
    279 	status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_READ, fnc_num,
    280 	                            addr, &data, 4);
    281 
    282 	if (err)
    283 		*err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR);
    284 
    285 	BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint32data = 0x%x\n", __FUNCTION__,
    286 	            fnc_num, addr, data));
    287 
    288 	return data;
    289 }
    290 
    291 void
    292 bcmsdh_cfg_write_word(void *sdh, uint fnc_num, uint32 addr, uint32 data, int *err)
    293 {
    294 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    295 	SDIOH_API_RC status;
    296 
    297 	if (!bcmsdh)
    298 		bcmsdh = l_bcmsdh;
    299 
    300 	ASSERT(bcmsdh->init_success);
    301 
    302 	status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_WRITE, fnc_num,
    303 	                            addr, &data, 4);
    304 
    305 	if (err)
    306 		*err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR);
    307 
    308 	BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint32data = 0x%x\n", __FUNCTION__, fnc_num,
    309 	             addr, data));
    310 }
    311 
    312 
    313 int
    314 bcmsdh_cis_read(void *sdh, uint func, uint8 *cis, uint length)
    315 {
    316 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    317 	SDIOH_API_RC status;
    318 
    319 	uint8 *tmp_buf, *tmp_ptr;
    320 	uint8 *ptr;
    321 	bool ascii = func & ~0xf;
    322 	func &= 0x7;
    323 
    324 	if (!bcmsdh)
    325 		bcmsdh = l_bcmsdh;
    326 
    327 	ASSERT(bcmsdh->init_success);
    328 	ASSERT(cis);
    329 	ASSERT(length <= SBSDIO_CIS_SIZE_LIMIT);
    330 
    331 	status = sdioh_cis_read(bcmsdh->sdioh, func, cis, length);
    332 
    333 	if (ascii) {
    334 		/* Move binary bits to tmp and format them into the provided buffer. */
    335 		if ((tmp_buf = (uint8 *)MALLOC(bcmsdh->osh, length)) == NULL) {
    336 			BCMSDH_ERROR(("%s: out of memory\n", __FUNCTION__));
    337 			return BCME_NOMEM;
    338 		}
    339 		bcopy(cis, tmp_buf, length);
    340 		for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4); tmp_ptr++) {
    341 			ptr += sprintf((char*)ptr, "%.2x ", *tmp_ptr & 0xff);
    342 			if ((((tmp_ptr - tmp_buf) + 1) & 0xf) == 0)
    343 				ptr += sprintf((char *)ptr, "\n");
    344 		}
    345 		MFREE(bcmsdh->osh, tmp_buf, length);
    346 	}
    347 
    348 	return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
    349 }
    350 
    351 
    352 static int
    353 bcmsdhsdio_set_sbaddr_window(void *sdh, uint32 address)
    354 {
    355 	int err = 0;
    356 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    357 	bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
    358 	                 (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
    359 	if (!err)
    360 		bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID,
    361 		                 (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
    362 	if (!err)
    363 		bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH,
    364 		                 (address >> 24) & SBSDIO_SBADDRHIGH_MASK, &err);
    365 
    366 
    367 	return err;
    368 }
    369 
    370 uint32
    371 bcmsdh_reg_read(void *sdh, uint32 addr, uint size)
    372 {
    373 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    374 	SDIOH_API_RC status;
    375 	uint32 word = 0;
    376 	uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
    377 
    378 	BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, ", __FUNCTION__, addr));
    379 
    380 	if (!bcmsdh)
    381 		bcmsdh = l_bcmsdh;
    382 
    383 	ASSERT(bcmsdh->init_success);
    384 
    385 	if (bar0 != bcmsdh->sbwad) {
    386 		if (bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0))
    387 			return 0xFFFFFFFF;
    388 
    389 		bcmsdh->sbwad = bar0;
    390 	}
    391 
    392 	addr &= SBSDIO_SB_OFT_ADDR_MASK;
    393 	if (size == 4)
    394 		addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
    395 
    396 	status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL,
    397 		SDIOH_READ, SDIO_FUNC_1, addr, &word, size);
    398 
    399 	bcmsdh->regfail = !(SDIOH_API_SUCCESS(status));
    400 
    401 	BCMSDH_INFO(("uint32data = 0x%x\n", word));
    402 
    403 	/* if ok, return appropriately masked word */
    404 	if (SDIOH_API_SUCCESS(status)) {
    405 		switch (size) {
    406 			case sizeof(uint8):
    407 				return (word & 0xff);
    408 			case sizeof(uint16):
    409 				return (word & 0xffff);
    410 			case sizeof(uint32):
    411 				return word;
    412 			default:
    413 				bcmsdh->regfail = TRUE;
    414 
    415 		}
    416 	}
    417 
    418 	/* otherwise, bad sdio access or invalid size */
    419 	BCMSDH_ERROR(("%s: error reading addr 0x%04x size %d\n", __FUNCTION__, addr, size));
    420 	return 0xFFFFFFFF;
    421 }
    422 
    423 uint32
    424 bcmsdh_reg_write(void *sdh, uint32 addr, uint size, uint32 data)
    425 {
    426 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    427 	SDIOH_API_RC status;
    428 	uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
    429 	int err = 0;
    430 
    431 	BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
    432 	             __FUNCTION__, addr, size*8, data));
    433 
    434 	if (!bcmsdh)
    435 		bcmsdh = l_bcmsdh;
    436 
    437 	ASSERT(bcmsdh->init_success);
    438 
    439 	if (bar0 != bcmsdh->sbwad) {
    440 		if ((err = bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0)))
    441 			return err;
    442 
    443 		bcmsdh->sbwad = bar0;
    444 	}
    445 
    446 	addr &= SBSDIO_SB_OFT_ADDR_MASK;
    447 	if (size == 4)
    448 		addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
    449 	status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_WRITE, SDIO_FUNC_1,
    450 	                            addr, &data, size);
    451 	bcmsdh->regfail = !(SDIOH_API_SUCCESS(status));
    452 
    453 	if (SDIOH_API_SUCCESS(status))
    454 		return 0;
    455 
    456 	BCMSDH_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
    457 	              __FUNCTION__, data, addr, size));
    458 	return 0xFFFFFFFF;
    459 }
    460 
    461 bool
    462 bcmsdh_regfail(void *sdh)
    463 {
    464 	return ((bcmsdh_info_t *)sdh)->regfail;
    465 }
    466 
    467 int
    468 bcmsdh_recv_buf(void *sdh, uint32 addr, uint fn, uint flags,
    469                 uint8 *buf, uint nbytes, void *pkt,
    470                 bcmsdh_cmplt_fn_t complete, void *handle)
    471 {
    472 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    473 	SDIOH_API_RC status;
    474 	uint incr_fix;
    475 	uint width;
    476 	uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
    477 	int err = 0;
    478 
    479 	ASSERT(bcmsdh);
    480 	ASSERT(bcmsdh->init_success);
    481 
    482 	BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
    483 	             __FUNCTION__, fn, addr, nbytes));
    484 
    485 	/* Async not implemented yet */
    486 	ASSERT(!(flags & SDIO_REQ_ASYNC));
    487 	if (flags & SDIO_REQ_ASYNC)
    488 		return BCME_UNSUPPORTED;
    489 
    490 	if (bar0 != bcmsdh->sbwad) {
    491 		if ((err = bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0)))
    492 			return err;
    493 
    494 		bcmsdh->sbwad = bar0;
    495 	}
    496 
    497 	addr &= SBSDIO_SB_OFT_ADDR_MASK;
    498 
    499 	incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
    500 	width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
    501 	if (width == 4)
    502 		addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
    503 
    504 	status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, incr_fix,
    505 	                              SDIOH_READ, fn, addr, width, nbytes, buf, pkt);
    506 
    507 	return (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR);
    508 }
    509 
    510 int
    511 bcmsdh_send_buf(void *sdh, uint32 addr, uint fn, uint flags,
    512                 uint8 *buf, uint nbytes, void *pkt,
    513                 bcmsdh_cmplt_fn_t complete, void *handle)
    514 {
    515 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    516 	SDIOH_API_RC status;
    517 	uint incr_fix;
    518 	uint width;
    519 	uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
    520 	int err = 0;
    521 
    522 	ASSERT(bcmsdh);
    523 	ASSERT(bcmsdh->init_success);
    524 
    525 	BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
    526 	            __FUNCTION__, fn, addr, nbytes));
    527 
    528 	/* Async not implemented yet */
    529 	ASSERT(!(flags & SDIO_REQ_ASYNC));
    530 	if (flags & SDIO_REQ_ASYNC)
    531 		return BCME_UNSUPPORTED;
    532 
    533 	if (bar0 != bcmsdh->sbwad) {
    534 		if ((err = bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0)))
    535 			return err;
    536 
    537 		bcmsdh->sbwad = bar0;
    538 	}
    539 
    540 	addr &= SBSDIO_SB_OFT_ADDR_MASK;
    541 
    542 	incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
    543 	width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
    544 	if (width == 4)
    545 		addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
    546 
    547 	status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, incr_fix,
    548 	                              SDIOH_WRITE, fn, addr, width, nbytes, buf, pkt);
    549 
    550 	return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
    551 }
    552 
    553 int
    554 bcmsdh_rwdata(void *sdh, uint rw, uint32 addr, uint8 *buf, uint nbytes)
    555 {
    556 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    557 	SDIOH_API_RC status;
    558 
    559 	ASSERT(bcmsdh);
    560 	ASSERT(bcmsdh->init_success);
    561 	ASSERT((addr & SBSDIO_SBWINDOW_MASK) == 0);
    562 
    563 	addr &= SBSDIO_SB_OFT_ADDR_MASK;
    564 	addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
    565 
    566 	status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, SDIOH_DATA_INC,
    567 	                              (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
    568 	                              addr, 4, nbytes, buf, NULL);
    569 
    570 	return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
    571 }
    572 
    573 int
    574 bcmsdh_abort(void *sdh, uint fn)
    575 {
    576 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    577 
    578 	return sdioh_abort(bcmsdh->sdioh, fn);
    579 }
    580 
    581 int
    582 bcmsdh_start(void *sdh, int stage)
    583 {
    584 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    585 
    586 	return sdioh_start(bcmsdh->sdioh, stage);
    587 }
    588 
    589 int
    590 bcmsdh_stop(void *sdh)
    591 {
    592 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    593 
    594 	return sdioh_stop(bcmsdh->sdioh);
    595 }
    596 
    597 
    598 int
    599 bcmsdh_query_device(void *sdh)
    600 {
    601 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    602 	bcmsdh->vendevid = (VENDOR_BROADCOM << 16) | 0;
    603 	return (bcmsdh->vendevid);
    604 }
    605 
    606 uint
    607 bcmsdh_query_iofnum(void *sdh)
    608 {
    609 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    610 
    611 	if (!bcmsdh)
    612 		bcmsdh = l_bcmsdh;
    613 
    614 	return (sdioh_query_iofnum(bcmsdh->sdioh));
    615 }
    616 
    617 int
    618 bcmsdh_reset(bcmsdh_info_t *sdh)
    619 {
    620 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    621 
    622 	return sdioh_sdio_reset(bcmsdh->sdioh);
    623 }
    624 
    625 void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh)
    626 {
    627 	ASSERT(sdh);
    628 	return sdh->sdioh;
    629 }
    630 
    631 /* Function to pass device-status bits to DHD. */
    632 uint32
    633 bcmsdh_get_dstatus(void *sdh)
    634 {
    635 	return 0;
    636 }
    637 uint32
    638 bcmsdh_cur_sbwad(void *sdh)
    639 {
    640 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
    641 
    642 	if (!bcmsdh)
    643 		bcmsdh = l_bcmsdh;
    644 
    645 	return (bcmsdh->sbwad);
    646 }
    647 
    648 void
    649 bcmsdh_chipinfo(void *sdh, uint32 chip, uint32 chiprev)
    650 {
    651 	return;
    652 }
    653