/* called by async task to perform the operation synchronously using direct MMC APIs */ A_STATUS DoHifReadWriteScatter(HIF_DEVICE *device, BUS_REQUEST *busrequest) { int i; A_UINT8 rw; A_UINT8 opcode; struct mmc_request mmcreq; struct mmc_command cmd; struct mmc_data data; HIF_SCATTER_REQ_PRIV *pReqPriv; HIF_SCATTER_REQ *pReq; A_STATUS status = A_OK; struct scatterlist *pSg; pReqPriv = busrequest->pScatterReq; A_ASSERT(pReqPriv != NULL); pReq = pReqPriv->pHifScatterReq; memset(&mmcreq, 0, sizeof(struct mmc_request)); memset(&cmd, 0, sizeof(struct mmc_command)); memset(&data, 0, sizeof(struct mmc_data)); data.blksz = HIF_MBOX_BLOCK_SIZE; data.blocks = pReq->TotalLength / HIF_MBOX_BLOCK_SIZE; AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: (%s) Address: 0x%X, (BlockLen: %d, BlockCount: %d) , (tot:%d,sg:%d)\n", (pReq->Request & HIF_WRITE) ? "WRITE":"READ", pReq->Address, data.blksz, data.blocks, pReq->TotalLength,pReq->ValidScatterEntries)); if (pReq->Request & HIF_WRITE) { rw = _CMD53_ARG_WRITE; data.flags = MMC_DATA_WRITE; } else { rw = _CMD53_ARG_READ; data.flags = MMC_DATA_READ; } if (pReq->Request & HIF_FIXED_ADDRESS) { opcode = _CMD53_ARG_FIXED_ADDRESS; } else { opcode = _CMD53_ARG_INCR_ADDRESS; } /* fill SG entries */ pSg = pReqPriv->sgentries; sg_init_table(pSg, pReq->ValidScatterEntries); /* assemble SG list */ for (i = 0 ; i < pReq->ValidScatterEntries ; i++, pSg++) { /* setup each sg entry */ if ((unsigned long)pReq->ScatterList[i].pBuffer & 0x3) { /* note some scatter engines can handle unaligned buffers, print this * as informational only */ AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF: (%s) Scatter Buffer is unaligned 0x%lx\n", pReq->Request & HIF_WRITE ? "WRITE":"READ", (unsigned long)pReq->ScatterList[i].pBuffer)); } AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, (" %d: Addr:0x%lX, Len:%d \n", i,(unsigned long)pReq->ScatterList[i].pBuffer,pReq->ScatterList[i].Length)); sg_set_buf(pSg, pReq->ScatterList[i].pBuffer, pReq->ScatterList[i].Length); } /* set scatter-gather table for request */ data.sg = pReqPriv->sgentries; data.sg_len = pReq->ValidScatterEntries; /* set command argument */ SDIO_SET_CMD53_ARG(cmd.arg, rw, device->func->num, _CMD53_ARG_BLOCK_BASIS, opcode, pReq->Address, data.blocks); cmd.opcode = SD_IO_RW_EXTENDED; cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; mmcreq.cmd = &cmd; mmcreq.data = &data; mmc_set_data_timeout(&data, device->func->card); /* synchronous call to process request */ mmc_wait_for_req(device->func->card->host, &mmcreq); if (cmd.error) { status = A_ERROR; AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: cmd error: %d \n",cmd.error)); } if (data.error) { status = A_ERROR; AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: data error: %d \n",data.error)); } if (A_FAILED(status)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: FAILED!!! (%s) Address: 0x%X, Block mode (BlockLen: %d, BlockCount: %d)\n", (pReq->Request & HIF_WRITE) ? "WRITE":"READ",pReq->Address, data.blksz, data.blocks)); } /* set completion status, fail or success */ pReq->CompletionStatus = status; if (pReq->Request & HIF_ASYNCHRONOUS) { AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: async_task completion routine req: 0x%lX (%d)\n",(unsigned long)busrequest, status)); /* complete the request */ A_ASSERT(pReq->CompletionRoutine != NULL); pReq->CompletionRoutine(pReq); } else { AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER async_task upping busrequest : 0x%lX (%d)\n", (unsigned long)busrequest,status)); /* signal wait */ up(&busrequest->sem_req); } return status; }
static A_STATUS HifReadWriteScatter(HIF_DEVICE *device, HIF_SCATTER_REQ *pReq) { A_STATUS status = A_EINVAL; SDREQUEST *sdrequest; A_UINT8 rw; A_UINT8 mode; A_UINT8 funcNo; A_UINT8 opcode; A_UINT16 count; SDIO_STATUS sdiostatus; A_UINT32 request = pReq->Request; do { AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("HIF Scatter : %d Scatter Entries: %d\n", pReq->TotalLength, pReq->ValidScatterEntries)); if (pReq->TotalLength > MAX_SCATTER_REQ_TRANSFER_SIZE) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Invalid length: %d \n", pReq->TotalLength)); break; } if (pReq->TotalLength == 0) { A_ASSERT(FALSE); break; } /* get the sd bus request associated with this scatter request */ sdrequest = GET_SDREQUEST_SR(pReq); if (request & HIF_SYNCHRONOUS) { sdrequest->Flags = SDREQ_FLAGS_RESP_SDIO_R5 | SDREQ_FLAGS_DATA_TRANS; sdrequest->pCompleteContext = NULL; sdrequest->pCompletion = NULL; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,(" Synchronous \n")); } else if (request & HIF_ASYNCHRONOUS) { sdrequest->Flags = SDREQ_FLAGS_RESP_SDIO_R5 | SDREQ_FLAGS_DATA_TRANS | SDREQ_FLAGS_TRANS_ASYNC; sdrequest->pCompleteContext = pReq; sdrequest->pCompletion = HifReadWriteScatterCompletion; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,(" Asynchronous \n")); } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Invalid execution mode: 0x%08x\n", request)); break; } if (!(request & HIF_EXTENDED_IO)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Invalid command type: 0x%08x\n", request)); break; } sdrequest->Command = CMD53; if (!(request & HIF_BLOCK_BASIS)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Invalid data mode: 0x%08x\n", request)); break; } /* only block-mode commands */ mode = CMD53_BLOCK_BASIS; sdrequest->BlockLen = HIF_MBOX_BLOCK_SIZE; sdrequest->BlockCount = pReq->TotalLength / HIF_MBOX_BLOCK_SIZE; count = sdrequest->BlockCount; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, (" Block mode (BlockLen: %d, BlockCount: %d)\n", sdrequest->BlockLen, sdrequest->BlockCount)); if (request & HIF_WRITE) { rw = CMD53_WRITE; sdrequest->Flags |= SDREQ_FLAGS_DATA_WRITE; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, (" Direction: Write\n")); } else if (request & HIF_READ) { rw = CMD53_READ; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, (" Direction: Read\n")); } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Invalid direction: 0x%08x\n", request)); break; } if (request & HIF_FIXED_ADDRESS) { opcode = CMD53_FIXED_ADDRESS; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, (" Address mode: Fixed\n")); } else if (request & HIF_INCREMENTAL_ADDRESS) { opcode = CMD53_INCR_ADDRESS; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, (" Address mode: Incremental\n")); } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Invalid address mode: 0x%08x\n", request)); break; } funcNo = SDDEVICE_GET_SDIO_FUNCNO(device->handle); SDIO_SET_CMD53_ARG(sdrequest->Argument, rw, funcNo, mode, opcode, pReq->Address, count); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("HIF Scatter : SDIO CMD53 card address: 0x%X blocks: %d\n", pReq->Address, count)); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("HIF Scatter : SDIO CMD53 , request flags:0x%X arg:0x%X\n", sdrequest->Flags, sdrequest->Argument)); status = SetupBusRequestForDMA(device, sdrequest, pReq); if (A_FAILED(status)){ break; } if (sdrequest->pDataBuffer == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, (" sdrequest->pDataBuffer is NULL!!!\n")); status = A_ERROR; // A_ASSERT(FALSE); break; } /* Send the command out */ sdiostatus = SDDEVICE_CALL_REQUEST_FUNC(device->handle, sdrequest); if (!SDIO_SUCCESS(sdiostatus)) { status = A_ERROR; break; } status = A_OK; } while (FALSE); if (A_FAILED(status) && (request & HIF_ASYNCHRONOUS)) { pReq->CompletionStatus = status; pReq->CompletionRoutine(pReq); status = A_OK; } return status; }