first and last commit
This commit is contained in:
commit
1bf4efd552
2612 files changed
+636500
No files matched your search
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
#include <AssertMacros.h>
|
||||
|
||||
#include <platform/soc/hwclocks.h>
|
||||
#include <platform/soc/pmgr.h>
|
||||
#include <platform/memmap.h>
|
||||
#include <platform.h>
|
||||
|
||||
#include <sys/task.h>
|
||||
|
||||
#include <iop.h>
|
||||
#include <qwi.h>
|
||||
#include <EmbeddedIOPProtocol.h>
|
||||
|
||||
#include "iop_sdio_protocol.h"
|
||||
#include "iop_sdio_wrapper.h"
|
||||
|
||||
#define cache_op_size(buf_size) (((buf_size) + (CPU_CACHELINE_SIZE-1)) & ~(CPU_CACHELINE_SIZE-1))
|
||||
|
||||
|
||||
static struct task_event sdio_message_event;
|
||||
|
||||
static int sdio_channel;
|
||||
static void sdio_message_wakeup(void *arg);
|
||||
static bool sdio_message_process(void);
|
||||
|
||||
static int iop_sdio_task(void *cfg);
|
||||
|
||||
IOP_FUNCTION(sdio, iop_sdio_task, 1024, SDIO_CONTROL_CHANNEL);
|
||||
|
||||
static int
|
||||
iop_sdio_task(void *cfg)
|
||||
{
|
||||
struct iop_channel_config *channel = (struct iop_channel_config *)cfg;
|
||||
|
||||
dprintf(DEBUG_SPEW, "++ SDIO task starting\n");
|
||||
|
||||
check(kIOPSDIO_COMMAND_SIZE == sizeof(IOPSDIO_Command));
|
||||
|
||||
/* establish the host communications channel */
|
||||
event_init(&sdio_message_event, EVENT_FLAG_AUTO_UNSIGNAL, false);
|
||||
dprintf(DEBUG_SPEW, "++ opening sdio channel\n");
|
||||
sdio_channel = qwi_instantiate_channel(
|
||||
"sdio message",
|
||||
QWI_ROLE_CONSUMER,
|
||||
channel->ring_size,
|
||||
(void *)mem_static_map_cached(channel->ring_base),
|
||||
sdio_message_wakeup,
|
||||
NULL);
|
||||
|
||||
for (;;) {
|
||||
dprintf(DEBUG_SPEW, "++ waiting for message on sdio channel\n");
|
||||
while (sdio_message_process())
|
||||
{
|
||||
// eat all available messages
|
||||
}
|
||||
event_wait(&sdio_message_event);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void
|
||||
sdio_message_wakeup(void *arg __unused)
|
||||
{
|
||||
event_signal(&sdio_message_event);
|
||||
}
|
||||
|
||||
extern unsigned int do_lookahead;
|
||||
extern void iopsdio_cacheTransferSDIOData(struct IOPSDIOTargetSDHC *targetSDHC);
|
||||
|
||||
|
||||
static bool
|
||||
sdio_message_process(void)
|
||||
{
|
||||
uint32_t messageAddr;
|
||||
|
||||
dprintf(DEBUG_SPEW, "++ handling host message\n");
|
||||
|
||||
do_lookahead = 0;
|
||||
|
||||
/* look to see if there's an item waiting for us */
|
||||
if (qwi_receive_item(sdio_channel, &messageAddr) == -1)
|
||||
return(false);
|
||||
|
||||
dprintf(DEBUG_SPEW, "++ received sdio message\n");
|
||||
|
||||
/* find the command structure based on the message */
|
||||
union IOPSDIOMessage *message = (union IOPSDIOMessage*)mem_static_map_cached(messageAddr);
|
||||
|
||||
/*
|
||||
* Flush any cached item contents we might have lying around - we are guaranteed
|
||||
* that the message size is a multiple of our cacheline size.
|
||||
*/
|
||||
platform_cache_operation(CACHE_INVALIDATE,
|
||||
(void *)message,
|
||||
cache_op_size(sizeof(*message)));
|
||||
|
||||
|
||||
switch (message->header.opcode) {
|
||||
|
||||
case kIOPSDIOOpcodeInit:
|
||||
{
|
||||
dprintf(DEBUG_INFO, "SDHC @ 0x%X: Init\n",
|
||||
message->targetSDHC.basePhysicalAddr);
|
||||
|
||||
message->header.status = iopsdio_init(&message->targetSDHC, &message->initCmd);
|
||||
break;
|
||||
}
|
||||
case kIOPSDIOOpcodeFree:
|
||||
{
|
||||
dprintf(DEBUG_INFO, "SDHC @ 0x%X: Free\n",
|
||||
message->targetSDHC.basePhysicalAddr);
|
||||
|
||||
message->header.status = iopsdio_free(&message->targetSDHC, &message->freeCmd);
|
||||
break;
|
||||
}
|
||||
case kIOPSDIOOpcodeReset:
|
||||
{
|
||||
dprintf(DEBUG_INFO, "SDHC @ 0x%X: Reset 0x%X\n",
|
||||
message->targetSDHC.basePhysicalAddr, message->resetCmd.resetFlags);
|
||||
|
||||
message->header.status = iopsdio_reset(&message->targetSDHC, &message->resetCmd);
|
||||
break;
|
||||
}
|
||||
case kIOPSDIOOpcodeSetBusParam:
|
||||
{
|
||||
/* dprintf(DEBUG_INFO, "SDHC @ 0x%X: clk = %+d, baseClk = %u, clkRate = %u Hz, width = %u, speed = %d\n",
|
||||
message->targetSDHC.basePhysicalAddr,
|
||||
message->setBusParamCmd.clockMode, message->setBusParamCmd.baseClockRateHz,
|
||||
message->setBusParamCmd.clockRateHz, message->setBusParamCmd.busWidth,
|
||||
message->setBusParamCmd.busSpeedMode);
|
||||
*/
|
||||
message->header.status = iopsdio_setBusConfig(&message->targetSDHC, &message->setBusParamCmd);
|
||||
break;
|
||||
}
|
||||
case kIOPSDIOOpcodeSendCommand:
|
||||
{
|
||||
/* dprintf(DEBUG_INFO, "SDHC @ 0x%X: Send SDIO Cmd: index = %u, arg = 0x%X\n",
|
||||
message->targetSDHC.basePhysicalAddr,
|
||||
message->sendSDIOCmd.sdioCmdIndex, message->sendSDIOCmd.sdioCmdArgument);
|
||||
*/
|
||||
message->header.status = iopsdio_sendSDIOCmd(&message->targetSDHC, &message->commandCmd);
|
||||
break;
|
||||
}
|
||||
case kIOPSDIOOpcodeTransferData:
|
||||
{
|
||||
/* dprintf(DEBUG_INFO, "SDHC @ 0x%X: Send SDIO DMA Cmd: index = %u, arg = 0x%X\n",
|
||||
message->targetSDHC.basePhysicalAddr,
|
||||
message->sdioDataCmd.sdioCmdIndex, message->sdioDataCmd.sdioCmdArgument);
|
||||
*/
|
||||
message->header.status = iopsdio_transferSDIOData(&message->targetSDHC, &message->transferCmd);
|
||||
break;
|
||||
}
|
||||
case kIOPSDIOOpcodePing:
|
||||
dprintf(DEBUG_CRITICAL, "SDHC: Ping received, IOKit <--> IOP Connection established\n");
|
||||
message->header.status = kIOPSDIOStatusSuccess;
|
||||
break;
|
||||
default:
|
||||
dprintf(DEBUG_CRITICAL, "SDHC @ 0x%X: ERROR: unrecognised sdio opcode 0x%x\n",
|
||||
message->targetSDHC.basePhysicalAddr, message->header.opcode);
|
||||
message->header.status = kIOPSDIOParameterInvalid;
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf(DEBUG_SPEW, "++ done processing sdio message with status 0x%08x\n", message->header.status);
|
||||
|
||||
platform_cache_operation(CACHE_CLEAN,
|
||||
(void *)message,
|
||||
sizeof(union IOPSDIOMessage));
|
||||
|
||||
qwi_send_item(sdio_channel, messageAddr);
|
||||
|
||||
|
||||
{
|
||||
if (do_lookahead) {
|
||||
iopsdio_cacheTransferSDIOData(&message->targetSDHC);
|
||||
do_lookahead = 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
dprintf(DEBUG_SPEW, "++ signaled completion of sdio message to host\n");
|
||||
|
||||
return(true);
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef _IOP_SDIO_PROTOCOL_H_
|
||||
#define _IOP_SDIO_PROTOCOL_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef PLATFORM_VARIANT_IOP
|
||||
#include <sdiocommon/sdio_types.h>
|
||||
#else
|
||||
#include <IOKit/sdio/sdio_types.h>
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Command size is (somewhat) tunable.
|
||||
*
|
||||
* The principal consideration here is the maximum scatter/gather list size
|
||||
* this permits.
|
||||
*/
|
||||
#define kIOPSDIO_MESSAGE_SIZE (512)
|
||||
|
||||
|
||||
typedef UInt32 IOPSDIO_opcode_t;
|
||||
|
||||
enum IOPSDIOOpcode
|
||||
{
|
||||
kIOPSDIOOpcodeUnknown = 0,
|
||||
kIOPSDIOOpcodePing = 1,
|
||||
kIOPSDIOOpcodeInit = 2,
|
||||
kIOPSDIOOpcodeFree = 3,
|
||||
kIOPSDIOOpcodeReset = 4,
|
||||
kIOPSDIOOpcodeSetBusParam = 5,
|
||||
kIOPSDIOOpcodeSendCommand = 6,
|
||||
kIOPSDIOOpcodeTransferData = 7,
|
||||
};
|
||||
|
||||
|
||||
typedef UInt32 IOPSDIO_flags_t;
|
||||
|
||||
enum IOPSDIOFlags
|
||||
{
|
||||
kIOPSDIOFlagsNone = 0,
|
||||
};
|
||||
|
||||
|
||||
typedef UInt32 IOPSDIO_status_t;
|
||||
|
||||
enum IOPSDIOStatus
|
||||
{
|
||||
// IOP Messaging Errors
|
||||
|
||||
/** @brief Command succeeded. */
|
||||
kIOPSDIOStatusSuccess = 0,
|
||||
|
||||
/** @brief Status is not yet known (e.g. message has not been sent or processed). */
|
||||
kIOPSDIOStatusUnknown = 1,
|
||||
|
||||
/** @brief One of the IOP parameters was invalid. */
|
||||
kIOPSDIOParameterInvalid = 2,
|
||||
|
||||
// Common IOReturn Values
|
||||
// If the IOP Status is in the range [0x200 0x300) then it is a standard
|
||||
// IOKit IOReturn value without the "iokit_common_err( )" bits set
|
||||
|
||||
// SDIOReturn_t Values
|
||||
// If the IOP status is in the range [0x300 0x800) it is an SDIOReturn_t
|
||||
// value. This value is the same as the base value of IOSDIOReturn in the
|
||||
// IOKit SDIO family, without the "iokit_family_err(sub_iokit_sdio, )"
|
||||
// bits set.
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* this must match <drivers/dma.h>::struct dma_segment */
|
||||
struct IOPSDIO_dma_segment {
|
||||
u_int32_t paddr;
|
||||
u_int32_t length;
|
||||
};
|
||||
|
||||
|
||||
/** @brief Standard header on all IOP SDIO Commands. */
|
||||
struct IOPSDIOHeader
|
||||
{
|
||||
IOPSDIO_opcode_t opcode;
|
||||
IOPSDIO_flags_t flags;
|
||||
IOPSDIO_status_t status;
|
||||
};
|
||||
|
||||
|
||||
/** @brief Info about the target SDIO Host Controller. */
|
||||
struct IOPSDIOTargetSDHC
|
||||
{
|
||||
/** @brief The Base physical address of the SDIO block's register file. */
|
||||
UInt32 basePhysicalAddr;
|
||||
|
||||
/** @brief Wake event. */
|
||||
UInt32 dmaCompleteEventAddr;
|
||||
};
|
||||
|
||||
|
||||
// SDIO INIT
|
||||
|
||||
|
||||
/** @brief Bus Parameter Command. */
|
||||
struct IOPSDIOInitCmd
|
||||
{
|
||||
/** @brief The capabilities of the SDHC. */
|
||||
UInt64 sdhcCapabilities;
|
||||
|
||||
/** @brief The Maximum current capabilities of the SDHC. */
|
||||
UInt64 sdhcMaxCurrentCapabilities;
|
||||
};
|
||||
|
||||
|
||||
// SDIO FREE
|
||||
|
||||
|
||||
/** @brief Bus Parameter Command. */
|
||||
struct IOPSDIOFreeCmd
|
||||
{
|
||||
// Nothing at the moment
|
||||
};
|
||||
|
||||
|
||||
// SDIO RESET
|
||||
|
||||
/** @brief SDHC Reset Command. */
|
||||
struct IOPSDIOResetCmd
|
||||
{
|
||||
/** @brief Reset flags. */
|
||||
UInt32 resetFlags;
|
||||
};
|
||||
|
||||
|
||||
// BUS PARAMETERS
|
||||
|
||||
/** @brief Bus Parameter Command. */
|
||||
struct IOPSDIOSetBusParamCmd
|
||||
{
|
||||
/** @brief Base clock rate input to the SD Block.
|
||||
* If 0, the value from the SDHC capabilities register is used instead.
|
||||
*/
|
||||
UInt32 baseClockRateHz;
|
||||
|
||||
/** @brief New SDIO clock rate in Hz. No change if 0.
|
||||
* On return, this is set the value that was actually programmed into the
|
||||
* SDHC block.
|
||||
*/
|
||||
UInt32 clockRateHz;
|
||||
|
||||
/** @brief New SDIO bus width (1 or 4). No change if 0. */
|
||||
UInt8 busWidth;
|
||||
|
||||
/** @brief 1 if the SDIO clock should be on, -1 if off, 0 to leave unchanged */
|
||||
int clockMode;
|
||||
|
||||
/** @brief 2 for high speed mode, 1 for normal speed, 0 to leave unchanged. */
|
||||
int busSpeedMode;
|
||||
};
|
||||
|
||||
|
||||
// SDIO COMMAND
|
||||
|
||||
/** @brief Send an SDIO Command using the command line.
|
||||
* Note that the status of the command will be reflected by the iopsdio.status field.
|
||||
*/
|
||||
struct IOPSDIOCommandCmd
|
||||
{
|
||||
/** @brief The SDIO Command. */
|
||||
struct SDIOCommand command;
|
||||
|
||||
/** @brief The command response. */
|
||||
struct SDIOCommandResponse response;
|
||||
};
|
||||
|
||||
|
||||
// SDIO DATA COMMAND
|
||||
|
||||
/** @brief Send an SDIO Command with data (including the command line)
|
||||
* Note that the status of the command will be reflected by the iopsdio.status field.
|
||||
*/
|
||||
struct IOPSDIOTransferCmd
|
||||
{
|
||||
/** @brief The SDIO Command. */
|
||||
struct SDIOCommand command;
|
||||
|
||||
/** @brief The command response. */
|
||||
struct SDIOCommandResponse response;
|
||||
|
||||
/** @brief The SDIO transfer parameters. */
|
||||
struct SDIOTransfer transfer;
|
||||
|
||||
/** @brief Information about the memory segments involved in the transfer. */
|
||||
struct SDIOMemorySegments memory;
|
||||
|
||||
/** @brief Physical segments for DMA engine. Variable Size. */
|
||||
struct IOPSDIO_dma_segment segment[];
|
||||
};
|
||||
|
||||
|
||||
|
||||
// IOP MESSAGES
|
||||
|
||||
/** @brief IOP SDIO Message. */
|
||||
union IOPSDIOMessage
|
||||
{
|
||||
struct {
|
||||
/** @brief IOP Header. */
|
||||
struct IOPSDIOHeader header;
|
||||
|
||||
/** @brief Target SDIO block. */
|
||||
struct IOPSDIOTargetSDHC targetSDHC;
|
||||
|
||||
/** @brief Command Data. */
|
||||
union {
|
||||
struct IOPSDIOInitCmd initCmd;
|
||||
struct IOPSDIOFreeCmd freeCmd;
|
||||
struct IOPSDIOResetCmd resetCmd;
|
||||
struct IOPSDIOSetBusParamCmd setBusParamCmd;
|
||||
struct IOPSDIOCommandCmd commandCmd;
|
||||
struct IOPSDIOTransferCmd transferCmd;
|
||||
};
|
||||
};
|
||||
|
||||
UInt8 _pad[kIOPSDIO_MESSAGE_SIZE] SDIO_RESERVED;
|
||||
};
|
||||
|
||||
|
||||
union _IOPSDIO_sgl_sizing_tool
|
||||
{
|
||||
struct {
|
||||
/** @brief IOP Header. */
|
||||
struct IOPSDIOHeader header;
|
||||
|
||||
/** @brief Target SDIO block. */
|
||||
struct IOPSDIOTargetSDHC targetSDHC;
|
||||
|
||||
/** @brief Command Data. */
|
||||
union {
|
||||
struct IOPSDIOTransferCmd transferCmd;
|
||||
/* XXX add other sgl-using commands */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
#define kIOPSDIO_MAX_SEGMENTS ((kIOPSDIO_MESSAGE_SIZE - sizeof(union _IOPSDIO_sgl_sizing_tool)) / sizeof(IOPSDIO_dma_segment))
|
||||
|
||||
|
||||
#endif // _IOP_SDIO_PROTOCOL_H_
|
||||
@@ -0,0 +1,667 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include "iop_sdio_wrapper.h"
|
||||
|
||||
#include <sys/task.h>
|
||||
#include <AssertMacros.h>
|
||||
|
||||
#include <sdiodrv_config.h>
|
||||
#include <sdiodrv_command.h>
|
||||
#include <sdiodrv_transfer.h>
|
||||
#include <platform.h>
|
||||
#include <platform/memmap.h>
|
||||
|
||||
#include "iop_sdio_protocol.h"
|
||||
#include <sdiocommon/sdio_cmdfields.h>
|
||||
|
||||
#include "debug.h"
|
||||
#define cache_op_size(buf_size) (((buf_size) + (CPU_CACHELINE_SIZE-1)) & ~(CPU_CACHELINE_SIZE-1))
|
||||
|
||||
#define MAGIC_WRITE 0x44555544
|
||||
#define MAGIC_READ 0x55555555
|
||||
|
||||
#define MAX_SDIO_READ_LEN (32*1024) //agreement with AppleBCMWLAN driver that there wont be any read bigger than that
|
||||
|
||||
#define BCOM_SDIO_CHANNEL_OFFSET 5
|
||||
#define BCOM_SDIO_NEXTLEN_OFFSET 6
|
||||
#define BCOM_SDIO_DATAOFFSET_OFFSET 7
|
||||
|
||||
#define BCOM_SDIO_GLOM_CHANNEL 3
|
||||
#define BCOM_SDIO_GLOM_FRAME_DESCRIPTOR 0x80
|
||||
|
||||
#define MAGIC_READ_PACKET_LEN_OFFSET 1
|
||||
#define MAGIC_READ_ENABLE_OFFSET 2
|
||||
#define MAGIC_READ_BUFFER_LENGTH_OFFSET 3
|
||||
|
||||
|
||||
#define LOOKAHEAD_READ_PKT_SIZE (lookahead_read_pkt_size)
|
||||
|
||||
struct cacheCmd {
|
||||
struct IOPSDIOTransferCmd transferCmd;
|
||||
struct IOPSDIO_dma_segment segment;
|
||||
};
|
||||
|
||||
struct cacheCmd cmd;
|
||||
SDIOReturn_t cachedError = kSDIOReturnSuccess;
|
||||
unsigned int do_lookahead = 0;
|
||||
unsigned int lookahead_read_pkt_size = 12 * 1024; //default buffer, max 12K per packet
|
||||
|
||||
|
||||
IOPSDIO_status_t
|
||||
iopsdio_init(struct IOPSDIOTargetSDHC *targetSDHC, struct IOPSDIOInitCmd *initCmd)
|
||||
{
|
||||
check(targetSDHC);
|
||||
check(initCmd);
|
||||
|
||||
SDHCRegisters_t *sdhc = (SDHCRegisters_t*)targetSDHC->basePhysicalAddr;
|
||||
if(!sdhc) {
|
||||
return kSDIOReturnNoHostController;
|
||||
}
|
||||
|
||||
// Create DMA completion event.
|
||||
struct task_event* dmaCompleteEvent = malloc(sizeof(struct task_event));
|
||||
if(!dmaCompleteEvent) {
|
||||
return kSDIOReturnNoMemory;
|
||||
}
|
||||
|
||||
event_init(dmaCompleteEvent, EVENT_FLAG_AUTO_UNSIGNAL, false);
|
||||
|
||||
targetSDHC->dmaCompleteEventAddr = (UInt32)dmaCompleteEvent;
|
||||
|
||||
#if 0
|
||||
/* 7256044 */
|
||||
initCmd->sdhcCapabilities = sdhc->capabilities;
|
||||
initCmd->sdhcMaxCurrentCapabilities = sdhc->maxCurrentCapabilities;
|
||||
#else
|
||||
initCmd->sdhcCapabilities = 0;
|
||||
initCmd->sdhcMaxCurrentCapabilities = 0;
|
||||
#endif
|
||||
|
||||
return kSDIOReturnSuccess;
|
||||
}
|
||||
|
||||
IOPSDIO_status_t
|
||||
iopsdio_free(struct IOPSDIOTargetSDHC *targetSDHC, struct IOPSDIOFreeCmd *freeCmd)
|
||||
{
|
||||
check(targetSDHC);
|
||||
check(freeCmd);
|
||||
|
||||
SDHCRegisters_t *sdhc = (SDHCRegisters_t*)targetSDHC->basePhysicalAddr;
|
||||
if(!sdhc) {
|
||||
return kSDIOReturnNoHostController;
|
||||
}
|
||||
|
||||
// Destroy the DMA completion event
|
||||
free((void*)targetSDHC->dmaCompleteEventAddr);
|
||||
targetSDHC->dmaCompleteEventAddr = 0;
|
||||
|
||||
return kSDIOReturnSuccess;
|
||||
}
|
||||
|
||||
IOPSDIO_status_t
|
||||
iopsdio_reset(struct IOPSDIOTargetSDHC *targetSDHC, struct IOPSDIOResetCmd *resetCmd)
|
||||
{
|
||||
check(targetSDHC);
|
||||
check(resetCmd);
|
||||
|
||||
SDHCRegisters_t *sdhc = (SDHCRegisters_t*)targetSDHC->basePhysicalAddr;
|
||||
if(!sdhc) {
|
||||
return kSDIOReturnNoHostController;
|
||||
}
|
||||
|
||||
SDIOReturn_t retval = sdiodrv_resetSDHC(sdhc, resetCmd->resetFlags);
|
||||
if(kSDIOReturnSuccess != retval) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
// restore interrupt state on reset
|
||||
if(resetCmd->resetFlags & kSDHCResetAll) {
|
||||
sdhc_enableCommandStatus(sdhc, true);
|
||||
sdhc_enableTransferStatus(sdhc, true);
|
||||
}
|
||||
|
||||
cachedError = retval;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
IOPSDIO_status_t
|
||||
iopsdio_setBusConfig(struct IOPSDIOTargetSDHC *targetSDHC, struct IOPSDIOSetBusParamCmd *busParamCmd)
|
||||
{
|
||||
check(targetSDHC);
|
||||
check(busParamCmd);
|
||||
|
||||
if (cachedError != kSDIOReturnSuccess)
|
||||
return cachedError;
|
||||
|
||||
SDHCRegisters_t *sdhc = (SDHCRegisters_t*)targetSDHC->basePhysicalAddr;
|
||||
if(!sdhc) {
|
||||
return kSDIOReturnNoHostController;
|
||||
}
|
||||
|
||||
SDIOReturn_t retval = kSDIOReturnSuccess;
|
||||
|
||||
if(busParamCmd->clockRateHz) {
|
||||
|
||||
retval = sdiodrv_setClockRate(sdhc, &busParamCmd->clockRateHz, busParamCmd->baseClockRateHz);
|
||||
if(kSDIOReturnSuccess != retval) {
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
if(busParamCmd->busWidth) {
|
||||
|
||||
retval = sdiodrv_setBusWidth(sdhc, busParamCmd->busWidth);
|
||||
if(kSDIOReturnSuccess != retval) {
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
if(busParamCmd->busSpeedMode) {
|
||||
|
||||
retval = sdiodrv_setBusSpeedMode(sdhc, busParamCmd->busSpeedMode);
|
||||
if(kSDIOReturnSuccess != retval) {
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
if(busParamCmd->clockMode) {
|
||||
|
||||
retval = sdiodrv_setClockMode(sdhc, busParamCmd->clockMode);
|
||||
if(kSDIOReturnSuccess != retval) {
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
unsigned int nm = 0;
|
||||
IOPSDIO_status_t
|
||||
iopsdio_sendSDIOCmd(struct IOPSDIOTargetSDHC *targetSDHC, struct IOPSDIOCommandCmd *commandCmd)
|
||||
{
|
||||
check(targetSDHC);
|
||||
check(commandCmd);
|
||||
|
||||
if (cachedError != kSDIOReturnSuccess)
|
||||
return cachedError;
|
||||
|
||||
SDHCRegisters_t *sdhc = (SDHCRegisters_t*)targetSDHC->basePhysicalAddr;
|
||||
if(!sdhc) {
|
||||
return kSDIOReturnNoHostController;
|
||||
}
|
||||
|
||||
SDIOReturn_t retval = sdiodrv_sendSDIOCommand(sdhc, &commandCmd->command, &commandCmd->response);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* read a complete SDIO packet:
|
||||
* reads are always block aligned
|
||||
*
|
||||
* blocks: number of blocks to read, if zero, then issue a one block read in order to get the frame header and
|
||||
* obtain the packet length from this header, issue a second read in order to to get the remaining blocks
|
||||
* max_blocks: max_blocks allowed
|
||||
* data: virtual address if read buffer
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
IOPSDIO_status_t iopsdio_read_packet(unsigned int blocks, unsigned int max_blocks, unsigned int * data, struct IOPSDIOTargetSDHC *targetSDHC, struct IOPSDIOTransferCmd *transferCmd)
|
||||
{
|
||||
IOPSDIO_status_t retval = 0;
|
||||
SDHCRegisters_t *sdhc = (SDHCRegisters_t*)targetSDHC->basePhysicalAddr;
|
||||
struct task_event *dmaCompleteEvent = (struct task_event *)targetSDHC->dmaCompleteEventAddr;
|
||||
|
||||
if (blocks == 0) {
|
||||
|
||||
transferCmd->transfer.blockCount = 1;
|
||||
transferCmd->memory.dataLength = transferCmd->transfer.blockSize;
|
||||
transferCmd->segment[0].length = transferCmd->transfer.blockSize;
|
||||
transferCmd->transfer.command.argument = (transferCmd->transfer.command.argument& 0xfffffe00) | 1;
|
||||
|
||||
data = mem_static_map_cached((uint32_t)data);
|
||||
|
||||
platform_cache_operation(CACHE_INVALIDATE,
|
||||
(void *)data,
|
||||
(32));
|
||||
|
||||
if (transferCmd->memory.dataLength > MAX_SDIO_READ_LEN) {
|
||||
//paranoia
|
||||
dprintf(DEBUG_CRITICAL, "iopsdio_read_packet1: len frame is too large %llu \n", transferCmd->memory.dataLength);
|
||||
retval = kSDIOReturnBadArgument;
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = sdiodrv_transferData(sdhc, &transferCmd->transfer, &transferCmd->memory, &transferCmd->response, dmaCompleteEvent);
|
||||
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
|
||||
|
||||
data = mem_static_map_cached((uint32_t)data);
|
||||
|
||||
platform_cache_operation(CACHE_INVALIDATE,
|
||||
(void *)data,
|
||||
(32));
|
||||
|
||||
unsigned short check = data[0]>>16;
|
||||
unsigned short fflen = data[0];
|
||||
|
||||
if (fflen) {
|
||||
|
||||
|
||||
|
||||
if ((fflen + check) != 0xffff) {
|
||||
|
||||
dprintf(DEBUG_CRITICAL, "iopsdio_read_packet error %x %d - %x blocks %u %x\n", fflen, fflen, check, blocks, data[1]);
|
||||
dprintf(DEBUG_CRITICAL, " ===== %p %x %x %x\n", data, transferCmd->segment[0].paddr, data[0],*(unsigned int*)transferCmd->segment[0].paddr);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
unsigned short mask = transferCmd->transfer.blockSize-1;
|
||||
unsigned short flen = (fflen+mask) & ~mask; //round up
|
||||
|
||||
unsigned int remain_blocks = flen ;
|
||||
if (128 == transferCmd->transfer.blockSize) {
|
||||
remain_blocks = remain_blocks/128;
|
||||
} else {
|
||||
remain_blocks = remain_blocks/transferCmd->transfer.blockSize;
|
||||
}
|
||||
|
||||
if (remain_blocks == 0) {
|
||||
dprintf(DEBUG_CRITICAL, "iopsdio_read_packet: error zero blocks \n");
|
||||
|
||||
return kSDIOReturnBadArgument;
|
||||
|
||||
}
|
||||
remain_blocks--;
|
||||
|
||||
if (remain_blocks >= max_blocks) {
|
||||
dprintf(DEBUG_CRITICAL, "iopsdio_read_packet: not enough blocks %u orig %u flen %x check %x\n", remain_blocks, max_blocks, fflen, check);
|
||||
|
||||
return kSDIOReturnBadArgument;
|
||||
}
|
||||
if (remain_blocks) {
|
||||
|
||||
//read remaining blocks
|
||||
transferCmd->transfer.blockCount = remain_blocks;
|
||||
transferCmd->memory.dataLength = transferCmd->transfer.blockSize * remain_blocks;
|
||||
transferCmd->segment[0].length = transferCmd->transfer.blockSize * remain_blocks;
|
||||
transferCmd->segment[0].paddr += transferCmd->transfer.blockSize;
|
||||
|
||||
transferCmd->transfer.command.argument = (transferCmd->transfer.command.argument& 0xfffffe00) | remain_blocks;
|
||||
|
||||
if (transferCmd->memory.dataLength > MAX_SDIO_READ_LEN) {
|
||||
//paranoia,
|
||||
dprintf(DEBUG_CRITICAL, "iopsdio_read_packet2: len frame is too large %llu remain %u size %hu\n", transferCmd->memory.dataLength, remain_blocks, transferCmd->transfer.blockSize);
|
||||
retval = kSDIOReturnBadArgument;
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = sdiodrv_transferData(sdhc, &transferCmd->transfer, &transferCmd->memory, &transferCmd->response, dmaCompleteEvent);
|
||||
transferCmd->segment[0].paddr -= transferCmd->transfer.blockSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
transferCmd->transfer.blockCount = blocks;
|
||||
transferCmd->memory.dataLength = transferCmd->transfer.blockSize * blocks;
|
||||
transferCmd->segment[0].length = transferCmd->transfer.blockSize * blocks;
|
||||
|
||||
transferCmd->transfer.command.argument = (transferCmd->transfer.command.argument& 0xfffffe00) | blocks;
|
||||
platform_cache_operation(CACHE_INVALIDATE,
|
||||
(void *)data,
|
||||
(32));
|
||||
retval = sdiodrv_transferData(sdhc, &transferCmd->transfer, &transferCmd->memory, &transferCmd->response, dmaCompleteEvent);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return retval;
|
||||
|
||||
}
|
||||
|
||||
void iopsdio_cacheTransferSDIOData(struct IOPSDIOTargetSDHC *targetSDHC)
|
||||
{
|
||||
|
||||
SDIOReturn_t retval = 0;
|
||||
cachedError = kSDIOReturnSuccess;
|
||||
|
||||
//perform access based on the cached command
|
||||
struct IOPSDIOTransferCmd *transferCmd = &cmd.transferCmd;
|
||||
|
||||
unsigned int * data = (unsigned int*)transferCmd->segment[0].paddr;
|
||||
data = mem_static_map_cached((uint32_t)data);
|
||||
|
||||
unsigned int max_blocks;
|
||||
if (128 == transferCmd->transfer.blockSize)
|
||||
max_blocks = LOOKAHEAD_READ_PKT_SIZE/128;
|
||||
else
|
||||
max_blocks = LOOKAHEAD_READ_PKT_SIZE/transferCmd->transfer.blockSize;
|
||||
|
||||
//kick SDIO transfer
|
||||
retval = iopsdio_read_packet(transferCmd->transfer.blockCount, max_blocks, data, targetSDHC, transferCmd);
|
||||
|
||||
if (retval) {
|
||||
if ((retval < kSDIOReturnDataError) || (retval > kSDIOReturnDataTimeout)) {
|
||||
//paranoia, make sure we return a Data error here, which means that the host will trigger a Reset
|
||||
cachedError = kSDIOReturnDataError;
|
||||
} else {
|
||||
|
||||
cachedError = retval;
|
||||
}
|
||||
} else {
|
||||
|
||||
cachedError = kSDIOReturnSuccess;
|
||||
}
|
||||
|
||||
unsigned int *retp = (unsigned int*)(((unsigned char*)data)+LOOKAHEAD_READ_PKT_SIZE);
|
||||
|
||||
//dprintf(0, "iopsdio_cacheTransferSDIOData done %x %x\n", *retp, retval);
|
||||
|
||||
//make sure we tell the host processor that we're done
|
||||
* retp = retval;
|
||||
platform_cache_operation(CACHE_CLEAN,
|
||||
(void *)retp,
|
||||
(32));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
IOPSDIO_status_t
|
||||
iopsdio_transferSDIOData(struct IOPSDIOTargetSDHC *targetSDHC, struct IOPSDIOTransferCmd *transferCmd)
|
||||
{
|
||||
check(targetSDHC);
|
||||
check(transferCmd);
|
||||
unsigned int orig_bcount = 0;
|
||||
unsigned int nlen = 0;
|
||||
|
||||
if (cachedError != kSDIOReturnSuccess)
|
||||
return cachedError;
|
||||
|
||||
|
||||
SDHCRegisters_t *sdhc = (SDHCRegisters_t*)targetSDHC->basePhysicalAddr;
|
||||
if(!sdhc) {
|
||||
return kSDIOReturnNoHostController;
|
||||
}
|
||||
|
||||
struct task_event *dmaCompleteEvent = (struct task_event *)targetSDHC->dmaCompleteEventAddr;
|
||||
|
||||
transferCmd->memory.segmentList = transferCmd->segment;
|
||||
|
||||
unsigned int orig_data = transferCmd->segment[0].paddr;
|
||||
|
||||
|
||||
unsigned int * data = mem_static_map_cached((uint32_t)orig_data);
|
||||
platform_cache_operation(CACHE_INVALIDATE,
|
||||
(void *)data,
|
||||
(32));
|
||||
SDIOReturn_t retval = 0;
|
||||
if (( transferCmd->transfer.direction == kSDIODirectionWrite) && (*data == MAGIC_WRITE) && ((transferCmd->transfer.command.argument & kSDIOCmd53BlockMode) == kSDIOCmd53BlockMode)) {
|
||||
unsigned int base_addr = transferCmd->segment[0].paddr + transferCmd->transfer.blockSize;
|
||||
unsigned int * l = data + 1;
|
||||
unsigned int cnt = 0;
|
||||
unsigned int bcount = *l ;
|
||||
// dprintf(0, "iopsdio_transferSDIOData magic wwwrite got %x %x [%x %x] %u %u %u\n",l[0],l[1], transferCmd->transfer.command.argument,transferCmd->transfer.command.index, transferCmd->transfer.blockCount,transferCmd->transfer.blockSize, transferCmd->memory.segmentCount);
|
||||
|
||||
//first sdio block = MAGIC_WRITE/block size of pkt1/block size of pkt 2/block size of pkt3 etc...
|
||||
//second sdio blocks and so on... = packets data
|
||||
|
||||
if (transferCmd->transfer.blockCount == 1) {
|
||||
|
||||
dprintf(DEBUG_CRITICAL, "iopsdio_transferSDIOData magic write error!! %p %x %x %x\n",data, l[0],l[1],l[2]);
|
||||
|
||||
return kSDIOReturnBadArgument;
|
||||
}
|
||||
|
||||
while (bcount!=0) {
|
||||
unsigned int transfer_len = bcount * transferCmd->transfer.blockSize;
|
||||
|
||||
transferCmd->memory.dataLength = transfer_len;
|
||||
|
||||
transferCmd->transfer.command.argument = (transferCmd->transfer.command.argument& 0xfffffe00) | bcount;
|
||||
|
||||
transferCmd->transfer.blockCount = bcount;
|
||||
|
||||
transferCmd->segment[0].length = transfer_len;
|
||||
transferCmd->segment[0].paddr = base_addr;
|
||||
unsigned int *p = (unsigned int*)transferCmd->segment[0].paddr;
|
||||
|
||||
|
||||
p = mem_static_map_cached((uint32_t)p);
|
||||
|
||||
platform_cache_operation(CACHE_INVALIDATE,
|
||||
(void *)p,
|
||||
(32));
|
||||
|
||||
unsigned short check = p[0]>>16;
|
||||
unsigned short fflen = p[0];
|
||||
if ((check + fflen) != 0xffff) {
|
||||
//internal error, the sender tries to send a corrupted packet
|
||||
dprintf(DEBUG_CRITICAL, "iopsdio_transferSDIOData detected error ---> %p : %x %x %x %x \n", p, p[0], p[1], p[2], p[3]);
|
||||
retval = kSDIOReturnBadArgument;
|
||||
} else {
|
||||
|
||||
retval = sdiodrv_transferData(sdhc, &transferCmd->transfer, &transferCmd->memory, &transferCmd->response, dmaCompleteEvent);
|
||||
}
|
||||
if (retval) {
|
||||
|
||||
*data = cnt; //tell the sender how many packets we did send successfully
|
||||
|
||||
platform_cache_operation(CACHE_CLEAN,
|
||||
(void *)data,
|
||||
(32));
|
||||
|
||||
unsigned int *p = (unsigned int *)base_addr;
|
||||
|
||||
dprintf(DEBUG_CRITICAL, "iopsdio_transferSDIOData ---> %x %x %x %x \n", p[0], p[1], p[2], p[3]);
|
||||
dprintf(DEBUG_CRITICAL, " --> cnt %u bc %u addr %p arg %x retval %x\n", cnt, transferCmd->transfer.blockCount, (void *)transferCmd->segment[0].paddr, transferCmd->transfer.command.argument, retval);
|
||||
return retval;
|
||||
}
|
||||
base_addr += transfer_len;//transferCmd->transfer.blockSize * bcount;
|
||||
cnt++;
|
||||
l++;
|
||||
bcount = *l ;
|
||||
|
||||
}
|
||||
|
||||
} else if ((transferCmd->transfer.direction == kSDIODirectionRead) && (*data == MAGIC_READ) && ((transferCmd->transfer.command.argument & kSDIOCmd53BlockMode) == kSDIOCmd53BlockMode)) {
|
||||
|
||||
|
||||
//MAGIC READ:
|
||||
//buffer1 of size LOOKAHEAD_READ_PKT_SIZE + buffer2 of size LOOKAHEAD_READ_PKT_SIZE + one
|
||||
//additional block used as end of transfer marker
|
||||
|
||||
orig_bcount = transferCmd->transfer.blockCount;
|
||||
// dprintf(0, "iopsdio_transferSDIOData read got %u %u %u \n",l[0],l[1],l[2]);
|
||||
unsigned int blocks = *(data+MAGIC_READ_PACKET_LEN_OFFSET);
|
||||
unsigned int lk = *(data+MAGIC_READ_ENABLE_OFFSET);
|
||||
if (*(data+MAGIC_READ_BUFFER_LENGTH_OFFSET)) {
|
||||
lookahead_read_pkt_size = *(data+MAGIC_READ_BUFFER_LENGTH_OFFSET);
|
||||
}
|
||||
retval = iopsdio_read_packet(blocks, orig_bcount, data, targetSDHC, transferCmd);
|
||||
|
||||
if (lk == 0) {
|
||||
//Host processor doesn't want the look ahead
|
||||
return retval;
|
||||
}
|
||||
if (retval) {
|
||||
goto return_clear;
|
||||
}
|
||||
|
||||
|
||||
unsigned char nextlen = *((unsigned char*)data + BCOM_SDIO_NEXTLEN_OFFSET);
|
||||
unsigned char channel = *((unsigned char*)data + BCOM_SDIO_CHANNEL_OFFSET);
|
||||
unsigned char offset = *((unsigned char*)data + BCOM_SDIO_DATAOFFSET_OFFSET);
|
||||
// dprintf(0, "iopsdio_transferSDIOData read got %x %x %x - %u channel %u offset %u\n",data[0],data[1],data[2], nextlen,channel, offset);
|
||||
|
||||
|
||||
unsigned short check = data[0]>>16;
|
||||
unsigned short fflen = data[0];
|
||||
|
||||
if (fflen) {
|
||||
|
||||
|
||||
|
||||
if ((fflen + check) != 0xffff) {
|
||||
|
||||
dprintf(DEBUG_CRITICAL, "iopsdio_transferSDIOData cksum error %x %d - %x \n", fflen, fflen, check);
|
||||
retval = kSDIOReturnDataError;
|
||||
goto return_clear;
|
||||
}
|
||||
} else {
|
||||
if (check==0) {
|
||||
//fflen and check are null, hence no more data pending
|
||||
goto return_clear;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nlen = 16 * nextlen;
|
||||
|
||||
|
||||
if (nlen == 0 && channel == (BCOM_SDIO_GLOM_FRAME_DESCRIPTOR|BCOM_SDIO_GLOM_CHANNEL)) {
|
||||
//reading a Glom descriptor: calculate the length of next frame
|
||||
//max number of GLom frames is tunable and typically 7, a glom frame descriptor should not be larger than 64 Bytes
|
||||
#define SANE_MAX_GLOM_FRAME_LEN 64
|
||||
if (fflen > SANE_MAX_GLOM_FRAME_LEN) {
|
||||
dprintf(DEBUG_CRITICAL, "iopsdio_transferSDIOData glom descriptor is too large %hu \n", fflen);
|
||||
goto return_clear;
|
||||
}
|
||||
|
||||
if (fflen > 32) {
|
||||
//uncache the rest of the frame
|
||||
platform_cache_operation(CACHE_INVALIDATE,
|
||||
(void *)data,
|
||||
cache_op_size(fflen));
|
||||
}
|
||||
|
||||
unsigned short * p = (unsigned short *)((unsigned char*)data + offset);
|
||||
unsigned short * end = (unsigned short *)((unsigned char*)data + fflen);
|
||||
|
||||
//calculate nlen
|
||||
while (p < end){
|
||||
nlen += *p++;
|
||||
}
|
||||
|
||||
|
||||
if (nlen > LOOKAHEAD_READ_PKT_SIZE) {
|
||||
dprintf(DEBUG_CRITICAL, "iopsdio_transferSDIOData calculated glom frame is too large %u \n", nlen);
|
||||
retval = kSDIOReturnDataError;
|
||||
goto return_clear;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//save parameters for the next transfer
|
||||
nlen += transferCmd->transfer.blockSize-1;
|
||||
nlen = nlen & ~(transferCmd->transfer.blockSize-1);
|
||||
|
||||
if (nlen > MAX_SDIO_READ_LEN) {
|
||||
//paranoia
|
||||
dprintf(DEBUG_CRITICAL, "iopsdio_transferSDIOData magic read calculating a bad len frame large %u \n", nlen);
|
||||
retval = kSDIOReturnBadArgument;
|
||||
goto return_clear;
|
||||
}
|
||||
|
||||
cmd.transferCmd.transfer.command.argument = transferCmd->transfer.command.argument;
|
||||
cmd.transferCmd.transfer.command.index = transferCmd->transfer.command.index;
|
||||
|
||||
|
||||
if (128 == transferCmd->transfer.blockSize)
|
||||
cmd.transferCmd.transfer.blockCount = nlen/128;
|
||||
else
|
||||
cmd.transferCmd.transfer.blockCount = nlen/transferCmd->transfer.blockSize;
|
||||
|
||||
cmd.transferCmd.transfer.blockSize = transferCmd->transfer.blockSize;
|
||||
cmd.transferCmd.transfer.direction = transferCmd->transfer.direction;
|
||||
|
||||
cmd.segment.length = nlen;
|
||||
cmd.segment.paddr = orig_data+LOOKAHEAD_READ_PKT_SIZE;
|
||||
|
||||
cmd.transferCmd.memory.segmentList = &cmd.segment;
|
||||
cmd.transferCmd.memory.dataLength = nlen;
|
||||
cmd.transferCmd.memory.segmentCount = 1;
|
||||
|
||||
if (lk > 1) {
|
||||
//experimental mode, read all at once while the host processor wait - used only for debug 14July2011
|
||||
iopsdio_cacheTransferSDIOData(targetSDHC);
|
||||
} else {
|
||||
//set lookahead to tell the sdio task handler in iop_sdio.c to generate the cached loakahead read
|
||||
do_lookahead = lk;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (transferCmd->transfer.direction == kSDIODirectionRead) {
|
||||
//if transfer is cmd53 block read, check that the requested length matches the number of blocks requested
|
||||
//and check that the total length is not overly large
|
||||
nlen = transferCmd->transfer.blockCount * transferCmd->transfer.blockSize;
|
||||
|
||||
if (nlen != transferCmd->memory.dataLength) {
|
||||
dprintf(DEBUG_CRITICAL, "iopsdio_transferSDIOData len mismatch %u %llu direction %hhu\n", nlen, transferCmd->memory.dataLength, transferCmd->transfer.direction);
|
||||
return kSDIOReturnBadArgument;
|
||||
}
|
||||
|
||||
if (nlen > MAX_SDIO_READ_LEN) {
|
||||
dprintf(DEBUG_CRITICAL, "iopsdio_transferSDIOData data transfer is too large %u %llu direction %hhu\n", nlen, transferCmd->memory.dataLength, transferCmd->transfer.direction);
|
||||
return kSDIOReturnBadArgument;
|
||||
}
|
||||
}
|
||||
|
||||
retval = sdiodrv_transferData(sdhc, &transferCmd->transfer, &transferCmd->memory, &transferCmd->response, dmaCompleteEvent);
|
||||
if (retval) {
|
||||
dprintf(DEBUG_CRITICAL, "iopsdio_transferSDIOData error %x\n",retval);
|
||||
}
|
||||
|
||||
}
|
||||
return retval;
|
||||
|
||||
return_clear:
|
||||
{
|
||||
|
||||
unsigned int last_block;
|
||||
if (128 == transferCmd->transfer.blockSize)
|
||||
last_block = (LOOKAHEAD_READ_PKT_SIZE*2)/128;
|
||||
else
|
||||
last_block = (LOOKAHEAD_READ_PKT_SIZE*2)/transferCmd->transfer.blockSize;
|
||||
|
||||
//paranoia: check if we have enough space in the buffer, then mark it as done
|
||||
if (orig_bcount >= last_block) {
|
||||
unsigned int *retp = (unsigned int*)(((unsigned char*)data)+LOOKAHEAD_READ_PKT_SIZE*2);
|
||||
|
||||
* retp = retval;
|
||||
platform_cache_operation(CACHE_CLEAN,
|
||||
(void *)retp,
|
||||
(32));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef _IOP_SDIO_WRAPPER_H
|
||||
#define _IOP_SDIO_WRAPPER_H
|
||||
|
||||
|
||||
#include "iop_sdio_protocol.h"
|
||||
|
||||
|
||||
IOPSDIO_status_t iopsdio_init(struct IOPSDIOTargetSDHC *targetSDHC, struct IOPSDIOInitCmd *initCmd);
|
||||
|
||||
IOPSDIO_status_t iopsdio_free(struct IOPSDIOTargetSDHC *targetSDHC, struct IOPSDIOFreeCmd *freeCmd);
|
||||
|
||||
IOPSDIO_status_t iopsdio_reset(struct IOPSDIOTargetSDHC *targetSDHC, struct IOPSDIOResetCmd *resetCmd);
|
||||
|
||||
IOPSDIO_status_t iopsdio_setBusConfig(struct IOPSDIOTargetSDHC *targetSDHC, struct IOPSDIOSetBusParamCmd *busParamCmd);
|
||||
|
||||
IOPSDIO_status_t iopsdio_sendSDIOCmd(struct IOPSDIOTargetSDHC *targetSDHC, struct IOPSDIOCommandCmd *commandCmd);
|
||||
|
||||
IOPSDIO_status_t iopsdio_transferSDIOData(struct IOPSDIOTargetSDHC *targetSDHC, struct IOPSDIOTransferCmd *transferCmd);
|
||||
|
||||
|
||||
|
||||
#endif // _IOP_SDIO_WRAPPER_H
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# Copyright (C) 2008 Apple Computer, Inc. All rights reserved.
|
||||
#
|
||||
# This document is the property of Apple Computer, Inc.
|
||||
# It is considered confidential and proprietary.
|
||||
#
|
||||
# This document may not be reproduced or transmitted in any form,
|
||||
# in whole or in part, without the express written permission of
|
||||
# Apple Computer, Inc.
|
||||
#
|
||||
|
||||
#
|
||||
# SDIO driver
|
||||
#
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
OPTIONS += WITH_FUNCTION_SDIO=1
|
||||
IOP_FUNCTIONS += SDIO
|
||||
|
||||
ALL_OBJS += $(LOCAL_DIR)/iop_sdio.o $(LOCAL_DIR)/iop_sdio_wrapper.o
|
||||
|
||||
INSTALL_HEADERS += $(LOCAL_DIR)/iop_sdio_protocol.h
|
||||
|
||||
# XXX tune this to suit SDIO requirements
|
||||
IOP_HEAP_REQUIRED := $(call ADD,$(IOP_HEAP_REQUIRED),8192)
|
||||
|
||||
Reference in new issue
Block a user