diff options
author | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-03-14 15:52:42 +0000 |
---|---|---|
committer | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-03-14 15:52:42 +0000 |
commit | 26e3776a22bf894ced5af4c28968dc1dc99968eb (patch) | |
tree | 2d38a3789e27a423439c37a45a09cae31990a615 /target/linux/s3c24xx/patches-2.6.26/1055-atheros_2_0_sdio_stack.patch.patch | |
parent | 4bd70fc26256cf485f19e0c8b881e078dc36134f (diff) |
nuke obsolete kernel stuff
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@14875 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/s3c24xx/patches-2.6.26/1055-atheros_2_0_sdio_stack.patch.patch')
-rwxr-xr-x | target/linux/s3c24xx/patches-2.6.26/1055-atheros_2_0_sdio_stack.patch.patch | 13982 |
1 files changed, 0 insertions, 13982 deletions
diff --git a/target/linux/s3c24xx/patches-2.6.26/1055-atheros_2_0_sdio_stack.patch.patch b/target/linux/s3c24xx/patches-2.6.26/1055-atheros_2_0_sdio_stack.patch.patch deleted file mode 100755 index e29f050afe..0000000000 --- a/target/linux/s3c24xx/patches-2.6.26/1055-atheros_2_0_sdio_stack.patch.patch +++ /dev/null @@ -1,13982 +0,0 @@ -From 79b0634b39757c62f4e61256c12ddf8e7b3783c4 Mon Sep 17 00:00:00 2001 -From: mokopatches <mokopatches@openmoko.org> -Date: Fri, 25 Jul 2008 22:21:24 +0100 -Subject: [PATCH] atheros_2_0_sdio_stack.patch - ---- - arch/arm/Kconfig | 2 + - drivers/Kconfig | 2 + - drivers/Makefile | 1 + - drivers/sdio/Kconfig | 17 + - drivers/sdio/Makefile | 4 + - drivers/sdio/stack/Makefile | 1 + - drivers/sdio/stack/busdriver/Makefile | 2 + - drivers/sdio/stack/busdriver/_busdriver.h | 466 ++++ - drivers/sdio/stack/busdriver/sdio_bus.c | 2120 +++++++++++++++ - drivers/sdio/stack/busdriver/sdio_bus_events.c | 1040 +++++++ - drivers/sdio/stack/busdriver/sdio_bus_misc.c | 3122 ++++++++++++++++++++++ - drivers/sdio/stack/busdriver/sdio_bus_os.c | 832 ++++++ - drivers/sdio/stack/busdriver/sdio_function.c | 715 +++++ - drivers/sdio/stack/lib/Makefile | 2 + - drivers/sdio/stack/lib/_sdio_lib.h | 50 + - drivers/sdio/stack/lib/sdio_lib_c.c | 908 +++++++ - drivers/sdio/stack/lib/sdio_lib_os.c | 251 ++ - drivers/sdio/stack/platform/Makefile | 2 + - drivers/sdio/stack/platform/sdioplatformdriver.c | 300 +++ - include/linux/sdio/_sdio_defs.h | 638 +++++ - include/linux/sdio/ctsystem.h | 115 + - include/linux/sdio/ctsystem_linux.h | 983 +++++++ - include/linux/sdio/mmc_defs.h | 103 + - include/linux/sdio/sdio_busdriver.h | 1435 ++++++++++ - include/linux/sdio/sdio_hcd_defs.h | 219 ++ - include/linux/sdio/sdio_lib.h | 270 ++ - include/linux/sdio/sdlist.h | 141 + - 27 files changed, 13741 insertions(+), 0 deletions(-) - create mode 100644 drivers/sdio/Kconfig - create mode 100644 drivers/sdio/Makefile - create mode 100644 drivers/sdio/stack/Makefile - create mode 100644 drivers/sdio/stack/busdriver/Makefile - create mode 100644 drivers/sdio/stack/busdriver/_busdriver.h - create mode 100644 drivers/sdio/stack/busdriver/sdio_bus.c - create mode 100644 drivers/sdio/stack/busdriver/sdio_bus_events.c - create mode 100644 drivers/sdio/stack/busdriver/sdio_bus_misc.c - create mode 100644 drivers/sdio/stack/busdriver/sdio_bus_os.c - create mode 100644 drivers/sdio/stack/busdriver/sdio_function.c - create mode 100644 drivers/sdio/stack/lib/Makefile - create mode 100644 drivers/sdio/stack/lib/_sdio_lib.h - create mode 100644 drivers/sdio/stack/lib/sdio_lib_c.c - create mode 100644 drivers/sdio/stack/lib/sdio_lib_os.c - create mode 100644 drivers/sdio/stack/platform/Makefile - create mode 100644 drivers/sdio/stack/platform/sdioplatformdriver.c - create mode 100644 include/linux/sdio/_sdio_defs.h - create mode 100644 include/linux/sdio/ctsystem.h - create mode 100644 include/linux/sdio/ctsystem_linux.h - create mode 100644 include/linux/sdio/mmc_defs.h - create mode 100644 include/linux/sdio/sdio_busdriver.h - create mode 100644 include/linux/sdio/sdio_hcd_defs.h - create mode 100644 include/linux/sdio/sdio_lib.h - create mode 100644 include/linux/sdio/sdlist.h - -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index b786e68..e394067 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -1169,6 +1169,8 @@ source "drivers/hid/Kconfig" - - source "drivers/usb/Kconfig" - -+source "drivers/sdio/Kconfig" -+ - source "drivers/mmc/Kconfig" - - source "drivers/leds/Kconfig" -diff --git a/drivers/Kconfig b/drivers/Kconfig -index 59f33fa..f5900b7 100644 ---- a/drivers/Kconfig -+++ b/drivers/Kconfig -@@ -78,6 +78,8 @@ source "drivers/hid/Kconfig" - - source "drivers/usb/Kconfig" - -+source "drivers/sdio/Kconfig" -+ - source "drivers/mmc/Kconfig" - - source "drivers/memstick/Kconfig" -diff --git a/drivers/Makefile b/drivers/Makefile -index f65deda..ce63a01 100644 ---- a/drivers/Makefile -+++ b/drivers/Makefile -@@ -80,6 +80,7 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq/ - obj-$(CONFIG_CPU_IDLE) += cpuidle/ - obj-$(CONFIG_MMC) += mmc/ - obj-$(CONFIG_MEMSTICK) += memstick/ -+obj-$(CONFIG_SDIO) += sdio/ - obj-$(CONFIG_NEW_LEDS) += leds/ - obj-$(CONFIG_INFINIBAND) += infiniband/ - obj-$(CONFIG_SGI_SN) += sn/ -diff --git a/drivers/sdio/Kconfig b/drivers/sdio/Kconfig -new file mode 100644 -index 0000000..14bf5e3 ---- /dev/null -+++ b/drivers/sdio/Kconfig -@@ -0,0 +1,17 @@ -+# -+# SDIO driver and host controller support -+# -+ -+menu "SDIO support" -+ -+config SDIO -+ tristate "SDIO support" -+ default m -+ ---help--- -+ good luck. -+ -+source "drivers/sdio/hcd/Kconfig" -+ -+source "drivers/sdio/function/Kconfig" -+ -+endmenu -diff --git a/drivers/sdio/Makefile b/drivers/sdio/Makefile -new file mode 100644 -index 0000000..f56aa0f ---- /dev/null -+++ b/drivers/sdio/Makefile -@@ -0,0 +1,4 @@ -+#Makefile for SDIO stack -+obj-$(CONFIG_SDIO) += stack/ -+obj-$(CONFIG_SDIO) += hcd/ -+obj-$(CONFIG_SDIO) += function/ -diff --git a/drivers/sdio/stack/Makefile b/drivers/sdio/stack/Makefile -new file mode 100644 -index 0000000..ff0e24d ---- /dev/null -+++ b/drivers/sdio/stack/Makefile -@@ -0,0 +1 @@ -+obj-$(CONFIG_SDIO) += busdriver/ lib/ -\ No newline at end of file -diff --git a/drivers/sdio/stack/busdriver/Makefile b/drivers/sdio/stack/busdriver/Makefile -new file mode 100644 -index 0000000..1130e2d ---- /dev/null -+++ b/drivers/sdio/stack/busdriver/Makefile -@@ -0,0 +1,2 @@ -+obj-$(CONFIG_SDIO) += sdio_busdriver.o -+sdio_busdriver-objs := sdio_bus.o sdio_function.o sdio_bus_misc.o sdio_bus_events.o sdio_bus_os.o -diff --git a/drivers/sdio/stack/busdriver/_busdriver.h b/drivers/sdio/stack/busdriver/_busdriver.h -new file mode 100644 -index 0000000..a85aed1 ---- /dev/null -+++ b/drivers/sdio/stack/busdriver/_busdriver.h -@@ -0,0 +1,466 @@ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+@file: _busdriver.h -+ -+@abstract: internal include file for busdriver -+ -+@notice: Copyright (c), 2004-2006 Atheros Communications, Inc. -+ -+ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * Software distributed under the License is distributed on an "AS -+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -+ * implied. See the License for the specific language governing -+ * rights and limitations under the License. -+ * -+ * Portions of this code were developed with information supplied from the -+ * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply: -+ * -+ * The following conditions apply to the release of the SD simplified specification (�Simplified -+ * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete -+ * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided -+ * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified -+ * Specification may require a license from the SD Card Association or other third parties. -+ * Disclaimers: -+ * The information contained in the Simplified Specification is presented only as a standard -+ * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any -+ * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for -+ * any damages, any infringements of patents or other right of the SD Card Association or any third -+ * parties, which may result from its use. No license is granted by implication, estoppel or otherwise -+ * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall -+ * be construed as an obligation by the SD Card Association to disclose or distribute any technical -+ * information, know-how or other confidential information to any third party. -+ * -+ * -+ * The initial developers of the original code are Seung Yi and Paul Lever -+ * -+ * sdio@atheros.com -+ * -+ * -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#ifndef ___BUSDRIVER_H___ -+#define ___BUSDRIVER_H___ -+#include <linux/sdio/sdio_lib.h> -+ -+#define SDIODBG_FUNC_IRQ (SDDBG_TRACE + 1) -+#define SDIODBG_REQUESTS (SDDBG_TRACE + 2) -+#define SDIODBG_CD_TIMER (SDDBG_TRACE + 3) -+#define SDIODBG_HCD_EVENTS (SDDBG_TRACE + 4) -+ -+#define SDIOBUS_CD_TIMER_ID 0 -+ -+#define SDBUS_MAX_RETRY 3 -+ -+/* Notes on list linkages: -+ * list heads are held in BDCONTEXT -+ * HcdList - SDHCD -+ * one per registered host controller -+ * Next - links of all HCDs -+ * DeviceList SDDEVICE -+ * one per inserted device -+ * Next - links of all devices -+ * DeviceListNext - links of all devices on a function -+ * pFunction - ptr to Function supportting this device -+ * pHcd - ptr to HCD with supporting this device -+ * FunctionList SDFUNCTION -+ * one per register function driver -+ * Next - links of all functions -+ * DeviceList - list of devices being support by this function -+ * uses DeviceListNext in SDDEVICE to link -+ * -+ * -+*/ -+ -+#define SDMMC_DEFAULT_CMD_RETRIES 1 -+#define SDMMC_DEFAULT_CARD_READY_RETRIES 200 -+#define OCR_READY_CHECK_DELAY_MS 10 -+#define SDMMC_POWER_SETTLE_DELAY 400 /* in milliseconds */ -+#define SDBUS_DEFAULT_REQ_LIST_SIZE 16 -+#define SDBUS_DEFAULT_REQ_SIG_SIZE 8 -+#define CARD_DETECT_PAUSE 100 -+#define SDBUS_DEFAULT_CD_POLLING_INTERVAL 1000 /* in milliseconds */ -+#define MAX_CARD_DETECT_MSGS 16 -+#define SDMMC_DEFAULT_BYTES_PER_BLOCK 2048 -+#define SDMMC_DEFAULT_BLOCKS_PER_TRANS 512 -+#define SDMMC_CMD13_POLLING_MULTIPLIER 1000 /* per block multiplier */ -+#define MAX_HCD_REQ_RECURSION 5 -+#define MAX_HCD_RECURSION_RUNAWAY 100 -+ -+ /* internal signalling item */ -+typedef struct _SIGNAL_ITEM{ -+ SDLIST SDList; /* list link*/ -+ OS_SIGNAL Signal; /* signal */ -+}SIGNAL_ITEM, *PSIGNAL_ITEM; -+ -+typedef struct _HCD_EVENT_MESSAGE { -+ HCD_EVENT Event; /* the event */ -+ PSDHCD pHcd; /* hcd that generated the event */ -+}HCD_EVENT_MESSAGE, *PHCD_EVENT_MESSAGE; -+ -+/* internal data for bus driver */ -+typedef struct _BDCONTEXT { -+ -+ /* list of SD requests and signalling semaphores and a semaphore to protect it */ -+ SDLIST RequestList; -+ SDLIST SignalList; -+ OS_CRITICALSECTION RequestListCritSection; -+ /* list of host controller bus drivers, sempahore to protect it */ -+ SDLIST HcdList; -+ OS_SEMAPHORE HcdListSem; -+ /* list of inserted devices, semaphore to protect it */ -+ SDLIST DeviceList; -+ OS_SEMAPHORE DeviceListSem; -+ /* list of function drivers, semaphore to protect it */ -+ SDLIST FunctionList; -+ OS_SEMAPHORE FunctionListSem; -+ INT RequestListSize; /* default request list */ -+ INT SignalSemListSize; /* default signalling semaphore size */ -+ INT CurrentRequestAllocations; /*current count of allocated requests */ -+ INT CurrentSignalAllocations; /* current count of signal allocations */ -+ INT MaxRequestAllocations; /* max number of allocated requests to keep around*/ -+ INT MaxSignalAllocations; /* max number of signal allocations to keep around*/ -+ INT RequestRetries; /* cmd retries */ -+ INT CardReadyPollingRetry; /* card ready polling retry count */ -+ INT PowerSettleDelay; /* power settle delay */ -+ INT CMD13PollingMultiplier; /* CMD13 (GET STATUS) multiplier */ -+ SD_BUSCLOCK_RATE DefaultOperClock; /* default operation clock */ -+ SD_BUSMODE_FLAGS DefaultBusMode; /* default bus mode */ -+ UINT16 DefaultOperBlockLen; /* default operational block length per block */ -+ UINT16 DefaultOperBlockCount; /* default operational block count per transaction */ -+ UINT32 CDPollingInterval; /* card insert/removal polling interval */ -+ UINT8 InitMask; /* bus driver init mask */ -+#define BD_TIMER_INIT 0x01 -+#define HELPER_INIT 0x02 -+#define RESOURCE_INIT 0x04 -+ BOOL CDTimerQueued; /* card detect timer queued */ -+ OSKERNEL_HELPER CardDetectHelper; /* card detect helper */ -+ PSDMESSAGE_QUEUE pCardDetectMsgQueue; /* card detect message queue */ -+ ULONG HcdInUseField; /* bit field of in use HCD numbers*/ -+ UINT32 ConfigFlags; /* bus driver configuration flags */ -+#define BD_CONFIG_SDREQ_FORCE_ALL_ASYNC 0x00000001 -+ INT MaxHcdRecursion; /* max HCD recurion level */ -+}BDCONTEXT, *PBDCONTEXT; -+ -+#define BD_DEFAULT_CONFIG_FLAGS 0x00000000 -+#define IsQueueBusy(pRequestQueue) (pRequestQueue)->Busy -+#define MarkQueueBusy(pRequestQueue) (pRequestQueue)->Busy = TRUE -+#define MarkQueueNotBusy(pRequestQueue) (pRequestQueue)->Busy = FALSE -+ -+#define CLEAR_INTERNAL_REQ_FLAGS(pReq) (pReq)->Flags &= ~(UINT)((SDREQ_FLAGS_RESP_SPI_CONVERTED | \ -+ SDREQ_FLAGS_FORCE_DEFERRED_COMPLETE)) -+ -+/* macros to insert request into the queue */ -+#define QueueRequest(pReqQ,pReq) SDListInsertTail(&(pReqQ)->Queue,&(pReq)->SDList) -+#define QueueRequestToFront(pReqQ,pReq) SDListInsertHead(&(pReqQ)->Queue,&(pReq)->SDList) -+ -+/* macros to remove an item from the head of the queue */ -+static INLINE PSDREQUEST DequeueRequest(PSDREQUESTQUEUE pRequestQueue) { -+ PSDLIST pItem; -+ pItem = SDListRemoveItemFromHead(&pRequestQueue->Queue); -+ if (pItem != NULL) { -+ return CONTAINING_STRUCT(pItem, SDREQUEST, SDList); -+ } -+ return NULL; -+}; -+ -+static INLINE SDIO_STATUS InitializeRequestQueue(PSDREQUESTQUEUE pRequestQueue) { -+ SDLIST_INIT(&pRequestQueue->Queue); -+ MarkQueueNotBusy(pRequestQueue); -+ return SDIO_STATUS_SUCCESS; -+} -+ -+static INLINE void CleanupRequestQueue(PSDREQUESTQUEUE pRequestQueue) { -+ -+} -+ -+/* for bus driver internal use only */ -+SDIO_STATUS _SDIO_BusDriverInitialize(void); -+SDIO_STATUS _SDIO_BusGetDefaultSettings(PBDCONTEXT pBdc); -+void _SDIO_BusDriverCleanup(void); -+SDIO_STATUS RemoveAllFunctions(void); -+SDIO_STATUS RemoveHcdFunctions(PSDHCD pHcd); -+PSDDEVICE AllocateDevice(PSDHCD pHcd); -+BOOL AddDeviceToList(PSDDEVICE pDevice); -+SDIO_STATUS DeleteDevices(PSDHCD pHcd); -+SDIO_STATUS NotifyDeviceRemove(PSDDEVICE pDevice); -+extern PBDCONTEXT pBusContext; -+extern const CT_VERSION_CODE g_Version; -+SDIO_STATUS _SDIO_RegisterHostController(PSDHCD pHcd); -+SDIO_STATUS _SDIO_UnregisterHostController(PSDHCD pHcd); -+SDIO_STATUS _SDIO_HandleHcdEvent(PSDHCD pHcd, HCD_EVENT Event); -+SDIO_STATUS _SDIO_RegisterFunction(PSDFUNCTION pFunction); -+SDIO_STATUS _SDIO_UnregisterFunction(PSDFUNCTION pFunction); -+SDIO_STATUS _SDIO_CheckResponse(PSDHCD pHcd, PSDREQUEST pReq, SDHCD_RESPONSE_CHECK_MODE CheckMode); -+SDIO_STATUS ProbeForFunction(PSDDEVICE pDevice, PSDHCD pHcd); -+SDIO_STATUS SDInitializeCard(PSDHCD pHcd); -+SDIO_STATUS SDQuerySDMMCInfo(PSDDEVICE pDevice); -+SDIO_STATUS SDQuerySDIOInfo(PSDDEVICE pDevice); -+SDIO_STATUS SDEnableFunction(PSDDEVICE pDevice, PSDCONFIG_FUNC_ENABLE_DISABLE_DATA pEnData); -+SDIO_STATUS SDAllocFreeSlotCurrent(PSDDEVICE pDevice, BOOL Allocate, PSDCONFIG_FUNC_SLOT_CURRENT_DATA pData); -+SDIO_STATUS SDMaskUnmaskFunctionIRQ(PSDDEVICE pDevice, BOOL Mask); -+SDIO_STATUS SDFunctionAckInterrupt(PSDDEVICE pDevice); -+SDIO_STATUS SDSPIModeEnableDisableCRC(PSDDEVICE pDevice,BOOL Enable); -+SDIO_STATUS IssueBusConfig(PSDDEVICE pDev, PSDCONFIG pConfig); -+SDIO_STATUS IssueBusRequest(PSDDEVICE pDev, PSDREQUEST pReq); -+PSDREQUEST IssueAllocRequest(PSDDEVICE pDev); -+void IssueFreeRequest(PSDDEVICE pDev, PSDREQUEST pReq); -+PSDREQUEST AllocateRequest(void); -+void FreeRequest(PSDREQUEST pReq); -+PSIGNAL_ITEM AllocateSignal(void); -+void FreeSignal(PSIGNAL_ITEM pSignal); -+SDIO_STATUS InitializeTimers(void); -+SDIO_STATUS CleanupTimers(void); -+SDIO_STATUS QueueTimer(INT TimerID, UINT32 TimeOut); -+SDIO_STATUS DeviceAttach(PSDHCD pHcd); -+SDIO_STATUS DeviceDetach(PSDHCD pHcd); -+SDIO_STATUS DeviceInterrupt(PSDHCD pHcd); -+SDIO_STATUS CardInitSetup(PSDHCD pHcd); -+void RunCardDetect(void); -+void SDIO_NotifyTimerTriggered(INT TimerID); -+SDIO_STATUS TestPresence(PSDHCD pHcd, -+ CARD_INFO_FLAGS TestType, -+ PSDREQUEST pReq); -+#define _IssueSimpleBusRequest(pHcd,Cmd,Arg,Flags,pReqToUse) \ -+ _IssueBusRequestBd((pHcd),(Cmd),(Arg),(Flags),(pReqToUse),NULL,0) -+ -+SDIO_STATUS Do_OS_IncHcdReference(PSDHCD pHcd); -+SDIO_STATUS Do_OS_DecHcdReference(PSDHCD pHcd); -+SDIO_STATUS TryNoIrqPendingCheck(PSDDEVICE pDev); -+ -+ /* check API version compatibility of an HCD or function driver to a stack major/minor version -+ if the driver version is greater than the major number, we are compatible -+ if the driver version is equal, then we check if the minor is greater than or equal -+ we don't have to check for the less than major, because the bus driver never loads -+ drivers with different major numbers ... -+ if the busdriver compiled version major is greater than the major version being checked this -+ macro will resolved to ALWAYS true thus optimizing the code to not check the HCD since -+ as a rule we never load an HCD with a lower major number */ -+#define CHECK_API_VERSION_COMPAT(p,major,minor) \ -+ ((CT_SDIO_STACK_VERSION_MAJOR(CT_SDIO_STACK_VERSION_CODE) > (major)) || \ -+ (GET_SDIO_STACK_VERSION_MINOR((p)) >= (minor))) -+ -+static INLINE SDIO_STATUS OS_IncHcdReference(PSDHCD pHcd) { -+ /* this API was added in version 2.3 which requires access to a field in the HCD structure */ -+ if (CHECK_API_VERSION_COMPAT(pHcd,2,3)) { -+ /* we can safely call the OS-dependent function */ -+ return Do_OS_IncHcdReference(pHcd); -+ } -+ return SDIO_STATUS_SUCCESS; -+} -+ -+static INLINE SDIO_STATUS OS_DecHcdReference(PSDHCD pHcd) { -+ /* this API was added in version 2.3 which requires access to a field in the HCD structure */ -+ if (CHECK_API_VERSION_COMPAT(pHcd,2,3)) { -+ /* we can safely call the OS-dependent function */ -+ return Do_OS_DecHcdReference(pHcd); -+ } -+ return SDIO_STATUS_SUCCESS; -+} -+ -+SDIO_STATUS _IssueBusRequestBd(PSDHCD pHcd, -+ UINT8 Cmd, -+ UINT32 Argument, -+ SDREQUEST_FLAGS Flags, -+ PSDREQUEST pReqToUse, -+ PVOID pData, -+ INT Length); -+ -+SDIO_STATUS IssueRequestToHCD(PSDHCD pHcd,PSDREQUEST pReq); -+ -+#define CALL_HCD_CONFIG(pHcd,pCfg) (pHcd)->pConfigure((pHcd),(pCfg)) -+ /* macro to force all requests to be asynchronous in the HCD */ -+static INLINE BOOL ForceAllRequestsAsync(void) { -+ return (pBusContext->ConfigFlags & BD_CONFIG_SDREQ_FORCE_ALL_ASYNC); -+} -+ -+static INLINE SDIO_STATUS CallHcdRequest(PSDHCD pHcd) { -+ -+ if (pHcd->pCurrentRequest->Flags & SDREQ_FLAGS_PSEUDO) { -+ DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: PSEUDO Request 0x%X \n", -+ (INT)pHcd->pCurrentRequest)); -+ /* return successful completion so that processing can finish */ -+ return SDIO_STATUS_SUCCESS; -+ } -+ -+ if (ForceAllRequestsAsync()) { -+ /* all requests must be completed(indicated) in a separate context */ -+ pHcd->pCurrentRequest->Flags |= SDREQ_FLAGS_FORCE_DEFERRED_COMPLETE; -+ } else { -+ /* otherwise perform a test on flags in the HCD */ -+ if (!CHECK_API_VERSION_COMPAT(pHcd,2,6) && -+ AtomicTest_Set(&pHcd->HcdFlags, HCD_REQUEST_CALL_BIT)) { -+ -+ /* bit was already set, this is a recursive call, -+ * we need to tell the HCD to complete the -+ * request in a separate context */ -+ DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Recursive CallHcdRequest \n")); -+ pHcd->pCurrentRequest->Flags |= SDREQ_FLAGS_FORCE_DEFERRED_COMPLETE; -+ } -+ } -+ #if DEBUG -+ { -+ SDIO_STATUS status; -+ BOOL forceDeferred; -+ forceDeferred = pHcd->pCurrentRequest->Flags & SDREQ_FLAGS_FORCE_DEFERRED_COMPLETE; -+ status = pHcd->pRequest(pHcd); -+ if (forceDeferred) { -+ /* status better be pending... */ -+ DBG_ASSERT(status == SDIO_STATUS_PENDING); -+ } -+ return status; -+ } -+ #else -+ return pHcd->pRequest(pHcd); -+ #endif -+ -+} -+ -+/* note the caller of this macro must take the HCD lock to protect the count */ -+#define CHECK_HCD_RECURSE(pHcd,pReq) \ -+{ \ -+ (pHcd)->Recursion++; \ -+ DBG_ASSERT((pHcd)->Recursion < MAX_HCD_RECURSION_RUNAWAY); \ -+ if ((pHcd)->Recursion > pBusContext->MaxHcdRecursion) { \ -+ DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Recursive Request Count Exceeded (%d) \n",(pHcd)->Recursion)); \ -+ (pReq)->Flags |= SDREQ_FLAGS_FORCE_DEFERRED_COMPLETE; \ -+ } \ -+} -+ -+/* InternalFlags bit number settings */ -+#define SDBD_INIT 1 -+#define SDBD_PENDING 15 -+#define SDBD_ALLOC_IRQ_SAFE 2 -+ -+#define SDBD_ALLOC_IRQ_SAFE_MASK (1 << SDBD_ALLOC_IRQ_SAFE) -+ -+static void INLINE DoRequestCompletion(PSDREQUEST pReq, PSDHCD pHcd) { -+ CLEAR_INTERNAL_REQ_FLAGS(pReq); -+ if (pReq->pCompletion != NULL) { -+ DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Calling completion on request:0x%X, CMD:%d \n", -+ (INT)pReq, pReq->Command)); -+ /* call completion routine, mark request reusable */ -+ AtomicTest_Clear(&pReq->InternalFlags, SDBD_PENDING); -+ pReq->pCompletion(pReq); -+ } else { -+ /* mark request reusable */ -+ AtomicTest_Clear(&pReq->InternalFlags, SDBD_PENDING); -+ } -+} -+ -+THREAD_RETURN CardDetectHelperFunction(POSKERNEL_HELPER pHelper); -+THREAD_RETURN SDIOIrqHelperFunction(POSKERNEL_HELPER pHelper); -+ -+void ConvertSPI_Response(PSDREQUEST pReq, UINT8 *pRespBuffer); -+ -+static INLINE SDIO_STATUS PostCardDetectEvent(PBDCONTEXT pSDB, HCD_EVENT Event, PSDHCD pHcd) { -+ HCD_EVENT_MESSAGE message; -+ SDIO_STATUS status; -+ message.Event = Event; -+ message.pHcd = pHcd; -+ -+ if (pHcd != NULL) { -+ /* increment HCD reference count to process this HCD message */ -+ status = OS_IncHcdReference(pHcd); -+ if (!SDIO_SUCCESS(status)) { -+ return status; -+ } -+ } -+ /* post card detect message */ -+ status = SDLIB_PostMessage(pSDB->pCardDetectMsgQueue, &message, sizeof(message)); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: PostCardDetectEvent error status %d\n",status)); -+ if (pHcd != NULL) { -+ /* decrement count */ -+ OS_DecHcdReference(pHcd); -+ } -+ return status; -+ } -+ /* wake card detect helper */ -+ DBG_PRINT(SDIODBG_HCD_EVENTS, ("SDIO Bus Driver: PostCardDetectEvent waking\n")); -+ return SD_WAKE_OS_HELPER(&pSDB->CardDetectHelper); -+}; -+ -+/* initialize device fields */ -+static INLINE void InitDeviceData(PSDHCD pHcd, PSDDEVICE pDevice) { -+ ZERO_POBJECT(pDevice); -+ SDLIST_INIT(&pDevice->SDList); -+ SDLIST_INIT(&pDevice->FuncListLink); -+ pDevice->pRequest = IssueBusRequest; -+ pDevice->pConfigure = IssueBusConfig; -+ pDevice->AllocRequest = IssueAllocRequest; -+ pDevice->FreeRequest = IssueFreeRequest; -+ /* set card flags in the ID */ -+ pDevice->pId[0].CardFlags = pHcd->CardProperties.Flags; -+ pDevice->pFunction = NULL; -+ pDevice->pHcd = pHcd; -+ SET_SDIO_STACK_VERSION(pDevice); -+} -+ -+/* de-initialize device fields */ -+static INLINE void DeinitDeviceData(PSDDEVICE pDevice) { -+} -+ -+/* reset hcd state */ -+static INLINE void ResetHcdState(PSDHCD pHcd) { -+ ZERO_POBJECT(&pHcd->CardProperties); -+ pHcd->PendingHelperIrqs = 0; -+ pHcd->PendingIrqAcks = 0; -+ pHcd->IrqsEnabled = 0; -+ pHcd->pCurrentRequest = NULL; -+ pHcd->IrqProcState = SDHCD_IDLE; -+ /* mark this device as special */ -+ pHcd->pPseudoDev->pId[0].CardFlags = CARD_PSEUDO; -+ pHcd->SlotCurrentAllocated = 0; -+} -+ -+static INLINE SDIO_STATUS _IssueConfig(PSDHCD pHcd, -+ SDCONFIG_COMMAND Command, -+ PVOID pData, -+ INT Length){ -+ SDCONFIG configHdr; -+ SET_SDCONFIG_CMD_INFO(&configHdr,Command,pData,Length); -+ return CALL_HCD_CONFIG(pHcd,&configHdr); -+} -+ -+/* prototypes */ -+#define _AcquireHcdLock(pHcd)CriticalSectionAcquireSyncIrq(&(pHcd)->HcdCritSection) -+#define _ReleaseHcdLock(pHcd)CriticalSectionReleaseSyncIrq(&(pHcd)->HcdCritSection) -+ -+#define AcquireHcdLock(pDev) CriticalSectionAcquireSyncIrq(&(pDev)->pHcd->HcdCritSection) -+#define ReleaseHcdLock(pDev) CriticalSectionReleaseSyncIrq(&(pDev)->pHcd->HcdCritSection) -+ -+SDIO_STATUS OS_AddDevice(PSDDEVICE pDevice, PSDFUNCTION pFunction); -+void OS_RemoveDevice(PSDDEVICE pDevice); -+SDIO_STATUS OS_InitializeDevice(PSDDEVICE pDevice, PSDFUNCTION pFunction); -+SDIO_STATUS SetOperationalBusMode(PSDDEVICE pDevice, -+ PSDCONFIG_BUS_MODE_DATA pBusMode); -+void FreeDevice(PSDDEVICE pDevice); -+BOOL IsPotentialIdMatch(PSD_PNP_INFO pIdsDev, PSD_PNP_INFO pIdsFuncList); -+ -+ -+#define CHECK_FUNCTION_DRIVER_VERSION(pF) \ -+ (GET_SDIO_STACK_VERSION_MAJOR((pF)) == CT_SDIO_STACK_VERSION_MAJOR(g_Version)) -+#define CHECK_HCD_DRIVER_VERSION(pH) \ -+ (GET_SDIO_STACK_VERSION_MAJOR((pH)) == CT_SDIO_STACK_VERSION_MAJOR(g_Version)) -+ -+/* CLARIFICATION on SDREQ_FLAGS_PSEUDO and SDREQ_FLAGS_BARRIER flags : -+ * -+ * A request marked as PSEUDO is synchronized with bus requests and is not a true request -+ * that is issued to an HCD. -+ * -+ * A request marked with a BARRIER flag requires that the completion routine be called -+ * before the next bus request starts. This is required for HCD requests that can change -+ * bus or clock modes. Changing the clock or bus mode while a bus request is pending -+ * can cause problems. -+ * -+ * -+ * -+ * */ -+#define SD_PSEUDO_REQ_FLAGS \ -+ (SDREQ_FLAGS_PSEUDO | SDREQ_FLAGS_BARRIER | SDREQ_FLAGS_TRANS_ASYNC) -+ -+#endif /*___BUSDRIVER_H___*/ -diff --git a/drivers/sdio/stack/busdriver/sdio_bus.c b/drivers/sdio/stack/busdriver/sdio_bus.c -new file mode 100644 -index 0000000..ffc1e9f ---- /dev/null -+++ b/drivers/sdio/stack/busdriver/sdio_bus.c -@@ -0,0 +1,2120 @@ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+@file: sdio_bus.c -+ -+@abstract: OS independent bus driver support -+@category abstract: HD_Reference Host Controller Driver Interfaces. -+@category abstract: PD_Reference -+ Peripheral Driver Interfaces. -+ -+#notes: this file supports the HCD's and generic functions -+ -+@notice: Copyright (c), 2004-2006 Atheros Communications, Inc. -+ -+ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * Software distributed under the License is distributed on an "AS -+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -+ * implied. See the License for the specific language governing -+ * rights and limitations under the License. -+ * -+ * Portions of this code were developed with information supplied from the -+ * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply: -+ * -+ * The following conditions apply to the release of the SD simplified specification (�Simplified -+ * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete -+ * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided -+ * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified -+ * Specification may require a license from the SD Card Association or other third parties. -+ * Disclaimers: -+ * The information contained in the Simplified Specification is presented only as a standard -+ * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any -+ * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for -+ * any damages, any infringements of patents or other right of the SD Card Association or any third -+ * parties, which may result from its use. No license is granted by implication, estoppel or otherwise -+ * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall -+ * be construed as an obligation by the SD Card Association to disclose or distribute any technical -+ * information, know-how or other confidential information to any third party. -+ * -+ * -+ * The initial developers of the original code are Seung Yi and Paul Lever -+ * -+ * sdio@atheros.com -+ * -+ * -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define MODULE_NAME SDBUSDRIVER -+#include <linux/sdio/ctsystem.h> -+#include <linux/sdio/sdio_busdriver.h> -+#include <linux/sdio/_sdio_defs.h> -+#include <linux/sdio/sdio_lib.h> -+#include <linux/sdio/mmc_defs.h> -+#include "_busdriver.h" -+ -+/* list of host controller bus drivers */ -+PBDCONTEXT pBusContext = NULL; -+static void CleanUpBusResources(void); -+static SDIO_STATUS AllocateBusResources(void); -+static PSIGNAL_ITEM BuildSignal(void); -+static void DestroySignal(PSIGNAL_ITEM pSignal); -+ -+const CT_VERSION_CODE g_Version = CT_SDIO_STACK_VERSION_CODE; -+/* -+ * _SDIO_BusDriverInitialize - call once on driver loading -+ * -+*/ -+SDIO_STATUS _SDIO_BusDriverInitialize(void) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Version: %d.%d\n", -+ CT_SDIO_STACK_VERSION_MAJOR(g_Version),CT_SDIO_STACK_VERSION_MINOR(g_Version))); -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: enter _SDIO_BusDriverInitialize\n")); -+ -+ do { -+ /* allocate our internal data initialize it */ -+ pBusContext = KernelAlloc(sizeof(BDCONTEXT)); -+ if (pBusContext == NULL) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't allocate memory.\n")); -+ status = SDIO_STATUS_NO_RESOURCES; -+ break; -+ } -+ memset(pBusContext,0,sizeof(BDCONTEXT)); -+ SDLIST_INIT(&pBusContext->RequestList); -+ SDLIST_INIT(&pBusContext->HcdList); -+ SDLIST_INIT(&pBusContext->DeviceList); -+ SDLIST_INIT(&pBusContext->FunctionList); -+ SDLIST_INIT(&pBusContext->SignalList); -+ -+ /* setup defaults */ -+ pBusContext->RequestRetries = SDMMC_DEFAULT_CMD_RETRIES; -+ pBusContext->CardReadyPollingRetry = SDMMC_DEFAULT_CARD_READY_RETRIES; -+ pBusContext->PowerSettleDelay = SDMMC_POWER_SETTLE_DELAY; -+ pBusContext->DefaultOperClock = MMC_HS_MAX_BUS_CLOCK; -+ pBusContext->DefaultBusMode = SDCONFIG_BUS_WIDTH_4_BIT; -+ pBusContext->RequestListSize = SDBUS_DEFAULT_REQ_LIST_SIZE; -+ pBusContext->SignalSemListSize = SDBUS_DEFAULT_REQ_SIG_SIZE; -+ pBusContext->CDPollingInterval = SDBUS_DEFAULT_CD_POLLING_INTERVAL; -+ pBusContext->DefaultOperBlockLen = SDMMC_DEFAULT_BYTES_PER_BLOCK; -+ pBusContext->DefaultOperBlockCount = SDMMC_DEFAULT_BLOCKS_PER_TRANS; -+ pBusContext->ConfigFlags = BD_DEFAULT_CONFIG_FLAGS; -+ pBusContext->CMD13PollingMultiplier = SDMMC_CMD13_POLLING_MULTIPLIER; -+ pBusContext->MaxHcdRecursion = MAX_HCD_REQ_RECURSION; -+ -+ /* get overrides for the defaults */ -+ status = _SDIO_BusGetDefaultSettings(pBusContext); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ -+ pBusContext->MaxRequestAllocations = pBusContext->RequestListSize << 1; -+ pBusContext->MaxSignalAllocations = pBusContext->SignalSemListSize << 1; -+ -+ status = CriticalSectionInit(&pBusContext->RequestListCritSection); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't CriticalSectionInit.\n")); -+ break; -+ } -+ status = SemaphoreInitialize(&pBusContext->HcdListSem, 1); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't SemaphoreInitialize HcdListSem.\n")); -+ break; -+ } -+ status = SemaphoreInitialize(&pBusContext->DeviceListSem, 1); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't SemaphoreInitialize DeviceListSem.\n")); -+ break; -+ } -+ status = SemaphoreInitialize(&pBusContext->FunctionListSem, 1); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't SemaphoreInitialize FunctionListSem.\n")); -+ break; -+ } -+ status = AllocateBusResources(); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't AllocateBusResources.\n")); -+ break; -+ } -+ -+ pBusContext->InitMask |= RESOURCE_INIT; -+ -+ pBusContext->pCardDetectMsgQueue = SDLIB_CreateMessageQueue(MAX_CARD_DETECT_MSGS, -+ sizeof(HCD_EVENT_MESSAGE)); -+ -+ if (NULL == pBusContext->pCardDetectMsgQueue) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't CreateMessageQueue.\n")); -+ status = SDIO_STATUS_NO_RESOURCES; -+ break; -+ } -+ -+ status = SDLIB_OSCreateHelper(&pBusContext->CardDetectHelper, -+ CardDetectHelperFunction, -+ NULL); -+ -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't OSCreateHelper.\n")); -+ break; -+ } -+ -+ pBusContext->InitMask |= HELPER_INIT; -+ -+ status = InitializeTimers(); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't InitializeTimers.\n")); -+ break; -+ } -+ pBusContext->InitMask |= BD_TIMER_INIT; -+ } while(FALSE); -+ -+ if (!SDIO_SUCCESS(status)) { -+ _SDIO_BusDriverCleanup(); -+ } -+ -+ return status; -+} -+ -+ -+/* -+ * _SDIO_BusDriverBusDriverCleanup - call once on driver unloading -+ * -+*/ -+void _SDIO_BusDriverCleanup(void) { -+ DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: _SDIO_BusDriverCleanup\n")); -+ -+ if (pBusContext->InitMask & BD_TIMER_INIT) { -+ CleanupTimers(); -+ } -+ -+ if (pBusContext->InitMask & HELPER_INIT) { -+ SDLIB_OSDeleteHelper(&pBusContext->CardDetectHelper); -+ } -+ -+ if (pBusContext->pCardDetectMsgQueue != NULL) { -+ SDLIB_DeleteMessageQueue(pBusContext->pCardDetectMsgQueue); -+ pBusContext->pCardDetectMsgQueue = NULL; -+ } -+ /* remove functions */ -+ RemoveAllFunctions(); -+ /* cleanup all devices */ -+ DeleteDevices(NULL); -+ CleanUpBusResources(); -+ CriticalSectionDelete(&pBusContext->RequestListCritSection); -+ SemaphoreDelete(&pBusContext->HcdListSem); -+ SemaphoreDelete(&pBusContext->DeviceListSem); -+ SemaphoreDelete(&pBusContext->FunctionListSem); -+ KernelFree(pBusContext); -+ pBusContext = NULL; -+ DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: _SDIO_BusDriverCleanup\n")); -+} -+ -+ -+/* cleanup hcd */ -+static void CleanupHcd(PSDHCD pHcd) -+{ -+ SDLIB_OSDeleteHelper(&pHcd->SDIOIrqHelper); -+ CleanupRequestQueue(&pHcd->CompletedRequestQueue); -+ CleanupRequestQueue(&pHcd->RequestQueue); -+ CriticalSectionDelete(&pHcd->HcdCritSection); -+ SemaphoreDelete(&pHcd->ConfigureOpsSem); -+ pHcd->pCurrentRequest = NULL; -+ if (pHcd->pPseudoDev != NULL) { -+ FreeDevice(pHcd->pPseudoDev); -+ pHcd->pPseudoDev = NULL; -+ } -+} -+ -+/* set up the hcd */ -+static SDIO_STATUS SetupHcd(PSDHCD pHcd) -+{ -+ SDIO_STATUS status; -+ -+ ZERO_POBJECT(&pHcd->SDIOIrqHelper); -+ ZERO_POBJECT(&pHcd->ConfigureOpsSem); -+ ZERO_POBJECT(&pHcd->HcdCritSection); -+ ZERO_POBJECT(&pHcd->RequestQueue); -+ ZERO_POBJECT(&pHcd->CompletedRequestQueue); -+ pHcd->pPseudoDev = NULL; -+ pHcd->Recursion = 0; -+ -+ do { -+ -+ pHcd->pPseudoDev = AllocateDevice(pHcd); -+ -+ if (NULL == pHcd->pPseudoDev) { -+ status = SDIO_STATUS_NO_RESOURCES; -+ break; -+ } -+ -+ ResetHcdState(pHcd); -+ -+ status = SemaphoreInitialize(&pHcd->ConfigureOpsSem,1); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ status = CriticalSectionInit(&pHcd->HcdCritSection); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ status = InitializeRequestQueue(&pHcd->RequestQueue); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ status = InitializeRequestQueue(&pHcd->CompletedRequestQueue); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ /* create SDIO Irq helper */ -+ status = SDLIB_OSCreateHelper(&pHcd->SDIOIrqHelper, -+ SDIOIrqHelperFunction, -+ (PVOID)pHcd); -+ } while(FALSE); -+ -+ if (!SDIO_SUCCESS(status)) { -+ /* undo what we did */ -+ CleanupHcd(pHcd); -+ } -+ return status; -+} -+ -+ -+/* -+ * _SDIO_RegisterHostController - register a host controller bus driver -+ * -+*/ -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Register a host controller driver with the bus driver. -+ -+ @function name: SDIO_RegisterHostController -+ @prototype: SDIO_STATUS SDIO_RegisterHostController (PSDHCD pHcd) -+ @category: HD_Reference -+ -+ @input: pHcd - the host controller definition structure. -+ -+ @output: none -+ -+ @return: SDIO_STATUS - SDIO_STATUS_SUCCESS when successful. -+ -+ @notes: Each host controller driver must register with the bus driver when loaded. -+ The driver registers an SDHCD structure initialized with hardware properties -+ and callback functions for bus requests and configuration. On multi-slot -+ hardware ,each slot should be registered with a separate SDHCD structure. -+ The bus driver views each slot as a seperate host controller object. -+ The driver should be prepared to receive configuration requests before -+ this call returns. The host controller driver must unregister itself when -+ shutting down. -+ -+ @example: Registering a host controller driver: -+ static SDHCD Hcd = { -+ .pName = "sdio_custom_hcd", -+ .Version = CT_SDIO_STACK_VERSION_CODE, // set stack version code -+ .SlotNumber = 0, // bus driver internal use -+ .Attributes = SDHCD_ATTRIB_BUS_1BIT | SDHCD_ATTRIB_BUS_4BIT | SDHCD_ATTRIB_MULTI_BLK_IRQ -+ SDHCD_ATTRIB_AUTO_CMD12 , -+ .MaxBytesPerBlock = 2048 // each data block can be up to 2048 bytes -+ .MaxBlocksPerTrans = 1024, // each data transaction can consist of 1024 blocks -+ .MaxSlotCurrent = 500, // max FET switch current rating -+ .SlotVoltageCaps = SLOT_POWER_3_3V, // only 3.3V operation -+ .SlotVoltagePreferred = SLOT_POWER_3_3V, -+ .MaxClockRate = 24000000, // 24 Mhz max operation -+ .pContext = &HcdContext, // set our driver context -+ .pRequest = HcdRequest, // set SDIO bus request callback -+ .pConfigure = HcdConfig, // set SDIO bus configuration callback -+ }; -+ if (!SDIO_SUCCESS((status = SDIO_RegisterHostController(&Hcd)))) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO HCD - failed to register with host, status =%d\n", -+ status)); -+ } -+ -+ @see also: SDIO_UnregisterHostController -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS _SDIO_RegisterHostController(PSDHCD pHcd) { -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ -+ DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: _SDIO_RegisterHostController - %s\n",pHcd->pName)); -+ DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: Host Controller Stack Version: %d.%d \n", -+ GET_SDIO_STACK_VERSION_MAJOR(pHcd),GET_SDIO_STACK_VERSION_MINOR(pHcd))); -+ -+ if (!CHECK_HCD_DRIVER_VERSION(pHcd)) { -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO Bus Driver: HCD Major Version Mismatch (hcd = %d, bus driver = %d)\n", -+ GET_SDIO_STACK_VERSION_MAJOR(pHcd), CT_SDIO_STACK_VERSION_MAJOR(g_Version))); -+ return SDIO_STATUS_INVALID_PARAMETER; -+ } -+ /* setup hcd */ -+ status = SetupHcd(pHcd); -+ if (!SDIO_SUCCESS(status)) { -+ return status; -+ } -+ -+ do { -+ INT slotNumber; -+ -+ /* protect the HCD list */ -+ if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->HcdListSem)))) { -+ break; /* wait interrupted */ -+ } -+ /* find a unique number for this HCD, must be done under semaphore protection */ -+ slotNumber = FirstClearBit(&pBusContext->HcdInUseField); -+ if (slotNumber < 0) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_RegisterHostController, error, slotNumber exceeded\n")); -+ /* fake something */ -+ slotNumber = 31; -+ } -+ SetBit(&pBusContext->HcdInUseField, slotNumber); -+ pHcd->SlotNumber = slotNumber; -+ /* add HCD to the end of the internal list */ -+ SDListAdd(&pBusContext->HcdList , &pHcd->SDList); -+ if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->HcdListSem)))) { -+ break; /* wait interrupted */ -+ } -+ if (pHcd->Attributes & SDHCD_ATTRIB_SLOT_POLLING) { -+ /* post message to card detect helper to do polling */ -+ PostCardDetectEvent(pBusContext, EVENT_HCD_CD_POLLING, NULL); -+ } -+ } while (FALSE); -+ -+ if (!SDIO_SUCCESS(status)) { -+ CleanupHcd(pHcd); -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_RegisterHostController, error 0x%X.\n", status)); -+ } -+ DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: _SDIO_RegisterHostController\n")); -+ return status; -+} -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Unregister a host controller driver with the bus driver. -+ -+ @function name: SDIO_UnregisterHostController -+ @prototype: SDIO_STATUS SDIO_UnregisterHostController (PSDHCD pHcd) -+ @category: HD_Reference -+ -+ @input: pHcd - the host controller definition structure that was registered. -+ -+ @output: none -+ -+ @return: SDIO_STATUS - SDIO_STATUS_SUCCESS when successful. -+ -+ @notes: Each host controller driver must unregister with the bus driver when -+ unloading. The driver is responsible for halting any outstanding I/O -+ operations. The bus driver will automatically unload function drivers -+ that may be attached assigned to cards inserted into slots. -+ -+ @example: Unregistering a host controller driver: -+ if (!SDIO_SUCCESS((status = SDIO_UnregisterHostController(&Hcd)))) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO HCD - failed to unregister with host, status =%d\n", -+ status)); -+ } -+ -+ @see also: SDIO_RegisterHostController -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS _SDIO_UnregisterHostController(PSDHCD pHcd) { -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ -+ DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: _SDIO_UnregisterHostController\n")); -+ -+ /* remove functions associated with the HCD */ -+ RemoveHcdFunctions(pHcd); -+ /* remove any devices associated with the HCD */ -+ DeleteDevices(pHcd); -+ /* wait for the message queue to be empty, so we don't have any delayed requests going -+ to this device */ -+ while(!SDLIB_IsQueueEmpty(pBusContext->pCardDetectMsgQueue)) { -+ /* wait for the messages to be handled */ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: _SDIO_UnregisterHostController, waiting on messages\n")); -+ OSSleep(250); -+ } -+ -+ /* protect the HCD list */ -+ if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->HcdListSem)))) { -+ goto cleanup; /* wait interrupted */ -+ } -+ ClearBit(&pBusContext->HcdInUseField, pHcd->SlotNumber); -+ /* delete HCD from list */ -+ SDListRemove(&pHcd->SDList); -+ if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->HcdListSem)))) { -+ goto cleanup; /* wait interrupted */ -+ } -+ /* cleanup anything we allocated */ -+ CleanupHcd(pHcd); -+ DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: _SDIO_UnregisterHostController\n")); -+ return status; -+cleanup: -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_UnregisterHostController, error 0x%X.\n", status)); -+ return status; -+} -+ -+/* documentation headers only for Request and Configure */ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: The bus driver calls the request callback to start an SDIO bus transaction. -+ @function name: Request -+ @prototype: SDIO_STATUS (*pRequest) (struct _SDHCD *pHcd) -+ @category: HD_Reference -+ -+ @input: pHcd - the host controller structure that was registered -+ -+ @output: none -+ -+ @return: SDIO_STATUS -+ -+ @notes: -+ The bus driver maintains an internal queue of SDREQUEST structures submited by function -+ drivers. The driver should use request macros to obtain a pointer to the current SDREQUEST -+ at the head of the queue. The driver can access the fields of the current request in order -+ to program hardware appropriately. Once the request completes, the driver should update -+ the current request information (final status, response bytes and/or data) and call -+ SDIO_HandleHcdEvent() with the event type of EVENT_HCD_TRANSFER_DONE. -+ The bus driver will remove the current request from the head of the queue and start the next -+ request. -+ -+ @example: Example of a typical Request callback: -+ SDIO_STATUS HcdRequest(PSDHCD pHcd) -+ { -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ PSDHCD_DRIVER_CONTEXT pHct = (PSDHCD_DRIVER_CONTEXT)pHcd->pContext; -+ UINT32 temp = 0; -+ PSDREQUEST pReq; -+ // get the current request -+ pReq = GET_CURRENT_REQUEST(pHcd); -+ DBG_ASSERT(pReq != NULL); -+ // get controller settings based on response type -+ switch (GET_SDREQ_RESP_TYPE(pReq->Flags)) { -+ case SDREQ_FLAGS_NO_RESP: -+ break; -+ case SDREQ_FLAGS_RESP_R1: -+ case SDREQ_FLAGS_RESP_MMC_R4: -+ case SDREQ_FLAGS_RESP_MMC_R5: -+ case SDREQ_FLAGS_RESP_R6: -+ case SDREQ_FLAGS_RESP_SDIO_R5: -+ temp |= CMDDAT_RES_R1_R4_R5; -+ break; -+ case SDREQ_FLAGS_RESP_R1B: -+ temp |= (CMDDAT_RES_R1_R4_R5 | CMDAT_RES_BUSY); -+ break; -+ case SDREQ_FLAGS_RESP_R2: -+ temp |= CMDDAT_RES_R2; -+ break; -+ case SDREQ_FLAGS_RESP_R3: -+ case SDREQ_FLAGS_RESP_SDIO_R4: -+ temp |= CMDDAT_RES_R3; -+ break; -+ } -+ // check for data -+ if (pReq->Flags & SDREQ_FLAGS_DATA_TRANS){ -+ temp |= CMDDAT_DATA_EN; -+ // set data remaining count -+ pReq->DataRemaining = pReq->BlockLen * pReq->BlockCount; -+ DBG_PRINT(TRACE_DATA, ("SDIO %s Data Transfer, Blocks:%d, BlockLen:%d, Total:%d \n", -+ IS_SDREQ_WRITE_DATA(pReq->Flags) ? "TX":"RX", -+ pReq->BlockCount, pReq->BlockLen, pReq->DataRemaining)); -+ if (IS_SDREQ_WRITE_DATA(pReq->Flags)) { -+ // write operation -+ } -+ } -+ // .... program hardware, interrupt handler will complete request -+ return SDIO_STATUS_PENDING; -+ } -+ -+ @see also: SDIO_HandleHcdEvent -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: The bus driver calls the configure callback to set various options -+ and modes in the host controller hardware. -+ -+ @function name: Configure -+ @prototype: SDIO_STATUS (*pConfigure) (struct _SDHCD *pHcd, PSDCONFIG pConfig) -+ @category: HD_Reference -+ -+ @input: pHcd - the host controller structure that was registered -+ @input: pConfig - configuration request structure -+ -+ @output: none -+ -+ @return: SDIO_STATUS -+ -+ @notes: -+ The host controller driver recieves configuration requests for options -+ such as slot voltage, bus width, clock rates and interrupt detection. -+ The bus driver guarantees that only one configuration option request -+ can be issued at a time. -+ -+ @example: Example of a typical configure callback: -+ SDIO_STATUS HcdConfig(PSDHCD pHcd, PSDCONFIG pConfig) -+ { -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ PSDHCD_DRIVER_CONTEXT pHct = (PSDHCD_DRIVER_CONTEXT)pHcd->pContext; -+ UINT16 command; -+ // get command -+ command = GET_SDCONFIG_CMD(pConfig); -+ // decode command -+ switch (command){ -+ case SDCONFIG_GET_WP: -+ if (GetGpioPinLevel(pHct,SDIO_CARD_WP_GPIO) == WP_POLARITY) { -+ *((SDCONFIG_WP_VALUE *)pConfig->pData) = 1; -+ } else { -+ *((SDCONFIG_WP_VALUE *)pConfig->pData) = 0; -+ } -+ break; -+ case SDCONFIG_SEND_INIT_CLOCKS: -+ ClockStartStop(pHct,CLOCK_ON); -+ // sleep a little, should be at least 80 clocks at our lowest clock setting -+ status = OSSleep(100); -+ ClockStartStop(pHct,CLOCK_OFF); -+ break; -+ case SDCONFIG_SDIO_INT_CTRL: -+ if (GET_SDCONFIG_CMD_DATA(PSDCONFIG_SDIO_INT_CTRL_DATA,pConfig)->SlotIRQEnable) { -+ // request to enable IRQ detection -+ } else { -+ // request to disable IRQ detectioon -+ } -+ break; -+ case SDCONFIG_SDIO_REARM_INT: -+ // request to re-arm the card IRQ detection logic -+ break; -+ case SDCONFIG_BUS_MODE_CTRL: -+ // request to set bus mode -+ { -+ // get bus mode data structure -+ PSDCONFIG_BUS_MODE_DATA pBusMode = -+ GET_SDCONFIG_CMD_DATA(PSDCONFIG_SDIO_INT_CTRL_DATA,pConfig); -+ // set bus mode based on settings in bus mode structure -+ // bus mode : pBusMode->BusModeFlags -+ // clock rate : pBusMode->ClockRate -+ } -+ break; -+ case SDCONFIG_POWER_CTRL: -+ // request to set power/voltage -+ { -+ PSDCONFIG_POWER_CTRL_DATA pPowerSetting = -+ GET_SDCONFIG_CMD_DATA(PSDCONFIG_POWER_CTRL_DATA,pConfig); -+ if (pPowerSetting->SlotPowerEnable) { -+ // turn on slot power -+ // -+ } else { -+ // turn off slot power -+ } -+ DBG_PRINT(PXA_TRACE_CONFIG, ("SDIO PXA255 PwrControl: En:%d, VCC:0x%X \n", -+ pPowerSetting->SlotPowerEnable, -+ pPowerSetting->SlotPowerVoltageMask)); -+ } -+ break; -+ default: -+ // unsupported -+ status = SDIO_STATUS_INVALID_PARAMETER; -+ } -+ return status; -+ } -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+ -+ -+/* -+ * Allocate a Device instance -+ */ -+PSDDEVICE AllocateDevice(PSDHCD pHcd) -+{ -+ PSDDEVICE pDevice; -+ -+ pDevice = KernelAlloc(sizeof(SDDEVICE)); -+ if (pDevice != NULL) { -+ InitDeviceData(pHcd,pDevice); -+ } -+ return pDevice; -+} -+ -+ -+/* -+ * Free a Device instance -+ */ -+void FreeDevice(PSDDEVICE pDevice) -+{ -+ DeinitDeviceData(pDevice); -+ KernelFree(pDevice); -+} -+/* -+ * add this device to the list -+ */ -+BOOL AddDeviceToList(PSDDEVICE pDevice) -+{ -+ BOOL success = FALSE; -+ -+ do { -+ /* protect the driver list */ -+ if (!SDIO_SUCCESS(SemaphorePendInterruptable(&pBusContext->DeviceListSem))) { -+ break; /* wait interrupted */ -+ } -+ -+ /* add new device to the internal list */ -+ SDListAdd(&pBusContext->DeviceList , &pDevice->SDList); -+ -+ if (!SDIO_SUCCESS(SemaphorePost(&pBusContext->DeviceListSem))) { -+ break; -+ } -+ -+ success = TRUE; -+ } while (FALSE); -+ -+ return success; -+} -+ -+/* -+ * Delete device associated with the HCD -+ * if pHCD is NULL this function cleans up all devices, the caller -+ * better have cleaned up functions first! -+ */ -+SDIO_STATUS DeleteDevices(PSDHCD pHcd) -+{ -+ SDIO_STATUS status; -+ PSDDEVICE pDevice; -+ DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: DeleteDevices hcd:0x%X \n", (INT)pHcd)); -+ /* protect the device list */ -+ if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->DeviceListSem)))) { -+ goto cleanup; /* wait interrupted */ -+ } -+ SDITERATE_OVER_LIST_ALLOW_REMOVE(&pBusContext->DeviceList,pDevice,SDDEVICE,SDList) { -+ /* only remove devices for the hcd or if we are cleaning up all */ -+ if ((NULL == pHcd) || (pDevice->pHcd == pHcd)) { -+ SDListRemove(&pDevice->SDList); -+ DeinitDeviceData(pDevice); -+ FreeDevice(pDevice); -+ } -+ }SDITERATE_END; -+ if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->DeviceListSem)))) { -+ goto cleanup; /* wait interrupted */ -+ } -+ DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: DeleteDevices \n")); -+ return status; -+cleanup: -+ DBG_PRINT(SDDBG_ERROR, ("-SDIO Bus Driver: DeleteDevice, error exit 0x%X\n", status)); -+ return status; -+} -+ -+ -+static SDIO_STATUS AllocateBusResources(void) -+{ -+ INT ii; -+ PSDREQUEST pReq; -+ PSIGNAL_ITEM pSignal; -+ -+ DBG_PRINT(SDDBG_TRACE, -+ ("+SDIO Bus Driver: AllocateBusResources (R:%d,S:%d) (CR:%d,MR:%d)(CS:%d,MS:%d) \n", -+ pBusContext->RequestListSize, -+ pBusContext->SignalSemListSize, -+ pBusContext->CurrentRequestAllocations,pBusContext->MaxRequestAllocations, -+ pBusContext->CurrentSignalAllocations,pBusContext->MaxSignalAllocations)); -+ -+ /* allocate some initial requests */ -+ for (ii = 0; ii < pBusContext->RequestListSize; ii++) { -+ pReq = AllocateRequest(); -+ if (pReq == NULL) { -+ break; -+ } -+ /* free requests adds the request to the list */ -+ FreeRequest(pReq); -+ } -+ -+ for (ii = 0; ii < pBusContext->SignalSemListSize; ii++) { -+ pSignal = AllocateSignal(); -+ if (pSignal == NULL) { -+ break; -+ } -+ /* freeing it adds it to the list */ -+ FreeSignal(pSignal); -+ } -+ -+ DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: AllocateBusResources\n")); -+ return SDIO_STATUS_SUCCESS; -+} -+ -+ -+/* cleanup bus resources */ -+static void CleanUpBusResources(void) -+{ -+ PSDLIST pItem; -+ PSDREQUEST pReq; -+ PSIGNAL_ITEM pSignal; -+ -+ DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: CleanUpBusResources (CR:%d,MR:%d)(CS:%d,MS:%d) \n", -+ pBusContext->CurrentRequestAllocations,pBusContext->MaxRequestAllocations, -+ pBusContext->CurrentSignalAllocations,pBusContext->MaxSignalAllocations)); -+ -+ while(1) { -+ pItem = SDListRemoveItemFromHead(&pBusContext->RequestList); -+ if (NULL == pItem) { -+ break; -+ } -+ /* free the request */ -+ pReq = CONTAINING_STRUCT(pItem, SDREQUEST, SDList); -+ if (pReq->InternalFlags & SDBD_ALLOC_IRQ_SAFE_MASK) { -+ KernelFreeIrqSafe(pReq); -+ } else { -+ KernelFree(pReq); -+ } -+ pBusContext->CurrentRequestAllocations--; -+ } -+ -+ if (pBusContext->CurrentRequestAllocations != 0) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Request allocations are not ZERO! (CR:%d)\n", -+ pBusContext->CurrentRequestAllocations)); -+ } -+ -+ while(1) { -+ pItem = SDListRemoveItemFromHead(&pBusContext->SignalList); -+ if (NULL == pItem) { -+ break; -+ } -+ pSignal = CONTAINING_STRUCT(pItem, SIGNAL_ITEM, SDList); -+ DestroySignal(pSignal); -+ pBusContext->CurrentSignalAllocations--; -+ } -+ -+ if (pBusContext->CurrentSignalAllocations != 0) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Signal allocations are not ZERO! (CR:%d)\n", -+ pBusContext->CurrentRequestAllocations)); -+ } -+ -+ DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: CleanUpBusResources\n")); -+} -+ -+ -+/* free a request to the lookaside list */ -+void FreeRequest(PSDREQUEST pReq) -+{ -+ SDIO_STATUS status; -+ CT_DECLARE_IRQ_SYNC_CONTEXT(); -+ -+ status = CriticalSectionAcquireSyncIrq(&pBusContext->RequestListCritSection); -+ /* protect request list */ -+ if (!SDIO_SUCCESS(status)) { -+ return; -+ } -+ -+ if ((pBusContext->CurrentRequestAllocations <= pBusContext->MaxRequestAllocations) || -+ !(pReq->InternalFlags & SDBD_ALLOC_IRQ_SAFE_MASK)) { -+ /* add it to the list */ -+ SDListAdd(&pBusContext->RequestList, &pReq->SDList); -+ /* we will hold onto this one */ -+ pReq = NULL; -+ } else { -+ /* decrement count */ -+ pBusContext->CurrentRequestAllocations--; -+ } -+ -+ status = CriticalSectionReleaseSyncIrq(&pBusContext->RequestListCritSection); -+ -+ if (pReq != NULL) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Free Request allocation (CR:%d,MR:%d)\n", -+ pBusContext->CurrentRequestAllocations,pBusContext->MaxRequestAllocations)); -+ if (pReq->InternalFlags & SDBD_ALLOC_IRQ_SAFE_MASK) { -+ KernelFreeIrqSafe(pReq); -+ } else { -+ /* we should never free the ones that were normally allocated */ -+ DBG_ASSERT(FALSE); -+ } -+ } -+} -+ -+/* allocate a request from the lookaside list */ -+PSDREQUEST AllocateRequest(void) -+{ -+ PSDLIST pItem; -+ SDIO_STATUS status; -+ PSDREQUEST pReq = NULL; -+ ATOMIC_FLAGS internalflags; -+ CT_DECLARE_IRQ_SYNC_CONTEXT(); -+ -+ -+ status = CriticalSectionAcquireSyncIrq(&pBusContext->RequestListCritSection); -+ -+ if (!SDIO_SUCCESS(status)) { -+ return NULL; -+ } -+ -+ if (pBusContext->InitMask & RESOURCE_INIT) { -+ /* check the list, we are now running... */ -+ pItem = SDListRemoveItemFromHead(&pBusContext->RequestList); -+ } else { -+ /* we are loading the list with requests at initialization */ -+ pItem = NULL; -+ } -+ status = CriticalSectionReleaseSyncIrq(&pBusContext->RequestListCritSection); -+ -+ if (pItem != NULL) { -+ pReq = CONTAINING_STRUCT(pItem, SDREQUEST, SDList); -+ } else { -+ if (pBusContext->InitMask & RESOURCE_INIT) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Request List empty..allocating new one (irq-safe) (CR:%d,MR:%d)\n", -+ pBusContext->CurrentRequestAllocations,pBusContext->MaxRequestAllocations)); -+ /* the resource list was already allocated, we must be running now. -+ * at run-time, we allocate using the safe IRQ */ -+ pReq = (PSDREQUEST)KernelAllocIrqSafe(sizeof(SDREQUEST)); -+ /* mark that this one was created using IRQ safe allocation */ -+ internalflags = SDBD_ALLOC_IRQ_SAFE_MASK; -+ } else { -+ /* use the normal allocation since we are called at initialization */ -+ pReq = (PSDREQUEST)KernelAlloc(sizeof(SDREQUEST)); -+ internalflags = 0; -+ } -+ -+ if (pReq != NULL) { -+ pReq->InternalFlags = internalflags; -+ /* keep track of allocations */ -+ status = CriticalSectionAcquireSyncIrq(&pBusContext->RequestListCritSection); -+ pBusContext->CurrentRequestAllocations++; -+ status = CriticalSectionReleaseSyncIrq(&pBusContext->RequestListCritSection); -+ } -+ } -+ -+ -+ if (pReq != NULL) { -+ /* preserve internal flags */ -+ internalflags = pReq->InternalFlags; -+ ZERO_POBJECT(pReq); -+ pReq->InternalFlags = internalflags; -+ } -+ -+ return pReq; -+} -+ -+void DestroySignal(PSIGNAL_ITEM pSignal) -+{ -+ SignalDelete(&pSignal->Signal); -+ KernelFree(pSignal); -+} -+ -+PSIGNAL_ITEM BuildSignal(void) -+{ -+ PSIGNAL_ITEM pSignal; -+ -+ pSignal = (PSIGNAL_ITEM)KernelAlloc(sizeof(SIGNAL_ITEM)); -+ if (pSignal != NULL) { -+ /* initialize signal */ -+ if (!SDIO_SUCCESS(SignalInitialize(&pSignal->Signal))) { -+ KernelFree(pSignal); -+ pSignal = NULL; -+ } -+ } -+ return pSignal; -+} -+/* free a signal*/ -+void FreeSignal(PSIGNAL_ITEM pSignal) -+{ -+ SDIO_STATUS status; -+ CT_DECLARE_IRQ_SYNC_CONTEXT(); -+ -+ status = CriticalSectionAcquireSyncIrq(&pBusContext->RequestListCritSection); -+ -+ if (!SDIO_SUCCESS(status)) { -+ return; -+ } -+ -+ if (pBusContext->CurrentSignalAllocations <= pBusContext->MaxSignalAllocations) { -+ /* add it to the list */ -+ SDListAdd(&pBusContext->SignalList, &pSignal->SDList); -+ /* flag that we are holding onto it */ -+ pSignal = NULL; -+ } else { -+ /* decrement count */ -+ pBusContext->CurrentSignalAllocations--; -+ } -+ -+ status = CriticalSectionReleaseSyncIrq(&pBusContext->RequestListCritSection); -+ -+ if (pSignal != NULL) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Free signal allocation (CS:%d,MS:%d)\n", -+ pBusContext->CurrentSignalAllocations,pBusContext->MaxSignalAllocations)); -+ DestroySignal(pSignal); -+ } -+} -+ -+/* allocate a signal from the list */ -+PSIGNAL_ITEM AllocateSignal(void) -+{ -+ PSDLIST pItem; -+ PSIGNAL_ITEM pSignal; -+ SDIO_STATUS status; -+ CT_DECLARE_IRQ_SYNC_CONTEXT(); -+ -+ status = CriticalSectionAcquireSyncIrq(&pBusContext->RequestListCritSection); -+ -+ if (!SDIO_SUCCESS(status)) { -+ return NULL; -+ } -+ -+ if (pBusContext->InitMask & RESOURCE_INIT) { -+ /* check the list */ -+ pItem = SDListRemoveItemFromHead(&pBusContext->SignalList); -+ } else { -+ /* we are loading the list */ -+ pItem = NULL; -+ } -+ -+ status = CriticalSectionReleaseSyncIrq(&pBusContext->RequestListCritSection); -+ if (pItem != NULL) { -+ /* return the one from the list */ -+ pSignal = CONTAINING_STRUCT(pItem, SIGNAL_ITEM, SDList); -+ } else { -+ if (pBusContext->InitMask & RESOURCE_INIT) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Signal List empty..allocating new one (CS:%d,MS:%d)\n", -+ pBusContext->CurrentSignalAllocations,pBusContext->MaxSignalAllocations)); -+ } -+ /* just allocate one */ -+ pSignal = BuildSignal(); -+ status = CriticalSectionAcquireSyncIrq(&pBusContext->RequestListCritSection); -+ if (pSignal != NULL) { -+ pBusContext->CurrentSignalAllocations++; -+ } -+ status = CriticalSectionReleaseSyncIrq(&pBusContext->RequestListCritSection); -+ } -+ -+ -+ return pSignal; -+} -+ -+/* -+ * Issus Bus Request (exposed to function drivers) -+*/ -+PSDREQUEST IssueAllocRequest(PSDDEVICE pDev) -+{ -+ return AllocateRequest(); -+} -+ -+/* -+ * Free Request (exposed to function drivers) -+*/ -+void IssueFreeRequest(PSDDEVICE pDev, PSDREQUEST pReq) -+{ -+ FreeRequest(pReq); -+} -+ -+/* -+ * Issus Bus Request (exposed to function drivers) -+*/ -+SDIO_STATUS IssueBusRequest(PSDDEVICE pDev, PSDREQUEST pReq) -+{ -+ pReq->pFunction = pDev->pFunction; -+ return IssueRequestToHCD(pDev->pHcd,pReq); -+} -+ -+ -+ /* completion routine for HCD configs, this is synchronized with normal bus requests */ -+static void HcdConfigComplete(PSDREQUEST pReq) -+{ -+ -+ pReq->Status = CALL_HCD_CONFIG((PSDHCD)pReq->pDataBuffer, (PSDCONFIG)pReq->pCompleteContext); -+ -+ SignalSet(&((PSIGNAL_ITEM)pReq->pHcdContext)->Signal); -+} -+ -+SDIO_STATUS SendSyncedHcdBusConfig(PSDDEVICE pDevice, PSDCONFIG pConfig) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ PSDREQUEST pReq = NULL; -+ PSIGNAL_ITEM pSignal = NULL; -+ -+ do { -+ -+ pSignal = AllocateSignal(); -+ if (NULL == pSignal) { -+ status = SDIO_STATUS_NO_RESOURCES; -+ break; -+ } -+ -+ pReq = AllocateRequest(); -+ if (NULL == pReq) { -+ status = SDIO_STATUS_NO_RESOURCES; -+ break; -+ } -+ -+ /* issue pseudo request to sync this with bus requests */ -+ pReq->pCompletion = HcdConfigComplete; -+ pReq->pCompleteContext = pConfig; -+ /* re-use hcd context to store the signal since this request -+ * never actually goes to an HCD */ -+ pReq->pHcdContext = pSignal; -+ pReq->pDataBuffer = pDevice->pHcd; -+ /* flag this as barrier in case it may change the bus mode of the HCD */ -+ pReq->Flags = SDREQ_FLAGS_PSEUDO | SDREQ_FLAGS_BARRIER | SDREQ_FLAGS_TRANS_ASYNC; -+ pReq->Status = SDIO_STATUS_SUCCESS; -+ -+ /* issue request */ -+ status = IssueRequestToHCD(pDevice->pHcd,pReq); -+ -+ } while (FALSE); -+ -+ if (SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Config Request Sync-Op waiting....\n")); -+ status = SignalWait(&pSignal->Signal); -+ -+ if (SDIO_SUCCESS(status)) { -+ /* return the result of the configuration request */ -+ status = pReq->Status; -+ } -+ } -+ -+ /* cleanup */ -+ if (pReq != NULL) { -+ FreeRequest(pReq); -+ } -+ -+ if (pSignal != NULL) { -+ FreeSignal(pSignal); -+ } -+ -+ return status; -+} -+ -+/* -+ * Issus bus Configuration (exposed to function drivers) -+*/ -+SDIO_STATUS IssueBusConfig(PSDDEVICE pDev, PSDCONFIG pConfig) -+{ -+ SDIO_STATUS status; -+ INT cmdLength; -+ UINT8 debugLevel = SDDBG_ERROR; -+ -+ cmdLength = GET_SDCONFIG_CMD_LEN(pConfig); -+ status = SDIO_STATUS_INVALID_PARAMETER; -+ -+ do { -+ /* check buffers and length */ -+ if (IS_SDCONFIG_CMD_GET(pConfig) || IS_SDCONFIG_CMD_PUT(pConfig)) { -+ if ((GET_SDCONFIG_CMD_DATA(PVOID,pConfig) == NULL) || (0 == cmdLength)) { -+ break; -+ } -+ } -+ -+ switch (GET_SDCONFIG_CMD(pConfig)) { -+ case SDCONFIG_FUNC_ACK_IRQ: -+ status = SDFunctionAckInterrupt(pDev); -+ break; -+ case SDCONFIG_FUNC_ENABLE_DISABLE: -+ if (cmdLength < sizeof(SDCONFIG_FUNC_ENABLE_DISABLE_DATA)) { -+ break; -+ } -+ status = SDEnableFunction(pDev, -+ GET_SDCONFIG_CMD_DATA(PSDCONFIG_FUNC_ENABLE_DISABLE_DATA,pConfig)); -+ break; -+ case SDCONFIG_FUNC_UNMASK_IRQ: -+ status = SDMaskUnmaskFunctionIRQ(pDev,FALSE); -+ break; -+ case SDCONFIG_FUNC_MASK_IRQ: -+ status = SDMaskUnmaskFunctionIRQ(pDev,TRUE); -+ break; -+ case SDCONFIG_FUNC_SPI_MODE_DISABLE_CRC: -+ status = SDSPIModeEnableDisableCRC(pDev,FALSE); -+ break; -+ case SDCONFIG_FUNC_SPI_MODE_ENABLE_CRC: -+ status = SDSPIModeEnableDisableCRC(pDev,TRUE); -+ break; -+ case SDCONFIG_FUNC_ALLOC_SLOT_CURRENT: -+ status = SDAllocFreeSlotCurrent(pDev, -+ TRUE, -+ GET_SDCONFIG_CMD_DATA(PSDCONFIG_FUNC_SLOT_CURRENT_DATA,pConfig)); -+ break; -+ case SDCONFIG_FUNC_FREE_SLOT_CURRENT: -+ status = SDAllocFreeSlotCurrent(pDev, FALSE, NULL); -+ break; -+ case SDCONFIG_FUNC_CHANGE_BUS_MODE: -+ -+ status = SetOperationalBusMode(pDev, -+ GET_SDCONFIG_CMD_DATA(PSDCONFIG_BUS_MODE_DATA, -+ pConfig)); -+ break; -+ case SDCONFIG_FUNC_NO_IRQ_PEND_CHECK: -+ status = TryNoIrqPendingCheck(pDev); -+ break; -+ default: -+ -+ if (GET_SDCONFIG_CMD(pConfig) & SDCONFIG_FLAGS_HC_CONFIG) { -+ /* synchronize config requests with busrequests */ -+ status = SendSyncedHcdBusConfig(pDev,pConfig); -+ } else { -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO Bus Driver: IssueBusConfig - unknown command:0x%X \n", -+ GET_SDCONFIG_CMD(pConfig))); -+ status = SDIO_STATUS_INVALID_PARAMETER; -+ } -+ break; -+ } -+ } while(FALSE); -+ -+ if (!SDIO_SUCCESS(status)) { -+ -+ if(status == SDIO_STATUS_FUNC_ENABLE_TIMEOUT ){ /* reduce debug level to avoid timeout error messages */ -+ debugLevel = SDDBG_TRACE; -+ } -+ -+ -+ DBG_PRINT(debugLevel, -+ ("SDIO Bus Driver: IssueBusConfig - Error in command:0x%X, Buffer:0x%X, Length:%d Err:%d\n", -+ GET_SDCONFIG_CMD(pConfig), -+ GET_SDCONFIG_CMD_DATA(INT,pConfig), -+ cmdLength, status)); -+ } -+ return status; -+} -+ -+/* start a request */ -+static INLINE SDIO_STATUS StartHcdRequest(PSDHCD pHcd, PSDREQUEST pReq) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ CT_DECLARE_IRQ_SYNC_CONTEXT(); -+ -+ if ((pReq->pFunction != NULL) && (pReq->pFunction->Flags & SDFUNCTION_FLAG_REMOVING)) { -+ /* this device or function is going away, fail any new requests */ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: StartHcdRequest, fail request 0x%X, device is removing\n", (UINT)pReq)); -+ pReq->Status = SDIO_STATUS_CANCELED; -+ return SDIO_STATUS_SDREQ_QUEUE_FAILED; -+ } -+ -+ status = _AcquireHcdLock(pHcd); -+ -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to acquire HCD request lock: Err:%d\n", status)); -+ pReq->Status = SDIO_STATUS_SDREQ_QUEUE_FAILED; -+ return SDIO_STATUS_SDREQ_QUEUE_FAILED; -+ } -+ -+ if (pReq->Flags & SDREQ_FLAGS_QUEUE_HEAD) { -+ /* caller wants this request queued to the head */ -+ -+ /* a completion routine for a barrier request is called -+ * while the queue is busy. A barrier request can -+ * insert a new request at the head of the queue */ -+ DBG_ASSERT(IsQueueBusy(&pHcd->RequestQueue)); -+ QueueRequestToFront(&pHcd->RequestQueue,pReq); -+ } else { -+ /* insert in queue at tail */ -+ QueueRequest(&pHcd->RequestQueue,pReq); -+ -+ /* is queue busy ? */ -+ if (IsQueueBusy(&pHcd->RequestQueue)) { -+ /* release lock */ -+ status = _ReleaseHcdLock(pHcd); -+ /* controller is busy already, no need to call the hcd */ -+ return SDIO_STATUS_PENDING; -+ } -+ /* mark it as busy */ -+ MarkQueueBusy(&pHcd->RequestQueue); -+ } -+ -+ /* remove item from head and set current request */ -+ SET_CURRENT_REQUEST(pHcd, DequeueRequest(&pHcd->RequestQueue)); -+ if (CHECK_API_VERSION_COMPAT(pHcd,2,6)) { -+ CHECK_HCD_RECURSE(pHcd, pHcd->pCurrentRequest); -+ } -+ /* release lock */ -+ status = _ReleaseHcdLock(pHcd); -+ /* controller was not busy, call into HCD to process current request */ -+ status = CallHcdRequest(pHcd); -+ return status; -+} -+ -+ -+/* used by CMD12,CMD13 to save the original completion routine */ -+#define GET_BD_RSV_REQUEST_COMPLETION(pR) (PSDEQUEST_COMPLETION)(pR)->pBdRsv1 -+#define SET_BD_RSV_REQUEST_COMPLETION(pR,c) (pR)->pBdRsv1 = (PVOID)(c) -+ -+/* used by CMD12 processing to save/restore the original data transfer status */ -+#define GET_BD_RSV_ORIG_STATUS(pR) (SDIO_STATUS)(pR)->pBdRsv2 -+#define SET_BD_RSV_ORIG_STATUS(pR,s) (pR)->pBdRsv2 = (PVOID)(s) -+ -+/* used by CMD13 processing to get/set polling count */ -+#define GET_BD_RSV_STATUS_POLL_COUNT(pR) (INT)(pR)->pBdRsv2 -+#define SET_BD_RSV_STATUS_POLL_COUNT(pR,s) (pR)->pBdRsv2 = (PVOID)(s) -+ -+/* used by CMD55 processing to save the second part of the request */ -+#define GET_BD_RSV_ORIG_REQ(pR) (PSDREQUEST)(pR)->pBdRsv1 -+#define SET_BD_RSV_ORIG_REQ(pR,r) (pR)->pBdRsv1 = (PVOID)(r) -+ -+/* used by all to save HCD */ -+#define GET_BD_RSV_HCD(pR) (PSDHCD)(pR)->pBdRsv3 -+#define SET_BD_RSV_HCD(pR,h) (pR)->pBdRsv3 = (PVOID)(h) -+ -+static void CMD13CompletionBarrier(PSDREQUEST pReq); -+ -+static INLINE void SetupCMD13(PSDHCD pHcd, PSDREQUEST pReq) -+{ -+ pReq->Command = CMD13; -+ /* sequence must be atomic, queue it to the head and flag as a barrier */ -+ pReq->Flags = SDREQ_FLAGS_QUEUE_HEAD | SDREQ_FLAGS_BARRIER | SDREQ_FLAGS_TRANS_ASYNC; -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ pReq->Argument = 0; -+ pReq->Flags |= SDREQ_FLAGS_RESP_R2; -+ } else { -+ pReq->Flags |= SDREQ_FLAGS_RESP_R1; -+ pReq->Argument |= pHcd->CardProperties.RCA << 16; -+ } -+ /* insert completion */ -+ pReq->pCompletion = CMD13CompletionBarrier; -+} -+ -+/* CMD13 (GET STATUS) completion */ -+static void CMD13CompletionBarrier(PSDREQUEST pReq) -+{ -+ PSDEQUEST_COMPLETION pOrigCompletion = GET_BD_RSV_REQUEST_COMPLETION(pReq); -+ PSDHCD pHcd = GET_BD_RSV_HCD(pReq); -+ INT pollingCount = GET_BD_RSV_STATUS_POLL_COUNT(pReq); -+ BOOL doCompletion = TRUE; -+ UINT32 cardStatus; -+ -+ DBG_ASSERT(pOrigCompletion != NULL); -+ DBG_ASSERT(pHcd != NULL); -+ DBG_PRINT(SDIODBG_REQUESTS, ("+SDIO Bus Driver: CMD13CompletionBarrier (cnt:%d) \n",pollingCount)); -+ -+ do { -+ if (!SDIO_SUCCESS(pReq->Status)) { -+ break; -+ } -+ -+ cardStatus = SD_R1_GET_CARD_STATUS(pReq->Response); -+ -+ if (cardStatus & SD_CS_TRANSFER_ERRORS) { -+ DBG_PRINT(SDIODBG_REQUESTS,("SDIO Bus Driver: Card transfer errors : 0x%X \n",cardStatus)); -+ pReq->Status = SDIO_STATUS_PROGRAM_STATUS_ERROR; -+ break; -+ } -+ -+ if (SD_CS_GET_STATE(cardStatus) != SD_CS_STATE_PRG) { -+ DBG_PRINT(SDIODBG_REQUESTS,("SDIO Bus Driver: Card programming done \n")); -+ break; -+ } -+ -+ DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Card still programming.. \n")); -+ pollingCount--; -+ -+ if (pollingCount < 0) { -+ pReq->Status = SDIO_STATUS_PROGRAM_TIMEOUT; -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: card programming timeout!\n")); -+ break; -+ } -+ -+ doCompletion = FALSE; -+ /* keep trying */ -+ SET_BD_RSV_STATUS_POLL_COUNT(pReq, pollingCount); -+ SetupCMD13(pHcd,pReq); -+ DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: re-issuing CMD13 \n")); -+ /* re-issue */ -+ IssueRequestToHCD(pHcd, pReq); -+ -+ } while (FALSE); -+ -+ -+ if (doCompletion) { -+ /* restore original completion routine */ -+ pReq->pCompletion = pOrigCompletion; -+ /* call original completion routine */ -+ pOrigCompletion(pReq); -+ } -+ -+ DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: CMD13CompletionBarrier \n")); -+} -+ -+/* command 13 (GET STATUS) preparation */ -+static void PrepCMD13Barrier(PSDREQUEST pReq) -+{ -+ SDIO_STATUS status = pReq->Status; -+ PSDHCD pHcd = GET_BD_RSV_HCD(pReq); -+ INT pollingCount; -+ PSDEQUEST_COMPLETION pOrigCompletion = GET_BD_RSV_REQUEST_COMPLETION(pReq); -+ -+ DBG_ASSERT(pHcd != NULL); -+ DBG_ASSERT(pOrigCompletion != NULL); -+ -+ DBG_PRINT(SDIODBG_REQUESTS, ("+SDIO Bus Driver: PrepCMD13Barrier \n")); -+ -+ if (SDIO_SUCCESS(status)) { -+ /* re-use the request for CMD13 */ -+ SetupCMD13(pHcd,pReq); -+ /* set polling count to a multiple of the Block count, if the BlockCount was -+ * zeroed by the HCD, then set it to 1X multiplier */ -+ pollingCount = max(pBusContext->CMD13PollingMultiplier, -+ pBusContext->CMD13PollingMultiplier * (INT)pReq->BlockCount); -+ /* initialize count */ -+ SET_BD_RSV_STATUS_POLL_COUNT(pReq, pollingCount); -+ /* re-issue it, we can call IssueRequest here since we are re-using the request */ -+ IssueRequestToHCD(pHcd, pReq); -+ } else { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Request Failure (%d) , CMD13 bypassed.\n",status)); -+ /* call the original completion routine */ -+ pOrigCompletion(pReq); -+ } -+ -+ DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: PrepCMD13Barrier (%d) \n",status)); -+} -+ -+/* CMD12 completion */ -+static void CMD12Completion(PSDREQUEST pReq) -+{ -+ PSDEQUEST_COMPLETION pOrigCompletion = GET_BD_RSV_REQUEST_COMPLETION(pReq); -+ -+ DBG_ASSERT(pOrigCompletion != NULL); -+ -+ DBG_PRINT(SDIODBG_REQUESTS, ("+SDIO Bus Driver: CMD12Completion \n")); -+ -+ /* restore original completion routine */ -+ pReq->pCompletion = pOrigCompletion; -+ -+ if (SDIO_SUCCESS(pReq->Status)) { -+ /* if CMD12 succeeds, we want to return the result of the original -+ * request */ -+ pReq->Status = GET_BD_RSV_ORIG_STATUS(pReq); -+ DBG_PRINT(SDIODBG_REQUESTS, -+ ("SDIO Bus Driver: PrepCMD12Completion original status %d \n",pReq->Status)); -+ } -+ /* call original completion routine */ -+ pOrigCompletion(pReq); -+ -+ DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: CMD12Completion \n")); -+} -+ -+/* CMD12 preparation */ -+static void PrepCMD12Barrier(PSDREQUEST pReq) -+{ -+ -+ SDIO_STATUS status = pReq->Status; -+ PSDHCD pHcd = GET_BD_RSV_HCD(pReq); -+ PSDEQUEST_COMPLETION pOrigCompletion = GET_BD_RSV_REQUEST_COMPLETION(pReq); -+ -+ DBG_ASSERT(pHcd != NULL); -+ DBG_ASSERT(pOrigCompletion != NULL); -+ -+ DBG_PRINT(SDIODBG_REQUESTS, ("+SDIO Bus Driver: PrepCMD12Barrier \n")); -+ -+ if (SDIO_SUCCESS(status) || /* only issue CMD12 on success or specific bus errors */ -+ (SDIO_STATUS_BUS_READ_TIMEOUT == status) || -+ (SDIO_STATUS_BUS_READ_CRC_ERR == status) || -+ (SDIO_STATUS_BUS_WRITE_ERROR == status)) { -+ if (!CHECK_API_VERSION_COMPAT(pHcd,2,6)) { -+ if (!ForceAllRequestsAsync()) { -+ /* clear the call bit as an optimization, note clearing it wholesale here will -+ * allow request processing to recurse one more level */ -+ AtomicTest_Clear(&pHcd->HcdFlags, HCD_REQUEST_CALL_BIT); -+ } -+ } -+ /* re-use the request for CMD12 */ -+ pReq->Command = CMD12; -+ pReq->Argument = 0; -+ -+ /* if the data transfer was successful, check for transfer check */ -+ if (SDIO_SUCCESS(status) && -+ (pReq->Flags & SDREQ_FLAGS_AUTO_TRANSFER_STATUS)) { -+ /* original data request requires a transfer status check, which is another -+ * barrier request */ -+ pReq->Flags = SDREQ_FLAGS_RESP_R1B | SDREQ_FLAGS_QUEUE_HEAD | SDREQ_FLAGS_BARRIER | -+ SDREQ_FLAGS_TRANS_ASYNC; -+ DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: PrepCMD12Barrier , chaining CMD13 \n")); -+ /* switch out completion to send the CMD13 next */ -+ pReq->pCompletion = PrepCMD13Barrier; -+ } else { -+ pReq->Flags = SDREQ_FLAGS_RESP_R1B | SDREQ_FLAGS_QUEUE_HEAD | SDREQ_FLAGS_TRANS_ASYNC; -+ pReq->pCompletion = CMD12Completion; -+ } -+ -+ /* save the original data transfer request status */ -+ SET_BD_RSV_ORIG_STATUS(pReq,status); -+ /* re-issue it, we can call IssueRequest here since we are re-using the request */ -+ IssueRequestToHCD(pHcd, pReq); -+ } else { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Request Failure (%d) , CMD12 bypassed.\n",status)); -+ /* call the original completion routine */ -+ pOrigCompletion(pReq); -+ } -+ -+ DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: PrepCMD12Barrier (%d) \n",status)); -+} -+ -+ -+/* CMD55 barrier - this is a special barrier completion routine, we have to submit the second -+ * part of the command command sequence atomically */ -+static void CMD55CompletionBarrier(PSDREQUEST pReq) -+{ -+ SDIO_STATUS status = pReq->Status; -+ PSDREQUEST pOrigReq = GET_BD_RSV_ORIG_REQ(pReq); -+ PSDHCD pHcd = GET_BD_RSV_HCD(pReq); -+ BOOL doCompletion = FALSE; -+ -+ DBG_ASSERT(pOrigReq != NULL); -+ DBG_ASSERT(pHcd != NULL); -+ -+ DBG_PRINT(SDIODBG_REQUESTS, ("+SDIO Bus Driver: CMD55Completion \n")); -+ -+ do { -+ -+ if (!SDIO_SUCCESS(status)) { -+ /* command 55 failed */ -+ pOrigReq->Status = status; -+ doCompletion = TRUE; -+ break; -+ } -+ -+ if (!(SD_R1_GET_CARD_STATUS(pReq->Response) & SD_CS_APP_CMD)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Card is not accepting CMD55, status:0x%X \n", -+ SD_R1_GET_CARD_STATUS(pReq->Response))); -+ pOrigReq->Status = SDIO_STATUS_INVALID_COMMAND; -+ doCompletion = TRUE; -+ break; -+ } -+ -+ if (!CHECK_API_VERSION_COMPAT(pHcd,2,6)) { -+ if (!ForceAllRequestsAsync()) { -+ AtomicTest_Clear(&pHcd->HcdFlags, HCD_REQUEST_CALL_BIT); -+ } -+ } -+ -+ /* flag the original request to queue to the head */ -+ pOrigReq->Flags |= SDREQ_FLAGS_QUEUE_HEAD; -+ /* submit original request, we cannot call IssueRequestHCD() here because the -+ * original request has already gone through IssueRequestHCD() already */ -+ status = StartHcdRequest(pHcd, pOrigReq); -+ -+ if (SDIO_STATUS_PENDING == status) { -+ break; -+ } -+ -+ pOrigReq->Status = status; -+ -+ if (SDIO_STATUS_SDREQ_QUEUE_FAILED == status) { -+ /* never made it to the queue */ -+ doCompletion = TRUE; -+ break; -+ } -+ -+ /* request completed in-line */ -+ _SDIO_HandleHcdEvent(pHcd, EVENT_HCD_TRANSFER_DONE); -+ -+ } while (FALSE); -+ -+ if (doCompletion) { -+ DoRequestCompletion(pOrigReq, pHcd); -+ } -+ -+ /* free the CMD55 request */ -+ FreeRequest(pReq); -+ -+ DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: CMD55Completion \n")); -+} -+ -+ -+/* synch completion routine */ -+static void SynchCompletion(PSDREQUEST pRequest) -+{ -+ PSIGNAL_ITEM pSignal; -+ -+ pSignal = (PSIGNAL_ITEM)pRequest->pCompleteContext; -+ DBG_ASSERT(pSignal != NULL); -+ if (!SDIO_SUCCESS(SignalSet(&pSignal->Signal))) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: SynchCompletion - signal failed \n")); -+ } -+ -+} -+ -+/* -+ * Issue a request to the host controller -+ * -+ * -+ * The following flags are handled internally by the bus driver to guarantee atomicity. -+ * -+ * SDREQ_FLAGS_APP_CMD - SD Extended commands requiring CMD55 to precede the actual command -+ * SDREQ_FLAGS_AUTO_CMD12 - Memory Card Data transfer needs CMD12 to stop transfer -+ * (multi-block reads/writes) -+ * SDREQ_FLAGS_AUTO_TRANSFER_STATUS - Memory card data transfer needs transfer status polling -+ * using CMD13 -+ * -+ * These request flags require additional commands prepended or appended to the original command -+ * -+ * The order of command execution : -+ * -+ * Order Condition Command Issued -+ * ------------------------------------------------------------- -+ * 1. If APP_CMD CMD55 issued. -+ * 2. Always Caller command issued. -+ * 3. If AUTO_CMD12 CMD12 issued. -+ * 4. If AUTO_TRANSFER_STATUS CMD13 issued until card programming is complete -+*/ -+SDIO_STATUS IssueRequestToHCD(PSDHCD pHcd, PSDREQUEST pReq) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ PSIGNAL_ITEM pSignal = NULL; -+ BOOL handleFailedReqSubmit = FALSE; -+ -+ CLEAR_INTERNAL_REQ_FLAGS(pReq); -+ -+ do { -+ /* mark request in-use */ -+ ATOMIC_FLAGS internal = AtomicTest_Set(&pReq->InternalFlags, SDBD_PENDING); -+ if (internal & (1<<SDBD_PENDING)) { -+ DBG_ASSERT_WITH_MSG(FALSE, -+ "SDIO Bus Driver: IssueRequestToHCD - request already in use \n"); -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Request already in use: 0x%X",(INT)pReq)); -+ } -+ -+ if (!(pReq->Flags & SDREQ_FLAGS_TRANS_ASYNC)) { -+ /* caller wants synchronous operation, insert our completion routine */ -+ pReq->pCompletion = SynchCompletion; -+ pSignal = AllocateSignal(); -+ if (NULL == pSignal) { -+ status = SDIO_STATUS_NO_RESOURCES; -+ pReq->Status = SDIO_STATUS_NO_RESOURCES; -+ handleFailedReqSubmit = TRUE; -+ /* no need to continue */ -+ break; -+ } -+ pReq->pCompleteContext = (PVOID)pSignal; -+ } -+ -+ if ((pReq->Flags & SDREQ_FLAGS_AUTO_CMD12) && -+ !(pHcd->Attributes & SDHCD_ATTRIB_AUTO_CMD12) && -+ !(IS_HCD_BUS_MODE_SPI(pHcd) && IS_SDREQ_WRITE_DATA(pReq->Flags))) { -+ DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Auto CMD12 on Request:0x%08X \n",(INT)pReq)); -+ /* caller wants CMD12 auto-issued and the HCD does not support it */ -+ /* setup caller's request as a barrier and replace their completion routine */ -+ pReq->Flags |= SDREQ_FLAGS_BARRIER; -+ /* take off the flag, since the BD will be issuing it */ -+ pReq->Flags &= ~SDREQ_FLAGS_AUTO_CMD12; -+ /* save original completion */ -+ SET_BD_RSV_REQUEST_COMPLETION(pReq,pReq->pCompletion); -+ /* save the HCD we are on */ -+ SET_BD_RSV_HCD(pReq,pHcd); -+ /* use completion for preping CMD12 */ -+ pReq->pCompletion = PrepCMD12Barrier; -+ } -+ -+ if (pReq->Flags & SDREQ_FLAGS_AUTO_TRANSFER_STATUS) { -+ /* caller wants transfer status checked. If a CMD12 -+ * barrier request has been setup we let the CMD12 completion take care -+ * of setting up the transfer check */ -+ if (pReq->pCompletion != PrepCMD12Barrier) { -+ /* make CMD13 prep a barrier */ -+ pReq->Flags |= SDREQ_FLAGS_BARRIER; -+ /* save original completion */ -+ SET_BD_RSV_REQUEST_COMPLETION(pReq,pReq->pCompletion); -+ /* save the HCD we are on */ -+ SET_BD_RSV_HCD(pReq,pHcd); -+ /* use completion for preping CMD13 */ -+ pReq->pCompletion = PrepCMD13Barrier; -+ } -+ } -+ -+ /* check app command, the two command sequence must be handled atomically */ -+ if (pReq->Flags & SDREQ_FLAGS_APP_CMD) { -+ PSDREQUEST pCmd55; -+ /* allocate request to handle initial CMD55 command */ -+ pCmd55 = AllocateRequest(); -+ if (NULL == pCmd55) { -+ status = SDIO_STATUS_NO_RESOURCES; -+ pReq->Status = SDIO_STATUS_NO_RESOURCES; -+ /* complete the caller's request with error */ -+ handleFailedReqSubmit = TRUE; -+ /* no need to continue */ -+ break; -+ } -+ /* first submit CMD55 */ -+ /* set RCA */ -+ pCmd55->Argument = pHcd->CardProperties.RCA << 16; -+ /* mark as a barrier request */ -+ pCmd55->Flags = SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_BARRIER | SDREQ_FLAGS_TRANS_ASYNC; -+ pCmd55->Command = CMD55; -+ /* call our barrier completion routine when done */ -+ pCmd55->pCompletion = CMD55CompletionBarrier; -+ /* save request and target HCD */ -+ SET_BD_RSV_ORIG_REQ(pCmd55,pReq); -+ SET_BD_RSV_HCD(pCmd55,pHcd); -+ /* recursively start the CMD55 request, since the CMD55 is a barrier -+ * request, it's completion routine will submit the actual request -+ * atomically */ -+ status = IssueRequestToHCD(pHcd, pCmd55); -+ -+ } else { -+ /* start the normal request */ -+ status = StartHcdRequest(pHcd,pReq); -+ } -+ -+ -+ if (SDIO_STATUS_SDREQ_QUEUE_FAILED == status) { -+ handleFailedReqSubmit = TRUE; -+ /* no need to continue, clean up at the end */ -+ break; -+ } -+ -+ /* at this point, the request was either queued or was processed by the -+ * HCD */ -+ -+ DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: HCD returned status:%d on request: 0x%X, (CMD:%d) \n", -+ status, (INT)pReq, pReq->Command)); -+ -+ if (status != SDIO_STATUS_PENDING) { -+ /* the HCD completed the request within the HCD request callback, -+ * check and see if this is a synchronous request */ -+ if (pSignal != NULL) { -+ /* it was synchronous */ -+ DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Sync-Op signal wait bypassed \n")); -+ /* NULL out completion info, there's no need to -+ * signal the semaphore */ -+ pReq->pCompletion = NULL; -+ -+ } else { -+ DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Async operation completed in-line \n")); -+ /* this was an async call, always return pending */ -+ status = SDIO_STATUS_PENDING; -+ } -+ /* process this completed transfer on behalf of the HCD */ -+ _SDIO_HandleHcdEvent(pHcd, EVENT_HCD_TRANSFER_DONE); -+ -+ /* done processing */ -+ break; -+ } -+ /* I/O is now pending, could be sync or async */ -+ /* check for synch op */ -+ if (pSignal != NULL) { -+ /* wait for completion */ -+ DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Sync-Op signal waiting....\n")); -+ /* this is not interruptable, as the HCD must complete it. */ -+ status = SignalWait(&pSignal->Signal); -+ /* don't need the signal anymore */ -+ FreeSignal(pSignal); -+ pSignal = NULL; -+ -+ /* note: it is safe to touch pReq since we own -+ * the completion routine for synch transfers */ -+ -+ /* check signal wait status */ -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO Bus Driver - IssueRequestToHCD: Synch transfer - signal wait failed, cancelling req 0X%X\n", -+ (UINT)pReq)); -+ pReq->Status = SDIO_STATUS_CANCELED; -+ status = SDIO_STATUS_CANCELED; -+ break; -+ } -+ DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Sync-Op woke up\n")); -+ /* return the completion status of the request */ -+ status = pReq->Status; -+ } else { -+ DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Async operation Pending \n")); -+ } -+ -+ } while (FALSE); -+ -+ /* see if we need to clean up failed submissions */ -+ if (handleFailedReqSubmit) { -+ /* make sure this is cleared */ -+ AtomicTest_Clear(&pReq->InternalFlags, SDBD_PENDING); -+ /* the request processing failed before it was submitted to the HCD */ -+ /* note: since it never made it to the queue we can touch pReq */ -+ if (pReq->Flags & SDREQ_FLAGS_TRANS_ASYNC) { -+ /* for ASYNC requests, we need to call the completion routine */ -+ DoRequestCompletion(pReq, pHcd); -+ /* return pending for all ASYNC requests */ -+ status = SDIO_STATUS_PENDING; -+ } -+ } -+ -+ /* check if we need to clean up the signal */ -+ if (pSignal != NULL) { -+ /* make sure this is freed */ -+ FreeSignal(pSignal); -+ } -+ /* return status */ -+ return status; -+} -+ -+/* documentation for configuration requests */ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Enable or Disable the SDIO Function -+ -+ @function name: SDCONFIG_FUNC_ENABLE_DISABLE -+ @prototype: SDCONFIG_FUNC_ENABLE_DISABLE -+ @category: PD_Reference -+ -+ @input: SDCONFIG_FUNC_ENABLE_DISABLE_DATA - Enable Data structure -+ -+ @output: none -+ -+ @return: SDIO Status -+ -+ @notes: This command code is used in the SDLIB_IssueConfig() API. The command -+ uses the SDCONFIG_FUNC_ENABLE_DISABLE_DATA structure. The caller must set the -+ EnableFlags and specify the TimeOut value in milliseconds. The TimeOut -+ value is used for polling the I/O ready bit. This command returns a status -+ of SDIO_STATUS_FUNC_ENABLE_TIMEOUT if the ready bit was not set/cleared -+ by the card within the timeout period. -+ -+ @example: Example of enabling an I/O function: -+ fData.EnableFlags = SDCONFIG_ENABLE_FUNC; -+ fData.TimeOut = 500; -+ status = SDLIB_IssueConfig(pInstance->pDevice, -+ SDCONFIG_FUNC_ENABLE_DISABLE, -+ &fData, -+ sizeof(fData)); -+ -+ @see also: SDLIB_IssueConfig -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+ -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Unmask the function's IRQ -+ -+ @function name: SDCONFIG_FUNC_UNMASK_IRQ -+ @prototype: SDCONFIG_FUNC_UNMASK_IRQ -+ @category: PD_Reference -+ -+ @input: none -+ -+ @output: none -+ -+ @return: SDIO Status -+ -+ @notes: This command code is used in the SDLIB_IssueConfig() API. The command -+ unmasks the IRQ for the I/O function. This request sets the function's -+ interrupt enable bit in the INTENABLE register in the -+ common register space. -+ -+ @example: Example of unmasking interrupt : -+ status = SDLIB_IssueConfig(pInstance->pDevice, -+ SDCONFIG_FUNC_UNMASK_IRQ, -+ NULL, -+ 0); -+ -+ @see also: SDCONFIG_FUNC_MASK_IRQ -+ @see also: SDLIB_IssueConfig -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Mask the function's IRQ -+ -+ @function name: SDCONFIG_FUNC_MASK_IRQ -+ @prototype: SDCONFIG_FUNC_MASK_IRQ -+ @category: PD_Reference -+ -+ @input: none -+ -+ @output: none -+ -+ @return: SDIO Status -+ -+ @notes: This command code is used in the SDLIB_IssueConfig() API. The command -+ masks the IRQ for the I/O function. -+ -+ @example: Example of unmasking interrupt : -+ status = SDLIB_IssueConfig(pInstance->pDevice, -+ SDCONFIG_FUNC_MASK_IRQ, -+ NULL, -+ 0); -+ -+ @see also: SDCONFIG_FUNC_UNMASK_IRQ -+ @see also: SDLIB_IssueConfig -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Acknowledge that the function's IRQ has been handled -+ -+ @function name: SDCONFIG_FUNC_ACK_IRQ -+ @prototype: SDCONFIG_FUNC_ACK_IRQ -+ @category: PD_Reference -+ -+ @input: none -+ -+ @output: none -+ -+ @return: SDIO Status -+ -+ @notes: This command code is used in the SDLIB_IssueConfig() API. The command -+ indicates to the bus driver that the function driver has handled the -+ interrupt. The bus driver will notify the host controller to unmask the -+ interrupt source. SDIO interrupts are level triggered and are masked at the -+ host controller level until all function drivers have indicated that they -+ have handled their respective interrupt. This command can be issued in either -+ the IRQ handler or asynchronous IRQ handler. -+ -+ @example: Example of acknowledging an interrupt : -+ status = SDLIB_IssueConfig(pInstance->pDevice, -+ SDCONFIG_FUNC_ACK_IRQ, -+ NULL, -+ 0); -+ -+ @see also: SDLIB_IssueConfig -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Disable SD/MMC/SDIO card CRC checking. -+ -+ @function name: SDCONFIG_FUNC_SPI_MODE_DISABLE_CRC -+ @prototype: SDCONFIG_FUNC_SPI_MODE_DISABLE_CRC -+ @category: PD_Reference -+ -+ @input: none -+ -+ @output: none -+ -+ @return: SDIO Status -+ -+ @notes: This command code is used in the SDLIB_IssueConfig() API. The command -+ issues CMD59 to disable SPI-CRC checking and requests the host controller -+ driver to stop checking the CRC. This is typically used in systems where -+ CRC checking is not required and performance is improved if the CRC checking -+ is ommitted (i.e. SPI implementations without hardware CRC support). -+ -+ @example: Example of disabling SPI CRC checking: -+ status = SDLIB_IssueConfig(pInstance->pDevice, -+ SDCONFIG_FUNC_SPI_MODE_DISABLE_CRC, -+ NULL, -+ 0); -+ -+ @see also: SDCONFIG_FUNC_SPI_MODE_ENABLE_CRC -+ @see also: SDLIB_IssueConfig -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Enable SD/MMC/SDIO card CRC checking. -+ -+ @function name: SDCONFIG_FUNC_SPI_MODE_ENABLE_CRC -+ @prototype: SDCONFIG_FUNC_SPI_MODE_ENABLE_CRC -+ @category: PD_Reference -+ -+ @input: none -+ -+ @output: none -+ -+ @return: SDIO Status -+ -+ @notes: This command code is used in the SDLIB_IssueConfig() API. The command -+ issues CMD59 to enable SPI-CRC checking and requests the host controller -+ driver to generate valid CRCs for commands and data as well as -+ check the CRC in responses and incomming data blocks. -+ -+ @example: Example of enabling SPI CRC checking: -+ status = SDLIB_IssueConfig(pInstance->pDevice, -+ SDCONFIG_FUNC_SPI_MODE_ENABLE_CRC, -+ NULL, -+ 0); -+ -+ @see also: SDCONFIG_FUNC_SPI_MODE_DISABLE_CRC -+ @see also: SDLIB_IssueConfig -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Allocate slot current for a card function. -+ -+ @function name: SDCONFIG_FUNC_ALLOC_SLOT_CURRENT -+ @prototype: SDCONFIG_FUNC_ALLOC_SLOT_CURRENT -+ @category: PD_Reference -+ -+ @input: SDCONFIG_FUNC_SLOT_CURRENT_DATA -+ -+ @output: SDCONFIG_FUNC_SLOT_CURRENT_DATA -+ -+ @return: SDIO Status -+ -+ @notes: This command code is used in the SDLIB_IssueConfig() API. The command -+ requests an allocation of slot current to satisfy the power requirements -+ of the function. The command uses the SDCONFIG_FUNC_SLOT_CURRENT_DATA -+ data structure to pass the required current in mA. Slot current allocation -+ is not cummulative and this command should only be issued once by each function -+ driver with the worse case slot current usage. -+ The command returns SDIO_STATUS_NO_RESOURCES if the -+ requirement cannot be met by the host hardware. The SlotCurrent field will -+ contain the remaining current available to the slot. The slot current should -+ be allocated before the function is enabled using SDCONFIG_FUNC_ENABLE_DISABLE. -+ When a function driver is unloaded it should free the slot current allocation -+ by using the SDCONFIG_FUNC_FREE_SLOT_CURRENT command. -+ -+ @example: Example of allocating slot current: -+ slotCurrent.SlotCurrent = 150; // 150 mA -+ status = SDLIB_IssueConfig(pInstance->pDevice, -+ SDCONFIG_FUNC_ALLOC_SLOT_CURRENT, -+ &slotCurrent, -+ sizeof(slotCurrent)); -+ -+ -+ @see also: SDCONFIG_FUNC_FREE_SLOT_CURRENT -+ @see also: SDLIB_IssueConfig -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Free slot current for a card function. -+ -+ @function name: SDCONFIG_FUNC_FREE_SLOT_CURRENT -+ @prototype: SDCONFIG_FUNC_FREE_SLOT_CURRENT -+ @category: PD_Reference -+ -+ @input: none -+ -+ @output: none -+ -+ @return: SDIO Status -+ -+ @notes: This command code is used in the SDLIB_IssueConfig() API. The command -+ frees the allocated current for a card function. This command should be -+ issued only once (per function) and only after an allocation was successfully made. -+ -+ @example: Example of freeing slot current: -+ status = SDLIB_IssueConfig(pInstance->pDevice, -+ SDCONFIG_FUNC_FREE_SLOT_CURRENT, -+ NULL, -+ 0); -+ -+ @see also: SDCONFIG_FUNC_ALLOC_SLOT_CURRENT -+ @see also: SDLIB_IssueConfig -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Set the bus mode for the SD/SDIO card. -+ -+ @function name: SDCONFIG_FUNC_CHANGE_BUS_MODE -+ @prototype: SDCONFIG_FUNC_CHANGE_BUS_MODE -+ @category: PD_Reference -+ -+ @input: none -+ -+ @output: none -+ -+ @return: SDIO Status -+ -+ @notes: This command code is used in the SDLIB_IssueConfig() API. The command -+ alters the card's bus mode (width and clock rate) to a driver specified -+ value. The driver must read the current bus mode flags, modify if necessary -+ and pass the value in the SDCONFIG_BUS_MODE_DATA structure. -+ If the bus width is changed (1 or 4 bit) the caller must adjust the mode flags -+ for the new width. Cards cannot be switched between 1/4 bit and SPI mode. -+ Switching to or from SPI mode requires a power cycle. Adjustments to the clock -+ rate is immediate on the next bus transaction. The actual clock rate value is -+ limited by the host controller and is reported in the ClockRate field when the -+ command completes successfully. -+ The bus mode change is card wide and may affect other SDIO functions on -+ multi-function cards. Use this feature with caution. This feature should NOT be -+ used to dynamically control clock rates during runtime and should only be used -+ at card initialization. Changing the bus mode must be done with SDIO function -+ interrupts masked. -+ This request can block and must only be called from a schedulable context. -+ -+ @example: Example of changing the clock rate: -+ SDCONFIG_BUS_MODE_DATA busSettings; -+ ZERO_OBJECT(busSettings); -+ // get current bus flags and keep the same bus width -+ busSettings.BusModeFlags = SDDEVICE_GET_BUSMODE_FLAGS(pInstance->pDevice); -+ busSettings.ClockRate = 8000000; // adjust clock to 8 Mhz -+ // issue config request to override clock rate -+ status = SDLIB_IssueConfig(pInstance->pDevice, -+ SDCONFIG_FUNC_CHANGE_BUS_MODE, -+ &busSettings, -+ sizeof(SDCONFIG_BUS_MODE_DATA)); -+ -+ @see also: SDDEVICE_GET_BUSMODE_FLAGS -+ @see also: SDLIB_IssueConfig -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get the debug level of the underlying host controller driver. -+ -+ @function name: SDCONFIG_GET_HCD_DEBUG -+ @prototype: SDCONFIG_GET_HCD_DEBUG -+ @category: PD_Reference -+ -+ @input: none -+ -+ @output: CT_DEBUG_LEVEL -+ -+ @return: SDIO Status -+ -+ @notes: This command code is used in the SDLIB_IssueConfig() API. The command -+ requests the current debug level of the HCD driver. This API is useful for -+ saving the current debug level of the HCD prior to issuing SDCONFIG_SET_HCD_DEBUG -+ in order to increase the verbosity of the HCD. This API should be used only for -+ debugging purposes. If multiple functions attempt to save and set the HCD debug -+ level simultanously, the final debug level will be unknown. Not all HCDs support -+ this command. -+ -+ @example: Example of saving the debug level: -+ CT_DEBUG_LEVEL savedDebug; -+ status = SDLIB_IssueConfig(pInstance->pDevice, -+ SDCONFIG_GET_HCD_DEBUG, -+ &savedDebug, -+ sizeof(savedDebug)); -+ -+ @see also: SDCONFIG_SET_HCD_DEBUG -+ @see also: SDLIB_IssueConfig -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Set the debug level of the underlying host controller driver. -+ -+ @function name: SDCONFIG_SET_HCD_DEBUG -+ @prototype: SDCONFIG_SET_HCD_DEBUG -+ @category: PD_Reference -+ -+ @input: CT_DEBUG_LEVEL -+ -+ @output: none -+ -+ @return: SDIO Status -+ -+ @notes: This command code is used in the SDLIB_IssueConfig() API. The command -+ sets the current debug level of the HCD driver. This API is useful for -+ setting the debug level of the HCD programatically for debugging purposes. -+ If multiple functions attempt to save and set the HCD debug -+ level simultanously, the final debug level will be unknown. Not all HCDs support -+ this request. -+ -+ @example: Example of setting the debug level: -+ CT_DEBUG_LEVEL setDebug = 15; -+ status = SDLIB_IssueConfig(pInstance->pDevice, -+ SDCONFIG_GET_HCD_DEBUG, -+ &setDebug, -+ sizeof(setDebug)); -+ -+ @see also: SDCONFIG_GET_HCD_DEBUG -+ @see also: SDLIB_IssueConfig -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Instruct the bus driver to not check the SDIO card interrupt pending -+ register on card interrupts, if possible. -+ -+ @function name: SDCONFIG_FUNC_NO_IRQ_PEND_CHECK -+ @prototype: SDCONFIG_FUNC_NO_IRQ_PEND_CHECK -+ @category: PD_Reference -+ -+ @input: none -+ -+ @output: none -+ -+ @return: SDIO Status -+ -+ @notes: This command code is used in the SDLIB_IssueConfig() API. The command instructs the -+ bus driver to skip checking the card interrupt pending register on each card -+ interrupt. The bus driver will assume the function is interrupting and immediately start -+ the interrupt processing stage. This option is only valid for single function cards. -+ The bus driver will reject the command for a card with more than 1 function. -+ For single function cards, this can improve interrupt response time. -+ -+ @example: Example of skipping IRQ pending checks: -+ -+ status = SDLIB_IssueConfig(pInstance->pDevice, -+ SDCONFIG_FUNC_NO_IRQ_PEND_CHECK, -+ NULL, -+ 0); -+ -+ @see also: SDLIB_IssueConfig -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -diff --git a/drivers/sdio/stack/busdriver/sdio_bus_events.c b/drivers/sdio/stack/busdriver/sdio_bus_events.c -new file mode 100644 -index 0000000..5b3148d ---- /dev/null -+++ b/drivers/sdio/stack/busdriver/sdio_bus_events.c -@@ -0,0 +1,1040 @@ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+@file: sdio_bus_events.c -+ -+@abstract: OS independent bus driver support -+ -+#notes: this file contains various event handlers and helpers -+ -+@notice: Copyright (c), 2004-2006 Atheros Communications, Inc. -+ -+ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * Software distributed under the License is distributed on an "AS -+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -+ * implied. See the License for the specific language governing -+ * rights and limitations under the License. -+ * -+ * Portions of this code were developed with information supplied from the -+ * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply: -+ * -+ * The following conditions apply to the release of the SD simplified specification (�Simplified -+ * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete -+ * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided -+ * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified -+ * Specification may require a license from the SD Card Association or other third parties. -+ * Disclaimers: -+ * The information contained in the Simplified Specification is presented only as a standard -+ * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any -+ * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for -+ * any damages, any infringements of patents or other right of the SD Card Association or any third -+ * parties, which may result from its use. No license is granted by implication, estoppel or otherwise -+ * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall -+ * be construed as an obligation by the SD Card Association to disclose or distribute any technical -+ * information, know-how or other confidential information to any third party. -+ * -+ * -+ * The initial developers of the original code are Seung Yi and Paul Lever -+ * -+ * sdio@atheros.com -+ * -+ * -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define MODULE_NAME SDBUSDRIVER -+#include <linux/sdio/ctsystem.h> -+#include <linux/sdio/sdio_busdriver.h> -+#include <linux/sdio/sdio_lib.h> -+#include "_busdriver.h" -+#include <linux/sdio/_sdio_defs.h> -+#include <linux/sdio/mmc_defs.h> -+ -+static SDIO_STATUS ScanSlotForCard(PSDHCD pHcd, -+ PBOOL pCardPresent); -+static void GetPendingIrqComplete(PSDREQUEST pReq); -+static void ProcessPendingIrqs(PSDHCD pHcd, UINT8 IntPendingMsk); -+ -+/* -+ * DeviceDetach - tell core a device was removed from a slot -+*/ -+SDIO_STATUS DeviceDetach(PSDHCD pHcd) -+{ -+ SDCONFIG_SDIO_INT_CTRL_DATA irqData; -+ -+ ZERO_OBJECT(irqData); -+ -+ DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: DeviceDetach\n")); -+ /* tell any function drivers we are gone */ -+ RemoveHcdFunctions(pHcd); -+ /* delete the devices associated with this HCD */ -+ DeleteDevices(pHcd); -+ /* check and see if there are any IRQs that were left enabled */ -+ if (pHcd->IrqsEnabled) { -+ irqData.SlotIRQEnable = FALSE; -+ /* turn off IRQ detection in HCD */ -+ _IssueConfig(pHcd,SDCONFIG_SDIO_INT_CTRL,(PVOID)&irqData, sizeof(irqData)); -+ } -+ -+ /* reset hcd state */ -+ ResetHcdState(pHcd); -+ -+ DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: DeviceDetach\n")); -+ return SDIO_STATUS_SUCCESS; -+} -+ -+/* -+ * DeviceAttach - tell core a device was inserted into a slot -+*/ -+SDIO_STATUS DeviceAttach(PSDHCD pHcd) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ PSDDEVICE pDevice = NULL; -+ UINT ii; -+ -+ -+ if (IS_CARD_PRESENT(pHcd)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: DeviceAttach called on occupied slot!\n")); -+ return SDIO_STATUS_ERROR; -+ } -+ -+ DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: DeviceAttach bdctxt:0x%X \n", (UINT32)pBusContext)); -+ -+ if (IS_HCD_RAW(pHcd)) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: RAW HCD (%s) device attach \n",pHcd->pName)); -+ /* this is a raw HCD */ -+ memset(&pHcd->CardProperties,0,sizeof(pHcd->CardProperties)); -+ pHcd->CardProperties.Flags = CARD_RAW; -+ pHcd->CardProperties.IOFnCount = 0; -+ /* for raw HCD, set up minimum parameters -+ * since we cannot determine these values using any standard, use values -+ * reported by the HCD */ -+ /* the operational rate is just the max clock rate reported */ -+ pHcd->CardProperties.OperBusClock = pHcd->MaxClockRate; -+ /* the max bytes per data transfer is just the max bytes per block */ -+ pHcd->CardProperties.OperBlockLenLimit = pHcd->MaxBytesPerBlock; -+ /* if the raw HCD uses blocks to transfer, report the operational size -+ * from the HCD max value */ -+ pHcd->CardProperties.OperBlockCountLimit = pHcd->MaxBlocksPerTrans; -+ /* set the slot preferred voltage */ -+ pHcd->CardProperties.CardVoltage = pHcd->SlotVoltagePreferred; -+ } else { -+ /* initialize this card and get card properties */ -+ if (!SDIO_SUCCESS((status = SDInitializeCard(pHcd)))) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: DeviceAttach, failed to initialize card, %d\n", -+ status)); -+ return status; -+ } -+ } -+ -+ /* check for SD or MMC, this must be done first as the query may involve -+ * de-selecting the card */ -+ do { -+ if (!(pHcd->CardProperties.Flags & (CARD_MMC | CARD_SD | CARD_RAW))) { -+ /* none of these were discovered */ -+ break; -+ } -+ pDevice = AllocateDevice(pHcd); -+ if (NULL == pDevice) { -+ break; -+ } -+ if (pHcd->CardProperties.Flags & CARD_RAW) { -+ /* set function number to 1 for IRQ processing */ -+ SDDEVICE_SET_SDIO_FUNCNO(pDevice,1); -+ } else { -+ /* get the ID info for the SD/MMC Card */ -+ if (!SDIO_SUCCESS((status = SDQuerySDMMCInfo(pDevice)))) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: DeviceAttach, query SDMMC Info failed \n")); -+ FreeDevice(pDevice); -+ break; -+ } -+ } -+ AddDeviceToList(pDevice); -+ /* look for a function driver to handle this card */ -+ ProbeForFunction(pDevice, pHcd); -+ } while (FALSE); -+ -+ /* create a device for each I/O function */ -+ for(ii= 1; ii <= pHcd->CardProperties.IOFnCount; ii++) { -+ pDevice = AllocateDevice(pHcd); -+ if (NULL == pDevice) { -+ break; -+ } -+ /* set the function number */ -+ SDDEVICE_SET_SDIO_FUNCNO(pDevice,ii); -+ /* get the ID info for each I/O function */ -+ if (!SDIO_SUCCESS((status = SDQuerySDIOInfo(pDevice)))) { -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO Bus Driver: DeviceAttach, could not query SDIO Info, funcNo:%d status:%d \n", -+ ii, status)); -+ FreeDevice(pDevice); -+ /* keep loading other functions */ -+ continue; -+ } -+ AddDeviceToList(pDevice); -+ /* look for a function driver to handle this card */ -+ ProbeForFunction(pDevice, pHcd); -+ } -+ -+ -+ DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: DeviceAttach \n")); -+ return status; -+} -+ -+static INLINE void CompleteRequestCheckCancel(PSDHCD pHcd, PSDREQUEST pReqToComplete) -+{ -+ BOOL cancel = FALSE; -+ PSDFUNCTION pFunc = NULL; -+ -+ /* handle cancel of current request */ -+ if (pReqToComplete->Flags & SDREQ_FLAGS_CANCELED) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - _SDIO_HandleHcdEvent: cancelling req 0X%X\n", (UINT)pReqToComplete)); -+ cancel = TRUE; -+ pReqToComplete->Status = SDIO_STATUS_CANCELED; -+ pFunc = pReqToComplete->pFunction; -+ DBG_ASSERT(pFunc != NULL); -+ } -+ -+ DoRequestCompletion(pReqToComplete, pHcd); -+ -+ if (cancel) { -+ SignalSet(&pFunc->CleanupReqSig); -+ } -+} -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Indicate to the SDIO bus driver (core) of an event in the host controller -+ driver. -+ -+ @function name: SDIO_HandleHcdEvent -+ @prototype: SDIO_STATUS SDIO_HandleHcdEvent(PSDHCD pHcd, HCD_EVENT Event) -+ @category: HD_Reference -+ -+ @input: pHcd - the host controller structure that was registered -+ HCD_EVENT - event code -+ -+ @output: none -+ -+ @return: SDIO_STATUS -+ -+ @notes: -+ The host controller driver can indicate asynchronous events by calling this -+ function with an appropriate event code. Refer to the HDK help manual for -+ more information on the event types -+ -+ @example: Example of indicating a card insertion event: -+ SDIO_HandleHcdEvent(&Hcd, EVENT_HCD_ATTACH); -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS _SDIO_HandleHcdEvent(PSDHCD pHcd, HCD_EVENT Event) -+{ -+ PSDREQUEST pReq; -+ PSDREQUEST pReqToComplete = NULL; -+ PSDREQUEST pNextReq = NULL; -+ SDIO_STATUS status; -+ CT_DECLARE_IRQ_SYNC_CONTEXT(); -+ -+ DBG_PRINT(SDIODBG_HCD_EVENTS, ("SDIO Bus Driver: _SDIO_HandleHcdEvent, event type 0x%X, HCD:0x%X\n", -+ Event, (UINT)pHcd)); -+ -+ if (Event == EVENT_HCD_TRANSFER_DONE) { -+ pReq = GET_CURRENT_REQUEST(pHcd); -+ if (NULL == pReq) { -+ DBG_ASSERT(FALSE); -+ return SDIO_STATUS_ERROR; -+ } -+ -+ status = _AcquireHcdLock(pHcd); -+ if (SDIO_SUCCESS(status)) { -+ /* null out the current request */ -+ SET_CURRENT_REQUEST(pHcd, NULL); -+ status = _ReleaseHcdLock(pHcd); -+ } else { -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO Bus Driver: SDIO_HandleHcdEvent Failed to acquire HCD lock \n")); -+ return SDIO_STATUS_ERROR; -+ } -+ -+ /* note: the queue is still marked busy to prevent other threads/tasks from starting -+ * new requests while we are handling completion , some completed requests are -+ * marked as barrier requests which must be handled atomically */ -+ -+ status = pReq->Status; -+ DBG_PRINT(SDIODBG_REQUESTS, -+ ("+SDIO Bus Driver: Handling Transfer Done (CMD:%d, Status:%d) from HCD:0x%08X \n", -+ pReq->Command, status, (INT)pHcd)); -+ /* check SPI mode conversion */ -+ if (IS_HCD_BUS_MODE_SPI(pHcd) && SDIO_SUCCESS(status)) { -+ if (!(pReq->Flags & SDREQ_FLAGS_RESP_SKIP_SPI_FILT) && !(pReq->Flags & SDREQ_FLAGS_PSEUDO) && -+ (GET_SDREQ_RESP_TYPE(pReq->Flags) != SDREQ_FLAGS_NO_RESP)) { -+ ConvertSPI_Response(pReq, NULL); -+ } -+ } -+ -+ DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Completing Request:0x%08X \n",(INT)pReq)); -+ -+ if (!SDIO_SUCCESS(status) && -+ (status != SDIO_STATUS_CANCELED) && -+ !(pReq->Flags & SDREQ_FLAGS_CANCELED) && -+ (pReq->RetryCount > 0)) { -+ /* retry the request if it failed, was NOT cancelled and the retry count -+ * is greater than zero */ -+ pReq->RetryCount--; -+ pReqToComplete = NULL; -+ /* clear SPI converted flag */ -+ pReq->Flags &= ~SDREQ_FLAGS_RESP_SPI_CONVERTED; -+ pNextReq = pReq; -+ } else { -+ /* complete the request */ -+ if (pReq->Flags & SDREQ_FLAGS_BARRIER) { -+ /* a barrier request must be completed before the next bus request is -+ * started */ -+ CompleteRequestCheckCancel(pHcd, pReq); -+ if (!ForceAllRequestsAsync()) { -+ if (CHECK_API_VERSION_COMPAT(pHcd,2,6)) { -+ /* the request was completed, decrement recursion count */ -+ status = _AcquireHcdLock(pHcd); -+ if (!SDIO_SUCCESS(status)) { -+ return status; -+ } -+ pHcd->Recursion--; -+ DBG_ASSERT(pHcd->Recursion >= 0); -+ status = _ReleaseHcdLock(pHcd); -+ } else { -+ /* reset bit */ -+ AtomicTest_Clear(&pHcd->HcdFlags, HCD_REQUEST_CALL_BIT); -+ } -+ } -+ pReqToComplete = NULL; -+ } else { -+ /* complete this after the next request has -+ * been started */ -+ pReqToComplete = pReq; -+ } -+ } -+ -+ /* acquire the hcd lock to look at the queues */ -+ status = _AcquireHcdLock(pHcd); -+ if (SDIO_SUCCESS(status)) { -+ if (pReqToComplete != NULL) { -+ /* queue the request that was completed */ -+ QueueRequest(&pHcd->CompletedRequestQueue, pReqToComplete); -+ } -+ if (NULL == pNextReq) { -+ /* check the queue for the next request */ -+ DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Checking queue.. \n")); -+ /* check to see if the HCD was already working on one. This occurs if -+ * the current request being completed was a barrier request and the -+ * barrier completion routine submitted a new request to the head of the -+ * queue */ -+ if (GET_CURRENT_REQUEST(pHcd) == NULL) { -+ pNextReq = DequeueRequest(&pHcd->RequestQueue); -+ if (NULL == pNextReq) { -+ /* nothing in the queue, mark it not busy */ -+ MarkQueueNotBusy(&pHcd->RequestQueue); -+ DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Queue idle \n")); -+ } else { -+ DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Next request in queue: 0x%X \n", -+ (INT)pNextReq)); -+ } -+ } else { -+ DBG_PRINT(SDIODBG_REQUESTS, -+ ("SDIO Bus Driver: Busy Queue from barrier request \n")); -+ } -+ } -+ -+ if (pNextReq != NULL) { -+ /* a new request will be submitted to the HCD below, -+ * check recursion while we have the lock */ -+ if (CHECK_API_VERSION_COMPAT(pHcd,2,6)) { -+ CHECK_HCD_RECURSE(pHcd,pNextReq); -+ } -+ } -+ status = _ReleaseHcdLock(pHcd); -+ } else { -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO Bus Driver: SDIO_HandleHcdEvent Failed to acquire HCD lock \n")); -+ return SDIO_STATUS_ERROR; -+ } -+ /* check for the next request to issue */ -+ if (pNextReq != NULL) { -+ DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Starting Next Request: 0x%X \n", -+ (INT)pNextReq)); -+ SET_CURRENT_REQUEST(pHcd,pNextReq); -+ status = CallHcdRequest(pHcd); -+ /* check and see if the HCD completed the request in the callback */ -+ if (status != SDIO_STATUS_PENDING) { -+ /* recurse and process the request */ -+ _SDIO_HandleHcdEvent(pHcd, EVENT_HCD_TRANSFER_DONE); -+ } -+ } -+ -+ /* now empty the completed request queue -+ * - this guarantees in-order completion even during recursion */ -+ status = _AcquireHcdLock(pHcd); -+ if (SDIO_SUCCESS(status)) { -+ while (1) { -+ pReqToComplete = DequeueRequest(&pHcd->CompletedRequestQueue); -+ status = _ReleaseHcdLock(pHcd); -+ if (pReqToComplete != NULL) { -+ CompleteRequestCheckCancel(pHcd, pReqToComplete); -+ if (!CHECK_API_VERSION_COMPAT(pHcd,2,6)) { -+ if (!ForceAllRequestsAsync()) { -+ /* reset bit */ -+ AtomicTest_Clear(&pHcd->HcdFlags, HCD_REQUEST_CALL_BIT); -+ } -+ } -+ /* re-acquire lock */ -+ status = _AcquireHcdLock(pHcd); -+ if (!SDIO_SUCCESS(status)) { -+ return SDIO_STATUS_ERROR; -+ } -+ if (CHECK_API_VERSION_COMPAT(pHcd,2,6)) { -+ if (!ForceAllRequestsAsync()) { -+ /* while we have the lock, decrement recursion count each time -+ * we complete a request */ -+ pHcd->Recursion--; -+ DBG_ASSERT(pHcd->Recursion >= 0); -+ } -+ } -+ } else { -+ /* we're done */ -+ break; -+ } -+ } -+ } else { -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO Bus Driver: SDIO_HandleHcdEvent Failed to acquire HCD lock \n")); -+ return SDIO_STATUS_ERROR; -+ } -+ DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: Transfer Done Handled \n")); -+ return SDIO_STATUS_SUCCESS; -+ } -+ -+ switch(Event) { -+ case EVENT_HCD_ATTACH: -+ case EVENT_HCD_DETACH: -+ /* card detect helper does the actual attach detach */ -+ return PostCardDetectEvent(pBusContext,Event,pHcd); -+ case EVENT_HCD_SDIO_IRQ_PENDING: -+ return DeviceInterrupt(pHcd); -+ default: -+ DBG_PRINT(SDDBG_ERROR, ("-SDIO Bus Driver: SDIO_HandleHcdEvent, invalid event type 0x%X, HCD:0x%X\n", -+ Event, (UINT)pHcd)); -+ return SDIO_STATUS_INVALID_PARAMETER; -+ } -+ -+} -+ -+/* card detect helper function */ -+THREAD_RETURN CardDetectHelperFunction(POSKERNEL_HELPER pHelper) -+{ -+ SDIO_STATUS status; -+ HCD_EVENT_MESSAGE message; -+ INT length; -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - CardDetectHelperFunction starting up: 0x%X \n", (INT)pHelper)); -+ -+ while (1) { -+ -+ /* wait for wake up event */ -+ status = SD_WAIT_FOR_WAKEUP(pHelper); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver - Card Detect Helper Semaphore Pend Error:%d \n", -+ status)); -+ break; -+ } -+ -+ if (SD_IS_HELPER_SHUTTING_DOWN(pHelper)) { -+ /* cleanup message queue on shutdown */ -+ while (1) { -+ length = sizeof(message); -+ /* get a message */ -+ status = SDLIB_GetMessage(pBusContext->pCardDetectMsgQueue, -+ &message, &length); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ if (message.pHcd != NULL) { -+ /* decrement HCD reference count */ -+ OS_DecHcdReference(message.pHcd); -+ } -+ } -+ -+ break; -+ } -+ -+ while (1) { -+ length = sizeof(message); -+ /* get a message */ -+ status = SDLIB_GetMessage(pBusContext->pCardDetectMsgQueue, -+ &message, &length); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ -+ switch (message.Event) { -+ case EVENT_HCD_ATTACH: -+ DeviceAttach(message.pHcd); -+ break; -+ case EVENT_HCD_DETACH: -+ DeviceDetach(message.pHcd); -+ break; -+ case EVENT_HCD_CD_POLLING: -+ /* run detector */ -+ RunCardDetect(); -+ break; -+ default: -+ DBG_ASSERT(FALSE); -+ break; -+ } -+ -+ if (message.pHcd != NULL) { -+ /* message was processed, decrement reference count */ -+ OS_DecHcdReference(message.pHcd); -+ } -+ } -+ } -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - Card Detect Helper Exiting.. \n")); -+ return 0; -+} -+ -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ RunCardDetect - run card detect on host controller slots that require polling -+ Input: -+ Output: -+ Return: -+ Notes: This function is called from the card detect timer thread -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+void RunCardDetect(void) -+{ -+ BOOL CDPollingRequired = FALSE; -+ PSDLIST pListItem; -+ PSDHCD pHcd; -+ BOOL cardPresent; -+ -+ DBG_PRINT(SDIODBG_CD_TIMER, ("+SDIO Bus Driver: RunCardDetect\n")); -+ -+ /* protect the HCD list */ -+ if (!SDIO_SUCCESS(SemaphorePendInterruptable(&pBusContext->HcdListSem))) { -+ DBG_ASSERT(FALSE); -+ return; /* wait interrupted */ -+ } -+ /* while we are running the detector we are blocking HCD removal*/ -+ SDITERATE_OVER_LIST(&pBusContext->HcdList, pListItem) { -+ pHcd = CONTAINING_STRUCT(pListItem, SDHCD, SDList); -+ /* does the HCD require polling ? */ -+ if (pHcd->Attributes & SDHCD_ATTRIB_SLOT_POLLING) { -+ DBG_PRINT(SDIODBG_CD_TIMER, ("SDIO Bus Driver: Found HCD requiring polling \n")); -+ /* set flag to queue the timer */ -+ CDPollingRequired = TRUE; -+ if (IS_CARD_PRESENT(pHcd)) { -+ /* there is a device in the slot */ -+ cardPresent = TRUE; -+ if (SDIO_SUCCESS(ScanSlotForCard(pHcd,&cardPresent))) { -+ if (!cardPresent) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver CD Polling.. Card Removal Detected\n")); -+ DeviceDetach(pHcd); -+ } -+ } -+ } else { -+ cardPresent = FALSE; -+ if (SDIO_SUCCESS(ScanSlotForCard(pHcd,&cardPresent))) { -+ if (cardPresent) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver CD Polling.. Card Detected\n")); -+ DeviceAttach(pHcd); -+ } -+ } -+ } -+ } -+ -+ DBG_PRINT(SDIODBG_CD_TIMER, ("SDIO Bus Driver: moving to next hcd:0x%X \n", -+ (INT)pListItem->pNext)); -+ } -+ -+ /* check if we need to queue the timer */ -+ if (CDPollingRequired && !pBusContext->CDTimerQueued) { -+ pBusContext->CDTimerQueued = TRUE; -+ DBG_PRINT(SDIODBG_CD_TIMER, ("SDIO Bus Driver: Queuing Card detect timer \n")); -+ if (!SDIO_SUCCESS( -+ QueueTimer(SDIOBUS_CD_TIMER_ID, pBusContext->CDPollingInterval))) { -+ DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: failed to queue CD timer \n")); -+ pBusContext->CDTimerQueued = FALSE; -+ } -+ } -+ /* release HCD list lock */ -+ SemaphorePost(&pBusContext->HcdListSem); -+ DBG_PRINT(SDIODBG_CD_TIMER, ("-SDIO Bus Driver: RunCardDetect\n")); -+} -+ -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ ScanSlotForCard - scan slot for a card -+ Input: pHcd - the hcd -+ Output: pCardPresent - card present flag (set/cleared on return) -+ Return: -+ Notes: -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static SDIO_STATUS ScanSlotForCard(PSDHCD pHcd,PBOOL pCardPresent) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ UINT8 temp; -+ -+ DBG_PRINT(SDIODBG_CD_TIMER, ("+SDIO Bus Driver: ScanSlotForCard\n")); -+ -+ do { -+ if (!IS_CARD_PRESENT(pHcd)) { -+ INT dbgLvl; -+ dbgLvl = DBG_GET_DEBUG_LEVEL(); -+ DBG_SET_DEBUG_LEVEL(SDDBG_WARN); -+ status = CardInitSetup(pHcd); -+ DBG_SET_DEBUG_LEVEL(dbgLvl); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ /* issue go-idle */ -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_RESP_R1,NULL); -+ } else { -+ _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_NO_RESP,NULL); -+ } -+ /* try SDIO */ -+ status = TestPresence(pHcd,CARD_SDIO,NULL); -+ if (SDIO_SUCCESS(status)) { -+ *pCardPresent = TRUE; -+ break; -+ } -+ /* issue go-idle */ -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_RESP_R1,NULL); -+ } else { -+ _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_NO_RESP,NULL); -+ } -+ /* try SD */ -+ status = TestPresence(pHcd,CARD_SD,NULL); -+ if (SDIO_SUCCESS(status)) { -+ *pCardPresent = TRUE; -+ break; -+ } -+ /* issue go-idle */ -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_RESP_R1,NULL); -+ } else { -+ _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_NO_RESP,NULL); -+ } -+ /* try MMC */ -+ status = TestPresence(pHcd,CARD_MMC,NULL); -+ if (SDIO_SUCCESS(status)) { -+ *pCardPresent = TRUE; -+ break; -+ } -+ } else { -+ if (pHcd->CardProperties.Flags & CARD_SDIO) { -+#ifdef DUMP_INT_PENDING -+ temp = 0; -+ /* handy debug prints to check interrupt status and print pending register */ -+ status = Cmd52ReadByteCommon(pHcd->pPseudoDev, SDIO_INT_ENABLE_REG, &temp); -+ if (SDIO_SUCCESS(status) && (temp != 0)) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: INT Enable Reg: 0x%2.2X\n", temp)); -+ status = Cmd52ReadByteCommon(pHcd->pPseudoDev, SDIO_INT_PENDING_REG, &temp); -+ if (SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: INT Pend Reg: 0x%2.2X\n", temp)); -+ } -+ } -+#endif -+ /* for SDIO cards, read the revision register */ -+ status = Cmd52ReadByteCommon(pHcd->pPseudoDev, CCCR_SDIO_REVISION_REG, &temp); -+ } else if (pHcd->CardProperties.Flags & (CARD_SD | CARD_MMC)) { -+ /* for SD/MMC cards, issue SEND_STATUS */ -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ /* SPI uses the SPI R2 response */ -+ status = _IssueSimpleBusRequest(pHcd, -+ CMD13, -+ 0, -+ SDREQ_FLAGS_RESP_R2, -+ NULL); -+ } else { -+ status = _IssueSimpleBusRequest(pHcd, -+ CMD13, -+ (pHcd->CardProperties.RCA << 16), -+ SDREQ_FLAGS_RESP_R1,NULL); -+ } -+ } else { -+ DBG_ASSERT(FALSE); -+ } -+ if (!SDIO_SUCCESS(status)) { -+ /* card is gone */ -+ *pCardPresent = FALSE; -+ } -+ } -+ } while (FALSE); -+ -+ if (status == SDIO_STATUS_BUS_RESP_TIMEOUT) { -+ status = SDIO_STATUS_SUCCESS; -+ } -+ -+ DBG_PRINT(SDIODBG_CD_TIMER, ("-SDIO Bus Driver: ScanSlotForCard status:%d\n", -+ status)); -+ -+ return status; -+} -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ DeviceInterrupt - handle device interrupt -+ Input: pHcd - host controller -+ Output: -+ Return: -+ Notes: -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS DeviceInterrupt(PSDHCD pHcd) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ SDIO_STATUS status2; -+ PSDREQUEST pReq = NULL; -+ CT_DECLARE_IRQ_SYNC_CONTEXT(); -+ -+ DBG_PRINT(SDIODBG_FUNC_IRQ, ("+SDIO Bus Driver: DeviceInterrupt\n")); -+ -+ if (!IS_CARD_PRESENT(pHcd)) { -+ DBG_PRINT(SDDBG_ERROR, ("-SDIO Bus Driver: Device interrupt asserted on empty slot!\n")); -+ return SDIO_STATUS_ERROR; -+ } -+ -+ do { -+ /* for RAW HCDs or HCDs flagged for single-function IRQ optimization */ -+ if (IS_HCD_RAW(pHcd) || (pHcd->HcdFlags & (1 << HCD_IRQ_NO_PEND_CHECK))) { -+ status = _AcquireHcdLock(pHcd); -+ if (!SDIO_SUCCESS(status)) { -+ return status; -+ } -+ if (pHcd->IrqProcState != SDHCD_IDLE) { -+ status = SDIO_STATUS_ERROR; -+ status2 = _ReleaseHcdLock(pHcd); -+ } else { -+ DBG_PRINT(SDIODBG_FUNC_IRQ, ("SDIO Bus Driver : Device Interrupt \n")); -+ /* mark that we are processing */ -+ pHcd->IrqProcState = SDHCD_IRQ_PENDING; -+ status2 = _ReleaseHcdLock(pHcd); -+ /* process Irqs for raw hcds or HCDs with the single function optimization */ -+ /* force processing of function 1 interrupt */ -+ ProcessPendingIrqs(pHcd, (1 << 1)); -+ } -+ DBG_PRINT(SDIODBG_FUNC_IRQ, ("-SDIO Bus Driver: DeviceInterrupt: %d\n", status)); -+ /* done with RAW irqs */ -+ return status; -+ } -+ -+ /* pre-allocate a request to get the pending bits, we have to do this outside the -+ * hcd lock acquisition */ -+ pReq = AllocateRequest(); -+ -+ if (NULL == pReq) { -+ status = SDIO_STATUS_NO_RESOURCES; -+ break; -+ } -+ -+ status = _AcquireHcdLock(pHcd); -+ -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ -+ if (pHcd->IrqProcState != SDHCD_IDLE) { -+ status = SDIO_STATUS_ERROR; -+ } else { -+ /* mark that we are processing */ -+ pHcd->IrqProcState = SDHCD_IRQ_PENDING; -+ /* build argument to read IRQ pending register */ -+ SDIO_SET_CMD52_READ_ARG(pReq->Argument,0,SDIO_INT_PENDING_REG); -+ pReq->Command = CMD52; -+ pReq->Flags = SDREQ_FLAGS_TRANS_ASYNC | SDREQ_FLAGS_RESP_SDIO_R5; -+ pReq->pCompleteContext = (PVOID)pHcd; -+ pReq->pCompletion = GetPendingIrqComplete; -+ pReq->RetryCount = SDBUS_MAX_RETRY; -+ } -+ -+ status2 = _ReleaseHcdLock(pHcd); -+ -+ if (!SDIO_SUCCESS(status2)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: lock release error: %d\n", status2)); -+ } -+ -+ } while (FALSE); -+ -+ if (SDIO_SUCCESS(status)) { -+ DBG_ASSERT(pReq != NULL); -+ IssueRequestToHCD(pHcd,pReq); -+ status = SDIO_STATUS_PENDING; -+ } else { -+ if (pReq != NULL) { -+ FreeRequest(pReq); -+ } -+ } -+ -+ DBG_PRINT(SDIODBG_FUNC_IRQ, ("-SDIO Bus Driver: DeviceInterrupt: %d\n", status)); -+ return status; -+} -+ -+ -+/* SDIO IRQ helper */ -+THREAD_RETURN SDIOIrqHelperFunction(POSKERNEL_HELPER pHelper) -+{ -+ PSDHCD pHcd; -+ SDIO_STATUS status; -+ PSDLIST pListItem; -+ PSDDEVICE pDevice; -+ UINT8 funcMask; -+ PSDDEVICE pDeviceIRQ[7]; -+ UINT deviceIrqCount = 0; -+ UINT ii; -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - SDIOIrqHelperFunction starting up \n")); -+ -+ pHcd = (PSDHCD)pHelper->pContext; -+ DBG_ASSERT(pHcd != NULL); -+ -+ while (1) { -+ -+ /* wait for wake up event */ -+ status = SD_WAIT_FOR_WAKEUP(pHelper); -+ -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver - SDIOIrqHelperFunction Pend Error:%d \n", -+ status)); -+ break; -+ } -+ -+ if (SD_IS_HELPER_SHUTTING_DOWN(pHelper)) { -+ break; -+ } -+ -+ DBG_PRINT(SDIODBG_FUNC_IRQ, ("SDIO Bus Driver - Pending IRQs:0x%X \n", -+ pHcd->PendingHelperIrqs)); -+ -+ /* take the device list lock as we iterate through the list, this blocks -+ * device removals */ -+ status = SemaphorePendInterruptable(&pBusContext->DeviceListSem); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ /* walk through the device list matching HCD and interrupting function */ -+ SDITERATE_OVER_LIST(&pBusContext->DeviceList, pListItem) { -+ pDevice = CONTAINING_STRUCT(pListItem, SDDEVICE, SDList); -+ /* check if device belongs to the HCD */ -+ if (pDevice->pHcd != pHcd){ -+ /* not on this hcd */ -+ continue; -+ } -+ funcMask = 1 << SDDEVICE_GET_SDIO_FUNCNO(pDevice); -+ /* check device function against the pending mask */ -+ if (!(funcMask & pHcd->PendingHelperIrqs)) { -+ /* this one is not scheduled for the helper */ -+ continue; -+ } -+ /* clear bit */ -+ pHcd->PendingHelperIrqs &= ~funcMask; -+ /* check for sync IRQ and call handler */ -+ if (pDevice->pIrqFunction != NULL) { -+ DBG_PRINT(SDIODBG_FUNC_IRQ, ("SDIO Bus Driver: Calling IRQ Handler. Fn:%d\n", -+ SDDEVICE_GET_SDIO_FUNCNO(pDevice))); -+ /* save the device so we can process it without holding any locks */ -+ pDeviceIRQ[deviceIrqCount++] = pDevice; -+ } else { -+ /* this is actually okay if the device is removing, the callback -+ * is NULLed out */ -+ DBG_PRINT(SDIODBG_FUNC_IRQ, ("SDIO Bus Driver: No IRQ handler Fn:%d\n", -+ SDDEVICE_GET_SDIO_FUNCNO(pDevice))); -+ } -+ } -+ /* should have handled all these */ -+ DBG_ASSERT(pHcd->PendingHelperIrqs == 0); -+ pHcd->PendingHelperIrqs = 0; -+ SemaphorePost(&pBusContext->DeviceListSem); -+ for (ii = 0; ii < deviceIrqCount; ii++) { -+ /* now call the function */ -+ SDDEVICE_CALL_IRQ_HANDLER(pDeviceIRQ[ii]); -+ } -+ deviceIrqCount = 0; -+ } -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - SDIOIrqHelperFunction Exiting.. \n")); -+ return 0; -+} -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ GetPendingIrqComplete - completion routine for getting pending IRQs -+ Input: pRequest - completed request -+ Output: -+ Return: -+ Notes: -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static void GetPendingIrqComplete(PSDREQUEST pReq) -+{ -+ UINT8 intPendingMsk; -+ PSDHCD pHcd; -+ -+ do { -+ pHcd = (PSDHCD)pReq->pCompleteContext; -+ DBG_ASSERT(pHcd != NULL); -+ -+ if (!SDIO_SUCCESS(pReq->Status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get Interrupt pending register Err:%d\n", -+ pReq->Status)); -+ break; -+ } -+ -+ if (SD_R5_GET_RESP_FLAGS(pReq->Response) & SD_R5_ERRORS) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: CMD52 resp error: 0x%X \n", -+ SD_R5_GET_RESP_FLAGS(pReq->Response))); -+ break; -+ } -+ /* extract the pending mask */ -+ intPendingMsk = SD_R5_GET_READ_DATA(pReq->Response) & SDIO_INT_PEND_MASK; -+ /* process them */ -+ ProcessPendingIrqs(pHcd, intPendingMsk); -+ -+ } while (FALSE); -+ -+ FreeRequest(pReq); -+ -+ DBG_PRINT(SDIODBG_FUNC_IRQ, ("-SDIO Bus Driver: GetPendingIrqComplete \n")); -+} -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ ProcessPendingIrqs - processing pending Irqs -+ Input: pHcd - host controller -+ Input: IntPendingMsk - pending irq bit mask -+ Output: -+ Return: -+ Notes: -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static void ProcessPendingIrqs(PSDHCD pHcd, UINT8 IntPendingMsk) -+{ -+ PSDLIST pListItem; -+ PSDDEVICE pDevice; -+ UINT8 funcMask; -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ CT_DECLARE_IRQ_SYNC_CONTEXT(); -+ -+ DBG_PRINT(SDIODBG_FUNC_IRQ, ("+SDIO Bus Driver: ProcessPendingIrqs \n")); -+ do { -+ /* acquire lock to protect configuration and irq enables */ -+ status = _AcquireHcdLock(pHcd); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ -+ /* sanity check */ -+ if ((IntPendingMsk & pHcd->IrqsEnabled) != IntPendingMsk) { -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO Bus Driver: IRQs asserting when not enabled : curr:0x%X , card reports: 0x%X\n", -+ pHcd->IrqsEnabled, IntPendingMsk)); -+ /* remove the pending IRQs that are not enabled */ -+ IntPendingMsk &= pHcd->IrqsEnabled; -+ /* fall through */ -+ } -+ -+ if (!IntPendingMsk) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: No interrupts on HCD:0x%X \n", (INT)pHcd)); -+ pHcd->IrqProcState = SDHCD_IDLE; -+ if (pHcd->IrqsEnabled) { -+ /* only re-arm if there are IRQs enabled */ -+ _IssueConfig(pHcd,SDCONFIG_SDIO_REARM_INT,NULL,0); -+ } -+ status = _ReleaseHcdLock(pHcd); -+ break; -+ } -+ /* reset helper IRQ bits */ -+ pHcd->PendingHelperIrqs = 0; -+ /* save pending IRQ acks */ -+ pHcd->PendingIrqAcks = IntPendingMsk; -+ status = _ReleaseHcdLock(pHcd); -+ DBG_PRINT(SDIODBG_FUNC_IRQ, ("SDIO Bus Driver: INTs Pending - 0x%2.2X \n", IntPendingMsk)); -+ /* take the device list lock as we iterate through the list, this blocks -+ * device removals */ -+ status = SemaphorePendInterruptable(&pBusContext->DeviceListSem); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ /* walk through the device list matching HCD and interrupting function */ -+ SDITERATE_OVER_LIST(&pBusContext->DeviceList, pListItem) { -+ pDevice = CONTAINING_STRUCT(pListItem, SDDEVICE, SDList); -+ /* check if device belongs to the HCD */ -+ if (pDevice->pHcd != pHcd){ -+ /* not on this hcd */ -+ continue; -+ } -+ funcMask = 1 << SDDEVICE_GET_SDIO_FUNCNO(pDevice); -+ /* check device function against the pending mask */ -+ if (!(funcMask & IntPendingMsk)) { -+ /* this one is not interrupting */ -+ continue; -+ } -+ /* check for async IRQ and call handler */ -+ if (pDevice->pIrqAsyncFunction != NULL) { -+ DBG_PRINT(SDIODBG_FUNC_IRQ, ("SDIO Bus Driver: Calling Async IRQ Handler. Fn:%d\n", -+ SDDEVICE_GET_SDIO_FUNCNO(pDevice))); -+ SDDEVICE_CALL_IRQ_ASYNC_HANDLER(pDevice); -+ } else { -+ /* this one needs the helper */ -+ pHcd->PendingHelperIrqs |= funcMask; -+ DBG_PRINT(SDIODBG_FUNC_IRQ, ("SDIO Bus Driver: No Async IRQ, Pending Helper Fn:%d\n", -+ SDDEVICE_GET_SDIO_FUNCNO(pDevice))); -+ } -+ } -+ /* release HCD list lock */ -+ SemaphorePost(&pBusContext->DeviceListSem); -+ /* check for helper IRQs */ -+ if (pHcd->PendingHelperIrqs) { -+ pHcd->IrqProcState = SDHCD_IRQ_HELPER; -+ DBG_PRINT(SDIODBG_FUNC_IRQ, ("SDIO Bus Driver: Waking IRQ Helper \n")); -+ if (!SDIO_SUCCESS(SD_WAKE_OS_HELPER(&pHcd->SDIOIrqHelper))) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: failed to wake helper! \n")); -+ } -+ } -+ } while (FALSE); -+ -+ DBG_PRINT(SDIODBG_FUNC_IRQ, ("-SDIO Bus Driver: ProcessPendingIrqs \n")); -+} -+ -+SDIO_STATUS TryNoIrqPendingCheck(PSDDEVICE pDevice) -+{ -+ if (pDevice->pHcd->CardProperties.IOFnCount > 1) { -+ /* not supported on multi-function cards */ -+ DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: IRQ Pending Check cannot be bypassed, (Funcs:%d)\n", -+ pDevice->pHcd->CardProperties.IOFnCount)); -+ return SDIO_STATUS_UNSUPPORTED; -+ } -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: pending IRQ check bypassed \n")); -+ /* set flag to optimize this */ -+ AtomicTest_Set(&pDevice->pHcd->HcdFlags, HCD_IRQ_NO_PEND_CHECK); -+ return SDIO_STATUS_SUCCESS; -+} -+ -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ SDIO_NotifyTimerTriggered - notification handler that a timer expired -+ Input: TimerID - ID of timer that expired -+ Output: -+ Return: -+ Notes: -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+void SDIO_NotifyTimerTriggered(INT TimerID) -+{ -+ -+ switch (TimerID) { -+ case SDIOBUS_CD_TIMER_ID: -+ pBusContext->CDTimerQueued = FALSE; -+ /* post an HCD polling event to the helper thread */ -+ PostCardDetectEvent(pBusContext, EVENT_HCD_CD_POLLING, NULL); -+ break; -+ default: -+ DBG_ASSERT(FALSE); -+ } -+ -+} -diff --git a/drivers/sdio/stack/busdriver/sdio_bus_misc.c b/drivers/sdio/stack/busdriver/sdio_bus_misc.c -new file mode 100644 -index 0000000..c5c7381 ---- /dev/null -+++ b/drivers/sdio/stack/busdriver/sdio_bus_misc.c -@@ -0,0 +1,3122 @@ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+@file: sdio_bus_misc.c -+ -+@abstract: OS independent bus driver support -+ -+#notes: this file contains miscellaneous control functions -+ -+@notice: Copyright (c), 2004-2006 Atheros Communications, Inc. -+ -+ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * Software distributed under the License is distributed on an "AS -+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -+ * implied. See the License for the specific language governing -+ * rights and limitations under the License. -+ * -+ * Portions of this code were developed with information supplied from the -+ * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply: -+ * -+ * The following conditions apply to the release of the SD simplified specification (�Simplified -+ * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete -+ * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided -+ * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified -+ * Specification may require a license from the SD Card Association or other third parties. -+ * Disclaimers: -+ * The information contained in the Simplified Specification is presented only as a standard -+ * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any -+ * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for -+ * any damages, any infringements of patents or other right of the SD Card Association or any third -+ * parties, which may result from its use. No license is granted by implication, estoppel or otherwise -+ * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall -+ * be construed as an obligation by the SD Card Association to disclose or distribute any technical -+ * information, know-how or other confidential information to any third party. -+ * -+ * -+ * The initial developers of the original code are Seung Yi and Paul Lever -+ * -+ * sdio@atheros.com -+ * -+ * -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define MODULE_NAME SDBUSDRIVER -+#include <linux/sdio/ctsystem.h> -+#include <linux/sdio/sdio_busdriver.h> -+#include <linux/sdio/sdio_lib.h> -+#include "_busdriver.h" -+#include <linux/sdio/_sdio_defs.h> -+#include <linux/sdio/mmc_defs.h> -+ -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ IssueBusRequestBd - issue a bus request -+ Input: pHcd - HCD object -+ Cmd - command to issue -+ Argument - command argument -+ Flags - request flags -+ -+ Output: pReqToUse - request to use (if caller wants response data) -+ Return: SDIO Status -+ Notes: This function only issues 1 block data transfers -+ This function issues the request synchronously -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS _IssueBusRequestBd(PSDHCD pHcd, -+ UINT8 Cmd, -+ UINT32 Argument, -+ SDREQUEST_FLAGS Flags, -+ PSDREQUEST pReqToUse, -+ PVOID pData, -+ INT Length) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ PSDREQUEST pReq; -+ -+ if (NULL == pReqToUse) { -+ /* caller doesn't care about the response data, allocate locally */ -+ pReq = AllocateRequest(); -+ if (NULL == pReq) { -+ return SDIO_STATUS_NO_RESOURCES; -+ } -+ } else { -+ /* use the caller's request buffer */ -+ pReq = pReqToUse; -+ } -+ -+ pReq->Argument = Argument; -+ pReq->Flags = Flags; -+ pReq->Command = Cmd; -+ if (pReq->Flags & SDREQ_FLAGS_DATA_TRANS) { -+ pReq->pDataBuffer = pData; -+ pReq->BlockCount = 1; -+ pReq->BlockLen = Length; -+ } -+ -+ status = IssueRequestToHCD(pHcd,pReq); -+ -+ if (NULL == pReqToUse) { -+ DBG_ASSERT(pReq != NULL); -+ FreeRequest(pReq); -+ } -+ return status; -+} -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ ConvertVoltageCapsToOCRMask - initialize card -+ Input: VoltageCaps - voltage cap to look up -+ Return: 32 bit OCR mask -+ Notes: this function sets voltage for +- 10% -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static UINT32 ConvertVoltageCapsToOCRMask(SLOT_VOLTAGE_MASK VoltageCaps) -+{ -+ UINT32 ocrMask; -+ -+ ocrMask = 0; -+ -+ if (VoltageCaps & SLOT_POWER_3_3V) { -+ ocrMask |= SD_OCR_3_2_TO_3_3_VDD | SD_OCR_3_3_TO_3_4_VDD; -+ } -+ if (VoltageCaps & SLOT_POWER_3_0V) { -+ ocrMask |= SD_OCR_2_9_TO_3_0_VDD | SD_OCR_3_0_TO_3_1_VDD; -+ } -+ if (VoltageCaps & SLOT_POWER_2_8V) { -+ ocrMask |= SD_OCR_2_7_TO_2_8_VDD | SD_OCR_2_8_TO_2_9_VDD; -+ } -+ if (VoltageCaps & SLOT_POWER_2_0V) { -+ ocrMask |= SD_OCR_1_9_TO_2_0_VDD | SD_OCR_2_0_TO_2_1_VDD; -+ } -+ if (VoltageCaps & SLOT_POWER_1_8V) { -+ ocrMask |= SD_OCR_1_7_TO_1_8_VDD | SD_OCR_1_8_TO_1_9_VDD; -+ } -+ if (VoltageCaps & SLOT_POWER_1_6V) { -+ ocrMask |= SD_OCR_1_6_TO_1_7_VDD; -+ } -+ -+ return ocrMask; -+} -+ -+static UINT32 GetUsableOCRValue(UINT32 CardOCR, UINT32 SlotOCRMask) -+{ -+ INT i; -+ UINT32 mask = 0; -+ -+ for (i = 0; i < 32; i++) { -+ mask = 1 << i; -+ if ((SlotOCRMask & mask) && (CardOCR & mask)) { -+ return mask; -+ } -+ } -+ -+ return mask; -+} -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ GetPowerSetting - power up the SDIO card -+ Input: pHcd - HCD object -+ pOCRvalue - OCR value of the card -+ Output: pOCRvalue - OCR to actually use -+ Return: power setting for HCD based on card's OCR, zero indicates unsupported -+ Notes: -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static SLOT_VOLTAGE_MASK GetPowerSetting(PSDHCD pHcd, UINT32 *pOCRvalue) -+{ -+ UINT32 ocrMask; -+ SLOT_VOLTAGE_MASK hcdVoltage = 0; -+ SLOT_VOLTAGE_MASK hcdVMask; -+ INT i; -+ -+ /* check preferred value */ -+ ocrMask = ConvertVoltageCapsToOCRMask(pHcd->SlotVoltagePreferred); -+ if (ocrMask & *pOCRvalue) { -+ /* using preferred voltage */ -+ *pOCRvalue = GetUsableOCRValue(*pOCRvalue, ocrMask); -+ hcdVoltage = pHcd->SlotVoltagePreferred; -+ } else { -+ /* walk through the slot voltage caps and find a match */ -+ for (i = 0; i < 8; i++) { -+ hcdVMask = (1 << i); -+ if (hcdVMask & pHcd->SlotVoltageCaps) { -+ ocrMask = ConvertVoltageCapsToOCRMask((SLOT_VOLTAGE_MASK)(pHcd->SlotVoltageCaps & hcdVMask)); -+ if (ocrMask & *pOCRvalue) { -+ /* found a match */ -+ *pOCRvalue = GetUsableOCRValue(*pOCRvalue, ocrMask); -+ hcdVoltage = pHcd->SlotVoltageCaps & hcdVMask; -+ break; -+ } -+ } -+ } -+ } -+ -+ return hcdVoltage; -+} -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ TestPresence - test the presence of a card/function -+ Input: pHcd - HCD object -+ TestType - type of test to perform -+ Output: pReq - Request to use (optional) -+ Return: -+ Notes: -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS TestPresence(PSDHCD pHcd, -+ CARD_INFO_FLAGS TestType, -+ PSDREQUEST pReq) -+{ -+ SDIO_STATUS status = SDIO_STATUS_ERROR; -+ -+ switch (TestType) { -+ case CARD_SDIO: -+ /* issue CMD5 */ -+ status = _IssueSimpleBusRequest(pHcd,CMD5,0, -+ SDREQ_FLAGS_RESP_SDIO_R4 | SDREQ_FLAGS_RESP_SKIP_SPI_FILT,pReq); -+ break; -+ case CARD_SD: -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ /* ACMD41 just starts initialization when in SPI mode, argument is ignored -+ * Note: In SPI mode ACMD41 uses an R1 response */ -+ status = _IssueSimpleBusRequest(pHcd,ACMD41,0, -+ SDREQ_FLAGS_APP_CMD | SDREQ_FLAGS_RESP_R1,pReq); -+ -+ } else { -+ /* issue ACMD41 with OCR value of zero */ -+ /* ACMD41 on SD uses an R3 response */ -+ status = _IssueSimpleBusRequest(pHcd,ACMD41,0, -+ SDREQ_FLAGS_APP_CMD | SDREQ_FLAGS_RESP_R3,pReq); -+ } -+ break; -+ case CARD_MMC: -+ /* issue CMD1 */ -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ /* note: in SPI mode an R1 response is used */ -+ status = _IssueSimpleBusRequest(pHcd,CMD1,0,SDREQ_FLAGS_RESP_R1,pReq); -+ } else { -+ status = _IssueSimpleBusRequest(pHcd,CMD1,0,SDREQ_FLAGS_RESP_R3,pReq); -+ } -+ break; -+ default: -+ DBG_ASSERT(FALSE); -+ break; -+ } -+ -+ return status; -+} -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ ReadOCR - read the OCR -+ Input: pHcd - HCD object -+ ReadType - type of read to perform -+ OCRValue - OCR value to use as an argument -+ Output: pReq - Request to use -+ pOCRValueRd - OCR value read back (can be NULL) -+ Return: -+ Notes: -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static SDIO_STATUS ReadOCR(PSDHCD pHcd, -+ CARD_INFO_FLAGS ReadType, -+ PSDREQUEST pReq, -+ UINT32 OCRValue, -+ UINT32 *pOCRValueRd) -+{ -+ SDIO_STATUS status = SDIO_STATUS_ERROR; -+ -+ switch (ReadType) { -+ case CARD_SDIO: -+ /* CMD5 for SDIO cards */ -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ /* skip the SPI filter, we will decode the response here */ -+ status = _IssueSimpleBusRequest(pHcd,CMD5, -+ OCRValue, -+ SDREQ_FLAGS_RESP_SDIO_R4 | -+ SDREQ_FLAGS_RESP_SKIP_SPI_FILT, -+ pReq); -+ } else { -+ /* native SD */ -+ status = _IssueSimpleBusRequest(pHcd,CMD5, -+ OCRValue, -+ SDREQ_FLAGS_RESP_SDIO_R4, -+ pReq); -+ } -+ break; -+ case CARD_SD: -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ /* CMD58 is used to read the OCR */ -+ status = _IssueSimpleBusRequest(pHcd,CMD58, -+ 0, /* argument ignored */ -+ (SDREQ_FLAGS_RESP_R3 | SDREQ_FLAGS_RESP_SKIP_SPI_FILT), -+ pReq); -+ } else { -+ /* SD Native uses ACMD41 */ -+ status = _IssueSimpleBusRequest(pHcd,ACMD41, -+ OCRValue, -+ SDREQ_FLAGS_APP_CMD | SDREQ_FLAGS_RESP_R3, -+ pReq); -+ } -+ break; -+ case CARD_MMC: -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ /* CMD58 is used to read the OCR */ -+ status = _IssueSimpleBusRequest(pHcd,CMD58, -+ 0, /* argument ignored */ -+ (SDREQ_FLAGS_RESP_R3 | SDREQ_FLAGS_RESP_SKIP_SPI_FILT), -+ pReq); -+ } else { -+ /* MMC Native uses CMD1 */ -+ status = _IssueSimpleBusRequest(pHcd,CMD1, -+ OCRValue, SDREQ_FLAGS_RESP_R3, -+ pReq); -+ } -+ break; -+ default: -+ DBG_ASSERT(FALSE); -+ break; -+ } -+ -+ if (SDIO_SUCCESS(status) && (pOCRValueRd != NULL)) { -+ *pOCRValueRd = 0; -+ /* someone wants the OCR read back */ -+ switch (ReadType) { -+ case CARD_SDIO: -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ *pOCRValueRd = SPI_SDIO_R4_GET_OCR(pReq->Response); -+ } else { -+ *pOCRValueRd = SD_SDIO_R4_GET_OCR(pReq->Response); -+ } -+ break; -+ case CARD_SD: -+ case CARD_MMC: -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ *pOCRValueRd = SPI_R3_GET_OCR(pReq->Response); -+ } else { -+ *pOCRValueRd = SD_R3_GET_OCR(pReq->Response); -+ } -+ break; -+ default: -+ DBG_ASSERT(FALSE); -+ break; -+ } -+ } -+ return status; -+} -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ PollCardReady - poll card till it's ready -+ Input: pHcd - HCD object -+ OCRValue - OCR value to poll with -+ PollType - polling type (based on card type) -+ Output: -+ Return: -+ Notes: -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS PollCardReady(PSDHCD pHcd, UINT32 OCRValue, CARD_INFO_FLAGS PollType) -+{ -+ INT cardReadyRetry; -+ SDIO_STATUS status; -+ PSDREQUEST pReq; -+ -+ if (!((PollType == CARD_SDIO) || (PollType == CARD_SD) || (PollType == CARD_MMC))) { -+ DBG_ASSERT(FALSE); -+ return SDIO_STATUS_INVALID_PARAMETER; -+ } -+ -+ pReq = AllocateRequest(); -+ if (NULL == pReq) { -+ return SDIO_STATUS_NO_RESOURCES; -+ } -+ -+ status = SDIO_STATUS_SUCCESS; -+ cardReadyRetry = pBusContext->CardReadyPollingRetry; -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Polling card ready, Using OCR:0x%8.8X, Poll Type:0x%X\n", -+ OCRValue,PollType)); -+ -+ /* now issue CMD with the actual OCR as an argument until the card is ready */ -+ while (cardReadyRetry) { -+ if (IS_HCD_BUS_MODE_SPI(pHcd) && !(PollType == CARD_SDIO)) { -+ if (PollType == CARD_MMC) { -+ /* under SPI mode for MMC cards, we need to issue CMD1 and -+ * check the response for the "in-idle" bit */ -+ status = _IssueSimpleBusRequest(pHcd, -+ CMD1, -+ 0, -+ SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_RESP_SKIP_SPI_FILT, -+ pReq); -+ } else if (PollType == CARD_SD) { -+ /* under SPI mode for SD cards, we need to issue ACMD41 and -+ * check the response for the "in-idle" bit */ -+ status = _IssueSimpleBusRequest(pHcd, -+ ACMD41, -+ 0, -+ SDREQ_FLAGS_RESP_R1 | -+ SDREQ_FLAGS_APP_CMD | -+ SDREQ_FLAGS_RESP_SKIP_SPI_FILT, -+ pReq); -+ } else { -+ DBG_ASSERT(FALSE); -+ } -+ } else { -+ /* for SD/MMC in native mode and SDIO (all modes) we need to read the OCR register */ -+ /* read the OCR using the supplied OCR value as an argument, we don't care about the -+ * actual OCR read-back, but we are interested in the response */ -+ status = ReadOCR(pHcd,PollType,pReq,OCRValue,NULL); -+ } -+ -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to issue CMD to poll ready \n")); -+ break; -+ } -+ if (PollType == CARD_SDIO) { -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ if (SPI_SDIO_R4_IS_CARD_READY(pReq->Response)) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SDIO Card Ready! (SPI) \n")); -+ break; -+ } -+ } else { -+ if (SD_SDIO_R4_IS_CARD_READY(pReq->Response)) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SDIO Card Ready! \n")); -+ break; -+ } -+ } -+ } else if ((PollType == CARD_SD) || (PollType == CARD_MMC)) { -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ /* check response when MMC or SD cards operate in SPI mode */ -+ if (!(GET_SPI_R1_RESP_TOKEN(pReq->Response) & SPI_CS_STATE_IDLE)) { -+ /* card is no longer in idle */ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD/MMC Card (SPI mode) is ready! \n")); -+ break; -+ } -+ } else { -+ /* check the OCR busy bit */ -+ if (SD_R3_IS_CARD_READY(pReq->Response)) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD/MMC (Native Mode) Card Ready! \n")); -+ break; -+ } -+ } -+ } else { -+ DBG_ASSERT(FALSE); -+ } -+ cardReadyRetry--; -+ /* delay */ -+ status = OSSleep(OCR_READY_CHECK_DELAY_MS); -+ if (!SDIO_SUCCESS(status)){ -+ break; -+ } -+ } -+ -+ if (0 == cardReadyRetry) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Card Ready timeout! \n")); -+ status = SDIO_STATUS_DEVICE_ERROR; -+ } -+ -+ FreeRequest(pReq); -+ -+ return status; -+} -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ AdjustSlotPower - adjust slot power -+ Input: pHcd - HCD object -+ Output: pOCRvalue - ocr value to use -+ Return: -+ Notes: -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static SDIO_STATUS AdjustSlotPower(PSDHCD pHcd, UINT32 *pOCRvalue) -+{ -+ SDCONFIG_POWER_CTRL_DATA pwrSetting; -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ -+ ZERO_OBJECT(pwrSetting); -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO Bus Driver: Adjusting Slot Power, Requesting adjustment for OCR:0x%8.8X \n", -+ *pOCRvalue)); -+ -+ do { -+ pwrSetting.SlotPowerEnable = TRUE; -+ /* get optimal power setting */ -+ pwrSetting.SlotPowerVoltageMask = GetPowerSetting(pHcd, pOCRvalue); -+ if (0 == pwrSetting.SlotPowerVoltageMask) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: No matching voltage for OCR \n")); -+ status = SDIO_STATUS_DEVICE_ERROR; -+ break; -+ } -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Slot Pwr Mask 0x%X for OCR:0x%8.8X \n", -+ pwrSetting.SlotPowerVoltageMask,*pOCRvalue)); -+ status = _IssueConfig(pHcd,SDCONFIG_POWER_CTRL,&pwrSetting,sizeof(pwrSetting)); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set power in hcd \n")); -+ break; -+ } -+ /* delay for power to settle */ -+ OSSleep(pBusContext->PowerSettleDelay); -+ /* save off for drivers */ -+ pHcd->CardProperties.CardVoltage = pwrSetting.SlotPowerVoltageMask; -+ -+ } while (FALSE); -+ -+ return status; -+} -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ ConvertEncodedTransSpeed - convert encoded TRANS_SPEED value to a clock rate -+ Input: TransSpeedValue - encoded transfer speed value -+ Output: -+ Return: appropriate SD clock rate -+ Notes: This function returns a rate of 0, if it could not be determined. -+ This function can check tran speed values for SD,SDIO and MMC cards -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static SD_BUSCLOCK_RATE ConvertEncodedTransSpeed(UINT8 TransSpeedValue) -+{ -+ SD_BUSCLOCK_RATE transfMul = 0; -+ UINT8 timeVal = 0; -+ -+ switch (TransSpeedValue & TRANSFER_UNIT_MULTIPIER_MASK) { -+ case 0: -+ transfMul = 10000; -+ break; -+ case 1: -+ transfMul = 100000; -+ break; -+ case 2: -+ transfMul = 1000000; -+ break; -+ case 3: -+ transfMul = 10000000; -+ break; -+ default: -+ transfMul = 0; -+ DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: Card transfer multipler is wrong (val=0x%X)! \n", -+ TransSpeedValue)); -+ break; -+ } -+ -+ switch ((TransSpeedValue & TIME_VALUE_MASK) >> TIME_VALUE_SHIFT) { -+ case 1: timeVal = 10; break; -+ case 2: timeVal = 12; break; -+ case 3: timeVal = 13; break; -+ case 4: timeVal = 15; break; -+ case 5: timeVal = 20; break; -+ case 6: timeVal = 25; break; -+ case 7: timeVal = 30; break; -+ case 8: timeVal = 35; break; -+ case 9: timeVal = 40; break; -+ case 10: timeVal = 45; break; -+ case 11: timeVal = 50; break; -+ case 12: timeVal = 55; break; -+ case 13: timeVal = 60; break; -+ case 14: timeVal = 70; break; -+ case 15: timeVal = 80; break; -+ default: timeVal = 0; -+ DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: Card time value is wrong (val=0x%X)! \n", -+ TransSpeedValue)); -+ break; -+ } -+ -+ if ((transfMul != 0) && (timeVal != 0)) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Card Reported Max: %d Hz (0x%X) \n", -+ (timeVal*transfMul), TransSpeedValue)); -+ return timeVal*transfMul; -+ } -+ -+ return 0; -+} -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ SelectDeselectCard - Select or deselect a card -+ Input: pHcd - HCD object -+ Select - select the card -+ Output: -+ Return: status -+ Notes: -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static SDIO_STATUS SelectDeselectCard(PSDHCD pHcd, BOOL Select) -+{ -+ SDIO_STATUS status; -+ -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ /* SPI mode cards do not support selection */ -+ status = SDIO_STATUS_SUCCESS; -+ } else { -+ if (!Select) { -+ /* deselect, note that deselecting a card does not return a response */ -+ status = _IssueSimpleBusRequest(pHcd, -+ CMD7,0, -+ SDREQ_FLAGS_NO_RESP,NULL); -+ } else { -+ /* select */ -+ status = _IssueSimpleBusRequest(pHcd, -+ CMD7,(pHcd->CardProperties.RCA << 16), -+ SDREQ_FLAGS_RESP_R1B,NULL); -+ } -+ } -+ -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Failed to %s card, RCA:0x%X Err:%d \n", -+ (Select ? "Select":"Deselect"), pHcd->CardProperties.RCA, status)); -+ } -+ return status; -+} -+ -+/* reorder a buffer by swapping MSB with LSB */ -+static void ReorderBuffer(UINT8 *pBuffer, INT Bytes) -+{ -+ UINT8 *pEnd; -+ UINT8 temp; -+ -+ DBG_ASSERT(!(Bytes & 1)); -+ /* point to the end */ -+ pEnd = &pBuffer[Bytes - 1]; -+ /* divide in half */ -+ Bytes = Bytes >> 1; -+ -+ while (Bytes) { -+ temp = *pBuffer; -+ /* swap bytes */ -+ *pBuffer = *pEnd; -+ *pEnd = temp; -+ pBuffer++; -+ pEnd--; -+ Bytes--; -+ } -+} -+ -+#define ADJUST_OPER_CLOCK(pBusMode,Clock) \ -+ (pBusMode)->ClockRate = min((SD_BUSCLOCK_RATE)(Clock),(pBusMode)->ClockRate) -+#define ADJUST_OPER_BLOCK_LEN(pCaps,Length) \ -+ (pCaps)->OperBlockLenLimit = min((UINT16)(Length),(pCaps)->OperBlockLenLimit) -+#define ADJUST_OPER_BLOCK_COUNT(pCaps,Count) \ -+ (pCaps)->OperBlockCountLimit = min((UINT16)(Count),(pCaps)->OperBlockCountLimit) -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ GetBusParameters - Get bus parameters for a card -+ Input: pHcd - HCD object -+ pBusMode - current bus mode on entry -+ Output: pBusMode - new adjusted bus mode -+ Return: status -+ Notes: -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static SDIO_STATUS GetBusParameters(PSDHCD pHcd, PSDCONFIG_BUS_MODE_DATA pBusMode) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ UINT8 temp; -+ UINT32 tplAddr; -+ struct SDIO_FUNC_EXT_COMMON_TPL func0ext; -+ UINT8 scrRegister[SD_SCR_BYTES]; -+ SD_BUSCLOCK_RATE cardReportedRate = 0; -+ PSDREQUEST pReq = NULL; -+ BOOL spiMode = FALSE; -+ -+ -+ if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_SPI) { -+ spiMode = TRUE; -+ } -+ -+ if (!spiMode) { -+ /* set highest bus mode bus driver is allowing (non-SPI), the code below will -+ * adjust to lower or equal settings */ -+ pBusMode->BusModeFlags = pBusContext->DefaultBusMode; -+ } -+ /* set operational parameters */ -+ pBusMode->ClockRate = pBusContext->DefaultOperClock; -+ pHcd->CardProperties.OperBlockLenLimit = pBusContext->DefaultOperBlockLen; -+ pHcd->CardProperties.OperBlockCountLimit = pBusContext->DefaultOperBlockCount; -+ -+ /* adjust operational block counts and length to match HCD */ -+ ADJUST_OPER_BLOCK_LEN(&pHcd->CardProperties,pHcd->MaxBytesPerBlock); -+ ADJUST_OPER_BLOCK_COUNT(&pHcd->CardProperties,pHcd->MaxBlocksPerTrans); -+ /* limit operational clock to the max clock rate */ -+ ADJUST_OPER_CLOCK(pBusMode,pHcd->MaxClockRate); -+ -+ if (!spiMode) { -+ /* check HCD bus mode */ -+ if (!(pHcd->Attributes & SDHCD_ATTRIB_BUS_4BIT) || -+ ((pHcd->CardProperties.Flags & CARD_SDIO) && -+ (pHcd->Attributes & SDHCD_ATTRIB_NO_4BIT_IRQ)) ) { -+ -+ if (pHcd->Attributes & SDHCD_ATTRIB_BUS_4BIT) { -+ DBG_PRINT(SDDBG_WARN, -+ ("SDIO Card Detected, but host does not support IRQs in 4 bit mode - dropping to 1 bit. \n")); -+ } -+ /* force to 1 bit mode */ -+ SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_1_BIT); -+ } -+ } -+ -+ /* now do various card inquiries to drop the bus mode or clock -+ * none of these checks can raise the bus mode or clock higher that what -+ * was initialized above */ -+ do { -+ if (pHcd->CardProperties.Flags & (CARD_SD | CARD_MMC)) { -+ /* allocate a request for response data we'll need */ -+ pReq = AllocateRequest(); -+ if (NULL == pReq) { -+ status = SDIO_STATUS_NO_RESOURCES; -+ break; -+ } -+ } -+ -+ if (!spiMode && (pHcd->CardProperties.Flags & CARD_MMC)) { -+ /* MMC cards all run in 1 bit mode */ -+ SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_1_BIT); -+ } -+ -+ if (pHcd->CardProperties.Flags & CARD_SD) { -+ DBG_ASSERT(pReq != NULL); -+ DBG_PRINT(SDDBG_TRACE, ("Getting SCR from SD Card..\n")); -+ /* read SCR (requires data transfer) to get supported modes */ -+ status = _IssueBusRequestBd(pHcd,ACMD51,0, -+ SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_APP_CMD | -+ SDREQ_FLAGS_DATA_TRANS, -+ pReq,&scrRegister,SD_SCR_BYTES); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_WARN, ("SD card does not have SCR. \n")); -+ if (!spiMode) { -+ /* switch it to 1 bit mode */ -+ SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_1_BIT); -+ } -+ status = SDIO_STATUS_SUCCESS; -+ } else { -+ /* we have to reorder this buffer since the SCR is sent MSB first on the data -+ * data bus */ -+ ReorderBuffer(scrRegister,SD_SCR_BYTES); -+ /* got the SCR */ -+ DBG_PRINT(SDDBG_TRACE, ("SD SCR StructRev:0x%X, Flags:0x%X \n", -+ GET_SD_SCR_STRUCT_VER(scrRegister), -+ GET_SD_SCR_BUSWIDTHS_FLAGS(scrRegister))); -+ /* set the revision */ -+ switch (GET_SD_SCR_SDSPEC_VER(scrRegister)) { -+ case SCR_SD_SPEC_1_00: -+ DBG_PRINT(SDDBG_TRACE, ("SD Spec Revision 1.01 \n")); -+ pHcd->CardProperties.SD_MMC_Revision = SD_REVISION_1_01; -+ break; -+ case SCR_SD_SPEC_1_10: -+ DBG_PRINT(SDDBG_TRACE, ("SD Spec Revision 1.10 \n")); -+ pHcd->CardProperties.SD_MMC_Revision = SD_REVISION_1_10; -+ break; -+ default: -+ DBG_PRINT(SDDBG_WARN, ("SD Spec Revision is greater than 1.10 \n")); -+ pHcd->CardProperties.SD_MMC_Revision = SD_REVISION_1_10; -+ break; -+ } -+ -+ if (!(GET_SD_SCR_BUSWIDTHS(scrRegister) & SCR_BUS_SUPPORTS_4_BIT)) { -+ if (!spiMode) { -+ DBG_PRINT(SDDBG_WARN, ("SD SCR reports 1bit only Mode \n")); -+ /* switch it to 1 bit mode */ -+ SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_1_BIT); -+ } -+ } -+ } -+ } -+ -+ if (pHcd->CardProperties.Flags & (CARD_SD | CARD_MMC)) { -+ DBG_ASSERT(pReq != NULL); -+ /* de-select the card in order to get the CSD */ -+ status = SelectDeselectCard(pHcd,FALSE); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to deselect card before getting CSD \n")); -+ break; -+ } -+ /* Get CSD for SD or MMC cards */ -+ if (spiMode) { -+ /* in SPI mode, getting the CSD requires a read data transfer */ -+ status = _IssueBusRequestBd(pHcd,CMD9,0, -+ SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_DATA_TRANS, -+ pReq, -+ pHcd->CardProperties.CardCSD, -+ MAX_CSD_CID_BYTES); -+ if (SDIO_SUCCESS(status)) { -+ /* when the CSD is sent over in SPI data mode, it comes to us in MSB first -+ * and thus is not ordered correctly as defined in the SD spec */ -+ ReorderBuffer(pHcd->CardProperties.CardCSD,MAX_CSD_CID_BYTES); -+ } -+ } else { -+ status = _IssueSimpleBusRequest(pHcd, -+ CMD9, -+ (pHcd->CardProperties.RCA << 16), -+ SDREQ_FLAGS_RESP_R2, -+ pReq); -+ if (SDIO_SUCCESS(status)) { -+ /* save the CSD */ -+ memcpy(pHcd->CardProperties.CardCSD,pReq->Response,MAX_CARD_RESPONSE_BYTES); -+ } -+ } -+ -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get CSD, Err:%d \n", -+ status)); -+ break; -+ } -+ /* for MMC cards, the spec version is in the CSD */ -+ if (pHcd->CardProperties.Flags & CARD_MMC) { -+ DBG_PRINT(SDDBG_TRACE, ("MMC Spec version : (0x%2.2X) \n", -+ GET_MMC_SPEC_VERSION(pHcd->CardProperties.CardCSD))); -+ switch (GET_MMC_SPEC_VERSION(pHcd->CardProperties.CardCSD)) { -+ case MMC_SPEC_1_0_TO_1_2: -+ case MMC_SPEC_1_4: -+ case MMC_SPEC_2_0_TO_2_2: -+ DBG_PRINT(SDDBG_WARN, ("MMC Spec version less than 3.1 \n")); -+ pHcd->CardProperties.SD_MMC_Revision = MMC_REVISION_1_0_2_2; -+ break; -+ case MMC_SPEC_3_1: -+ DBG_PRINT(SDDBG_TRACE, ("MMC Spec version 3.1 \n")); -+ pHcd->CardProperties.SD_MMC_Revision = MMC_REVISION_3_1; -+ break; -+ case MMC_SPEC_4_0_TO_4_1: -+ DBG_PRINT(SDDBG_TRACE, ("MMC Spec version 4.0-4.1 \n")); -+ pHcd->CardProperties.SD_MMC_Revision = MMC_REVISION_4_0; -+ break; -+ default: -+ pHcd->CardProperties.SD_MMC_Revision = MMC_REVISION_3_1; -+ DBG_PRINT(SDDBG_WARN, ("MMC Spec version greater than 4.1\n")); -+ break; -+ } -+ } -+ /* re-select the card */ -+ status = SelectDeselectCard(pHcd,TRUE); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to re-select card after getting CSD \n")); -+ break; -+ } -+ } -+ -+ if ((pHcd->CardProperties.Flags & CARD_SD) && -+ !(pHcd->CardProperties.Flags & CARD_SDIO) && -+ SDDEVICE_IS_SD_REV_GTEQ_1_10(pHcd->pPseudoDev) && -+ (pHcd->Attributes & SDHCD_ATTRIB_SD_HIGH_SPEED) && -+ !spiMode) { -+ UINT32 arg; -+ PUINT8 pSwitchStatusBlock = KernelAlloc(SD_SWITCH_FUNC_STATUS_BLOCK_BYTES); -+ -+ if (NULL == pSwitchStatusBlock) { -+ status = SDIO_STATUS_NO_RESOURCES; -+ break; -+ } -+ -+ arg = SD_SWITCH_FUNC_ARG_GROUP_CHECK(SD_SWITCH_HIGH_SPEED_GROUP, -+ SD_SWITCH_HIGH_SPEED_FUNC_NO); -+ -+ /* for 1.10 SD cards, check if high speed mode is supported */ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Checking SD Card for switchable functions (CMD6 arg:0x%X)\n",arg)); -+ -+ /* issue simple data transfer request to read the switch status */ -+ status = _IssueBusRequestBd(pHcd, -+ CMD6, -+ arg, -+ SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_DATA_TRANS, -+ pReq, -+ pSwitchStatusBlock, -+ SD_SWITCH_FUNC_STATUS_BLOCK_BYTES); -+ -+ if (SDIO_SUCCESS(status)) { -+ UINT16 switchGroupMask; -+ /* need to reorder this since cards send this MSB first */ -+ ReorderBuffer(pSwitchStatusBlock,SD_SWITCH_FUNC_STATUS_BLOCK_BYTES); -+ switchGroupMask = SD_SWITCH_FUNC_STATUS_GET_GRP_BIT_MASK(pSwitchStatusBlock,SD_SWITCH_HIGH_SPEED_GROUP); -+ DBG_PRINT(SDDBG_TRACE, ("SD Card Switch Status Group1 Mask:0x%X Max Current:%d\n", -+ switchGroupMask, SD_SWITCH_FUNC_STATUS_GET_MAX_CURRENT(pSwitchStatusBlock) )); -+ if (SD_SWITCH_FUNC_STATUS_GET_MAX_CURRENT(pSwitchStatusBlock) == 0) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: SD Switch Status block has zero max current \n")); -+ SDLIB_PrintBuffer(pSwitchStatusBlock, -+ SD_SWITCH_FUNC_STATUS_BLOCK_BYTES, -+ "SDIO Bus Driver: SD Switch Status Block Error"); -+ } else { -+ /* check HS support */ -+ if (switchGroupMask & (1 << SD_SWITCH_HIGH_SPEED_FUNC_NO)) { -+ DBG_PRINT(SDDBG_TRACE, ("SD Card Supports High Speed Mode\n")); -+ /* set the rate, this will override the CSD value */ -+ cardReportedRate = SD_HS_MAX_BUS_CLOCK; -+ pBusMode->BusModeFlags |= SDCONFIG_BUS_MODE_SD_HS; -+ } -+ } -+ } else { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get SD Switch Status block (%d)\n", status)); -+ /* just fall through, we'll handle this like a normal SD card */ -+ status = SDIO_STATUS_SUCCESS; -+ } -+ -+ KernelFree(pSwitchStatusBlock); -+ } -+ -+ if ((pHcd->CardProperties.Flags & CARD_MMC) && -+ SDDEVICE_IS_MMC_REV_GTEQ_4_0(pHcd->pPseudoDev) && -+ (pHcd->Attributes & SDHCD_ATTRIB_MMC_HIGH_SPEED) && -+ !spiMode) { -+ /* for MMC cards, get the Extended CSD to get the High speed and -+ * wide bus paramaters */ -+ -+ PUINT8 pExtData = KernelAlloc(MMC_EXT_CSD_SIZE); -+ -+ if (NULL == pExtData) { -+ status = SDIO_STATUS_NO_RESOURCES; -+ break; -+ } -+ /* issue simple data transfer request to read the extended CSD */ -+ status = _IssueBusRequestBd(pHcd,MMC_CMD8,0, -+ SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_DATA_TRANS, -+ pReq, -+ pExtData, -+ MMC_EXT_CSD_SIZE); -+ if (SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_TRACE, ("MMC Ext CSD Version: 0x%X Card Type: 0x%X\n", -+ pExtData[MMC_EXT_VER_OFFSET],pExtData[MMC_EXT_CARD_TYPE_OFFSET])); -+ /* check HS support */ -+ if (pExtData[MMC_EXT_CARD_TYPE_OFFSET] & MMC_EXT_CARD_TYPE_HS_52) { -+ /* try 52 Mhz */ -+ cardReportedRate = 52000000; -+ pBusMode->BusModeFlags |= SDCONFIG_BUS_MODE_MMC_HS; -+ } else if (pExtData[MMC_EXT_CARD_TYPE_OFFSET] & MMC_EXT_CARD_TYPE_HS_26) { -+ /* try 26MHZ */ -+ cardReportedRate = 26000000; -+ pBusMode->BusModeFlags |= SDCONFIG_BUS_MODE_MMC_HS; -+ } else { -+ /* doesn't report high speed capable */ -+ cardReportedRate = 0; -+ } -+ -+ if (cardReportedRate && !spiMode) { -+ /* figure out the bus mode */ -+ if (pHcd->Attributes & SDHCD_ATTRIB_BUS_MMC8BIT) { -+ SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_MMC8_BIT); -+ } else if (pHcd->Attributes & SDHCD_ATTRIB_BUS_4BIT) { -+ SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_4_BIT); -+ } else { -+ /* we leave it to default to 1 bit mode */ -+ } -+ } -+ } else { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get MMC Extended CSD \n")); -+ /* just fall through, we'll do without the extended information -+ * and run it like a legacy MMC card */ -+ status = SDIO_STATUS_SUCCESS; -+ } -+ -+ KernelFree(pExtData); -+ } -+ -+ if (pHcd->CardProperties.Flags & (CARD_SD | CARD_MMC)) { -+ -+ if (0 == cardReportedRate) { -+ /* extract rate from CSD only if it was not set by earlier tests */ -+ cardReportedRate = ConvertEncodedTransSpeed( -+ GET_SD_CSD_TRANS_SPEED(pHcd->CardProperties.CardCSD)); -+ /* fall through and test for zero again */ -+ } -+ -+ if (cardReportedRate != 0) { -+ /* adjust clock based on what the card can handle */ -+ ADJUST_OPER_CLOCK(pBusMode,cardReportedRate); -+ } else { -+ /* something is wrong with the CSD */ -+ if (DBG_GET_DEBUG_LEVEL() >= SDDBG_TRACE) { -+ SDLIB_PrintBuffer(pHcd->CardProperties.CardCSD, -+ MAX_CARD_RESPONSE_BYTES, -+ "SDIO Bus Driver: CSD Dump"); -+ } -+ /* can't figure out the card rate, so set reasonable defaults */ -+ if (pHcd->CardProperties.Flags & CARD_SD) { -+ ADJUST_OPER_CLOCK(pBusMode,SD_MAX_BUS_CLOCK); -+ } else { -+ ADJUST_OPER_CLOCK(pBusMode,MMC_MAX_BUS_CLOCK); -+ } -+ } -+ } -+ -+ /* note, we do SDIO card "after" SD in case this is a combo card */ -+ if (pHcd->CardProperties.Flags & CARD_SDIO) { -+ /* read card capabilities */ -+ status = Cmd52ReadByteCommon(pHcd->pPseudoDev, -+ SDIO_CARD_CAPS_REG, -+ &pHcd->CardProperties.SDIOCaps); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Card Caps: 0x%X \n",pHcd->CardProperties.SDIOCaps)); -+ if (pHcd->CardProperties.SDIOCaps & SDIO_CAPS_LOW_SPEED) { -+ /* adjust max clock for LS device */ -+ ADJUST_OPER_CLOCK(pBusMode,SDIO_LOW_SPEED_MAX_BUS_CLOCK); -+ /* adjust bus if LS device does not support 4 bit mode */ -+ if (!(pHcd->CardProperties.SDIOCaps & SDIO_CAPS_4BIT_LS)) { -+ if (!spiMode) { -+ /* low speed device does not support 4 bit mode, force us to 1 bit */ -+ SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, -+ SDCONFIG_BUS_WIDTH_1_BIT); -+ } -+ } -+ } -+ -+ /* check if 1.2 card supports high speed mode, checking HCD as well*/ -+ if (SDDEVICE_IS_SDIO_REV_GTEQ_1_20(pHcd->pPseudoDev) && -+ (pHcd->Attributes & SDHCD_ATTRIB_SD_HIGH_SPEED) && -+ !spiMode) { -+ UCHAR hsControl = 0; -+ -+ status = Cmd52ReadByteCommon(pHcd->pPseudoDev, -+ SDIO_HS_CONTROL_REG, -+ &hsControl); -+ -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO Failed to read high speed control (%d) \n",status)); -+ /* reset status and continue */ -+ status = SDIO_STATUS_SUCCESS; -+ } else { -+ if (hsControl & SDIO_HS_CONTROL_SHS) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Card Supports High Speed Mode\n")); -+ pBusMode->BusModeFlags |= SDCONFIG_BUS_MODE_SD_HS; -+ } -+ } -+ -+ } -+ -+ cardReportedRate = 0; -+ temp = sizeof(func0ext); -+ tplAddr = pHcd->CardProperties.CommonCISPtr; -+ /* get the FUNCE tuple */ -+ status = SDLIB_FindTuple(pHcd->pPseudoDev, -+ CISTPL_FUNCE, -+ &tplAddr, -+ (PUINT8)&func0ext, -+ &temp); -+ if (!SDIO_SUCCESS(status) || (temp < sizeof(func0ext))) { -+ DBG_PRINT(SDDBG_WARN, ("SDIO Function 0 Ext. Tuple Missing (Got size:%d) \n", temp)); -+ /* reset status */ -+ status = SDIO_STATUS_SUCCESS; -+ } else { -+ /* convert encoded value to rate */ -+ cardReportedRate = ConvertEncodedTransSpeed(func0ext.MaxTransSpeed); -+ } -+ -+ if (cardReportedRate != 0) { -+ if (pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_SD_HS) { -+ if (cardReportedRate <= SD_MAX_BUS_CLOCK) { -+ DBG_PRINT(SDDBG_WARN, -+ ("SDIO Function tuple reports clock:%d Hz, with advertised High Speed support \n", cardReportedRate)); -+ /* back off high speed support */ -+ pBusMode->BusModeFlags &= ~SDCONFIG_BUS_MODE_SD_HS; -+ } -+ } else { -+ if (cardReportedRate > SD_MAX_BUS_CLOCK) { -+ DBG_PRINT(SDDBG_WARN, -+ ("SDIO Function tuple reports clock:%d Hz, without advertising High Speed support..using 25Mhz \n", cardReportedRate)); -+ cardReportedRate = SD_MAX_BUS_CLOCK; -+ } -+ } -+ /* adjust clock based on what the card can handle */ -+ ADJUST_OPER_CLOCK(pBusMode,cardReportedRate); -+ -+ } else { -+ /* set a reasonable default */ -+ ADJUST_OPER_CLOCK(pBusMode,SD_MAX_BUS_CLOCK); -+ } -+ } -+ } while (FALSE); -+ -+ if (pReq != NULL) { -+ FreeRequest(pReq); -+ } -+ return status; -+} -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ SetOperationalBusMode - set operational bus mode -+ Input: pDevice - pDevice that is requesting the change -+ pBusMode - operational bus mode -+ Output: pBusMode - on return will have the actual clock rate set -+ Return: status -+ Notes: -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS SetOperationalBusMode(PSDDEVICE pDevice, -+ PSDCONFIG_BUS_MODE_DATA pBusMode) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ UCHAR regData; -+ UINT32 arg; -+ UINT32 switcharg; -+ PSDHCD pHcd = pDevice->pHcd; -+ -+ /* synchronize access for updating bus mode settings */ -+ status = SemaphorePendInterruptable(&pDevice->pHcd->ConfigureOpsSem); -+ if (!SDIO_SUCCESS(status)) { -+ return status; -+ } -+ -+ do { -+ -+ if (!IS_CARD_PRESENT(pHcd)) { -+ /* for an empty slot (a Pseudo dev was passed in) we still allow the -+ * bus mode to be set for the card detect -+ * polling */ -+ status = _IssueConfig(pHcd,SDCONFIG_BUS_MODE_CTRL,pBusMode,sizeof(SDCONFIG_BUS_MODE_DATA)); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set bus mode in hcd : Err:%d \n", -+ status)); -+ } -+ /* nothing more to do */ -+ break; -+ } -+ -+ -+ if ((pBusMode->BusModeFlags == SDDEVICE_GET_BUSMODE_FLAGS(pDevice)) && -+ (pBusMode->ClockRate == SDDEVICE_GET_OPER_CLOCK(pDevice))) { -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO Bus Driver: Bus mode already set, nothing to do\n")); -+ pBusMode->ActualClockRate = SDDEVICE_GET_OPER_CLOCK(pDevice); -+ break; -+ } -+ -+ if (pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_MMC_HS) { -+ if (!(pHcd->Attributes & SDHCD_ATTRIB_MMC_HIGH_SPEED)) { -+ status = SDIO_STATUS_INVALID_PARAMETER; -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO Bus Driver: HCD does not support MMC High Speed\n")); -+ break; -+ } -+ } -+ -+ if (pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_SD_HS) { -+ if (!(pHcd->Attributes & SDHCD_ATTRIB_SD_HIGH_SPEED)) { -+ status = SDIO_STATUS_INVALID_PARAMETER; -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO Bus Driver: HCD does not support SD High Speed\n")); -+ break; -+ } -+ } -+ -+ /* before we set the operational clock and mode, configure the clock for high -+ * speed mode on the card , if necessary */ -+ if ((pHcd->CardProperties.Flags & CARD_MMC) && -+ (pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_MMC_HS) && -+ !(SDDEVICE_GET_BUSMODE_FLAGS(pDevice) & SDCONFIG_BUS_MODE_MMC_HS)) { -+ -+ switcharg = MMC_SWITCH_BUILD_ARG(MMC_SWITCH_CMD_SET0, -+ MMC_SWITCH_WRITE_BYTE, -+ MMC_EXT_HS_TIMING_OFFSET, -+ MMC_EXT_HS_TIMING_ENABLE); -+ status = _IssueSimpleBusRequest(pHcd, -+ MMC_CMD_SWITCH, -+ switcharg, -+ SDREQ_FLAGS_RESP_R1B, -+ NULL); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO Bus Driver: Failed to switch MMC High Speed Mode (arg:0x%X): %d \n", -+ switcharg, status)); -+ break; -+ } -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: High Speed MMC enabled (arg:0x%X)\n", -+ switcharg)); -+ } -+ -+ /* before setting bus mode and clock in the HCD, switch card to high speed mode -+ * if necessary */ -+ if ((pHcd->CardProperties.Flags & CARD_SD) && -+ (pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_SD_HS) && -+ !(SDDEVICE_GET_BUSMODE_FLAGS(pDevice) & SDCONFIG_BUS_MODE_SD_HS)) { -+ UINT32 arg; -+ PUINT8 pSwitchStatusBlock; -+ -+ pSwitchStatusBlock = KernelAlloc(SD_SWITCH_FUNC_STATUS_BLOCK_BYTES); -+ -+ if (NULL == pSwitchStatusBlock) { -+ status = SDIO_STATUS_NO_RESOURCES; -+ break; -+ } -+ -+ /* set high speed group */ -+ arg = SD_SWITCH_FUNC_ARG_GROUP_SET(SD_SWITCH_HIGH_SPEED_GROUP, -+ SD_SWITCH_HIGH_SPEED_FUNC_NO); -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Setting SD Card for High Speed mode (CMD6 arg:0x%X)\n",arg)); -+ -+ /* issue simple data transfer request to switch modes */ -+ status = _IssueBusRequestBd(pHcd, -+ CMD6, -+ arg, -+ SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_DATA_TRANS, -+ NULL, -+ pSwitchStatusBlock, -+ SD_SWITCH_FUNC_STATUS_BLOCK_BYTES); -+ -+ if (SDIO_SUCCESS(status)) { -+ ReorderBuffer(pSwitchStatusBlock,SD_SWITCH_FUNC_STATUS_BLOCK_BYTES); -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD High Speed Result, Got Max Current:%d mA, SwitchResult:0x%X \n", -+ SD_SWITCH_FUNC_STATUS_GET_MAX_CURRENT(pSwitchStatusBlock), -+ SDSwitchGetSwitchResult(pSwitchStatusBlock, SD_SWITCH_HIGH_SPEED_GROUP))); -+ if (SD_SWITCH_FUNC_STATUS_GET_MAX_CURRENT(pSwitchStatusBlock) == 0) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Error in Status Block after High Speed Switch (current==0) \n")); -+ status = SDIO_STATUS_DEVICE_ERROR; -+ } -+ if (SDSwitchGetSwitchResult(pSwitchStatusBlock, SD_SWITCH_HIGH_SPEED_GROUP) != -+ SD_SWITCH_HIGH_SPEED_FUNC_NO) { -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO Bus Driver: Error in Status Block after High Speed Switch (Group1 did not switch) \n")); -+ status = SDIO_STATUS_DEVICE_ERROR; -+ } -+ if (SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD High Speed Mode Enabled \n")); -+ } else { -+ SDLIB_PrintBuffer(pSwitchStatusBlock, -+ SD_SWITCH_FUNC_STATUS_BLOCK_BYTES, -+ "SDIO Bus Driver: SD Switch Status Block Error"); -+ } -+ } else { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to Set SD High Speed Mode (%d) \n",status)); -+ } -+ KernelFree(pSwitchStatusBlock); -+ -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ } -+ -+ /* enable/disable high speed mode for SDIO card */ -+ if (pHcd->CardProperties.Flags & CARD_SDIO) { -+ BOOL doSet = TRUE; -+ -+ if ((pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_SD_HS) && -+ !(SDDEVICE_GET_BUSMODE_FLAGS(pDevice) & SDCONFIG_BUS_MODE_SD_HS)) { -+ /* enable */ -+ regData = SDIO_HS_CONTROL_EHS; -+ } else if (!(pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_SD_HS) && -+ (SDDEVICE_GET_BUSMODE_FLAGS(pDevice) & SDCONFIG_BUS_MODE_SD_HS)) { -+ /* disable */ -+ regData = 0; -+ } else { -+ /* do nothing */ -+ doSet = FALSE; -+ } -+ -+ if (doSet) { -+ status = Cmd52WriteByteCommon(pDevice, -+ SDIO_HS_CONTROL_REG, -+ ®Data); -+ -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to %s HS mode in SDIO card : Err:%d\n", -+ (SDIO_HS_CONTROL_EHS == regData) ? "enable":"disable" , status)); -+ break; -+ } else { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver:SDIO Card %s for High Speed mode \n", -+ (SDIO_HS_CONTROL_EHS == regData) ? "enabled":"disabled" )); -+ } -+ } -+ } -+ -+ /* use synchronize-with-bus request version, this may have been requested by a -+ * function driver */ -+ status = SDLIB_IssueConfig(pDevice, -+ SDCONFIG_BUS_MODE_CTRL, -+ pBusMode, -+ sizeof(SDCONFIG_BUS_MODE_DATA)); -+ -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set bus mode in hcd : Err:%d \n", -+ status)); -+ break; -+ } -+ -+ /* check requested bus width against the current mode */ -+ if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == -+ SDCONFIG_GET_BUSWIDTH(pHcd->CardProperties.BusMode)) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Bus mode set, no width change\n")); -+ break; -+ } -+ -+ if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_SPI) { -+ /* nothing more to do for SPI */ -+ break; -+ } -+ -+ /* set the bus width for SD and combo cards */ -+ if (pHcd->CardProperties.Flags & CARD_SD) { -+ if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_4_BIT) { -+ /* turn off card detect resistor */ -+ status = _IssueSimpleBusRequest(pHcd, -+ ACMD42, -+ 0, /* disable CD */ -+ SDREQ_FLAGS_APP_CMD | SDREQ_FLAGS_RESP_R1, -+ NULL); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: Failed to disable CD Res: %d \n", -+ status)); /* this should be okay */ -+ } -+ arg = SD_ACMD6_BUS_WIDTH_4_BIT; -+ } else { -+ /* don't need to turn off CD in 1 bit mode, just set mode */ -+ arg = SD_ACMD6_BUS_WIDTH_1_BIT; -+ -+ } -+ /* set the bus width */ -+ status = _IssueSimpleBusRequest(pHcd, -+ ACMD6, -+ arg, /* set bus mode */ -+ SDREQ_FLAGS_APP_CMD | SDREQ_FLAGS_RESP_R1, -+ NULL); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set bus width: %d \n", -+ status)); -+ break; -+ } -+ } -+ /* set bus width for SDIO cards */ -+ if (pHcd->CardProperties.Flags & CARD_SDIO) { -+ /* default */ -+ regData = CARD_DETECT_DISABLE | SDIO_BUS_WIDTH_1_BIT; -+ -+ if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_4_BIT) { -+ /* turn off card detect resistor and set buswidth */ -+ regData = CARD_DETECT_DISABLE | SDIO_BUS_WIDTH_4_BIT; -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Enabling 4 bit mode on card \n")); -+ } else { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Enabling 1 bit mode on card \n")); -+ } -+ status = Cmd52WriteByteCommon(pDevice, -+ SDIO_BUS_IF_REG, -+ ®Data); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set bus mode in Card : Err:%d\n", -+ status)); -+ break; -+ } -+ -+ /* check for 4-bit interrupt detect mode */ -+ if ((SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_4_BIT) && -+ (pHcd->CardProperties.SDIOCaps & SDIO_CAPS_INT_MULTI_BLK) && -+ (pHcd->Attributes & SDHCD_ATTRIB_MULTI_BLK_IRQ)) { -+ /* enable interrupts between blocks, this doesn't actually turn on interrupts -+ * it merely allows interrupts to be asserted in the inter-block gap */ -+ pHcd->CardProperties.SDIOCaps |= SDIO_CAPS_ENB_INT_MULTI_BLK; -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: 4-Bit Multi-blk Interrupt support enabled\n")); -+ } else { -+ /* make sure this is disabled */ -+ pHcd->CardProperties.SDIOCaps &= ~SDIO_CAPS_ENB_INT_MULTI_BLK; -+ } -+ -+ status = Cmd52WriteByteCommon(pDevice, -+ SDIO_CARD_CAPS_REG, -+ &pHcd->CardProperties.SDIOCaps); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to update Card Caps register Err:%d\n", -+ status)); -+ break; -+ } -+ } -+ -+ /* set data bus width for MMC */ -+ if (pHcd->CardProperties.Flags & CARD_MMC) { -+ UINT8 buswidth = 0; -+ -+ if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_4_BIT) { -+ buswidth = MMC_EXT_BUS_WIDTH_4_BIT; -+ } else if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_MMC8_BIT) { -+ buswidth = MMC_EXT_BUS_WIDTH_8_BIT; -+ } else { -+ /* normal 1 bit mode .. nothing to do */ -+ break; -+ } -+ /* now set the bus mode on the card */ -+ switcharg = MMC_SWITCH_BUILD_ARG(MMC_SWITCH_CMD_SET0, -+ MMC_SWITCH_WRITE_BYTE, -+ MMC_EXT_BUS_WIDTH_OFFSET, -+ buswidth); -+ -+ status = _IssueSimpleBusRequest(pHcd, -+ MMC_CMD_SWITCH, -+ switcharg, -+ SDREQ_FLAGS_RESP_R1B, -+ NULL); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set MMC bus width (arg:0x%X): %d \n", -+ switcharg, status)); -+ break; -+ } -+ -+ if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_4_BIT) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: 4 bit MMC mode enabled (arg:0x%X) \n", -+ switcharg)); -+ } else if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_MMC8_BIT) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: 8-Bit MMC mode enabled (arg:0x%X) \n", -+ switcharg)); -+ } -+ } -+ -+ } while (FALSE); -+ -+ if (SDIO_SUCCESS(status)) { -+ /* set the operating mode */ -+ pHcd->CardProperties.BusMode = pBusMode->BusModeFlags; -+ /* set the actual clock rate */ -+ pHcd->CardProperties.OperBusClock = pBusMode->ActualClockRate; -+ } -+ -+ SemaphorePost(&pDevice->pHcd->ConfigureOpsSem); -+ -+ return status; -+} -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ CardInitSetup - setup host for card initialization -+ Input: pHcd - HCD object -+ Output: -+ Return: -+ Notes: -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS CardInitSetup(PSDHCD pHcd) -+{ -+ SDCONFIG_INIT_CLOCKS_DATA initClocks; -+ SDCONFIG_BUS_MODE_DATA busMode; -+ UINT32 OCRvalue; -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ -+ ZERO_OBJECT(initClocks); -+ ZERO_OBJECT(busMode); -+ /* setup defaults */ -+ initClocks.NumberOfClocks = SDMMC_MIN_INIT_CLOCKS; -+ busMode.ClockRate = SD_INIT_BUS_CLOCK; -+ -+ /* check for SPI only */ -+ if (pHcd->Attributes & SDHCD_ATTRIB_BUS_SPI) { -+ /* SPI cards startup in non-CRC mode with the exception of CMD0, the -+ * HCDs must issue CMD0 with the correct CRC , the spec shows that a -+ * CMD 0 sequence is 0x40,0x00,0x00,0x00,0x00,0x95 */ -+ busMode.BusModeFlags = SDCONFIG_BUS_WIDTH_SPI | SDCONFIG_BUS_MODE_SPI_NO_CRC; -+ } -+ /* check if host supports 1 bit mode */ -+ /* TODO : if host supports power switching, we can -+ * could initialize cards in SPI mode first */ -+ if (pHcd->Attributes & SDHCD_ATTRIB_BUS_1BIT) { -+ busMode.BusModeFlags = SDCONFIG_BUS_WIDTH_1_BIT; -+ } -+ -+ /* set initial VDD, starting at the highest allowable voltage and working -+ * our way down */ -+ if (pHcd->SlotVoltageCaps & SLOT_POWER_3_3V) { -+ OCRvalue = SD_OCR_3_2_TO_3_3_VDD; -+ } else if (pHcd->SlotVoltageCaps & SLOT_POWER_3_0V) { -+ OCRvalue = SD_OCR_2_9_TO_3_0_VDD; -+ } else if (pHcd->SlotVoltageCaps & SLOT_POWER_2_8V) { -+ OCRvalue = SD_OCR_2_7_TO_2_8_VDD; -+ } else if (pHcd->SlotVoltageCaps & SLOT_POWER_2_0V) { -+ OCRvalue = SD_OCR_1_9_TO_2_0_VDD; -+ } else if (pHcd->SlotVoltageCaps & SLOT_POWER_1_8V) { -+ OCRvalue = SD_OCR_1_7_TO_1_8_VDD; -+ } else if (pHcd->SlotVoltageCaps & SLOT_POWER_1_6V) { -+ OCRvalue = SD_OCR_1_6_TO_1_7_VDD; -+ } else { -+ DBG_ASSERT(FALSE); -+ OCRvalue = 0; -+ } -+ -+ do { -+ /* power up the card */ -+ status = AdjustSlotPower(pHcd, &OCRvalue); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to adjust slot power \n")); -+ break; -+ } -+ status = SetOperationalBusMode(pHcd->pPseudoDev,&busMode); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set bus mode \n")); -+ break; -+ } -+ status = _IssueConfig(pHcd,SDCONFIG_SEND_INIT_CLOCKS,&initClocks,sizeof(initClocks)); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to send init clocks in hcd \n")); -+ break; -+ } -+ -+ } while(FALSE); -+ -+ return status; -+} -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ SDInitializeCard - initialize card -+ Input: pHcd - HCD object -+ Output: pProperties - card properties -+ Return: -+ Notes: -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS SDInitializeCard(PSDHCD pHcd) -+{ -+ SDCONFIG_BUS_MODE_DATA busMode; -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ PSDREQUEST pReq = NULL; -+ UINT32 OCRvalue; -+ UINT32 tplAddr; -+ UINT8 temp; -+ struct SDIO_MANFID_TPL manfid; -+ SDCONFIG_WP_VALUE wpValue; -+ UINT8 cisBuffer[3]; -+ -+ OCRvalue = 0; -+ -+ do { -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Initializing card in SPI mode \n")); -+ } else { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Initializing card in MMC/SD mode \n")); -+ } -+ -+ pReq = AllocateRequest(); -+ if (NULL == pReq) { -+ status = SDIO_STATUS_NO_RESOURCES; -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: failed to allocate bus request \n")); -+ break; -+ } -+ memset(pReq, 0, sizeof(SDREQUEST)); -+ -+ status = CardInitSetup(pHcd); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to setup card \n")); -+ break; -+ } -+ status = _IssueConfig(pHcd,SDCONFIG_GET_WP,&wpValue,sizeof(wpValue)); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: host doesn't support Write Protect \n")); -+ } else { -+ if (wpValue) { -+ pHcd->CardProperties.Flags |= CARD_SD_WP; -+ DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: SD WP switch is on \n")); -+ } -+ } -+ -+ if (!(pHcd->Attributes & SDHCD_ATTRIB_SLOT_POLLING) && -+ IS_HCD_BUS_MODE_SPI(pHcd)) { -+ /* for non-slot polling HCDs operating in SPI mode -+ * issue CMD0 to reset card state and to place the card -+ * in SPI mode. If slot polling is used, the polling thread -+ * will have already issued a CMD0 to place the card in SPI mode*/ -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ INT ii = 256; -+ status = SDIO_STATUS_ERROR; -+ /* if the CMD0 fails, retry it. Some cards have a hard time getting into SPI mode.*/ -+ while ((!SDIO_SUCCESS(status)) && (ii-- >= 0)) { -+ status = _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_RESP_R1,pReq); -+ OSSleep(20); -+ } -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: cmd0 go SPI retries:(256) %d\n", ii)); -+ -+ } else { -+ status = _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_NO_RESP,pReq); -+ } -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: go-idle failed! \n")); -+ break; -+ } -+ } -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Looking for SDIO.. \n")); -+ /* check for SDIO card by trying to read it's OCR */ -+ status = ReadOCR(pHcd,CARD_SDIO,pReq,0,&OCRvalue); -+ if (SDIO_SUCCESS(status)) { -+ /* we got a response, this is an SDIO card */ -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ /* handle SPI */ -+ pHcd->CardProperties.IOFnCount = SPI_SDIO_R4_GET_IO_FUNC_COUNT(pReq->Response); -+ if (SPI_SDIO_R4_IS_MEMORY_PRESENT(pReq->Response)) { -+ /* flag an SD function exists */ -+ pHcd->CardProperties.Flags |= CARD_SD; -+ } -+ } else { -+ /* handle native SD */ -+ pHcd->CardProperties.IOFnCount = SD_SDIO_R4_GET_IO_FUNC_COUNT(pReq->Response); -+ if (SD_SDIO_R4_IS_MEMORY_PRESENT(pReq->Response)) { -+ /* flag an SD function exists */ -+ pHcd->CardProperties.Flags |= CARD_SD; -+ } -+ -+ } -+ if (0 == pHcd->CardProperties.IOFnCount) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SDIO Card reports no functions \n")); -+ status = SDIO_STATUS_DEVICE_ERROR; -+ pHcd->CardProperties.Flags = 0; -+ break; -+ } -+ pHcd->CardProperties.Flags |= CARD_SDIO; -+ -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO Bus Driver: SDIO Card, Functions: %d Card Info Flags:0x%X OCR:0x%8.8X\n", -+ pHcd->CardProperties.IOFnCount, pHcd->CardProperties.Flags, OCRvalue)); -+ /* adjust slot power for this SDIO card */ -+ status = AdjustSlotPower(pHcd, &OCRvalue); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set power in hcd \n")); -+ break; -+ } -+ /* poll for SDIO card ready */ -+ status = PollCardReady(pHcd,OCRvalue,CARD_SDIO); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ } else if (status != SDIO_STATUS_BUS_RESP_TIMEOUT){ -+ /* major error in hcd, bail */ -+ break; -+ } -+ -+ /* check if this is an SDIO-only card before continuing */ -+ if (!(pHcd->CardProperties.Flags & CARD_SD) && (pHcd->CardProperties.Flags & CARD_SDIO)) { -+ /* this is an SDIO card with no memory function */ -+ goto prepareCard; -+ } -+ -+ if (!(pHcd->CardProperties.Flags & CARD_SDIO)) { -+ /* issue go idle only if we did not find an SDIO function in our earlier test */ -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ status = _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_RESP_R1,pReq); -+ } else { -+ status = _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_NO_RESP,pReq); -+ } -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: go-idle failed! \n")); -+ break; -+ } -+ } -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Looking for SD Memory.. \n")); -+ /* SD Memory Card checking */ -+ /* test for present of SD card (stand-alone or combo card) */ -+ status = TestPresence(pHcd, CARD_SD, pReq); -+ if (SDIO_SUCCESS(status)) { -+ /* there is an SD Card present, could be part of a combo system */ -+ pHcd->CardProperties.Flags |= CARD_SD; -+ if (0 == OCRvalue) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD Memory card detected. \n")); -+ /* no OCR value on entry this is a stand-alone card, go and get it*/ -+ status = ReadOCR(pHcd,CARD_SD,pReq,0,&OCRvalue); -+ if (!SDIO_SUCCESS(status) || (OCRvalue == 0)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get OCR (status:%d) \n", -+ status)); -+ break; -+ } -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD Card Reports OCR:0x%8.8X \n", OCRvalue)); -+ status = AdjustSlotPower(pHcd, &OCRvalue); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to adjust power \n")); -+ break; -+ } -+ } else { -+ DBG_ASSERT((pHcd->CardProperties.Flags & (CARD_SD | CARD_SDIO))); -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SDIO Combo Card detected \n")); -+ } -+ /* poll for SD card ready */ -+ status = PollCardReady(pHcd,OCRvalue,CARD_SD); -+ if (!SDIO_SUCCESS(status)) { -+ /* check if this card has an SDIO function */ -+ if (pHcd->CardProperties.Flags & CARD_SDIO) { -+ DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: Combo Detected but SD memory function failed \n")); -+ /* allow SDIO functions to load normally */ -+ status = SDIO_STATUS_SUCCESS; -+ /* remove SD flag */ -+ pHcd->CardProperties.Flags &= ~CARD_SD; -+ } else { -+ break; -+ } -+ } else { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD Memory ready. \n")); -+ } -+ /* we're done, no need to check for MMC */ -+ goto prepareCard; -+ } else if (status != SDIO_STATUS_BUS_RESP_TIMEOUT){ -+ /* major error in hcd, bail */ -+ break; -+ } -+ -+ /* MMC card checking */ -+ /* if we get here, these better not be set */ -+ DBG_ASSERT(!(pHcd->CardProperties.Flags & (CARD_SD | CARD_SDIO))); -+ /* issue go idle */ -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ status = _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_RESP_R1,pReq); -+ } else { -+ status = _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_NO_RESP,pReq); -+ } -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: go-idle failed! \n")); -+ break; -+ } -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Looking for MMC.. \n")); -+ status = TestPresence(pHcd, CARD_MMC, pReq); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: unknown card detected \n")); -+ break; -+ } -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: MMC Card Detected \n")); -+ pHcd->CardProperties.Flags |= CARD_MMC; -+ /* read the OCR value */ -+ status = ReadOCR(pHcd,CARD_MMC,pReq,0,&OCRvalue); -+ if (!SDIO_SUCCESS(status) || (OCRvalue == 0)) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Failed to get OCR (status:%d)", -+ status)); -+ break; -+ } -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: MMC Card Reports OCR:0x%8.8X \n", OCRvalue)); -+ /* adjust power */ -+ status = AdjustSlotPower(pHcd, &OCRvalue); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to adjust power \n")); -+ break; -+ } -+ /* poll for MMC card ready */ -+ status = PollCardReady(pHcd,OCRvalue,CARD_MMC); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ /* fall through and prepare MMC card */ -+ -+prepareCard: -+ /* we're done figuring out what was inserted, and setting up -+ * optimal slot voltage, now we need to prepare the card */ -+ if (!IS_HCD_BUS_MODE_SPI(pHcd) && -+ (pHcd->CardProperties.Flags & (CARD_SD | CARD_MMC))) { -+ /* non-SPI SD or MMC cards need to be moved to the "ident" state before we can get the -+ * RCA or select the card using the new RCA */ -+ status = _IssueSimpleBusRequest(pHcd,CMD2,0,SDREQ_FLAGS_RESP_R2,pReq); -+ if (!SDIO_SUCCESS(status)){ -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: failed to move SD/MMC card into ident state \n")); -+ break; -+ } -+ } -+ -+ if (!IS_HCD_BUS_MODE_SPI(pHcd)) { -+ /* non-SPI mode cards need their RCA's setup */ -+ if (pHcd->CardProperties.Flags & (CARD_SD | CARD_SDIO)) { -+ /* issue CMD3 to get RCA on SD/SDIO cards */ -+ status = _IssueSimpleBusRequest(pHcd,CMD3,0,SDREQ_FLAGS_RESP_R6,pReq); -+ if (!SDIO_SUCCESS(status)){ -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: failed to get RCA for SD/SDIO card \n")); -+ break; -+ } -+ pHcd->CardProperties.RCA = SD_R6_GET_RCA(pReq->Response); -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD/SDIO RCA:0x%X \n", -+ pHcd->CardProperties.RCA)); -+ } else if (pHcd->CardProperties.Flags & CARD_MMC) { -+ /* for MMC cards, we have to assign a relative card address */ -+ /* just a non-zero number */ -+ pHcd->CardProperties.RCA = 1; -+ /* issue CMD3 to set the RCA for MMC cards */ -+ status = _IssueSimpleBusRequest(pHcd, -+ CMD3,(pHcd->CardProperties.RCA << 16), -+ SDREQ_FLAGS_RESP_R1,pReq); -+ if (!SDIO_SUCCESS(status)){ -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO Bus Driver: failed to set RCA for MMC card! (err=%d) \n",status)); -+ break; -+ } -+ } else { -+ DBG_ASSERT(FALSE); -+ } -+ } -+ /* select the card in order to get the rest of the card info, applies -+ * to SDIO/SD/MMC cards*/ -+ status = SelectDeselectCard(pHcd, TRUE); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: failed to select card! \n")); -+ break; -+ } -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver, Card now Selected.. \n")); -+ -+ if (pHcd->CardProperties.Flags & CARD_SDIO) { -+ /* read SDIO revision register */ -+ status = Cmd52ReadByteCommon(pHcd->pPseudoDev, CCCR_SDIO_REVISION_REG, &temp); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Revision Reg: 0x%X \n", temp)); -+ switch (temp & SDIO_REV_MASK) { -+ case SDIO_REV_1_00: -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Spec Revision 1.00 \n")); -+ pHcd->CardProperties.SDIORevision = SDIO_REVISION_1_00; -+ break; -+ case SDIO_REV_1_10: -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Spec Revision 1.10 \n")); -+ pHcd->CardProperties.SDIORevision = SDIO_REVISION_1_10; -+ break; -+ case SDIO_REV_1_20: -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Spec Revision 1.20 \n")); -+ pHcd->CardProperties.SDIORevision = SDIO_REVISION_1_20; -+ break; -+ default: -+ DBG_PRINT(SDDBG_WARN, ("SDIO Warning: unknown SDIO revision, treating like 1.0 device \n")); -+ pHcd->CardProperties.SDIORevision = SDIO_REVISION_1_00; -+ break; -+ } -+ /* get the common CIS ptr */ -+ status = Cmd52ReadMultipleCommon(pHcd->pPseudoDev, -+ SDIO_CMN_CIS_PTR_LOW_REG, -+ cisBuffer, -+ 3); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get CIS ptr, Err:%d", status)); -+ break; -+ } -+ /* this is endian-safe*/ -+ pHcd->CardProperties.CommonCISPtr = ((UINT32)cisBuffer[0]) | -+ (((UINT32)cisBuffer[1]) << 8) | -+ (((UINT32)cisBuffer[2]) << 16); -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Card CIS Ptr: 0x%X \n", pHcd->CardProperties.CommonCISPtr)); -+ temp = sizeof(manfid); -+ tplAddr = pHcd->CardProperties.CommonCISPtr; -+ /* get the MANFID tuple */ -+ status = SDLIB_FindTuple(pHcd->pPseudoDev, -+ CISTPL_MANFID, -+ &tplAddr, -+ (PUINT8)&manfid, -+ &temp); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: Failed to get MANFID tuple err:%d \n", status)); -+ status = SDIO_STATUS_SUCCESS; -+ } else { -+ /* save this off so that it can be copied into each SDIO Func's SDDEVICE structure */ -+ pHcd->CardProperties.SDIO_ManufacturerCode = -+ CT_LE16_TO_CPU_ENDIAN(manfid.ManufacturerCode); -+ pHcd->CardProperties.SDIO_ManufacturerID = -+ CT_LE16_TO_CPU_ENDIAN(manfid.ManufacturerInfo); -+ DBG_PRINT(SDDBG_TRACE, ("SDIO MANFID:0x%X, MANFINFO:0x%X \n", -+ pHcd->CardProperties.SDIO_ManufacturerID, -+ pHcd->CardProperties.SDIO_ManufacturerCode)); -+ } -+ -+ if (pHcd->CardProperties.SDIORevision >= SDIO_REVISION_1_10) { -+ /* read power control */ -+ status = Cmd52ReadByteCommon(pHcd->pPseudoDev, SDIO_POWER_CONTROL_REG, &temp); -+ if (SDIO_SUCCESS(status)) { -+ /* check for power control support which indicates the card may use more -+ * than 200 mA */ -+ if (temp & SDIO_POWER_CONTROL_SMPC) { -+ /* check that the host can support this. */ -+ if (pHcd->MaxSlotCurrent >= SDIO_EMPC_CURRENT_THRESHOLD) { -+ temp = SDIO_POWER_CONTROL_EMPC; -+ /* enable power control on the card */ -+ status = Cmd52WriteByteCommon(pHcd->pPseudoDev, SDIO_POWER_CONTROL_REG, &temp); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO Busdriver: failed to enable power control (%d) \n",status)); -+ break; -+ } -+ /* mark that the card is high power */ -+ pHcd->CardProperties.Flags |= CARD_HIPWR; -+ -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO Busdriver: Power Control Enabled on SDIO (1.10 or greater) card \n")); -+ } else { -+ DBG_PRINT(SDDBG_WARN, -+ ("SDIO Busdriver: Card can operate higher than 200mA, host cannot (max:%d) \n", -+ pHcd->MaxSlotCurrent)); -+ /* this is not fatal, the card should operate at a reduced rate */ -+ } -+ } else { -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO Busdriver: SDIO 1.10 (or greater) card draws less than 200mA \n")); -+ } -+ } else { -+ DBG_PRINT(SDDBG_WARN, -+ ("SDIO Busdriver: failed to get POWER CONTROL REG (%d) \n",status)); -+ /* fall through and continue on at reduced mode */ -+ } -+ } -+ } -+ /* get the current bus parameters */ -+ busMode.BusModeFlags = pHcd->CardProperties.BusMode; -+ busMode.ClockRate = pHcd->CardProperties.OperBusClock; -+ /* get the rest of the bus parameters like clock and supported bus width */ -+ status = GetBusParameters(pHcd,&busMode); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ /* check HCD if it wants to run without SPI CRC */ -+ if (pHcd->Attributes & SDHCD_ATTRIB_NO_SPI_CRC) { -+ /* hcd would rather not run with CRC we don't need to tell the card since SPI mode -+ * cards power up with CRC initially disabled */ -+ busMode.BusModeFlags |= SDCONFIG_BUS_MODE_SPI_NO_CRC; -+ } else { -+ /* first enable SPI CRC checking if the HCD can handle it */ -+ status = SDSPIModeEnableDisableCRC(pHcd->pPseudoDev, TRUE); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO Bus Driver: Failed to set Enable SPI CRC on card \n")); -+ break; -+ } -+ } -+ } -+ -+ status = SetOperationalBusMode(pHcd->pPseudoDev, &busMode); -+ -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set operational bus mode\n")); -+ break; -+ } -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Oper. Mode: Clock:%d, Bus:0x%X \n", -+ pHcd->CardProperties.OperBusClock,pHcd->CardProperties.BusMode)); -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Card in TRANS state, Ready: CardInfo Flags 0x%X \n", -+ pHcd->CardProperties.Flags)); -+ -+ } while (FALSE); -+ -+ if (pReq != NULL) { -+ FreeRequest(pReq); -+ } -+ -+ return status; -+} -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ SDQuerySDMMCInfo - query MMC card info -+ Input: pDevice - device -+ Output: -+ Return: -+ Notes: -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS SDQuerySDMMCInfo(PSDDEVICE pDevice) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ PSDREQUEST pReq = NULL; -+ UINT8 CID[MAX_CSD_CID_BYTES]; -+ -+ do { -+ pReq = AllocateRequest(); -+ if (NULL == pReq) { -+ status = SDIO_STATUS_NO_RESOURCES; -+ break; -+ } -+ /* de-select the card */ -+ status = SelectDeselectCard(pDevice->pHcd,FALSE); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to deselect card before getting CID \n")); -+ break; -+ } -+ -+ if (SDDEVICE_IS_BUSMODE_SPI(pDevice)) { -+ /* in SPI mode, getting the CSD requires a data transfer */ -+ status = _IssueBusRequestBd(pDevice->pHcd,CMD10,0, -+ SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_DATA_TRANS, -+ pReq, -+ CID, -+ MAX_CSD_CID_BYTES); -+ if (SDIO_SUCCESS(status)) { -+ /* in SPI mode we need to reorder to the CID since SPI data comes in MSB first*/ -+ ReorderBuffer(CID,MAX_CSD_CID_BYTES); -+ } -+ } else { -+ /* get the CID */ -+ status = _IssueSimpleBusRequest(pDevice->pHcd, -+ CMD10, -+ (SDDEVICE_GET_CARD_RCA(pDevice) << 16), -+ SDREQ_FLAGS_RESP_R2, -+ pReq); -+ if (SDIO_SUCCESS(status)) { -+ /* extract it from the reponse */ -+ memcpy(CID,pReq->Response,MAX_CSD_CID_BYTES); -+ } -+ } -+ -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_WARN, ("SDQuerySDMMCInfo: failed to get CID. \n")); -+ status = SDIO_STATUS_SUCCESS; -+ } else { -+ pDevice->pId[0].SDMMC_ManfacturerID = GET_SD_CID_MANFID(CID); -+ pDevice->pId[0].SDMMC_OEMApplicationID = GET_SD_CID_OEMID(CID); -+#if DEBUG -+ { -+ char pBuf[7]; -+ -+ pBuf[0] = GET_SD_CID_PN_1(CID); -+ pBuf[1] = GET_SD_CID_PN_2(CID); -+ pBuf[2] = GET_SD_CID_PN_3(CID); -+ pBuf[3] = GET_SD_CID_PN_4(CID); -+ pBuf[4] = GET_SD_CID_PN_5(CID); -+ if (pDevice->pHcd->CardProperties.Flags & CARD_MMC) { -+ pBuf[5] = GET_SD_CID_PN_6(CID); -+ pBuf[6] = 0; -+ } else { -+ pBuf[5] = 0; -+ } -+ DBG_PRINT(SDDBG_TRACE, ("SDQuerySDMMCInfo: Product String: %s\n", pBuf)); -+ } -+#endif -+ DBG_PRINT(SDDBG_TRACE, ("SDQuerySDMMCInfo: ManfID: 0x%X, OEMID:0x%X \n", -+ pDevice->pId[0].SDMMC_ManfacturerID, pDevice->pId[0].SDMMC_OEMApplicationID)); -+ } -+ /* re-select card */ -+ status = SelectDeselectCard(pDevice->pHcd,TRUE); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to re-select card after getting CID \n")); -+ break; -+ } -+ } while (FALSE); -+ -+ if (pReq != NULL) { -+ FreeRequest(pReq); -+ } -+ -+ return status; -+} -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ SDQuerySDIOInfo - query SDIO card info -+ Input: pDevice - the device -+ Output: -+ Return: -+ Notes: -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS SDQuerySDIOInfo(PSDDEVICE pDevice) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ UINT32 faddress; -+ UINT8 fInfo; -+ UINT32 nextTpl; -+ UINT8 tplLength; -+ UINT8 cisPtrBuffer[3]; -+ struct SDIO_FUNC_EXT_FUNCTION_TPL_1_1 funcTuple; -+ -+ /* use the card-wide SDIO manufacturer code and ID previously read.*/ -+ pDevice->pId[0].SDIO_ManufacturerCode = pDevice->pHcd->CardProperties.SDIO_ManufacturerCode; -+ pDevice->pId[0].SDIO_ManufacturerID = pDevice->pHcd->CardProperties.SDIO_ManufacturerID; -+ -+ /* calculate function base address */ -+ faddress = CalculateFBROffset(SDDEVICE_GET_SDIO_FUNCNO(pDevice)); -+ DBG_ASSERT(faddress != 0); -+ -+ do { -+ status = Cmd52ReadByteCommon(pDevice, -+ FBR_FUNC_INFO_REG_OFFSET(faddress), -+ &fInfo); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get function info, Err:%d , using Class:UNKNOWN\n", status)); -+ fInfo = 0; -+ pDevice->pId[0].SDIO_FunctionClass = 0; -+ status = SDIO_STATUS_SUCCESS; -+ } else { -+ pDevice->pId[0].SDIO_FunctionClass = fInfo & FUNC_INFO_DEVICE_CODE_MASK; -+ } -+ -+ if ((FUNC_INFO_DEVICE_CODE_LAST == pDevice->pId[0].SDIO_FunctionClass) && -+ SDDEVICE_IS_SDIO_REV_GTEQ_1_10(pDevice)) { -+ /* if the device code is the last one, check for 1.1 revision and get the -+ * extended code */ -+ status = Cmd52ReadByteCommon(pDevice, -+ FBR_FUNC_EXT_DEVICE_CODE_OFFSET(faddress), -+ &(pDevice->pId[0].SDIO_FunctionClass)); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get 1.1 extended DC, Err:%d\n", -+ status)); -+ break; -+ } -+ } -+ -+ /* get the function CIS ptr */ -+ status = Cmd52ReadMultipleCommon(pDevice, -+ FBR_FUNC_CIS_LOW_OFFSET(faddress), -+ cisPtrBuffer, -+ 3); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get FN CIS ptr, Err:%d\n", status)); -+ break; -+ } -+ /* endian safe */ -+ pDevice->DeviceInfo.AsSDIOInfo.FunctionCISPtr = ((UINT32)cisPtrBuffer[0]) | -+ (((UINT32)cisPtrBuffer[1]) << 8) | -+ (((UINT32)cisPtrBuffer[2]) << 16); -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Function:%d, Class:%d FnCISPtr:0x%X \n", -+ SDDEVICE_GET_SDIO_FUNCNO(pDevice), -+ pDevice->pId[0].SDIO_FunctionClass,pDevice->DeviceInfo.AsSDIOInfo.FunctionCISPtr)); -+ -+ if (fInfo & FUNC_INFO_SUPPORTS_CSA_MASK) { -+ /* get the function CSA ptr */ -+ status = Cmd52ReadMultipleCommon(pDevice, -+ FBR_FUNC_CSA_LOW_OFFSET(faddress), -+ cisPtrBuffer, -+ 3); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get FN CSA ptr, Err:%d \n", status)); -+ break; -+ } -+ /* endian safe */ -+ pDevice->DeviceInfo.AsSDIOInfo.FunctionCSAPtr = ((UINT32)cisPtrBuffer[0]) | -+ (((UINT32)cisPtrBuffer[1]) << 8) | -+ (((UINT32)cisPtrBuffer[2]) << 16); -+ -+ } -+ -+ nextTpl = SDDEVICE_GET_SDIO_FUNC_CISPTR(pDevice); -+ /* look for the funce TPL */ -+ tplLength = sizeof(funcTuple); -+ /* go get the func CE tuple */ -+ status = SDLIB_FindTuple(pDevice, -+ CISTPL_FUNCE, -+ &nextTpl, -+ (PUINT8)&funcTuple, -+ &tplLength); -+ -+ if (!SDIO_SUCCESS(status)){ -+ /* handles case of bad CIS or missing tupple, allow function driver to handle */ -+ DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: Failed to get FuncCE Tuple: %d \n", status)); -+ status = SDIO_STATUS_SUCCESS; -+ break; -+ } -+ /* set the max block size */ -+ pDevice->DeviceInfo.AsSDIOInfo.FunctionMaxBlockSize = -+ CT_LE16_TO_CPU_ENDIAN(funcTuple.CommonInfo.MaxBlockSize); -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Function:%d, MaxBlocks:%d \n", -+ SDDEVICE_GET_SDIO_FUNCNO(pDevice), -+ pDevice->DeviceInfo.AsSDIOInfo.FunctionMaxBlockSize)); -+ -+ /* check for MANFID function tuple (SDIO 1.1 or greater) */ -+ if (SDDEVICE_IS_SDIO_REV_GTEQ_1_10(pDevice)) { -+ struct SDIO_MANFID_TPL manfid; -+ nextTpl = SDDEVICE_GET_SDIO_FUNC_CISPTR(pDevice); -+ tplLength = sizeof(manfid); -+ /* get the MANFID tuple */ -+ status = SDLIB_FindTuple(pDevice, -+ CISTPL_MANFID, -+ &nextTpl, -+ (PUINT8)&manfid, -+ &tplLength); -+ if (SDIO_SUCCESS(status)) { -+ /* this function has a MANFID tuple */ -+ pDevice->pId[0].SDIO_ManufacturerCode = -+ CT_LE16_TO_CPU_ENDIAN(manfid.ManufacturerCode); -+ pDevice->pId[0].SDIO_ManufacturerID = -+ CT_LE16_TO_CPU_ENDIAN(manfid.ManufacturerInfo); -+ DBG_PRINT(SDDBG_TRACE, ("SDIO 1.1 (Function Specific) MANFID:0x%X, MANFINFO:0x%X \n", -+ pDevice->pId[0].SDIO_ManufacturerID, -+ pDevice->pId[0].SDIO_ManufacturerCode)); -+ } else { -+ DBG_PRINT(SDDBG_WARN, ("SDIO 1.1, No CISTPL_MANFID Tuple in FUNC CIS \n")); -+ status = SDIO_STATUS_SUCCESS; -+ } -+ } -+ } while (FALSE); -+ -+ return status; -+} -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ SDEnableFunction - enable function -+ Input: pDevice - the device/function -+ pEnData - enable data; -+ Output: -+ Return: status -+ Notes: Note, this performs synchronous calls -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS SDEnableFunction(PSDDEVICE pDevice, PSDCONFIG_FUNC_ENABLE_DISABLE_DATA pEnData) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ UINT8 registerValue; -+ UINT8 mask; -+ FUNC_ENABLE_TIMEOUT retry; -+ -+ /* take the configure op lock to make this atomic */ -+ status = SemaphorePendInterruptable(&pDevice->pHcd->ConfigureOpsSem); -+ if (!SDIO_SUCCESS(status)) { -+ return status; -+ } -+ -+ status = SDIO_STATUS_INVALID_PARAMETER; -+ do { -+ if (!(pDevice->pHcd->CardProperties.Flags & CARD_SDIO)){ -+ /* nothing to do if it's not an SDIO card */ -+ break; -+ } -+ -+ if (!((SDDEVICE_GET_SDIO_FUNCNO(pDevice) >= SDIO_FIRST_FUNCTION_NUMBER) && -+ (SDDEVICE_GET_SDIO_FUNCNO(pDevice) <= SDIO_LAST_FUNCTION_NUMBER))){ -+ DBG_ASSERT(FALSE); -+ break; -+ } -+ /* make sure there is a timeout value */ -+ if (0 == pEnData->TimeOut) { -+ break; -+ } -+ -+ mask = 1 << SDDEVICE_GET_SDIO_FUNCNO(pDevice); -+ /* read the enable register */ -+ status = Cmd52ReadByteCommon(pDevice, SDIO_ENABLE_REG, ®isterValue); -+ if (!SDIO_SUCCESS(status)){ -+ break; -+ } -+ if (pEnData->EnableFlags & SDCONFIG_ENABLE_FUNC) { -+ /* set the enable register bit */ -+ registerValue |= mask; -+ } else { -+ /* clear the bit */ -+ registerValue &= ~mask; -+ } -+ -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO Bus Driver %s Function, Mask:0x%X Enable Reg Value:0x%2.2X\n", -+ (pEnData->EnableFlags & SDCONFIG_ENABLE_FUNC) ? "Enabling":"Disabling", -+ mask, -+ registerValue)); -+ -+ /* write it back out */ -+ status = Cmd52WriteByteCommon(pDevice, SDIO_ENABLE_REG, ®isterValue); -+ if (!SDIO_SUCCESS(status)){ -+ break; -+ } -+ /* now poll the ready bit until it sets or clears */ -+ retry = pEnData->TimeOut; -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Function Enable/Disable Polling: %d retries \n", -+ retry)); -+ while (retry) { -+ status = Cmd52ReadByteCommon(pDevice, SDIO_READY_REG, ®isterValue); -+ if (!SDIO_SUCCESS(status)){ -+ break; -+ } -+ if (pEnData->EnableFlags & SDCONFIG_ENABLE_FUNC) { -+ /* if the bit is set, the device is ready */ -+ if (registerValue & mask) { -+ /* device ready */ -+ break; -+ } -+ } else { -+ if (!(registerValue & mask)) { -+ /* device is no longer ready */ -+ break; -+ } -+ } -+ /* sleep before trying again */ -+ status = OSSleep(1); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("OSSleep Failed! \n")); -+ break; -+ } -+ retry--; -+ } -+ -+ if (0 == retry) { -+ status = SDIO_STATUS_FUNC_ENABLE_TIMEOUT; -+ break; -+ } -+ -+ } while (FALSE); -+ -+ SemaphorePost(&pDevice->pHcd->ConfigureOpsSem); -+ return status; -+} -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ SDAllocFreeSlotCurrent - allocate or free slot current -+ Input: pDevice - the device/function -+ Allocate - Allocate current, else free -+ pData - slotcurrent data (non-NULL if Allocate is TRUE) -+ Output: -+ Return: status -+ Notes: if the function returns SDIO_STATUS_NO_RESOURCES, the pData->SlotCurrent field is -+ updated with the available current -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS SDAllocFreeSlotCurrent(PSDDEVICE pDevice, BOOL Allocate, PSDCONFIG_FUNC_SLOT_CURRENT_DATA pData) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ -+ DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: SDAllocFreeSlotCurrent\n")); -+ -+ /* take the configure op lock to make this atomic */ -+ status = SemaphorePendInterruptable(&pDevice->pHcd->ConfigureOpsSem); -+ if (!SDIO_SUCCESS(status)) { -+ return status; -+ } -+ -+ status = SDIO_STATUS_INVALID_PARAMETER; -+ do { -+ /* check the current budget and allocate */ -+ if (Allocate) { -+ if (0 == pData->SlotCurrent) { -+ /* caller must specify current requirement for the power mode */ -+ break; -+ } -+ if (pDevice->SlotCurrentAlloc != 0) { -+ /* slot current has already been allocated, caller needs to free -+ * first */ -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Slot Current Already allocated! \n")); -+ break; -+ } -+ if (((UINT32)pDevice->pHcd->SlotCurrentAllocated + (UINT32)pData->SlotCurrent) > -+ (UINT32)pDevice->pHcd->MaxSlotCurrent) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Slot Current Budget exceeded, Requesting: %d, Allocated already: %d, Max: %d \n", -+ pData->SlotCurrent, pDevice->pHcd->SlotCurrentAllocated, -+ pDevice->pHcd->MaxSlotCurrent)); -+ status = SDIO_STATUS_NO_RESOURCES; -+ /* return remaining */ -+ pData->SlotCurrent = pDevice->pHcd->MaxSlotCurrent - -+ pDevice->pHcd->SlotCurrentAllocated; -+ break; -+ } -+ /* bump up allocation */ -+ pDevice->pHcd->SlotCurrentAllocated += pData->SlotCurrent; -+ /* save this off for the call to free slot current */ -+ pDevice->SlotCurrentAlloc = pData->SlotCurrent; -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Slot Current Requested: %d, New Total: %d, Max: %d \n", -+ pData->SlotCurrent, pDevice->pHcd->SlotCurrentAllocated, -+ pDevice->pHcd->MaxSlotCurrent)); -+ -+ } else { -+ if (0 == pDevice->SlotCurrentAlloc) { -+ /* no allocation */ -+ break; -+ } -+ /* return the allocation back */ -+ if (pDevice->SlotCurrentAlloc <= pDevice->pHcd->SlotCurrentAllocated) { -+ pDevice->pHcd->SlotCurrentAllocated -= pDevice->SlotCurrentAlloc; -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Slot Current Freed: %d, New Total: %d, Max: %d \n", -+ pDevice->SlotCurrentAlloc, pDevice->pHcd->SlotCurrentAllocated, -+ pDevice->pHcd->MaxSlotCurrent)); -+ } else { -+ DBG_ASSERT(FALSE); -+ } -+ -+ /* make sure this is zeroed */ -+ pDevice->SlotCurrentAlloc = 0; -+ } -+ -+ status = SDIO_STATUS_SUCCESS; -+ -+ } while (FALSE); -+ -+ SemaphorePost(&pDevice->pHcd->ConfigureOpsSem); -+ DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: SDAllocFreeSlotCurrent, %d\n", status)); -+ return status; -+} -+ -+static void RawHcdIrqControl(PSDHCD pHcd, BOOL Enable) -+{ -+ SDIO_STATUS status; -+ SDCONFIG_SDIO_INT_CTRL_DATA irqData; -+ CT_DECLARE_IRQ_SYNC_CONTEXT(); -+ -+ ZERO_OBJECT(irqData); -+ -+ status = _AcquireHcdLock(pHcd); -+ if (!SDIO_SUCCESS(status)) { -+ return; -+ } -+ -+ do { -+ /* for raw devices, we simply enable/disable in the HCD only */ -+ if (Enable) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver (RAW) Unmasking Int \n")); -+ irqData.IRQDetectMode = IRQ_DETECT_RAW; -+ irqData.SlotIRQEnable = TRUE; -+ } else { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver (RAW) Masking Int \n")); -+ irqData.SlotIRQEnable = FALSE; -+ } -+ -+ status = _IssueConfig(pHcd,SDCONFIG_SDIO_INT_CTRL, -+ (PVOID)&irqData, sizeof(irqData)); -+ -+ if (!SDIO_SUCCESS(status)){ -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver failed to enable/disable IRQ in (RAW) hcd :%d\n", -+ status)); -+ } -+ -+ } while (FALSE); -+ -+ status = _ReleaseHcdLock(pHcd); -+} -+ -+static void RawHcdEnableIrqPseudoComplete(PSDREQUEST pReq) -+{ -+ if (SDIO_SUCCESS(pReq->Status)) { -+ RawHcdIrqControl((PSDHCD)pReq->pCompleteContext, TRUE); -+ } -+ FreeRequest(pReq); -+} -+ -+static void RawHcdDisableIrqPseudoComplete(PSDREQUEST pReq) -+{ -+ RawHcdIrqControl((PSDHCD)pReq->pCompleteContext, FALSE); -+ FreeRequest(pReq); -+} -+ -+static void HcdIrqControl(PSDHCD pHcd, BOOL Enable) -+{ -+ SDIO_STATUS status; -+ SDCONFIG_SDIO_INT_CTRL_DATA irqData; -+ CT_DECLARE_IRQ_SYNC_CONTEXT(); -+ -+ ZERO_OBJECT(irqData); -+ -+ status = _AcquireHcdLock(pHcd); -+ if (!SDIO_SUCCESS(status)) { -+ return; -+ } -+ -+ do { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: HcdIrqControl (%s), IrqsEnabled:0x%X \n", -+ Enable ? "Enable":"Disable",pHcd->IrqsEnabled )); -+ -+ if (Enable) { -+ irqData.SlotIRQEnable = TRUE; -+ } else { -+ irqData.SlotIRQEnable = FALSE; -+ } -+ /* setup HCD to enable/disable it's detection hardware */ -+ if (irqData.SlotIRQEnable) { -+ /* set the IRQ detection mode */ -+ switch (SDCONFIG_GET_BUSWIDTH(pHcd->CardProperties.BusMode)) { -+ case SDCONFIG_BUS_WIDTH_SPI: -+ irqData.IRQDetectMode = IRQ_DETECT_SPI; -+ break; -+ case SDCONFIG_BUS_WIDTH_1_BIT: -+ irqData.IRQDetectMode = IRQ_DETECT_1_BIT; -+ break; -+ case SDCONFIG_BUS_WIDTH_4_BIT: -+ irqData.IRQDetectMode = IRQ_DETECT_4_BIT; -+ /* check card and HCD for 4bit multi-block interrupt support */ -+ if ((pHcd->CardProperties.SDIOCaps & SDIO_CAPS_INT_MULTI_BLK) && -+ (pHcd->Attributes & SDHCD_ATTRIB_MULTI_BLK_IRQ)) { -+ /* note: during initialization of the card, the mult-blk IRQ support -+ * is enabled in card caps register */ -+ irqData.IRQDetectMode |= IRQ_DETECT_MULTI_BLK; -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver enabling IRQ in multi-block mode:\n")); -+ } -+ break; -+ default: -+ DBG_ASSERT(FALSE); -+ break; -+ } -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver enabling IRQ in HCD Mode:0x%X\n", -+ irqData.IRQDetectMode)); -+ } -+ -+ status = _IssueConfig(pHcd,SDCONFIG_SDIO_INT_CTRL, -+ (PVOID)&irqData, sizeof(irqData)); -+ if (!SDIO_SUCCESS(status)){ -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver failed to enable/disable IRQ in hcd %d\n", -+ status)); -+ } -+ -+ } while (FALSE); -+ -+ status = _ReleaseHcdLock(pHcd); -+} -+ -+static BOOL CheckWriteIntEnableSuccess(PSDREQUEST pReq) -+{ -+ if (!SDIO_SUCCESS(pReq->Status)){ -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get write INT Enable register Err:%d\n", -+ pReq->Status)); -+ return FALSE; -+ } -+ -+ if (SD_R5_GET_RESP_FLAGS(pReq->Response) & SD_R5_ERRORS) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: WriteIntEnableComplete CMD52 resp error: 0x%X \n", -+ SD_R5_GET_RESP_FLAGS(pReq->Response))); -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+static void HcdIrqEnableComplete(PSDREQUEST pReq) -+{ -+ if (CheckWriteIntEnableSuccess(pReq)) { -+ /* configure HCD */ -+ HcdIrqControl((PSDHCD)pReq->pCompleteContext, TRUE); -+ } -+ FreeRequest(pReq); -+} -+ -+static void HcdIrqDisableComplete(PSDREQUEST pReq) -+{ -+ CheckWriteIntEnableSuccess(pReq); -+ HcdIrqControl((PSDHCD)pReq->pCompleteContext, FALSE); -+ FreeRequest(pReq); -+} -+ -+static void WriteIntEnableComplete(PSDREQUEST pReq) -+{ -+ if (CheckWriteIntEnableSuccess(pReq)) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Wrote INT Enable value:0x%X \n", -+ (INT)pReq->pCompleteContext)); -+ } -+ FreeRequest(pReq); -+} -+ -+static void HcdAckComplete(PSDREQUEST pReq) -+{ -+ SDIO_STATUS status; -+ DBG_PRINT(SDIODBG_FUNC_IRQ, ("SDIO Bus Driver: Hcd (0x%X) Irq Ack \n", -+ (INT)pReq->pCompleteContext)); -+ /* re-arm the HCD */ -+ status = _IssueConfig((PSDHCD)pReq->pCompleteContext,SDCONFIG_SDIO_REARM_INT,NULL,0); -+ -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: HCD Re-Arm failed : %d\n", -+ status)); -+ } -+ FreeRequest(pReq); -+} -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ SDFunctionAckInterrupt - handle device interrupt acknowledgement -+ Input: pDevice - the device -+ Output: -+ Return: -+ Notes: -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS SDFunctionAckInterrupt(PSDDEVICE pDevice) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ UCHAR mask; -+ PSDREQUEST pReq = NULL; -+ BOOL setHcd = FALSE; -+ SDIO_STATUS status2; -+ CT_DECLARE_IRQ_SYNC_CONTEXT(); -+ -+ pReq = AllocateRequest(); -+ if (NULL == pReq) { -+ return SDIO_STATUS_NO_RESOURCES; -+ } -+ -+ status = _AcquireHcdLock(pDevice->pHcd); -+ -+ if (!SDIO_SUCCESS(status)) { -+ FreeRequest(pReq); -+ return status; -+ } -+ -+ do { -+ if (!((SDDEVICE_GET_SDIO_FUNCNO(pDevice) >= SDIO_FIRST_FUNCTION_NUMBER) && -+ (SDDEVICE_GET_SDIO_FUNCNO(pDevice) <= SDIO_LAST_FUNCTION_NUMBER))){ -+ status = SDIO_STATUS_INVALID_PARAMETER; -+ DBG_ASSERT(FALSE); -+ break; -+ } -+ mask = 1 << SDDEVICE_GET_SDIO_FUNCNO(pDevice); -+ if (pDevice->pHcd->PendingIrqAcks & mask) { -+ /* clear the ack bit in question */ -+ pDevice->pHcd->PendingIrqAcks &= ~mask; -+ if (0 == pDevice->pHcd->PendingIrqAcks) { -+ pDevice->pHcd->IrqProcState = SDHCD_IDLE; -+ /* no pending acks, so re-arm if irqs are stilled enabled */ -+ if (pDevice->pHcd->IrqsEnabled) { -+ setHcd = TRUE; -+ /* issue pseudo request to sync this with bus requests */ -+ pReq->Status = SDIO_STATUS_SUCCESS; -+ pReq->pCompletion = HcdAckComplete; -+ pReq->pCompleteContext = pDevice->pHcd; -+ pReq->Flags = SD_PSEUDO_REQ_FLAGS; -+ } -+ } -+ } else { -+ DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: AckInterrupt: no IRQ pending on Function :%d, \n", -+ SDDEVICE_GET_SDIO_FUNCNO(pDevice))); -+ } -+ } while (FALSE); -+ -+ status2 = ReleaseHcdLock(pDevice); -+ -+ if (pReq != NULL) { -+ if (SDIO_SUCCESS(status) && (setHcd)) { -+ /* issue request */ -+ IssueRequestToHCD(pDevice->pHcd,pReq); -+ } else { -+ FreeRequest(pReq); -+ } -+ } -+ -+ return status; -+} -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ SDMaskUnmaskFunctionIRQ - mask/unmask function IRQ -+ Input: pDevice - the device/function -+ MaskInt - mask interrupt -+ Output: -+ Return: status -+ Notes: Note, this function can be called from an ISR or completion context -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS SDMaskUnmaskFunctionIRQ(PSDDEVICE pDevice, BOOL MaskInt) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ UINT8 mask; -+ UINT8 controlVal; -+ BOOL setHcd; -+ PSDREQUEST pReq = NULL; -+ SDIO_STATUS status2; -+ -+ CT_DECLARE_IRQ_SYNC_CONTEXT(); -+ -+ setHcd = FALSE; -+ -+ pReq = AllocateRequest(); -+ if (NULL == pReq) { -+ return SDIO_STATUS_NO_RESOURCES; -+ } -+ -+ status = _AcquireHcdLock(pDevice->pHcd); -+ -+ if (!SDIO_SUCCESS(status)) { -+ FreeRequest(pReq); -+ return status; -+ } -+ -+ do { -+ -+ if (pDevice->pHcd->CardProperties.Flags & CARD_RAW) { -+ if (!MaskInt) { -+ if (!pDevice->pHcd->IrqsEnabled) { -+ pReq->pCompletion = RawHcdEnableIrqPseudoComplete; -+ setHcd = TRUE; -+ pDevice->pHcd->IrqsEnabled = 1 << 1; -+ } -+ } else { -+ if (pDevice->pHcd->IrqsEnabled) { -+ pReq->pCompletion = RawHcdDisableIrqPseudoComplete; -+ setHcd = TRUE; -+ pDevice->pHcd->IrqsEnabled = 0; -+ } -+ } -+ -+ if (setHcd) { -+ /* hcd IRQ control requests must be synched with outstanding -+ * bus requests so we issue a pseudo bus request */ -+ pReq->pCompleteContext = pDevice->pHcd; -+ pReq->Flags = SD_PSEUDO_REQ_FLAGS; -+ pReq->Status = SDIO_STATUS_SUCCESS; -+ } else { -+ /* no request to submit, just free it */ -+ FreeRequest(pReq); -+ pReq = NULL; -+ } -+ /* we're done, submit the bus request if any */ -+ break; -+ } -+ -+ if (!(pDevice->pHcd->CardProperties.Flags & CARD_SDIO)){ -+ /* nothing to do if it's not an SDIO card */ -+ DBG_ASSERT(FALSE); -+ status = SDIO_STATUS_INVALID_PARAMETER; -+ break; -+ } -+ -+ if (!((SDDEVICE_GET_SDIO_FUNCNO(pDevice) >= SDIO_FIRST_FUNCTION_NUMBER) && -+ (SDDEVICE_GET_SDIO_FUNCNO(pDevice) <= SDIO_LAST_FUNCTION_NUMBER))){ -+ status = SDIO_STATUS_INVALID_PARAMETER; -+ DBG_ASSERT(FALSE); -+ break; -+ } -+ -+ mask = 1 << SDDEVICE_GET_SDIO_FUNCNO(pDevice); -+ if (!MaskInt) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver Unmasking Int, Mask:0x%X\n", mask)); -+ /* check interrupts that were enabled on entry */ -+ if (0 == pDevice->pHcd->IrqsEnabled) { -+ /* need to turn on interrupts in HCD */ -+ setHcd = TRUE; -+ /* use this completion routine */ -+ pReq->pCompletion = HcdIrqEnableComplete; -+ } -+ /* set the enable bit, in the shadow register */ -+ pDevice->pHcd->IrqsEnabled |= mask; -+ /* make sure control value includes the master enable */ -+ controlVal = pDevice->pHcd->IrqsEnabled | SDIO_INT_MASTER_ENABLE; -+ } else { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver Masking Int, Mask:0x%X\n", mask)); -+ /* clear the bit */ -+ pDevice->pHcd->IrqsEnabled &= ~mask; -+ /* check and see if this clears all the bits */ -+ if (0 == pDevice->pHcd->IrqsEnabled){ -+ /* if none of the functions are enabled, clear this register */ -+ controlVal = 0; -+ /* disable in host */ -+ setHcd = TRUE; -+ /* use this completion routine */ -+ pReq->pCompletion = HcdIrqDisableComplete; -+ } else { -+ /* set control value making sure master enable is left on */ -+ controlVal = pDevice->pHcd->IrqsEnabled | SDIO_INT_MASTER_ENABLE; -+ } -+ } -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver INT_ENABLE_REG value:0x%X\n", controlVal)); -+ /* setup bus request to update the mask register */ -+ SDIO_SET_CMD52_WRITE_ARG(pReq->Argument,0,SDIO_INT_ENABLE_REG,controlVal); -+ pReq->Command = CMD52; -+ pReq->Flags = SDREQ_FLAGS_TRANS_ASYNC | SDREQ_FLAGS_RESP_SDIO_R5; -+ -+ if (setHcd) { -+ /* make this a barrier request and set context*/ -+ pReq->Flags |= SDREQ_FLAGS_BARRIER; -+ pReq->pCompleteContext = pDevice->pHcd; -+ } else { -+ /* does not require an update to the HCD */ -+ pReq->pCompleteContext = (PVOID)(UINT32)controlVal; -+ pReq->pCompletion = WriteIntEnableComplete; -+ } -+ -+ } while (FALSE); -+ -+ status2 = _ReleaseHcdLock(pDevice->pHcd); -+ -+ if (pReq != NULL) { -+ if (SDIO_SUCCESS(status)) { -+ /* issue request */ -+ IssueRequestToHCD(pDevice->pHcd,pReq); -+ } else { -+ FreeRequest(pReq); -+ } -+ } -+ -+ return status; -+} -+ -+ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ SDSPIModeEnableDisableCRC - Enable/Disable SPI Mode CRC checking -+ Input: pDevice - the device/function -+ Enable - Enable CRC -+ Output: -+ Return: status -+ Notes: Note, this function can be called from an ISR or completion context -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS SDSPIModeEnableDisableCRC(PSDDEVICE pDevice,BOOL Enable) -+{ -+ SDCONFIG_BUS_MODE_DATA busMode; -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ UINT32 cmdARG = 0; -+ -+ if (!SDDEVICE_IS_BUSMODE_SPI(pDevice)) { -+ return SDIO_STATUS_INVALID_PARAMETER; -+ } -+ //??we should make these atomic using a barrier -+ -+ /* get the current mode and clock */ -+ busMode.BusModeFlags = pDevice->pHcd->CardProperties.BusMode; -+ busMode.ClockRate = pDevice->pHcd->CardProperties.OperBusClock; -+ -+ if (Enable) { -+ /* clear the no-CRC flag */ -+ busMode.BusModeFlags &= ~SDCONFIG_BUS_MODE_SPI_NO_CRC; -+ cmdARG = SD_CMD59_CRC_ON; -+ } else { -+ busMode.BusModeFlags |= SDCONFIG_BUS_MODE_SPI_NO_CRC; -+ cmdARG = SD_CMD59_CRC_OFF; -+ } -+ -+ do { -+ /* issue CMD59 to turn on/off CRC */ -+ status = _IssueSimpleBusRequest(pDevice->pHcd, -+ CMD59, -+ cmdARG, -+ SDREQ_FLAGS_RESP_R1, -+ NULL); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed issue CMD59 (arg=0x%X) Err:%d \n", -+ cmdARG, status)); -+ break; -+ } -+ if (Enable) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: CRC Enabled in SPI mode \n")); -+ } else { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: CRC Disabled in SPI mode \n")); -+ } -+ status = SetOperationalBusMode(pDevice,&busMode); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set SPI NO CRC mode in hcd : Err:%d \n", -+ status)); -+ break; -+ } -+ } while (FALSE); -+ -+ return status; -+} -+ -+ -+static UINT32 ConvertSPIStatusToSDCardStatus(UINT8 SpiR1, UINT8 SpiR2) -+{ -+ UINT32 cardStatus = 0; -+ -+ if (SpiR1 != 0) { -+ /* convert the error */ -+ if (SpiR1 & SPI_CS_ERASE_RESET) { -+ cardStatus |= SD_CS_ERASE_RESET; -+ } -+ if (SpiR1 & SPI_CS_ILLEGAL_CMD) { -+ cardStatus |= SD_CS_ILLEGAL_CMD_ERR; -+ } -+ if (SpiR1 & SPI_CS_CMD_CRC_ERR) { -+ cardStatus |= SD_CS_PREV_CMD_CRC_ERR; -+ } -+ if (SpiR1 & SPI_CS_ERASE_SEQ_ERR) { -+ cardStatus |= SD_CS_ERASE_SEQ_ERR; -+ } -+ if (SpiR1 & SPI_CS_ADDRESS_ERR) { -+ cardStatus |= SD_CS_ADDRESS_ERR; -+ } -+ if (SpiR1 & SPI_CS_PARAM_ERR) { -+ cardStatus |= SD_CS_CMD_OUT_OF_RANGE; -+ } -+ } -+ -+ if (SpiR2 != 0) { -+ /* convert the error */ -+ if (SpiR2 & SPI_CS_CARD_IS_LOCKED) { -+ cardStatus |= SD_CS_CARD_LOCKED; -+ } -+ if (SpiR2 & SPI_CS_LOCK_UNLOCK_FAILED) { -+ /* this bit is shared, just set both */ -+ cardStatus |= (SD_CS_LK_UNLK_FAILED | SD_CS_WP_ERASE_SKIP); -+ } -+ if (SpiR2 & SPI_CS_ERROR) { -+ cardStatus |= SD_CS_GENERAL_ERR; -+ } -+ if (SpiR2 & SPI_CS_INTERNAL_ERROR) { -+ cardStatus |= SD_CS_CARD_INTERNAL_ERR; -+ } -+ if (SpiR2 & SPI_CS_ECC_FAILED) { -+ cardStatus |= SD_CS_ECC_FAILED; -+ } -+ if (SpiR2 & SPI_CS_WP_VIOLATION) { -+ cardStatus |= SD_CS_WP_ERR; -+ } -+ if (SpiR2 & SPI_CS_ERASE_PARAM_ERR) { -+ cardStatus |= SD_CS_ERASE_PARAM_ERR; -+ } -+ if (SpiR2 & SPI_CS_OUT_OF_RANGE) { -+ cardStatus |= SD_CS_CMD_OUT_OF_RANGE; -+ } -+ } -+ -+ return cardStatus; -+} -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ ConvertSPI_Response - filter the SPI response and convert it to an SD Response -+ Input: pReq - request -+ Output: pReq - modified response, if pRespBuffer is not NULL -+ pRespBuffer - converted response (optional) -+ Return: -+ Notes: This function converts a SPI response into an SD response. A caller -+ can supply a buffer instead. -+ For SPI bus operation the HCD must send the SPI response as -+ a stream of bytes, the highest byte contains the first received byte from the -+ card. This function only filters simple responses (R1 primarily). -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+void ConvertSPI_Response(PSDREQUEST pReq, UINT8 *pRespBuffer) -+{ -+ -+ UINT32 cardStatus; -+ -+ if (pReq->Flags & SDREQ_FLAGS_RESP_SPI_CONVERTED) { -+ /* already converted */ -+ return; -+ } -+ if (NULL == pRespBuffer) { -+ pRespBuffer = pReq->Response; -+ } -+ -+ switch (GET_SDREQ_RESP_TYPE(pReq->Flags)) { -+ case SDREQ_FLAGS_RESP_R1: -+ case SDREQ_FLAGS_RESP_R1B: -+ cardStatus = ConvertSPIStatusToSDCardStatus(GET_SPI_R1_RESP_TOKEN(pReq->Response), -+ 0); -+ if (CMD55 == pReq->Command) { -+ /* we emulate this since SPI does not have such a bit */ -+ cardStatus |= SD_CS_APP_CMD; -+ } -+ /* stuff the SD card status */ -+ SD_R1_SET_CMD_STATUS(pRespBuffer,cardStatus); -+ /* stuff the command */ -+ SD_R1_SET_CMD(pRespBuffer,pReq->Command); -+ pReq->Flags |= SDREQ_FLAGS_RESP_SPI_CONVERTED; -+ break; -+ case SDREQ_FLAGS_RESP_SDIO_R5: -+ { -+ UINT8 respFlags; -+ UINT8 readData; -+ -+ readData = GET_SPI_SDIO_R5_RESPONSE_RDATA(pReq->Response); -+ respFlags = GET_SPI_SDIO_R5_RESP_TOKEN(pReq->Response); -+ -+ pRespBuffer[SD_R5_RESP_FLAGS_OFFSET] = 0; -+ if (respFlags != 0) { -+ if (respFlags & SPI_R5_ILLEGAL_CMD) { -+ pRespBuffer[SD_R5_RESP_FLAGS_OFFSET] |= SD_R5_ILLEGAL_CMD; -+ } -+ if (respFlags & SPI_R5_CMD_CRC) { -+ pRespBuffer[SD_R5_RESP_FLAGS_OFFSET] |= SD_R5_RESP_CMD_ERR; -+ } -+ if (respFlags & SPI_R5_FUNC_ERR) { -+ pRespBuffer[SD_R5_RESP_FLAGS_OFFSET] |= SD_R5_INVALID_FUNC; -+ } -+ if (respFlags & SPI_R5_PARAM_ERR) { -+ pRespBuffer[SD_R5_RESP_FLAGS_OFFSET] |= SD_R5_ARG_RANGE_ERR; -+ } -+ } -+ /* stuff read data */ -+ pRespBuffer[SD_SDIO_R5_READ_DATA_OFFSET] = readData; -+ /* stuff the command */ -+ SD_R5_SET_CMD(pRespBuffer,pReq->Command); -+ } -+ pReq->Flags |= SDREQ_FLAGS_RESP_SPI_CONVERTED; -+ break; -+ case SDREQ_FLAGS_RESP_R2: -+ /* for CMD13 and ACMD13 , SPI uses it's own R2 response format (2 bytes) */ -+ /* the issue of CMD13 needs to change the response flag to R2 */ -+ if (CMD13 == pReq->Command) { -+ cardStatus = ConvertSPIStatusToSDCardStatus( -+ GET_SPI_R2_RESP_TOKEN(pReq->Response), -+ GET_SPI_R2_STATUS_TOKEN(pReq->Response)); -+ /* stuff the SD card status */ -+ SD_R1_SET_CMD_STATUS(pRespBuffer,cardStatus); -+ /* stuff the command */ -+ SD_R1_SET_CMD(pRespBuffer,pReq->Command); -+ pReq->Flags |= SDREQ_FLAGS_RESP_SPI_CONVERTED; -+ break; -+ } -+ /* no other commands should be using R2 when using SPI, if they are -+ * they should be bypassing the filter */ -+ DBG_ASSERT(FALSE); -+ break; -+ default: -+ /* for all others: -+ * -+ * SDREQ_FLAGS_RESP_R6 - SPI mode does not use RCA -+ * SDREQ_FLAGS_RESP_R3 - bus driver handles this internally -+ * SDREQ_FLAGS_RESP_SDIO_R4 - bus driver handles this internally -+ * -+ */ -+ DBG_PRINT(SDDBG_ERROR, ("ConvertSPI_Response - invalid response type:0x%2.2X", -+ GET_SDREQ_RESP_TYPE(pReq->Flags))); -+ DBG_ASSERT(FALSE); -+ break; -+ } -+} -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Check an SD/MMC/SDIO response. -+ -+ @function name: SDIO_CheckResponse -+ @prototype: SDIO_STATUS SDIO_CheckResponse(PSDHCD pHcd, PSDREQUEST pReq, SDHCD_RESPONSE_CHECK_MODE CheckMode) -+ @category: HD_Reference -+ -+ @input: pHcd - the host controller definition structure. -+ @input: pReq - request containing the response -+ @input: CheckMode - mode -+ -+ @return: SDIO_STATUS -+ -+ @notes: Host controller drivers must call into this function to validate various command -+ responses before continuing with data transfers or for decoding received SPI tokens. -+ The CheckMode option determines the type of validation to perform. -+ if (CheckMode == SDHCD_CHECK_DATA_TRANS_OK) : -+ The host controller must check the card response to determine whether it -+ is safe to perform a data transfer. This API only checks commands that -+ involve data transfers and checks various status fields in the command response. -+ If the card cannot accept data, this function will return a non-successful status that -+ should be treated as a request failure. The host driver should complete the request with the -+ returned status. Host controller should only call this function in preparation for a -+ data transfer. -+ if (CheckMode == SDHCD_CHECK_SPI_TOKEN) : -+ This API checks the SPI token and returns a timeout status if the illegal command bit is -+ set. This simulates the behavior of SD 1/4 bit operation where illegal commands result in -+ a command timeout. A driver that supports SPI mode should pass every response to this -+ function to determine the appropriate error status to complete the request with. If the -+ API returns success, the response indicates that the card accepted the command. -+ -+ @example: Checking the response before starting the data transfer : -+ if (SDIO_SUCCESS(status) && (pReq->Flags & SDREQ_FLAGS_DATA_TRANS)) { -+ // check the response to see if we should continue with data -+ status = SDIO_CheckResponse(pHcd, pReq, SDHCD_CHECK_DATA_TRANS_OK); -+ if (SDIO_SUCCESS(status)) { -+ .... start data transfer phase -+ } else { -+ ... card response indicates that the card cannot handle data -+ // set completion status -+ pRequest->Status = status; -+ } -+ } -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ _SDIO_CheckResponse - check response on behalf of the host controller -+ Input: pHcd - host controller -+ pReq - request containing the response -+ CheckMode - mode -+ Output: -+ Return: status -+ Notes: -+ -+ CheckMode == SDHCD_CHECK_DATA_TRANS_OK : -+ The host controller requests a check on the response to determine whether it -+ is okay to perform a data transfer. This function only filters on commands that -+ involve data. Host controller should only call this function in preparation for a -+ data transfer. -+ -+ CheckMode == SDHCD_CHECK_SPI_TOKEN : -+ The bus driver checks the SPI token and returns a timeout status if the illegal command bit is -+ set. This simulates the behavior of SD native operation. -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS _SDIO_CheckResponse(PSDHCD pHcd, PSDREQUEST pReq, SDHCD_RESPONSE_CHECK_MODE CheckMode) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ -+ if (CheckMode == SDHCD_CHECK_DATA_TRANS_OK) { -+ UINT32 cardStatus; -+ UINT8 *pResponse; -+ UINT8 convertedResponse[MAX_CARD_RESPONSE_BYTES]; -+ -+ if (!(pReq->Flags & SDREQ_FLAGS_DATA_TRANS) || -+ (pReq->Flags & SDREQ_FLAGS_DATA_SKIP_RESP_CHK) || -+ (GET_SDREQ_RESP_TYPE(pReq->Flags) == SDREQ_FLAGS_NO_RESP)) { -+ return SDIO_STATUS_SUCCESS; -+ } -+ pResponse = pReq->Response; -+ /* check SPI mode */ -+ if (IS_HCD_BUS_MODE_SPI(pHcd)) { -+ if (!(pReq->Flags & SDREQ_FLAGS_RESP_SKIP_SPI_FILT)) { -+ /* apply conversion */ -+ ConvertSPI_Response(pReq, NULL); -+ } else { -+ /* temporarily convert the response, without altering the original */ -+ ConvertSPI_Response(pReq, convertedResponse); -+ /* point to the converted one */ -+ pResponse = convertedResponse; -+ } -+ } -+ -+ switch (GET_SDREQ_RESP_TYPE(pReq->Flags)) { -+ case SDREQ_FLAGS_RESP_R1: -+ case SDREQ_FLAGS_RESP_R1B: -+ cardStatus = SD_R1_GET_CARD_STATUS(pResponse); -+ if (!(cardStatus & -+ (SD_CS_ILLEGAL_CMD_ERR | SD_CS_CARD_INTERNAL_ERR | SD_CS_GENERAL_ERR))) { -+ /* okay for data */ -+ break; -+ } -+ /* figure out what it was */ -+ if (cardStatus & SD_CS_ILLEGAL_CMD_ERR) { -+ status = SDIO_STATUS_DATA_STATE_INVALID; -+ } else { -+ status = SDIO_STATUS_DATA_ERROR_UNKNOWN; -+ } -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Check Response Error. R1 CardStatus:0x%X \n", -+ cardStatus)); -+ break; -+ case SDREQ_FLAGS_RESP_SDIO_R5: -+ cardStatus = SD_R5_GET_RESP_FLAGS(pResponse); -+ if (!(cardStatus & SD_R5_CURRENT_CMD_ERRORS)){ -+ /* all okay */ -+ break; -+ } -+ -+ status = ConvertCMD52ResponseToSDIOStatus((UINT8)cardStatus); -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Check Response Error. R5 CardStatus:0x%X \n", -+ cardStatus)); -+ break; -+ default: -+ break; -+ } -+ -+ return status; -+ } -+ -+ { -+ UINT8 spiToken; -+ -+ /* handle SPI token validation */ -+ switch (GET_SDREQ_RESP_TYPE(pReq->Flags)) { -+ case SDREQ_FLAGS_RESP_R2: -+ spiToken = GET_SPI_R2_RESP_TOKEN(pReq->Response); -+ break; -+ case SDREQ_FLAGS_RESP_SDIO_R5: -+ spiToken = GET_SPI_SDIO_R5_RESP_TOKEN(pReq->Response); -+ break; -+ case SDREQ_FLAGS_RESP_R3: -+ spiToken = GET_SPI_R3_RESP_TOKEN(pReq->Response); -+ break; -+ case SDREQ_FLAGS_RESP_SDIO_R4: -+ spiToken = GET_SPI_SDIO_R4_RESP_TOKEN(pReq->Response); -+ break; -+ default: -+ /* all other tokesn are SPI R1 type */ -+ spiToken = GET_SPI_R1_RESP_TOKEN(pReq->Response); -+ break; -+ } -+ -+ if ((GET_SDREQ_RESP_TYPE(pReq->Flags) == SDREQ_FLAGS_RESP_SDIO_R5) || -+ (GET_SDREQ_RESP_TYPE(pReq->Flags) == SDREQ_FLAGS_RESP_SDIO_R4)) { -+ /* handle SDIO status tokens */ -+ if ((spiToken & SPI_R5_ILLEGAL_CMD) || -+ (spiToken & SPI_R5_CMD_CRC)) { -+ status = SDIO_STATUS_BUS_RESP_TIMEOUT; -+ } -+ } else { -+ /* handle all other status tokens */ -+ if ((spiToken & SPI_CS_ILLEGAL_CMD) || -+ (spiToken & SPI_CS_CMD_CRC_ERR)) { -+ status = SDIO_STATUS_BUS_RESP_TIMEOUT; -+ } -+ } -+ } -+ -+ return status; -+} -+ -diff --git a/drivers/sdio/stack/busdriver/sdio_bus_os.c b/drivers/sdio/stack/busdriver/sdio_bus_os.c -new file mode 100644 -index 0000000..dbdb955 ---- /dev/null -+++ b/drivers/sdio/stack/busdriver/sdio_bus_os.c -@@ -0,0 +1,832 @@ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+@file: sdio_bus_os.c -+ -+@abstract: Linux implementation module -+ -+#notes: includes module load and unload functions -+ -+@notice: Copyright (c), 2004-2006 Atheros Communications, Inc. -+ -+ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * Software distributed under the License is distributed on an "AS -+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -+ * implied. See the License for the specific language governing -+ * rights and limitations under the License. -+ * -+ * Portions of this code were developed with information supplied from the -+ * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply: -+ * -+ * The following conditions apply to the release of the SD simplified specification (�Simplified -+ * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete -+ * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided -+ * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified -+ * Specification may require a license from the SD Card Association or other third parties. -+ * Disclaimers: -+ * The information contained in the Simplified Specification is presented only as a standard -+ * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any -+ * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for -+ * any damages, any infringements of patents or other right of the SD Card Association or any third -+ * parties, which may result from its use. No license is granted by implication, estoppel or otherwise -+ * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall -+ * be construed as an obligation by the SD Card Association to disclose or distribute any technical -+ * information, know-how or other confidential information to any third party. -+ * -+ * -+ * The initial developers of the original code are Seung Yi and Paul Lever -+ * -+ * sdio@atheros.com -+ * -+ * -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+/* debug level for this module*/ -+#define DBG_DECLARE 3; -+ -+#include <linux/sdio/ctsystem.h> -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/version.h> -+#include <linux/init.h> -+#include <linux/workqueue.h> -+#include <linux/delay.h> -+#include <linux/kthread.h> -+#include <linux/pnp.h> -+void pnp_remove_card_device(struct pnp_dev *dev); -+#include <linux/sdio/sdio_busdriver.h> -+#include <linux/sdio/sdio_lib.h> -+#include "_busdriver.h" -+ -+#define DESCRIPTION "SDIO Bus Driver" -+#define AUTHOR "Atheros Communications, Inc." -+ -+/* debug print parameter */ -+/* configuration and default parameters */ -+static int RequestRetries = SDMMC_DEFAULT_CMD_RETRIES; -+module_param(RequestRetries, int, 0644); -+MODULE_PARM_DESC(RequestRetries, "number of command retries"); -+static int CardReadyPollingRetry = SDMMC_DEFAULT_CARD_READY_RETRIES; -+module_param(CardReadyPollingRetry, int, 0644); -+MODULE_PARM_DESC(CardReadyPollingRetry, "number of card ready retries"); -+static int PowerSettleDelay = SDMMC_POWER_SETTLE_DELAY; -+module_param(PowerSettleDelay, int, 0644); -+MODULE_PARM_DESC(PowerSettleDelay, "delay in ms for power to settle after power changes"); -+static int DefaultOperClock = 52000000; -+module_param(DefaultOperClock, int, 0644); -+MODULE_PARM_DESC(DefaultOperClock, "maximum operational clock limit"); -+static int DefaultBusMode = SDCONFIG_BUS_WIDTH_4_BIT; -+module_param(DefaultBusMode, int, 0644); -+MODULE_PARM_DESC(DefaultBusMode, "default bus mode: see SDCONFIG_BUS_WIDTH_xxx"); -+static int RequestListSize = SDBUS_DEFAULT_REQ_LIST_SIZE; -+module_param(RequestListSize, int, 0644); -+MODULE_PARM_DESC(RequestListSize, ""); -+static int SignalSemListSize = SDBUS_DEFAULT_REQ_SIG_SIZE; -+module_param(SignalSemListSize, int, 0644); -+MODULE_PARM_DESC(SignalSemListSize, ""); -+static int CDPollingInterval = SDBUS_DEFAULT_CD_POLLING_INTERVAL; -+module_param(CDPollingInterval, int, 0644); -+MODULE_PARM_DESC(CDPollingInterval, ""); -+static int DefaultOperBlockLen = SDMMC_DEFAULT_BYTES_PER_BLOCK; -+module_param(DefaultOperBlockLen, int, 0644); -+MODULE_PARM_DESC(DefaultOperBlockLen, "operational block length"); -+static int DefaultOperBlockCount = SDMMC_DEFAULT_BLOCKS_PER_TRANS; -+module_param(DefaultOperBlockCount, int, 0644); -+MODULE_PARM_DESC(DefaultOperBlockCount, "operational block count"); -+static int ConfigFlags = BD_DEFAULT_CONFIG_FLAGS; -+module_param(ConfigFlags, int, 0644); -+MODULE_PARM_DESC(ConfigFlags, "config flags"); -+ -+static int HcdRCount = MAX_HCD_REQ_RECURSION; -+module_param(HcdRCount, int, 0644); -+MODULE_PARM_DESC(HcdRCount, "HCD request recursion count"); -+ -+static void CardDetect_WorkItem( -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -+void *context); -+#else -+struct work_struct *ignored); -+#endif -+static void CardDetect_TimerFunc(unsigned long Context); -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+static DECLARE_WORK(CardDetectPollWork, CardDetect_WorkItem -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -+, 0); -+#else -+); -+#endif -+#endif -+static int RegisterDriver(PSDFUNCTION pFunction); -+static int UnregisterDriver(PSDFUNCTION pFunction); -+ -+static struct timer_list CardDetectTimer; -+ -+#define SDDEVICE_FROM_OSDEVICE(pOSDevice) container_of(pOSDevice, SDDEVICE, Device) -+#define SDFUNCTION_FROM_OSDRIVER(pOSDriver) container_of(pOSDriver, SDFUNCTION, Driver) -+ -+ -+/* -+ * SDIO_RegisterHostController - register a host controller bus driver -+*/ -+SDIO_STATUS SDIO_RegisterHostController(PSDHCD pHcd) { -+ /* we are the exported verison, call the internal verison */ -+ return _SDIO_RegisterHostController(pHcd); -+} -+ -+/* -+ * SDIO_UnregisterHostController - unregister a host controller bus driver -+*/ -+SDIO_STATUS SDIO_UnregisterHostController(PSDHCD pHcd) { -+ /* we are the exported verison, call the internal verison */ -+ return _SDIO_UnregisterHostController(pHcd); -+} -+ -+/* -+ * SDIO_RegisterFunction - register a function driver -+*/ -+SDIO_STATUS SDIO_RegisterFunction(PSDFUNCTION pFunction) { -+ int error; -+ SDIO_STATUS status; -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO BusDriver - SDIO_RegisterFunction\n")); -+ -+ /* since we do PnP registration first, we need to check the version */ -+ if (!CHECK_FUNCTION_DRIVER_VERSION(pFunction)) { -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO Bus Driver: Function Major Version Mismatch (hcd = %d, bus driver = %d)\n", -+ GET_SDIO_STACK_VERSION_MAJOR(pFunction), CT_SDIO_STACK_VERSION_MAJOR(g_Version))); -+ return SDIO_STATUS_INVALID_PARAMETER; -+ } -+ -+ /* we are the exported verison, call the internal verison after registering with the bus -+ we handle probes internally to the bus driver */ -+ if ((error = RegisterDriver(pFunction)) < 0) { -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO BusDriver - SDIO_RegisterFunction, failed to register with system bus driver: %d\n", -+ error)); -+ status = OSErrorToSDIOError(error); -+ } else { -+ status = _SDIO_RegisterFunction(pFunction); -+ if (!SDIO_SUCCESS(status)) { -+ UnregisterDriver(pFunction); -+ } -+ } -+ -+ return status; -+} -+ -+/* -+ * SDIO_UnregisterFunction - unregister a function driver -+*/ -+SDIO_STATUS SDIO_UnregisterFunction(PSDFUNCTION pFunction) { -+ SDIO_STATUS status; -+ /* we are the exported verison, call the internal verison */ -+ status = _SDIO_UnregisterFunction(pFunction); -+ UnregisterDriver(pFunction); -+ return status; -+} -+ -+/* -+ * SDIO_HandleHcdEvent - tell core an event occurred -+*/ -+SDIO_STATUS SDIO_HandleHcdEvent(PSDHCD pHcd, HCD_EVENT Event) { -+ /* we are the exported verison, call the internal verison */ -+ DBG_PRINT(SDIODBG_HCD_EVENTS, ("SDIO Bus Driver: SDIO_HandleHcdEvent, event type 0x%X, HCD:0x%X\n", -+ Event, (UINT)pHcd)); -+ return _SDIO_HandleHcdEvent(pHcd, Event); -+} -+ -+/* get default settings */ -+SDIO_STATUS _SDIO_BusGetDefaultSettings(PBDCONTEXT pBdc) -+{ -+ /* these defaults are module params */ -+ pBdc->RequestRetries = RequestRetries; -+ pBdc->CardReadyPollingRetry = CardReadyPollingRetry; -+ pBdc->PowerSettleDelay = PowerSettleDelay; -+ pBdc->DefaultOperClock = DefaultOperClock; -+ pBdc->DefaultBusMode = DefaultBusMode; -+ pBdc->RequestListSize = RequestListSize; -+ pBdc->SignalSemListSize = SignalSemListSize; -+ pBdc->CDPollingInterval = CDPollingInterval; -+ pBdc->DefaultOperBlockLen = DefaultOperBlockLen; -+ pBdc->DefaultOperBlockCount = DefaultOperBlockCount; -+ pBdc->ConfigFlags = ConfigFlags; -+ pBdc->MaxHcdRecursion = HcdRCount; -+ return SDIO_STATUS_SUCCESS; -+} -+ -+static void CardDetect_TimerFunc(unsigned long Context) -+{ -+ DBG_PRINT(SDIODBG_CD_TIMER, ("+ SDIO BusDriver Card Detect Timer\n")); -+ -+ /* timers run in an ISR context and cannot block or sleep, so we need -+ * to queue a work item to call the bus driver timer notification */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ if (schedule_work(&CardDetectPollWork) <= 0) { -+ DBG_PRINT(SDDBG_ERROR, ("Failed to queue Card Detect timer!\n")); -+ } -+#else -+ CardDetect_WorkItem(NULL); -+#endif -+ DBG_PRINT(SDIODBG_CD_TIMER, ("- SDIO BusDriver Card Detect Timer\n")); -+} -+ -+/* -+ * Initialize any timers we are using -+*/ -+SDIO_STATUS InitializeTimers(void) -+{ -+ init_timer(&CardDetectTimer); -+ CardDetectTimer.function = CardDetect_TimerFunc; -+ CardDetectTimer.data = 0; -+ return SDIO_STATUS_SUCCESS; -+} -+ -+/* -+ * cleanup timers -+*/ -+SDIO_STATUS CleanupTimers(void) -+{ -+ del_timer(&CardDetectTimer); -+ return SDIO_STATUS_SUCCESS; -+} -+ -+ -+/* -+ * Queue a timer, Timeout is in milliseconds -+*/ -+SDIO_STATUS QueueTimer(INT TimerID, UINT32 TimeOut) -+{ -+ UINT32 delta; -+ -+ /* convert timeout to ticks */ -+ delta = (TimeOut * HZ)/1000; -+ if (delta == 0) { -+ delta = 1; -+ } -+ DBG_PRINT(SDIODBG_CD_TIMER, ("SDIO BusDriver - SDIO_QueueTimer System Ticks Per Sec:%d \n",HZ)); -+ DBG_PRINT(SDIODBG_CD_TIMER, ("SDIO BusDriver - SDIO_QueueTimer TimerID: %d TimeOut:%d MS, requires %d Ticks\n", -+ TimerID,TimeOut,delta)); -+ switch (TimerID) { -+ case SDIOBUS_CD_TIMER_ID: -+ CardDetectTimer.expires = jiffies + delta; -+ add_timer(&CardDetectTimer); -+ break; -+ default: -+ return SDIO_STATUS_INVALID_PARAMETER; -+ } -+ -+ return SDIO_STATUS_SUCCESS; -+} -+ -+/* check a response on behalf of the host controller, to allow it to proceed with a -+ * data transfer */ -+SDIO_STATUS SDIO_CheckResponse(PSDHCD pHcd, PSDREQUEST pReq, SDHCD_RESPONSE_CHECK_MODE CheckMode) -+{ -+ return _SDIO_CheckResponse(pHcd,pReq,CheckMode); -+} -+ -+/* -+ * CardDetect_WorkItem - the work item for handling card detect polling interrupt -+*/ -+static void CardDetect_WorkItem( -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -+void *context) -+#else -+struct work_struct *ignored) -+#endif -+{ -+ /* call bus driver function */ -+ SDIO_NotifyTimerTriggered(SDIOBUS_CD_TIMER_ID); -+} -+ -+/* -+ * OS_IncHcdReference - increment host controller driver reference count -+*/ -+SDIO_STATUS Do_OS_IncHcdReference(PSDHCD pHcd) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ -+ do { -+ if (NULL == pHcd->pModule) { -+ /* hcds that are 2.3 or higher should set this */ -+ DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: HCD:%s should set module ptr!\n", -+ (pHcd->pName != NULL) ? pHcd->pName : "Unknown")); -+ break; -+ } -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ if (!try_module_get(pHcd->pModule)) { -+ status = SDIO_STATUS_ERROR; -+ } -+#else -+ if (!try_inc_mod_count(pHcd->pModule)) { -+ status = SDIO_STATUS_ERROR; -+ } -+#endif -+ -+ } while (FALSE); -+ -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: HCD:%s failed to get module\n", -+ (pHcd->pName != NULL) ? pHcd->pName : "Unknown")); -+ } -+ -+ return status; -+} -+ -+/* -+ * OS_DecHcdReference - decrement host controller driver reference count -+*/ -+SDIO_STATUS Do_OS_DecHcdReference(PSDHCD pHcd) -+{ -+ if (pHcd->pModule != NULL) { -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ module_put(pHcd->pModule); -+#else -+ /* 2.4 or lower */ -+ __MOD_DEC_USE_COUNT(pHcd->pModule); -+#endif -+ } -+ return SDIO_STATUS_SUCCESS; -+} -+ -+/****************************************************************************************/ -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+#include <linux/pnp.h> -+ -+#if !defined(CONFIG_PNP) -+#error "CONFIG_PNP not defined" -+#endif -+ -+static ULONG InUseDevices = 0; -+static spinlock_t InUseDevicesLock = SPIN_LOCK_UNLOCKED; -+ -+static const struct pnp_device_id pnp_idtable[] = { -+ {"SD_XXXX", 0} -+}; -+static int sdio_get_resources(struct pnp_dev * pDev, struct pnp_resource_table * res) -+{ -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO BusDriver - sdio_get_resources: %s\n", -+ pDev->dev.bus_id)); -+ return 0; -+} -+static int sdio_set_resources(struct pnp_dev * pDev, struct pnp_resource_table * res) -+{ -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO BusDriver - sdio_set_resources: %s\n", -+ pDev->dev.bus_id)); -+ return 0; -+} -+ -+static int sdio_disable_resources(struct pnp_dev *pDev) -+{ -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO BusDriver - sdio_disable_resources: %s\n", -+ pDev->dev.bus_id)); -+ if (pDev != NULL) { -+ pDev->active = 0; -+ } -+ return 0; -+} -+void release(struct device * pDev) { -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO BusDriver - release: %s\n", -+ pDev->bus_id)); -+ return; -+} -+struct pnp_protocol sdio_protocol = { -+ .name = "SDIO", -+ .get = sdio_get_resources, -+ .set = sdio_set_resources, -+ .disable = sdio_disable_resources, -+ .dev.release = release, -+}; -+ -+/* -+ * driver_probe - probe for OS based driver -+*/ -+static int driver_probe(struct pnp_dev* pOSDevice, const struct pnp_device_id *pId) -+{ -+ PSDDEVICE pDevice = SDDEVICE_FROM_OSDEVICE(pOSDevice); -+ PSDFUNCTION pFunction = pDevice->Device.dev.driver_data; -+ -+ if (pFunction == NULL) { -+ return -1; -+ } -+ -+ if (strcmp(pFunction->pName, pOSDevice->dev.driver->name) == 0) { -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO BusDriver - driver_probe, match: %s/%s driver: %s\n", -+ pOSDevice->dev.bus_id, pFunction->pName, pOSDevice->dev.driver->name)); -+ return 1; -+ } else { -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO BusDriver - driver_probe, no match: %s/%s driver: %s\n", -+ pOSDevice->dev.bus_id, pFunction->pName, pOSDevice->dev.driver->name)); -+ return -1; -+ } -+/* if (pOSDevice->id != NULL) { -+ if (strcmp(pOSDevice->id->id, pId->id) == 0) { -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO BusDriver - driver_probe, match: %s/%s\n", -+ pOSDevice->dev.bus_id, pId->id)); -+ return 1; -+ } -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO BusDriver - driver_probe, did not match: %s/%s/%s\n", -+ pOSDevice->dev.bus_id, pId->id, pOSDevice->id->id)); -+ } else { -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO BusDriver - driver_probe, did not match: %s/%s\n", -+ pOSDevice->dev.bus_id, pId->id)); -+ } -+ return -1; -+*/ -+//?? if (pDevice->Device.dev.driver_data != NULL) { -+//?? if (pDevice->Device.dev.driver_data == pFunction) { -+//?? if (pDevice->Device.data != NULL) { -+//?? if (pDevice->Device.data == pFunction) { -+//?? DBG_PRINT(SDDBG_TRACE, -+//?? ("SDIO BusDriver - driver_probe, match: %s\n", -+//?? pOSDevice->dev.bus_id)); -+//?? return 1; -+//?? } -+//?? } -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO BusDriver - driver_probe, match: %s\n", -+ pOSDevice->dev.bus_id)); -+ return 1; -+} -+ -+static int RegisterDriver(PSDFUNCTION pFunction) -+{ -+ memset(&pFunction->Driver, 0, sizeof(pFunction->Driver)); -+ pFunction->Driver.name = pFunction->pName; -+ pFunction->Driver.probe = driver_probe; -+ pFunction->Driver.id_table = pnp_idtable; -+ pFunction->Driver.flags = PNP_DRIVER_RES_DO_NOT_CHANGE; -+ -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO BusDriver - SDIO_RegisterFunction, registering driver: %s\n", -+ pFunction->Driver.name)); -+ return pnp_register_driver(&pFunction->Driver); -+} -+ -+static int UnregisterDriver(PSDFUNCTION pFunction) -+{ -+ DBG_PRINT(SDDBG_TRACE, -+ ("+SDIO BusDriver - UnregisterDriver, driver: %s\n", -+ pFunction->Driver.name)); -+ pnp_unregister_driver(&pFunction->Driver); -+ DBG_PRINT(SDDBG_TRACE, -+ ("-SDIO BusDriver - UnregisterDriver\n")); -+ return 0; -+} -+ -+/* -+ * OS_InitializeDevice - initialize device that will be registered -+*/ -+SDIO_STATUS OS_InitializeDevice(PSDDEVICE pDevice, PSDFUNCTION pFunction) -+{ -+ struct pnp_id *pFdname; -+ memset(&pDevice->Device, 0, sizeof(pDevice->Device)); -+ pDevice->Device.dev.driver_data = (PVOID)pFunction; -+//?? pDevice->Device.data = (PVOID)pFunction; -+//?? pDevice->Device.dev.driver = &pFunction->Driver.driver; -+//?? pDevice->Device.driver = &pFunction->Driver; -+//?? pDevice->Device.dev.release = release; -+ /* get a unique device number, must be done with locks held */ -+ spin_lock(&InUseDevicesLock); -+ pDevice->Device.number = FirstClearBit(&InUseDevices); -+ SetBit(&InUseDevices, pDevice->Device.number); -+ spin_unlock(&InUseDevicesLock); -+ pDevice->Device.capabilities = PNP_REMOVABLE | PNP_DISABLE; -+ pDevice->Device.protocol = &sdio_protocol; -+ pDevice->Device.active = 1; -+ -+ pnp_init_resource_table(&pDevice->Device.res); -+ -+ pFdname = KernelAlloc(sizeof(struct pnp_id)); -+ -+ if (NULL == pFdname) { -+ return SDIO_STATUS_NO_RESOURCES; -+ } -+ /* set the id as slot number/function number */ -+ snprintf(pFdname->id, sizeof(pFdname->id), "SD_%02X%02X", -+ pDevice->pHcd->SlotNumber, (UINT)SDDEVICE_GET_SDIO_FUNCNO(pDevice)); -+ pFdname->next = NULL; -+ DBG_PRINT(SDDBG_TRACE, ("SDIO BusDriver - OS_InitializeDevice adding id: %s\n", -+ pFdname->id)); -+ pnp_add_id(pFdname, &pDevice->Device); -+ -+ /* deal with DMA settings */ -+ if (pDevice->pHcd->pDmaDescription != NULL) { -+ pDevice->Device.dev.dma_mask = &pDevice->pHcd->pDmaDescription->Mask; -+ pDevice->Device.dev.coherent_dma_mask = pDevice->pHcd->pDmaDescription->Mask; -+ } -+ -+ return SDIO_STATUS_SUCCESS; -+} -+ -+/* -+ * OS_AddDevice - must be pre-initialized with OS_InitializeDevice -+*/ -+SDIO_STATUS OS_AddDevice(PSDDEVICE pDevice, PSDFUNCTION pFunction) -+{ -+ int error; -+ DBG_PRINT(SDDBG_TRACE, ("SDIO BusDriver - OS_AddDevice adding function: %s\n", -+ pFunction->pName)); -+ error = pnp_add_device(&pDevice->Device); -+ if (error < 0) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO BusDriver - OS_AddDevice failed pnp_add_device: %d\n", -+ error)); -+ } -+ /* replace the buggy pnp's release */ -+ pDevice->Device.dev.release = release; -+ -+ return OSErrorToSDIOError(error); -+} -+ -+/* -+ * OS_RemoveDevice - unregister device with driver and bus -+*/ -+void OS_RemoveDevice(PSDDEVICE pDevice) -+{ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO BusDriver - OS_RemoveDevice \n")); -+ pnp_remove_card_device(&pDevice->Device); -+ spin_lock(&InUseDevicesLock); -+ ClearBit(&InUseDevices, pDevice->Device.number); -+ spin_unlock(&InUseDevicesLock); -+ -+ if (pDevice->Device.id != NULL) { -+ KernelFree(pDevice->Device.id); -+ pDevice->Device.id = NULL; -+ } -+} -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Add OS device to bus driver. -+ -+ @function name: SDIO_BusAddOSDevice -+ @category: HD_Reference -+ -+ @output: pDma - descrip[tion of support DMA or NULL -+ @output: pDriver - assigned driver object -+ @output: pDevice - assigned device object -+ -+ @return: SDIO_STATUS - SDIO_STATUS_SUCCESS when successful. -+ -+ @notes: If the HCD does not register with the driver sub-system directly (like in the PCI case), -+ then it should register with the bus driver to obtain OS dependent device objects. -+ All input structures should be maintained throughout the life of the driver. -+ -+ @example: getting device objects: -+ typedef struct _SDHCD_DRIVER { -+ OS_PNPDEVICE HcdDevice; / * the OS device for this HCD * / -+ OS_PNPDRIVER HcdDriver; / * the OS driver for this HCD * / -+ SDDMA_DESCRIPTION Dma; / * driver DMA description * / -+ }SDHCD_DRIVER, *PSDHCD_DRIVER; -+ -+ typedef struct _SDHCD_DRIVER_CONTEXT { -+ PTEXT pDescription; / * human readable device decsription * / -+ SDLIST DeviceList; / * the list of current devices handled by this driver * / -+ OS_SEMAPHORE DeviceListSem; / * protection for the DeviceList * / -+ UINT DeviceCount; / * number of devices currently installed * / -+ SDHCD_DRIVER Driver; / * OS dependent driver specific info * / -+ }SDHCD_DRIVER_CONTEXT, *PSDHCD_DRIVER_CONTEXT; -+ -+ static SDHCD_DRIVER_CONTEXT HcdContext = { -+ .pDescription = DESCRIPTION, -+ .DeviceCount = 0, -+ .Driver.HcdDevice.name = "sdio_xxx_hcd", -+ .Driver.HcdDriver.name = "sdio_xxx_hcd", -+ } -+ ..... -+ status = SDIO_BusAddOSDevice(NULL, &HcdContext.Driver, &HcdContext.Device); -+ if (SDIO_SUCCESS(status) { -+ return Probe(&HcdContext.Device); -+ } -+ return SDIOErrorToOSError(status); -+ -+ @see also: SDIO_BusRemoveOSDevice -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS SDIO_BusAddOSDevice(PSDDMA_DESCRIPTION pDma, POS_PNPDRIVER pDriver, POS_PNPDEVICE pDevice) -+{ -+ int err; -+ struct pnp_id *pFdname; -+ struct pnp_device_id *pFdid; -+ static int slotNumber = 0; /* we just use an increasing count for the slots number */ -+ -+ if (pDma != NULL) { -+ pDevice->dev.dma_mask = &pDma->Mask; -+ pDevice->dev.coherent_dma_mask = pDma->Mask; -+ } -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO BusDriver - SDIO_GetBusOSDevice, registering driver: %s DMAmask: 0x%x\n", -+ pDriver->name, (UINT)*pDevice->dev.dma_mask)); -+ pFdid = KernelAlloc(sizeof(struct pnp_device_id)*2); -+ /* set the id as slot number/function number */ -+ snprintf(pFdid[0].id, sizeof(pFdid[0].id), "SD_%02X08", -+ slotNumber++); -+ pFdid[0].driver_data = 0; -+ pFdid[1].id[0] = '\0'; -+ pFdid[1].driver_data = 0; -+ -+ pDriver->id_table = pFdid; -+ pDriver->flags = PNP_DRIVER_RES_DO_NOT_CHANGE; -+ err = pnp_register_driver(pDriver); -+ if (err < 0) { -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO BusDriver - SDIO_GetBusOSDevice, failed registering driver: %s, err: %d\n", -+ pDriver->name, err)); -+ return OSErrorToSDIOError(err); -+ } -+ -+ pDevice->protocol = &sdio_protocol; -+ pDevice->capabilities = PNP_REMOVABLE | PNP_DISABLE; -+ pDevice->active = 1; -+ -+ pFdname = KernelAlloc(sizeof(struct pnp_id)); -+ /* set the id as slot number/function number */ -+ snprintf(pFdname->id, sizeof(pFdname->id), "SD_%02X08", -+ 0); //??pDevice->pHcd->SlotNumber);//?????fix this, slotnumber isn't vaialble yet -+ pFdname->next = NULL; -+ pnp_add_id(pFdname, pDevice); -+ -+ /* get a unique device number */ -+ spin_lock(&InUseDevicesLock); -+ pDevice->number = FirstClearBit(&InUseDevices); -+ SetBit(&InUseDevices, pDevice->number); -+ spin_unlock(&InUseDevicesLock); -+ pnp_init_resource_table(&pDevice->res); -+ err = pnp_add_device(pDevice); -+ if (err < 0) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO BusDriver - SDIO_GetBusOSDevice failed pnp_device_add: %d\n", -+ err)); -+ pnp_unregister_driver(pDriver); -+ } -+ /* replace the buggy pnp's release */ -+ pDevice->dev.release = release; -+ return OSErrorToSDIOError(err); -+} -+ -+/**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Return OS device from bus driver. -+ -+ @function name: SDIO_BusRemoveOSDevice -+ @category: HD_Reference -+ -+ @input: pDriver - setup PNP driver object -+ @input: pDevice - setup PNP device object -+ -+ @return: none -+ -+ -+ @example: returning device objects: -+ SDIO_BusRemoveOSDevice(&HcdContext.Driver, &HcdContext.Device); -+ -+ -+ @see also: SDIO_BusAddOSDevice -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+void SDIO_BusRemoveOSDevice(POS_PNPDRIVER pDriver, POS_PNPDEVICE pDevice) -+{ -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO BusDriver - SDIO_PutBusOSDevice, unregistering driver: %s\n", -+ pDriver->name)); -+ -+ pnp_remove_card_device(pDevice); -+ if (pDevice->id != NULL) { -+ KernelFree(pDevice->id); -+ pDevice->id = NULL; -+ } -+ -+ spin_lock(&InUseDevicesLock); -+ ClearBit(&InUseDevices, pDevice->number); -+ spin_unlock(&InUseDevicesLock); -+ -+ pnp_unregister_driver(pDriver); -+ if (pDriver->id_table != NULL) { -+ KernelFree((void *)pDriver->id_table); -+ pDriver->id_table = NULL; -+ } -+ -+} -+ -+ -+/* -+ * module init -+*/ -+static int __init sdio_busdriver_init(void) { -+ SDIO_STATUS status; -+ int error; -+ REL_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: loaded\n")); -+ if (!SDIO_SUCCESS((status = _SDIO_BusDriverInitialize()))) { -+ return SDIOErrorToOSError(status); -+ } -+ /* register the sdio bus */ -+ error = pnp_register_protocol(&sdio_protocol); -+ if (error < 0) { -+ REL_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: failed to register bus device, %d\n", error)); -+ _SDIO_BusDriverCleanup(); -+ return error; -+ } -+ return 0; -+} -+ -+/* -+ * module cleanup -+*/ -+static void __exit sdio_busdriver_cleanup(void) { -+ REL_PRINT(SDDBG_TRACE, ("SDIO unloaded\n")); -+ _SDIO_BusDriverCleanup(); -+ pnp_unregister_protocol(&sdio_protocol); -+DBG_PRINT(SDDBG_TRACE, -+ ("SDIO BusDriver - unloaded 1\n")); -+} -+EXPORT_SYMBOL(SDIO_BusAddOSDevice); -+EXPORT_SYMBOL(SDIO_BusRemoveOSDevice); -+ -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+ /* 2.4 */ -+static int RegisterDriver(PSDFUNCTION pFunction) -+{ -+ return 0; -+} -+ -+static int UnregisterDriver(PSDFUNCTION pFunction) -+{ -+ DBG_PRINT(SDDBG_TRACE, -+ ("+-SDIO BusDriver - UnregisterDriver, driver: \n")); -+ return 0; -+} -+ -+/* -+ * OS_InitializeDevice - initialize device that will be registered -+*/ -+SDIO_STATUS OS_InitializeDevice(PSDDEVICE pDevice, PSDFUNCTION pFunction) -+{ -+ return SDIO_STATUS_SUCCESS; -+} -+ -+/* -+ * OS_AddDevice - must be pre-initialized with OS_InitializeDevice -+*/ -+SDIO_STATUS OS_AddDevice(PSDDEVICE pDevice, PSDFUNCTION pFunction) -+{ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO BusDriver - OS_AddDevice adding function: %s\n", -+ pFunction->pName)); -+ return SDIO_STATUS_SUCCESS; -+ -+} -+ -+/* -+ * OS_RemoveDevice - unregister device with driver and bus -+*/ -+void OS_RemoveDevice(PSDDEVICE pDevice) -+{ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO BusDriver - OS_RemoveDevice \n")); -+} -+ -+/* -+ * module init -+*/ -+static int __init sdio_busdriver_init(void) { -+ SDIO_STATUS status; -+ REL_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: loaded\n")); -+ if (!SDIO_SUCCESS((status = _SDIO_BusDriverInitialize()))) { -+ return SDIOErrorToOSError(status); -+ } -+ return 0; -+} -+ -+/* -+ * module cleanup -+*/ -+static void __exit sdio_busdriver_cleanup(void) { -+ REL_PRINT(SDDBG_TRACE, ("SDIO unloaded\n")); -+ _SDIO_BusDriverCleanup(); -+} -+#else ////KERNEL_VERSION -+#error "unsupported kernel version: "UTS_RELEASE -+#endif //KERNEL_VERSION -+ -+MODULE_LICENSE("GPL and additional rights"); -+MODULE_DESCRIPTION(DESCRIPTION); -+MODULE_AUTHOR(AUTHOR); -+ -+module_init(sdio_busdriver_init); -+module_exit(sdio_busdriver_cleanup); -+EXPORT_SYMBOL(SDIO_RegisterHostController); -+EXPORT_SYMBOL(SDIO_UnregisterHostController); -+EXPORT_SYMBOL(SDIO_HandleHcdEvent); -+EXPORT_SYMBOL(SDIO_CheckResponse); -+EXPORT_SYMBOL(SDIO_RegisterFunction); -+EXPORT_SYMBOL(SDIO_UnregisterFunction); -diff --git a/drivers/sdio/stack/busdriver/sdio_function.c b/drivers/sdio/stack/busdriver/sdio_function.c -new file mode 100644 -index 0000000..78b8e17 ---- /dev/null -+++ b/drivers/sdio/stack/busdriver/sdio_function.c -@@ -0,0 +1,715 @@ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+@file: sdio_function.c -+ -+@abstract: OS independent bus driver support for function drivers -+ -+@notes: This file supports the interface between SDIO function drivers and the bus driver. -+ -+@notice: Copyright (c), 2004-2005 Atheros Communications, Inc. -+ -+ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * Software distributed under the License is distributed on an "AS -+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -+ * implied. See the License for the specific language governing -+ * rights and limitations under the License. -+ * -+ * Portions of this code were developed with information supplied from the -+ * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply: -+ * -+ * The following conditions apply to the release of the SD simplified specification (�Simplified -+ * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete -+ * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided -+ * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified -+ * Specification may require a license from the SD Card Association or other third parties. -+ * Disclaimers: -+ * The information contained in the Simplified Specification is presented only as a standard -+ * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any -+ * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for -+ * any damages, any infringements of patents or other right of the SD Card Association or any third -+ * parties, which may result from its use. No license is granted by implication, estoppel or otherwise -+ * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall -+ * be construed as an obligation by the SD Card Association to disclose or distribute any technical -+ * information, know-how or other confidential information to any third party. -+ * -+ * -+ * The initial developers of the original code are Seung Yi and Paul Lever -+ * -+ * sdio@atheros.com -+ * -+ * -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define MODULE_NAME SDBUSDRIVER -+#include <linux/sdio/ctsystem.h> -+#include <linux/sdio/sdio_busdriver.h> -+#include <linux/sdio/sdio_lib.h> -+#include "_busdriver.h" -+ -+static SDIO_STATUS ProbeForDevice(PSDFUNCTION pFunction); -+ -+#ifdef CT_MAN_CODE_CHECK -+static UINT16 ManCodeCheck = CT_MAN_CODE_CHECK; -+#endif -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Register a function driver with the bus driver. -+ -+ @function name: SDIO_RegisterFunction -+ @prototype: SDIO_STATUS SDIO_RegisterFunction(PSDFUNCTION pFunction) -+ @category: PD_Reference -+ @input: pFunction - the function definition structure. -+ -+ @output: none -+ -+ @return: SDIO_STATUS - SDIO_STATUS_SUCCESS when succesful. -+ -+ @notes: Each function driver must register with the bus driver once upon loading. -+ The calling function must be prepared to receive a Probe callback before -+ this function returns. This will occur when an perpheral device is already -+ pluugged in that is supported by this function. -+ The function driver should unregister itself when exiting. -+ The bus driver checks for possible function drivers to support a device -+ in reverse registration order. -+ -+ @example: Registering a function driver: -+ //list of devices supported by this function driver -+ static SD_PNP_INFO Ids[] = { -+ {.SDIO_ManufacturerID = 0xaa55, -+ .SDIO_ManufacturerCode = 0x5555, -+ .SDIO_FunctionNo = 1}, -+ {} //list is null termintaed -+ }; -+ static GENERIC_FUNCTION_CONTEXT FunctionContext = { -+ .Function.pName = "sdio_generic", //name of the device -+ .Function.Version = CT_SDIO_STACK_VERSION_CODE, // set stack version -+ .Function.MaxDevices = 1, //maximum number of devices supported by this driver -+ .Function.NumDevices = 0, //current number of devices, always zero to start -+ .Function.pIds = Ids, //the list of devices supported by this device -+ .Function.pProbe = Probe, //pointer to the function drivers Probe function -+ // that will be called when a possibly supported device -+ // is inserted. -+ .Function.pRemove = Remove, //pointer to the function drivers Remove function -+ / that will be called when a device is removed. -+ .Function.pContext = &FunctionContext, //data value that will be passed into Probe and -+ // Remove callbacks. -+ }; -+ SDIO_STATUS status; -+ status = SDIO_RegisterFunction(&FunctionContext.Function) -+ if (!SDIO_SUCCESS(status)) { -+ ...failed to register -+ } -+ -+ @see also: SDIO_UnregisterFunction -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS _SDIO_RegisterFunction(PSDFUNCTION pFunction) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ -+#ifdef CT_MAN_CODE_CHECK -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO Bus Driver: _SDIO_RegisterFunction: WARNING, this version is locked to Memory cards and SDIO cards with JEDEC IDs of: 0x%X\n", -+ ManCodeCheck)); -+#else -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: _SDIO_RegisterFunction\n")); -+#endif -+ -+ DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: Function Driver Stack Version: %d.%d \n", -+ GET_SDIO_STACK_VERSION_MAJOR(pFunction),GET_SDIO_STACK_VERSION_MINOR(pFunction))); -+ -+ if (!CHECK_FUNCTION_DRIVER_VERSION(pFunction)) { -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO Bus Driver: Function Major Version Mismatch (hcd = %d, bus driver = %d)\n", -+ GET_SDIO_STACK_VERSION_MAJOR(pFunction), CT_SDIO_STACK_VERSION_MAJOR(g_Version))); -+ return SDIO_STATUS_INVALID_PARAMETER; -+ } -+ -+ -+ /* sanity check the driver */ -+ if ((pFunction == NULL) || -+ (pFunction->pProbe == NULL) || -+ (pFunction->pIds == NULL)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_RegisterFunction, invalid registration data\n")); -+ return SDIO_STATUS_INVALID_PARAMETER; -+ } -+ /* protect the function list and add the function */ -+ if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->FunctionListSem)))) { -+ goto cleanup; /* wait interrupted */ -+ } -+ SignalInitialize(&pFunction->CleanupReqSig); -+ SDLIST_INIT(&pFunction->DeviceList); -+ SDListAdd(&pBusContext->FunctionList, &pFunction->SDList); -+ if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->FunctionListSem)))) { -+ goto cleanup; /* wait interrupted */ -+ } -+ -+ /* see if we have devices for this new function driver */ -+ ProbeForDevice(pFunction); -+ -+ return status; -+cleanup: -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_RegisterFunction, error exit 0x%X\n", status)); -+ return status; -+} -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Unregister a function driver with the bus driver. -+ -+ @function name: SDIO_UnregisterFunction -+ @prototype: SDIO_STATUS SDIO_UnregisterFunction(PSDFUNCTION pFunction) -+ @category: PD_Reference -+ -+ @input: pFunction - the function definition structure. -+ -+ @output: none -+ -+ @return: SDIO_STATUS - SDIO_STATUS_SUCCESS when succesful. -+ -+ @notes: Each function driver must unregister from the bus driver when the function driver -+ exits. -+ A function driver must disconnect from any interrupts before calling this function. -+ -+ @example: Unregistering a function driver: -+ SDIO_UnregisterFunction(&FunctionContext.Function); -+ -+ @see also: SDIO_RegisterFunction -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS _SDIO_UnregisterFunction(PSDFUNCTION pFunction) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ PSDDEVICE pDevice; -+ -+ DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: _SDIO_UnregisterFunction\n")); -+ -+ /* protect the function list and synchronize with Probe() and Remove()*/ -+ if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->FunctionListSem)))) { -+ goto cleanup; /* wait interrupted */ -+ } -+ /* remove this function from the function list */ -+ SDListRemove(&pFunction->SDList); -+ /* now remove this function as the handler for any of its devices */ -+ SDITERATE_OVER_LIST_ALLOW_REMOVE(&pFunction->DeviceList, pDevice, SDDEVICE,FuncListLink) { -+ if (pDevice->pFunction == pFunction) { -+ /* notify removal */ -+ NotifyDeviceRemove(pDevice); -+ } -+ }SDITERATE_END; -+ -+ SignalDelete(&pFunction->CleanupReqSig); -+ -+ if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->FunctionListSem)))) { -+ goto cleanup; /* wait interrupted */ -+ } -+ DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: _SDIO_UnregisterFunction\n")); -+ return status; -+ -+cleanup: -+ DBG_PRINT(SDDBG_ERROR, ("-SDIO Bus Driver: _SDIO_UnregisterFunction, error exit 0x%X\n", status)); -+ return status; -+} -+ -+/* documentation headers only for Probe and Remove */ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: This function is called by the Busdriver when a device is inserted that can be supported by this function driver. -+ -+ @function name: Probe -+ @prototype: BOOL (*pProbe)(struct _SDFUNCTION *pFunction, struct _SDDEVICE *pDevice) -+ @category: PD_Reference -+ -+ @input: pFunction - the function definition structure that was passed to Busdriver -+ via the SDIO_RegisterFunction. -+ @input: pDevice - the description of the newly inserted device. -+ -+ @output: none -+ -+ @return: TRUE - this function driver will suport this device -+ FALSE - this function driver will not support this device -+ -+ @notes: The Busdriver calls the Probe function of a function driver to inform it that device is -+ available for the function driver to control. The function driver should initialize the -+ device and be pepared to acceopt any interrupts from the device before returning. -+ -+ @example: Example of typical Probe function callback: -+ static BOOL Probe(PSDFUNCTION pFunction, PSDDEVICE pDevice) { -+ ...get the our context info passed into the SDIO_RegisterFunction -+ PSDXXX_DRIVER_CONTEXT pFunctionContext = -+ (PSDXXX_DRIVER_CONTEXT)pFunction->pContext; -+ SDIO_STATUS status; -+ //test the identification of this device and ensure we want to support it -+ // we can test based on class, or use more specific tests on SDIO_ManufacturerID, etc. -+ if (pDevice->pId[0].SDIO_FunctionClass == XXX) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO XXX Function: Probe - card matched (0x%X/0x%X/0x%X)\n", -+ pDevice->pId[0].SDIO_ManufacturerID, -+ pDevice->pId[0].SDIO_ManufacturerCode, -+ pDevice->pId[0].SDIO_FunctionNo)); -+ ... -+ -+ @see also: SDIO_RegisterFunction -+ @see also: Remove -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+ -+BOOL FilterPnpInfo(PSDDEVICE pDevice) -+{ -+#ifdef CT_MAN_CODE_CHECK -+ if (pDevice->pId[0].CardFlags & CARD_SDIO) { -+ if (pDevice->pId[0].SDIO_ManufacturerCode != ManCodeCheck) { -+ DBG_PRINT(SDDBG_ERROR, -+ ("SDIO Card with JEDEC ID:0x%X , not Allowed! Driver check halted. " -+ "Please Contact sales@codetelligence.com.\n", -+ pDevice->pId[0].SDIO_ManufacturerCode)); -+ return FALSE; -+ } -+ } -+ return TRUE; -+#else -+ return TRUE; -+#endif -+} -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: This function is called by the Busdriver when a device controlled by this function -+ function driver is removed. -+ -+ @function name: Remove -+ @prototype: void (*pRemove)(struct _SDFUNCTION *pFunction, struct _SDDEVICE *pDevice) -+ @category: PD_Reference -+ -+ @input: pFunction - the function definition structure that was passed to Busdriver -+ via the SDIO_RegisterFunction. -+ @input: pDevice - the description of the device being removed. -+ -+ @output: none -+ -+ @return: none -+ -+ @notes: The Busdriver calls the Remove function of a function driver to inform it that device it -+ was supporting has been removed. The device has already been removed, so no further I/O -+ to the device can be performed. -+ -+ @example: Example of typical Remove function callback: -+ void Remove(PSDFUNCTION pFunction, PSDDEVICE pDevice) { -+ // get the our context info passed into the SDIO_RegisterFunction -+ PSDXXX_DRIVER_CONTEXT pFunctionContext = -+ (PSDXXX_DRIVER_CONTEXT)pFunction->pContext; -+ ...free any acquired resources. -+ -+ @see also: SDIO_RegisterFunction -+ @see also: Probe -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+ -+/* -+ * ProbeForFunction - look for a function driver to handle this card -+ * -+*/ -+SDIO_STATUS ProbeForFunction(PSDDEVICE pDevice, PSDHCD pHcd) { -+ SDIO_STATUS status; -+ PSDLIST pList; -+ PSDFUNCTION pFunction; -+ -+ DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: ProbeForFunction\n")); -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: ProbeForFunction - Dump of Device PNP Data: \n")); -+ DBG_PRINT(SDDBG_TRACE, (" Card Flags 0x%X \n", pDevice->pId[0].CardFlags)); -+ if (pDevice->pId[0].CardFlags & CARD_SDIO) { -+ DBG_PRINT(SDDBG_TRACE, (" SDIO MANF: 0x%X \n", pDevice->pId[0].SDIO_ManufacturerID)); -+ DBG_PRINT(SDDBG_TRACE, (" SDIO MANFCODE: 0x%X \n", pDevice->pId[0].SDIO_ManufacturerCode)); -+ DBG_PRINT(SDDBG_TRACE, (" SDIO FuncNo: %d \n", pDevice->pId[0].SDIO_FunctionNo)); -+ DBG_PRINT(SDDBG_TRACE, (" SDIO FuncClass: %d \n", pDevice->pId[0].SDIO_FunctionClass)); -+ } -+ if (pDevice->pId[0].CardFlags & (CARD_MMC | CARD_SD)) { -+ DBG_PRINT(SDDBG_TRACE, (" SDMMC MANFID: 0x%X \n",pDevice->pId[0].SDMMC_ManfacturerID)); -+ DBG_PRINT(SDDBG_TRACE, (" SDMMC OEMID: 0x%X \n",pDevice->pId[0].SDMMC_OEMApplicationID)); -+ } -+ -+ if (!FilterPnpInfo(pDevice)) { -+ status = SDIO_STATUS_SUCCESS; -+ goto cleanup; -+ } -+ -+ /* protect the function list */ -+ if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->FunctionListSem)))) { -+ goto cleanup; /* wait interrupted */ -+ } -+ -+ /* protect against ProbeForDevice */ -+ if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->DeviceListSem)))) { -+ /* release the function list semaphore we just took */ -+ SemaphorePost(&pBusContext->FunctionListSem); -+ goto cleanup; -+ } -+ -+ if (pDevice->pFunction != NULL) { -+ /* device already has a function driver handling it */ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: ProbeForFunction, device already has function\n")); -+ /* release function list */ -+ SemaphorePost(&pBusContext->DeviceListSem); -+ /* release function list */ -+ SemaphorePost(&pBusContext->FunctionListSem); -+ /* just return success */ -+ status = SDIO_STATUS_SUCCESS; -+ goto cleanup; -+ } -+ -+ /* release device list */ -+ SemaphorePost(&pBusContext->DeviceListSem); -+ -+ /* walk functions looking for one that can handle this device */ -+ SDITERATE_OVER_LIST(&pBusContext->FunctionList, pList) { -+ pFunction = CONTAINING_STRUCT(pList, SDFUNCTION, SDList); -+ if (pFunction->NumDevices >= pFunction->MaxDevices) { -+ /* function can't support any more devices */ -+ continue; -+ } -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: ProbeForFunction - checking: %s \n", -+ pFunction->pName)); -+ -+ /* see if this function handles this device */ -+ if (IsPotentialIdMatch(pDevice->pId, pFunction->pIds)) { -+ if (!FilterPnpInfo(pDevice)) { -+ break; -+ } -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: ProbeForFunction -Got Match, probing: %s \n", -+ pFunction->pName)); -+ /* we need to setup with the OS bus driver before the probe, so probe can -+ do OS operations. */ -+ OS_InitializeDevice(pDevice, pFunction); -+ if (!SDIO_SUCCESS(OS_AddDevice(pDevice, pFunction))) { -+ break; -+ } -+ /* close enough match, ask the function driver if it supports us */ -+ if (pFunction->pProbe(pFunction, pDevice)) { -+ /* she accepted the device, add to list */ -+ pDevice->pFunction = pFunction; -+ SDListAdd(&pFunction->DeviceList, &pDevice->FuncListLink); -+ pFunction->NumDevices++; -+ break; -+ } else { -+ DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: %s did not claim the device \n", -+ pFunction->pName)); -+ /* didn't take this device */ -+ OS_RemoveDevice(pDevice); -+ } -+ -+ } -+ } -+ if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->FunctionListSem)))) { -+ goto cleanup; /* wait interrupted */ -+ } -+ DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: ProbeForFunction\n")); -+ return status; -+cleanup: -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: ProbeForFunction, error exit 0x%X\n", status)); -+ return status; -+} -+ -+/* -+ * ProbeForDevice - look for a device that this function driver supports -+ * -+*/ -+static SDIO_STATUS ProbeForDevice(PSDFUNCTION pFunction) { -+ SDIO_STATUS status; -+ PSDLIST pList; -+ PSDDEVICE pDevice; -+ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: ProbeForDevice\n")); -+ if (pFunction->NumDevices >= pFunction->MaxDevices) { -+ /* function can't support any more devices */ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: ProbeForDevice, too many devices in function\n")); -+ return SDIO_STATUS_SUCCESS; -+ } -+ -+ /* protect the driver list */ -+ if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->DeviceListSem)))) { -+ goto cleanup; /* wait interrupted */ -+ } -+ /* walk device list */ -+ SDITERATE_OVER_LIST(&pBusContext->DeviceList, pList) { -+ pDevice = CONTAINING_STRUCT(pList, SDDEVICE, SDList); -+ if (pDevice->pFunction != NULL) { -+ /* device already has a function driver handling it */ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: ProbeForDevice, device already has function\n")); -+ continue; -+ } -+ /* see if this function handles this device */ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: ProbeForDevice, matching ID:%d %d class:%d\n", -+ pDevice->pId[0].SDIO_ManufacturerID, -+ pDevice->pId[0].SDIO_FunctionNo, -+ pDevice->pId[0].SDIO_FunctionClass)); -+ if (IsPotentialIdMatch(pDevice->pId, pFunction->pIds)) { -+ if (!FilterPnpInfo(pDevice)) { -+ break; -+ } -+ /* we need to setup with the OS bus driver before the probe, so probe can -+ do OS operations. */ -+ OS_InitializeDevice(pDevice, pFunction); -+ if (!SDIO_SUCCESS(OS_AddDevice(pDevice, pFunction))) { -+ break; -+ } -+ /* close enough match, ask the function driver if it supports us */ -+ if (pFunction->pProbe(pFunction, pDevice)) { -+ /* she accepted the device, add to list */ -+ pDevice->pFunction = pFunction; -+ SDListAdd(&pFunction->DeviceList, &pDevice->FuncListLink); -+ pFunction->NumDevices++; -+ break; -+ } else { -+ DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: %s did not claim the device \n", -+ pFunction->pName)); -+ /* didn't take this device */ -+ OS_RemoveDevice(pDevice); -+ } -+ } -+ } -+ if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->DeviceListSem)))) { -+ goto cleanup; /* wait interrupted */ -+ } -+ -+ return status; -+cleanup: -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: ProbeForDevice, error exit 0x%X\n", status)); -+ return status; -+} -+ -+#if 0 -+static void DumpPnpEntry(PSD_PNP_INFO pInfo) -+{ -+ DBG_PRINT(SDDBG_TRACE, ("Function PnpInfo Dump: \n")); -+ DBG_PRINT(SDDBG_TRACE, (" Card Flags 0x%X \n", pInfo->CardFlags)); -+ DBG_PRINT(SDDBG_TRACE, (" SDIO MANF: 0x%X \n", pInfo->SDIO_ManufacturerID)); -+ DBG_PRINT(SDDBG_TRACE, (" SDIO MANFCODE: 0x%X \n", pInfo->SDIO_ManufacturerCode)); -+ DBG_PRINT(SDDBG_TRACE, (" SDIO FuncNo: %d \n", pInfo->SDIO_FunctionNo)); -+ DBG_PRINT(SDDBG_TRACE, (" SDIO FuncClass: %d \n", pInfo->SDIO_FunctionClass)); -+ DBG_PRINT(SDDBG_TRACE, (" SDMMC MANFID: 0x%X \n", pInfo->SDMMC_ManfacturerID)); -+ DBG_PRINT(SDDBG_TRACE, (" SDMMC OEMID: 0x%X \n", pInfo->SDMMC_OEMApplicationID)); -+} -+#endif -+/* -+ * IsPotentialIdMatch - test for potential device match -+ * -+*/ -+BOOL IsPotentialIdMatch(PSD_PNP_INFO pIdsDev, PSD_PNP_INFO pIdsFuncList) { -+ PSD_PNP_INFO pTFn; -+ BOOL match = FALSE; -+ -+ for (pTFn = pIdsFuncList;!IS_LAST_SDPNPINFO_ENTRY(pTFn);pTFn++) { -+ //DumpPnpEntry(pTFn); -+ /* check specific SDIO Card manufacturer ID, Code and Function number */ -+ if ((pIdsDev->SDIO_ManufacturerID != 0) && -+ (pTFn->SDIO_ManufacturerID != 0) && -+ (pIdsDev->SDIO_ManufacturerID == pTFn->SDIO_ManufacturerID) && -+ (pIdsDev->SDIO_ManufacturerCode == pTFn->SDIO_ManufacturerCode) && -+ ((pIdsDev->SDIO_FunctionNo == pTFn->SDIO_FunctionNo) || -+ (pTFn->SDIO_FunctionNo == 0)) ) { -+ match = TRUE; -+ break; -+ } -+ /* check generic function class */ -+ if ((pIdsDev->SDIO_FunctionClass != 0) && -+ (pTFn->SDIO_FunctionClass != 0) && -+ (pIdsDev->SDIO_FunctionClass == pTFn->SDIO_FunctionClass)) { -+ match = TRUE; -+ break; -+ } -+ /* check specific SDMMC MANFID and APPLICATION ID, NOTE SANDISK -+ * uses a MANFID of zero! */ -+ if ((pTFn->SDMMC_OEMApplicationID != 0) && -+ (pIdsDev->SDMMC_ManfacturerID == pTFn->SDMMC_ManfacturerID) && -+ (pIdsDev->SDMMC_OEMApplicationID == pTFn->SDMMC_OEMApplicationID)) { -+ match = TRUE; -+ break; -+ } -+ -+ /* check generic SD Card */ -+ if ((pIdsDev->CardFlags & CARD_SD) && -+ (pTFn->CardFlags & CARD_SD)){ -+ match = TRUE; -+ break; -+ } -+ -+ /* check generic MMC Card */ -+ if ((pIdsDev->CardFlags & CARD_MMC) && -+ (pTFn->CardFlags & CARD_MMC)){ -+ match = TRUE; -+ break; -+ } -+ -+ /* check raw Card */ -+ if ((pIdsDev->CardFlags & CARD_RAW) && -+ (pTFn->CardFlags & CARD_RAW)){ -+ match = TRUE; -+ break; -+ } -+ } -+ -+ return match; -+} -+ -+/* -+ * NotifyDeviceRemove - tell function driver on this device that the device is being removed -+ * -+*/ -+SDIO_STATUS NotifyDeviceRemove(PSDDEVICE pDevice) { -+ SDIO_STATUS status; -+ SDREQUESTQUEUE cancelQueue; -+ PSDREQUEST pReq; -+ CT_DECLARE_IRQ_SYNC_CONTEXT(); -+ -+ InitializeRequestQueue(&cancelQueue); -+ -+ if ((pDevice->pFunction != NULL) && -+ (pDevice->pFunction->pRemove != NULL)){ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: removing device 0x%X\n", (INT)pDevice)); -+ /* fail any outstanding requests for this device */ -+ /* acquire lock for request queue */ -+ status = _AcquireHcdLock(pDevice->pHcd); -+ if (!SDIO_SUCCESS(status)) { -+ return status; -+ } -+ /* mark the function to block any more requests comming down */ -+ pDevice->pFunction->Flags |= SDFUNCTION_FLAG_REMOVING; -+ /* walk through HCD queue and remove this function's requests */ -+ SDITERATE_OVER_LIST_ALLOW_REMOVE(&pDevice->pHcd->RequestQueue.Queue, pReq, SDREQUEST, SDList) { -+ if (pReq->pFunction == pDevice->pFunction) { -+ /* cancel this request, as this device or function is being removed */ -+ /* note that these request are getting completed out of order */ -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - NotifyDeviceRemove: canceling req 0x%X\n", (UINT)pReq)); -+ pReq->Status = SDIO_STATUS_CANCELED; -+ /* remove it from the HCD queue */ -+ SDListRemove(&pReq->SDList); -+ /* add it to the cancel queue */ -+ QueueRequest(&cancelQueue, pReq); -+ } -+ }SDITERATE_END; -+ -+ status = _ReleaseHcdLock(pDevice->pHcd); -+ -+ /* now empty the cancel queue if anything is in there */ -+ while (TRUE) { -+ pReq = DequeueRequest(&cancelQueue); -+ if (NULL == pReq) { -+ break; -+ } -+ /* complete the request */ -+ DoRequestCompletion(pReq, pDevice->pHcd); -+ } -+ /* re-acquire the lock to deal with the current request */ -+ status = _AcquireHcdLock(pDevice->pHcd); -+ if (!SDIO_SUCCESS(status)) { -+ return status; -+ } -+ /* now deal with the current request */ -+ pReq = GET_CURRENT_REQUEST(pDevice->pHcd); -+ if ((pReq !=NULL) && (pReq->pFunction == pDevice->pFunction) && (pReq->pFunction != NULL)) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - NotifyDeviceRemove: Outstanding Req 0x%X on HCD: 0x%X.. waiting...\n", -+ (UINT)pReq, (UINT)pDevice->pHcd)); -+ /* the outstanding request on this device is for the function being removed */ -+ pReq->Flags |= SDREQ_FLAGS_CANCELED; -+ /* wait for this request to get completed normally */ -+ status = _ReleaseHcdLock(pDevice->pHcd); -+ SignalWait(&pDevice->pFunction->CleanupReqSig); -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - NotifyDeviceRemove: Outstanding HCD Req 0x%X completed \n", (UINT)pReq)); -+ } else { -+ /* release lock */ -+ status = _ReleaseHcdLock(pDevice->pHcd); -+ } -+ -+ /* synchronize with ISR SYNC Handlers */ -+ status = SemaphorePendInterruptable(&pBusContext->DeviceListSem); -+ if (!SDIO_SUCCESS(status)) { -+ return status; -+ } -+ /* call this devices Remove function */ -+ pDevice->pFunction->pRemove(pDevice->pFunction,pDevice); -+ pDevice->pFunction->NumDevices--; -+ /* make sure the sync handler is NULLed out */ -+ pDevice->pIrqFunction = NULL; -+ SemaphorePost(&pBusContext->DeviceListSem); -+ -+ OS_RemoveDevice(pDevice); -+ /* detach this device from the function list it belongs to */ -+ SDListRemove(&pDevice->FuncListLink); -+ pDevice->pFunction->Flags &= ~SDFUNCTION_FLAG_REMOVING; -+ pDevice->pFunction = NULL; -+ } -+ return SDIO_STATUS_SUCCESS; -+} -+ -+ -+/* -+ * RemoveHcdFunctions - remove all functions attached to an HCD -+ * -+*/ -+SDIO_STATUS RemoveHcdFunctions(PSDHCD pHcd) { -+ SDIO_STATUS status; -+ PSDLIST pList; -+ PSDFUNCTION pFunction; -+ PSDDEVICE pDevice; -+ DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: RemoveHcdFunctions\n")); -+ -+ /* walk through the functions and remove the ones associated with this HCD */ -+ /* protect the driver list */ -+ if (!SDIO_SUCCESS((status = SemaphorePend(&pBusContext->FunctionListSem)))) { -+ goto cleanup; /* wait interrupted */ -+ } -+ /* mark that card is being removed */ -+ pHcd->CardProperties.CardState |= CARD_STATE_REMOVED; -+ SDITERATE_OVER_LIST(&pBusContext->FunctionList, pList) { -+ pFunction = CONTAINING_STRUCT(pList, SDFUNCTION, SDList); -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: scanning function 0x%X, %s\n", (INT)pFunction, -+ (pFunction == NULL)?"NULL":pFunction->pName)); -+ -+ /* walk the devices on this function and look for a match */ -+ SDITERATE_OVER_LIST_ALLOW_REMOVE(&pFunction->DeviceList, pDevice, SDDEVICE,FuncListLink) { -+ if (pDevice->pHcd == pHcd) { -+ /* match, remove it */ -+ NotifyDeviceRemove(pDevice); -+ } -+ SDITERATE_END; -+ SDITERATE_END; -+ if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->FunctionListSem)))) { -+ goto cleanup; /* wait interrupted */ -+ } -+ DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: RemoveHcdFunctions\n")); -+ return SDIO_STATUS_SUCCESS; -+ -+cleanup: -+ DBG_PRINT(SDDBG_ERROR, ("-SDIO Bus Driver: RemoveHcdFunctions, error exit 0x%X\n", status)); -+ return status; -+} -+ -+/* -+ * RemoveAllFunctions - remove all functions attached -+ * -+*/ -+SDIO_STATUS RemoveAllFunctions() -+{ -+ SDIO_STATUS status; -+ PSDLIST pList; -+ PSDHCD pHcd; -+ -+ /* walk through the HCDs */ -+ /* protect the driver list */ -+ if (!SDIO_SUCCESS((status = SemaphorePend(&pBusContext->HcdListSem)))) { -+ goto cleanup; /* wait interrupted */ -+ } -+ SDITERATE_OVER_LIST(&pBusContext->HcdList, pList) { -+ pHcd = CONTAINING_STRUCT(pList, SDHCD, SDList); -+ /* remove the functions */ -+ RemoveHcdFunctions(pHcd); -+ } -+ if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->HcdListSem)))) { -+ goto cleanup; /* wait interrupted */ -+ } -+ return SDIO_STATUS_SUCCESS; -+cleanup: -+ DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: RemoveAllFunctions, error exit 0x%X\n", status)); -+ return status; -+} -+ -diff --git a/drivers/sdio/stack/lib/Makefile b/drivers/sdio/stack/lib/Makefile -new file mode 100644 -index 0000000..44fa038 ---- /dev/null -+++ b/drivers/sdio/stack/lib/Makefile -@@ -0,0 +1,2 @@ -+obj-$(CONFIG_SDIO) += sdio_lib.o -+sdio_lib-objs := sdio_lib_c.o sdio_lib_os.o -diff --git a/drivers/sdio/stack/lib/_sdio_lib.h b/drivers/sdio/stack/lib/_sdio_lib.h -new file mode 100644 -index 0000000..28762b0 ---- /dev/null -+++ b/drivers/sdio/stack/lib/_sdio_lib.h -@@ -0,0 +1,50 @@ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+@file: _sdio_lib.h -+ -+@abstract: SDIO Lib internal include -+ -+#notes: -+ -+@notice: Copyright (c), 2004-2006 Atheros Communications, Inc. -+ -+ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * Software distributed under the License is distributed on an "AS -+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -+ * implied. See the License for the specific language governing -+ * rights and limitations under the License. -+ * -+ * Portions of this code were developed with information supplied from the -+ * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply: -+ * -+ * The following conditions apply to the release of the SD simplified specification (�Simplified -+ * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete -+ * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided -+ * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified -+ * Specification may require a license from the SD Card Association or other third parties. -+ * Disclaimers: -+ * The information contained in the Simplified Specification is presented only as a standard -+ * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any -+ * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for -+ * any damages, any infringements of patents or other right of the SD Card Association or any third -+ * parties, which may result from its use. No license is granted by implication, estoppel or otherwise -+ * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall -+ * be construed as an obligation by the SD Card Association to disclose or distribute any technical -+ * information, know-how or other confidential information to any third party. -+ * -+ * -+ * The initial developers of the original code are Seung Yi and Paul Lever -+ * -+ * sdio@atheros.com -+ * -+ * -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#ifndef ___SDIO_LIB_H___ -+#define ___SDIO_LIB_H___ -+ -+#endif /* ___SDIO_LIB_H___*/ -diff --git a/drivers/sdio/stack/lib/sdio_lib_c.c b/drivers/sdio/stack/lib/sdio_lib_c.c -new file mode 100644 -index 0000000..4bc5a83 ---- /dev/null -+++ b/drivers/sdio/stack/lib/sdio_lib_c.c -@@ -0,0 +1,908 @@ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+@file: sdio_lib_c.c -+ -+@abstract: OS independent SDIO library functions -+@category abstract: Support_Reference Support Functions. -+ -+@notes: Support functions for device I/O -+ -+@notice: Copyright (c), 2004-2005 Atheros Communications, Inc. -+ -+ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * Software distributed under the License is distributed on an "AS -+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -+ * implied. See the License for the specific language governing -+ * rights and limitations under the License. -+ * -+ * Portions of this code were developed with information supplied from the -+ * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply: -+ * -+ * The following conditions apply to the release of the SD simplified specification (�Simplified -+ * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete -+ * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided -+ * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified -+ * Specification may require a license from the SD Card Association or other third parties. -+ * Disclaimers: -+ * The information contained in the Simplified Specification is presented only as a standard -+ * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any -+ * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for -+ * any damages, any infringements of patents or other right of the SD Card Association or any third -+ * parties, which may result from its use. No license is granted by implication, estoppel or otherwise -+ * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall -+ * be construed as an obligation by the SD Card Association to disclose or distribute any technical -+ * information, know-how or other confidential information to any third party. -+ * -+ * -+ * The initial developers of the original code are Seung Yi and Paul Lever -+ * -+ * sdio@atheros.com -+ * -+ * -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define MODULE_NAME SDLIB_ -+ -+#include <linux/sdio/ctsystem.h> -+#include <linux/sdio/sdio_busdriver.h> -+#include <linux/sdio/_sdio_defs.h> -+#include <linux/sdio/sdio_lib.h> -+#include "_sdio_lib.h" -+ -+#define _Cmd52WriteByteCommon(pDev, Address, pValue) \ -+ _SDLIB_IssueCMD52((pDev),0,(Address),(pValue),1,TRUE) -+#define _Cmd52ReadByteCommon(pDev, Address, pValue) \ -+ _SDLIB_IssueCMD52((pDev),0,(Address),pValue,1,FALSE) -+#define _Cmd52ReadMultipleCommon(pDev, Address, pBuf,length) \ -+ _SDLIB_IssueCMD52((pDev),0,(Address),(pBuf),(length),FALSE) -+ -+/* inline version */ -+static INLINE void _iSDLIB_SetupCMD52Request(UINT8 FuncNo, -+ UINT32 Address, -+ BOOL Write, -+ UINT8 WriteData, -+ PSDREQUEST pRequest) { -+ if (Write) { -+ SDIO_SET_CMD52_ARG(pRequest->Argument,CMD52_WRITE, -+ FuncNo, -+ CMD52_NORMAL_WRITE,Address,WriteData); -+ } else { -+ SDIO_SET_CMD52_ARG(pRequest->Argument,CMD52_READ,FuncNo,0,Address,0x00); -+ } -+ -+ pRequest->Flags = SDREQ_FLAGS_RESP_SDIO_R5; -+ pRequest->Command = CMD52; -+} -+ -+/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Setup cmd52 requests -+ -+ @function name: SDLIB_SetupCMD52Request -+ @prototype: void SDLIB_SetupCMD52Request(UINT8 FuncNo, -+ UINT32 Address, -+ BOOL Write, -+ UINT8 WriteData, -+ PSDREQUEST pRequest) -+ @category: PD_Reference -+ -+ @input: FunctionNo - function number. -+ @input: Address - I/O address, 17-bit register address. -+ @input: Write - TRUE if a write operation, FALSE for reads. -+ @input: WriteData - write data, byte to write if write operation. -+ -+ @output: pRequest - request is updated with cmd52 parameters -+ -+ @return: none -+ -+ @notes: This function does not perform any I/O. For register reads, the completion -+ routine can use the SD_R5_GET_READ_DATA() macro to extract the register value. -+ The routine should also extract the response flags using the SD_R5_GET_RESP_FLAGS() -+ macro and check the flags with the SD_R5_ERRORS mask. -+ -+ @example: Getting the register value from the completion routine: -+ flags = SD_R5_GET_RESP_FLAGS(pRequest->Response); -+ if (flags & SD_R5_ERRORS) { -+ ... errors -+ } else { -+ registerValue = SD_R5_GET_READ_DATA(pRequest->Response); -+ } -+ -+ @see also: SDLIB_IssueCMD52 -+ @see also: SDDEVICE_CALL_REQUEST_FUNC -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+void _SDLIB_SetupCMD52Request(UINT8 FuncNo, -+ UINT32 Address, -+ BOOL Write, -+ UINT8 WriteData, -+ PSDREQUEST pRequest) -+{ -+ _iSDLIB_SetupCMD52Request(FuncNo,Address,Write,WriteData,pRequest); -+} -+ -+/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Issue a CMD52 to read or write a register -+ -+ @function name: SDLIB_IssueCMD52 -+ @prototype: SDIO_STATUS SDLIB_IssueCMD52(PSDDEVICE pDevice, -+ UINT8 FuncNo, -+ UINT32 Address, -+ PUINT8 pData, -+ INT ByteCount, -+ BOOL Write) -+ @category: PD_Reference -+ @input: pDevice - the device that is the target of the command. -+ @input: FunctionNo - function number of the target. -+ @input: Address - 17-bit register address. -+ @input: ByteCount - number of bytes to read or write, -+ @input: Write - TRUE if a write operation, FALSE for reads. -+ @input: pData - data buffer for writes. -+ -+ @output: pData - data buffer for writes. -+ -+ @return: SDIO Status -+ -+ @notes: This function will allocate a request and issue multiple byte reads or writes -+ to satisfy the ByteCount requested. This function is fully synchronous and will block -+ the caller. -+ -+ @see also: SDLIB_SetupCMD52Request -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS _SDLIB_IssueCMD52(PSDDEVICE pDevice, -+ UINT8 FuncNo, -+ UINT32 Address, -+ PUINT8 pData, -+ INT ByteCount, -+ BOOL Write) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ -+ PSDREQUEST pReq = NULL; -+ -+ pReq = SDDeviceAllocRequest(pDevice); -+ -+ if (NULL == pReq) { -+ return SDIO_STATUS_NO_RESOURCES; -+ } -+ -+ while (ByteCount) { -+ _iSDLIB_SetupCMD52Request(FuncNo,Address,Write,*pData,pReq); -+ status = SDDEVICE_CALL_REQUEST_FUNC(pDevice,pReq); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ -+ status = ConvertCMD52ResponseToSDIOStatus(SD_R5_GET_RESP_FLAGS(pReq->Response)); -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Library: CMD52 resp error: 0x%X \n", -+ SD_R5_GET_RESP_FLAGS(pReq->Response))); -+ break; -+ } -+ if (!Write) { -+ /* store the byte */ -+ *pData = SD_R5_GET_READ_DATA(pReq->Response); -+ } -+ pData++; -+ Address++; -+ ByteCount--; -+ } -+ -+ SDDeviceFreeRequest(pDevice,pReq); -+ return status; -+} -+ -+ -+ -+/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Find a device's tuple. -+ -+ @function name: SDLIB_FindTuple -+ @prototype: SDIO_STATUS SDLIB_FindTuple(PSDDEVICE pDevice, -+ UINT8 Tuple, -+ UINT32 *pTupleScanAddress, -+ PUINT8 pBuffer, -+ UINT8 *pLength) -+ -+ @category: PD_Reference -+ @input: pDevice - the device that is the target of the command. -+ @input: Tuple - 8-bit ID of tuple to find -+ @input: pTupleScanAddress - On entry pTupleScanAddress is the adddress to start scanning -+ @input: pLength - length of pBuffer -+ -+ @output: pBuffer - storage for tuple -+ @output: pTupleScanAddress - address of the next tuple -+ @output: pLength - length of tuple read -+ -+ @return: status -+ -+ @notes: It is possible to have the same tuple ID multiple times with different lengths. This function -+ blocks and is fully synchronous. -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS _SDLIB_FindTuple(PSDDEVICE pDevice, -+ UINT8 Tuple, -+ UINT32 *pTupleScanAddress, -+ PUINT8 pBuffer, -+ UINT8 *pLength) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ UINT32 scanStart = *pTupleScanAddress; -+ UINT8 tupleCode; -+ UINT8 tupleLink; -+ -+ /* sanity check */ -+ if (scanStart < SDIO_CIS_AREA_BEGIN) { -+ return SDIO_STATUS_CIS_OUT_OF_RANGE; -+ } -+ -+ while (TRUE) { -+ /* check for end */ -+ if (scanStart > SDIO_CIS_AREA_END) { -+ status = SDIO_STATUS_TUPLE_NOT_FOUND; -+ break; -+ } -+ /* get the code */ -+ status = _Cmd52ReadByteCommon(pDevice, scanStart, &tupleCode); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ if (CISTPL_END == tupleCode) { -+ /* found the end */ -+ status = SDIO_STATUS_TUPLE_NOT_FOUND; -+ break; -+ } -+ /* bump past tuple code */ -+ scanStart++; -+ /* get the tuple link value */ -+ status = _Cmd52ReadByteCommon(pDevice, scanStart, &tupleLink); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ /* bump past tuple link*/ -+ scanStart++; -+ /* check tuple we just found */ -+ if (tupleCode == Tuple) { -+ DBG_PRINT(SDDBG_TRACE, ("SDIO Library: Tuple:0x%2.2X Found at Address:0x%X, TupleLink:0x%X \n", -+ Tuple, (scanStart - 2), tupleLink)); -+ if (tupleLink != CISTPL_LINK_END) { -+ /* return the next scan address to the caller */ -+ *pTupleScanAddress = scanStart + tupleLink; -+ } else { -+ /* the tuple link is an end marker */ -+ *pTupleScanAddress = 0xFFFFFFFF; -+ } -+ /* go get the tuple */ -+ status = _Cmd52ReadMultipleCommon(pDevice, scanStart,pBuffer,min(*pLength,tupleLink)); -+ if (SDIO_SUCCESS(status)) { -+ /* set the actual return length */ -+ *pLength = min(*pLength,tupleLink); -+ } -+ /* break out of loop */ -+ break; -+ } -+ /*increment past this entire tuple */ -+ scanStart += tupleLink; -+ } -+ -+ return status; -+} -+ -+/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Issue an SDIO configuration command. -+ -+ @function name: SDLIB_IssueConfig -+ @prototype: SDIO_STATUS _SDLIB_IssueConfig(PSDDEVICE pDevice, -+ SDCONFIG_COMMAND Command, -+ PVOID pData, -+ INT Length) -+ -+ @category: PD_Reference -+ @input: pDevice - the device that is the target of the command. -+ @input: Command - command to send, see example. -+ @input: pData - command's data -+ @input: Length length of pData -+ -+ @output: pData - updated on commands that return data. -+ -+ @return: SDIO Status -+ -+ @example: Command and data pairs: -+ Type Data -+ SDCONFIG_GET_WP SDCONFIG_WP_VALUE -+ SDCONFIG_SEND_INIT_CLOCKS none -+ SDCONFIG_SDIO_INT_CTRL SDCONFIG_SDIO_INT_CTRL_DATA -+ SDCONFIG_SDIO_REARM_INT none -+ SDCONFIG_BUS_MODE_CTRL SDCONFIG_BUS_MODE_DATA -+ SDCONFIG_POWER_CTRL SDCONFIG_POWER_CTRL_DATA -+ -+ @notes: -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS _SDLIB_IssueConfig(PSDDEVICE pDevice, -+ SDCONFIG_COMMAND Command, -+ PVOID pData, -+ INT Length) -+{ -+ SDCONFIG configHdr; -+ SET_SDCONFIG_CMD_INFO(&configHdr,Command,pData,Length); -+ return SDDEVICE_CALL_CONFIG_FUNC(pDevice,&configHdr); -+} -+ -+/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Set function block size -+ -+ @function name: SDLIB_SetFunctionBlockSize -+ @prototype: SDIO_STATUS SDLIB_SetFunctionBlockSize(PSDDEVICE pDevice, -+ UINT16 BlockSize) -+ -+ @category: PD_Reference -+ @input: pDevice - the device that is the target of the command. -+ @input: BlockSize - block size to set in function -+ -+ @output: none -+ -+ @return: SDIO Status -+ -+ @notes: Issues CMD52 to set the block size. This function is fully synchronous and may -+ block. -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS _SDLIB_SetFunctionBlockSize(PSDDEVICE pDevice, -+ UINT16 BlockSize) -+{ -+ UINT8 data[2]; -+ -+ /* endian safe */ -+ data[0] = (UINT8)BlockSize; -+ data[1] = (UINT8)(BlockSize >> 8); -+ /* write the function blk size control register */ -+ return _SDLIB_IssueCMD52(pDevice, -+ 0, /* function 0 register space */ -+ FBR_FUNC_BLK_SIZE_LOW_OFFSET(CalculateFBROffset( -+ SDDEVICE_GET_SDIO_FUNCNO(pDevice))), -+ data, -+ 2, -+ TRUE); -+} -+ -+/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Print a buffer to the debug output -+ -+ @function name: SDLIB_PrintBuffer -+ @prototype: void SDLIB_PrintBuffer(PUCHAR pBuffer, INT Length, PTEXT pDescription) -+ @category: Support_Reference -+ -+ @input: pBuffer - Hex buffer to be printed. -+ @input: Length - length of pBuffer. -+ @input: pDescription - String title to be printed above the dump. -+ -+ @output: none -+ -+ @return: none -+ -+ @notes: Prints the buffer by converting to ASCII and using REL_PRINT() with 16 -+ bytes per line. -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+void _SDLIB_PrintBuffer(PUCHAR pBuffer, INT Length, PTEXT pDescription) -+{ -+ TEXT line[49]; -+ TEXT address[5]; -+ TEXT ascii[17]; -+ TEXT temp[5]; -+ INT i; -+ UCHAR num; -+ USHORT offset = 0; -+ -+ REL_PRINT(0, -+ ("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n")); -+ if (pDescription != NULL) { -+ REL_PRINT(0, ("Description: %s \n\n",pDescription)); -+ } else { -+ REL_PRINT(0, ("Description: NONE \n\n")); -+ } -+ REL_PRINT(0, -+ ("Offset Data ASCII \n")); -+ REL_PRINT(0, -+ ("--------------------------------------------------------------------------\n")); -+ -+ while (Length) { -+ line[0] = (TEXT)0; -+ ascii[0] = (TEXT)0; -+ address[0] = (TEXT)0; -+ sprintf(address,"%4.4X",offset); -+ for (i = 0; i < 16; i++) { -+ if (Length != 0) { -+ num = *pBuffer; -+ sprintf(temp,"%2.2X ",num); -+ strcat(line,temp); -+ if ((num >= 0x20) && (num <= 0x7E)) { -+ sprintf(temp,"%c",*pBuffer); -+ } else { -+ sprintf(temp,"%c",0x2e); -+ } -+ strcat(ascii,temp); -+ pBuffer++; -+ Length--; -+ } else { -+ /* pad partial line with spaces */ -+ strcat(line," "); -+ strcat(ascii," "); -+ } -+ } -+ REL_PRINT(0,("%s %s %s\n", address, line, ascii)); -+ offset += 16; -+ } -+ REL_PRINT(0, -+ ("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n")); -+ -+} -+ -+/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get default operational current -+ -+ @function name: SDLIB_GetDefaultOpCurrent -+ @prototype: SDIO_STATUS SDLIB_GetDefaultOpCurrent(PSDDEVICE pDevice, SD_SLOT_CURRENT *pOpCurrent) -+ @category: PD_Reference -+ -+ @input: pDevice - the device that is the target of the command. -+ -+ @output: pOpCurrent - operational current in mA. -+ -+ @return: SDIO_STATUS -+ -+ @notes: This routine reads the function's CISTPL_FUNCE tuple for the default operational -+ current. For SDIO 1.0 devices this value is read from the 8-bit TPLFE_OP_MAX_PWR -+ field. For SDIO 1.1 devices, the HP MAX power field is used only if the device is -+ operating in HIPWR mode. Otherwise the 8-bit TPLFE_OP_MAX_PWR field is used. -+ Some systems may restrict high power/current mode and force cards to operate in a -+ legacy (< 200mA) mode. This function is fully synchronous and will block the caller. -+ -+ @example: Getting the default operational current for this function: -+ // get default operational current -+ status = SDLIB_GetDefaultOpCurrent(pDevice, &slotCurrent); -+ if (!SDIO_SUCCESS(status)) { -+ .. failed -+ } -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS _SDLIB_GetDefaultOpCurrent(PSDDEVICE pDevice, SD_SLOT_CURRENT *pOpCurrent) -+{ -+ UINT32 nextTpl; -+ UINT8 tplLength; -+ struct SDIO_FUNC_EXT_FUNCTION_TPL_1_1 funcTuple; -+ SDIO_STATUS status; -+ -+ /* get the FUNCE tuple */ -+ nextTpl = SDDEVICE_GET_SDIO_FUNC_CISPTR(pDevice); -+ tplLength = sizeof(funcTuple); -+ /* go get the function Extension tuple */ -+ status = _SDLIB_FindTuple(pDevice, -+ CISTPL_FUNCE, -+ &nextTpl, -+ (PUINT8)&funcTuple, -+ &tplLength); -+ -+ if (!SDIO_SUCCESS(status)) { -+ DBG_PRINT(SDDBG_ERROR, ("SDLIB_GetDefaultOpCurrent: Failed to get FuncE Tuple: %d \n", status)); -+ return status; -+ } -+ /* use the operational power (8-bit) value of current in mA as default*/ -+ *pOpCurrent = funcTuple.CommonInfo.OpMaxPwr; -+ if ((tplLength >= sizeof(funcTuple)) && (SDDEVICE_IS_SDIO_REV_GTEQ_1_10(pDevice))) { -+ /* we have a 1.1 tuple */ -+ /* check for HIPWR mode */ -+ if (SDDEVICE_GET_CARD_FLAGS(pDevice) & CARD_HIPWR) { -+ /* use the maximum operational power (16 bit ) from the tuple */ -+ *pOpCurrent = CT_LE16_TO_CPU_ENDIAN(funcTuple.HiPwrMaxPwr); -+ } -+ } -+ return SDIO_STATUS_SUCCESS; -+} -+ -+ -+static INLINE void FreeMessageBlock(PSDMESSAGE_QUEUE pQueue, PSDMESSAGE_BLOCK pMsg) { -+ SDListInsertHead(&pQueue->FreeMessageList, &pMsg->SDList); -+} -+static INLINE void QueueMessageBlock(PSDMESSAGE_QUEUE pQueue, PSDMESSAGE_BLOCK pMsg) { -+ SDListInsertTail(&pQueue->MessageList, &pMsg->SDList); -+} -+static INLINE void QueueMessageToHead(PSDMESSAGE_QUEUE pQueue, PSDMESSAGE_BLOCK pMsg) { -+ SDListInsertHead(&pQueue->MessageList, &pMsg->SDList); -+} -+ -+static INLINE PSDMESSAGE_BLOCK GetFreeMessageBlock(PSDMESSAGE_QUEUE pQueue) { -+ PSDLIST pItem = SDListRemoveItemFromHead(&pQueue->FreeMessageList); -+ if (pItem != NULL) { -+ return CONTAINING_STRUCT(pItem, SDMESSAGE_BLOCK , SDList); -+ } -+ return NULL; -+} -+static INLINE PSDMESSAGE_BLOCK GetQueuedMessage(PSDMESSAGE_QUEUE pQueue) { -+ PSDLIST pItem = SDListRemoveItemFromHead(&pQueue->MessageList); -+ if (pItem != NULL) { -+ return CONTAINING_STRUCT(pItem, SDMESSAGE_BLOCK , SDList); -+ } -+ return NULL; -+} -+ -+/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Create a message queue -+ -+ @function name: SDLIB_CreateMessageQueue -+ @prototype: PSDMESSAGE_QUEUE SDLIB_CreateMessageQueue(INT MaxMessages, INT MaxMessageLength) -+ @category: Support_Reference -+ -+ @input: MaxMessages - Maximum number of messages this queue supports -+ @input: MaxMessageLength - Maximum size of each message -+ -+ @return: Message queue object, NULL on failure -+ -+ @notes: This function creates a simple first-in-first-out message queue. The caller must determine -+ the maximum number of messages the queue supports and the size of each message. This -+ function will pre-allocate memory for each message. A producer of data posts a message -+ using SDLIB_PostMessage with a user defined data structure. A consumer of this data -+ can retrieve the message (in FIFO order) using SDLIB_GetMessage. A message queue does not -+ provide a signaling mechanism for notifying a consumer of data. Notifying a consumer is -+ user defined. -+ -+ @see also: SDLIB_DeleteMessageQueue, SDLIB_GetMessage, SDLIB_PostMessage. -+ -+ @example: Creating a message queue: -+ typedef struct _MyMessage { -+ UINT8 Code; -+ PVOID pDataBuffer; -+ } MyMessage; -+ // create message queue, 16 messages max. -+ pMsgQueue = SDLIB_CreateMessageQueue(16,sizeof(MyMessage)); -+ if (NULL == pMsgQueue) { -+ .. failed -+ } -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+PSDMESSAGE_QUEUE _CreateMessageQueue(INT MaxMessages, INT MaxMessageLength) -+{ -+ PSDMESSAGE_QUEUE pQueue = NULL; -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ INT ii; -+ PSDMESSAGE_BLOCK pMsg; -+ -+ do { -+ pQueue = (PSDMESSAGE_QUEUE)KernelAlloc(sizeof(SDMESSAGE_QUEUE)); -+ -+ if (NULL == pQueue) { -+ status = SDIO_STATUS_NO_RESOURCES; -+ break; -+ } -+ SDLIST_INIT(&pQueue->MessageList); -+ SDLIST_INIT(&pQueue->FreeMessageList); -+ pQueue->MaxMessageLength = MaxMessageLength; -+ status = CriticalSectionInit(&pQueue->MessageCritSection); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ /* allocate message blocks */ -+ for (ii = 0; ii < MaxMessages; ii++) { -+ pMsg = (PSDMESSAGE_BLOCK)KernelAlloc(sizeof(SDMESSAGE_BLOCK) + MaxMessageLength -1); -+ if (NULL == pMsg) { -+ break; -+ } -+ FreeMessageBlock(pQueue, pMsg); -+ } -+ -+ if (0 == ii) { -+ status = SDIO_STATUS_NO_RESOURCES; -+ break; -+ } -+ -+ } while (FALSE); -+ -+ if (!SDIO_SUCCESS(status)) { -+ if (pQueue != NULL) { -+ _DeleteMessageQueue(pQueue); -+ pQueue = NULL; -+ } -+ } -+ return pQueue; -+} -+ -+/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Delete a message queue -+ -+ @function name: SDLIB_DeleteMessageQueue -+ @prototype: void SDLIB_DeleteMessageQueue(PSDMESSAGE_QUEUE pQueue) -+ @category: Support_Reference -+ -+ @input: pQueue - message queue to delete -+ -+ @notes: This function flushes the message queue and frees all memory allocated for -+ messages. -+ -+ @see also: SDLIB_CreateMessageQueue -+ -+ @example: Deleting a message queue: -+ if (pMsgQueue != NULL) { -+ SDLIB_DeleteMessageQueue(pMsgQueue); -+ } -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+void _DeleteMessageQueue(PSDMESSAGE_QUEUE pQueue) -+{ -+ PSDMESSAGE_BLOCK pMsg; -+ SDIO_STATUS status; -+ CT_DECLARE_IRQ_SYNC_CONTEXT(); -+ -+ status = CriticalSectionAcquireSyncIrq(&pQueue->MessageCritSection); -+ -+ /* cleanup free list */ -+ while (1) { -+ pMsg = GetFreeMessageBlock(pQueue); -+ if (pMsg != NULL) { -+ KernelFree(pMsg); -+ } else { -+ break; -+ } -+ } -+ /* cleanup any in the queue */ -+ while (1) { -+ pMsg = GetQueuedMessage(pQueue); -+ if (pMsg != NULL) { -+ KernelFree(pMsg); -+ } else { -+ break; -+ } -+ } -+ -+ status = CriticalSectionReleaseSyncIrq(&pQueue->MessageCritSection); -+ CriticalSectionDelete(&pQueue->MessageCritSection); -+ KernelFree(pQueue); -+ -+} -+ -+/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Post a message queue -+ -+ @function name: SDLIB_PostMessage -+ @prototype: SDIO_STATUS SDLIB_PostMessage(PSDMESSAGE_QUEUE pQueue, PVOID pMessage, INT MessageLength) -+ @category: Support_Reference -+ -+ @input: pQueue - message queue to post to -+ @input: pMessage - message to post -+ @input: MessageLength - length of message (for validation) -+ -+ @return: SDIO_STATUS -+ -+ @notes: The message queue uses an internal list of user defined message structures. When -+ posting a message the message is copied into an allocated structure and queued. The memory -+ pointed to by pMessage does not need to be allocated and can reside on the stack. -+ The length of the message to post can be smaller that the maximum message size. This allows -+ for variable length messages up to the maximum message size. This -+ function returns SDIO_STATUS_NO_RESOURCES, if the message queue is full. This -+ function returns SDIO_STATUS_BUFFER_TOO_SMALL, if the message size exceeds the maximum -+ size of a message. Posting and getting messsages from a message queue is safe in any -+ driver context. -+ -+ @see also: SDLIB_CreateMessageQueue , SDLIB_GetMessage -+ -+ @example: Posting a message -+ MyMessage message; -+ // set up message -+ message.code = MESSAGE_DATA_READY; -+ message.pData = pInstance->pDataBuffers[currentIndex]; -+ // post message -+ status = SDLIB_PostMessage(pInstance->pReadQueue,&message,sizeof(message)); -+ if (!SDIO_SUCCESS(status)) { -+ // failed -+ } -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS _PostMessage(PSDMESSAGE_QUEUE pQueue, PVOID pMessage, INT MessageLength) -+{ -+ SDIO_STATUS status2; -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ PSDMESSAGE_BLOCK pMsg; -+ CT_DECLARE_IRQ_SYNC_CONTEXT(); -+ -+ if (MessageLength > pQueue->MaxMessageLength) { -+ return SDIO_STATUS_BUFFER_TOO_SMALL; -+ } -+ -+ status = CriticalSectionAcquireSyncIrq(&pQueue->MessageCritSection); -+ if (!SDIO_SUCCESS(status)) { -+ return status; -+ } -+ -+ do { -+ /* get a message block */ -+ pMsg = GetFreeMessageBlock(pQueue); -+ if (NULL == pMsg) { -+ status = SDIO_STATUS_NO_RESOURCES; -+ break; -+ } -+ /* copy the message */ -+ memcpy(pMsg->MessageStart,pMessage,MessageLength); -+ /* set the length of the message */ -+ pMsg->MessageLength = MessageLength; -+ /* queue the message to the list */ -+ QueueMessageBlock(pQueue,pMsg); -+ } while (FALSE); -+ -+ status2 = CriticalSectionReleaseSyncIrq(&pQueue->MessageCritSection); -+ return status; -+} -+ -+/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get a message from a message queue -+ -+ @function name: SDLIB_GetMessage -+ @prototype: SDIO_STATUS SDLIB_GetMessage(PSDMESSAGE_QUEUE pQueue, PVOID pData, INT *pBufferLength) -+ @category: Support_Reference -+ -+ @input: pQueue - message queue to retreive a message from -+ @input: pBufferLength - on entry, the length of the data buffer -+ @output: pData - buffer to hold the message -+ @output: pBufferLength - on return, contains the number of bytes copied -+ -+ @return: SDIO_STATUS -+ -+ @notes: The message queue uses an internal list of user defined message structures. The message is -+ dequeued (FIFO order) and copied to the callers buffer. The internal allocation for the message -+ is returned back to the message queue. This function returns SDIO_STATUS_NO_MORE_MESSAGES -+ if the message queue is empty. If the length of the buffer is smaller than the length of -+ the message at the head of the queue,this function returns SDIO_STATUS_BUFFER_TOO_SMALL and -+ returns the required length in pBufferLength. -+ -+ @see also: SDLIB_CreateMessageQueue , SDLIB_PostMessage -+ -+ @example: Getting a message -+ MyMessage message; -+ INT length; -+ // set length -+ length = sizeof(message); -+ // post message -+ status = SDLIB_GetMessage(pInstance->pReadQueue,&message,&length); -+ if (!SDIO_SUCCESS(status)) { -+ // failed -+ } -+ -+ @example: Checking queue for a message and getting the size of the message -+ INT length; -+ // use zero length to get the size of the message -+ length = 0; -+ status = SDLIB_GetMessage(pInstance->pReadQueue,NULL,&length); -+ if (status == SDIO_STATUS_NO_MORE_MESSAGES) { -+ // no messages in queue -+ } else if (status == SDIO_STATUS_BUFFER_TOO_SMALL) { -+ // message exists in queue and length of message is returned -+ messageSizeInQueue = length; -+ } else { -+ // some other failure -+ } -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+SDIO_STATUS _GetMessage(PSDMESSAGE_QUEUE pQueue, PVOID pData, INT *pBufferLength) -+{ -+ SDIO_STATUS status2; -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ PSDMESSAGE_BLOCK pMsg; -+ CT_DECLARE_IRQ_SYNC_CONTEXT(); -+ -+ status = CriticalSectionAcquireSyncIrq(&pQueue->MessageCritSection); -+ if (!SDIO_SUCCESS(status)) { -+ return status; -+ } -+ -+ do { -+ pMsg = GetQueuedMessage(pQueue); -+ if (NULL == pMsg) { -+ status = SDIO_STATUS_NO_MORE_MESSAGES; -+ break; -+ } -+ if (*pBufferLength < pMsg->MessageLength) { -+ /* caller buffer is too small */ -+ *pBufferLength = pMsg->MessageLength; -+ /* stick it back to the front */ -+ QueueMessageToHead(pQueue, pMsg); -+ status = SDIO_STATUS_BUFFER_TOO_SMALL; -+ break; -+ } -+ /* copy the message to the callers buffer */ -+ memcpy(pData,pMsg->MessageStart,pMsg->MessageLength); -+ /* return actual length */ -+ *pBufferLength = pMsg->MessageLength; -+ /* return this message block back to the free list */ -+ FreeMessageBlock(pQueue, pMsg); -+ -+ } while (FALSE); -+ -+ status2 = CriticalSectionReleaseSyncIrq(&pQueue->MessageCritSection); -+ -+ return status; -+} -+ -+/* the following documents the OS helper APIs */ -+ -+/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Create an OS-specific helper task/thread -+ -+ @function name: SDLIB_OSCreateHelper -+ @prototype: SDIO_STATUS SDLIB_OSCreateHelper(POSKERNEL_HELPER pHelper, -+ PHELPER_FUNCTION pFunction, -+ PVOID pContext) -+ @category: Support_Reference -+ -+ @input: pHelper - caller allocated helper object -+ @input: pFunction - helper function -+ @input: pContext - helper context -+ -+ @return: SDIO_STATUS -+ -+ @notes: This function creates a helper task/thread that runs in a new execution context. The newly -+ created task/thread invokes the helper function. The thread/task exits when the helper -+ function returns. The helper function has the prototype of: -+ THREAD_RETURN HelperFunction(POSKERNEL_HELPER pHelper) -+ The helper function usually implements a while loop and suspends execution using -+ SD_WAIT_FOR_WAKEUP(). On exit the helper function can return an OS-specific THREAD_RETURN -+ code (usually zero). The helper function executes in a fully schedule-able context and -+ can block on semaphores and sleep. -+ -+ @see also: SDLIB_OSDeleteHelper , SD_WAIT_FOR_WAKEUP -+ -+ @example: A thread helper function: -+ THREAD_RETURN HelperFunction(POSKERNEL_HELPER pHelper) -+ { -+ SDIO_STATUS status; -+ PMYCONTEXT pContext = (PMYCONTEXT)SD_GET_OS_HELPER_CONTEXT(pHelper); -+ // wait for wake up -+ while(1) { -+ status = SD_WAIT_FOR_WAKEUP(pHelper); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ if (SD_IS_HELPER_SHUTTING_DOWN(pHelper)) { -+ //... shutting down -+ break; -+ } -+ // handle wakeup... -+ } -+ return 0; -+ } -+ -+ @example: Creating a helper: -+ status = SDLIB_OSCreateHelper(&pInstance->OSHelper,HelperFunction,pInstance); -+ if (!SDIO_SUCCESS(status)) { -+ // failed -+ } -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+ -+/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Delete an OS helper task/thread -+ -+ @function name: SDLIB_OSDeleteHelper -+ @prototype: void SDLIB_OSDeleteHelper(POSKERNEL_HELPER pHelper) -+ @category: Support_Reference -+ -+ @input: pHelper - caller allocated helper object -+ -+ @notes: This function wakes the helper and waits(blocks) until the helper exits. The caller can -+ only pass an OS helper structure that was initialized sucessfully by -+ SDLIB_OSCreateHelper. The caller must be in a schedulable context. -+ -+ @see also: SDLIB_OSCreateHelper -+ -+ @example: Deleting a helper: -+ if (pInstance->HelperCreated) { -+ // clean up the helper if we successfully created it -+ SDLIB_OSDeleteHelper(&pInstance->OSHelper); -+ } -+ -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+ -+ -diff --git a/drivers/sdio/stack/lib/sdio_lib_os.c b/drivers/sdio/stack/lib/sdio_lib_os.c -new file mode 100644 -index 0000000..55363d0 ---- /dev/null -+++ b/drivers/sdio/stack/lib/sdio_lib_os.c -@@ -0,0 +1,251 @@ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+@file: sdio_function_os.c -+ -+@abstract: Linux implementation module for SDIO library -+ -+#notes: includes module load and unload functions -+ -+@notice: Copyright (c), 2004 Atheros Communications, Inc. -+ -+ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * Software distributed under the License is distributed on an "AS -+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -+ * implied. See the License for the specific language governing -+ * rights and limitations under the License. -+ * -+ * Portions of this code were developed with information supplied from the -+ * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply: -+ * -+ * The following conditions apply to the release of the SD simplified specification (�Simplified -+ * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete -+ * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided -+ * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified -+ * Specification may require a license from the SD Card Association or other third parties. -+ * Disclaimers: -+ * The information contained in the Simplified Specification is presented only as a standard -+ * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any -+ * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for -+ * any damages, any infringements of patents or other right of the SD Card Association or any third -+ * parties, which may result from its use. No license is granted by implication, estoppel or otherwise -+ * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall -+ * be construed as an obligation by the SD Card Association to disclose or distribute any technical -+ * information, know-how or other confidential information to any third party. -+ * -+ * -+ * The initial developers of the original code are Seung Yi and Paul Lever -+ * -+ * sdio@atheros.com -+ * -+ * -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+/* debug level for this module*/ -+#define DBG_DECLARE 4; -+#include <linux/sdio/ctsystem.h> -+ -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/kthread.h> -+ -+#include <linux/sdio/sdio_busdriver.h> -+#include <linux/sdio/sdio_lib.h> -+#include "_sdio_lib.h" -+ -+#define DESCRIPTION "SDIO Kernel Library" -+#define AUTHOR "Atheros Communications, Inc." -+ -+/* proxies */ -+SDIO_STATUS SDLIB_IssueCMD52(PSDDEVICE pDevice, -+ UINT8 FuncNo, -+ UINT32 Address, -+ PUINT8 pData, -+ INT ByteCount, -+ BOOL Write) -+{ -+ return _SDLIB_IssueCMD52(pDevice,FuncNo,Address,pData,ByteCount,Write); -+} -+ -+SDIO_STATUS SDLIB_FindTuple(PSDDEVICE pDevice, -+ UINT8 Tuple, -+ UINT32 *pTupleScanAddress, -+ PUINT8 pBuffer, -+ UINT8 *pLength) -+{ -+ return _SDLIB_FindTuple(pDevice,Tuple,pTupleScanAddress,pBuffer,pLength); -+} -+ -+SDIO_STATUS SDLIB_IssueConfig(PSDDEVICE pDevice, -+ SDCONFIG_COMMAND Command, -+ PVOID pData, -+ INT Length) -+{ -+ return _SDLIB_IssueConfig(pDevice,Command,pData,Length); -+} -+ -+void SDLIB_PrintBuffer(PUCHAR pBuffer,INT Length,PTEXT pDescription) -+{ -+ _SDLIB_PrintBuffer(pBuffer,Length,pDescription); -+} -+ -+SDIO_STATUS SDLIB_SetFunctionBlockSize(PSDDEVICE pDevice, -+ UINT16 BlockSize) -+{ -+ return _SDLIB_SetFunctionBlockSize(pDevice,BlockSize); -+} -+ -+void SDLIB_SetupCMD52Request(UINT8 FuncNo, -+ UINT32 Address, -+ BOOL Write, -+ UINT8 WriteData, -+ PSDREQUEST pRequest) -+{ -+ _SDLIB_SetupCMD52Request(FuncNo,Address,Write,WriteData,pRequest); -+} -+ -+SDIO_STATUS SDLIB_GetDefaultOpCurrent(PSDDEVICE pDevice, SD_SLOT_CURRENT *pOpCurrent) -+{ -+ return _SDLIB_GetDefaultOpCurrent(pDevice,pOpCurrent); -+} -+ -+/* helper function launcher */ -+INT HelperLaunch(PVOID pContext) -+{ -+ INT exit; -+ /* call function */ -+ exit = ((POSKERNEL_HELPER)pContext)->pHelperFunc((POSKERNEL_HELPER)pContext); -+ complete_and_exit(&((POSKERNEL_HELPER)pContext)->Completion, exit); -+ return exit; -+} -+ -+/* -+ * OSCreateHelper - create a worker kernel thread -+*/ -+SDIO_STATUS SDLIB_OSCreateHelper(POSKERNEL_HELPER pHelper, -+ PHELPER_FUNCTION pFunction, -+ PVOID pContext) -+{ -+ SDIO_STATUS status = SDIO_STATUS_SUCCESS; -+ -+ memset(pHelper,0,sizeof(OSKERNEL_HELPER)); -+ -+ do { -+ pHelper->pContext = pContext; -+ pHelper->pHelperFunc = pFunction; -+ status = SignalInitialize(&pHelper->WakeSignal); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ init_completion(&pHelper->Completion); -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ pHelper->pTask = kthread_create(HelperLaunch, -+ (PVOID)pHelper, -+ "SDIO Helper"); -+ if (NULL == pHelper->pTask) { -+ status = SDIO_STATUS_NO_RESOURCES; -+ break; -+ } -+ wake_up_process(pHelper->pTask); -+#else -+ /* 2.4 */ -+ pHelper->pTask = kernel_thread(HelperLaunch, -+ (PVOID)pHelper, -+ (CLONE_FS | CLONE_FILES | SIGCHLD)); -+ if (pHelper->pTask < 0) { -+ DBG_PRINT(SDDBG_TRACE, -+ ("SDIO BusDriver - OSCreateHelper, failed to create thread\n")); -+ } -+#endif -+ -+ } while (FALSE); -+ -+ if (!SDIO_SUCCESS(status)) { -+ SDLIB_OSDeleteHelper(pHelper); -+ } -+ return status; -+} -+ -+/* -+ * OSDeleteHelper - delete thread created with OSCreateHelper -+*/ -+void SDLIB_OSDeleteHelper(POSKERNEL_HELPER pHelper) -+{ -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ if (pHelper->pTask != NULL) { -+#else -+ /* 2.4 */ -+ if (pHelper->pTask >= 0) { -+#endif -+ pHelper->ShutDown = TRUE; -+ SignalSet(&pHelper->WakeSignal); -+ /* wait for thread to exit */ -+ wait_for_completion(&pHelper->Completion); -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ pHelper->pTask = NULL; -+#else -+ /* 2.4 */ -+ pHelper->pTask = 0; -+#endif -+ } -+ -+ SignalDelete(&pHelper->WakeSignal); -+} -+ -+/* -+ * module init -+*/ -+static int __init sdio_lib_init(void) { -+ REL_PRINT(SDDBG_TRACE, ("SDIO Library load\n")); -+ return 0; -+} -+ -+/* -+ * module cleanup -+*/ -+static void __exit sdio_lib_cleanup(void) { -+ REL_PRINT(SDDBG_TRACE, ("SDIO Library unload\n")); -+} -+ -+PSDMESSAGE_QUEUE SDLIB_CreateMessageQueue(INT MaxMessages, INT MaxMessageLength) -+{ -+ return _CreateMessageQueue(MaxMessages,MaxMessageLength); -+ -+} -+void SDLIB_DeleteMessageQueue(PSDMESSAGE_QUEUE pQueue) -+{ -+ _DeleteMessageQueue(pQueue); -+} -+ -+SDIO_STATUS SDLIB_PostMessage(PSDMESSAGE_QUEUE pQueue, PVOID pMessage, INT MessageLength) -+{ -+ return _PostMessage(pQueue,pMessage,MessageLength); -+} -+ -+SDIO_STATUS SDLIB_GetMessage(PSDMESSAGE_QUEUE pQueue, PVOID pData, INT *pBufferLength) -+{ -+ return _GetMessage(pQueue,pData,pBufferLength); -+} -+ -+MODULE_LICENSE("GPL and additional rights"); -+MODULE_DESCRIPTION(DESCRIPTION); -+MODULE_AUTHOR(AUTHOR); -+module_init(sdio_lib_init); -+module_exit(sdio_lib_cleanup); -+EXPORT_SYMBOL(SDLIB_IssueCMD52); -+EXPORT_SYMBOL(SDLIB_FindTuple); -+EXPORT_SYMBOL(SDLIB_IssueConfig); -+EXPORT_SYMBOL(SDLIB_PrintBuffer); -+EXPORT_SYMBOL(SDLIB_SetFunctionBlockSize); -+EXPORT_SYMBOL(SDLIB_SetupCMD52Request); -+EXPORT_SYMBOL(SDLIB_GetDefaultOpCurrent); -+EXPORT_SYMBOL(SDLIB_OSCreateHelper); -+EXPORT_SYMBOL(SDLIB_OSDeleteHelper); -+EXPORT_SYMBOL(SDLIB_CreateMessageQueue); -+EXPORT_SYMBOL(SDLIB_DeleteMessageQueue); -+EXPORT_SYMBOL(SDLIB_PostMessage); -+EXPORT_SYMBOL(SDLIB_GetMessage); -diff --git a/drivers/sdio/stack/platform/Makefile b/drivers/sdio/stack/platform/Makefile -new file mode 100644 -index 0000000..14b3612 ---- /dev/null -+++ b/drivers/sdio/stack/platform/Makefile -@@ -0,0 +1,2 @@ -+obj-$(CONFIG_SDIO) += sdio_platform.o -+sdio_platform-objs := sdioplatformdriver.o -\ No newline at end of file -diff --git a/drivers/sdio/stack/platform/sdioplatformdriver.c b/drivers/sdio/stack/platform/sdioplatformdriver.c -new file mode 100644 -index 0000000..d5520fc ---- /dev/null -+++ b/drivers/sdio/stack/platform/sdioplatformdriver.c -@@ -0,0 +1,300 @@ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+@file: sdioplatformdriver.c -+ -+@abstract: Linux implementation module for SDIO pltaform driver -+ -+#notes: -+ -+@notice: Copyright (c), 2006 Atheros Communications, Inc. -+ -+@license: This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License version 2 as -+ published by the Free Software Foundation. -+ -+ -+ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * Software distributed under the License is distributed on an "AS -+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -+ * implied. See the License for the specific language governing -+ * rights and limitations under the License. -+ * -+ * Portions of this code were developed with information supplied from the -+ * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply: -+ * -+ * The following conditions apply to the release of the SD simplified specification (�Simplified -+ * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete -+ * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided -+ * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified -+ * Specification may require a license from the SD Card Association or other third parties. -+ * Disclaimers: -+ * The information contained in the Simplified Specification is presented only as a standard -+ * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any -+ * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for -+ * any damages, any infringements of patents or other right of the SD Card Association or any third -+ * parties, which may result from its use. No license is granted by implication, estoppel or otherwise -+ * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall -+ * be construed as an obligation by the SD Card Association to disclose or distribute any technical -+ * information, know-how or other confidential information to any third party. -+ * -+ * -+ * The initial developers of the original code are Seung Yi and Paul Lever -+ * -+ * sdio@atheros.com -+ * -+ * -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+ -+#define DESCRIPTION "SDIO Platform Driver" -+#define AUTHOR "Atheros Communications, Inc." -+ -+//??for .h -+ -+struct sdioplatform_peripheral { -+ struct list_head node; -+ struct sdioplatform_controller *controller; -+ struct device dev; -+}; -+struct sdioplatform_driver { -+ struct device_driver drv; -+ int (*probe)(struct sdioplatform_peripheral *); -+ void (*remove)(struct sdioplatform_peripheral *); -+ int (*suspend)(struct sdioplatform_peripheral *, pm_message_t); -+ int (*resume)(struct sdioplatform_peripheral *); -+}; -+ -+ -+struct sdioplatform_controller { -+ struct device *dev; -+}; -+struct sdioplatform_controller_driver { -+ struct device_driver drv; -+ int (*probe)(struct sdioplatform_controller *); -+ void (*remove)(struct sdioplatform_controller *); -+ int (*suspend)(struct sdioplatform_controller *, pm_message_t); -+ int (*resume)(struct sdioplatform_controller *); -+}; -+ -+ -+ -+#define device_to_sdioplatform_peripheral(d) container_of(d, struct sdioplatform_peripheral, dev) -+#define driver_to_sdioplatform_driver(d) container_of(d, struct sdioplatform_driver, drv) -+ -+#define device_to_sdioplatform_controller(d) container_of(d, struct sdioplatform_controller, dev) -+#define driver_to_sdioplatform_controller_driver(d) container_of(d, struct sdioplatform_controller_driver, drv) -+ -+#define SDIOPLATFORM_ATTR(name, fmt, args...) \ -+static ssize_t sdio_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \ -+{ \ -+ struct sdioplatform_peripheral *peripheral = device_to_sdioplatform_peripheral(dev); \ -+ return sprintf(buf, fmt, args); \ -+} -+ -+SDIOPLATFORM_ATTR(bus_id, "%s\n", bus_id); -+#define SDIOPLATFORM_ATTR_RO(name) __ATTR(name, S_IRUGO, sdioplatform_##name##_show, NULL) -+ -+static struct device_attribute sdioplatform_dev_attrs[] = { -+ SDIOPLATFORM_ATTR_RO(bus_id), -+ __ATTR_NULL -+}; -+ -+static struct bus_type sdioplatform_bus_type = { -+ .name = "sdioplatform", -+ .dev_attrs = sdioplatform_dev_attrs, -+ .match = sdioplatform_bus_match, -+ .hotplug = NULL, -+ .suspend = sdioplatform_bus_suspend, -+ .resume = sdioplatform_bus_resume, -+}; -+ -+ -+/* controller functions */ -+static int sdioplatform_controllerdrv_probe(struct device *dev) -+{ -+ struct sdioplatform_controller_driver *drv = driver_to_sdioplatform_controller_driver(dev->driver); -+ struct sdioplatform_controller *controller = device_to_sdioplatform_controller(dev); -+ -+ return drv->probe(controller); -+} -+ -+static int sdioplatform_controllerdrv_remove(struct device *dev) -+{ -+ struct sdioplatform_controller_driver *drv = driver_to_sdioplatform_controller_driver(dev->driver); -+ struct sdioplatform_controller *controller = device_to_sdioplatform_controller(dev); -+ -+ return drv->remove(controller); -+} -+ -+/* -+ * sdioplatform_register_controller_driver - register a controller driver -+ */ -+int sdioplatform_register_controller_driver(struct sdioplatform_controller_driver *drv) -+{ -+ drv->drv.bus = &sdioplatform_bus_type; -+ drv->drv.probe = sdioplatform_controllerdrv_probe; -+ drv->drv.remove = sdioplatform_controllerdrv_remove; -+ return driver_register(&drv->drv); -+} -+ -+/* -+ * sdioplatform_unregister_controller_driver - unregister a controller driver -+ */ -+void sdioplatform_unregister_controller_driver(struct sdioplatform_driver *drv) -+{ -+ driver_unregister(&drv->drv); -+} -+ -+/* -+ * sdioplatform_add_controller - register a controller device -+ */ -+int sdioplatform_add_controller(char *name, struct sdioplatform_controller *dev) -+{ -+ if (!dev) { -+ return -EINVAL; -+ } -+ strncpy(dev->dev.bus_id, BUS_ID_SIZE, name); -+ return device_register(&dev->dev); -+} -+ -+/* -+ * sdioplatform_remove_controller - unregister a controller device -+ */ -+int sdioplatform_remove_controller(char *name, struct sdioplatform_controller *dev) -+{ -+ if (!dev) { -+ return -EINVAL; -+ } -+ return device_unregister(&dev->dev); -+} -+ -+/* peripheral functions */ -+static int sdioplatform_drv_probe(struct device *dev) -+{ -+ struct sdioplatform_driver *drv = driver_to_sdioplatform_driver(dev->driver); -+ struct sdioplatform_peripheral *peripheral = device_to_sdioplatform_peripheral(dev); -+ -+ return drv->probe(peripheral); -+} -+ -+static int sdioplatform_controllerdrv_remove(struct device *dev) -+{ -+ struct sdioplatform_controller_driver *drv = driver_to_sdioplatform_controller_driver(dev->driver); -+ struct sdioplatform_controller *controller = device_to_sdioplatform_controller(dev); -+ -+ return drv->remove(controller); -+} -+ -+/* -+ * sdioplatform_register_driver - register a driver -+ */ -+int sdioplatform_register_driver(struct sdioplatform_driver *drv) -+{ -+ drv->drv.bus = &sdioplatform_bus_type; -+ drv->drv.probe = sdioplatform_drv_probe; -+ drv->drv.remove = sdioplatform_drv_remove; -+ return driver_register(&drv->drv); -+} -+ -+/* -+ * sdioplatform_unregister_driver - unregister a driver -+ */ -+void sdioplatform_unregister_driver(struct sdioplatform_driver *drv) -+{ -+ driver_unregister(&drv->drv); -+} -+ -+/* -+ * sdioplatform_add_peripheral - register a peripheral device -+ */ -+int sdioplatform_add_peripheral(char *name, struct sdioplatform_peripheral *dev) -+{ -+ if (!dev) { -+ return -EINVAL; -+ } -+ strncpy(dev->dev.bus_id, BUS_ID_SIZE, name); -+ return device_register(&dev->dev); -+} -+ -+/* -+ * sdioplatform_remove_peripheral - unregister a peripheral device -+ */ -+int sdioplatform_remove_peripheral(char *name, struct sdioplatform_peripheral *dev) -+{ -+ if (!dev) { -+ return -EINVAL; -+ } -+ return device_unregister(&dev->dev); -+} -+ -+ -+ -+ -+ -+static int sdioplatform_bus_match(struct device *dev, struct device_driver *drv) -+{ -+ /* probes handle the matching */ -+ return 1; -+} -+ -+static int sdioplatform_bus_suspend(struct device *dev, pm_message_t state) -+{ -+ struct sdioplatform_driver *drv = driver_to_sdioplatform_driver(dev->driver); -+ struct sdioplatform_peripheral *peripheral = device_to_sdioplatform_peripheral(dev); -+ int ret = 0; -+ -+ if (peripheral->driver && drv->suspend) { -+ ret = drv->suspend(peripheral, state); -+ } -+ return ret; -+} -+ -+static int sdioplatform_bus_resume(struct device *dev) -+{ -+ struct sdioplatform_driver *drv = driver_to_sdioplatform_driver(dev->driver); -+ struct sdioplatform_peripheral *peripheral = device_to_sdioplatform_peripheral(dev); -+ int ret = 0; -+ -+ if (peripheral->driver && drv->resume) { -+ ret = drv->resume(card); -+ } -+ return ret; -+} -+ -+/* -+ * module init -+*/ -+static int __init sdio_platformdriver_init(void) { -+ int ret = bus_register(&sdioplatform_bus_type); -+ return ret; -+} -+ -+/* -+ * module cleanup -+*/ -+static void __exit sdio_platformdriver_cleanup(void) { -+ REL_PRINT(SDDBG_TRACE, ("SDIO unloaded\n")); -+ _SDIO_BusDriverCleanup(); -+} -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION(DESCRIPTION); -+MODULE_AUTHOR(AUTHOR); -+ -+module_init(sdio_platformdriver_init); -+module_exit(sdio_platformdriver_cleanup); -+EXPORT_SYMBOL(sdioplatform_register_controller_driver); -+EXPORT_SYMBOL(sdioplatform_unregister_controller_driver); -+EXPORT_SYMBOL(sdioplatform_add_controller); -+EXPORT_SYMBOL(sdioplatform_remove_controller); -+EXPORT_SYMBOL(sdioplatform_register_driver); -+EXPORT_SYMBOL(sdioplatform_unregister_driver); -+EXPORT_SYMBOL(sdioplatform_add_peripheral); -+EXPORT_SYMBOL(sdioplatform_remove_peripheral); -+ -+ -+ -diff --git a/include/linux/sdio/_sdio_defs.h b/include/linux/sdio/_sdio_defs.h -new file mode 100644 -index 0000000..a3f5542 ---- /dev/null -+++ b/include/linux/sdio/_sdio_defs.h -@@ -0,0 +1,638 @@ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+@file: _sdio_defs.h -+ -+@abstract: SD/SDIO definitions -+ -+@notice: Copyright (c), 2004-2006 Atheros Communications, Inc. -+ -+ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * Software distributed under the License is distributed on an "AS -+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -+ * implied. See the License for the specific language governing -+ * rights and limitations under the License. -+ * -+ * Portions of this code were developed with information supplied from the -+ * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply: -+ * -+ * The following conditions apply to the release of the SD simplified specification (�Simplified -+ * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete -+ * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided -+ * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified -+ * Specification may require a license from the SD Card Association or other third parties. -+ * Disclaimers: -+ * The information contained in the Simplified Specification is presented only as a standard -+ * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any -+ * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for -+ * any damages, any infringements of patents or other right of the SD Card Association or any third -+ * parties, which may result from its use. No license is granted by implication, estoppel or otherwise -+ * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall -+ * be construed as an obligation by the SD Card Association to disclose or distribute any technical -+ * information, know-how or other confidential information to any third party. -+ * -+ * -+ * The initial developers of the original code are Seung Yi and Paul Lever -+ * -+ * sdio@atheros.com -+ * -+ * -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#ifndef ___SDIO_DEFS_H___ -+#define ___SDIO_DEFS_H___ -+ -+#define SD_INIT_BUS_CLOCK 100000 /* initialization clock in hz */ -+#define SPI_INIT_BUS_CLOCK 100000 /* initialization clock in hz */ -+#define SD_MAX_BUS_CLOCK 25000000 /* max clock speed in hz */ -+#define SD_HS_MAX_BUS_CLOCK 50000000 /* SD high speed max clock speed in hz */ -+#define SDIO_LOW_SPEED_MAX_BUS_CLOCK 400000 /* max low speed clock in hz */ -+#define SDMMC_MIN_INIT_CLOCKS 80 /* minimun number of initialization clocks */ -+#define SDIO_EMPC_CURRENT_THRESHOLD 300 /* SDIO 1.10 , EMPC (mA) threshold, we add some overhead */ -+ -+/* commands */ -+#define CMD0 0 -+#define CMD1 1 -+#define CMD2 2 -+#define CMD3 3 -+#define CMD4 4 -+#define CMD5 5 -+#define CMD6 6 -+#define CMD7 7 -+#define CMD9 9 -+#define CMD10 10 -+#define CMD12 12 -+#define CMD13 13 -+#define CMD15 15 -+#define CMD16 16 -+#define CMD17 17 -+#define CMD18 18 -+#define CMD24 24 -+#define CMD25 25 -+#define CMD27 27 -+#define CMD28 28 -+#define CMD29 29 -+#define CMD30 30 -+#define CMD32 32 -+#define CMD33 33 -+#define CMD38 38 -+#define CMD42 42 -+#define CMD52 52 -+#define CMD53 53 -+#define CMD55 55 -+#define CMD56 56 -+#define CMD58 58 -+#define CMD59 59 -+#define ACMD6 6 -+#define ACMD13 13 -+#define ACMD22 22 -+#define ACMD23 23 -+#define ACMD41 41 -+#define ACMD42 42 -+#define ACMD51 51 -+ -+#define SD_ACMD6_BUS_WIDTH_1_BIT 0x00 -+#define SD_ACMD6_BUS_WIDTH_4_BIT 0x02 -+ -+#define SD_CMD59_CRC_OFF 0x00000000 -+#define SD_CMD59_CRC_ON 0x00000001 -+ -+/* SD/SPI max response size */ -+#define SD_MAX_CMD_RESPONSE_BYTES SD_R2_RESPONSE_BYTES -+ -+#define SD_R1_RESPONSE_BYTES 6 -+#define SD_R1B_RESPONSE_BYTES SD_R1_RESPONSE_BYTES -+#define SD_R1_GET_CMD(pR) ((pR)[5] & 0xC0)) -+#define SD_R1_SET_CMD(pR,cmd) (pR)[5] = (cmd) & 0xC0 -+#define SD_R1_GET_CARD_STATUS(pR) (((UINT32)((pR)[1])) | \ -+ (((UINT32)((pR)[2])) << 8) | \ -+ (((UINT32)((pR)[3])) << 16) | \ -+ (((UINT32)((pR)[4])) << 24) ) -+#define SD_R1_SET_CMD_STATUS(pR,status) \ -+{ \ -+ (pR)[1] = (UINT8)(status); \ -+ (pR)[2] = (UINT8)((status) >> 8); \ -+ (pR)[3] = (UINT8)((status) >> 16); \ -+ (pR)[4] = (UINT8)((status) >> 24); \ -+} -+ -+/* SD R1 card status bit masks */ -+#define SD_CS_CMD_OUT_OF_RANGE ((UINT32)(1 << 31)) -+#define SD_CS_ADDRESS_ERR (1 << 30) -+#define SD_CS_BLK_LEN_ERR (1 << 29) -+#define SD_CS_ERASE_SEQ_ERR (1 << 28) -+#define SD_CS_ERASE_PARAM_ERR (1 << 27) -+#define SD_CS_WP_ERR (1 << 26) -+#define SD_CS_CARD_LOCKED (1 << 25) -+#define SD_CS_LK_UNLK_FAILED (1 << 24) -+#define SD_CS_PREV_CMD_CRC_ERR (1 << 23) -+#define SD_CS_ILLEGAL_CMD_ERR (1 << 22) -+#define SD_CS_ECC_FAILED (1 << 21) -+#define SD_CS_CARD_INTERNAL_ERR (1 << 20) -+#define SD_CS_GENERAL_ERR (1 << 19) -+#define SD_CS_CSD_OVERWR_ERR (1 << 16) -+#define SD_CS_WP_ERASE_SKIP (1 << 15) -+#define SD_CS_ECC_DISABLED (1 << 14) -+#define SD_CS_ERASE_RESET (1 << 13) -+#define SD_CS_GET_STATE(status) (((status) >> 9) & 0x0f) -+#define SD_CS_SET_STATE(status, state) \ -+{ \ -+ (status) &= ~(0x0F << 9); \ -+ (status) |= (state) << 9 \ -+} -+ -+#define SD_CS_TRANSFER_ERRORS \ -+ ( SD_CS_ADDRESS_ERR | \ -+ SD_CS_BLK_LEN_ERR | \ -+ SD_CS_ERASE_SEQ_ERR | \ -+ SD_CS_ERASE_PARAM_ERR | \ -+ SD_CS_WP_ERR | \ -+ SD_CS_ECC_FAILED | \ -+ SD_CS_CARD_INTERNAL_ERR | \ -+ SD_CS_GENERAL_ERR ) -+ -+#define SD_CS_STATE_IDLE 0 -+#define SD_CS_STATE_READY 1 -+#define SD_CS_STATE_IDENT 2 -+#define SD_CS_STATE_STBY 3 -+#define SD_CS_STATE_TRANS 4 -+#define SD_CS_STATE_DATA 5 -+#define SD_CS_STATE_RCV 6 -+#define SD_CS_STATE_PRG 7 -+#define SD_CS_STATE_DIS 8 -+#define SD_CS_READY_FOR_DATA (1 << 8) -+#define SD_CS_APP_CMD (1 << 5) -+#define SD_CS_AKE_SEQ_ERR (1 << 3) -+ -+/* SD R2 response */ -+#define SD_R2_RESPONSE_BYTES 17 -+#define MAX_CSD_CID_BYTES 16 -+#define SD_R2_SET_STUFF_BITS(pR) (pR)[16] = 0x3F -+#define GET_SD_CSD_TRANS_SPEED(pR) (pR)[12] -+#define GET_SD_CID_MANFID(pR) (pR)[15] -+#define GET_SD_CID_PN_1(pR) (pR)[12] -+#define GET_SD_CID_PN_2(pR) (pR)[11] -+#define GET_SD_CID_PN_3(pR) (pR)[10] -+#define GET_SD_CID_PN_4(pR) (pR)[9] -+#define GET_SD_CID_PN_5(pR) (pR)[8] -+#define GET_SD_CID_PN_6(pR) (pR)[7] -+ -+#define GET_SD_CID_OEMID(pR) ((((UINT16)(pR)[14]) << 8 )| (UINT16)((pR)[13])) -+#define SDMMC_OCR_VOLTAGE_MASK 0x7FFFFFFF -+/* SD R3 response */ -+#define SD_R3_RESPONSE_BYTES 6 -+#define SD_R3_GET_OCR(pR) ((((UINT32)((pR)[1])) | \ -+ (((UINT32)((pR)[2])) << 8) | \ -+ (((UINT32)((pR)[3])) << 16) | \ -+ (((UINT32)((pR)[4])) << 24)) & SDMMC_OCR_VOLTAGE_MASK) -+#define SD_R3_IS_CARD_READY(pR) (((pR)[4] & 0x80) == 0x80) -+ -+/* OCR bit definitions */ -+#define SD_OCR_CARD_PWR_UP_STATUS ((UINT32)(1 << 31)) -+#define SD_OCR_3_5_TO_3_6_VDD (1 << 23) -+#define SD_OCR_3_4_TO_3_5_VDD (1 << 22) -+#define SD_OCR_3_3_TO_3_4_VDD (1 << 21) -+#define SD_OCR_3_2_TO_3_3_VDD (1 << 20) -+#define SD_OCR_3_1_TO_3_2_VDD (1 << 19) -+#define SD_OCR_3_0_TO_3_1_VDD (1 << 18) -+#define SD_OCR_2_9_TO_3_0_VDD (1 << 17) -+#define SD_OCR_2_8_TO_2_9_VDD (1 << 16) -+#define SD_OCR_2_7_TO_2_8_VDD (1 << 15) -+#define SD_OCR_2_6_TO_2_7_VDD (1 << 14) -+#define SD_OCR_2_5_TO_2_6_VDD (1 << 13) -+#define SD_OCR_2_4_TO_2_5_VDD (1 << 12) -+#define SD_OCR_2_3_TO_2_4_VDD (1 << 11) -+#define SD_OCR_2_2_TO_2_3_VDD (1 << 10) -+#define SD_OCR_2_1_TO_2_2_VDD (1 << 9) -+#define SD_OCR_2_0_TO_2_1_VDD (1 << 8) -+#define SD_OCR_1_9_TO_2_0_VDD (1 << 7) -+#define SD_OCR_1_8_TO_1_9_VDD (1 << 6) -+#define SD_OCR_1_7_TO_1_8_VDD (1 << 5) -+#define SD_OCR_1_6_TO_1_7_VDD (1 << 4) -+ -+/* SD Status data block */ -+#define SD_STATUS_DATA_BYTES 64 -+#define SDS_GET_DATA_WIDTH(buffer) ((buffer)[0] & 0xC0) -+#define SDS_BUS_1_BIT 0x00 -+#define SDS_BUS_4_BIT 0x80 -+#define SDS_GET_SECURE_MODE(buffer) ((buffer)[0] & 0x20) -+#define SDS_CARD_SECURE_MODE 0x20 -+#define SDS_GET_CARD_TYPE(buffer) ((buffer)[60] & 0x0F) -+#define SDS_SD_CARD_RW 0x00 -+#define SDS_SD_CARD_ROM 0x01 -+ -+/* SD R6 response */ -+#define SD_R6_RESPONSE_BYTES 6 -+#define SD_R6_GET_RCA(pR) ((UINT16)((pR)[3]) | (((UINT16)((pR)[4])) << 8)) -+#define SD_R6_GET_CS(pR) ((UINT16)((pR)[1]) | (((UINT16)((pR)[2])) << 8)) -+ -+/* SD Configuration Register (SCR) */ -+#define SD_SCR_BYTES 8 -+#define SCR_REV_1_0 0x00 -+#define SCR_SD_SPEC_1_00 0x00 -+#define SCR_SD_SPEC_1_10 0x01 -+#define SCR_BUS_SUPPORTS_1_BIT 0x01 -+#define SCR_BUS_SUPPORTS_4_BIT 0x04 -+#define SCR_SD_SECURITY_MASK 0x70 -+#define SCR_SD_NO_SECURITY 0x00 -+#define SCR_SD_SECURITY_1_0 0x10 -+#define SCR_SD_SECURITY_2_0 0x20 -+#define SCR_DATA_STATUS_1_AFTER_ERASE 0x80 -+ -+#define GET_SD_SCR_STRUCT_VER(pB) ((pB)[7] >> 4) -+#define GET_SD_SCR_SDSPEC_VER(pB) ((pB)[7] & 0x0F) -+#define GET_SD_SCR_BUSWIDTHS(pB) ((pB)[6] & 0x0F) -+#define GET_SD_SCR_BUSWIDTHS_FLAGS(pB) (pB)[6] -+#define GET_SD_SCR_SECURITY(pB) (((pB)[6] >> 4) & 0x07) -+#define GET_SD_SCR_DATA_STAT_AFTER_ERASE(pB) (((pB)[6] >> 7) & 0x01) -+ -+/* SDIO R4 Response */ -+#define SD_SDIO_R4_RESPONSE_BYTES 6 -+#define SD_SDIO_R4_GET_OCR(pR) ((UINT32)((pR)[1]) | \ -+ (((UINT32)(pR)[2]) << 8) | \ -+ (((UINT32)(pR)[3]) << 16)) -+#define SD_SDIO_R4_IS_MEMORY_PRESENT(pR) (((pR)[4] & 0x08) == 0x08) -+#define SD_SDIO_R4_GET_IO_FUNC_COUNT(pR) (((pR)[4] >> 4) & 0x07) -+#define SD_SDIO_R4_IS_CARD_READY(pR) (((pR)[4] & 0x80) == 0x80) -+ -+/* SDIO R5 response */ -+#define SD_SDIO_R5_RESPONSE_BYTES 6 -+#define SD_SDIO_R5_READ_DATA_OFFSET 1 -+#define SD_R5_GET_READ_DATA(pR) (pR)[SD_SDIO_R5_READ_DATA_OFFSET] -+#define SD_R5_RESP_FLAGS_OFFSET 2 -+#define SD_R5_GET_RESP_FLAGS(pR) (pR)[SD_R5_RESP_FLAGS_OFFSET] -+#define SD_R5_SET_CMD(pR,cmd) (pR)[5] = (cmd) & 0xC0 -+#define SD_R5_RESP_CMD_ERR (1 << 7) /* for previous cmd */ -+#define SD_R5_ILLEGAL_CMD (1 << 6) -+#define SD_R5_GENERAL_ERR (1 << 3) -+#define SD_R5_INVALID_FUNC (1 << 1) -+#define SD_R5_ARG_RANGE_ERR (1 << 0) -+#define SD_R5_CURRENT_CMD_ERRORS (SD_R5_ILLEGAL_CMD | SD_R5_GENERAL_ERR \ -+ | SD_R5_INVALID_FUNC | SD_R5_ARG_RANGE_ERR) -+#define SD_R5_ERRORS (SD_R5_CURRENT_CMD_ERRORS) -+ -+#define SD_R5_GET_IO_STATE(pR) (((pR)[2] >> 4) & 0x03) -+#define SD_R5_STATE_DIS 0x00 -+#define SD_R5_STATE_CMD 0x01 -+#define SD_R5_STATE_TRN 0x02 -+ -+/* SDIO Modified R6 Response */ -+#define SD_SDIO_R6_RESPONSE_BYTES 6 -+#define SD_SDIO_R6_GET_RCA(pR) ((UINT16)((pR)[3]) | ((UINT16)((pR)[4]) << 8)) -+#define SD_SDIO_R6_GET_CSTAT(pR)((UINT16)((pR)[1]) | ((UINT16)((pR)[2]) << 8)) -+ -+/* SPI mode R1 response */ -+#define SPI_R1_RESPONSE_BYTES 1 -+#define GET_SPI_R1_RESP_TOKEN(pR) (pR)[0] -+#define SPI_CS_STATE_IDLE 0x01 -+#define SPI_CS_ERASE_RESET (1 << 1) -+#define SPI_CS_ILLEGAL_CMD (1 << 2) -+#define SPI_CS_CMD_CRC_ERR (1 << 3) -+#define SPI_CS_ERASE_SEQ_ERR (1 << 4) -+#define SPI_CS_ADDRESS_ERR (1 << 5) -+#define SPI_CS_PARAM_ERR (1 << 6) -+#define SPI_CS_ERR_MASK 0x7c -+ -+/* SPI mode R2 response */ -+#define SPI_R2_RESPONSE_BYTES 2 -+#define GET_SPI_R2_RESP_TOKEN(pR) (pR)[1] -+#define GET_SPI_R2_STATUS_TOKEN(pR) (pR)[0] -+/* the first response byte is defined above */ -+/* the second response byte is defined below */ -+#define SPI_CS_CARD_IS_LOCKED (1 << 0) -+#define SPI_CS_LOCK_UNLOCK_FAILED (1 << 1) -+#define SPI_CS_ERROR (1 << 2) -+#define SPI_CS_INTERNAL_ERROR (1 << 3) -+#define SPI_CS_ECC_FAILED (1 << 4) -+#define SPI_CS_WP_VIOLATION (1 << 5) -+#define SPI_CS_ERASE_PARAM_ERR (1 << 6) -+#define SPI_CS_OUT_OF_RANGE (1 << 7) -+ -+/* SPI mode R3 response */ -+#define SPI_R3_RESPONSE_BYTES 5 -+#define SPI_R3_GET_OCR(pR) ((((UINT32)((pR)[0])) | \ -+ (((UINT32)((pR)[1])) << 8) | \ -+ (((UINT32)((pR)[2])) << 16) | \ -+ (((UINT32)((pR)[3])) << 24)) & SDMMC_OCR_VOLTAGE_MASK) -+#define SPI_R3_IS_CARD_READY(pR) (((pR)[3] & 0x80) == 0x80) -+#define GET_SPI_R3_RESP_TOKEN(pR) (pR)[4] -+ -+/* SPI mode SDIO R4 response */ -+#define SPI_SDIO_R4_RESPONSE_BYTES 5 -+#define SPI_SDIO_R4_GET_OCR(pR) ((UINT32)((pR)[0]) | \ -+ (((UINT32)(pR)[1]) << 8) | \ -+ (((UINT32)(pR)[2]) << 16)) -+#define SPI_SDIO_R4_IS_MEMORY_PRESENT(pR) (((pR)[3] & 0x08) == 0x08) -+#define SPI_SDIO_R4_GET_IO_FUNC_COUNT(pR) (((pR)[3] >> 4) & 0x07) -+#define SPI_SDIO_R4_IS_CARD_READY(pR) (((pR)[3] & 0x80) == 0x80) -+#define GET_SPI_SDIO_R4_RESP_TOKEN(pR) (pR)[4] -+ -+/* SPI Mode SDIO R5 response */ -+#define SPI_SDIO_R5_RESPONSE_BYTES 2 -+#define GET_SPI_SDIO_R5_RESP_TOKEN(pR) (pR)[1] -+#define GET_SPI_SDIO_R5_RESPONSE_RDATA(pR) (pR)[0] -+#define SPI_R5_IDLE_STATE 0x01 -+#define SPI_R5_ILLEGAL_CMD (1 << 2) -+#define SPI_R5_CMD_CRC (1 << 3) -+#define SPI_R5_FUNC_ERR (1 << 4) -+#define SPI_R5_PARAM_ERR (1 << 6) -+ -+/* SDIO COMMAND 52 Definitions */ -+#define CMD52_READ 0 -+#define CMD52_WRITE 1 -+#define CMD52_READ_AFTER_WRITE 1 -+#define CMD52_NORMAL_WRITE 0 -+#define SDIO_SET_CMD52_ARG(arg,rw,func,raw,address,writedata) \ -+ (arg) = (((rw) & 1) << 31) | \ -+ (((func) & 0x7) << 28) | \ -+ (((raw) & 1) << 27) | \ -+ (1 << 26) | \ -+ (((address) & 0x1FFFF) << 9) | \ -+ (1 << 8) | \ -+ ((writedata) & 0xFF) -+#define SDIO_SET_CMD52_READ_ARG(arg,func,address) \ -+ SDIO_SET_CMD52_ARG(arg,CMD52_READ,(func),0,address,0x00) -+#define SDIO_SET_CMD52_WRITE_ARG(arg,func,address,value) \ -+ SDIO_SET_CMD52_ARG(arg,CMD52_WRITE,(func),CMD52_NORMAL_WRITE,address,value) -+ -+/* SDIO COMMAND 53 Definitions */ -+#define CMD53_READ 0 -+#define CMD53_WRITE 1 -+#define CMD53_BLOCK_BASIS 1 -+#define CMD53_BYTE_BASIS 0 -+#define CMD53_FIXED_ADDRESS 0 -+#define CMD53_INCR_ADDRESS 1 -+#define SDIO_SET_CMD53_ARG(arg,rw,func,mode,opcode,address,bytes_blocks) \ -+ (arg) = (((rw) & 1) << 31) | \ -+ (((func) & 0x7) << 28) | \ -+ (((mode) & 1) << 27) | \ -+ (((opcode) & 1) << 26) | \ -+ (((address) & 0x1FFFF) << 9) | \ -+ ((bytes_blocks) & 0x1FF) -+ -+#define SDIO_MAX_LENGTH_BYTE_BASIS 512 -+#define SDIO_MAX_BLOCKS_BLOCK_BASIS 511 -+#define SDIO_MAX_BYTES_PER_BLOCK 2048 -+#define SDIO_COMMON_AREA_FUNCTION_NUMBER 0 -+#define SDIO_FIRST_FUNCTION_NUMBER 1 -+#define SDIO_LAST_FUNCTION_NUMBER 7 -+ -+#define CMD53_CONVERT_BYTE_BASIS_BLK_LENGTH_PARAM(b) (((b) < SDIO_MAX_LENGTH_BYTE_BASIS) ? (b) : 0) -+#define CMD53_CONVERT_BLOCK_BASIS_BLK_COUNT_PARAM(b) (((b) <= SDIO_MAX_BLOCKS_BLOCK_BASIS) ? (b) : 0) -+ -+ -+/* SDIO COMMON Registers */ -+ -+/* revision register */ -+#define CCCR_SDIO_REVISION_REG 0x00 -+#define CCCR_REV_MASK 0x0F -+#define CCCR_REV_1_0 0x00 -+#define CCCR_REV_1_1 0x01 -+#define SDIO_REV_MASK 0xF0 -+#define SDIO_REV_1_00 0x00 -+#define SDIO_REV_1_10 0x10 -+#define SDIO_REV_1_20 0x20 -+/* SD physical spec revision */ -+#define SD_SPEC_REVISION_REG 0x01 -+#define SD_REV_MASK 0x0F -+#define SD_REV_1_01 0x00 -+#define SD_REV_1_10 0x01 -+/* I/O Enable */ -+#define SDIO_ENABLE_REG 0x02 -+/* I/O Ready */ -+#define SDIO_READY_REG 0x03 -+/* Interrupt Enable */ -+#define SDIO_INT_ENABLE_REG 0x04 -+#define SDIO_INT_MASTER_ENABLE 0x01 -+#define SDIO_INT_ALL_ENABLE 0xFE -+/* Interrupt Pending */ -+#define SDIO_INT_PENDING_REG 0x05 -+#define SDIO_INT_PEND_MASK 0xFE -+/* I/O Abort */ -+#define SDIO_IO_ABORT_REG 0x06 -+#define SDIO_IO_RESET (1 << 3) -+/* Bus Interface */ -+#define SDIO_BUS_IF_REG 0x07 -+#define CARD_DETECT_DISABLE 0x80 -+#define SDIO_BUS_WIDTH_1_BIT 0x00 -+#define SDIO_BUS_WIDTH_4_BIT 0x02 -+/* Card Capabilities */ -+#define SDIO_CARD_CAPS_REG 0x08 -+#define SDIO_CAPS_CMD52_WHILE_DATA 0x01 /* card can issue CMD52 while data transfer */ -+#define SDIO_CAPS_MULTI_BLOCK 0x02 /* card supports multi-block data transfers */ -+#define SDIO_CAPS_READ_WAIT 0x04 /* card supports read-wait protocol */ -+#define SDIO_CAPS_SUSPEND_RESUME 0x08 /* card supports I/O function suspend/resume */ -+#define SDIO_CAPS_INT_MULTI_BLK 0x10 /* interrupts between multi-block data capable */ -+#define SDIO_CAPS_ENB_INT_MULTI_BLK 0x20 /* enable ints between muli-block data */ -+#define SDIO_CAPS_LOW_SPEED 0x40 /* low speed card */ -+#define SDIO_CAPS_4BIT_LS 0x80 /* 4 bit low speed card */ -+/* Common CIS pointer */ -+#define SDIO_CMN_CIS_PTR_LOW_REG 0x09 -+#define SDIO_CMN_CIS_PTR_MID_REG 0x0a -+#define SDIO_CMN_CIS_PTR_HI_REG 0x0b -+/* Bus suspend */ -+#define SDIO_BUS_SUSPEND_REG 0x0c -+#define SDIO_FUNC_SUSPEND_STATUS_MASK 0x01 /* selected function is suspended */ -+#define SDIO_SUSPEND_FUNCTION 0x02 /* suspend the current selected function */ -+/* Function select (for bus suspension) */ -+#define SDIO_FUNCTION_SELECT_REG 0x0d -+#define SDIO_SUSPEND_FUNCTION_0 0x00 -+#define SDIO_SUSPEND_MEMORY_FUNC_MASK 0x08 -+/* Function Execution */ -+#define SDIO_FUNCTION_EXEC_REG 0x0e -+#define SDIO_MEMORY_FUNC_EXEC_MASK 0x01 -+/* Function Ready */ -+#define SDIO_FUNCTION_READY_REG 0x0f -+#define SDIO_MEMORY_FUNC_BUSY_MASK 0x01 -+ -+/* power control 1.10 only */ -+#define SDIO_POWER_CONTROL_REG 0x12 -+#define SDIO_POWER_CONTROL_SMPC 0x01 -+#define SDIO_POWER_CONTROL_EMPC 0x02 -+ -+/* high speed control , 1.20 only */ -+#define SDIO_HS_CONTROL_REG 0x13 -+#define SDIO_HS_CONTROL_SHS 0x01 -+#define SDIO_HS_CONTROL_EHS 0x02 -+ -+/* Function Base Registers */ -+#define xFUNCTION_FBR_OFFSET(funcNo) (0x100*(funcNo)) -+/* offset calculation that does not use multiplication */ -+static INLINE UINT32 CalculateFBROffset(UCHAR FuncNo) { -+ UCHAR i = FuncNo; -+ UINT32 offset = 0; -+ while (i) { -+ offset += 0x100; -+ i--; -+ } -+ return offset; -+} -+/* Function info */ -+#define FBR_FUNC_INFO_REG_OFFSET(fbr) ((fbr) + 0x00) -+#define FUNC_INFO_SUPPORTS_CSA_MASK 0x40 -+#define FUNC_INFO_ENABLE_CSA 0x80 -+#define FUNC_INFO_DEVICE_CODE_MASK 0x0F -+#define FUNC_INFO_DEVICE_CODE_LAST 0x0F -+#define FBR_FUNC_EXT_DEVICE_CODE_OFFSET(fbr) ((fbr) + 0x01) -+/* Function Power selection */ -+#define FBR_FUNC_POWER_SELECT_OFFSET(fbr) ((fbr) + 0x02) -+#define FUNC_POWER_SELECT_SPS 0x01 -+#define FUNC_POWER_SELECT_EPS 0x02 -+/* Function CIS ptr */ -+#define FBR_FUNC_CIS_LOW_OFFSET(fbr) ((fbr) + 0x09) -+#define FBR_FUNC_CIS_MID_OFFSET(fbr) ((fbr) + 0x0a) -+#define FBR_FUNC_CIS_HI_OFFSET(fbr) ((fbr) + 0x0b) -+/* Function CSA ptr */ -+#define FBR_FUNC_CSA_LOW_OFFSET(fbr) ((fbr) + 0x0c) -+#define FBR_FUNC_CSA_MID_OFFSET(fbr) ((fbr) + 0x0d) -+#define FBR_FUNC_CSA_HI_OFFSET(fbr) ((fbr) + 0x0e) -+/* Function CSA data window */ -+#define FBR_FUNC_CSA_DATA_OFFSET(fbr) ((fbr) + 0x0f) -+/* Function Block Size Control */ -+#define FBR_FUNC_BLK_SIZE_LOW_OFFSET(fbr) ((fbr) + 0x10) -+#define FBR_FUNC_BLK_SIZE_HI_OFFSET(fbr) ((fbr) + 0x11) -+#define SDIO_CIS_AREA_BEGIN 0x00001000 -+#define SDIO_CIS_AREA_END 0x00017fff -+/* Tuple definitions */ -+#define CISTPL_NULL 0x00 -+#define CISTPL_CHECKSUM 0x10 -+#define CISTPL_VERS_1 0x15 -+#define CISTPL_ALTSTR 0x16 -+#define CISTPL_MANFID 0x20 -+#define CISTPL_FUNCID 0x21 -+#define CISTPL_FUNCE 0x22 -+#define CISTPL_VENDOR 0x91 -+#define CISTPL_END 0xff -+#define CISTPL_LINK_END 0xff -+ -+ -+/* these structures must be packed */ -+ -+/* Manufacturer ID tuple */ -+struct SDIO_MANFID_TPL { -+ UINT16 ManufacturerCode; /* jedec code */ -+ UINT16 ManufacturerInfo; /* manufacturer specific code */ -+}CT_PACK_STRUCT; -+ -+/* Function ID Tuple */ -+struct SDIO_FUNC_ID_TPL { -+ UINT8 DeviceCode; /* device code */ -+ UINT8 InitMask; /* system initialization mask (not used) */ -+}CT_PACK_STRUCT; -+ -+ /* Extended Function Tuple (Common) */ -+struct SDIO_FUNC_EXT_COMMON_TPL { -+ UINT8 Type; /* type */ -+ UINT16 Func0_MaxBlockSize; /* max function 0 block transfer size */ -+ UINT8 MaxTransSpeed; /* max transfer speed (encoded) */ -+#define TRANSFER_UNIT_MULTIPIER_MASK 0x07 -+#define TIME_VALUE_MASK 0x78 -+#define TIME_VALUE_SHIFT 3 -+}CT_PACK_STRUCT; -+ -+/* Extended Function Tuple (Per Function) */ -+struct SDIO_FUNC_EXT_FUNCTION_TPL { -+ UINT8 Type; /* type */ -+#define SDIO_FUNC_INFO_WAKEUP_SUPPORT 0x01 -+ UINT8 FunctionInfo; /* function info */ -+ UINT8 SDIORev; /* revision */ -+ UINT32 CardPSN; /* product serial number */ -+ UINT32 CSASize; /* CSA size */ -+ UINT8 CSAProperties; /* CSA properties */ -+ UINT16 MaxBlockSize; /* max block size for block transfers */ -+ UINT32 FunctionOCR; /* optimal function OCR */ -+ UINT8 OpMinPwr; /* operational min power */ -+ UINT8 OpAvgPwr; /* operational average power */ -+ UINT8 OpMaxPwr; /* operation maximum power */ -+ UINT8 SbMinPwr; /* standby minimum power */ -+ UINT8 SbAvgPwr; /* standby average power */ -+ UINT8 SbMaxPwr; /* standby maximum power */ -+ UINT16 MinBandWidth; /* minimum bus bandwidth */ -+ UINT16 OptBandWidth; /* optimalbus bandwitdh */ -+}CT_PACK_STRUCT; -+ -+struct SDIO_FUNC_EXT_FUNCTION_TPL_1_1 { -+ struct SDIO_FUNC_EXT_FUNCTION_TPL CommonInfo; /* from 1.0*/ -+ UINT16 EnableTimeOut; /* timeout for enable */ -+ UINT16 OperPwrMaxPwr; -+ UINT16 OperPwrAvgPwr; -+ UINT16 HiPwrMaxPwr; -+ UINT16 HiPwrAvgPwr; -+ UINT16 LowPwrMaxPwr; -+ UINT16 LowPwrAvgPwr; -+}CT_PACK_STRUCT; -+ -+static INLINE SDIO_STATUS ConvertCMD52ResponseToSDIOStatus(UINT8 CMD52ResponseFlags) { -+ if (!(CMD52ResponseFlags & SD_R5_ERRORS)) { -+ return SDIO_STATUS_SUCCESS; -+ } -+ if (CMD52ResponseFlags & SD_R5_ILLEGAL_CMD) { -+ return SDIO_STATUS_DATA_STATE_INVALID; -+ } else if (CMD52ResponseFlags & SD_R5_INVALID_FUNC) { -+ return SDIO_STATUS_INVALID_FUNC; -+ } else if (CMD52ResponseFlags & SD_R5_ARG_RANGE_ERR) { -+ return SDIO_STATUS_FUNC_ARG_ERROR; -+ } else { -+ return SDIO_STATUS_DATA_ERROR_UNKNOWN; -+ } -+} -+ -+/* CMD6 mode switch definitions */ -+ -+#define SD_SWITCH_FUNC_CHECK 0 -+#define SD_SWITCH_FUNC_SET ((UINT32)(1 << 31)) -+#define SD_FUNC_NO_SELECT_MASK 0x00FFFFFF -+#define SD_SWITCH_GRP_1 0 -+#define SD_SWITCH_GRP_2 1 -+#define SD_SWITCH_GRP_3 2 -+#define SD_SWITCH_GRP_4 3 -+#define SD_SWITCH_GRP_5 4 -+#define SD_SWITCH_GRP_6 5 -+ -+#define SD_SWITCH_HIGH_SPEED_GROUP SD_SWITCH_GRP_1 -+#define SD_SWITCH_HIGH_SPEED_FUNC_NO 1 -+ -+#define SD_SWITCH_MAKE_SHIFT(grp) ((grp) * 4) -+ -+#define SD_SWITCH_MAKE_GRP_PATTERN(FuncGrp,FuncNo) \ -+ ((SD_FUNC_NO_SELECT_MASK & (~(0xF << SD_SWITCH_MAKE_SHIFT(FuncGrp)))) | \ -+ (((FuncNo) & 0xF) << SD_SWITCH_MAKE_SHIFT(FuncGrp))) \ -+ -+#define SD_SWITCH_FUNC_ARG_GROUP_CHECK(FuncGrp,FuncNo) \ -+ (SD_SWITCH_FUNC_CHECK | SD_SWITCH_MAKE_GRP_PATTERN(FuncGrp,FuncNo)) -+ -+#define SD_SWITCH_FUNC_ARG_GROUP_SET(FuncGrp,FuncNo) \ -+ (SD_SWITCH_FUNC_SET | SD_SWITCH_MAKE_GRP_PATTERN(FuncGrp,FuncNo)) -+ -+#define SD_SWITCH_FUNC_STATUS_BLOCK_BYTES 64 -+ -+#define SD_SWITCH_FUNC_STATUS_GET_GRP_BIT_MASK(pBuffer,FuncGrp) \ -+ (USHORT)((pBuffer)[50 + ((FuncGrp)*2)] | ((pBuffer)[51 + ((FuncGrp)*2)] << 8)) -+ -+#define SD_SWITCH_FUNC_STATUS_GET_MAX_CURRENT(pBuffer) \ -+ (USHORT)((pBuffer)[62] | ((pBuffer)[63] << 8)) -+ -+static INLINE UINT8 SDSwitchGetSwitchResult(PUINT8 pBuffer, UINT8 FuncGrp) -+{ -+ switch (FuncGrp) { -+ case 0: -+ return (pBuffer[47] & 0xF); -+ case 1: -+ return (pBuffer[47] >> 4); -+ case 2: -+ return (pBuffer[48] & 0xF); -+ case 3: -+ return (pBuffer[48] >> 4); -+ case 4: -+ return (pBuffer[49] & 0xF); -+ case 5: -+ return (pBuffer[49] >> 4); -+ default: -+ return 0xF; -+ } -+} -+ -+#endif -diff --git a/include/linux/sdio/ctsystem.h b/include/linux/sdio/ctsystem.h -new file mode 100644 -index 0000000..4f72739 ---- /dev/null -+++ b/include/linux/sdio/ctsystem.h -@@ -0,0 +1,115 @@ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+@file: cpsystem.h -+ -+@abstract: common system include file. -+ -+@notice: Copyright (c), 2004-2006 Atheros Communications, Inc. -+ -+ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * Software distributed under the License is distributed on an "AS -+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -+ * implied. See the License for the specific language governing -+ * rights and limitations under the License. -+ * -+ * Portions of this code were developed with information supplied from the -+ * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply: -+ * -+ * The following conditions apply to the release of the SD simplified specification (�Simplified -+ * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete -+ * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided -+ * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified -+ * Specification may require a license from the SD Card Association or other third parties. -+ * Disclaimers: -+ * The information contained in the Simplified Specification is presented only as a standard -+ * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any -+ * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for -+ * any damages, any infringements of patents or other right of the SD Card Association or any third -+ * parties, which may result from its use. No license is granted by implication, estoppel or otherwise -+ * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall -+ * be construed as an obligation by the SD Card Association to disclose or distribute any technical -+ * information, know-how or other confidential information to any third party. -+ * -+ * -+ * The initial developers of the original code are Seung Yi and Paul Lever -+ * -+ * sdio@atheros.com -+ * -+ * -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#ifndef __CPSYSTEM_H___ -+#define __CPSYSTEM_H___ -+ -+/* SDIO stack status defines */ -+/* < 0 error, >0 warning, 0 success */ -+#define SDIO_IS_WARNING(status) ((status) > 0) -+#define SDIO_IS_ERROR(status) ((status) < 0) -+#define SDIO_SUCCESS(status) ((SDIO_STATUS)(status) >= 0) -+#define SDIO_STATUS_SUCCESS 0 -+#define SDIO_STATUS_ERROR -1 -+#define SDIO_STATUS_INVALID_PARAMETER -2 -+#define SDIO_STATUS_PENDING 3 -+#define SDIO_STATUS_DEVICE_NOT_FOUND -4 -+#define SDIO_STATUS_DEVICE_ERROR -5 -+#define SDIO_STATUS_INTERRUPTED -6 -+#define SDIO_STATUS_NO_RESOURCES -7 -+#define SDIO_STATUS_CANCELED -8 -+#define SDIO_STATUS_BUFFER_TOO_SMALL -9 -+#define SDIO_STATUS_NO_MORE_MESSAGES -10 -+#define SDIO_STATUS_BUS_RESP_TIMEOUT -20 /* response timed-out */ -+#define SDIO_STATUS_BUS_READ_TIMEOUT -21 /* read data timed-out */ -+#define SDIO_STATUS_BUS_READ_CRC_ERR -22 /* data CRC failed */ -+#define SDIO_STATUS_BUS_WRITE_ERROR -23 /* write failed */ -+#define SDIO_STATUS_BUS_RESP_CRC_ERR -24 /* response received with a CRC error */ -+#define SDIO_STATUS_INVALID_TUPLE_LENGTH -25 /* tuple length was invalid */ -+#define SDIO_STATUS_TUPLE_NOT_FOUND -26 /* tuple could not be found */ -+#define SDIO_STATUS_CIS_OUT_OF_RANGE -27 /* CIS is out of range in the tuple scan */ -+#define SDIO_STATUS_FUNC_ENABLE_TIMEOUT -28 /* card timed out enabling or disabling */ -+#define SDIO_STATUS_DATA_STATE_INVALID -29 /* card is in an invalid state for data */ -+#define SDIO_STATUS_DATA_ERROR_UNKNOWN -30 /* card cannot process data transfer */ -+#define SDIO_STATUS_INVALID_FUNC -31 /* sdio request is not valid for the function */ -+#define SDIO_STATUS_FUNC_ARG_ERROR -32 /* sdio request argument is invalid or out of range */ -+#define SDIO_STATUS_INVALID_COMMAND -33 /* SD COMMAND is invalid for the card state */ -+#define SDIO_STATUS_SDREQ_QUEUE_FAILED -34 /* request failed to insert into queue */ -+#define SDIO_STATUS_BUS_RESP_TIMEOUT_SHIFTABLE -35 /* response timed-out, possibily shiftable to correct */ -+#define SDIO_STATUS_UNSUPPORTED -36 /* not supported */ -+#define SDIO_STATUS_PROGRAM_TIMEOUT -37 /* memory card programming timeout */ -+#define SDIO_STATUS_PROGRAM_STATUS_ERROR -38 /* memory card programming errors */ -+ -+#include <linux/sdio/ctsystem_linux.h> -+ -+/* get structure from contained field */ -+#define CONTAINING_STRUCT(address, struct_type, field_name)\ -+ ((struct_type *)((ULONG_PTR)(address) - (ULONG_PTR)(&((struct_type *)0)->field_name))) -+ -+#define ZERO_OBJECT(obj) memset(&(obj),0,sizeof(obj)) -+#define ZERO_POBJECT(pObj) memset((pObj),0,sizeof(*(pObj))) -+ -+ -+/* bit field support functions */ -+static INLINE void SetBit(PULONG pField, UINT position) { -+ *pField |= 1 << position; -+} -+static INLINE void ClearBit(PULONG pField, UINT position) { -+ *pField &= ~(1 << position); -+} -+static INLINE BOOL IsBitSet(PULONG pField, UINT position) { -+ return (*pField & (1 << position)); -+} -+static INLINE INT FirstClearBit(PULONG pField) { -+ UINT ii; -+ for(ii = 0; ii < sizeof(ULONG)*8; ii++) { -+ if (!IsBitSet(pField, ii)) { -+ return ii; -+ } -+ } -+ /* no clear bits found */ -+ return -1; -+} -+ -+#endif /* __CPSYSTEM_H___ */ -diff --git a/include/linux/sdio/ctsystem_linux.h b/include/linux/sdio/ctsystem_linux.h -new file mode 100644 -index 0000000..0de89a6 ---- /dev/null -+++ b/include/linux/sdio/ctsystem_linux.h -@@ -0,0 +1,983 @@ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+@file: ctsystem_linux.h -+ -+@abstract: common system include file for Linux. -+ -+@notice: Copyright (c), 2004-2006 Atheros Communications, Inc. -+ -+ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * Software distributed under the License is distributed on an "AS -+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -+ * implied. See the License for the specific language governing -+ * rights and limitations under the License. -+ * -+ * Portions of this code were developed with information supplied from the -+ * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply: -+ * -+ * The following conditions apply to the release of the SD simplified specification (�Simplified -+ * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete -+ * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided -+ * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified -+ * Specification may require a license from the SD Card Association or other third parties. -+ * Disclaimers: -+ * The information contained in the Simplified Specification is presented only as a standard -+ * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any -+ * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for -+ * any damages, any infringements of patents or other right of the SD Card Association or any third -+ * parties, which may result from its use. No license is granted by implication, estoppel or otherwise -+ * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall -+ * be construed as an obligation by the SD Card Association to disclose or distribute any technical -+ * information, know-how or other confidential information to any third party. -+ * -+ * -+ * The initial developers of the original code are Seung Yi and Paul Lever -+ * -+ * sdio@atheros.com -+ * -+ * -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#ifndef __CPSYSTEM_LINUX_H___ -+#define __CPSYSTEM_LINUX_H___ -+ -+/* #define DBG_TIMESTAMP 1 */ -+#define SD_TRACK_REQ 1 -+ -+/* LINUX support */ -+#include <linux/version.h> -+ -+#ifndef KERNEL_VERSION -+ #error KERNEL_VERSION macro not defined! -+#endif -+ -+#ifndef LINUX_VERSION_CODE -+ #error LINUX_VERSION_CODE macro not defined! -+#endif -+ -+#include <linux/autoconf.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/types.h> -+#include <linux/spinlock.h> -+#include <linux/module.h> -+ -+#include <linux/interrupt.h> -+#include <linux/pnp.h> -+#include <asm/hardirq.h> -+#include <asm/semaphore.h> -+#include <asm/io.h> -+#include <asm/scatterlist.h> -+#ifdef DBG_TIMESTAMP -+#include <asm/timex.h> -+#endif /* DBG_TIMESTAMP */ -+#ifndef in_atomic -+ /* released version of 2.6.9 */ -+#include <linux/hardirq.h> -+#endif -+#include <linux/delay.h> -+#include <linux/device.h> -+ -+/* generic types */ -+typedef unsigned char UCHAR; -+typedef unsigned char * PUCHAR; -+typedef char TEXT; -+typedef char * PTEXT; -+typedef unsigned short USHORT; -+typedef unsigned short* PUSHORT; -+typedef unsigned int UINT; -+typedef unsigned int* PUINT; -+typedef int INT; -+typedef int* PINT; -+typedef unsigned long ULONG; -+typedef unsigned long* PULONG; -+typedef u8 UINT8; -+typedef u16 UINT16; -+typedef u32 UINT32; -+typedef u8* PUINT8; -+typedef u16* PUINT16; -+typedef u32* PUINT32; -+typedef unsigned char * ULONG_PTR; -+typedef void* PVOID; -+typedef unsigned char BOOL; -+typedef BOOL* PBOOL; -+typedef int SDIO_STATUS; -+typedef int SYSTEM_STATUS; -+typedef unsigned int EVENT_TYPE; -+typedef unsigned int EVENT_ARG; -+typedef unsigned int* PEVENT_TYPE; -+typedef struct semaphore OS_SEMAPHORE; -+typedef struct semaphore* POS_SEMAPHORE; -+typedef struct semaphore OS_SIGNAL; /* OS signals are just semaphores */ -+typedef struct semaphore* POS_SIGNAL; -+typedef spinlock_t OS_CRITICALSECTION; -+typedef spinlock_t *POS_CRITICALSECTION; -+typedef int SDPOWER_STATE; -+typedef unsigned long ATOMIC_FLAGS; -+typedef INT THREAD_RETURN; -+typedef dma_addr_t DMA_ADDRESS; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9) -+typedef struct task_struct* PKERNEL_TASK; -+typedef struct device_driver OS_DRIVER; -+typedef struct device_driver* POS_DRIVER; -+typedef struct device OS_DEVICE; -+typedef struct device* POS_DEVICE; -+typedef struct pnp_driver OS_PNPDRIVER; -+typedef struct pnp_driver* POS_PNPDRIVER; -+typedef struct pnp_dev OS_PNPDEVICE; -+typedef struct pnp_dev* POS_PNPDEVICE; -+typedef struct module* POS_MODULE; -+#else -+/* 2.4 */ -+typedef int PKERNEL_TASK; -+typedef PVOID OS_DRIVER; -+typedef PVOID* POS_DRIVER; -+typedef PVOID OS_DEVICE; -+typedef PVOID* POS_DEVICE; -+typedef PVOID OS_PNPDRIVER; -+typedef PVOID* POS_PNPDRIVER; -+typedef PVOID OS_PNPDEVICE; -+typedef PVOID* POS_PNPDEVICE; -+typedef struct module* POS_MODULE; -+#define module_param(a,b,c) MODULE_PARM(a, "i") -+#endif -+ -+typedef int CT_DEBUG_LEVEL; -+ -+ -+#ifndef TRUE -+#define TRUE 1 -+#endif -+#ifndef FALSE -+#define FALSE 0 -+#endif -+#ifndef NULL -+#define NULL ((PVOID)0) -+#endif -+#define SDDMA_DESCRIPTION_FLAG_DMA 0x1 /* DMA enabled */ -+#define SDDMA_DESCRIPTION_FLAG_SGDMA 0x2 /* Scatter-Gather DMA enabled */ -+typedef struct _SDDMA_DESCRIPTION { -+ UINT16 Flags; /* SDDMA_DESCRIPTION_FLAG_xxx */ -+ UINT16 MaxDescriptors; /* number of supported scatter gather entries */ -+ UINT32 MaxBytesPerDescriptor; /* maximum bytes in a DMA descriptor entry */ -+ u64 Mask; /* dma address mask */ -+ UINT32 AddressAlignment; /* dma address alignment mask, least significant bits indicate illegal address bits */ -+ UINT32 LengthAlignment; /* dma buffer length alignment mask, least significant bits indicate illegal length bits */ -+}SDDMA_DESCRIPTION, *PSDDMA_DESCRIPTION; -+typedef struct scatterlist SDDMA_DESCRIPTOR, *PSDDMA_DESCRIPTOR; -+ -+#define INLINE inline -+#define CT_PACK_STRUCT __attribute__ ((packed)) -+ -+#define CT_DECLARE_MODULE_PARAM_INTEGER(p) module_param(p, int, 0644); -+ -+/* debug print macros */ -+//#define SDDBG_KERNEL_PRINT_LEVEL KERN_DEBUG -+#define SDDBG_KERNEL_PRINT_LEVEL KERN_ALERT -+#define DBG_MASK_NONE 0x0 -+#define DBG_MASK_HCD 0x100 -+#define DBG_MASK_LIB 0x200 -+#define DBG_MASK_BUS 0x400 -+ -+/* debug output levels, this must be order low number to higher */ -+#define SDDBG_ERROR 3 -+#define SDDBG_WARN 4 -+#define SDDBG_DEBUG 6 -+#define SDDBG_TRACE 7 -+#define SDDBG_ALL 0xff -+ -+#define DBG_LEVEL_NONE 0 -+#define DBG_LEVEL_ERROR SDDBG_ERROR -+#define DBG_LEVEL_WARN SDDBG_WARN -+#define DBG_LEVEL_DEBUG SDDBG_DEBUG -+#define DBG_LEVEL_TRACE SDDBG_TRACE -+#define DBG_LEVEL_ALL SDDBG_ALL -+ -+#define DBG_GET_LEVEL(lvl) ((lvl) & 0xff) -+#define DBG_GET_MASK(lvl) (((lvl) & 0xff00)) -+ -+#define DBG_SDIO_MASK (DBG_MASK_NONE | DBG_LEVEL_DEBUG) -+ -+#define DEBUG 1 -+ -+#ifdef DEBUG -+ -+#define DBG_ASSERT(test) \ -+{ \ -+ if (!(test)) { \ -+ DBG_PRINT(SDDBG_ERROR, ("Debug Assert Caught, File %s, Line: %d, Test:%s \n",__FILE__, __LINE__,#test)); \ -+ } \ -+} -+#define DBG_ASSERT_WITH_MSG(test,s) \ -+{ \ -+ if (!(test)) { \ -+ DBG_PRINT(SDDBG_ERROR, ("Assert:%s File %s, Line: %d \n",(s),__FILE__, __LINE__)); \ -+ } \ -+} -+ -+#define DBG_PRINT(lvl, args)\ -+ do {\ -+ if (DBG_GET_LEVEL(lvl) <= (DBG_SDIO_MASK & 0xff)) \ -+ printk(_DBG_PRINTX_ARG args); \ -+ } while(0); -+ -+#else /* DEBUG */ -+ -+#define DBG_PRINT(lvl, str) -+#define DBG_ASSERT(test) -+#define DBG_ASSERT_WITH_MSG(test,s) -+#endif /* DEBUG */ -+ -+#define _DBG_PRINTX_ARG(arg...) arg /* unroll the parens around the var args*/ -+#define DBG_GET_DEBUG_LEVEL() DBG_GET_LEVEL(DBG_SDIO_MASK) -+#define DBG_SET_DEBUG_LEVEL(v) -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Print a string to the debugger or console -+ -+ @function name: REL_PRINT -+ @prototype: void REL_PRINT(INT Level, string) -+ @category: Support_Reference -+ @input: Level - debug level for the print -+ -+ @output: none -+ -+ @return: -+ -+ @notes: If Level is less than the current debug level, the print will be -+ issued. This print cannot be conditionally compiled. -+ @see also: DBG_PRINT -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define REL_PRINT(lvl, args)\ -+ {if (lvl <= DBG_GET_DEBUG_LEVEL())\ -+ printk(SDDBG_KERNEL_PRINT_LEVEL _DBG_PRINTX_ARG args);\ -+ } -+/* debug output levels, this must be order low number to higher */ -+#define SDDBG_ERROR 3 -+#define SDDBG_WARN 4 -+#define SDDBG_DEBUG 6 -+#define SDDBG_TRACE 7 -+ -+#ifdef DBG_CRIT_SECTION_RECURSE -+ /* this macro thows an exception if the lock is recursively taken -+ * the kernel must be configured with: CONFIG_DEBUG_SPINLOCK=y */ -+#define call_spin_lock(pCrit) \ -+{ \ -+ UINT32 unlocked = 1; \ -+ if ((pCrit)->lock) {unlocked = 0;} \ -+ spin_lock_bh(pCrit); \ -+ if (!unlocked) { \ -+ unlocked = 0x01; \ -+ unlocked = *((volatile UINT32 *)unlocked); \ -+ } \ -+} -+ -+#define call_spin_lock_irqsave(pCrit,isc) \ -+{ \ -+ UINT32 unlocked = 1; \ -+ if ((pCrit)->lock) {unlocked = 0;} \ -+ spin_lock_irqsave(pCrit,isc); \ -+ if (!unlocked) { \ -+ unlocked = 0x01; \ -+ unlocked = *((volatile UINT32 *)unlocked); \ -+ } \ -+} -+ -+#else -+#define call_spin_lock(s) spin_lock_bh(s) -+#define call_spin_lock_irqsave(s,isc) spin_lock_irqsave(s,isc) -+#endif -+ -+#define call_spin_unlock(s) spin_unlock_bh((s)) -+#define call_spin_unlock_irqrestore(s,isc) spin_unlock_irqrestore(s,isc) -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9) -+#define NonSchedulable() (in_atomic() || irqs_disabled()) -+#else -+#define NonSchedulable() (irqs_disabled()) -+#endif -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Initialize a critical section object. -+ -+ @function name: CriticalSectionInit -+ @prototype: SDIO_STATUS CriticalSectionInit(POS_CRITICALSECTION pCrit) -+ @category: Support_Reference -+ @output: pCrit - pointer to critical section to initialize -+ -+ @return: SDIO_STATUS_SUCCESS on success. -+ -+ @notes: CriticalSectionDelete() must be called to cleanup any resources -+ associated with the critical section. -+ -+ @see also: CriticalSectionDelete, CriticalSectionAcquire, CriticalSectionRelease -+ @example: To initialize a critical section: -+ status = CriticalSectionInit(&pDevice->ListLock); -+ if (!SDIO_SUCCESS(status)) { -+ .. failed -+ return status; -+ } -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static inline SDIO_STATUS CriticalSectionInit(POS_CRITICALSECTION pCrit) { -+ spin_lock_init(pCrit); -+ return SDIO_STATUS_SUCCESS; -+} -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Acquire a critical section lock. -+ -+ @function name: CriticalSectionAcquire -+ @prototype: SDIO_STATUS CriticalSectionAcquire(POS_CRITICALSECTION pCrit) -+ @category: Support_Reference -+ -+ @input: pCrit - pointer to critical section that was initialized -+ -+ @return: SDIO_STATUS_SUCCESS on success. -+ -+ @notes: The critical section lock is acquired when this function returns -+ SDIO_STATUS_SUCCESS. Use CriticalSectionRelease() to release -+ the critical section lock. -+ -+ @see also: CriticalSectionRelease -+ -+ @example: To acquire a critical section lock: -+ status = CriticalSectionAcquire(&pDevice->ListLock); -+ if (!SDIO_SUCCESS(status)) { -+ .. failed -+ return status; -+ } -+ ... access protected data -+ // unlock -+ status = CriticalSectionRelease(&pDevice->ListLock); -+ if (!SDIO_SUCCESS(status)) { -+ .. failed -+ return status; -+ } -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static inline SDIO_STATUS CriticalSectionAcquire(POS_CRITICALSECTION pCrit) { -+ call_spin_lock(pCrit); -+ return SDIO_STATUS_SUCCESS; -+} -+ -+// macro-tized versions -+#define CriticalSectionAcquire_M(pCrit) \ -+ SDIO_STATUS_SUCCESS; call_spin_lock(pCrit) -+#define CriticalSectionRelease_M(pCrit) \ -+ SDIO_STATUS_SUCCESS; call_spin_unlock(pCrit) -+ -+#define CT_DECLARE_IRQ_SYNC_CONTEXT() unsigned long _ctSyncFlags -+ -+#define CriticalSectionAcquireSyncIrq(pCrit) \ -+ SDIO_STATUS_SUCCESS; call_spin_lock_irqsave(pCrit,_ctSyncFlags) -+ -+#define CriticalSectionReleaseSyncIrq(pCrit) \ -+ SDIO_STATUS_SUCCESS; call_spin_unlock_irqrestore(pCrit,_ctSyncFlags) -+ -+ -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Release a critical section lock. -+ -+ @function name: CriticalSectionRelease -+ @prototype: SDIO_STATUS CriticalSectionRelease(POS_CRITICALSECTION pCrit) -+ @category: Support_Reference -+ -+ @input: pCrit - pointer to critical section that was initialized -+ -+ @return: SDIO_STATUS_SUCCESS on success. -+ -+ @notes: The critical section lock is released when this function returns -+ SDIO_STATUS_SUCCESS. -+ -+ @see also: CriticalSectionAcquire -+ -+ @example: see CriticalSectionAcquire -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static inline SDIO_STATUS CriticalSectionRelease(POS_CRITICALSECTION pCrit) { -+ call_spin_unlock(pCrit); -+ return SDIO_STATUS_SUCCESS; -+} -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Cleanup a critical section object -+ -+ @function name: CriticalSectionDelete -+ @prototype: void CriticalSectionDelete(POS_CRITICALSECTION pCrit) -+ @category: Support_Reference -+ -+ @input: pCrit - an initialized critical section object -+ -+ @return: SDIO_STATUS_SUCCESS on success. -+ -+ @notes: -+ -+ @see also: CriticalSectionInit, CriticalSectionAcquire, CriticalSectionRelease -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static inline void CriticalSectionDelete(POS_CRITICALSECTION pCrit) { -+ return; -+} -+ -+/* internal use */ -+static inline SDIO_STATUS SignalInitialize(POS_SIGNAL pSignal) { -+ sema_init(pSignal, 0); -+ return SDIO_STATUS_SUCCESS; -+} -+/* internal use */ -+static inline void SignalDelete(POS_SIGNAL pSignal) { -+ return; -+} -+/* internal use */ -+static inline SDIO_STATUS SignalWaitInterruptible(POS_SIGNAL pSignal) { -+ DBG_ASSERT_WITH_MSG(!NonSchedulable(),"SignalWaitInterruptible not allowed\n"); -+ if (down_interruptible(pSignal) == 0) { -+ return SDIO_STATUS_SUCCESS; -+ } else { -+ return SDIO_STATUS_INTERRUPTED; -+ } -+} -+/* internal use */ -+static inline SDIO_STATUS SignalWait(POS_SIGNAL pSignal) { -+ DBG_ASSERT_WITH_MSG(!NonSchedulable(),"SignalWait not allowed\n"); -+ down(pSignal); -+ return SDIO_STATUS_SUCCESS; -+} -+ -+/* internal use */ -+static inline SDIO_STATUS SignalSet(POS_SIGNAL pSignal) { -+ up(pSignal); -+ return SDIO_STATUS_SUCCESS; -+} -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Initialize a semaphore object. -+ -+ @function name: SemaphoreInitialize -+ @prototype: SDIO_STATUS SemaphoreInitialize(POS_SEMAPHORE pSem, UINT value) -+ @category: Support_Reference -+ -+ @input: value - initial value of the semaphore -+ -+ @output: pSem - pointer to a semaphore object to initialize -+ -+ @return: SDIO_STATUS_SUCCESS on success. -+ -+ @notes: SemaphoreDelete() must be called to cleanup any resources -+ associated with the semaphore -+ -+ @see also: SemaphoreDelete, SemaphorePend, SemaphorePendInterruptable -+ -+ @example: To initialize a semaphore: -+ status = SemaphoreInitialize(&pDevice->ResourceSem,1); -+ if (!SDIO_SUCCESS(status)) { -+ .. failed -+ return status; -+ } -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static inline SDIO_STATUS SemaphoreInitialize(POS_SEMAPHORE pSem, UINT value) { -+ sema_init(pSem, value); -+ return SDIO_STATUS_SUCCESS; -+} -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Cleanup a semaphore object. -+ -+ @function name: SemaphoreDelete -+ @prototype: void SemaphoreDelete(POS_SEMAPHORE pSem) -+ @category: Support_Reference -+ -+ @input: pSem - pointer to a semaphore object to cleanup -+ -+ @return: -+ -+ @notes: -+ -+ @see also: SemaphoreInitialize -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static inline void SemaphoreDelete(POS_SEMAPHORE pSem) { -+ return; -+} -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Acquire the semaphore or pend if the resource is not available -+ -+ @function name: SemaphorePend -+ @prototype: SDIO_STATUS SemaphorePend(POS_SEMAPHORE pSem) -+ @category: Support_Reference -+ -+ @input: pSem - pointer to an initialized semaphore object -+ -+ @return: SDIO_STATUS_SUCCESS on success. -+ -+ @notes: If the semaphore count is zero this function blocks until the count -+ becomes non-zero, otherwise the count is decremented and execution -+ continues. While waiting, the task/thread cannot be interrupted. -+ If the task or thread should be interruptible, use SemaphorePendInterruptible. -+ On some OSes SemaphorePend and SemaphorePendInterruptible behave the same. -+ -+ @see also: SemaphorePendInterruptable, SemaphorePost -+ @example: To wait for a resource using a semaphore: -+ status = SemaphorePend(&pDevice->ResourceSem); -+ if (!SDIO_SUCCESS(status)) { -+ .. failed -+ return status; -+ } -+ ... resource acquired -+ SemaphorePost(&pDevice->ResourceSem); -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static inline SDIO_STATUS SemaphorePend(POS_SEMAPHORE pSem) { -+ DBG_ASSERT_WITH_MSG(!NonSchedulable(),"SemaphorePend not allowed\n"); -+ down(pSem); -+ return SDIO_STATUS_SUCCESS; -+} -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Acquire the semaphore or pend if the resource is not available -+ -+ @function name: SemaphorePendInterruptable -+ @prototype: SDIO_STATUS SemaphorePendInterruptable(POS_SEMAPHORE pSem) -+ @category: Support_Reference -+ -+ @input: pSem - pointer to an initialized semaphore object -+ -+ @return: SDIO_STATUS_SUCCESS on success. -+ -+ @notes: If the semaphore count is zero this function blocks until the count -+ becomes non-zero, otherwise the count is decremented and execution -+ continues. While waiting, the task/thread can be interrupted. -+ If the task or thread should not be interruptible, use SemaphorePend. -+ -+ @see also: SemaphorePend, SemaphorePost -+ @example: To wait for a resource using a semaphore: -+ status = SemaphorePendInterruptable(&pDevice->ResourceSem); -+ if (!SDIO_SUCCESS(status)) { -+ .. failed, could have been interrupted -+ return status; -+ } -+ ... resource acquired -+ SemaphorePost(&pDevice->ResourceSem); -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static inline SDIO_STATUS SemaphorePendInterruptable(POS_SEMAPHORE pSem) { -+ DBG_ASSERT_WITH_MSG(!NonSchedulable(),"SemaphorePendInterruptable not allowed\n"); -+ if (down_interruptible(pSem) == 0) { -+ return SDIO_STATUS_SUCCESS; -+ } else { -+ return SDIO_STATUS_INTERRUPTED; -+ } -+} -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Post a semaphore. -+ -+ @function name: SemaphorePost -+ @prototype: SDIO_STATUS SemaphorePost(POS_SEMAPHORE pSem) -+ @category: Support_Reference -+ -+ @input: pSem - pointer to an initialized semaphore object -+ -+ @return: SDIO_STATUS_SUCCESS on success. -+ -+ @notes: This function increments the semaphore count. -+ -+ @see also: SemaphorePend, SemaphorePendInterruptable. -+ @example: Posting a semaphore: -+ status = SemaphorePendInterruptable(&pDevice->ResourceSem); -+ if (!SDIO_SUCCESS(status)) { -+ .. failed, could have been interrupted -+ return status; -+ } -+ ... resource acquired -+ // post the semaphore -+ SemaphorePost(&pDevice->ResourceSem); -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static inline SDIO_STATUS SemaphorePost(POS_SEMAPHORE pSem) { -+ DBG_ASSERT_WITH_MSG(!NonSchedulable(),"SemaphorePost not allowed\n"); -+ up(pSem); -+ return SDIO_STATUS_SUCCESS; -+} -+ -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Allocate a block of kernel accessible memory -+ -+ @function name: KernelAlloc -+ @prototype: PVOID KernelAlloc(UINT size) -+ @category: Support_Reference -+ -+ @input: size - size of memory block to allocate -+ -+ @return: pointer to the allocated memory, NULL if allocation failed -+ -+ @notes: For operating systems that use paging, the allocated memory is always -+ non-paged memory. Caller should only use KernelFree() to release the -+ block of memory. This call can potentially block and should only be called -+ from a schedulable context. Use KernelAllocIrqSafe() if the allocation -+ must be made from a non-schedulable context. -+ -+ @see also: KernelFree, KernelAllocIrqSafe -+ @example: allocating memory: -+ pBlock = KernelAlloc(1024); -+ if (pBlock == NULL) { -+ .. failed, no memory -+ return SDIO_STATUS_INSUFFICIENT_RESOURCES; -+ } -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static inline PVOID KernelAlloc(UINT size) { -+ PVOID pMem = kmalloc(size, GFP_KERNEL); -+ if (pMem != NULL) { memset(pMem,0,size); } -+ return pMem; -+} -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Free a block of kernel accessible memory. -+ -+ @function name: KernelFree -+ @prototype: void KernelFree(PVOID ptr) -+ @category: Support_Reference -+ -+ @input: ptr - pointer to memory allocated with KernelAlloc() -+ -+ @return: -+ -+ @notes: Caller should only use KernelFree() to release memory that was allocated -+ with KernelAlloc(). -+ -+ @see also: KernelAlloc -+ @example: KernelFree(pBlock); -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static inline void KernelFree(PVOID ptr) { -+ kfree(ptr); -+} -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Allocate a block of kernel accessible memory in an IRQ-safe manner -+ -+ @function name: KernelAllocIrqSafe -+ @prototype: PVOID KernelAllocIrqSafe(UINT size) -+ @category: Support_Reference -+ -+ @input: size - size of memory block to allocate -+ -+ @return: pointer to the allocated memory, NULL if allocation failed -+ -+ @notes: This variant of KernelAlloc allows the allocation of small blocks of -+ memory from an ISR or from a context where scheduling has been disabled. -+ The allocations should be small as the memory is typically allocated -+ from a critical heap. The caller should only use KernelFreeIrqSafe() -+ to release the block of memory. -+ -+ @see also: KernelAlloc, KernelFreeIrqSafe -+ @example: allocating memory: -+ pBlock = KernelAllocIrqSafe(16); -+ if (pBlock == NULL) { -+ .. failed, no memory -+ return SDIO_STATUS_INSUFFICIENT_RESOURCES; -+ } -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static inline PVOID KernelAllocIrqSafe(UINT size) { -+ return kmalloc(size, GFP_ATOMIC); -+} -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Free a block of kernel accessible memory. -+ -+ @function name: KernelFreeIrqSafe -+ @prototype: void KernelFreeIrqSafe(PVOID ptr) -+ @category: Support_Reference -+ -+ @input: ptr - pointer to memory allocated with KernelAllocIrqSafe() -+ -+ @return: -+ -+ @notes: Caller should only use KernelFreeIrqSafe() to release memory that was allocated -+ with KernelAllocIrqSafe(). -+ -+ @see also: KernelAllocIrqSafe -+ @example: KernelFreeIrqSafe(pBlock); -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static inline void KernelFreeIrqSafe(PVOID ptr) { -+ kfree(ptr); -+} -+ -+/* error status conversions */ -+static inline SYSTEM_STATUS SDIOErrorToOSError(SDIO_STATUS status) { -+ switch (status) { -+ case SDIO_STATUS_SUCCESS: -+ return 0; -+ case SDIO_STATUS_INVALID_PARAMETER: -+ return -EINVAL; -+ case SDIO_STATUS_PENDING: -+ return -EAGAIN; /* try again */ -+ case SDIO_STATUS_DEVICE_NOT_FOUND: -+ return -ENXIO; -+ case SDIO_STATUS_DEVICE_ERROR: -+ return -EIO; -+ case SDIO_STATUS_INTERRUPTED: -+ return -EINTR; -+ case SDIO_STATUS_NO_RESOURCES: -+ return -ENOMEM; -+ case SDIO_STATUS_ERROR: -+ default: -+ return -EFAULT; -+ } -+} -+static inline SDIO_STATUS OSErrorToSDIOError(SYSTEM_STATUS status) { -+ if (status >=0) { -+ return SDIO_STATUS_SUCCESS; -+ } -+ switch (status) { -+ case -EINVAL: -+ return SDIO_STATUS_INVALID_PARAMETER; -+ case -ENXIO: -+ return SDIO_STATUS_DEVICE_NOT_FOUND; -+ case -EIO: -+ return SDIO_STATUS_DEVICE_ERROR; -+ case -EINTR: -+ return SDIO_STATUS_INTERRUPTED; -+ case -ENOMEM: -+ return SDIO_STATUS_NO_RESOURCES; -+ case -EFAULT: -+ return SDIO_STATUS_ERROR; -+ default: -+ return SDIO_STATUS_ERROR; -+ } -+} -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Sleep or delay the execution context for a number of milliseconds. -+ -+ @function name: OSSleep -+ @prototype: SDIO_STATUS OSSleep(INT SleepInterval) -+ @category: Support_Reference -+ -+ @input: SleepInterval - time in milliseconds to put the execution context to sleep -+ -+ @return: SDIO_STATUS_SUCCESS if sleep succeeded. -+ -+ @notes: Caller should be in a context that allows it to sleep or block. The -+ minimum duration of sleep may be greater than 1 MS on some platforms and OSes. -+ -+ @see also: OSSleep -+ @example: Using sleep to delay -+ EnableSlotPower(pSlot); -+ // wait for power to settle -+ status = OSSleep(100); -+ if (!SDIO_SUCCESS(status)){ -+ // failed.. -+ } -+ -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static inline SDIO_STATUS OSSleep(INT SleepInterval) { -+ UINT32 delta; -+ -+ DBG_ASSERT_WITH_MSG(!NonSchedulable(),"OSSleep not allowed\n"); -+ /* convert timeout to ticks */ -+ delta = (SleepInterval * HZ)/1000; -+ if (delta == 0) { -+ delta = 1; -+ } -+ set_current_state(TASK_INTERRUPTIBLE); -+ if (schedule_timeout(delta) != 0) { -+ return SDIO_STATUS_INTERRUPTED; -+ } -+ return SDIO_STATUS_SUCCESS; -+} -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: get the OSs device object -+ -+ @function name: SD_GET_OS_DEVICE -+ @prototype: POS_DEVICE SD_GET_OS_DEVICE(PSDDEVICE pDevice) -+ @category: Support_Reference -+ -+ @input: pDevice - the device on the HCD -+ -+ @return: pointer to the OSs device -+ -+ @see also: -+ @example: obtain low level device -+ pFunctionContext->GpsDevice.Port.dev = SD_GET_OS_DEVICE(pDevice); -+ -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SD_GET_OS_DEVICE(pDevice) &((pDevice)->Device.dev) -+ -+ -+#ifdef __iomem -+ /* new type checking in 2.6.9 */ -+ /* I/O Access macros */ -+#define _READ_DWORD_REG(reg) \ -+ readl((const volatile void __iomem *)(reg)) -+#define _READ_WORD_REG(reg) \ -+ readw((const volatile void __iomem *)(reg)) -+#define _READ_BYTE_REG(reg) \ -+ readb((const volatile void __iomem *)(reg)) -+#define _WRITE_DWORD_REG(reg,value) \ -+ writel((value),(volatile void __iomem *)(reg)) -+#define _WRITE_WORD_REG(reg,value) \ -+ writew((value),(volatile void __iomem *)(reg)) -+#define _WRITE_BYTE_REG(reg,value) \ -+ writeb((value),(volatile void __iomem *)(reg)) -+#else -+ /* I/O Access macros */ -+#define _READ_DWORD_REG(reg) \ -+ readl((reg)) -+#define _READ_WORD_REG(reg) \ -+ readw((reg)) -+#define _READ_BYTE_REG(reg) \ -+ readb((reg)) -+#define _WRITE_DWORD_REG(reg,value) \ -+ writel((value),(reg)) -+#define _WRITE_WORD_REG(reg,value) \ -+ writew((value),(reg)) -+#define _WRITE_BYTE_REG(reg,value) \ -+ writeb((value),(reg)) -+#endif -+ /* atomic operators */ -+static inline ATOMIC_FLAGS AtomicTest_Set(volatile ATOMIC_FLAGS *pValue, INT BitNo) { -+ return test_and_set_bit(BitNo,(ATOMIC_FLAGS *)pValue); -+} -+static inline ATOMIC_FLAGS AtomicTest_Clear(volatile ATOMIC_FLAGS *pValue, INT BitNo) { -+ return test_and_clear_bit(BitNo,(ATOMIC_FLAGS *)pValue); -+} -+ -+struct _OSKERNEL_HELPER; -+ -+typedef THREAD_RETURN (*PHELPER_FUNCTION)(struct _OSKERNEL_HELPER *); -+ -+typedef struct _OSKERNEL_HELPER { -+ PKERNEL_TASK pTask; -+ BOOL ShutDown; -+ OS_SIGNAL WakeSignal; -+ struct completion Completion; -+ PVOID pContext; -+ PHELPER_FUNCTION pHelperFunc; -+}OSKERNEL_HELPER, *POSKERNEL_HELPER; -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Wake the helper thread -+ -+ @function name: SD_WAKE_OS_HELPER -+ @prototype: SD_WAKE_OS_HELPER(POSKERNEL_HELPER pOSHelper) -+ @category: Support_Reference -+ -+ @input: pOSHelper - the OS helper object -+ -+ @return: SDIO_STATUS -+ -+ @see also: SDLIB_OSCreateHelper -+ -+ @example: Waking up a helper thread -+ status = SD_WAKE_OS_HELPER(&pInstance->OSHelper); -+ -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SD_WAKE_OS_HELPER(p) SignalSet(&(p)->WakeSignal) -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Obtains the context for the helper function -+ -+ @function name: SD_GET_OS_HELPER_CONTEXT -+ @prototype: SD_GET_OS_HELPER_CONTEXT(POSKERNEL_HELPER pOSHelper) -+ @category: Support_Reference -+ -+ @input: pOSHelper - the OS helper object -+ -+ @return: helper specific context -+ -+ @notes: This macro should only be called by the function associated with -+ the helper object. -+ -+ @see also: SDLIB_OSCreateHelper -+ -+ @example: Getting the helper specific context -+ PMYCONTEXT pContext = (PMYCONTEXT)SD_GET_OS_HELPER_CONTEXT(pHelper); -+ -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SD_GET_OS_HELPER_CONTEXT(p) (p)->pContext -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Check helper function shut down flag. -+ -+ @function name: SD_IS_HELPER_SHUTTING_DOWN -+ @prototype: SD_IS_HELPER_SHUTTING_DOWN(POSKERNEL_HELPER pOSHelper) -+ @category: Support_Reference -+ -+ @input: pOSHelper - the OS helper object -+ -+ @return: TRUE if shutting down, else FALSE -+ -+ @notes: This macro should only be called by the function associated with -+ the helper object. The function should call this macro when it -+ unblocks from the call to SD_WAIT_FOR_WAKEUP(). If this function -+ returns TRUE, the function should clean up and exit. -+ -+ @see also: SDLIB_OSCreateHelper , SD_WAIT_FOR_WAKEUP -+ -+ @example: Checking for shutdown -+ while(1) { -+ status = SD_WAIT_FOR_WAKEUP(pHelper); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ if (SD_IS_HELPER_SHUTTING_DOWN(pHelper)) { -+ ... shutting down -+ break; -+ } -+ } -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SD_IS_HELPER_SHUTTING_DOWN(p) (p)->ShutDown -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Suspend and wait for wakeup signal -+ -+ @function name: SD_WAIT_FOR_WAKEUP -+ @prototype: SD_WAIT_FOR_WAKEUP(POSKERNEL_HELPER pOSHelper) -+ @category: Support_Reference -+ -+ @input: pOSHelper - the OS helper object -+ -+ @return: SDIO_STATUS -+ -+ @notes: This macro should only be called by the function associated with -+ the helper object. The function should call this function to suspend (block) -+ itself and wait for a wake up signal. The function should always check -+ whether the function should exit by calling SD_IS_HELPER_SHUTTING_DOWN. -+ -+ @see also: SDLIB_OSCreateHelper , SD_IS_HELPER_SHUTTING_DOWN -+ -+ @example: block on the wake signal -+ while(1) { -+ status = SD_WAIT_FOR_WAKEUP(pHelper); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ if (SD_IS_HELPER_SHUTTING_DOWN(pHelper)) { -+ ... shutting down -+ break; -+ } -+ } -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SD_WAIT_FOR_WAKEUP(p) SignalWait(&(p)->WakeSignal); -+ -+#define CT_LE16_TO_CPU_ENDIAN(x) __le16_to_cpu(x) -+#define CT_LE32_TO_CPU_ENDIAN(x) __le32_to_cpu(x) -+#define CT_CPU_ENDIAN_TO_LE16(x) __cpu_to_le16(x) -+#define CT_CPU_ENDIAN_TO_LE32(x) __cpu_to_le32(x) -+ -+#define CT_CPU_ENDIAN_TO_BE16(x) __cpu_to_be16(x) -+#define CT_CPU_ENDIAN_TO_BE32(x) __cpu_to_be32(x) -+#define CT_BE16_TO_CPU_ENDIAN(x) __be16_to_cpu(x) -+#define CT_BE32_TO_CPU_ENDIAN(x) __be32_to_cpu(x) -+#endif /* __CPSYSTEM_LINUX_H___ */ -+ -diff --git a/include/linux/sdio/mmc_defs.h b/include/linux/sdio/mmc_defs.h -new file mode 100644 -index 0000000..576ebd7 ---- /dev/null -+++ b/include/linux/sdio/mmc_defs.h -@@ -0,0 +1,103 @@ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+@file: mmc_defs.h -+ -+@abstract: MMC definitions not already defined in _sdio_defs.h -+ -+@notice: Copyright (c), 2004-2006 Atheros Communications, Inc. -+ -+ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * Software distributed under the License is distributed on an "AS -+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -+ * implied. See the License for the specific language governing -+ * rights and limitations under the License. -+ * -+ * Portions of this code were developed with information supplied from the -+ * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply: -+ * -+ * The following conditions apply to the release of the SD simplified specification (�Simplified -+ * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete -+ * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided -+ * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified -+ * Specification may require a license from the SD Card Association or other third parties. -+ * Disclaimers: -+ * The information contained in the Simplified Specification is presented only as a standard -+ * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any -+ * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for -+ * any damages, any infringements of patents or other right of the SD Card Association or any third -+ * parties, which may result from its use. No license is granted by implication, estoppel or otherwise -+ * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall -+ * be construed as an obligation by the SD Card Association to disclose or distribute any technical -+ * information, know-how or other confidential information to any third party. -+ * -+ * -+ * The initial developers of the original code are Seung Yi and Paul Lever -+ * -+ * sdio@atheros.com -+ * -+ * -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#ifndef ___MMC_DEFS_H___ -+#define ___MMC_DEFS_H___ -+ -+#define MMC_MAX_BUS_CLOCK 20000000 /* max clock speed in hz */ -+#define MMC_HS_MAX_BUS_CLOCK 52000000 /* MMC PLUS (high speed) max clock rate in hz */ -+ -+/* R2 (CSD) macros */ -+#define GET_MMC_CSD_TRANS_SPEED(pR) (pR)[12] -+#define GET_MMC_SPEC_VERSION(pR) (((pR)[15] >> 2) & 0x0F) -+#define MMC_SPEC_1_0_TO_1_2 0x00 -+#define MMC_SPEC_1_4 0x01 -+#define MMC_SPEC_2_0_TO_2_2 0x02 -+#define MMC_SPEC_3_1 0x03 -+#define MMC_SPEC_4_0_TO_4_1 0x04 -+ -+#define MMC_CMD_SWITCH 6 -+#define MMC_CMD8 8 -+ -+#define MMC_SWITCH_CMD_SET 0 -+#define MMC_SWITCH_SET_BITS 1 -+#define MMC_SWITCH_CLEAR_BITS 2 -+#define MMC_SWITCH_WRITE_BYTE 3 -+#define MMC_SWITCH_CMD_SET0 0 -+#define MMC_SWITCH_BUILD_ARG(cmdset,access,index,value) \ -+ (((cmdset) & 0x07) | (((access) & 0x03) << 24) | (((index) & 0xFF) << 16) | (((value) & 0xFF) << 8)) -+ -+#define MMC_EXT_CSD_SIZE 512 -+ -+#define MMC_EXT_S_CMD_SET_OFFSET 504 -+#define MMC_EXT_MIN_PERF_W_8_52_OFFSET 210 -+#define MMC_EXT_MIN_PERF_R_8_52_OFFSET 209 -+#define MMC_EXT_MIN_PERF_W_8_26_4_52_OFFSET 208 -+#define MMC_EXT_MIN_PERF_R_8_26_4_52_OFFSET 207 -+#define MMC_EXT_MIN_PERF_W_4_26_OFFSET 206 -+#define MMC_EXT_MIN_PERF_R_4_56_OFFSET 205 -+#define MMC_EXT_PWR_CL_26_360_OFFSET 203 -+#define MMC_EXT_PWR_CL_52_360_OFFSET 202 -+#define MMC_EXT_PWR_CL_26_195_OFFSET 201 -+#define MMC_EXT_PWR_CL_52_195_OFFSET 200 -+#define MMC_EXT_GET_PWR_CLASS(reg) ((reg) & 0xF) -+#define MMC_EXT_MAX_PWR_CLASSES 16 -+#define MMC_EXT_CARD_TYPE_OFFSET 196 -+#define MMC_EXT_CARD_TYPE_HS_52 (1 << 1) -+#define MMC_EXT_CARD_TYPE_HS_26 (1 << 0) -+#define MMC_EXT_CSD_VER_OFFSET 194 -+#define MMC_EXT_VER_OFFSET 192 -+#define MMC_EXT_VER_1_0 0 -+#define MMC_EXT_VER_1_1 1 -+#define MMC_EXT_CMD_SET_OFFSET 191 -+#define MMC_EXT_CMD_SET_REV_OFFSET 189 -+#define MMC_EXT_PWR_CLASS_OFFSET 187 -+#define MMC_EXT_HS_TIMING_OFFSET 185 -+#define MMC_EXT_HS_TIMING_ENABLE 0x01 -+#define MMC_EXT_BUS_WIDTH_OFFSET 183 -+#define MMC_EXT_BUS_WIDTH_1_BIT 0x00 -+#define MMC_EXT_BUS_WIDTH_4_BIT 0x01 -+#define MMC_EXT_BUS_WIDTH_8_BIT 0x02 -+ -+#endif -diff --git a/include/linux/sdio/sdio_busdriver.h b/include/linux/sdio/sdio_busdriver.h -new file mode 100644 -index 0000000..b431d3d ---- /dev/null -+++ b/include/linux/sdio/sdio_busdriver.h -@@ -0,0 +1,1435 @@ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+@file: sdio_busdriver.h -+ -+@abstract: include file for registration of SDIO function drivers -+ and SDIO host controller bus drivers. -+ -+@notice: Copyright (c), 2004-2006 Atheros Communications, Inc. -+ -+ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * Software distributed under the License is distributed on an "AS -+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -+ * implied. See the License for the specific language governing -+ * rights and limitations under the License. -+ * -+ * Portions of this code were developed with information supplied from the -+ * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply: -+ * -+ * The following conditions apply to the release of the SD simplified specification (�Simplified -+ * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete -+ * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided -+ * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified -+ * Specification may require a license from the SD Card Association or other third parties. -+ * Disclaimers: -+ * The information contained in the Simplified Specification is presented only as a standard -+ * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any -+ * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for -+ * any damages, any infringements of patents or other right of the SD Card Association or any third -+ * parties, which may result from its use. No license is granted by implication, estoppel or otherwise -+ * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall -+ * be construed as an obligation by the SD Card Association to disclose or distribute any technical -+ * information, know-how or other confidential information to any third party. -+ * -+ * -+ * The initial developers of the original code are Seung Yi and Paul Lever -+ * -+ * sdio@atheros.com -+ * -+ * -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#ifndef __SDIO_BUSDRIVER_H___ -+#define __SDIO_BUSDRIVER_H___ -+ -+typedef UINT8 CT_VERSION_CODE; -+#define CT_SDIO_STACK_VERSION_CODE ((CT_VERSION_CODE)0x26) /* version code that must be set in various structures */ -+#define CT_SDIO_STACK_VERSION_MAJOR(v) (((v) & 0xF0) >> 4) -+#define CT_SDIO_STACK_VERSION_MINOR(v) (((v) & 0x0F)) -+#define SET_SDIO_STACK_VERSION(p) (p)->Version = CT_SDIO_STACK_VERSION_CODE -+#define GET_SDIO_STACK_VERSION(p) (p)->Version -+#define GET_SDIO_STACK_VERSION_MAJOR(p) CT_SDIO_STACK_VERSION_MAJOR(GET_SDIO_STACK_VERSION(p)) -+#define GET_SDIO_STACK_VERSION_MINOR(p) CT_SDIO_STACK_VERSION_MINOR(GET_SDIO_STACK_VERSION(p)) -+#include "sdlist.h" -+ -+/* card flags */ -+typedef UINT16 CARD_INFO_FLAGS; -+#define CARD_MMC 0x0001 /* Multi-media card */ -+#define CARD_SD 0x0002 /* SD-Memory present */ -+#define CARD_SDIO 0x0004 /* SDIO present */ -+#define CARD_RAW 0x0008 /* Raw card */ -+#define CARD_COMBO (CARD_SD | CARD_SDIO) /* SDIO with SD */ -+#define CARD_TYPE_MASK 0x000F /* card type mask */ -+#define CARD_SD_WP 0x0010 /* SD WP on */ -+#define CARD_PSEUDO 0x0020 /* pseudo card (internal use) */ -+#define CARD_HIPWR 0x0040 /* card can use more than 200mA (SDIO 1.1 or greater)*/ -+#define GET_CARD_TYPE(flags) ((flags) & CARD_TYPE_MASK) -+ -+/* bus mode and clock rate */ -+typedef UINT32 SD_BUSCLOCK_RATE; /* clock rate in hz */ -+typedef UINT16 SD_BUSMODE_FLAGS; -+#define SDCONFIG_BUS_WIDTH_RESERVED 0x00 -+#define SDCONFIG_BUS_WIDTH_SPI 0x01 -+#define SDCONFIG_BUS_WIDTH_1_BIT 0x02 -+#define SDCONFIG_BUS_WIDTH_4_BIT 0x03 -+#define SDCONFIG_BUS_WIDTH_MMC8_BIT 0x04 -+#define SDCONFIG_BUS_WIDTH_MASK 0x0F -+#define SDCONFIG_SET_BUS_WIDTH(flags,width) \ -+{ \ -+ (flags) &= ~SDCONFIG_BUS_WIDTH_MASK; \ -+ (flags) |= (width); \ -+} -+#define SDCONFIG_GET_BUSWIDTH(flags) ((flags) & SDCONFIG_BUS_WIDTH_MASK) -+#define SDCONFIG_BUS_MODE_SPI_NO_CRC 0x40 /* SPI bus is operating with NO CRC */ -+#define SDCONFIG_BUS_MODE_SD_HS 0x80 /* set interface to SD high speed mode */ -+#define SDCONFIG_BUS_MODE_MMC_HS 0x20 /* set interface to MMC high speed mode */ -+ -+typedef UINT16 SD_SLOT_CURRENT; /* slot current in mA */ -+ -+typedef UINT8 SLOT_VOLTAGE_MASK; /* slot voltage */ -+#define SLOT_POWER_3_3V 0x01 -+#define SLOT_POWER_3_0V 0x02 -+#define SLOT_POWER_2_8V 0x04 -+#define SLOT_POWER_2_0V 0x08 -+#define SLOT_POWER_1_8V 0x10 -+#define SLOT_POWER_1_6V 0x20 -+ -+#define MAX_CARD_RESPONSE_BYTES 17 -+ -+/* plug and play information for SD cards */ -+typedef struct _SD_PNP_INFO { -+ UINT16 SDIO_ManufacturerCode; /* JEDEC Code */ -+ UINT16 SDIO_ManufacturerID; /* manf-specific ID */ -+ UINT8 SDIO_FunctionNo; /* function number 1-7 */ -+ UINT8 SDIO_FunctionClass; /* function class */ -+ UINT8 SDMMC_ManfacturerID; /* card CID's MANF-ID */ -+ UINT16 SDMMC_OEMApplicationID; /* card CID's OEMAPP-ID */ -+ CARD_INFO_FLAGS CardFlags; /* card flags */ -+}SD_PNP_INFO, *PSD_PNP_INFO; -+ -+#define IS_LAST_SDPNPINFO_ENTRY(id)\ -+ (((id)->SDIO_ManufacturerCode == 0) &&\ -+ ((id)->SDIO_ManufacturerID == 0) &&\ -+ ((id)->SDIO_FunctionNo == 0) &&\ -+ ((id)->SDIO_FunctionClass == 0) &&\ -+ ((id)->SDMMC_OEMApplicationID == 0) && \ -+ ((id)->CardFlags == 0)) -+ -+/* card properties */ -+typedef struct _CARD_PROPERTIES { -+ UINT8 IOFnCount; /* number of I/O functions */ -+ UINT8 SDIORevision; /* SDIO revision */ -+#define SDIO_REVISION_1_00 0x00 -+#define SDIO_REVISION_1_10 0x01 -+#define SDIO_REVISION_1_20 0x02 -+ UINT8 SD_MMC_Revision; /* SD or MMC revision */ -+#define SD_REVISION_1_01 0x00 -+#define SD_REVISION_1_10 0x01 -+#define MMC_REVISION_1_0_2_2 0x00 -+#define MMC_REVISION_3_1 0x01 -+#define MMC_REVISION_4_0 0x02 -+ UINT16 SDIO_ManufacturerCode; /* JEDEC Code */ -+ UINT16 SDIO_ManufacturerID; /* manf-specific ID */ -+ UINT32 CommonCISPtr; /* common CIS ptr */ -+ UINT16 RCA; /* relative card address */ -+ UINT8 SDIOCaps; /* SDIO card capabilities (refer to SDIO spec for decoding) */ -+ UINT8 CardCSD[MAX_CARD_RESPONSE_BYTES]; /* for SD/MMC cards */ -+ CARD_INFO_FLAGS Flags; /* card flags */ -+ SD_BUSCLOCK_RATE OperBusClock; /* operational bus clock (based on HCD limit)*/ -+ SD_BUSMODE_FLAGS BusMode; /* current card bus mode */ -+ UINT16 OperBlockLenLimit; /* operational bytes per block length limit*/ -+ UINT16 OperBlockCountLimit; /* operational number of blocks per transfer limit */ -+ UINT8 CardState; /* card state flags */ -+ SLOT_VOLTAGE_MASK CardVoltage; /* card operational voltage */ -+#define CARD_STATE_REMOVED 0x01 -+}CARD_PROPERTIES, *PCARD_PROPERTIES; -+ -+/* SDREQUEST request flags */ -+typedef UINT32 SDREQUEST_FLAGS; -+/* write operation */ -+#define SDREQ_FLAGS_DATA_WRITE 0x8000 -+/* has data (read or write) */ -+#define SDREQ_FLAGS_DATA_TRANS 0x4000 -+/* command is an atomic APP command, requiring CMD55 to be issued */ -+#define SDREQ_FLAGS_APP_CMD 0x2000 -+/* transfer should be handled asynchronously */ -+#define SDREQ_FLAGS_TRANS_ASYNC 0x1000 -+/* host should skip the SPI response filter for this command */ -+#define SDREQ_FLAGS_RESP_SKIP_SPI_FILT 0x0800 -+/* host should skip the response check for this data transfer */ -+#define SDREQ_FLAGS_DATA_SKIP_RESP_CHK 0x0400 -+/* flag requesting a CMD12 be automatically issued by host controller */ -+#define SDREQ_FLAGS_AUTO_CMD12 0x0200 -+/* flag indicating that the data buffer meets HCD's DMA restrictions */ -+#define SDREQ_FLAGS_DATA_DMA 0x0010 -+/* indicate to host that this is a short and quick transfer, the HCD may optimize -+ * this request to reduce interrupt overhead */ -+#define SDREQ_FLAGS_DATA_SHORT_TRANSFER 0x00010000 -+/* indicate to the host that this is a raw request */ -+#define SDREQ_FLAGS_RAW 0x00020000 -+/* auto data transfer status check for MMC and Memory cards */ -+#define SDREQ_FLAGS_AUTO_TRANSFER_STATUS 0x00100000 -+ -+#define SDREQ_FLAGS_UNUSED1 0x00200000 -+#define SDREQ_FLAGS_UNUSED2 0x00400000 -+#define SDREQ_FLAGS_UNUSED3 0x00800000 -+#define SDREQ_FLAGS_UNUSED4 0x01000000 -+#define SDREQ_FLAGS_UNUSED5 0x02000000 -+ -+/* the following flags are internal use only */ -+#define SDREQ_FLAGS_FORCE_DEFERRED_COMPLETE 0x0100 -+/* flag indicating that response has been converted (internal use) */ -+#define SDREQ_FLAGS_RESP_SPI_CONVERTED 0x0040 -+/* request was cancelled - internal use only */ -+#define SDREQ_FLAGS_CANCELED 0x0020 -+/* a barrier operation */ -+#define SDREQ_FLAGS_BARRIER 0x00040000 -+/* a pseudo bus request */ -+#define SDREQ_FLAGS_PSEUDO 0x00080000 -+/* queue to the head */ -+#define SDREQ_FLAGS_QUEUE_HEAD 0x04000000 -+ -+#define SDREQ_FLAGS_I_UNUSED1 0x08000000 -+#define SDREQ_FLAGS_I_UNUSED2 0x10000000 -+#define SDREQ_FLAGS_I_UNUSED3 0x20000000 -+#define SDREQ_FLAGS_I_UNUSED4 0x40000000 -+#define SDREQ_FLAGS_I_UNUSED5 0x80000000 -+ -+/* response type mask */ -+#define SDREQ_FLAGS_RESP_MASK 0x000F -+#define GET_SDREQ_RESP_TYPE(flags) ((flags) & SDREQ_FLAGS_RESP_MASK) -+#define IS_SDREQ_WRITE_DATA(flags) ((flags) & SDREQ_FLAGS_DATA_WRITE) -+#define IS_SDREQ_DATA_TRANS(flags) ((flags) & SDREQ_FLAGS_DATA_TRANS) -+#define IS_SDREQ_RAW(flags) ((flags) & SDREQ_FLAGS_RAW) -+#define IS_SDREQ_FORCE_DEFERRED_COMPLETE(flags) ((flags) & SDREQ_FLAGS_FORCE_DEFERRED_COMPLETE) -+#define SDREQ_FLAGS_NO_RESP 0x0000 -+#define SDREQ_FLAGS_RESP_R1 0x0001 -+#define SDREQ_FLAGS_RESP_R1B 0x0002 -+#define SDREQ_FLAGS_RESP_R2 0x0003 -+#define SDREQ_FLAGS_RESP_R3 0x0004 -+#define SDREQ_FLAGS_RESP_MMC_R4 0x0005 /* not supported, for future use */ -+#define SDREQ_FLAGS_RESP_MMC_R5 0x0006 /* not supported, for future use */ -+#define SDREQ_FLAGS_RESP_R6 0x0007 -+#define SDREQ_FLAGS_RESP_SDIO_R4 0x0008 -+#define SDREQ_FLAGS_RESP_SDIO_R5 0x0009 -+ -+struct _SDREQUEST; -+struct _SDFUNCTION; -+ -+typedef void (*PSDEQUEST_COMPLETION)(struct _SDREQUEST *); -+ -+/* defines SD/MMC and SDIO requests for the RAW-mode API */ -+typedef struct _SDREQUEST { -+ SDLIST SDList; /* internal use list*/ -+ UINT32 Argument; /* SD/SDIO/MMC 32 bit argument */ -+ SDREQUEST_FLAGS Flags; /* request flags */ -+ ATOMIC_FLAGS InternalFlags; /* internal use flags */ -+ UINT8 Command; /* SD/SDIO/MMC 8 bit command */ -+ UINT8 Response[MAX_CARD_RESPONSE_BYTES]; /* buffer for CMD response */ -+ UINT16 BlockCount; /* number of blocks to send/rcv */ -+ UINT16 BlockLen; /* length of each block */ -+ UINT16 DescriptorCount; /* number of DMA descriptor entries in pDataBuffer if DMA */ -+ PVOID pDataBuffer; /* starting address of buffer (or ptr to PSDDMA_DESCRIPTOR*/ -+ UINT32 DataRemaining; /* number of bytes remaining in the transfer (internal use) */ -+ PVOID pHcdContext; /* internal use context */ -+ PSDEQUEST_COMPLETION pCompletion; /* function driver completion routine */ -+ PVOID pCompleteContext; /* function driver completion context */ -+ SDIO_STATUS Status; /* completion status */ -+ struct _SDFUNCTION* pFunction; /* function driver that generated request (internal use)*/ -+ INT RetryCount; /* number of times to retry on error, non-data cmds only */ -+ PVOID pBdRsv1; /* reserved */ -+ PVOID pBdRsv2; -+ PVOID pBdRsv3; -+}SDREQUEST, *PSDREQUEST; -+ -+ /* a request queue */ -+typedef struct _SDREQUESTQUEUE { -+ SDLIST Queue; /* the queue of requests */ -+ BOOL Busy; /* busy flag */ -+}SDREQUESTQUEUE, *PSDREQUESTQUEUE; -+ -+ -+typedef UINT16 SDCONFIG_COMMAND; -+/* SDCONFIG request flags */ -+/* get operation */ -+#define SDCONFIG_FLAGS_DATA_GET 0x8000 -+/* put operation */ -+#define SDCONFIG_FLAGS_DATA_PUT 0x4000 -+/* host controller */ -+#define SDCONFIG_FLAGS_HC_CONFIG 0x2000 -+/* both */ -+#define SDCONFIG_FLAGS_DATA_BOTH (SDCONFIG_FLAGS_DATA_GET | SDCONFIG_FLAGS_DATA_PUT) -+/* no data */ -+#define SDCONFIG_FLAGS_DATA_NONE 0x0000 -+ -+/* SDCONFIG commands */ -+#define SDCONFIG_GET_HCD_DEBUG (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_GET | 275) -+#define SDCONFIG_SET_HCD_DEBUG (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_PUT | 276) -+ -+/* custom hcd commands */ -+#define SDCONFIG_GET_HOST_CUSTOM (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_GET | 300) -+#define SDCONFIG_PUT_HOST_CUSTOM (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_PUT | 301) -+ -+/* function commands */ -+#define SDCONFIG_FUNC_ENABLE_DISABLE (SDCONFIG_FLAGS_DATA_PUT | 18) -+#define SDCONFIG_FUNC_UNMASK_IRQ (SDCONFIG_FLAGS_DATA_NONE | 21) -+#define SDCONFIG_FUNC_MASK_IRQ (SDCONFIG_FLAGS_DATA_NONE | 22) -+#define SDCONFIG_FUNC_ACK_IRQ (SDCONFIG_FLAGS_DATA_NONE | 23) -+#define SDCONFIG_FUNC_SPI_MODE_DISABLE_CRC (SDCONFIG_FLAGS_DATA_NONE | 24) -+#define SDCONFIG_FUNC_SPI_MODE_ENABLE_CRC (SDCONFIG_FLAGS_DATA_NONE | 25) -+#define SDCONFIG_FUNC_ALLOC_SLOT_CURRENT (SDCONFIG_FLAGS_DATA_PUT | 26) -+#define SDCONFIG_FUNC_FREE_SLOT_CURRENT (SDCONFIG_FLAGS_DATA_NONE | 27) -+#define SDCONFIG_FUNC_CHANGE_BUS_MODE (SDCONFIG_FLAGS_DATA_BOTH | 28) -+#define SDCONFIG_FUNC_CHANGE_BUS_MODE_ASYNC (SDCONFIG_FLAGS_DATA_BOTH | 29) -+#define SDCONFIG_FUNC_NO_IRQ_PEND_CHECK (SDCONFIG_FLAGS_DATA_NONE | 30) -+ -+typedef UINT8 FUNC_ENABLE_DISABLE_FLAGS; -+typedef UINT32 FUNC_ENABLE_TIMEOUT; -+ -+ /* function enable */ -+typedef struct _SDCONFIG_FUNC_ENABLE_DISABLE_DATA { -+#define SDCONFIG_DISABLE_FUNC 0x0000 -+#define SDCONFIG_ENABLE_FUNC 0x0001 -+ FUNC_ENABLE_DISABLE_FLAGS EnableFlags; /* enable flags*/ -+ FUNC_ENABLE_TIMEOUT TimeOut; /* timeout in milliseconds */ -+ void (*pOpComplete)(PVOID Context, SDIO_STATUS status); /* reserved */ -+ PVOID pOpCompleteContext; /* reserved */ -+}SDCONFIG_FUNC_ENABLE_DISABLE_DATA, *PSDCONFIG_FUNC_ENABLE_DISABLE_DATA; -+ -+ /* slot current allocation data */ -+typedef struct _SDCONFIG_FUNC_SLOT_CURRENT_DATA { -+ SD_SLOT_CURRENT SlotCurrent; /* slot current to request in mA*/ -+}SDCONFIG_FUNC_SLOT_CURRENT_DATA, *PSDCONFIG_FUNC_SLOT_CURRENT_DATA; -+ -+/* slot bus mode configuration */ -+typedef struct _SDCONFIG_BUS_MODE_DATA { -+ SD_BUSCLOCK_RATE ClockRate; /* clock rate in Hz */ -+ SD_BUSMODE_FLAGS BusModeFlags; /* bus mode flags */ -+ SD_BUSCLOCK_RATE ActualClockRate; /* actual rate in KHz */ -+}SDCONFIG_BUS_MODE_DATA, *PSDCONFIG_BUS_MODE_DATA; -+ -+/* defines configuration requests for the HCD */ -+typedef struct _SDCONFIG { -+ SDCONFIG_COMMAND Cmd; /* configuration command */ -+ PVOID pData; /* configuration data */ -+ INT DataLength; /* config data length */ -+}SDCONFIG, *PSDCONFIG; -+ -+#define SET_SDCONFIG_CMD_INFO(pHdr,cmd,pC,len) \ -+{ \ -+ (pHdr)->Cmd = (cmd); \ -+ (pHdr)->pData = (PVOID)(pC); \ -+ (pHdr)->DataLength = (len); \ -+} -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get a pointer to the configuration command data. -+ -+ @function name: GET_SDCONFIG_CMD -+ @prototype: UNIT16 GET_SDCONFIG_CMD (PSDCONFIG pCommand) -+ @category: HD_Reference -+ -+ @input: pCommand - config command structure. -+ -+ @return: command code -+ -+ @notes: Implemented as a macro. This macro returns the command code for this -+ configuration request. -+ -+ @example: getting the command code: -+ cmd = GET_SDCONFIG_CMD(pConfig); -+ switch (cmd) { -+ case SDCONFIG_GET_WP: -+ .. get write protect switch position -+ break; -+ ... -+ } -+ -+ @see also: GET_SDCONFIG_CMD_LEN, GET_SDCONFIG_CMD_DATA -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define GET_SDCONFIG_CMD(pBuffer) ((pBuffer)->Cmd) -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get a pointer to the configuration command data. -+ -+ @function name: GET_SDCONFIG_CMD_LEN -+ @prototype: INT GET_SDCONFIG_CMD_LEN (PSDCONFIG pCommand) -+ @category: HD_Reference -+ -+ @input: pCommand - config command structure. -+ -+ @return: length of config command data -+ -+ @notes: Implemented as a macro. Host controller drivers can use this macro to extract -+ the number of bytes of command specific data. This can be used to validate the -+ config data buffer size. -+ -+ @example: getting the data length: -+ length = GET_SDCONFIG_CMD_LEN(pConfig); -+ if (length < CUSTOM_COMMAND_XXX_SIZE) { -+ ... invalid length -+ } -+ -+ @see also: GET_SDCONFIG_CMD, GET_SDCONFIG_CMD_DATA -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define GET_SDCONFIG_CMD_LEN(pBuffer) ((pBuffer)->DataLength) -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get a pointer to the configuration command data. -+ -+ @function name: GET_SDCONFIG_CMD_DATA -+ @prototype: (casted ptr) GET_SDCONFIG_CMD_DATA (type, PSDCONFIG pCommand) -+ @category: HD_Reference -+ -+ @input: type - pointer type to cast the returned pointer to. -+ pCommand - config command structure. -+ -+ @return: type-casted pointer to the command's data -+ -+ @notes: Implemented as a macro. Host controller drivers can use this macro to extract -+ a pointer to the command specific data in an HCD configuration request. -+ -+ @example: getting the pointer: -+ // get interrupt control data -+ pIntControl = GET_SDCONFIG_CMD_DATA(PSDCONFIG_SDIO_INT_CTRL_DATA,pConfig); -+ if (pIntControl->SlotIRQEnable) { -+ ... enable slot IRQ detection -+ } -+ -+ @see also: GET_SDCONFIG_CMD, GET_SDCONFIG_CMD_LEN -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define GET_SDCONFIG_CMD_DATA(type,pBuffer) ((type)((pBuffer)->pData)) -+#define IS_SDCONFIG_CMD_GET(pBuffer) ((pBuffer)->Cmd & SDCONFIG_FLAGS_DATA_GET) -+#define IS_SDCONFIG_CMD_PUT(pBuffer) ((pBuffer)->Cmd & SDCONFIG_FLAGS_DATA_PUT) -+ -+struct _SDDEVICE; -+struct _SDHCD; -+ -+typedef UINT8 SD_FUNCTION_FLAGS; -+#define SDFUNCTION_FLAG_REMOVING 0x01 -+ -+/* function driver registration structure */ -+typedef struct _SDFUNCTION { -+ CT_VERSION_CODE Version; /* version code of the SDIO stack */ -+ SDLIST SDList; /* internal use list*/ -+ PTEXT pName; /* name of registering driver */ -+ UINT MaxDevices; /* maximum number of devices supported by this function */ -+ UINT NumDevices; /* number of devices supported by this function */ -+ PSD_PNP_INFO pIds; /* null terminated table of supported devices*/ -+ BOOL (*pProbe)(struct _SDFUNCTION *pFunction, struct _SDDEVICE *pDevice);/* New device inserted */ -+ /* Device removed (NULL if not a hot-plug capable driver) */ -+ void (*pRemove)(struct _SDFUNCTION *pFunction, struct _SDDEVICE *pDevice); -+ SDIO_STATUS (*pSuspend)(struct _SDFUNCTION *pFunction, SDPOWER_STATE state); /* Device suspended */ -+ SDIO_STATUS (*pResume)(struct _SDFUNCTION *pFunction); /* Device woken up */ -+ /* Enable wake event */ -+ SDIO_STATUS (*pWake) (struct _SDFUNCTION *pFunction, SDPOWER_STATE state, BOOL enable); -+ PVOID pContext; /* function driver use data */ -+ OS_PNPDRIVER Driver; /* driver registration with base system */ -+ SDLIST DeviceList; /* the list of devices this driver is using*/ -+ OS_SIGNAL CleanupReqSig; /* wait for requests completion on cleanup (internal use) */ -+ SD_FUNCTION_FLAGS Flags; /* internal flags (internal use) */ -+}SDFUNCTION, *PSDFUNCTION; -+ -+typedef UINT8 HCD_EVENT; -+ -+ /* device info for SDIO functions */ -+typedef struct _SDIO_DEVICE_INFO { -+ UINT32 FunctionCISPtr; /* function's CIS ptr */ -+ UINT32 FunctionCSAPtr; /* function's CSA ptr */ -+ UINT16 FunctionMaxBlockSize; /* function's reported max block size */ -+}SDIO_DEVICE_INFO, *PSDIO_DEVICE_INFO; -+ -+ /* device info for SD/MMC card functions */ -+typedef struct _SDMMC_INFO{ -+ UINT8 Unused; /* reserved */ -+}SDMMC_INFO, *PSDMMC_INFO; -+ -+ /* union of SDIO function and device info */ -+typedef union _SDDEVICE_INFO { -+ SDIO_DEVICE_INFO AsSDIOInfo; -+ SDMMC_INFO AsSDMMCInfo; -+}SDDEVICE_INFO, *PSDDEVICE_INFO; -+ -+ -+typedef UINT8 SD_DEVICE_FLAGS; -+#define SDDEVICE_FLAG_REMOVING 0x01 -+ -+/* inserted device description, describes an inserted card */ -+typedef struct _SDDEVICE { -+ SDLIST SDList; /* internal use list*/ -+ SDLIST FuncListLink; /* internal use list */ -+ /* read/write request function */ -+ SDIO_STATUS (*pRequest)(struct _SDDEVICE *pDev, PSDREQUEST req); -+ /* get/set configuration */ -+ SDIO_STATUS (*pConfigure)(struct _SDDEVICE *pDev, PSDCONFIG config); -+ PSDREQUEST (*AllocRequest)(struct _SDDEVICE *pDev); /* allocate a request */ -+ void (*FreeRequest)(struct _SDDEVICE *pDev, PSDREQUEST pReq); /* free the request */ -+ void (*pIrqFunction)(PVOID pContext); /* interrupt routine, synchronous calls allowed */ -+ void (*pIrqAsyncFunction)(PVOID pContext); /* async IRQ function , asynch only calls */ -+ PVOID IrqContext; /* irq context */ -+ PVOID IrqAsyncContext; /* irq async context */ -+ PSDFUNCTION pFunction; /* function driver supporting this device */ -+ struct _SDHCD *pHcd; /* host controller this device is on (internal use) */ -+ SDDEVICE_INFO DeviceInfo; /* device info */ -+ SD_PNP_INFO pId[1]; /* id of this device */ -+ OS_PNPDEVICE Device; /* device registration with base system */ -+ SD_SLOT_CURRENT SlotCurrentAlloc; /* allocated slot current for this device/function (internal use) */ -+ SD_DEVICE_FLAGS Flags; /* internal use flags */ -+ CT_VERSION_CODE Version; /* version code of the bus driver */ -+}SDDEVICE, *PSDDEVICE; -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get SDIO Bus Driver Version Major number -+ -+ @function name: SDDEVICE_GET_VERSION_MAJOR -+ @prototype: INT SDDEVICE_GET_VERSION_MAJOR(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: integer value for the major version -+ -+ @notes: Implemented as a macro. -+ -+ @see also: SDDEVICE_GET_VERSION_MINOR -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_VERSION_MAJOR(pDev) (GET_SDIO_STACK_VERSION_MAJOR(pDev)) -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get SDIO Bus Driver Version Minor number -+ -+ @function name: SDDEVICE_GET_VERSION_MINOR -+ @prototype: INT SDDEVICE_GET_VERSION_MINOR(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: integer value for the minor version -+ -+ @notes: Implemented as a macro. -+ -+ @see also: SDDEVICE_GET_VERSION_MAJOR -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_VERSION_MINOR(pDev) (GET_SDIO_STACK_VERSION_MINOR(pDev)) -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Test the SDIO revision for greater than or equal to 1.10 -+ -+ @function name: SDDEVICE_IS_SDIO_REV_GTEQ_1_10 -+ @prototype: BOOL SDDEVICE_IS_SDIO_REV_GTEQ_1_10(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: TRUE if the revision is greater than or equal to 1.10 -+ -+ @notes: Implemented as a macro. -+ -+ @see also: SDDEVICE_IS_SD_REV_GTEQ_1_10 -+ @see also: SDDEVICE_IS_MMC_REV_GTEQ_4_0 -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_IS_SDIO_REV_GTEQ_1_10(pDev) ((pDev)->pHcd->CardProperties.SDIORevision >= SDIO_REVISION_1_10) -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Test the SDIO revision for greater than or equal to 1.20 -+ -+ @function name: SDDEVICE_IS_SDIO_REV_GTEQ_1_20 -+ @prototype: BOOL SDDEVICE_IS_SDIO_REV_GTEQ_1_20(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: TRUE if the revision is greater than or equal to 1.20 -+ -+ @notes: Implemented as a macro. -+ -+ @see also: SDDEVICE_IS_SD_REV_GTEQ_1_10 -+ @see also: SDDEVICE_IS_SDIO_REV_GTEQ_1_10 -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_IS_SDIO_REV_GTEQ_1_20(pDev) ((pDev)->pHcd->CardProperties.SDIORevision >= SDIO_REVISION_1_20) -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Test the SD revision for greater than or equal to 1.10 -+ -+ @function name: SDDEVICE_IS_SD_REV_GTEQ_1_10 -+ @prototype: BOOL SDDEVICE_IS_SD_REV_GTEQ_1_10(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: TRUE if the revision is greater than or equal to 1.10 -+ -+ @notes: Implemented as a macro. -+ -+ @see also: SDDEVICE_IS_SDIO_REV_GTEQ_1_10 -+ @see also: SDDEVICE_IS_MMC_REV_GTEQ_4_0 -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_IS_SD_REV_GTEQ_1_10(pDev) ((pDev)->pHcd->CardProperties.SD_MMC_Revision >= SD_REVISION_1_10) -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Test the MMC revision for greater than or equal to 4.0 -+ -+ @function name: SDDEVICE_IS_MMC_REV_GTEQ_4_0 -+ @prototype: BOOL SDDEVICE_IS_MMC_REV_GTEQ_4_0(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: TRUE if the revision is greater than or equal to 4.0 -+ -+ @notes: Implemented as a macro. -+ -+ @see also: SDDEVICE_IS_SDIO_REV_GTEQ_1_10 -+ @see also: SDDEVICE_IS_SD_REV_GTEQ_1_10 -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_IS_MMC_REV_GTEQ_4_0(pDev) ((pDev)->pHcd->CardProperties.SD_MMC_Revision >= MMC_REVISION_4_0) -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Test for write protect enabled -+ -+ @function name: SDDEVICE_IS_CARD_WP_ON -+ @prototype: BOOL SDDEVICE_IS_CARD_WP_ON(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: TRUE if device is write protected. -+ -+ @notes: Implemented as a macro. -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_IS_CARD_WP_ON(pDev) ((pDev)->pHcd->CardProperties.Flags & CARD_SD_WP) -+ -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get the device's manufacturer specific ID -+ -+ @function name: SDDEVICE_GET_SDIO_MANFID -+ @prototype: UINT16 SDDEVICE_GET_SDIO_MANFID(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: function number -+ -+ @notes: Implemented as a macro. -+ -+ @see also: SDDEVICE_GET_SDIO_MANFCODE -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_SDIO_MANFID(pDev) (pDev)->pId[0].SDIO_ManufacturerID -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get the device's manufacturer code -+ -+ @function name: SDDEVICE_GET_SDIO_MANFCODE -+ @prototype: UINT16 SDDEVICE_GET_SDIO_MANFCODE(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: function number -+ -+ @notes: Implemented as a macro. -+ -+ @see also: SDDEVICE_GET_SDIO_MANFID -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_SDIO_MANFCODE(pDev) (pDev)->pId[0].SDIO_ManufacturerCode -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get the device's function number -+ -+ @function name: SDDEVICE_GET_SDIO_FUNCNO -+ @prototype: UINT8 SDDEVICE_GET_SDIO_FUNCNO(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: function number -+ -+ @notes: Implemented as a macro. -+ -+ @see also: SDDEVICE_GET_SDIO_FUNC_CLASS -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_SDIO_FUNCNO(pDev) (pDev)->pId[0].SDIO_FunctionNo -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get the functions's class -+ -+ @function name: SDDEVICE_GET_SDIO_FUNC_CLASS -+ @prototype: UINT8 SDDEVICE_GET_SDIO_FUNC_CLASS(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: class number -+ -+ @notes: Implemented as a macro. -+ -+ @see also: SDDEVICE_GET_SDIO_FUNCNO -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_SDIO_FUNC_CLASS(pDev) (pDev)->pId[0].SDIO_FunctionClass -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get the functions's Card Information Structure pointer -+ -+ @function name: SDDEVICE_GET_SDIO_FUNC_CISPTR -+ @prototype: UINT32 SDDEVICE_GET_SDIO_FUNC_CISPTR(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: CIS offset -+ -+ @notes: Implemented as a macro. -+ -+ @see also: SDDEVICE_GET_SDIO_FUNC_CSAPTR -+ @see also: SDDEVICE_GET_SDIO_COMMON_CISPTR -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_SDIO_FUNC_CISPTR(pDev)(pDev)->DeviceInfo.AsSDIOInfo.FunctionCISPtr -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get the functions's Code Stoarge Area pointer -+ -+ @function name: SDDEVICE_GET_SDIO_FUNC_CSAPTR -+ @prototype: UINT32 SDDEVICE_GET_SDIO_FUNC_CSAPTR(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: CSA offset -+ -+ @notes: Implemented as a macro. -+ -+ @see also: SDDEVICE_GET_SDIO_FUNC_CISPTR -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_SDIO_FUNC_CSAPTR(pDev)(pDev)->DeviceInfo.AsSDIOInfo.FunctionCSAPtr -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get the functions's maximum reported block size -+ -+ @function name: SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE -+ @prototype: UINT16 SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: block size -+ -+ @notes: Implemented as a macro. -+ -+ @see also: -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(pDev) (pDev)->DeviceInfo.AsSDIOInfo.FunctionMaxBlockSize -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get the common Card Information Structure pointer -+ -+ @function name: SDDEVICE_GET_SDIO_COMMON_CISPTR -+ @prototype: UINT32 SDDEVICE_GET_SDIO_COMMON_CISPTR(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: Common CIS Address (in SDIO address space) -+ -+ @notes: Implemented as a macro. -+ -+ @see also: SDDEVICE_GET_SDIO_FUNC_CSAPTR -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_SDIO_COMMON_CISPTR(pDev) (pDev)->pHcd->CardProperties.CommonCISPtr -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get the card capabilities -+ -+ @function name: SDDEVICE_GET_SDIO_CARD_CAPS -+ @prototype: UINT8 SDDEVICE_GET_SDIO_CARD_CAPS(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: 8-bit card capabilities register -+ -+ @notes: Implemented as a macro. Refer to SDIO spec for decoding. -+ -+ @see also: SDDEVICE_GET_CARD_FLAGS -+ @see also: SDDEVICE_GET_SDIOCARD_CAPS -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_SDIO_CARD_CAPS(pDev) (pDev)->pHcd->CardProperties.SDIOCaps -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get the card flags -+ -+ @function name: SDDEVICE_GET_CARD_FLAGS -+ @prototype: CARD_INFO_FLAGS SDDEVICE_GET_CARD_FLAGS(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: flags -+ -+ @notes: Implemented as a macro. -+ -+ @example: Get card type: -+ CARD_INFO_FLAGS flags; -+ flags = SDDEVICE_GET_CARD_FLAGS(pDevice); -+ switch(GET_CARD_TYPE(flags)) { -+ case CARD_MMC: // Multi-media card -+ ... -+ case CARD_SD: // SD-Memory present -+ ... -+ case CARD_SDIO: // SDIO card present -+ ... -+ case CARD_COMBO: //SDIO card with SD -+ ... -+ } -+ if (flags & CARD_SD_WP) { -+ ...SD write protect on -+ } -+ -+ @see also: SDDEVICE_GET_SDIO_CARD_CAPS -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_CARD_FLAGS(pDev) (pDev)->pHcd->CardProperties.Flags -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get the Relative Card Address register -+ -+ @function name: SDDEVICE_GET_CARD_RCA -+ @prototype: UINT16 SDDEVICE_GET_CARD_RCA(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: register address -+ -+ @notes: Implemented as a macro. Refer to SDIO spec for decoding. -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_CARD_RCA(pDev) (pDev)->pHcd->CardProperties.RCA -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get operational bus clock -+ -+ @function name: SDDEVICE_GET_OPER_CLOCK -+ @prototype: SD_BUSCLOCK_RATE SDDEVICE_GET_OPER_CLOCK(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: clock rate -+ -+ @notes: Implemented as a macro. Returns the current bus clock rate. -+ This may be lower than reported by the card due to Host Controller, -+ Bus driver, or power management limitations. -+ -+ @see also: SDDEVICE_GET_MAX_CLOCK -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_OPER_CLOCK(pDev) (pDev)->pHcd->CardProperties.OperBusClock -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get maximum bus clock -+ -+ @function name: SDDEVICE_GET_MAX_CLOCK -+ @prototype: SD_BUSCLOCK_RATE SDDEVICE_GET_MAX_CLOCK(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: clock rate -+ -+ @notes: To obtain the current maximum clock rate use SDDEVICE_GET_OPER_CLOCK(). -+ This rate my be lower than the host controllers maximum obtained using -+ SDDEVICE_GET_MAX_CLOCK(). -+ -+ @see also: SDDEVICE_GET_OPER_CLOCK -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_MAX_CLOCK(pDev) (pDev)->pHcd->MaxClockRate -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get operational maximum block length. -+ -+ @function name: SDDEVICE_GET_OPER_BLOCK_LEN -+ @prototype: UINT16 SDDEVICE_GET_OPER_BLOCK_LEN(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: block size in bytes -+ -+ @notes: Implemented as a macro. Returns the maximum current block length. -+ This may be lower than reported by the card due to Host Controller, -+ Bus driver, or power management limitations. -+ -+ @see also: SDDEVICE_GET_MAX_BLOCK_LEN -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_OPER_BLOCK_LEN(pDev) (pDev)->pHcd->CardProperties.OperBlockLenLimit -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get maximum block length. -+ -+ @function name: SDDEVICE_GET_MAX_BLOCK_LEN -+ @prototype: UINT16 SDDEVICE_GET_MAX_BLOCK_LEN(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: block size in bytes -+ -+ @notes: Implemented as a macro. Use SDDEVICE_GET_OPER_BLOCK_LEN to obtain -+ the current block length. -+ -+ @see also: SDDEVICE_GET_OPER_BLOCK_LEN -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_MAX_BLOCK_LEN(pDev) (pDev)->pHcd->MaxBytesPerBlock -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get operational maximum block count. -+ -+ @function name: SDDEVICE_GET_OPER_BLOCKS -+ @prototype: UINT16 SDDEVICE_GET_OPER_BLOCKS(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: maximum number of blocks per transaction. -+ -+ @notes: Implemented as a macro. Returns the maximum current block count. -+ This may be lower than reported by the card due to Host Controller, -+ Bus driver, or power management limitations. -+ -+ @see also: SDDEVICE_GET_MAX_BLOCK_LEN -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_OPER_BLOCKS(pDev) (pDev)->pHcd->CardProperties.OperBlockCountLimit -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get maximum block count. -+ -+ @function name: SDDEVICE_GET_MAX_BLOCKS -+ @prototype: UINT16 SDDEVICE_GET_MAX_BLOCKS(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: maximum number of blocks per transaction. -+ -+ @notes: Implemented as a macro. Use SDDEVICE_GET_OPER_BLOCKS to obtain -+ the current block count. -+ -+ @see also: SDDEVICE_GET_OPER_BLOCKS -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_MAX_BLOCKS(pDev) (pDev)->pHcd->MaxBlocksPerTrans -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get applied slot voltage -+ -+ @function name: SDDEVICE_GET_SLOT_VOLTAGE_MASK -+ @prototype: SLOT_VOLTAGE_MASK SDDEVICE_GET_SLOT_VOLTAGE_MASK(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: slot voltage mask -+ -+ @notes: This function returns the applied voltage on the slot. The voltage value is a -+ mask having the following values: -+ SLOT_POWER_3_3V -+ SLOT_POWER_3_0V -+ SLOT_POWER_2_8V -+ SLOT_POWER_2_0V -+ SLOT_POWER_1_8V -+ SLOT_POWER_1_6V -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_SLOT_VOLTAGE_MASK(pDev) (pDev)->pHcd->CardProperties.CardVoltage -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get the Card Specific Data Register. -+ -+ @function name: SDDEVICE_GET_CARDCSD -+ @prototype: PUINT8 SDDEVICE_GET_CARDCSD(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: UINT8 CardCSD[MAX_CARD_RESPONSE_BYTES] array of CSD data. -+ -+ @notes: Implemented as a macro. -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_CARDCSD(pDev) (pDev)->pHcd->CardProperties.CardCSD -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get the bus mode flags -+ -+ @function name: SDDEVICE_GET_BUSMODE_FLAGS -+ @prototype: SD_BUSMODE_FLAGS SDDEVICE_GET_BUSMODE_FLAGS(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: -+ -+ @notes: Implemented as a macro. This function returns the raw bus mode flags. This -+ is useful for function drivers that wish to override the bus clock without -+ modifying the current bus mode. -+ -+ @see also: SDDEVICE_GET_BUSWIDTH -+ @see also: SDCONFIG_BUS_MODE_CTRL -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_BUSMODE_FLAGS(pDev) (pDev)->pHcd->CardProperties.BusMode -+ -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get the bus width. -+ -+ @function name: SDDEVICE_GET_BUSWIDTH -+ @prototype: UINT8 SDDEVICE_GET_BUSWIDTH(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: bus width: SDCONFIG_BUS_WIDTH_SPI, SDCONFIG_BUS_WIDTH_1_BIT, SDCONFIG_BUS_WIDTH_4_BIT -+ -+ @notes: Implemented as a macro. -+ -+ @see also: SDDEVICE_IS_BUSMODE_SPI -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_BUSWIDTH(pDev) SDCONFIG_GET_BUSWIDTH((pDev)->pHcd->CardProperties.BusMode) -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Is bus in SPI mode. -+ -+ @function name: SDDEVICE_IS_BUSMODE_SPI -+ @prototype: BOOL SDDEVICE_IS_BUSMODE_SPI(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: TRUE, SPI mode. -+ -+ @notes: Implemented as a macro. -+ -+ @see also: SDDEVICE_GET_BUSWIDTH -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_IS_BUSMODE_SPI(pDev) (SDDEVICE_GET_BUSWIDTH(pDev) == SDCONFIG_BUS_WIDTH_SPI) -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Send a request to a device. -+ -+ @function name: SDDEVICE_CALL_REQUEST_FUNC -+ @prototype: SDIO_STATUS SDDEVICE_CALL_REQUEST_FUNC(PSDDEVICE pDevice, PSDREQUEST pRequest) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ @input: pRequest - the request to be sent -+ -+ @output: none -+ -+ @return: SDIO_STATUS -+ -+ @notes: Sends a request to the specified device. If the request is successfully sent, then -+ the response flags can be checked to detemine the result of the request. -+ -+ @example: Example of sending a request to a device: -+ PSDREQUEST pReq = NULL; -+ //allocate a request -+ pReq = SDDeviceAllocRequest(pDevice); -+ if (NULL == pReq) { -+ return SDIO_STATUS_NO_RESOURCES; -+ } -+ //initialize the request -+ SDLIB_SetupCMD52Request(FuncNo, Address, Write, *pData, pReq); -+ //send the request to the target -+ status = SDDEVICE_CALL_REQUEST_FUNC(pDevice,pReq); -+ if (!SDIO_SUCCESS(status)) { -+ break; -+ } -+ //check the request response (based on the request type) -+ if (SD_R5_GET_RESP_FLAGS(pReq->Response) & SD_R5_ERRORS) { -+ ... -+ } -+ if (!Write) { -+ // store the byte -+ *pData = SD_R5_GET_READ_DATA(pReq->Response); -+ } -+ //free the request -+ SDDeviceFreeRequest(pDevice,pReq); -+ ... -+ -+ @see also: SDDeviceAllocRequest -+ @see also: SDDEVICE_CALL_CONFIG_FUNC -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_CALL_REQUEST_FUNC(pDev,pReq) (pDev)->pRequest((pDev),(pReq)) -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Send configuration to a device. -+ -+ @function name: SDDEVICE_CALL_CONFIG_FUNC -+ @prototype: SDIO_STATUS SDDEVICE_CALL_CONFIG_FUNC(PSDDEVICE pDevice, PSDCONFIG pConfigure) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ @input: pConfigure - configuration request -+ -+ @output: none -+ -+ @return: SDIO_STATUS -+ -+ @notes: Sends a configuration request to the specified device. -+ -+ @example: Example of sending a request to a device: -+ SDCONFIG configHdr; -+ SDCONFIG_FUNC_ENABLE_DISABLE_DATA fData; -+ fData.EnableFlags = SDCONFIG_ENABLE_FUNC; -+ fData.TimeOut = 500; -+ SET_SDCONFIG_CMD_INFO(&configHdr, SDCONFIG_FUNC_ENABLE_DISABLE, fData, sizeof(fData)); -+ return SDDEVICE_CALL_CONFIG_FUNC(pDevice, &configHdr); -+ -+ @see also: SDLIB_IssueConfig -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_CALL_CONFIG_FUNC(pDev,pCfg) (pDev)->pConfigure((pDev),(pCfg)) -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Allocate a request structure. -+ -+ @function name: SDDeviceAllocRequest -+ @prototype: PSDREQUEST SDDeviceAllocRequest(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: request pointer or NULL if not available. -+ -+ @notes: This function must not be called in a non-schedulable (interrupts off) context. -+ Allocating memory on some OSes may block. -+ -+ @see also: SDDEVICE_CALL_REQUEST_FUNC -+ @see also: SDDeviceFreeRequest -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDeviceAllocRequest(pDev) (pDev)->AllocRequest((pDev)) -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Free a request structure. -+ -+ @function name: SDDeviceFreeRequest -+ @prototype: void SDDeviceFreeRequest(PSDDEVICE pDevice, PSDREQUEST pRequest) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ @input: pRequest - request allocated by SDDeviceAllocRequest(). -+ -+ @output: none -+ -+ @return: none -+ -+ @notes: This function must not be called in a non-schedulable (interrupts off) context. -+ Freeing memory on some OSes may block. -+ -+ @see also: SDDEVICE_CALL_REQUEST_FUNC -+ @see also: SDDeviceAllocRequest -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDeviceFreeRequest(pDev,pReq) (pDev)->FreeRequest((pDev),pReq) -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Register an interrupt handler for a device. -+ -+ @function name: SDDEVICE_SET_IRQ_HANDLER -+ @prototype: void SDDEVICE_SET_IRQ_HANDLER(PSDDEVICE pDevice, -+ void (*pIrqFunction)(PVOID pContext), -+ PVOID pContext) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ @input: pIrqFunction - the interrupt function to execute. -+ @input: pContext - context value passed into interrupt routine. -+ -+ @output: none -+ -+ @return: none -+ -+ @notes: The registered routine will be called upon each card interrupt. -+ The interrupt function should acknowledge the interrupt when it is -+ ready to handle more interrupts using: -+ SDLIB_IssueConfig(pDevice, SDCONFIG_FUNC_ACK_IRQ, NULL, 0); -+ The interrupt handler can perform synchronous request calls. -+ -+ @see also: SDDEVICE_SET_ASYNC_IRQ_HANDLER -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_SET_IRQ_HANDLER(pDev,pFn,pContext) \ -+{ \ -+ (pDev)->pIrqFunction = (pFn); \ -+ (pDev)->IrqContext = (PVOID)(pContext); \ -+} -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Register an asynchronous interrupt handler for a device. -+ -+ @function name: SDDEVICE_SET_ASYNC_IRQ_HANDLER -+ @prototype: void SDDEVICE_SET_ASYNC_IRQ_HANDLER(PSDDEVICE pDevice, -+ void (*pIrqAsyncFunction)(PVOID pContext), -+ PVOID pContext) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ @input: pIrqAsyncFunction - the interrupt function to execute. -+ @input: pContext - context value passed into interrupt routine. -+ -+ @output: none -+ -+ @return: none -+ -+ @notes: The registered routine will be called upon each card interrupt. -+ The interrupt function should acknowledge the interrupt when it is -+ ready to handle more interrupts using: -+ SDLIB_IssueConfig(pDevice, SDCONFIG_FUNC_ACK_IRQ, NULL, 0); -+ The interrupt handler can not perform any synchronous request calls. -+ Using this call provides a faster interrupt dispatch, but limits all -+ requests to asynchronous mode. -+ -+ @see also: SDDEVICE_SET_IRQ_HANDLER -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_SET_ASYNC_IRQ_HANDLER(pDev,pFn,pContext) \ -+{ \ -+ (pDev)->pIrqAsyncFunction = (pFn); \ -+ (pDev)->IrqAsyncContext = (PVOID)(pContext); \ -+} -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get the SDIO capabilities rgeister. -+ -+ @function name: SDDEVICE_GET_SDIOCARD_CAPS -+ @prototype: UINT8 SDDEVICE_GET_SDIOCARD_CAPS(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: SD capabilities -+ -+ @notes: See SD specification for decoding of these capabilities. -+ -+ @see also: SDDEVICE_GET_SDIO_CARD_CAPS -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_SDIOCARD_CAPS(pDev) (pDev)->pHcd->CardProperties.SDIOCaps -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get HCD driver name -+ -+ @function name: SDDEVICE_GET_HCDNAME -+ @prototype: PTEXT SDDEVICE_GET_HCDNAME(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the target device for this request -+ -+ @output: none -+ -+ @return: pointer to a string containing the name of the underlying HCD -+ -+ @notes: Implemented as a macro. -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_HCDNAME(pDev) (pDev)->pHcd->pName -+ -+ -+#define SDDEVICE_CALL_IRQ_HANDLER(pDev) (pDev)->pIrqFunction((pDev)->IrqContext) -+#define SDDEVICE_CALL_IRQ_ASYNC_HANDLER(pDev) (pDev)->pIrqAsyncFunction((pDev)->IrqAsyncContext) -+ -+ -+#define SDDEVICE_SET_SDIO_FUNCNO(pDev,Num) (pDev)->pId[0].SDIO_FunctionNo = (Num) -+#define SDDEVICE_IS_CARD_REMOVED(pDev) ((pDev)->pHcd->CardProperties.CardState & \ -+ CARD_STATE_REMOVED) -+ -+ -+typedef enum _SDHCD_IRQ_PROC_STATE { -+ SDHCD_IDLE = 0, -+ SDHCD_IRQ_PENDING = 1, -+ SDHCD_IRQ_HELPER = 2 -+}SDHCD_IRQ_PROC_STATE, *PSDHCD_IRQ_PROC_STATE; -+ -+/* host controller bus driver registration structure */ -+typedef struct _SDHCD { -+ CT_VERSION_CODE Version; /* version code of the SDIO stack */ -+ SDLIST SDList; /* internal use list*/ -+ PTEXT pName; /* name of registering host/slot driver */ -+ UINT32 Attributes; /* attributes of host controller */ -+ UINT16 MaxBytesPerBlock; /* max bytes per block */ -+ UINT16 MaxBlocksPerTrans; /* max blocks per transaction */ -+ SD_SLOT_CURRENT MaxSlotCurrent; /* max current per slot in milli-amps */ -+ UINT8 SlotNumber; /* sequential slot number for this HCD, set by bus driver */ -+ SD_BUSCLOCK_RATE MaxClockRate; /* max clock rate in hz */ -+ SLOT_VOLTAGE_MASK SlotVoltageCaps; /* slot voltage capabilities */ -+ SLOT_VOLTAGE_MASK SlotVoltagePreferred; /* preferred slot voltage */ -+ PVOID pContext; /* host controller driver use data */ -+ SDIO_STATUS (*pRequest)(struct _SDHCD *pHcd); -+ /* get/set configuration */ -+ SDIO_STATUS (*pConfigure)(struct _SDHCD *pHcd, PSDCONFIG pConfig); -+ /* everything below this line is for bus driver use */ -+ OS_SEMAPHORE ConfigureOpsSem; /* semaphore to make specific configure ops atomic, internal use */ -+ OS_CRITICALSECTION HcdCritSection; /* critical section to protect hcd data structures (internal use) */ -+ SDREQUESTQUEUE RequestQueue; /* request queue, internal use */ -+ PSDREQUEST pCurrentRequest; /* current request we are working on */ -+ CARD_PROPERTIES CardProperties; /* properties for the currently inserted card*/ -+ OSKERNEL_HELPER SDIOIrqHelper; /* synch IRQ helper, internal use */ -+ SDDEVICE *pPseudoDev; /* pseudo device used for initialization (internal use) */ -+ UINT8 PendingHelperIrqs; /* IRQ helper pending IRQs */ -+ UINT8 PendingIrqAcks; /* pending IRQ acks from function drivers */ -+ UINT8 IrqsEnabled; /* current irq enabled mask */ -+ SDHCD_IRQ_PROC_STATE IrqProcState; /* irq processing state */ -+ POS_DEVICE pDevice; /* device registration with base system */ -+ SD_SLOT_CURRENT SlotCurrentAllocated; /* slot current allocated (internal use ) */ -+ ATOMIC_FLAGS HcdFlags; /* HCD Flags */ -+#define HCD_REQUEST_CALL_BIT 0 -+#define HCD_IRQ_NO_PEND_CHECK 1 /* HCD flag to bypass interrupt pending register -+ check, typically done on single function cards */ -+ SDREQUESTQUEUE CompletedRequestQueue; /* completed request queue, internal use */ -+ PSDDMA_DESCRIPTION pDmaDescription; /* description of HCD's DMA capabilities */ -+ POS_MODULE pModule; /* OS-specific module information */ -+ INT Recursion; /* recursion level */ -+ PVOID Reserved1; -+ PVOID Reserved2; -+}SDHCD, *PSDHCD; -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get a pointer to the HCD's DMA description -+ -+ @function name: SDGET_DMA_DESCRIPTION -+ @prototype: PSDDMA_DESCRIPTION SDGET_DMA_DESCRIPTION(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - device structure -+ -+ @return: PSDDMA_DESCRIPTION or NULL if no DMA support -+ -+ @notes: Implemented as a macro. -+ -+ @example: getting the current request: -+ PSDDMA_DESCRIPTION pDmaDescrp = SDGET_DMA_DESCRIPTION(pDevice); -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDGET_DMA_DESCRIPTION(pDevice) (pDevice)->pHcd->pDmaDescription -+ -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get the logical slot number the device is assigned to. -+ -+ @function name: SDDEVICE_GET_SLOT_NUMBER -+ @prototype: UINT8 SDDEVICE_GET_SLOT_NUMBER(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - device structure -+ -+ @return: unsigned number representing the slot number -+ -+ @notes: Implemented as a macro. This value is unique for each physical slot in the system -+ and assigned by the bus driver. Devices on a multi-function card will share the same -+ slot number. -+ -+ @example: getting the slot number: -+ UINT8 thisSlot = SDDEVICE_GET_SLOT_NUMBER(pDevice); -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDDEVICE_GET_SLOT_NUMBER(pDevice) (pDevice)->pHcd->SlotNumber -+ -+/* for function use */ -+SDIO_STATUS SDIO_RegisterFunction(PSDFUNCTION pFunction); -+SDIO_STATUS SDIO_UnregisterFunction(PSDFUNCTION pFunction); -+ -+#include "sdio_hcd_defs.h" -+#endif /* __SDIO_BUSDRIVER_H___ */ -diff --git a/include/linux/sdio/sdio_hcd_defs.h b/include/linux/sdio/sdio_hcd_defs.h -new file mode 100644 -index 0000000..1782469 ---- /dev/null -+++ b/include/linux/sdio/sdio_hcd_defs.h -@@ -0,0 +1,219 @@ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+@file: sdio_hcd_defs.h -+ -+@abstract: host controller driver definitions -+ -+@notice: Copyright (c), 2005-2006 Atheros Communications, Inc. -+ -+ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * Software distributed under the License is distributed on an "AS -+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -+ * implied. See the License for the specific language governing -+ * rights and limitations under the License. -+ * -+ * Portions of this code were developed with information supplied from the -+ * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply: -+ * -+ * The following conditions apply to the release of the SD simplified specification (�Simplified -+ * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete -+ * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided -+ * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified -+ * Specification may require a license from the SD Card Association or other third parties. -+ * Disclaimers: -+ * The information contained in the Simplified Specification is presented only as a standard -+ * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any -+ * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for -+ * any damages, any infringements of patents or other right of the SD Card Association or any third -+ * parties, which may result from its use. No license is granted by implication, estoppel or otherwise -+ * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall -+ * be construed as an obligation by the SD Card Association to disclose or distribute any technical -+ * information, know-how or other confidential information to any third party. -+ * -+ * -+ * The initial developers of the original code are Seung Yi and Paul Lever -+ * -+ * sdio@atheros.com -+ * -+ * -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#ifndef __SDIO_HCD_DEFS_H___ -+#define __SDIO_HCD_DEFS_H___ -+ -+ /* write protect switch position data */ -+typedef UINT8 SDCONFIG_WP_VALUE; -+ -+ /* HC commands */ -+#define SDCONFIG_SEND_INIT_CLOCKS (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_PUT | 1) -+#define SDCONFIG_SDIO_INT_CTRL (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_PUT | 2) -+#define SDCONFIG_SDIO_REARM_INT (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_NONE | 3) -+#define SDCONFIG_BUS_MODE_CTRL (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_BOTH | 4) -+#define SDCONFIG_POWER_CTRL (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_PUT | 5) -+#define SDCONFIG_GET_WP (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_GET | 6) -+ -+ /* slot init clocks control */ -+typedef struct _SDCONFIG_INIT_CLOCKS_DATA { -+ UINT16 NumberOfClocks; /* number of clocks to issue in the current bus mode*/ -+}SDCONFIG_INIT_CLOCKS_DATA, *PSDCONFIG_INIT_CLOCKS_DATA; -+ -+/* slot power control */ -+typedef struct _SDCONFIG_POWER_CTRL_DATA { -+ BOOL SlotPowerEnable; /* turn on/off slot power */ -+ SLOT_VOLTAGE_MASK SlotPowerVoltageMask; /* slot power voltage mask */ -+}SDCONFIG_POWER_CTRL_DATA, *PSDCONFIG_POWER_CTRL_DATA; -+ -+typedef UINT8 SDIO_IRQ_MODE_FLAGS; -+/* SDIO Interrupt control */ -+typedef struct _SDCONFIG_SDIO_INT_CTRL_DATA { -+ BOOL SlotIRQEnable; /* turn on/off Slot IRQ detection */ -+ SDIO_IRQ_MODE_FLAGS IRQDetectMode; /* slot IRQ detect mode , only valid if Enabled = TRUE */ -+#define IRQ_DETECT_RAW 0x00 -+#define IRQ_DETECT_MULTI_BLK 0x01 -+#define IRQ_DETECT_4_BIT 0x02 -+#define IRQ_DETECT_1_BIT 0x04 -+#define IRQ_DETECT_SPI 0x08 -+}SDCONFIG_SDIO_INT_CTRL_DATA, *PSDCONFIG_SDIO_INT_CTRL_DATA; -+ -+/* card insert */ -+#define EVENT_HCD_ATTACH 1 -+/* card remove */ -+#define EVENT_HCD_DETACH 2 -+/* card slot interrupt */ -+#define EVENT_HCD_SDIO_IRQ_PENDING 3 -+/* transfer done */ -+#define EVENT_HCD_TRANSFER_DONE 4 -+/* (internal use only) */ -+#define EVENT_HCD_CD_POLLING 5 -+/* NOP */ -+#define EVENT_HCD_NOP 0 -+ -+/* attrib_flags */ -+#define SDHCD_ATTRIB_SUPPORTS_POWER 0x0001 /* host controller driver supports power managment */ -+#define SDHCD_ATTRIB_BUS_1BIT 0x0002 /* SD Native 1 - bit mode */ -+#define SDHCD_ATTRIB_BUS_4BIT 0x0004 /* SD Native 4 - bit mode */ -+#define SDHCD_ATTRIB_BUS_SPI 0x0008 /* SPI mode capable */ -+#define SDHCD_ATTRIB_READ_WAIT 0x0010 /* read wait supported (SD-only) */ -+#define SDHCD_ATTRIB_MULTI_BLK_IRQ 0x0020 /* interrupts between multi-block capable (SD-only) */ -+#define SDHCD_ATTRIB_BUS_MMC8BIT 0x0040 /* MMC 8-bit */ -+#define SDHCD_ATTRIB_SLOT_POLLING 0x0080 /* requires slot polling for Card Detect */ -+#define SDHCD_ATTRIB_POWER_SWITCH 0x0100 /* host has power switch control, must be set if SPI -+ mode can be switched to 1 or 4 bit mode */ -+#define SDHCD_ATTRIB_NO_SPI_CRC 0x0200 /* when in SPI mode, -+ host wants to run without SPI CRC */ -+#define SDHCD_ATTRIB_AUTO_CMD12 0x0400 /* host controller supports auto CMD12 */ -+#define SDHCD_ATTRIB_NO_4BIT_IRQ 0x0800 /* host controller does not support 4 bit IRQ mode*/ -+#define SDHCD_ATTRIB_RAW_MODE 0x1000 /* host controller is a raw mode hcd*/ -+#define SDHCD_ATTRIB_SD_HIGH_SPEED 0x2000 /* host controller supports SD high speed interface */ -+#define SDHCD_ATTRIB_MMC_HIGH_SPEED 0x4000 /* host controller supports MMC high speed interface */ -+ -+#define IS_CARD_PRESENT(pHcd) ((pHcd)->CardProperties.Flags & CARD_TYPE_MASK) -+#define SET_CURRENT_REQUEST(pHcd,Req) (pHcd)->pCurrentRequest = (Req) -+#define IS_HCD_RAW(pHcd) ((pHcd)->Attributes & SDHCD_ATTRIB_RAW_MODE) -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get a pointer to the current bus request for a host controller -+ -+ @function name: GET_CURRENT_REQUEST -+ @prototype: PSDREQUEST GET_CURRENT_REQUEST (PSDHCD pHcd) -+ @category: HD_Reference -+ -+ @input: pHcd - host structure -+ -+ @return: current SD/SDIO bus request being worked on -+ -+ @notes: Implemented as a macro. This macro returns the current SD request that is -+ being worked on. -+ -+ @example: getting the current request: -+ pReq = GET_CURRENT_REQUEST(&pHct->Hcd); -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define GET_CURRENT_REQUEST(pHcd) (pHcd)->pCurrentRequest -+#define GET_CURRENT_BUS_WIDTH(pHcd) SDCONFIG_GET_BUSWIDTH((pHcd)->CardProperties.BusMode) -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Get host controller's current operational bus clock -+ -+ @function name: SDHCD_GET_OPER_CLOCK -+ @prototype: SD_BUSCLOCK_RATE SDHCD_GET_OPER_CLOCK(PSDHCD pHcd) -+ @category: HD_Reference -+ -+ @input: pHcd - the registered host structure -+ -+ @output: none -+ -+ @return: clock rate -+ -+ @notes: Implemented as a macro. Returns the current bus clock rate. -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDHCD_GET_OPER_CLOCK(pHcd) (pHcd)->CardProperties.OperBusClock -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Is host controller operating in SPI mode -+ -+ @function name: IS_HCD_BUS_MODE_SPI -+ @prototype: BOOL IS_HCD_BUS_MODE_SPI (PSDHCD pHcd) -+ @category: HD_Reference -+ -+ @input: pHcd - host structure -+ -+ @return: TRUE if in SPI mode -+ -+ @notes: Implemented as a macro. Host controllers that operate in SPI mode -+ dynamically can use this macro to check for SPI operation. -+ -+ @example: testing for SPI mode: -+ if (IS_HCD_BUS_MODE_SPI(&pHct->Hcd)) { -+ .. in spi mode -+ } -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define IS_HCD_BUS_MODE_SPI(pHcd) (GET_CURRENT_BUS_WIDTH(pHcd) == SDCONFIG_BUS_WIDTH_SPI) -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Is host controller using SPI in non-CRC mode -+ -+ @function name: IS_HCD_BUS_MODE_SPI_NO_CRC -+ @prototype: BOOL IS_HCD_BUS_MODE_SPI_NO_CRC(PSDHCD pHcd) -+ @category: HD_Reference -+ -+ @input: pHcd - host structure -+ -+ @return: TRUE if CRC mode is off -+ -+ @notes: Implemented as a macro. SPI-capable cards and systems can operate in -+ non-CRC protected mode. In this mode the host controller should ignore -+ CRC fields and/or disable CRC generation when issuing command or data -+ packets. This option is useful for software based SPI mode where CRC -+ should be turned off in order to reduce processing overhead. -+ -+ @example: test for non-CRC SPI mode: -+ if (IS_HCD_BUS_MODE_SPI_NO_CRC(&pHct->Hcd)) { -+ .. disable CRC checking in hardware. -+ } -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define IS_HCD_BUS_MODE_SPI_NO_CRC(pHcd) ((pHcd)->CardProperties.BusMode & \ -+ SDCONFIG_BUS_MODE_SPI_NO_CRC) -+ -+typedef UINT8 SDHCD_RESPONSE_CHECK_MODE; -+/* have SDIO core check the response token and see if it is okay to continue with -+ * the data portion */ -+#define SDHCD_CHECK_DATA_TRANS_OK 0x01 -+/* have SDIO core check the SPI token received */ -+#define SDHCD_CHECK_SPI_TOKEN 0x02 -+ -+/* prototypes */ -+/* for HCD use */ -+SDIO_STATUS SDIO_RegisterHostController(PSDHCD pHcd); -+SDIO_STATUS SDIO_UnregisterHostController(PSDHCD pHcd); -+SDIO_STATUS SDIO_HandleHcdEvent(PSDHCD pHcd, HCD_EVENT Event); -+SDIO_STATUS SDIO_CheckResponse(PSDHCD pHcd, PSDREQUEST pReq, SDHCD_RESPONSE_CHECK_MODE CheckMode); -+SDIO_STATUS SDIO_BusAddOSDevice(PSDDMA_DESCRIPTION pDma, POS_PNPDRIVER pDriver, POS_PNPDEVICE pDevice); -+void SDIO_BusRemoveOSDevice(POS_PNPDRIVER pDriver, POS_PNPDEVICE pDevice); -+ -+#endif /* __SDIO_BUSDRIVER_H___ */ -diff --git a/include/linux/sdio/sdio_lib.h b/include/linux/sdio/sdio_lib.h -new file mode 100644 -index 0000000..ac0cbd7 ---- /dev/null -+++ b/include/linux/sdio/sdio_lib.h -@@ -0,0 +1,270 @@ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+@file: sdio_lib.h -+ -+@abstract: SDIO Library include -+ -+#notes: -+ -+@notice: Copyright (c), 2004-2006 Atheros Communications, Inc. -+ -+ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * Software distributed under the License is distributed on an "AS -+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -+ * implied. See the License for the specific language governing -+ * rights and limitations under the License. -+ * -+ * Portions of this code were developed with information supplied from the -+ * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply: -+ * -+ * The following conditions apply to the release of the SD simplified specification (�Simplified -+ * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete -+ * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided -+ * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified -+ * Specification may require a license from the SD Card Association or other third parties. -+ * Disclaimers: -+ * The information contained in the Simplified Specification is presented only as a standard -+ * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any -+ * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for -+ * any damages, any infringements of patents or other right of the SD Card Association or any third -+ * parties, which may result from its use. No license is granted by implication, estoppel or otherwise -+ * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall -+ * be construed as an obligation by the SD Card Association to disclose or distribute any technical -+ * information, know-how or other confidential information to any third party. -+ * -+ * -+ * The initial developers of the original code are Seung Yi and Paul Lever -+ * -+ * sdio@atheros.com -+ * -+ * -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#ifndef __SDIO_LIB_H___ -+#define __SDIO_LIB_H___ -+ -+#ifdef UNDER_CE -+#include "wince\sdio_lib_wince.h" -+#endif /* WINCE */ -+ -+#define CMD52_DO_READ FALSE -+#define CMD52_DO_WRITE TRUE -+ -+ /* read/write macros to any function */ -+#define Cmd52WriteByteFunc(pDev,Func,Address,pValue) \ -+ SDLIB_IssueCMD52((pDev),(Func),(Address),(pValue),1,CMD52_DO_WRITE) -+#define Cmd52ReadByteFunc(pDev,Func,Address,pValue) \ -+ SDLIB_IssueCMD52((pDev),(Func),(Address),pValue,1,CMD52_DO_READ) -+#define Cmd52ReadMultipleFunc(pDev,Func, Address, pBuf,length) \ -+ SDLIB_IssueCMD52((pDev),(Func),(Address),(pBuf),(length),CMD52_DO_READ) -+ -+ /* macros to access common registers */ -+#define Cmd52WriteByteCommon(pDev, Address, pValue) \ -+ Cmd52WriteByteFunc((pDev),0,(Address),(pValue)) -+#define Cmd52ReadByteCommon(pDev, Address, pValue) \ -+ Cmd52ReadByteFunc((pDev),0,(Address),(pValue)) -+#define Cmd52ReadMultipleCommon(pDev, Address, pBuf,length) \ -+ Cmd52ReadMultipleFunc((pDev),0,(Address),(pBuf),(length)) -+ -+#define SDLIB_SetupCMD52RequestAsync(f,a,w,wd,pR) \ -+{ \ -+ SDLIB_SetupCMD52Request((f),(a),(w),(wd),(pR)); \ -+ (pR)->Flags |= SDREQ_FLAGS_TRANS_ASYNC; \ -+} -+ -+ /* a message block */ -+typedef struct _SDMESSAGE_BLOCK { -+ SDLIST SDList; /* list entry */ -+ INT MessageLength; /* number of bytes in this message */ -+ UINT8 MessageStart[1]; /* message start */ -+}SDMESSAGE_BLOCK, *PSDMESSAGE_BLOCK; -+ -+ /* message queue */ -+typedef struct _SDMESSAGE_QUEUE { -+ SDLIST MessageList; /* message list */ -+ OS_CRITICALSECTION MessageCritSection; /* message semaphore */ -+ SDLIST FreeMessageList; /* free message list */ -+ INT MaxMessageLength; /* max message block length */ -+}SDMESSAGE_QUEUE, *PSDMESSAGE_QUEUE; -+ -+/* internal library prototypes that can be proxied */ -+SDIO_STATUS _SDLIB_IssueCMD52(PSDDEVICE pDevice, -+ UINT8 FuncNo, -+ UINT32 Address, -+ PUINT8 pData, -+ INT ByteCount, -+ BOOL Write); -+SDIO_STATUS _SDLIB_FindTuple(PSDDEVICE pDevice, -+ UINT8 Tuple, -+ UINT32 *pTupleScanAddress, -+ PUINT8 pBuffer, -+ UINT8 *pLength); -+SDIO_STATUS _SDLIB_IssueConfig(PSDDEVICE pDevice, -+ SDCONFIG_COMMAND Command, -+ PVOID pData, -+ INT Length); -+void _SDLIB_PrintBuffer(PUCHAR pBuffer, INT Length,PTEXT pDescription); -+void _SDLIB_SetupCMD52Request(UINT8 FuncNo, -+ UINT32 Address, -+ BOOL Write, -+ UINT8 WriteData, -+ PSDREQUEST pRequest); -+SDIO_STATUS _SDLIB_SetFunctionBlockSize(PSDDEVICE pDevice, -+ UINT16 BlockSize); -+ -+SDIO_STATUS _SDLIB_GetDefaultOpCurrent(PSDDEVICE pDevice, -+ SD_SLOT_CURRENT *pOpCurrent); -+PSDMESSAGE_QUEUE _CreateMessageQueue(INT MaxMessages, INT MaxMessageLength); -+void _DeleteMessageQueue(PSDMESSAGE_QUEUE pQueue); -+SDIO_STATUS _PostMessage(PSDMESSAGE_QUEUE pQueue, PVOID pMessage, INT MessageLength); -+SDIO_STATUS _GetMessage(PSDMESSAGE_QUEUE pQueue, PVOID pData, INT *pBufferLength); -+ -+#ifdef CTSYSTEM_NO_FUNCTION_PROXIES -+ /* OS port requires no proxy functions, use methods directly from the library */ -+#define SDLIB_IssueCMD52 _SDLIB_IssueCMD52 -+#define SDLIB_SetupCMD52Request _SDLIB_SetupCMD52Request -+#define SDLIB_FindTuple _SDLIB_FindTuple -+#define SDLIB_IssueConfig _SDLIB_IssueConfig -+#define SDLIB_SetFunctionBlockSize _SDLIB_SetFunctionBlockSize -+#define SDLIB_GetDefaultOpCurrent _SDLIB_GetDefaultOpCurrent -+#define SDLIB_CreateMessageQueue _CreateMessageQueue -+#define SDLIB_DeleteMessageQueue _DeleteMessageQueue -+#define SDLIB_PostMessage _PostMessage -+#define SDLIB_GetMessage _GetMessage -+#define SDLIB_PrintBuffer _SDLIB_PrintBuffer -+#else -+ -+/* proxied versions */ -+SDIO_STATUS SDLIB_IssueCMD52(PSDDEVICE pDevice, -+ UINT8 FuncNo, -+ UINT32 Address, -+ PUINT8 pData, -+ INT ByteCount, -+ BOOL Write); -+ -+void SDLIB_SetupCMD52Request(UINT8 FuncNo, -+ UINT32 Address, -+ BOOL Write, -+ UINT8 WriteData, -+ PSDREQUEST pRequest); -+ -+SDIO_STATUS SDLIB_FindTuple(PSDDEVICE pDevice, -+ UINT8 Tuple, -+ UINT32 *pTupleScanAddress, -+ PUINT8 pBuffer, -+ UINT8 *pLength); -+ -+SDIO_STATUS SDLIB_IssueConfig(PSDDEVICE pDevice, -+ SDCONFIG_COMMAND Command, -+ PVOID pData, -+ INT Length); -+ -+SDIO_STATUS SDLIB_SetFunctionBlockSize(PSDDEVICE pDevice, -+ UINT16 BlockSize); -+ -+void SDLIB_PrintBuffer(PUCHAR pBuffer, INT Length,PTEXT pDescription); -+ -+SDIO_STATUS SDLIB_GetDefaultOpCurrent(PSDDEVICE pDevice, SD_SLOT_CURRENT *pOpCurrent); -+ -+PSDMESSAGE_QUEUE SDLIB_CreateMessageQueue(INT MaxMessages, INT MaxMessageLength); -+ -+void SDLIB_DeleteMessageQueue(PSDMESSAGE_QUEUE pQueue); -+ -+SDIO_STATUS SDLIB_PostMessage(PSDMESSAGE_QUEUE pQueue, PVOID pMessage, INT MessageLength); -+ -+SDIO_STATUS SDLIB_GetMessage(PSDMESSAGE_QUEUE pQueue, PVOID pData, INT *pBufferLength); -+#endif /* CTSYSTEM_NO_FUNCTION_PROXIES */ -+ -+ -+SDIO_STATUS SDLIB_OSCreateHelper(POSKERNEL_HELPER pHelper, -+ PHELPER_FUNCTION pFunction, -+ PVOID pContext); -+ -+void SDLIB_OSDeleteHelper(POSKERNEL_HELPER pHelper); -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Check message queue is empty -+ -+ @function name: SDLIB_IsQueueEmpty -+ @prototype: BOOL SDLIB_IsQueueEmpty(PSDMESSAGE_QUEUE pQueue) -+ @category: Support_Reference -+ -+ @input: pQueue - message queue to check -+ -+ @return: TRUE if empty else false -+ -+ @see also: SDLIB_CreateMessageQueue -+ -+ @example: Check message queue : -+ if (SDLIB_IsQueueEmpty(pInstance->pQueue)) { -+ .. message queue is empty -+ } -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static INLINE BOOL SDLIB_IsQueueEmpty(PSDMESSAGE_QUEUE pQueue) { -+ return SDLIST_IS_EMPTY(&pQueue->MessageList); -+} -+ -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Issue an I/O abort request -+ -+ @function name: SDLIB_IssueIOAbort -+ @prototype: SDIO_STATUS SDLIB_IssueIOAbort(PSDDEVICE pDevice) -+ @category: PD_Reference -+ -+ @input: pDevice - the device that is the target of this request -+ -+ @return: SDIO_STATUS -+ -+ @notes: This procedure can be called to issue an I/O abort request to an I/O function. -+ This procedure cannot be used to abort a data (block) transfer already in progress. -+ It is intended to be used when a data (block) transfer completes with an error and only if -+ the I/O function requires an abort action. Some I/O functions may automatically -+ recover from such failures and not require this action. This function issues -+ the abort command synchronously and can potentially block. -+ If an async request is required, you must allocate a request and use -+ SDLIB_SetupIOAbortAsync() to prepare the request. -+ -+ @example: Issuing I/O Abort synchronously : -+ .. check status from last block operation: -+ if (status == SDIO_STATUS_BUS_READ_TIMEOUT) { -+ .. on failure, issue I/O abort -+ status2 = SDLIB_IssueIOAbort(pDevice); -+ } -+ Issuing I/O Abort asynchronously: -+ ... allocate a request -+ ... setup the request: -+ SDLIB_SetupIOAbortAsync(pDevice,pReq); -+ pReq->pCompletion = myIOAbortCompletion; -+ pReq->pCompleteContext = pDevice; -+ status = SDDEVICE_CALL_REQUEST_FUNC(pDevice,pReq); -+ -+ @see also: SDLIB_SetupIOAbortAsync -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+static INLINE SDIO_STATUS SDLIB_IssueIOAbort(PSDDEVICE pDevice) { -+ UINT8 value = SDDEVICE_GET_SDIO_FUNCNO(pDevice); -+ return Cmd52WriteByteCommon(pDevice,0x06,&value); -+} -+ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ @function: Setup an I/O abort request for async operation -+ -+ @function name: SDLIB_SetupIOAbortAsync -+ @prototype: SDLIB_SetupIOAbortAsync(PSDDEVICE pDevice, PSDREQUEST pRequest) -+ @category: PD_Reference -+ -+ @input: pDevice - the device that is the target of this request -+ pRequest - the request to set up -+ -+ @see also: SDLIB_IssueIOAbort -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#define SDLIB_SetupIOAbortAsync(pDevice, pReq) \ -+ SDLIB_SetupCMD52RequestAsync(0,0x06,TRUE,SDDEVICE_GET_SDIO_FUNCNO(pDevice),(pReq)) -+ -+ -+#endif /* __SDIO_LIB_H___*/ -diff --git a/include/linux/sdio/sdlist.h b/include/linux/sdio/sdlist.h -new file mode 100644 -index 0000000..dc35e1c ---- /dev/null -+++ b/include/linux/sdio/sdlist.h -@@ -0,0 +1,141 @@ -+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+@file: sdlist.h -+ -+@abstract: OS independent list functions -+ -+@notice: Copyright (c), 2004-2006 Atheros Communications, Inc. -+ -+ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * Software distributed under the License is distributed on an "AS -+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -+ * implied. See the License for the specific language governing -+ * rights and limitations under the License. -+ * -+ * Portions of this code were developed with information supplied from the -+ * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply: -+ * -+ * The following conditions apply to the release of the SD simplified specification (�Simplified -+ * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete -+ * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided -+ * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified -+ * Specification may require a license from the SD Card Association or other third parties. -+ * Disclaimers: -+ * The information contained in the Simplified Specification is presented only as a standard -+ * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any -+ * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for -+ * any damages, any infringements of patents or other right of the SD Card Association or any third -+ * parties, which may result from its use. No license is granted by implication, estoppel or otherwise -+ * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall -+ * be construed as an obligation by the SD Card Association to disclose or distribute any technical -+ * information, know-how or other confidential information to any third party. -+ * -+ * -+ * The initial developers of the original code are Seung Yi and Paul Lever -+ * -+ * sdio@atheros.com -+ * -+ * -+ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -+#ifndef __SDLIST_H___ -+#define __SDLIST_H___ -+ -+/* list functions */ -+/* pointers for the list */ -+typedef struct _SDLIST { -+ struct _SDLIST *pPrev; -+ struct _SDLIST *pNext; -+}SDLIST, *PSDLIST; -+/* -+ * SDLIST_INIT , circular list -+*/ -+#define SDLIST_INIT(pList)\ -+ {(pList)->pPrev = pList; (pList)->pNext = pList;} -+#define SDLIST_INIT_DECLARE(List)\ -+ SDLIST List = {&List, &List} -+ -+ -+#define SDLIST_IS_EMPTY(pList) (((pList)->pPrev == (pList)) && ((pList)->pNext == (pList))) -+#define SDLIST_GET_ITEM_AT_HEAD(pList) (pList)->pNext -+#define SDLIST_GET_ITEM_AT_TAIL(pList) (pList)->pPrev -+/* -+ * SDITERATE_OVER_LIST pStart is the list, pTemp is a temp list member -+ * NOT: do not use this function if the items in the list are deleted inside the -+ * iteration loop -+*/ -+#define SDITERATE_OVER_LIST(pStart, pTemp) \ -+ for((pTemp) =(pStart)->pNext; pTemp != (pStart); (pTemp) = (pTemp)->pNext) -+ -+ -+/* safe iterate macro that allows the item to be removed from the list -+ * the iteration continues to the next item in the list -+ */ -+#define SDITERATE_OVER_LIST_ALLOW_REMOVE(pStart,pItem,st,offset) \ -+{ \ -+ PSDLIST pTemp; \ -+ pTemp = (pStart)->pNext; \ -+ while (pTemp != (pStart)) { \ -+ (pItem) = CONTAINING_STRUCT(pTemp,st,offset); \ -+ pTemp = pTemp->pNext; \ -+ -+#define SDITERATE_END }} -+ -+/* -+ * SDListInsertTail - insert pAdd to the end of the list -+*/ -+static INLINE PSDLIST SDListInsertTail(PSDLIST pList, PSDLIST pAdd) { -+ /* this assert catches when an item is added twice */ -+ DBG_ASSERT(pAdd->pNext != pList); -+ /* insert at tail */ -+ pAdd->pPrev = pList->pPrev; -+ pAdd->pNext = pList; -+ pList->pPrev->pNext = pAdd; -+ pList->pPrev = pAdd; -+ return pAdd; -+} -+ -+/* -+ * SDListInsertHead - insert pAdd into the head of the list -+*/ -+static INLINE PSDLIST SDListInsertHead(PSDLIST pList, PSDLIST pAdd) { -+ /* this assert catches when an item is added twice */ -+ DBG_ASSERT(pAdd->pPrev != pList); -+ /* insert at head */ -+ pAdd->pPrev = pList; -+ pAdd->pNext = pList->pNext; -+ pList->pNext->pPrev = pAdd; -+ pList->pNext = pAdd; -+ return pAdd; -+} -+ -+#define SDListAdd(pList,pItem) SDListInsertHead((pList),(pItem)) -+/* -+ * SDListRemove - remove pDel from list -+*/ -+static INLINE PSDLIST SDListRemove(PSDLIST pDel) { -+ pDel->pNext->pPrev = pDel->pPrev; -+ pDel->pPrev->pNext = pDel->pNext; -+ /* point back to itself just to be safe, incase remove is called again */ -+ pDel->pNext = pDel; -+ pDel->pPrev = pDel; -+ return pDel; -+} -+ -+/* -+ * SDListRemoveItemFromHead - get a list item from the head -+*/ -+static INLINE PSDLIST SDListRemoveItemFromHead(PSDLIST pList) { -+ PSDLIST pItem = NULL; -+ if (pList->pNext != pList) { -+ pItem = pList->pNext; -+ /* remove the first item from head */ -+ SDListRemove(pItem); -+ } -+ return pItem; -+} -+#endif /* __SDLIST_H___ */ --- -1.5.6.3 - |