A_STATUS HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode, void *config, A_UINT32 configLen) { A_UINT32 count; switch(opcode) { case HIF_DEVICE_GET_MBOX_BLOCK_SIZE: ((A_UINT32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE; ((A_UINT32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE; ((A_UINT32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE; ((A_UINT32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE; break; case HIF_DEVICE_GET_MBOX_ADDR: for (count = 0; count < 4; count ++) { ((A_UINT32 *)config)[count] = HIF_MBOX_START_ADDR(count); } break; case HIF_DEVICE_GET_IRQ_PROC_MODE: *((HIF_DEVICE_IRQ_PROCESSING_MODE *)config) = HIF_DEVICE_IRQ_SYNC_ONLY; break; case HIF_DEVICE_GET_OS_DEVICE: /* pass back a pointer to the SDIO function's "dev" struct */ ((HIF_DEVICE_OS_DEVICE_INFO *)config)->pOSDevice = &device->func->dev; break; default: AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6000: Unsupported configuration opcode: %d\n", opcode)); return A_ERROR; } return A_OK; }
A_STATUS HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode, void *config, A_UINT32 configLen) { A_UINT32 count; switch(opcode) { case HIF_DEVICE_GET_MBOX_BLOCK_SIZE: ((A_UINT32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE; ((A_UINT32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE; ((A_UINT32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE; ((A_UINT32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE; break; case HIF_DEVICE_GET_MBOX_ADDR: for (count = 0; count < 4; count ++) { ((A_UINT32 *)config)[count] = HIF_MBOX_START_ADDR(count); } if (configLen >= sizeof(HIF_DEVICE_MBOX_INFO)) { HIF_DEVICE_MBOX_INFO *pInfo = (HIF_DEVICE_MBOX_INFO *)config; /* SPI interface cannot handle bundled messages due to limitations * in the bus protocol */ pInfo->Flags |= HIF_MBOX_FLAG_NO_BUNDLING; } break; case HIF_DEVICE_GET_PENDING_EVENTS_FUNC: /* set pending events */ *((HIF_PENDING_EVENTS_FUNC *)config) = hifGetPendingEvents; break; case HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC: /* set recv masking function */ *((HIF_MASK_UNMASK_RECV_EVENT *)config) = hifMaskUnmaskRecvMsg; break; case HIF_DEVICE_GET_IRQ_PROC_MODE: /* only SYNC mode supported */ *((HIF_DEVICE_IRQ_PROCESSING_MODE *)config) = HIF_DEVICE_IRQ_SYNC_ONLY; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" SPI2 HIF requires sync mode IRQ processing \n")); break; case HIF_DEVICE_DEBUG_BUS_STATE: HIFSpiDumpRegs(device); break; default: AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Invalid configuration opcode: %d\n", opcode)); return A_ERROR; } return A_OK; }
A_STATUS HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode, void *config, A_UINT32 configLen) { A_UINT32 count; A_STATUS status = A_OK; switch(opcode) { case HIF_DEVICE_GET_MBOX_BLOCK_SIZE: ((A_UINT32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE; ((A_UINT32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE; ((A_UINT32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE; ((A_UINT32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE; break; case HIF_DEVICE_GET_MBOX_ADDR: for (count = 0; count < 4; count ++) { ((A_UINT32 *)config)[count] = HIF_MBOX_START_ADDR(count); } break; case HIF_DEVICE_GET_IRQ_PROC_MODE: *((HIF_DEVICE_IRQ_PROCESSING_MODE *)config) = HIF_DEVICE_IRQ_SYNC_ONLY; break; case HIF_DEVICE_GET_OS_DEVICE: #if 0 //bluebird /* pass back a pointer to the SDIO function's "dev" struct */ ((HIF_DEVICE_OS_DEVICE_INFO *)config)->pOSDevice = &device->func->dev; #else NDIS_DEBUG_PRINTF(DBG_ERR, "HIF_DEVICE_GET_OS_DEVICE isn't ready ~ must have to do something \r\n"); return A_ERROR; #endif break; case HIF_DEVICE_POWER_STATE_CHANGE: status = PowerChangeNotify(device, *(HIF_DEVICE_POWER_CHANGE_TYPE *)config); break; default: NDIS_DEBUG_PRINTF(DBG_ERR, "AR6000: Unsupported configuration opcode: %d \r\n", opcode); return A_ERROR; } return A_OK; }
A_STATUS HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode, void *config, A_UINT32 configLen) { A_UINT32 count; A_STATUS status; switch(opcode) { case HIF_DEVICE_GET_MBOX_BLOCK_SIZE: ((A_UINT32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE; ((A_UINT32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE; ((A_UINT32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE; ((A_UINT32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE; break; case HIF_DEVICE_GET_MBOX_ADDR: for (count = 0; count < 4; count ++) { ((A_UINT32 *)config)[count] = HIF_MBOX_START_ADDR(count); } if (configLen >= sizeof(HIF_DEVICE_MBOX_INFO)) { SetExtendedMboxWindowInfo((A_UINT16)device->func->device, (HIF_DEVICE_MBOX_INFO *)config); } break; case HIF_DEVICE_GET_IRQ_PROC_MODE: *((HIF_DEVICE_IRQ_PROCESSING_MODE *)config) = HIF_DEVICE_IRQ_SYNC_ONLY; break; case HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT: if (!device->scatter_enabled) { return A_ENOTSUP; } status = SetupHIFScatterSupport(device, (HIF_DEVICE_SCATTER_SUPPORT_INFO *)config); if (A_FAILED(status)) { device->scatter_enabled = FALSE; } return status; case HIF_DEVICE_GET_OS_DEVICE: /* pass back a pointer to the SDIO function's "dev" struct */ ((HIF_DEVICE_OS_DEVICE_INFO *)config)->pOSDevice = &device->func->dev; break; default: AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6000: Unsupported configuration opcode: %d\n", opcode)); return A_ERROR; } return A_OK; }
A_STATUS HIFReadWrite(HIF_DEVICE *device, A_UINT32 address, A_UCHAR *buffer, A_UINT32 length, HIF_REQUEST *request, void *context) { A_UINT8 rw; A_UINT8 mode; A_UINT8 opcode; A_UINT32 blockLen, blockCount, count; PSD_BUS_REQUEST busRequest; A_STATUS status = A_OK; SD_TRANSFER_CLASS transferClass; DWORD dwArg; A_UCHAR command; SD_API_STATUS sdStatus; SD_COMMAND_RESPONSE response; HIF_DEBUG_PRINTF(ATH_LOG_TRC, "HIFReadWrite:Enter\n"); HIF_DEBUG_PRINTF(ATH_LOG_TRC, "Address 0x%x\n", address); if (request->dmode == HIF_BLOCK_BASIS && request->type != HIF_EXTENDED_IO) { HIF_DEBUG_PRINTF(ATH_LOG_ERR, "Block mode not allowed for this type of command\n"); return A_ERROR; } if (request->dmode == HIF_BLOCK_BASIS) { mode = SD_IO_BLOCK_MODE; blockLen = HIF_MBOX_BLOCK_SIZE; blockCount = length / HIF_MBOX_BLOCK_SIZE; count = blockCount; HIF_DEBUG_PRINTF(ATH_LOG_TRC, "Block mode (BlockLen: %d, BlockCount: %d)\n", blockLen, blockCount); } else if (request->dmode == HIF_BYTE_BASIS) { mode = SD_IO_BYTE_MODE; blockLen = length; blockCount = 1; count = blockLen; HIF_DEBUG_PRINTF(ATH_LOG_TRC, "Byte mode (BlockLen: %d, BlockCount: %d)\n", blockLen, blockCount); } else { HIF_DEBUG_PRINTF(ATH_LOG_ERR, "Invalid data mode: %d\n", request->dmode); return A_ERROR; } if (request->amode == HIF_FIXED_ADDRESS) { opcode = SD_IO_FIXED_ADDRESS; HIF_DEBUG_PRINTF(ATH_LOG_TRC, "Fixed "); } else if (request->amode == HIF_INCREMENTAL_ADDRESS) { opcode = SD_IO_INCREMENT_ADDRESS; HIF_DEBUG_PRINTF(ATH_LOG_TRC, "Incremental "); } else { HIF_DEBUG_PRINTF(ATH_LOG_ERR, "Invalid address mode: %d\n", request->amode); return A_ERROR; } if (request->direction == HIF_WRITE) { transferClass = SD_WRITE; rw = SD_IO_OP_WRITE; if ((address >= HIF_MBOX_START_ADDR(0)) && (address <= HIF_MBOX_END_ADDR(3))) { /* Mailbox write. Adjust the address so that the last byte falls on the EOM address */ address = address + HIF_MBOX_WIDTH - length; } HIF_DEBUG_PRINTF(ATH_LOG_TRC, "[Write]"); } else { transferClass = SD_READ; rw = SD_IO_OP_READ; HIF_DEBUG_PRINTF(ATH_LOG_TRC, "[Read ]"); } if (request->type == HIF_EXTENDED_IO) { dwArg = BUILD_IO_RW_EXTENDED_ARG(rw, mode, funcNo, address, opcode, count); command = SD_IO_RW_EXTENDED; } else if (request->type == HIF_BASIC_IO) { dwArg = BUILD_IO_RW_DIRECT_ARG(rw, SD_IO_RW_NORMAL, funcNo, address, 0); command = SD_IO_RW_NORMAL; } else { HIF_DEBUG_PRINTF(ATH_LOG_ERR, "Invalid command type: %d\n", request->type); return A_ERROR; } if (request->emode == HIF_SYNCHRONOUS) { HIF_DEBUG_PRINTF(ATH_LOG_TRC, "Synchronous\n"); sdStatus = SDSynchronousBusRequest(device->handle, command, dwArg, transferClass, ResponseR5, &response, blockCount, blockLen, buffer, 0); if (!SD_API_SUCCESS(sdStatus)) { HIF_DEBUG_PRINTF(ATH_LOG_ERR, "SDBusRequest failed 0x%x\n", sdStatus); status = A_ERROR; } } else { HIF_DEBUG_PRINTF(ATH_LOG_TRC, "Asynchronous\n"); sdStatus = SDBusRequest(device->handle, command, dwArg, transferClass, ResponseR5, blockCount, blockLen, buffer, hifRWCompletionHandler, (DWORD) context, &busRequest, 0); if (!SD_API_SUCCESS(sdStatus)) { status = A_ERROR; } } return status; }
static A_STATUS __HIFReadWrite(HIF_DEVICE *device, A_UINT32 address, A_UCHAR *buffer, A_UINT32 length, A_UINT32 request, void *context) { A_UINT8 opcode; A_STATUS status = A_OK; int ret; A_UINT8 *tbuffer; A_BOOL bounced = FALSE; AR_DEBUG_ASSERT(device != NULL); AR_DEBUG_ASSERT(device->func != NULL); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device: 0x%p, buffer:0x%p (addr:0x%X)\n", device, buffer, address)); do { if (request & HIF_EXTENDED_IO) { //AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Command type: CMD53\n")); } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: Invalid command type: 0x%08x\n", request)); status = A_EINVAL; break; } if (request & HIF_BLOCK_BASIS) { /* round to whole block length size */ length = (length / HIF_MBOX_BLOCK_SIZE) * HIF_MBOX_BLOCK_SIZE; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Block mode (BlockLen: %d)\n", length)); } else if (request & HIF_BYTE_BASIS) { AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Byte mode (BlockLen: %d)\n", length)); } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: Invalid data mode: 0x%08x\n", request)); status = A_EINVAL; break; } #if 0 /* useful for checking register accesses */ if (length & 0x3) { A_PRINTF(KERN_ALERT"AR6000: HIF (%s) is not a multiple of 4 bytes, addr:0x%X, len:%d\n", request & HIF_WRITE ? "write":"read", address, length); } #endif if (request & HIF_WRITE) { if ((address >= HIF_MBOX_START_ADDR(0)) && (address <= HIF_MBOX_END_ADDR(3))) { AR_DEBUG_ASSERT(length <= HIF_MBOX_WIDTH); /* * Mailbox write. Adjust the address so that the last byte * falls on the EOM address. */ address += (HIF_MBOX_WIDTH - length); } } if (request & HIF_FIXED_ADDRESS) { opcode = CMD53_FIXED_ADDRESS; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Address mode: Fixed 0x%X\n", address)); } else if (request & HIF_INCREMENTAL_ADDRESS) { opcode = CMD53_INCR_ADDRESS; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Address mode: Incremental 0x%X\n", address)); } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: Invalid address mode: 0x%08x\n", request)); status = A_EINVAL; break; } if (request & HIF_WRITE) { #if HIF_USE_DMA_BOUNCE_BUFFER if (BUFFER_NEEDS_BOUNCE(buffer)) { AR_DEBUG_ASSERT(device->dma_buffer != NULL); tbuffer = device->dma_buffer; /* copy the write data to the dma buffer */ AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE); memcpy(tbuffer, buffer, length); bounced = TRUE; } else { tbuffer = buffer; } #else tbuffer = buffer; #endif if (opcode == CMD53_FIXED_ADDRESS) { ret = sdio_writesb(device->func, address, tbuffer, length); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writesb ret=%d address: 0x%X, len: %d, 0x%X\n", ret, address, length, *(int *)tbuffer)); } else { ret = sdio_memcpy_toio(device->func, address, tbuffer, length); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writeio ret=%d address: 0x%X, len: %d, 0x%X\n", ret, address, length, *(int *)tbuffer)); } } else if (request & HIF_READ) { #if HIF_USE_DMA_BOUNCE_BUFFER if (BUFFER_NEEDS_BOUNCE(buffer)) { AR_DEBUG_ASSERT(device->dma_buffer != NULL); AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE); tbuffer = device->dma_buffer; bounced = TRUE; } else { tbuffer = buffer; } #else tbuffer = buffer; #endif if (opcode == CMD53_FIXED_ADDRESS) { ret = sdio_readsb(device->func, tbuffer, address, length); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: readsb ret=%d address: 0x%X, len: %d, 0x%X\n", ret, address, length, *(int *)tbuffer)); } else { ret = sdio_memcpy_fromio(device->func, tbuffer, address, length); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: readio ret=%d address: 0x%X, len: %d, 0x%X\n", ret, address, length, *(int *)tbuffer)); } #if HIF_USE_DMA_BOUNCE_BUFFER if (bounced) { /* copy the read data from the dma buffer */ memcpy(buffer, tbuffer, length); } #endif } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: Invalid direction: 0x%08x\n", request)); status = A_EINVAL; break; } if (ret) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: SDIO bus operation failed! MMC stack returned : %d \n", ret)); status = A_ERROR; } } while (FALSE); return status; }
/* BMI Access routines */ A_STATUS bmiBufferSend(HIF_DEVICE *device, A_UCHAR *buffer, A_UINT32 length) { A_STATUS status; A_UINT32 timeout; A_UINT32 address; #ifdef ONLY_16BIT A_UINT16 cmdCredits; #else A_UCHAR cmdCredits; #endif HIF_REQUEST request; /* Read the counter register to get the command credits */ HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); address = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4; status = HIFReadWrite(device, address, (A_UCHAR *)&cmdCredits, sizeof(cmdCredits), &request, NULL); if (status != A_OK) { BMI_DEBUG_PRINTF(ATH_LOG_ERR,"Unable to decrement the command credit count register\n"); return A_ERROR; } timeout = BMI_COMMUNICATION_TIMEOUT; while(timeout--) { if (cmdCredits == 1) { HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, HIF_BYTE_BASIS, HIF_INCREMENTAL_ADDRESS); address = HIF_MBOX_START_ADDR(ENDPOINT1); status = HIFReadWrite(device, address, buffer, length, &request, NULL); if (status != A_OK) { BMI_DEBUG_PRINTF(ATH_LOG_ERR,"Unable to send the BMI data to the device\n"); return A_ERROR; } break; } HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); address = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4; status = HIFReadWrite(device, address, (A_UCHAR *)&cmdCredits, sizeof(cmdCredits), &request, NULL); if (status != A_OK) { BMI_DEBUG_PRINTF(ATH_LOG_ERR,"Unable to decrement the command credit count register\n"); return A_ERROR; } status = A_ERROR; A_MDELAY(1); } if (status != A_OK) { BMI_DEBUG_PRINTF(ATH_LOG_ERR,"BMI Communication timeout\n"); } return status; }
static A_STATUS __HIFReadWrite(HIF_DEVICE *device, A_UINT32 address, A_UCHAR *buffer, A_UINT32 length, A_UINT32 request, void *context) { A_UINT8 rw; A_UINT8 mode; A_UINT8 opcode; A_UINT32 blockLen, blockCount, count; PSD_BUS_REQUEST busRequest=NULL; A_STATUS status = A_OK; SD_TRANSFER_CLASS transferClass; DWORD dwArg; A_UCHAR command; SD_API_STATUS sdStatus; SD_COMMAND_RESPONSE response; NDIS_DEBUG_PRINTF(0, "%s() : Enter \r\n",__FUNCTION__); if(context != NULL) NDIS_DEBUG_PRINTF(0, "%s() : context = 0x%08x \r\n", __FUNCTION__,context); if ((request & HIF_BLOCK_BASIS) && (!(request & HIF_EXTENDED_IO))) { NDIS_DEBUG_PRINTF(DBG_ERR, "Block mode not allowed for this type of command\r\n"); return A_ERROR; } if (request & HIF_BLOCK_BASIS) { mode = SD_IO_BLOCK_MODE; blockLen = HIF_MBOX_BLOCK_SIZE; blockCount = length / HIF_MBOX_BLOCK_SIZE; count = blockCount; } else if (request & HIF_BYTE_BASIS) { mode = SD_IO_BYTE_MODE; blockLen = length; blockCount = 1; count = blockLen; } else { NDIS_DEBUG_PRINTF(DBG_ERR, "Invalid data mode: %08x\r\n", request); return A_ERROR; } if (request & HIF_FIXED_ADDRESS) { opcode = SD_IO_FIXED_ADDRESS; NDIS_DEBUG_PRINTF(DBG_TRACE, "Fixed "); } else if (request & HIF_INCREMENTAL_ADDRESS) { opcode = SD_IO_INCREMENT_ADDRESS; NDIS_DEBUG_PRINTF(0, "Incremental "); } else { NDIS_DEBUG_PRINTF(DBG_ERR, "Invalid address mode: %08x\r\n", request); return A_ERROR; } if (request & HIF_WRITE) { transferClass = SD_WRITE; rw = SD_IO_OP_WRITE; if ((address >= HIF_MBOX_START_ADDR(0)) && (address <= HIF_MBOX_END_ADDR(3))) { /* Mailbox write. Adjust the address so that the last byte falls on the EOM address */ address = address + HIF_MBOX_WIDTH - length; } NDIS_DEBUG_PRINTF(0, "[Write]"); } else { transferClass = SD_READ; rw = SD_IO_OP_READ; NDIS_DEBUG_PRINTF(0, "[Read ] \r\n"); } if (request & HIF_EXTENDED_IO) { dwArg = BUILD_IO_RW_EXTENDED_ARG(rw, mode, funcNo, address, opcode, count); command = SD_IO_RW_EXTENDED; } else if (request & HIF_BASIC_IO) { dwArg = BUILD_IO_RW_DIRECT_ARG(rw, SD_IO_RW_NORMAL, funcNo, address, 0); command = SD_IO_RW_NORMAL; } else { NDIS_DEBUG_PRINTF(DBG_ERR, "Invalid command type: %08x\r\n", request); return A_ERROR; } if((request & HIF_READ) && (dwArg > 0x14000000)) { NDIS_DEBUG_PRINTF(DBG_TRACE, "Synchronous, command = %d, dwArg = 0x%08x, funcNo=%d \r\n", command, dwArg,funcNo); NDIS_DEBUG_PRINTF(0, "blockCount=%d,blockLen=%d \r\n", blockCount, blockLen); } sdStatus = SDSynchronousBusRequest(device->handle, command, dwArg, transferClass, ResponseR5, &response, blockCount, blockLen, buffer, 0); if (!SD_API_SUCCESS(sdStatus)) { NDIS_DEBUG_PRINTF(DBG_ERR, "SDBusRequest failed 0x%x, device->handle = 0x%x, buffer = 0x%x\r\n", sdStatus, device->handle, buffer); NDIS_DEBUG_PRINTF(DBG_ERR, "1[%d]2[%d]3[%d]4[%d]5[%d]6[%d] \r\n",buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5]); status = A_ERROR; } if(status != A_OK) NDIS_DEBUG_PRINTF(DBG_ERR, "%s() : Status = %d - Exit \r\n",__FUNCTION__, status); 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; }