/* Driver_SetAddressWindowRegister - Utility function to set the window * register. This is used for diagnostic reads and writes. * void *pCxt - the driver context. * uint32_t RegisterAddr - The window register address. * uint32_t Address - the target address. *****************************************************************************/ static A_STATUS Driver_SetAddressWindowRegister(void *pCxt, uint32_t RegisterAddr, uint32_t Address) { A_STATUS status; A_NETBUF_DECLARE req; void *pReq = (void *)&req; Address = A_CPU2LE32(Address); do { A_NETBUF_CONFIGURE(pReq, (((uint8_t *)(&Address)) + 1), (sizeof(uint32_t) - 1)); ATH_SET_PIO_EXTERNAL_WRITE_OPERATION(pReq, RegisterAddr + 1, true, (sizeof(uint32_t) - 1)); if (A_OK != (status = Hcd_DoPioExternalAccess(pCxt, pReq))) { break; } A_NETBUF_CONFIGURE(pReq, ((uint8_t *)(&Address)), sizeof(uint8_t)); ATH_SET_PIO_EXTERNAL_WRITE_OPERATION(pReq, RegisterAddr, true, sizeof(uint8_t)); if (A_OK != (status = Hcd_DoPioExternalAccess(pCxt, pReq))) { break; } } while (0); return status; }
/* Driver_WriteRegDiag - Writes four bytes of data to the specified chip * device address. * void *pCxt - the driver context. * uint32_t address - the device chip address to start the write. * uint8_t *data - the start of data source buffer. *****************************************************************************/ A_STATUS Driver_WriteRegDiag(void *pCxt, uint32_t *address, uint32_t *data) { A_STATUS status; A_NETBUF_DECLARE req; void *pReq = (void *)&req; A_NETBUF_CONFIGURE(pReq, data, 0, sizeof(uint32_t), sizeof(uint32_t)); ATH_SET_PIO_EXTERNAL_WRITE_OPERATION(pReq, WINDOW_DATA_ADDRESS, true, sizeof(uint32_t)); do { if (A_OK != (status = Hcd_DoPioExternalAccess(pCxt, pReq))) { break; } /* set window register, which starts the write cycle */ if (A_OK != (status = Driver_SetAddressWindowRegister(pCxt, WINDOW_WRITE_ADDR_ADDRESS, *address))) { break; } } while (0); return status; }
/* Driver_SetAddressWindowRegister - Utility function to set the window * register. This is used for diagnostic reads and writes. * void *pCxt - the driver context. * uint32_t RegisterAddr - The window register address. * uint32_t Address - the target address. *****************************************************************************/ static A_STATUS Driver_SetAddressWindowRegister(void *pCxt, uint32_t RegisterAddr, uint32_t Address) { A_STATUS status; uint8_t addrValue[4]; int32_t i; A_NETBUF_DECLARE req; void *pReq = (void *)&req; /* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written * last to initiate the access cycle */ Address = A_CPU2LE32(Address); for (i = 1; i <= 3; i++) { /* fill the buffer with the address byte value we want to hit 4 times*/ addrValue[0] = ((uint8_t *)&Address)[i]; addrValue[1] = addrValue[0]; addrValue[2] = addrValue[0]; addrValue[3] = addrValue[0]; A_NETBUF_CONFIGURE(pReq, (void *)addrValue, 0, 4, 4); ATH_SET_PIO_EXTERNAL_WRITE_OPERATION(pReq, RegisterAddr + i, false, 4); if (A_OK != (status = Hcd_DoPioExternalAccess(pCxt, pReq))) { break; } } if (status != A_OK) { return status; } A_NETBUF_CONFIGURE(pReq, (void *)&Address, 0, 4, 4); ATH_SET_PIO_EXTERNAL_WRITE_OPERATION(pReq, RegisterAddr, true, 4); status = Hcd_DoPioExternalAccess(pCxt, pReq); return status; }
A_STATUS HIFReadWrite(HIF_DEVICE *device, A_UINT32 address, A_UCHAR *buffer, A_UINT32 length, A_UINT32 request, void *context) { SDIO_STATUS status; SDREQUEST *sdrequest; BUS_REQUEST *busrequest = NULL; A_STATUS a_status = A_OK; /* Return any new requests if the shutdown is already in progress */ if (device->shutdownInProgress) { if (request & HIF_ASYNCHRONOUS) { device->htcCallbacks.rwCompletionHandler(context, A_ERROR); return A_PENDING; } return A_ERROR; } AR_DEBUG_ASSERT(device != NULL); AR_DEBUG_ASSERT(device->handle != NULL); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("Device: %p\n", device)); if (length > device->curBlockSize) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Invalid data length: %d\n", length)); return A_ERROR; } /* * We do not differentiate between the extended and the basic I/O so * we do not process the request type. */ /* * We do not differentiate between the byte and block data mode so * we do not process the request dmode. */ do { /* Addressing mode */ if (request & HIF_FIXED_ADDRESS) { AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("Address mode: Fixed\n")); } else if (request & HIF_INCREMENTAL_ADDRESS) { AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("Address mode: Incremental\n")); } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Invalid address mode: 0x%08x\n", request)); a_status = A_ERROR; break; } /* * Mailbox write. Adjust the address so that the last byte * falls on the EOM address. */ if (request & HIF_WRITE) { if ((address >= HIF_MBOX_START_ADDR(0)) && (address <= HIF_MBOX_END_ADDR(3))) { DBG_ASSERT(length <= HIF_MBOX_WIDTH); address += (HIF_MBOX_WIDTH - length); } } /* Allocate a new bus request */ busrequest = hifAllocateBusRequest(device); if (busrequest == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Unable to allocate bus request\n")); a_status = A_ERROR; break; } sdrequest = busrequest->request; sdrequest->pDataBuffer = buffer; if (request & HIF_SYNCHRONOUS) { AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("Execution mode: Synchronous\n")); sdrequest->Flags = SDREQ_FLAGS_RAW; sdrequest->pCompleteContext = NULL; sdrequest->pCompletion = NULL; } else if (request & HIF_ASYNCHRONOUS) { /* Populate the bus request to be passed in as context */ AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("Execution mode: Asynchronous\n")); /* setup async context */ busrequest->device = device; busrequest->context = context; sdrequest->pCompleteContext = busrequest; sdrequest->Flags = SDREQ_FLAGS_RAW | SDREQ_FLAGS_TRANS_ASYNC; sdrequest->pCompletion = hifRWCompletionHandler; } /* Indicate to the bus driver if its a read or a write */ if (request & HIF_WRITE) { AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("Direction: Write\n")); if (((address >= HIF_MBOX_START_ADDR(0)) && (address <= HIF_MBOX_END_ADDR(3)))) { /* trapping HTC WRITE to mailbox, these will use the special DMA operation */ AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("--- MAILBOX WRITE ACCESS!!!!\n")); ATH_SET_DMA_OPERATION(sdrequest,ATH_TRANS_WRITE,address,length); } else { ATH_SET_PIO_EXTERNAL_WRITE_OPERATION(sdrequest, address, (request & HIF_INCREMENTAL_ADDRESS) ? TRUE : FALSE, length); } } else if (request & HIF_READ) { AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("Direction: Read\n")); if (((address >= HIF_MBOX_START_ADDR(0)) && (address <= HIF_MBOX_END_ADDR(3)))) { AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" --- MAILBOX READ ACCESS!!!!\n")); /* trapping on HTC READ mailbox , these will use the special DMA operation */ ATH_SET_DMA_OPERATION(sdrequest,ATH_TRANS_READ,address,length); } else { ATH_SET_PIO_EXTERNAL_READ_OPERATION(sdrequest, address, request & HIF_INCREMENTAL_ADDRESS ? TRUE : FALSE, length); } } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Invalid direction: 0x%08x\n", request)); a_status = A_ERROR; break; } /* issue the request */ status = SDDEVICE_CALL_REQUEST_FUNC(device->handle, sdrequest); if (!SDIO_SUCCESS(status)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF Read/Write failure: %d\n", status)); a_status = A_ERROR; } } while (FALSE); if ((busrequest != NULL) && (request & HIF_SYNCHRONOUS)) { hifFreeBusRequest(device,busrequest); } return a_status; }