1 From 79b0634b39757c62f4e61256c12ddf8e7b3783c4 Mon Sep 17 00:00:00 2001
2 From: mokopatches <mokopatches@openmoko.org>
3 Date: Fri, 25 Jul 2008 22:21:24 +0100
4 Subject: [PATCH] atheros_2_0_sdio_stack.patch
10 drivers/sdio/Kconfig | 17 +
11 drivers/sdio/Makefile | 4 +
12 drivers/sdio/stack/Makefile | 1 +
13 drivers/sdio/stack/busdriver/Makefile | 2 +
14 drivers/sdio/stack/busdriver/_busdriver.h | 466 ++++
15 drivers/sdio/stack/busdriver/sdio_bus.c | 2120 +++++++++++++++
16 drivers/sdio/stack/busdriver/sdio_bus_events.c | 1040 +++++++
17 drivers/sdio/stack/busdriver/sdio_bus_misc.c | 3122 ++++++++++++++++++++++
18 drivers/sdio/stack/busdriver/sdio_bus_os.c | 832 ++++++
19 drivers/sdio/stack/busdriver/sdio_function.c | 715 +++++
20 drivers/sdio/stack/lib/Makefile | 2 +
21 drivers/sdio/stack/lib/_sdio_lib.h | 50 +
22 drivers/sdio/stack/lib/sdio_lib_c.c | 908 +++++++
23 drivers/sdio/stack/lib/sdio_lib_os.c | 251 ++
24 drivers/sdio/stack/platform/Makefile | 2 +
25 drivers/sdio/stack/platform/sdioplatformdriver.c | 300 +++
26 include/linux/sdio/_sdio_defs.h | 638 +++++
27 include/linux/sdio/ctsystem.h | 115 +
28 include/linux/sdio/ctsystem_linux.h | 983 +++++++
29 include/linux/sdio/mmc_defs.h | 103 +
30 include/linux/sdio/sdio_busdriver.h | 1435 ++++++++++
31 include/linux/sdio/sdio_hcd_defs.h | 219 ++
32 include/linux/sdio/sdio_lib.h | 270 ++
33 include/linux/sdio/sdlist.h | 141 +
34 27 files changed, 13741 insertions(+), 0 deletions(-)
35 create mode 100644 drivers/sdio/Kconfig
36 create mode 100644 drivers/sdio/Makefile
37 create mode 100644 drivers/sdio/stack/Makefile
38 create mode 100644 drivers/sdio/stack/busdriver/Makefile
39 create mode 100644 drivers/sdio/stack/busdriver/_busdriver.h
40 create mode 100644 drivers/sdio/stack/busdriver/sdio_bus.c
41 create mode 100644 drivers/sdio/stack/busdriver/sdio_bus_events.c
42 create mode 100644 drivers/sdio/stack/busdriver/sdio_bus_misc.c
43 create mode 100644 drivers/sdio/stack/busdriver/sdio_bus_os.c
44 create mode 100644 drivers/sdio/stack/busdriver/sdio_function.c
45 create mode 100644 drivers/sdio/stack/lib/Makefile
46 create mode 100644 drivers/sdio/stack/lib/_sdio_lib.h
47 create mode 100644 drivers/sdio/stack/lib/sdio_lib_c.c
48 create mode 100644 drivers/sdio/stack/lib/sdio_lib_os.c
49 create mode 100644 drivers/sdio/stack/platform/Makefile
50 create mode 100644 drivers/sdio/stack/platform/sdioplatformdriver.c
51 create mode 100644 include/linux/sdio/_sdio_defs.h
52 create mode 100644 include/linux/sdio/ctsystem.h
53 create mode 100644 include/linux/sdio/ctsystem_linux.h
54 create mode 100644 include/linux/sdio/mmc_defs.h
55 create mode 100644 include/linux/sdio/sdio_busdriver.h
56 create mode 100644 include/linux/sdio/sdio_hcd_defs.h
57 create mode 100644 include/linux/sdio/sdio_lib.h
58 create mode 100644 include/linux/sdio/sdlist.h
60 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
61 index b786e68..e394067 100644
62 --- a/arch/arm/Kconfig
63 +++ b/arch/arm/Kconfig
64 @@ -1169,6 +1169,8 @@ source "drivers/hid/Kconfig"
66 source "drivers/usb/Kconfig"
68 +source "drivers/sdio/Kconfig"
70 source "drivers/mmc/Kconfig"
72 source "drivers/leds/Kconfig"
73 diff --git a/drivers/Kconfig b/drivers/Kconfig
74 index 59f33fa..f5900b7 100644
77 @@ -78,6 +78,8 @@ source "drivers/hid/Kconfig"
79 source "drivers/usb/Kconfig"
81 +source "drivers/sdio/Kconfig"
83 source "drivers/mmc/Kconfig"
85 source "drivers/memstick/Kconfig"
86 diff --git a/drivers/Makefile b/drivers/Makefile
87 index f65deda..ce63a01 100644
88 --- a/drivers/Makefile
89 +++ b/drivers/Makefile
90 @@ -80,6 +80,7 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq/
91 obj-$(CONFIG_CPU_IDLE) += cpuidle/
92 obj-$(CONFIG_MMC) += mmc/
93 obj-$(CONFIG_MEMSTICK) += memstick/
94 +obj-$(CONFIG_SDIO) += sdio/
95 obj-$(CONFIG_NEW_LEDS) += leds/
96 obj-$(CONFIG_INFINIBAND) += infiniband/
97 obj-$(CONFIG_SGI_SN) += sn/
98 diff --git a/drivers/sdio/Kconfig b/drivers/sdio/Kconfig
100 index 0000000..14bf5e3
102 +++ b/drivers/sdio/Kconfig
105 +# SDIO driver and host controller support
111 + tristate "SDIO support"
116 +source "drivers/sdio/hcd/Kconfig"
118 +source "drivers/sdio/function/Kconfig"
121 diff --git a/drivers/sdio/Makefile b/drivers/sdio/Makefile
123 index 0000000..f56aa0f
125 +++ b/drivers/sdio/Makefile
127 +#Makefile for SDIO stack
128 +obj-$(CONFIG_SDIO) += stack/
129 +obj-$(CONFIG_SDIO) += hcd/
130 +obj-$(CONFIG_SDIO) += function/
131 diff --git a/drivers/sdio/stack/Makefile b/drivers/sdio/stack/Makefile
133 index 0000000..ff0e24d
135 +++ b/drivers/sdio/stack/Makefile
137 +obj-$(CONFIG_SDIO) += busdriver/ lib/
138 \ No newline at end of file
139 diff --git a/drivers/sdio/stack/busdriver/Makefile b/drivers/sdio/stack/busdriver/Makefile
141 index 0000000..1130e2d
143 +++ b/drivers/sdio/stack/busdriver/Makefile
145 +obj-$(CONFIG_SDIO) += sdio_busdriver.o
146 +sdio_busdriver-objs := sdio_bus.o sdio_function.o sdio_bus_misc.o sdio_bus_events.o sdio_bus_os.o
147 diff --git a/drivers/sdio/stack/busdriver/_busdriver.h b/drivers/sdio/stack/busdriver/_busdriver.h
149 index 0000000..a85aed1
151 +++ b/drivers/sdio/stack/busdriver/_busdriver.h
153 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
156 +@abstract: internal include file for busdriver
158 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
162 + * This program is free software; you can redistribute it and/or modify
163 + * it under the terms of the GNU General Public License version 2 as
164 + * published by the Free Software Foundation;
166 + * Software distributed under the License is distributed on an "AS
167 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
168 + * implied. See the License for the specific language governing
169 + * rights and limitations under the License.
171 + * Portions of this code were developed with information supplied from the
172 + * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply:
174 + * The following conditions apply to the release of the SD simplified specification (�Simplified
175 + * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete
176 + * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided
177 + * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified
178 + * Specification may require a license from the SD Card Association or other third parties.
180 + * The information contained in the Simplified Specification is presented only as a standard
181 + * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any
182 + * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for
183 + * any damages, any infringements of patents or other right of the SD Card Association or any third
184 + * parties, which may result from its use. No license is granted by implication, estoppel or otherwise
185 + * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall
186 + * be construed as an obligation by the SD Card Association to disclose or distribute any technical
187 + * information, know-how or other confidential information to any third party.
190 + * The initial developers of the original code are Seung Yi and Paul Lever
196 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
197 +#ifndef ___BUSDRIVER_H___
198 +#define ___BUSDRIVER_H___
199 +#include <linux/sdio/sdio_lib.h>
201 +#define SDIODBG_FUNC_IRQ (SDDBG_TRACE + 1)
202 +#define SDIODBG_REQUESTS (SDDBG_TRACE + 2)
203 +#define SDIODBG_CD_TIMER (SDDBG_TRACE + 3)
204 +#define SDIODBG_HCD_EVENTS (SDDBG_TRACE + 4)
206 +#define SDIOBUS_CD_TIMER_ID 0
208 +#define SDBUS_MAX_RETRY 3
210 +/* Notes on list linkages:
211 + * list heads are held in BDCONTEXT
213 + * one per registered host controller
214 + * Next - links of all HCDs
215 + * DeviceList SDDEVICE
216 + * one per inserted device
217 + * Next - links of all devices
218 + * DeviceListNext - links of all devices on a function
219 + * pFunction - ptr to Function supportting this device
220 + * pHcd - ptr to HCD with supporting this device
221 + * FunctionList SDFUNCTION
222 + * one per register function driver
223 + * Next - links of all functions
224 + * DeviceList - list of devices being support by this function
225 + * uses DeviceListNext in SDDEVICE to link
230 +#define SDMMC_DEFAULT_CMD_RETRIES 1
231 +#define SDMMC_DEFAULT_CARD_READY_RETRIES 200
232 +#define OCR_READY_CHECK_DELAY_MS 10
233 +#define SDMMC_POWER_SETTLE_DELAY 400 /* in milliseconds */
234 +#define SDBUS_DEFAULT_REQ_LIST_SIZE 16
235 +#define SDBUS_DEFAULT_REQ_SIG_SIZE 8
236 +#define CARD_DETECT_PAUSE 100
237 +#define SDBUS_DEFAULT_CD_POLLING_INTERVAL 1000 /* in milliseconds */
238 +#define MAX_CARD_DETECT_MSGS 16
239 +#define SDMMC_DEFAULT_BYTES_PER_BLOCK 2048
240 +#define SDMMC_DEFAULT_BLOCKS_PER_TRANS 512
241 +#define SDMMC_CMD13_POLLING_MULTIPLIER 1000 /* per block multiplier */
242 +#define MAX_HCD_REQ_RECURSION 5
243 +#define MAX_HCD_RECURSION_RUNAWAY 100
245 + /* internal signalling item */
246 +typedef struct _SIGNAL_ITEM{
247 + SDLIST SDList; /* list link*/
248 + OS_SIGNAL Signal; /* signal */
249 +}SIGNAL_ITEM, *PSIGNAL_ITEM;
251 +typedef struct _HCD_EVENT_MESSAGE {
252 + HCD_EVENT Event; /* the event */
253 + PSDHCD pHcd; /* hcd that generated the event */
254 +}HCD_EVENT_MESSAGE, *PHCD_EVENT_MESSAGE;
256 +/* internal data for bus driver */
257 +typedef struct _BDCONTEXT {
259 + /* list of SD requests and signalling semaphores and a semaphore to protect it */
260 + SDLIST RequestList;
262 + OS_CRITICALSECTION RequestListCritSection;
263 + /* list of host controller bus drivers, sempahore to protect it */
265 + OS_SEMAPHORE HcdListSem;
266 + /* list of inserted devices, semaphore to protect it */
268 + OS_SEMAPHORE DeviceListSem;
269 + /* list of function drivers, semaphore to protect it */
270 + SDLIST FunctionList;
271 + OS_SEMAPHORE FunctionListSem;
272 + INT RequestListSize; /* default request list */
273 + INT SignalSemListSize; /* default signalling semaphore size */
274 + INT CurrentRequestAllocations; /*current count of allocated requests */
275 + INT CurrentSignalAllocations; /* current count of signal allocations */
276 + INT MaxRequestAllocations; /* max number of allocated requests to keep around*/
277 + INT MaxSignalAllocations; /* max number of signal allocations to keep around*/
278 + INT RequestRetries; /* cmd retries */
279 + INT CardReadyPollingRetry; /* card ready polling retry count */
280 + INT PowerSettleDelay; /* power settle delay */
281 + INT CMD13PollingMultiplier; /* CMD13 (GET STATUS) multiplier */
282 + SD_BUSCLOCK_RATE DefaultOperClock; /* default operation clock */
283 + SD_BUSMODE_FLAGS DefaultBusMode; /* default bus mode */
284 + UINT16 DefaultOperBlockLen; /* default operational block length per block */
285 + UINT16 DefaultOperBlockCount; /* default operational block count per transaction */
286 + UINT32 CDPollingInterval; /* card insert/removal polling interval */
287 + UINT8 InitMask; /* bus driver init mask */
288 +#define BD_TIMER_INIT 0x01
289 +#define HELPER_INIT 0x02
290 +#define RESOURCE_INIT 0x04
291 + BOOL CDTimerQueued; /* card detect timer queued */
292 + OSKERNEL_HELPER CardDetectHelper; /* card detect helper */
293 + PSDMESSAGE_QUEUE pCardDetectMsgQueue; /* card detect message queue */
294 + ULONG HcdInUseField; /* bit field of in use HCD numbers*/
295 + UINT32 ConfigFlags; /* bus driver configuration flags */
296 +#define BD_CONFIG_SDREQ_FORCE_ALL_ASYNC 0x00000001
297 + INT MaxHcdRecursion; /* max HCD recurion level */
298 +}BDCONTEXT, *PBDCONTEXT;
300 +#define BD_DEFAULT_CONFIG_FLAGS 0x00000000
301 +#define IsQueueBusy(pRequestQueue) (pRequestQueue)->Busy
302 +#define MarkQueueBusy(pRequestQueue) (pRequestQueue)->Busy = TRUE
303 +#define MarkQueueNotBusy(pRequestQueue) (pRequestQueue)->Busy = FALSE
305 +#define CLEAR_INTERNAL_REQ_FLAGS(pReq) (pReq)->Flags &= ~(UINT)((SDREQ_FLAGS_RESP_SPI_CONVERTED | \
306 + SDREQ_FLAGS_FORCE_DEFERRED_COMPLETE))
308 +/* macros to insert request into the queue */
309 +#define QueueRequest(pReqQ,pReq) SDListInsertTail(&(pReqQ)->Queue,&(pReq)->SDList)
310 +#define QueueRequestToFront(pReqQ,pReq) SDListInsertHead(&(pReqQ)->Queue,&(pReq)->SDList)
312 +/* macros to remove an item from the head of the queue */
313 +static INLINE PSDREQUEST DequeueRequest(PSDREQUESTQUEUE pRequestQueue) {
315 + pItem = SDListRemoveItemFromHead(&pRequestQueue->Queue);
316 + if (pItem != NULL) {
317 + return CONTAINING_STRUCT(pItem, SDREQUEST, SDList);
322 +static INLINE SDIO_STATUS InitializeRequestQueue(PSDREQUESTQUEUE pRequestQueue) {
323 + SDLIST_INIT(&pRequestQueue->Queue);
324 + MarkQueueNotBusy(pRequestQueue);
325 + return SDIO_STATUS_SUCCESS;
328 +static INLINE void CleanupRequestQueue(PSDREQUESTQUEUE pRequestQueue) {
332 +/* for bus driver internal use only */
333 +SDIO_STATUS _SDIO_BusDriverInitialize(void);
334 +SDIO_STATUS _SDIO_BusGetDefaultSettings(PBDCONTEXT pBdc);
335 +void _SDIO_BusDriverCleanup(void);
336 +SDIO_STATUS RemoveAllFunctions(void);
337 +SDIO_STATUS RemoveHcdFunctions(PSDHCD pHcd);
338 +PSDDEVICE AllocateDevice(PSDHCD pHcd);
339 +BOOL AddDeviceToList(PSDDEVICE pDevice);
340 +SDIO_STATUS DeleteDevices(PSDHCD pHcd);
341 +SDIO_STATUS NotifyDeviceRemove(PSDDEVICE pDevice);
342 +extern PBDCONTEXT pBusContext;
343 +extern const CT_VERSION_CODE g_Version;
344 +SDIO_STATUS _SDIO_RegisterHostController(PSDHCD pHcd);
345 +SDIO_STATUS _SDIO_UnregisterHostController(PSDHCD pHcd);
346 +SDIO_STATUS _SDIO_HandleHcdEvent(PSDHCD pHcd, HCD_EVENT Event);
347 +SDIO_STATUS _SDIO_RegisterFunction(PSDFUNCTION pFunction);
348 +SDIO_STATUS _SDIO_UnregisterFunction(PSDFUNCTION pFunction);
349 +SDIO_STATUS _SDIO_CheckResponse(PSDHCD pHcd, PSDREQUEST pReq, SDHCD_RESPONSE_CHECK_MODE CheckMode);
350 +SDIO_STATUS ProbeForFunction(PSDDEVICE pDevice, PSDHCD pHcd);
351 +SDIO_STATUS SDInitializeCard(PSDHCD pHcd);
352 +SDIO_STATUS SDQuerySDMMCInfo(PSDDEVICE pDevice);
353 +SDIO_STATUS SDQuerySDIOInfo(PSDDEVICE pDevice);
354 +SDIO_STATUS SDEnableFunction(PSDDEVICE pDevice, PSDCONFIG_FUNC_ENABLE_DISABLE_DATA pEnData);
355 +SDIO_STATUS SDAllocFreeSlotCurrent(PSDDEVICE pDevice, BOOL Allocate, PSDCONFIG_FUNC_SLOT_CURRENT_DATA pData);
356 +SDIO_STATUS SDMaskUnmaskFunctionIRQ(PSDDEVICE pDevice, BOOL Mask);
357 +SDIO_STATUS SDFunctionAckInterrupt(PSDDEVICE pDevice);
358 +SDIO_STATUS SDSPIModeEnableDisableCRC(PSDDEVICE pDevice,BOOL Enable);
359 +SDIO_STATUS IssueBusConfig(PSDDEVICE pDev, PSDCONFIG pConfig);
360 +SDIO_STATUS IssueBusRequest(PSDDEVICE pDev, PSDREQUEST pReq);
361 +PSDREQUEST IssueAllocRequest(PSDDEVICE pDev);
362 +void IssueFreeRequest(PSDDEVICE pDev, PSDREQUEST pReq);
363 +PSDREQUEST AllocateRequest(void);
364 +void FreeRequest(PSDREQUEST pReq);
365 +PSIGNAL_ITEM AllocateSignal(void);
366 +void FreeSignal(PSIGNAL_ITEM pSignal);
367 +SDIO_STATUS InitializeTimers(void);
368 +SDIO_STATUS CleanupTimers(void);
369 +SDIO_STATUS QueueTimer(INT TimerID, UINT32 TimeOut);
370 +SDIO_STATUS DeviceAttach(PSDHCD pHcd);
371 +SDIO_STATUS DeviceDetach(PSDHCD pHcd);
372 +SDIO_STATUS DeviceInterrupt(PSDHCD pHcd);
373 +SDIO_STATUS CardInitSetup(PSDHCD pHcd);
374 +void RunCardDetect(void);
375 +void SDIO_NotifyTimerTriggered(INT TimerID);
376 +SDIO_STATUS TestPresence(PSDHCD pHcd,
377 + CARD_INFO_FLAGS TestType,
379 +#define _IssueSimpleBusRequest(pHcd,Cmd,Arg,Flags,pReqToUse) \
380 + _IssueBusRequestBd((pHcd),(Cmd),(Arg),(Flags),(pReqToUse),NULL,0)
382 +SDIO_STATUS Do_OS_IncHcdReference(PSDHCD pHcd);
383 +SDIO_STATUS Do_OS_DecHcdReference(PSDHCD pHcd);
384 +SDIO_STATUS TryNoIrqPendingCheck(PSDDEVICE pDev);
386 + /* check API version compatibility of an HCD or function driver to a stack major/minor version
387 + if the driver version is greater than the major number, we are compatible
388 + if the driver version is equal, then we check if the minor is greater than or equal
389 + we don't have to check for the less than major, because the bus driver never loads
390 + drivers with different major numbers ...
391 + if the busdriver compiled version major is greater than the major version being checked this
392 + macro will resolved to ALWAYS true thus optimizing the code to not check the HCD since
393 + as a rule we never load an HCD with a lower major number */
394 +#define CHECK_API_VERSION_COMPAT(p,major,minor) \
395 + ((CT_SDIO_STACK_VERSION_MAJOR(CT_SDIO_STACK_VERSION_CODE) > (major)) || \
396 + (GET_SDIO_STACK_VERSION_MINOR((p)) >= (minor)))
398 +static INLINE SDIO_STATUS OS_IncHcdReference(PSDHCD pHcd) {
399 + /* this API was added in version 2.3 which requires access to a field in the HCD structure */
400 + if (CHECK_API_VERSION_COMPAT(pHcd,2,3)) {
401 + /* we can safely call the OS-dependent function */
402 + return Do_OS_IncHcdReference(pHcd);
404 + return SDIO_STATUS_SUCCESS;
407 +static INLINE SDIO_STATUS OS_DecHcdReference(PSDHCD pHcd) {
408 + /* this API was added in version 2.3 which requires access to a field in the HCD structure */
409 + if (CHECK_API_VERSION_COMPAT(pHcd,2,3)) {
410 + /* we can safely call the OS-dependent function */
411 + return Do_OS_DecHcdReference(pHcd);
413 + return SDIO_STATUS_SUCCESS;
416 +SDIO_STATUS _IssueBusRequestBd(PSDHCD pHcd,
419 + SDREQUEST_FLAGS Flags,
420 + PSDREQUEST pReqToUse,
424 +SDIO_STATUS IssueRequestToHCD(PSDHCD pHcd,PSDREQUEST pReq);
426 +#define CALL_HCD_CONFIG(pHcd,pCfg) (pHcd)->pConfigure((pHcd),(pCfg))
427 + /* macro to force all requests to be asynchronous in the HCD */
428 +static INLINE BOOL ForceAllRequestsAsync(void) {
429 + return (pBusContext->ConfigFlags & BD_CONFIG_SDREQ_FORCE_ALL_ASYNC);
432 +static INLINE SDIO_STATUS CallHcdRequest(PSDHCD pHcd) {
434 + if (pHcd->pCurrentRequest->Flags & SDREQ_FLAGS_PSEUDO) {
435 + DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: PSEUDO Request 0x%X \n",
436 + (INT)pHcd->pCurrentRequest));
437 + /* return successful completion so that processing can finish */
438 + return SDIO_STATUS_SUCCESS;
441 + if (ForceAllRequestsAsync()) {
442 + /* all requests must be completed(indicated) in a separate context */
443 + pHcd->pCurrentRequest->Flags |= SDREQ_FLAGS_FORCE_DEFERRED_COMPLETE;
445 + /* otherwise perform a test on flags in the HCD */
446 + if (!CHECK_API_VERSION_COMPAT(pHcd,2,6) &&
447 + AtomicTest_Set(&pHcd->HcdFlags, HCD_REQUEST_CALL_BIT)) {
449 + /* bit was already set, this is a recursive call,
450 + * we need to tell the HCD to complete the
451 + * request in a separate context */
452 + DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Recursive CallHcdRequest \n"));
453 + pHcd->pCurrentRequest->Flags |= SDREQ_FLAGS_FORCE_DEFERRED_COMPLETE;
458 + SDIO_STATUS status;
459 + BOOL forceDeferred;
460 + forceDeferred = pHcd->pCurrentRequest->Flags & SDREQ_FLAGS_FORCE_DEFERRED_COMPLETE;
461 + status = pHcd->pRequest(pHcd);
462 + if (forceDeferred) {
463 + /* status better be pending... */
464 + DBG_ASSERT(status == SDIO_STATUS_PENDING);
469 + return pHcd->pRequest(pHcd);
474 +/* note the caller of this macro must take the HCD lock to protect the count */
475 +#define CHECK_HCD_RECURSE(pHcd,pReq) \
477 + (pHcd)->Recursion++; \
478 + DBG_ASSERT((pHcd)->Recursion < MAX_HCD_RECURSION_RUNAWAY); \
479 + if ((pHcd)->Recursion > pBusContext->MaxHcdRecursion) { \
480 + DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Recursive Request Count Exceeded (%d) \n",(pHcd)->Recursion)); \
481 + (pReq)->Flags |= SDREQ_FLAGS_FORCE_DEFERRED_COMPLETE; \
485 +/* InternalFlags bit number settings */
487 +#define SDBD_PENDING 15
488 +#define SDBD_ALLOC_IRQ_SAFE 2
490 +#define SDBD_ALLOC_IRQ_SAFE_MASK (1 << SDBD_ALLOC_IRQ_SAFE)
492 +static void INLINE DoRequestCompletion(PSDREQUEST pReq, PSDHCD pHcd) {
493 + CLEAR_INTERNAL_REQ_FLAGS(pReq);
494 + if (pReq->pCompletion != NULL) {
495 + DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Calling completion on request:0x%X, CMD:%d \n",
496 + (INT)pReq, pReq->Command));
497 + /* call completion routine, mark request reusable */
498 + AtomicTest_Clear(&pReq->InternalFlags, SDBD_PENDING);
499 + pReq->pCompletion(pReq);
501 + /* mark request reusable */
502 + AtomicTest_Clear(&pReq->InternalFlags, SDBD_PENDING);
506 +THREAD_RETURN CardDetectHelperFunction(POSKERNEL_HELPER pHelper);
507 +THREAD_RETURN SDIOIrqHelperFunction(POSKERNEL_HELPER pHelper);
509 +void ConvertSPI_Response(PSDREQUEST pReq, UINT8 *pRespBuffer);
511 +static INLINE SDIO_STATUS PostCardDetectEvent(PBDCONTEXT pSDB, HCD_EVENT Event, PSDHCD pHcd) {
512 + HCD_EVENT_MESSAGE message;
513 + SDIO_STATUS status;
514 + message.Event = Event;
515 + message.pHcd = pHcd;
517 + if (pHcd != NULL) {
518 + /* increment HCD reference count to process this HCD message */
519 + status = OS_IncHcdReference(pHcd);
520 + if (!SDIO_SUCCESS(status)) {
524 + /* post card detect message */
525 + status = SDLIB_PostMessage(pSDB->pCardDetectMsgQueue, &message, sizeof(message));
526 + if (!SDIO_SUCCESS(status)) {
527 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: PostCardDetectEvent error status %d\n",status));
528 + if (pHcd != NULL) {
529 + /* decrement count */
530 + OS_DecHcdReference(pHcd);
534 + /* wake card detect helper */
535 + DBG_PRINT(SDIODBG_HCD_EVENTS, ("SDIO Bus Driver: PostCardDetectEvent waking\n"));
536 + return SD_WAKE_OS_HELPER(&pSDB->CardDetectHelper);
539 +/* initialize device fields */
540 +static INLINE void InitDeviceData(PSDHCD pHcd, PSDDEVICE pDevice) {
541 + ZERO_POBJECT(pDevice);
542 + SDLIST_INIT(&pDevice->SDList);
543 + SDLIST_INIT(&pDevice->FuncListLink);
544 + pDevice->pRequest = IssueBusRequest;
545 + pDevice->pConfigure = IssueBusConfig;
546 + pDevice->AllocRequest = IssueAllocRequest;
547 + pDevice->FreeRequest = IssueFreeRequest;
548 + /* set card flags in the ID */
549 + pDevice->pId[0].CardFlags = pHcd->CardProperties.Flags;
550 + pDevice->pFunction = NULL;
551 + pDevice->pHcd = pHcd;
552 + SET_SDIO_STACK_VERSION(pDevice);
555 +/* de-initialize device fields */
556 +static INLINE void DeinitDeviceData(PSDDEVICE pDevice) {
559 +/* reset hcd state */
560 +static INLINE void ResetHcdState(PSDHCD pHcd) {
561 + ZERO_POBJECT(&pHcd->CardProperties);
562 + pHcd->PendingHelperIrqs = 0;
563 + pHcd->PendingIrqAcks = 0;
564 + pHcd->IrqsEnabled = 0;
565 + pHcd->pCurrentRequest = NULL;
566 + pHcd->IrqProcState = SDHCD_IDLE;
567 + /* mark this device as special */
568 + pHcd->pPseudoDev->pId[0].CardFlags = CARD_PSEUDO;
569 + pHcd->SlotCurrentAllocated = 0;
572 +static INLINE SDIO_STATUS _IssueConfig(PSDHCD pHcd,
573 + SDCONFIG_COMMAND Command,
576 + SDCONFIG configHdr;
577 + SET_SDCONFIG_CMD_INFO(&configHdr,Command,pData,Length);
578 + return CALL_HCD_CONFIG(pHcd,&configHdr);
582 +#define _AcquireHcdLock(pHcd)CriticalSectionAcquireSyncIrq(&(pHcd)->HcdCritSection)
583 +#define _ReleaseHcdLock(pHcd)CriticalSectionReleaseSyncIrq(&(pHcd)->HcdCritSection)
585 +#define AcquireHcdLock(pDev) CriticalSectionAcquireSyncIrq(&(pDev)->pHcd->HcdCritSection)
586 +#define ReleaseHcdLock(pDev) CriticalSectionReleaseSyncIrq(&(pDev)->pHcd->HcdCritSection)
588 +SDIO_STATUS OS_AddDevice(PSDDEVICE pDevice, PSDFUNCTION pFunction);
589 +void OS_RemoveDevice(PSDDEVICE pDevice);
590 +SDIO_STATUS OS_InitializeDevice(PSDDEVICE pDevice, PSDFUNCTION pFunction);
591 +SDIO_STATUS SetOperationalBusMode(PSDDEVICE pDevice,
592 + PSDCONFIG_BUS_MODE_DATA pBusMode);
593 +void FreeDevice(PSDDEVICE pDevice);
594 +BOOL IsPotentialIdMatch(PSD_PNP_INFO pIdsDev, PSD_PNP_INFO pIdsFuncList);
597 +#define CHECK_FUNCTION_DRIVER_VERSION(pF) \
598 + (GET_SDIO_STACK_VERSION_MAJOR((pF)) == CT_SDIO_STACK_VERSION_MAJOR(g_Version))
599 +#define CHECK_HCD_DRIVER_VERSION(pH) \
600 + (GET_SDIO_STACK_VERSION_MAJOR((pH)) == CT_SDIO_STACK_VERSION_MAJOR(g_Version))
602 +/* CLARIFICATION on SDREQ_FLAGS_PSEUDO and SDREQ_FLAGS_BARRIER flags :
604 + * A request marked as PSEUDO is synchronized with bus requests and is not a true request
605 + * that is issued to an HCD.
607 + * A request marked with a BARRIER flag requires that the completion routine be called
608 + * before the next bus request starts. This is required for HCD requests that can change
609 + * bus or clock modes. Changing the clock or bus mode while a bus request is pending
610 + * can cause problems.
615 +#define SD_PSEUDO_REQ_FLAGS \
616 + (SDREQ_FLAGS_PSEUDO | SDREQ_FLAGS_BARRIER | SDREQ_FLAGS_TRANS_ASYNC)
618 +#endif /*___BUSDRIVER_H___*/
619 diff --git a/drivers/sdio/stack/busdriver/sdio_bus.c b/drivers/sdio/stack/busdriver/sdio_bus.c
621 index 0000000..ffc1e9f
623 +++ b/drivers/sdio/stack/busdriver/sdio_bus.c
625 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
628 +@abstract: OS independent bus driver support
629 +@category abstract: HD_Reference Host Controller Driver Interfaces.
630 +@category abstract: PD_Reference
631 + Peripheral Driver Interfaces.
633 +#notes: this file supports the HCD's and generic functions
635 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
639 + * This program is free software; you can redistribute it and/or modify
640 + * it under the terms of the GNU General Public License version 2 as
641 + * published by the Free Software Foundation;
643 + * Software distributed under the License is distributed on an "AS
644 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
645 + * implied. See the License for the specific language governing
646 + * rights and limitations under the License.
648 + * Portions of this code were developed with information supplied from the
649 + * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply:
651 + * The following conditions apply to the release of the SD simplified specification (�Simplified
652 + * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete
653 + * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided
654 + * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified
655 + * Specification may require a license from the SD Card Association or other third parties.
657 + * The information contained in the Simplified Specification is presented only as a standard
658 + * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any
659 + * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for
660 + * any damages, any infringements of patents or other right of the SD Card Association or any third
661 + * parties, which may result from its use. No license is granted by implication, estoppel or otherwise
662 + * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall
663 + * be construed as an obligation by the SD Card Association to disclose or distribute any technical
664 + * information, know-how or other confidential information to any third party.
667 + * The initial developers of the original code are Seung Yi and Paul Lever
673 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
674 +#define MODULE_NAME SDBUSDRIVER
675 +#include <linux/sdio/ctsystem.h>
676 +#include <linux/sdio/sdio_busdriver.h>
677 +#include <linux/sdio/_sdio_defs.h>
678 +#include <linux/sdio/sdio_lib.h>
679 +#include <linux/sdio/mmc_defs.h>
680 +#include "_busdriver.h"
682 +/* list of host controller bus drivers */
683 +PBDCONTEXT pBusContext = NULL;
684 +static void CleanUpBusResources(void);
685 +static SDIO_STATUS AllocateBusResources(void);
686 +static PSIGNAL_ITEM BuildSignal(void);
687 +static void DestroySignal(PSIGNAL_ITEM pSignal);
689 +const CT_VERSION_CODE g_Version = CT_SDIO_STACK_VERSION_CODE;
691 + * _SDIO_BusDriverInitialize - call once on driver loading
694 +SDIO_STATUS _SDIO_BusDriverInitialize(void)
696 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
698 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Version: %d.%d\n",
699 + CT_SDIO_STACK_VERSION_MAJOR(g_Version),CT_SDIO_STACK_VERSION_MINOR(g_Version)));
701 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: enter _SDIO_BusDriverInitialize\n"));
704 + /* allocate our internal data initialize it */
705 + pBusContext = KernelAlloc(sizeof(BDCONTEXT));
706 + if (pBusContext == NULL) {
707 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't allocate memory.\n"));
708 + status = SDIO_STATUS_NO_RESOURCES;
711 + memset(pBusContext,0,sizeof(BDCONTEXT));
712 + SDLIST_INIT(&pBusContext->RequestList);
713 + SDLIST_INIT(&pBusContext->HcdList);
714 + SDLIST_INIT(&pBusContext->DeviceList);
715 + SDLIST_INIT(&pBusContext->FunctionList);
716 + SDLIST_INIT(&pBusContext->SignalList);
718 + /* setup defaults */
719 + pBusContext->RequestRetries = SDMMC_DEFAULT_CMD_RETRIES;
720 + pBusContext->CardReadyPollingRetry = SDMMC_DEFAULT_CARD_READY_RETRIES;
721 + pBusContext->PowerSettleDelay = SDMMC_POWER_SETTLE_DELAY;
722 + pBusContext->DefaultOperClock = MMC_HS_MAX_BUS_CLOCK;
723 + pBusContext->DefaultBusMode = SDCONFIG_BUS_WIDTH_4_BIT;
724 + pBusContext->RequestListSize = SDBUS_DEFAULT_REQ_LIST_SIZE;
725 + pBusContext->SignalSemListSize = SDBUS_DEFAULT_REQ_SIG_SIZE;
726 + pBusContext->CDPollingInterval = SDBUS_DEFAULT_CD_POLLING_INTERVAL;
727 + pBusContext->DefaultOperBlockLen = SDMMC_DEFAULT_BYTES_PER_BLOCK;
728 + pBusContext->DefaultOperBlockCount = SDMMC_DEFAULT_BLOCKS_PER_TRANS;
729 + pBusContext->ConfigFlags = BD_DEFAULT_CONFIG_FLAGS;
730 + pBusContext->CMD13PollingMultiplier = SDMMC_CMD13_POLLING_MULTIPLIER;
731 + pBusContext->MaxHcdRecursion = MAX_HCD_REQ_RECURSION;
733 + /* get overrides for the defaults */
734 + status = _SDIO_BusGetDefaultSettings(pBusContext);
735 + if (!SDIO_SUCCESS(status)) {
739 + pBusContext->MaxRequestAllocations = pBusContext->RequestListSize << 1;
740 + pBusContext->MaxSignalAllocations = pBusContext->SignalSemListSize << 1;
742 + status = CriticalSectionInit(&pBusContext->RequestListCritSection);
743 + if (!SDIO_SUCCESS(status)) {
744 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't CriticalSectionInit.\n"));
747 + status = SemaphoreInitialize(&pBusContext->HcdListSem, 1);
748 + if (!SDIO_SUCCESS(status)) {
749 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't SemaphoreInitialize HcdListSem.\n"));
752 + status = SemaphoreInitialize(&pBusContext->DeviceListSem, 1);
753 + if (!SDIO_SUCCESS(status)) {
754 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't SemaphoreInitialize DeviceListSem.\n"));
757 + status = SemaphoreInitialize(&pBusContext->FunctionListSem, 1);
758 + if (!SDIO_SUCCESS(status)) {
759 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't SemaphoreInitialize FunctionListSem.\n"));
762 + status = AllocateBusResources();
763 + if (!SDIO_SUCCESS(status)) {
764 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't AllocateBusResources.\n"));
768 + pBusContext->InitMask |= RESOURCE_INIT;
770 + pBusContext->pCardDetectMsgQueue = SDLIB_CreateMessageQueue(MAX_CARD_DETECT_MSGS,
771 + sizeof(HCD_EVENT_MESSAGE));
773 + if (NULL == pBusContext->pCardDetectMsgQueue) {
774 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't CreateMessageQueue.\n"));
775 + status = SDIO_STATUS_NO_RESOURCES;
779 + status = SDLIB_OSCreateHelper(&pBusContext->CardDetectHelper,
780 + CardDetectHelperFunction,
783 + if (!SDIO_SUCCESS(status)) {
784 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't OSCreateHelper.\n"));
788 + pBusContext->InitMask |= HELPER_INIT;
790 + status = InitializeTimers();
791 + if (!SDIO_SUCCESS(status)) {
792 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't InitializeTimers.\n"));
795 + pBusContext->InitMask |= BD_TIMER_INIT;
798 + if (!SDIO_SUCCESS(status)) {
799 + _SDIO_BusDriverCleanup();
807 + * _SDIO_BusDriverBusDriverCleanup - call once on driver unloading
810 +void _SDIO_BusDriverCleanup(void) {
811 + DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: _SDIO_BusDriverCleanup\n"));
813 + if (pBusContext->InitMask & BD_TIMER_INIT) {
817 + if (pBusContext->InitMask & HELPER_INIT) {
818 + SDLIB_OSDeleteHelper(&pBusContext->CardDetectHelper);
821 + if (pBusContext->pCardDetectMsgQueue != NULL) {
822 + SDLIB_DeleteMessageQueue(pBusContext->pCardDetectMsgQueue);
823 + pBusContext->pCardDetectMsgQueue = NULL;
825 + /* remove functions */
826 + RemoveAllFunctions();
827 + /* cleanup all devices */
828 + DeleteDevices(NULL);
829 + CleanUpBusResources();
830 + CriticalSectionDelete(&pBusContext->RequestListCritSection);
831 + SemaphoreDelete(&pBusContext->HcdListSem);
832 + SemaphoreDelete(&pBusContext->DeviceListSem);
833 + SemaphoreDelete(&pBusContext->FunctionListSem);
834 + KernelFree(pBusContext);
835 + pBusContext = NULL;
836 + DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: _SDIO_BusDriverCleanup\n"));
841 +static void CleanupHcd(PSDHCD pHcd)
843 + SDLIB_OSDeleteHelper(&pHcd->SDIOIrqHelper);
844 + CleanupRequestQueue(&pHcd->CompletedRequestQueue);
845 + CleanupRequestQueue(&pHcd->RequestQueue);
846 + CriticalSectionDelete(&pHcd->HcdCritSection);
847 + SemaphoreDelete(&pHcd->ConfigureOpsSem);
848 + pHcd->pCurrentRequest = NULL;
849 + if (pHcd->pPseudoDev != NULL) {
850 + FreeDevice(pHcd->pPseudoDev);
851 + pHcd->pPseudoDev = NULL;
855 +/* set up the hcd */
856 +static SDIO_STATUS SetupHcd(PSDHCD pHcd)
858 + SDIO_STATUS status;
860 + ZERO_POBJECT(&pHcd->SDIOIrqHelper);
861 + ZERO_POBJECT(&pHcd->ConfigureOpsSem);
862 + ZERO_POBJECT(&pHcd->HcdCritSection);
863 + ZERO_POBJECT(&pHcd->RequestQueue);
864 + ZERO_POBJECT(&pHcd->CompletedRequestQueue);
865 + pHcd->pPseudoDev = NULL;
866 + pHcd->Recursion = 0;
870 + pHcd->pPseudoDev = AllocateDevice(pHcd);
872 + if (NULL == pHcd->pPseudoDev) {
873 + status = SDIO_STATUS_NO_RESOURCES;
877 + ResetHcdState(pHcd);
879 + status = SemaphoreInitialize(&pHcd->ConfigureOpsSem,1);
880 + if (!SDIO_SUCCESS(status)) {
883 + status = CriticalSectionInit(&pHcd->HcdCritSection);
884 + if (!SDIO_SUCCESS(status)) {
887 + status = InitializeRequestQueue(&pHcd->RequestQueue);
888 + if (!SDIO_SUCCESS(status)) {
891 + status = InitializeRequestQueue(&pHcd->CompletedRequestQueue);
892 + if (!SDIO_SUCCESS(status)) {
895 + /* create SDIO Irq helper */
896 + status = SDLIB_OSCreateHelper(&pHcd->SDIOIrqHelper,
897 + SDIOIrqHelperFunction,
901 + if (!SDIO_SUCCESS(status)) {
902 + /* undo what we did */
910 + * _SDIO_RegisterHostController - register a host controller bus driver
914 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
915 + @function: Register a host controller driver with the bus driver.
917 + @function name: SDIO_RegisterHostController
918 + @prototype: SDIO_STATUS SDIO_RegisterHostController (PSDHCD pHcd)
919 + @category: HD_Reference
921 + @input: pHcd - the host controller definition structure.
925 + @return: SDIO_STATUS - SDIO_STATUS_SUCCESS when successful.
927 + @notes: Each host controller driver must register with the bus driver when loaded.
928 + The driver registers an SDHCD structure initialized with hardware properties
929 + and callback functions for bus requests and configuration. On multi-slot
930 + hardware ,each slot should be registered with a separate SDHCD structure.
931 + The bus driver views each slot as a seperate host controller object.
932 + The driver should be prepared to receive configuration requests before
933 + this call returns. The host controller driver must unregister itself when
936 + @example: Registering a host controller driver:
937 + static SDHCD Hcd = {
938 + .pName = "sdio_custom_hcd",
939 + .Version = CT_SDIO_STACK_VERSION_CODE, // set stack version code
940 + .SlotNumber = 0, // bus driver internal use
941 + .Attributes = SDHCD_ATTRIB_BUS_1BIT | SDHCD_ATTRIB_BUS_4BIT | SDHCD_ATTRIB_MULTI_BLK_IRQ
942 + SDHCD_ATTRIB_AUTO_CMD12 ,
943 + .MaxBytesPerBlock = 2048 // each data block can be up to 2048 bytes
944 + .MaxBlocksPerTrans = 1024, // each data transaction can consist of 1024 blocks
945 + .MaxSlotCurrent = 500, // max FET switch current rating
946 + .SlotVoltageCaps = SLOT_POWER_3_3V, // only 3.3V operation
947 + .SlotVoltagePreferred = SLOT_POWER_3_3V,
948 + .MaxClockRate = 24000000, // 24 Mhz max operation
949 + .pContext = &HcdContext, // set our driver context
950 + .pRequest = HcdRequest, // set SDIO bus request callback
951 + .pConfigure = HcdConfig, // set SDIO bus configuration callback
953 + if (!SDIO_SUCCESS((status = SDIO_RegisterHostController(&Hcd)))) {
954 + DBG_PRINT(SDDBG_ERROR, ("SDIO HCD - failed to register with host, status =%d\n",
958 + @see also: SDIO_UnregisterHostController
960 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
961 +SDIO_STATUS _SDIO_RegisterHostController(PSDHCD pHcd) {
962 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
964 + DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: _SDIO_RegisterHostController - %s\n",pHcd->pName));
965 + DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: Host Controller Stack Version: %d.%d \n",
966 + GET_SDIO_STACK_VERSION_MAJOR(pHcd),GET_SDIO_STACK_VERSION_MINOR(pHcd)));
968 + if (!CHECK_HCD_DRIVER_VERSION(pHcd)) {
969 + DBG_PRINT(SDDBG_ERROR,
970 + ("SDIO Bus Driver: HCD Major Version Mismatch (hcd = %d, bus driver = %d)\n",
971 + GET_SDIO_STACK_VERSION_MAJOR(pHcd), CT_SDIO_STACK_VERSION_MAJOR(g_Version)));
972 + return SDIO_STATUS_INVALID_PARAMETER;
975 + status = SetupHcd(pHcd);
976 + if (!SDIO_SUCCESS(status)) {
983 + /* protect the HCD list */
984 + if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->HcdListSem)))) {
985 + break; /* wait interrupted */
987 + /* find a unique number for this HCD, must be done under semaphore protection */
988 + slotNumber = FirstClearBit(&pBusContext->HcdInUseField);
989 + if (slotNumber < 0) {
990 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_RegisterHostController, error, slotNumber exceeded\n"));
991 + /* fake something */
994 + SetBit(&pBusContext->HcdInUseField, slotNumber);
995 + pHcd->SlotNumber = slotNumber;
996 + /* add HCD to the end of the internal list */
997 + SDListAdd(&pBusContext->HcdList , &pHcd->SDList);
998 + if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->HcdListSem)))) {
999 + break; /* wait interrupted */
1001 + if (pHcd->Attributes & SDHCD_ATTRIB_SLOT_POLLING) {
1002 + /* post message to card detect helper to do polling */
1003 + PostCardDetectEvent(pBusContext, EVENT_HCD_CD_POLLING, NULL);
1007 + if (!SDIO_SUCCESS(status)) {
1009 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_RegisterHostController, error 0x%X.\n", status));
1011 + DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: _SDIO_RegisterHostController\n"));
1015 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1016 + @function: Unregister a host controller driver with the bus driver.
1018 + @function name: SDIO_UnregisterHostController
1019 + @prototype: SDIO_STATUS SDIO_UnregisterHostController (PSDHCD pHcd)
1020 + @category: HD_Reference
1022 + @input: pHcd - the host controller definition structure that was registered.
1026 + @return: SDIO_STATUS - SDIO_STATUS_SUCCESS when successful.
1028 + @notes: Each host controller driver must unregister with the bus driver when
1029 + unloading. The driver is responsible for halting any outstanding I/O
1030 + operations. The bus driver will automatically unload function drivers
1031 + that may be attached assigned to cards inserted into slots.
1033 + @example: Unregistering a host controller driver:
1034 + if (!SDIO_SUCCESS((status = SDIO_UnregisterHostController(&Hcd)))) {
1035 + DBG_PRINT(SDDBG_ERROR, ("SDIO HCD - failed to unregister with host, status =%d\n",
1039 + @see also: SDIO_RegisterHostController
1041 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
1042 +SDIO_STATUS _SDIO_UnregisterHostController(PSDHCD pHcd) {
1043 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
1045 + DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: _SDIO_UnregisterHostController\n"));
1047 + /* remove functions associated with the HCD */
1048 + RemoveHcdFunctions(pHcd);
1049 + /* remove any devices associated with the HCD */
1050 + DeleteDevices(pHcd);
1051 + /* wait for the message queue to be empty, so we don't have any delayed requests going
1053 + while(!SDLIB_IsQueueEmpty(pBusContext->pCardDetectMsgQueue)) {
1054 + /* wait for the messages to be handled */
1055 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: _SDIO_UnregisterHostController, waiting on messages\n"));
1059 + /* protect the HCD list */
1060 + if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->HcdListSem)))) {
1061 + goto cleanup; /* wait interrupted */
1063 + ClearBit(&pBusContext->HcdInUseField, pHcd->SlotNumber);
1064 + /* delete HCD from list */
1065 + SDListRemove(&pHcd->SDList);
1066 + if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->HcdListSem)))) {
1067 + goto cleanup; /* wait interrupted */
1069 + /* cleanup anything we allocated */
1071 + DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: _SDIO_UnregisterHostController\n"));
1074 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_UnregisterHostController, error 0x%X.\n", status));
1078 +/* documentation headers only for Request and Configure */
1079 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1080 + @function: The bus driver calls the request callback to start an SDIO bus transaction.
1081 + @function name: Request
1082 + @prototype: SDIO_STATUS (*pRequest) (struct _SDHCD *pHcd)
1083 + @category: HD_Reference
1085 + @input: pHcd - the host controller structure that was registered
1089 + @return: SDIO_STATUS
1092 + The bus driver maintains an internal queue of SDREQUEST structures submited by function
1093 + drivers. The driver should use request macros to obtain a pointer to the current SDREQUEST
1094 + at the head of the queue. The driver can access the fields of the current request in order
1095 + to program hardware appropriately. Once the request completes, the driver should update
1096 + the current request information (final status, response bytes and/or data) and call
1097 + SDIO_HandleHcdEvent() with the event type of EVENT_HCD_TRANSFER_DONE.
1098 + The bus driver will remove the current request from the head of the queue and start the next
1101 + @example: Example of a typical Request callback:
1102 + SDIO_STATUS HcdRequest(PSDHCD pHcd)
1104 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
1105 + PSDHCD_DRIVER_CONTEXT pHct = (PSDHCD_DRIVER_CONTEXT)pHcd->pContext;
1108 + // get the current request
1109 + pReq = GET_CURRENT_REQUEST(pHcd);
1110 + DBG_ASSERT(pReq != NULL);
1111 + // get controller settings based on response type
1112 + switch (GET_SDREQ_RESP_TYPE(pReq->Flags)) {
1113 + case SDREQ_FLAGS_NO_RESP:
1115 + case SDREQ_FLAGS_RESP_R1:
1116 + case SDREQ_FLAGS_RESP_MMC_R4:
1117 + case SDREQ_FLAGS_RESP_MMC_R5:
1118 + case SDREQ_FLAGS_RESP_R6:
1119 + case SDREQ_FLAGS_RESP_SDIO_R5:
1120 + temp |= CMDDAT_RES_R1_R4_R5;
1122 + case SDREQ_FLAGS_RESP_R1B:
1123 + temp |= (CMDDAT_RES_R1_R4_R5 | CMDAT_RES_BUSY);
1125 + case SDREQ_FLAGS_RESP_R2:
1126 + temp |= CMDDAT_RES_R2;
1128 + case SDREQ_FLAGS_RESP_R3:
1129 + case SDREQ_FLAGS_RESP_SDIO_R4:
1130 + temp |= CMDDAT_RES_R3;
1134 + if (pReq->Flags & SDREQ_FLAGS_DATA_TRANS){
1135 + temp |= CMDDAT_DATA_EN;
1136 + // set data remaining count
1137 + pReq->DataRemaining = pReq->BlockLen * pReq->BlockCount;
1138 + DBG_PRINT(TRACE_DATA, ("SDIO %s Data Transfer, Blocks:%d, BlockLen:%d, Total:%d \n",
1139 + IS_SDREQ_WRITE_DATA(pReq->Flags) ? "TX":"RX",
1140 + pReq->BlockCount, pReq->BlockLen, pReq->DataRemaining));
1141 + if (IS_SDREQ_WRITE_DATA(pReq->Flags)) {
1142 + // write operation
1145 + // .... program hardware, interrupt handler will complete request
1146 + return SDIO_STATUS_PENDING;
1149 + @see also: SDIO_HandleHcdEvent
1151 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
1153 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1154 + @function: The bus driver calls the configure callback to set various options
1155 + and modes in the host controller hardware.
1157 + @function name: Configure
1158 + @prototype: SDIO_STATUS (*pConfigure) (struct _SDHCD *pHcd, PSDCONFIG pConfig)
1159 + @category: HD_Reference
1161 + @input: pHcd - the host controller structure that was registered
1162 + @input: pConfig - configuration request structure
1166 + @return: SDIO_STATUS
1169 + The host controller driver recieves configuration requests for options
1170 + such as slot voltage, bus width, clock rates and interrupt detection.
1171 + The bus driver guarantees that only one configuration option request
1172 + can be issued at a time.
1174 + @example: Example of a typical configure callback:
1175 + SDIO_STATUS HcdConfig(PSDHCD pHcd, PSDCONFIG pConfig)
1177 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
1178 + PSDHCD_DRIVER_CONTEXT pHct = (PSDHCD_DRIVER_CONTEXT)pHcd->pContext;
1181 + command = GET_SDCONFIG_CMD(pConfig);
1184 + case SDCONFIG_GET_WP:
1185 + if (GetGpioPinLevel(pHct,SDIO_CARD_WP_GPIO) == WP_POLARITY) {
1186 + *((SDCONFIG_WP_VALUE *)pConfig->pData) = 1;
1188 + *((SDCONFIG_WP_VALUE *)pConfig->pData) = 0;
1191 + case SDCONFIG_SEND_INIT_CLOCKS:
1192 + ClockStartStop(pHct,CLOCK_ON);
1193 + // sleep a little, should be at least 80 clocks at our lowest clock setting
1194 + status = OSSleep(100);
1195 + ClockStartStop(pHct,CLOCK_OFF);
1197 + case SDCONFIG_SDIO_INT_CTRL:
1198 + if (GET_SDCONFIG_CMD_DATA(PSDCONFIG_SDIO_INT_CTRL_DATA,pConfig)->SlotIRQEnable) {
1199 + // request to enable IRQ detection
1201 + // request to disable IRQ detectioon
1204 + case SDCONFIG_SDIO_REARM_INT:
1205 + // request to re-arm the card IRQ detection logic
1207 + case SDCONFIG_BUS_MODE_CTRL:
1208 + // request to set bus mode
1210 + // get bus mode data structure
1211 + PSDCONFIG_BUS_MODE_DATA pBusMode =
1212 + GET_SDCONFIG_CMD_DATA(PSDCONFIG_SDIO_INT_CTRL_DATA,pConfig);
1213 + // set bus mode based on settings in bus mode structure
1214 + // bus mode : pBusMode->BusModeFlags
1215 + // clock rate : pBusMode->ClockRate
1218 + case SDCONFIG_POWER_CTRL:
1219 + // request to set power/voltage
1221 + PSDCONFIG_POWER_CTRL_DATA pPowerSetting =
1222 + GET_SDCONFIG_CMD_DATA(PSDCONFIG_POWER_CTRL_DATA,pConfig);
1223 + if (pPowerSetting->SlotPowerEnable) {
1224 + // turn on slot power
1227 + // turn off slot power
1229 + DBG_PRINT(PXA_TRACE_CONFIG, ("SDIO PXA255 PwrControl: En:%d, VCC:0x%X \n",
1230 + pPowerSetting->SlotPowerEnable,
1231 + pPowerSetting->SlotPowerVoltageMask));
1236 + status = SDIO_STATUS_INVALID_PARAMETER;
1241 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
1245 + * Allocate a Device instance
1247 +PSDDEVICE AllocateDevice(PSDHCD pHcd)
1249 + PSDDEVICE pDevice;
1251 + pDevice = KernelAlloc(sizeof(SDDEVICE));
1252 + if (pDevice != NULL) {
1253 + InitDeviceData(pHcd,pDevice);
1260 + * Free a Device instance
1262 +void FreeDevice(PSDDEVICE pDevice)
1264 + DeinitDeviceData(pDevice);
1265 + KernelFree(pDevice);
1268 + * add this device to the list
1270 +BOOL AddDeviceToList(PSDDEVICE pDevice)
1272 + BOOL success = FALSE;
1275 + /* protect the driver list */
1276 + if (!SDIO_SUCCESS(SemaphorePendInterruptable(&pBusContext->DeviceListSem))) {
1277 + break; /* wait interrupted */
1280 + /* add new device to the internal list */
1281 + SDListAdd(&pBusContext->DeviceList , &pDevice->SDList);
1283 + if (!SDIO_SUCCESS(SemaphorePost(&pBusContext->DeviceListSem))) {
1294 + * Delete device associated with the HCD
1295 + * if pHCD is NULL this function cleans up all devices, the caller
1296 + * better have cleaned up functions first!
1298 +SDIO_STATUS DeleteDevices(PSDHCD pHcd)
1300 + SDIO_STATUS status;
1301 + PSDDEVICE pDevice;
1302 + DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: DeleteDevices hcd:0x%X \n", (INT)pHcd));
1303 + /* protect the device list */
1304 + if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->DeviceListSem)))) {
1305 + goto cleanup; /* wait interrupted */
1307 + SDITERATE_OVER_LIST_ALLOW_REMOVE(&pBusContext->DeviceList,pDevice,SDDEVICE,SDList) {
1308 + /* only remove devices for the hcd or if we are cleaning up all */
1309 + if ((NULL == pHcd) || (pDevice->pHcd == pHcd)) {
1310 + SDListRemove(&pDevice->SDList);
1311 + DeinitDeviceData(pDevice);
1312 + FreeDevice(pDevice);
1315 + if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->DeviceListSem)))) {
1316 + goto cleanup; /* wait interrupted */
1318 + DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: DeleteDevices \n"));
1321 + DBG_PRINT(SDDBG_ERROR, ("-SDIO Bus Driver: DeleteDevice, error exit 0x%X\n", status));
1326 +static SDIO_STATUS AllocateBusResources(void)
1330 + PSIGNAL_ITEM pSignal;
1332 + DBG_PRINT(SDDBG_TRACE,
1333 + ("+SDIO Bus Driver: AllocateBusResources (R:%d,S:%d) (CR:%d,MR:%d)(CS:%d,MS:%d) \n",
1334 + pBusContext->RequestListSize,
1335 + pBusContext->SignalSemListSize,
1336 + pBusContext->CurrentRequestAllocations,pBusContext->MaxRequestAllocations,
1337 + pBusContext->CurrentSignalAllocations,pBusContext->MaxSignalAllocations));
1339 + /* allocate some initial requests */
1340 + for (ii = 0; ii < pBusContext->RequestListSize; ii++) {
1341 + pReq = AllocateRequest();
1342 + if (pReq == NULL) {
1345 + /* free requests adds the request to the list */
1346 + FreeRequest(pReq);
1349 + for (ii = 0; ii < pBusContext->SignalSemListSize; ii++) {
1350 + pSignal = AllocateSignal();
1351 + if (pSignal == NULL) {
1354 + /* freeing it adds it to the list */
1355 + FreeSignal(pSignal);
1358 + DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: AllocateBusResources\n"));
1359 + return SDIO_STATUS_SUCCESS;
1363 +/* cleanup bus resources */
1364 +static void CleanUpBusResources(void)
1368 + PSIGNAL_ITEM pSignal;
1370 + DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: CleanUpBusResources (CR:%d,MR:%d)(CS:%d,MS:%d) \n",
1371 + pBusContext->CurrentRequestAllocations,pBusContext->MaxRequestAllocations,
1372 + pBusContext->CurrentSignalAllocations,pBusContext->MaxSignalAllocations));
1375 + pItem = SDListRemoveItemFromHead(&pBusContext->RequestList);
1376 + if (NULL == pItem) {
1379 + /* free the request */
1380 + pReq = CONTAINING_STRUCT(pItem, SDREQUEST, SDList);
1381 + if (pReq->InternalFlags & SDBD_ALLOC_IRQ_SAFE_MASK) {
1382 + KernelFreeIrqSafe(pReq);
1386 + pBusContext->CurrentRequestAllocations--;
1389 + if (pBusContext->CurrentRequestAllocations != 0) {
1390 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Request allocations are not ZERO! (CR:%d)\n",
1391 + pBusContext->CurrentRequestAllocations));
1395 + pItem = SDListRemoveItemFromHead(&pBusContext->SignalList);
1396 + if (NULL == pItem) {
1399 + pSignal = CONTAINING_STRUCT(pItem, SIGNAL_ITEM, SDList);
1400 + DestroySignal(pSignal);
1401 + pBusContext->CurrentSignalAllocations--;
1404 + if (pBusContext->CurrentSignalAllocations != 0) {
1405 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Signal allocations are not ZERO! (CR:%d)\n",
1406 + pBusContext->CurrentRequestAllocations));
1409 + DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: CleanUpBusResources\n"));
1413 +/* free a request to the lookaside list */
1414 +void FreeRequest(PSDREQUEST pReq)
1416 + SDIO_STATUS status;
1417 + CT_DECLARE_IRQ_SYNC_CONTEXT();
1419 + status = CriticalSectionAcquireSyncIrq(&pBusContext->RequestListCritSection);
1420 + /* protect request list */
1421 + if (!SDIO_SUCCESS(status)) {
1425 + if ((pBusContext->CurrentRequestAllocations <= pBusContext->MaxRequestAllocations) ||
1426 + !(pReq->InternalFlags & SDBD_ALLOC_IRQ_SAFE_MASK)) {
1427 + /* add it to the list */
1428 + SDListAdd(&pBusContext->RequestList, &pReq->SDList);
1429 + /* we will hold onto this one */
1432 + /* decrement count */
1433 + pBusContext->CurrentRequestAllocations--;
1436 + status = CriticalSectionReleaseSyncIrq(&pBusContext->RequestListCritSection);
1438 + if (pReq != NULL) {
1439 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Free Request allocation (CR:%d,MR:%d)\n",
1440 + pBusContext->CurrentRequestAllocations,pBusContext->MaxRequestAllocations));
1441 + if (pReq->InternalFlags & SDBD_ALLOC_IRQ_SAFE_MASK) {
1442 + KernelFreeIrqSafe(pReq);
1444 + /* we should never free the ones that were normally allocated */
1445 + DBG_ASSERT(FALSE);
1450 +/* allocate a request from the lookaside list */
1451 +PSDREQUEST AllocateRequest(void)
1454 + SDIO_STATUS status;
1455 + PSDREQUEST pReq = NULL;
1456 + ATOMIC_FLAGS internalflags;
1457 + CT_DECLARE_IRQ_SYNC_CONTEXT();
1460 + status = CriticalSectionAcquireSyncIrq(&pBusContext->RequestListCritSection);
1462 + if (!SDIO_SUCCESS(status)) {
1466 + if (pBusContext->InitMask & RESOURCE_INIT) {
1467 + /* check the list, we are now running... */
1468 + pItem = SDListRemoveItemFromHead(&pBusContext->RequestList);
1470 + /* we are loading the list with requests at initialization */
1473 + status = CriticalSectionReleaseSyncIrq(&pBusContext->RequestListCritSection);
1475 + if (pItem != NULL) {
1476 + pReq = CONTAINING_STRUCT(pItem, SDREQUEST, SDList);
1478 + if (pBusContext->InitMask & RESOURCE_INIT) {
1479 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Request List empty..allocating new one (irq-safe) (CR:%d,MR:%d)\n",
1480 + pBusContext->CurrentRequestAllocations,pBusContext->MaxRequestAllocations));
1481 + /* the resource list was already allocated, we must be running now.
1482 + * at run-time, we allocate using the safe IRQ */
1483 + pReq = (PSDREQUEST)KernelAllocIrqSafe(sizeof(SDREQUEST));
1484 + /* mark that this one was created using IRQ safe allocation */
1485 + internalflags = SDBD_ALLOC_IRQ_SAFE_MASK;
1487 + /* use the normal allocation since we are called at initialization */
1488 + pReq = (PSDREQUEST)KernelAlloc(sizeof(SDREQUEST));
1489 + internalflags = 0;
1492 + if (pReq != NULL) {
1493 + pReq->InternalFlags = internalflags;
1494 + /* keep track of allocations */
1495 + status = CriticalSectionAcquireSyncIrq(&pBusContext->RequestListCritSection);
1496 + pBusContext->CurrentRequestAllocations++;
1497 + status = CriticalSectionReleaseSyncIrq(&pBusContext->RequestListCritSection);
1502 + if (pReq != NULL) {
1503 + /* preserve internal flags */
1504 + internalflags = pReq->InternalFlags;
1505 + ZERO_POBJECT(pReq);
1506 + pReq->InternalFlags = internalflags;
1512 +void DestroySignal(PSIGNAL_ITEM pSignal)
1514 + SignalDelete(&pSignal->Signal);
1515 + KernelFree(pSignal);
1518 +PSIGNAL_ITEM BuildSignal(void)
1520 + PSIGNAL_ITEM pSignal;
1522 + pSignal = (PSIGNAL_ITEM)KernelAlloc(sizeof(SIGNAL_ITEM));
1523 + if (pSignal != NULL) {
1524 + /* initialize signal */
1525 + if (!SDIO_SUCCESS(SignalInitialize(&pSignal->Signal))) {
1526 + KernelFree(pSignal);
1533 +void FreeSignal(PSIGNAL_ITEM pSignal)
1535 + SDIO_STATUS status;
1536 + CT_DECLARE_IRQ_SYNC_CONTEXT();
1538 + status = CriticalSectionAcquireSyncIrq(&pBusContext->RequestListCritSection);
1540 + if (!SDIO_SUCCESS(status)) {
1544 + if (pBusContext->CurrentSignalAllocations <= pBusContext->MaxSignalAllocations) {
1545 + /* add it to the list */
1546 + SDListAdd(&pBusContext->SignalList, &pSignal->SDList);
1547 + /* flag that we are holding onto it */
1550 + /* decrement count */
1551 + pBusContext->CurrentSignalAllocations--;
1554 + status = CriticalSectionReleaseSyncIrq(&pBusContext->RequestListCritSection);
1556 + if (pSignal != NULL) {
1557 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Free signal allocation (CS:%d,MS:%d)\n",
1558 + pBusContext->CurrentSignalAllocations,pBusContext->MaxSignalAllocations));
1559 + DestroySignal(pSignal);
1563 +/* allocate a signal from the list */
1564 +PSIGNAL_ITEM AllocateSignal(void)
1567 + PSIGNAL_ITEM pSignal;
1568 + SDIO_STATUS status;
1569 + CT_DECLARE_IRQ_SYNC_CONTEXT();
1571 + status = CriticalSectionAcquireSyncIrq(&pBusContext->RequestListCritSection);
1573 + if (!SDIO_SUCCESS(status)) {
1577 + if (pBusContext->InitMask & RESOURCE_INIT) {
1578 + /* check the list */
1579 + pItem = SDListRemoveItemFromHead(&pBusContext->SignalList);
1581 + /* we are loading the list */
1585 + status = CriticalSectionReleaseSyncIrq(&pBusContext->RequestListCritSection);
1586 + if (pItem != NULL) {
1587 + /* return the one from the list */
1588 + pSignal = CONTAINING_STRUCT(pItem, SIGNAL_ITEM, SDList);
1590 + if (pBusContext->InitMask & RESOURCE_INIT) {
1591 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Signal List empty..allocating new one (CS:%d,MS:%d)\n",
1592 + pBusContext->CurrentSignalAllocations,pBusContext->MaxSignalAllocations));
1594 + /* just allocate one */
1595 + pSignal = BuildSignal();
1596 + status = CriticalSectionAcquireSyncIrq(&pBusContext->RequestListCritSection);
1597 + if (pSignal != NULL) {
1598 + pBusContext->CurrentSignalAllocations++;
1600 + status = CriticalSectionReleaseSyncIrq(&pBusContext->RequestListCritSection);
1608 + * Issus Bus Request (exposed to function drivers)
1610 +PSDREQUEST IssueAllocRequest(PSDDEVICE pDev)
1612 + return AllocateRequest();
1616 + * Free Request (exposed to function drivers)
1618 +void IssueFreeRequest(PSDDEVICE pDev, PSDREQUEST pReq)
1620 + FreeRequest(pReq);
1624 + * Issus Bus Request (exposed to function drivers)
1626 +SDIO_STATUS IssueBusRequest(PSDDEVICE pDev, PSDREQUEST pReq)
1628 + pReq->pFunction = pDev->pFunction;
1629 + return IssueRequestToHCD(pDev->pHcd,pReq);
1633 + /* completion routine for HCD configs, this is synchronized with normal bus requests */
1634 +static void HcdConfigComplete(PSDREQUEST pReq)
1637 + pReq->Status = CALL_HCD_CONFIG((PSDHCD)pReq->pDataBuffer, (PSDCONFIG)pReq->pCompleteContext);
1639 + SignalSet(&((PSIGNAL_ITEM)pReq->pHcdContext)->Signal);
1642 +SDIO_STATUS SendSyncedHcdBusConfig(PSDDEVICE pDevice, PSDCONFIG pConfig)
1644 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
1645 + PSDREQUEST pReq = NULL;
1646 + PSIGNAL_ITEM pSignal = NULL;
1650 + pSignal = AllocateSignal();
1651 + if (NULL == pSignal) {
1652 + status = SDIO_STATUS_NO_RESOURCES;
1656 + pReq = AllocateRequest();
1657 + if (NULL == pReq) {
1658 + status = SDIO_STATUS_NO_RESOURCES;
1662 + /* issue pseudo request to sync this with bus requests */
1663 + pReq->pCompletion = HcdConfigComplete;
1664 + pReq->pCompleteContext = pConfig;
1665 + /* re-use hcd context to store the signal since this request
1666 + * never actually goes to an HCD */
1667 + pReq->pHcdContext = pSignal;
1668 + pReq->pDataBuffer = pDevice->pHcd;
1669 + /* flag this as barrier in case it may change the bus mode of the HCD */
1670 + pReq->Flags = SDREQ_FLAGS_PSEUDO | SDREQ_FLAGS_BARRIER | SDREQ_FLAGS_TRANS_ASYNC;
1671 + pReq->Status = SDIO_STATUS_SUCCESS;
1673 + /* issue request */
1674 + status = IssueRequestToHCD(pDevice->pHcd,pReq);
1678 + if (SDIO_SUCCESS(status)) {
1679 + DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Config Request Sync-Op waiting....\n"));
1680 + status = SignalWait(&pSignal->Signal);
1682 + if (SDIO_SUCCESS(status)) {
1683 + /* return the result of the configuration request */
1684 + status = pReq->Status;
1689 + if (pReq != NULL) {
1690 + FreeRequest(pReq);
1693 + if (pSignal != NULL) {
1694 + FreeSignal(pSignal);
1701 + * Issus bus Configuration (exposed to function drivers)
1703 +SDIO_STATUS IssueBusConfig(PSDDEVICE pDev, PSDCONFIG pConfig)
1705 + SDIO_STATUS status;
1707 + UINT8 debugLevel = SDDBG_ERROR;
1709 + cmdLength = GET_SDCONFIG_CMD_LEN(pConfig);
1710 + status = SDIO_STATUS_INVALID_PARAMETER;
1713 + /* check buffers and length */
1714 + if (IS_SDCONFIG_CMD_GET(pConfig) || IS_SDCONFIG_CMD_PUT(pConfig)) {
1715 + if ((GET_SDCONFIG_CMD_DATA(PVOID,pConfig) == NULL) || (0 == cmdLength)) {
1720 + switch (GET_SDCONFIG_CMD(pConfig)) {
1721 + case SDCONFIG_FUNC_ACK_IRQ:
1722 + status = SDFunctionAckInterrupt(pDev);
1724 + case SDCONFIG_FUNC_ENABLE_DISABLE:
1725 + if (cmdLength < sizeof(SDCONFIG_FUNC_ENABLE_DISABLE_DATA)) {
1728 + status = SDEnableFunction(pDev,
1729 + GET_SDCONFIG_CMD_DATA(PSDCONFIG_FUNC_ENABLE_DISABLE_DATA,pConfig));
1731 + case SDCONFIG_FUNC_UNMASK_IRQ:
1732 + status = SDMaskUnmaskFunctionIRQ(pDev,FALSE);
1734 + case SDCONFIG_FUNC_MASK_IRQ:
1735 + status = SDMaskUnmaskFunctionIRQ(pDev,TRUE);
1737 + case SDCONFIG_FUNC_SPI_MODE_DISABLE_CRC:
1738 + status = SDSPIModeEnableDisableCRC(pDev,FALSE);
1740 + case SDCONFIG_FUNC_SPI_MODE_ENABLE_CRC:
1741 + status = SDSPIModeEnableDisableCRC(pDev,TRUE);
1743 + case SDCONFIG_FUNC_ALLOC_SLOT_CURRENT:
1744 + status = SDAllocFreeSlotCurrent(pDev,
1746 + GET_SDCONFIG_CMD_DATA(PSDCONFIG_FUNC_SLOT_CURRENT_DATA,pConfig));
1748 + case SDCONFIG_FUNC_FREE_SLOT_CURRENT:
1749 + status = SDAllocFreeSlotCurrent(pDev, FALSE, NULL);
1751 + case SDCONFIG_FUNC_CHANGE_BUS_MODE:
1753 + status = SetOperationalBusMode(pDev,
1754 + GET_SDCONFIG_CMD_DATA(PSDCONFIG_BUS_MODE_DATA,
1757 + case SDCONFIG_FUNC_NO_IRQ_PEND_CHECK:
1758 + status = TryNoIrqPendingCheck(pDev);
1762 + if (GET_SDCONFIG_CMD(pConfig) & SDCONFIG_FLAGS_HC_CONFIG) {
1763 + /* synchronize config requests with busrequests */
1764 + status = SendSyncedHcdBusConfig(pDev,pConfig);
1766 + DBG_PRINT(SDDBG_ERROR,
1767 + ("SDIO Bus Driver: IssueBusConfig - unknown command:0x%X \n",
1768 + GET_SDCONFIG_CMD(pConfig)));
1769 + status = SDIO_STATUS_INVALID_PARAMETER;
1775 + if (!SDIO_SUCCESS(status)) {
1777 + if(status == SDIO_STATUS_FUNC_ENABLE_TIMEOUT ){ /* reduce debug level to avoid timeout error messages */
1778 + debugLevel = SDDBG_TRACE;
1782 + DBG_PRINT(debugLevel,
1783 + ("SDIO Bus Driver: IssueBusConfig - Error in command:0x%X, Buffer:0x%X, Length:%d Err:%d\n",
1784 + GET_SDCONFIG_CMD(pConfig),
1785 + GET_SDCONFIG_CMD_DATA(INT,pConfig),
1786 + cmdLength, status));
1791 +/* start a request */
1792 +static INLINE SDIO_STATUS StartHcdRequest(PSDHCD pHcd, PSDREQUEST pReq)
1794 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
1795 + CT_DECLARE_IRQ_SYNC_CONTEXT();
1797 + if ((pReq->pFunction != NULL) && (pReq->pFunction->Flags & SDFUNCTION_FLAG_REMOVING)) {
1798 + /* this device or function is going away, fail any new requests */
1799 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: StartHcdRequest, fail request 0x%X, device is removing\n", (UINT)pReq));
1800 + pReq->Status = SDIO_STATUS_CANCELED;
1801 + return SDIO_STATUS_SDREQ_QUEUE_FAILED;
1804 + status = _AcquireHcdLock(pHcd);
1806 + if (!SDIO_SUCCESS(status)) {
1807 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to acquire HCD request lock: Err:%d\n", status));
1808 + pReq->Status = SDIO_STATUS_SDREQ_QUEUE_FAILED;
1809 + return SDIO_STATUS_SDREQ_QUEUE_FAILED;
1812 + if (pReq->Flags & SDREQ_FLAGS_QUEUE_HEAD) {
1813 + /* caller wants this request queued to the head */
1815 + /* a completion routine for a barrier request is called
1816 + * while the queue is busy. A barrier request can
1817 + * insert a new request at the head of the queue */
1818 + DBG_ASSERT(IsQueueBusy(&pHcd->RequestQueue));
1819 + QueueRequestToFront(&pHcd->RequestQueue,pReq);
1821 + /* insert in queue at tail */
1822 + QueueRequest(&pHcd->RequestQueue,pReq);
1824 + /* is queue busy ? */
1825 + if (IsQueueBusy(&pHcd->RequestQueue)) {
1826 + /* release lock */
1827 + status = _ReleaseHcdLock(pHcd);
1828 + /* controller is busy already, no need to call the hcd */
1829 + return SDIO_STATUS_PENDING;
1831 + /* mark it as busy */
1832 + MarkQueueBusy(&pHcd->RequestQueue);
1835 + /* remove item from head and set current request */
1836 + SET_CURRENT_REQUEST(pHcd, DequeueRequest(&pHcd->RequestQueue));
1837 + if (CHECK_API_VERSION_COMPAT(pHcd,2,6)) {
1838 + CHECK_HCD_RECURSE(pHcd, pHcd->pCurrentRequest);
1840 + /* release lock */
1841 + status = _ReleaseHcdLock(pHcd);
1842 + /* controller was not busy, call into HCD to process current request */
1843 + status = CallHcdRequest(pHcd);
1848 +/* used by CMD12,CMD13 to save the original completion routine */
1849 +#define GET_BD_RSV_REQUEST_COMPLETION(pR) (PSDEQUEST_COMPLETION)(pR)->pBdRsv1
1850 +#define SET_BD_RSV_REQUEST_COMPLETION(pR,c) (pR)->pBdRsv1 = (PVOID)(c)
1852 +/* used by CMD12 processing to save/restore the original data transfer status */
1853 +#define GET_BD_RSV_ORIG_STATUS(pR) (SDIO_STATUS)(pR)->pBdRsv2
1854 +#define SET_BD_RSV_ORIG_STATUS(pR,s) (pR)->pBdRsv2 = (PVOID)(s)
1856 +/* used by CMD13 processing to get/set polling count */
1857 +#define GET_BD_RSV_STATUS_POLL_COUNT(pR) (INT)(pR)->pBdRsv2
1858 +#define SET_BD_RSV_STATUS_POLL_COUNT(pR,s) (pR)->pBdRsv2 = (PVOID)(s)
1860 +/* used by CMD55 processing to save the second part of the request */
1861 +#define GET_BD_RSV_ORIG_REQ(pR) (PSDREQUEST)(pR)->pBdRsv1
1862 +#define SET_BD_RSV_ORIG_REQ(pR,r) (pR)->pBdRsv1 = (PVOID)(r)
1864 +/* used by all to save HCD */
1865 +#define GET_BD_RSV_HCD(pR) (PSDHCD)(pR)->pBdRsv3
1866 +#define SET_BD_RSV_HCD(pR,h) (pR)->pBdRsv3 = (PVOID)(h)
1868 +static void CMD13CompletionBarrier(PSDREQUEST pReq);
1870 +static INLINE void SetupCMD13(PSDHCD pHcd, PSDREQUEST pReq)
1872 + pReq->Command = CMD13;
1873 + /* sequence must be atomic, queue it to the head and flag as a barrier */
1874 + pReq->Flags = SDREQ_FLAGS_QUEUE_HEAD | SDREQ_FLAGS_BARRIER | SDREQ_FLAGS_TRANS_ASYNC;
1875 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
1876 + pReq->Argument = 0;
1877 + pReq->Flags |= SDREQ_FLAGS_RESP_R2;
1879 + pReq->Flags |= SDREQ_FLAGS_RESP_R1;
1880 + pReq->Argument |= pHcd->CardProperties.RCA << 16;
1882 + /* insert completion */
1883 + pReq->pCompletion = CMD13CompletionBarrier;
1886 +/* CMD13 (GET STATUS) completion */
1887 +static void CMD13CompletionBarrier(PSDREQUEST pReq)
1889 + PSDEQUEST_COMPLETION pOrigCompletion = GET_BD_RSV_REQUEST_COMPLETION(pReq);
1890 + PSDHCD pHcd = GET_BD_RSV_HCD(pReq);
1891 + INT pollingCount = GET_BD_RSV_STATUS_POLL_COUNT(pReq);
1892 + BOOL doCompletion = TRUE;
1893 + UINT32 cardStatus;
1895 + DBG_ASSERT(pOrigCompletion != NULL);
1896 + DBG_ASSERT(pHcd != NULL);
1897 + DBG_PRINT(SDIODBG_REQUESTS, ("+SDIO Bus Driver: CMD13CompletionBarrier (cnt:%d) \n",pollingCount));
1900 + if (!SDIO_SUCCESS(pReq->Status)) {
1904 + cardStatus = SD_R1_GET_CARD_STATUS(pReq->Response);
1906 + if (cardStatus & SD_CS_TRANSFER_ERRORS) {
1907 + DBG_PRINT(SDIODBG_REQUESTS,("SDIO Bus Driver: Card transfer errors : 0x%X \n",cardStatus));
1908 + pReq->Status = SDIO_STATUS_PROGRAM_STATUS_ERROR;
1912 + if (SD_CS_GET_STATE(cardStatus) != SD_CS_STATE_PRG) {
1913 + DBG_PRINT(SDIODBG_REQUESTS,("SDIO Bus Driver: Card programming done \n"));
1917 + DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Card still programming.. \n"));
1920 + if (pollingCount < 0) {
1921 + pReq->Status = SDIO_STATUS_PROGRAM_TIMEOUT;
1922 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: card programming timeout!\n"));
1926 + doCompletion = FALSE;
1928 + SET_BD_RSV_STATUS_POLL_COUNT(pReq, pollingCount);
1929 + SetupCMD13(pHcd,pReq);
1930 + DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: re-issuing CMD13 \n"));
1932 + IssueRequestToHCD(pHcd, pReq);
1937 + if (doCompletion) {
1938 + /* restore original completion routine */
1939 + pReq->pCompletion = pOrigCompletion;
1940 + /* call original completion routine */
1941 + pOrigCompletion(pReq);
1944 + DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: CMD13CompletionBarrier \n"));
1947 +/* command 13 (GET STATUS) preparation */
1948 +static void PrepCMD13Barrier(PSDREQUEST pReq)
1950 + SDIO_STATUS status = pReq->Status;
1951 + PSDHCD pHcd = GET_BD_RSV_HCD(pReq);
1953 + PSDEQUEST_COMPLETION pOrigCompletion = GET_BD_RSV_REQUEST_COMPLETION(pReq);
1955 + DBG_ASSERT(pHcd != NULL);
1956 + DBG_ASSERT(pOrigCompletion != NULL);
1958 + DBG_PRINT(SDIODBG_REQUESTS, ("+SDIO Bus Driver: PrepCMD13Barrier \n"));
1960 + if (SDIO_SUCCESS(status)) {
1961 + /* re-use the request for CMD13 */
1962 + SetupCMD13(pHcd,pReq);
1963 + /* set polling count to a multiple of the Block count, if the BlockCount was
1964 + * zeroed by the HCD, then set it to 1X multiplier */
1965 + pollingCount = max(pBusContext->CMD13PollingMultiplier,
1966 + pBusContext->CMD13PollingMultiplier * (INT)pReq->BlockCount);
1967 + /* initialize count */
1968 + SET_BD_RSV_STATUS_POLL_COUNT(pReq, pollingCount);
1969 + /* re-issue it, we can call IssueRequest here since we are re-using the request */
1970 + IssueRequestToHCD(pHcd, pReq);
1972 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Request Failure (%d) , CMD13 bypassed.\n",status));
1973 + /* call the original completion routine */
1974 + pOrigCompletion(pReq);
1977 + DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: PrepCMD13Barrier (%d) \n",status));
1980 +/* CMD12 completion */
1981 +static void CMD12Completion(PSDREQUEST pReq)
1983 + PSDEQUEST_COMPLETION pOrigCompletion = GET_BD_RSV_REQUEST_COMPLETION(pReq);
1985 + DBG_ASSERT(pOrigCompletion != NULL);
1987 + DBG_PRINT(SDIODBG_REQUESTS, ("+SDIO Bus Driver: CMD12Completion \n"));
1989 + /* restore original completion routine */
1990 + pReq->pCompletion = pOrigCompletion;
1992 + if (SDIO_SUCCESS(pReq->Status)) {
1993 + /* if CMD12 succeeds, we want to return the result of the original
1995 + pReq->Status = GET_BD_RSV_ORIG_STATUS(pReq);
1996 + DBG_PRINT(SDIODBG_REQUESTS,
1997 + ("SDIO Bus Driver: PrepCMD12Completion original status %d \n",pReq->Status));
1999 + /* call original completion routine */
2000 + pOrigCompletion(pReq);
2002 + DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: CMD12Completion \n"));
2005 +/* CMD12 preparation */
2006 +static void PrepCMD12Barrier(PSDREQUEST pReq)
2009 + SDIO_STATUS status = pReq->Status;
2010 + PSDHCD pHcd = GET_BD_RSV_HCD(pReq);
2011 + PSDEQUEST_COMPLETION pOrigCompletion = GET_BD_RSV_REQUEST_COMPLETION(pReq);
2013 + DBG_ASSERT(pHcd != NULL);
2014 + DBG_ASSERT(pOrigCompletion != NULL);
2016 + DBG_PRINT(SDIODBG_REQUESTS, ("+SDIO Bus Driver: PrepCMD12Barrier \n"));
2018 + if (SDIO_SUCCESS(status) || /* only issue CMD12 on success or specific bus errors */
2019 + (SDIO_STATUS_BUS_READ_TIMEOUT == status) ||
2020 + (SDIO_STATUS_BUS_READ_CRC_ERR == status) ||
2021 + (SDIO_STATUS_BUS_WRITE_ERROR == status)) {
2022 + if (!CHECK_API_VERSION_COMPAT(pHcd,2,6)) {
2023 + if (!ForceAllRequestsAsync()) {
2024 + /* clear the call bit as an optimization, note clearing it wholesale here will
2025 + * allow request processing to recurse one more level */
2026 + AtomicTest_Clear(&pHcd->HcdFlags, HCD_REQUEST_CALL_BIT);
2029 + /* re-use the request for CMD12 */
2030 + pReq->Command = CMD12;
2031 + pReq->Argument = 0;
2033 + /* if the data transfer was successful, check for transfer check */
2034 + if (SDIO_SUCCESS(status) &&
2035 + (pReq->Flags & SDREQ_FLAGS_AUTO_TRANSFER_STATUS)) {
2036 + /* original data request requires a transfer status check, which is another
2037 + * barrier request */
2038 + pReq->Flags = SDREQ_FLAGS_RESP_R1B | SDREQ_FLAGS_QUEUE_HEAD | SDREQ_FLAGS_BARRIER |
2039 + SDREQ_FLAGS_TRANS_ASYNC;
2040 + DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: PrepCMD12Barrier , chaining CMD13 \n"));
2041 + /* switch out completion to send the CMD13 next */
2042 + pReq->pCompletion = PrepCMD13Barrier;
2044 + pReq->Flags = SDREQ_FLAGS_RESP_R1B | SDREQ_FLAGS_QUEUE_HEAD | SDREQ_FLAGS_TRANS_ASYNC;
2045 + pReq->pCompletion = CMD12Completion;
2048 + /* save the original data transfer request status */
2049 + SET_BD_RSV_ORIG_STATUS(pReq,status);
2050 + /* re-issue it, we can call IssueRequest here since we are re-using the request */
2051 + IssueRequestToHCD(pHcd, pReq);
2053 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Request Failure (%d) , CMD12 bypassed.\n",status));
2054 + /* call the original completion routine */
2055 + pOrigCompletion(pReq);
2058 + DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: PrepCMD12Barrier (%d) \n",status));
2062 +/* CMD55 barrier - this is a special barrier completion routine, we have to submit the second
2063 + * part of the command command sequence atomically */
2064 +static void CMD55CompletionBarrier(PSDREQUEST pReq)
2066 + SDIO_STATUS status = pReq->Status;
2067 + PSDREQUEST pOrigReq = GET_BD_RSV_ORIG_REQ(pReq);
2068 + PSDHCD pHcd = GET_BD_RSV_HCD(pReq);
2069 + BOOL doCompletion = FALSE;
2071 + DBG_ASSERT(pOrigReq != NULL);
2072 + DBG_ASSERT(pHcd != NULL);
2074 + DBG_PRINT(SDIODBG_REQUESTS, ("+SDIO Bus Driver: CMD55Completion \n"));
2078 + if (!SDIO_SUCCESS(status)) {
2079 + /* command 55 failed */
2080 + pOrigReq->Status = status;
2081 + doCompletion = TRUE;
2085 + if (!(SD_R1_GET_CARD_STATUS(pReq->Response) & SD_CS_APP_CMD)) {
2086 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Card is not accepting CMD55, status:0x%X \n",
2087 + SD_R1_GET_CARD_STATUS(pReq->Response)));
2088 + pOrigReq->Status = SDIO_STATUS_INVALID_COMMAND;
2089 + doCompletion = TRUE;
2093 + if (!CHECK_API_VERSION_COMPAT(pHcd,2,6)) {
2094 + if (!ForceAllRequestsAsync()) {
2095 + AtomicTest_Clear(&pHcd->HcdFlags, HCD_REQUEST_CALL_BIT);
2099 + /* flag the original request to queue to the head */
2100 + pOrigReq->Flags |= SDREQ_FLAGS_QUEUE_HEAD;
2101 + /* submit original request, we cannot call IssueRequestHCD() here because the
2102 + * original request has already gone through IssueRequestHCD() already */
2103 + status = StartHcdRequest(pHcd, pOrigReq);
2105 + if (SDIO_STATUS_PENDING == status) {
2109 + pOrigReq->Status = status;
2111 + if (SDIO_STATUS_SDREQ_QUEUE_FAILED == status) {
2112 + /* never made it to the queue */
2113 + doCompletion = TRUE;
2117 + /* request completed in-line */
2118 + _SDIO_HandleHcdEvent(pHcd, EVENT_HCD_TRANSFER_DONE);
2122 + if (doCompletion) {
2123 + DoRequestCompletion(pOrigReq, pHcd);
2126 + /* free the CMD55 request */
2127 + FreeRequest(pReq);
2129 + DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: CMD55Completion \n"));
2133 +/* synch completion routine */
2134 +static void SynchCompletion(PSDREQUEST pRequest)
2136 + PSIGNAL_ITEM pSignal;
2138 + pSignal = (PSIGNAL_ITEM)pRequest->pCompleteContext;
2139 + DBG_ASSERT(pSignal != NULL);
2140 + if (!SDIO_SUCCESS(SignalSet(&pSignal->Signal))) {
2141 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: SynchCompletion - signal failed \n"));
2147 + * Issue a request to the host controller
2150 + * The following flags are handled internally by the bus driver to guarantee atomicity.
2152 + * SDREQ_FLAGS_APP_CMD - SD Extended commands requiring CMD55 to precede the actual command
2153 + * SDREQ_FLAGS_AUTO_CMD12 - Memory Card Data transfer needs CMD12 to stop transfer
2154 + * (multi-block reads/writes)
2155 + * SDREQ_FLAGS_AUTO_TRANSFER_STATUS - Memory card data transfer needs transfer status polling
2158 + * These request flags require additional commands prepended or appended to the original command
2160 + * The order of command execution :
2162 + * Order Condition Command Issued
2163 + * -------------------------------------------------------------
2164 + * 1. If APP_CMD CMD55 issued.
2165 + * 2. Always Caller command issued.
2166 + * 3. If AUTO_CMD12 CMD12 issued.
2167 + * 4. If AUTO_TRANSFER_STATUS CMD13 issued until card programming is complete
2169 +SDIO_STATUS IssueRequestToHCD(PSDHCD pHcd, PSDREQUEST pReq)
2171 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
2172 + PSIGNAL_ITEM pSignal = NULL;
2173 + BOOL handleFailedReqSubmit = FALSE;
2175 + CLEAR_INTERNAL_REQ_FLAGS(pReq);
2178 + /* mark request in-use */
2179 + ATOMIC_FLAGS internal = AtomicTest_Set(&pReq->InternalFlags, SDBD_PENDING);
2180 + if (internal & (1<<SDBD_PENDING)) {
2181 + DBG_ASSERT_WITH_MSG(FALSE,
2182 + "SDIO Bus Driver: IssueRequestToHCD - request already in use \n");
2183 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Request already in use: 0x%X",(INT)pReq));
2186 + if (!(pReq->Flags & SDREQ_FLAGS_TRANS_ASYNC)) {
2187 + /* caller wants synchronous operation, insert our completion routine */
2188 + pReq->pCompletion = SynchCompletion;
2189 + pSignal = AllocateSignal();
2190 + if (NULL == pSignal) {
2191 + status = SDIO_STATUS_NO_RESOURCES;
2192 + pReq->Status = SDIO_STATUS_NO_RESOURCES;
2193 + handleFailedReqSubmit = TRUE;
2194 + /* no need to continue */
2197 + pReq->pCompleteContext = (PVOID)pSignal;
2200 + if ((pReq->Flags & SDREQ_FLAGS_AUTO_CMD12) &&
2201 + !(pHcd->Attributes & SDHCD_ATTRIB_AUTO_CMD12) &&
2202 + !(IS_HCD_BUS_MODE_SPI(pHcd) && IS_SDREQ_WRITE_DATA(pReq->Flags))) {
2203 + DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Auto CMD12 on Request:0x%08X \n",(INT)pReq));
2204 + /* caller wants CMD12 auto-issued and the HCD does not support it */
2205 + /* setup caller's request as a barrier and replace their completion routine */
2206 + pReq->Flags |= SDREQ_FLAGS_BARRIER;
2207 + /* take off the flag, since the BD will be issuing it */
2208 + pReq->Flags &= ~SDREQ_FLAGS_AUTO_CMD12;
2209 + /* save original completion */
2210 + SET_BD_RSV_REQUEST_COMPLETION(pReq,pReq->pCompletion);
2211 + /* save the HCD we are on */
2212 + SET_BD_RSV_HCD(pReq,pHcd);
2213 + /* use completion for preping CMD12 */
2214 + pReq->pCompletion = PrepCMD12Barrier;
2217 + if (pReq->Flags & SDREQ_FLAGS_AUTO_TRANSFER_STATUS) {
2218 + /* caller wants transfer status checked. If a CMD12
2219 + * barrier request has been setup we let the CMD12 completion take care
2220 + * of setting up the transfer check */
2221 + if (pReq->pCompletion != PrepCMD12Barrier) {
2222 + /* make CMD13 prep a barrier */
2223 + pReq->Flags |= SDREQ_FLAGS_BARRIER;
2224 + /* save original completion */
2225 + SET_BD_RSV_REQUEST_COMPLETION(pReq,pReq->pCompletion);
2226 + /* save the HCD we are on */
2227 + SET_BD_RSV_HCD(pReq,pHcd);
2228 + /* use completion for preping CMD13 */
2229 + pReq->pCompletion = PrepCMD13Barrier;
2233 + /* check app command, the two command sequence must be handled atomically */
2234 + if (pReq->Flags & SDREQ_FLAGS_APP_CMD) {
2235 + PSDREQUEST pCmd55;
2236 + /* allocate request to handle initial CMD55 command */
2237 + pCmd55 = AllocateRequest();
2238 + if (NULL == pCmd55) {
2239 + status = SDIO_STATUS_NO_RESOURCES;
2240 + pReq->Status = SDIO_STATUS_NO_RESOURCES;
2241 + /* complete the caller's request with error */
2242 + handleFailedReqSubmit = TRUE;
2243 + /* no need to continue */
2246 + /* first submit CMD55 */
2248 + pCmd55->Argument = pHcd->CardProperties.RCA << 16;
2249 + /* mark as a barrier request */
2250 + pCmd55->Flags = SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_BARRIER | SDREQ_FLAGS_TRANS_ASYNC;
2251 + pCmd55->Command = CMD55;
2252 + /* call our barrier completion routine when done */
2253 + pCmd55->pCompletion = CMD55CompletionBarrier;
2254 + /* save request and target HCD */
2255 + SET_BD_RSV_ORIG_REQ(pCmd55,pReq);
2256 + SET_BD_RSV_HCD(pCmd55,pHcd);
2257 + /* recursively start the CMD55 request, since the CMD55 is a barrier
2258 + * request, it's completion routine will submit the actual request
2260 + status = IssueRequestToHCD(pHcd, pCmd55);
2263 + /* start the normal request */
2264 + status = StartHcdRequest(pHcd,pReq);
2268 + if (SDIO_STATUS_SDREQ_QUEUE_FAILED == status) {
2269 + handleFailedReqSubmit = TRUE;
2270 + /* no need to continue, clean up at the end */
2274 + /* at this point, the request was either queued or was processed by the
2277 + DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: HCD returned status:%d on request: 0x%X, (CMD:%d) \n",
2278 + status, (INT)pReq, pReq->Command));
2280 + if (status != SDIO_STATUS_PENDING) {
2281 + /* the HCD completed the request within the HCD request callback,
2282 + * check and see if this is a synchronous request */
2283 + if (pSignal != NULL) {
2284 + /* it was synchronous */
2285 + DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Sync-Op signal wait bypassed \n"));
2286 + /* NULL out completion info, there's no need to
2287 + * signal the semaphore */
2288 + pReq->pCompletion = NULL;
2291 + DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Async operation completed in-line \n"));
2292 + /* this was an async call, always return pending */
2293 + status = SDIO_STATUS_PENDING;
2295 + /* process this completed transfer on behalf of the HCD */
2296 + _SDIO_HandleHcdEvent(pHcd, EVENT_HCD_TRANSFER_DONE);
2298 + /* done processing */
2301 + /* I/O is now pending, could be sync or async */
2302 + /* check for synch op */
2303 + if (pSignal != NULL) {
2304 + /* wait for completion */
2305 + DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Sync-Op signal waiting....\n"));
2306 + /* this is not interruptable, as the HCD must complete it. */
2307 + status = SignalWait(&pSignal->Signal);
2308 + /* don't need the signal anymore */
2309 + FreeSignal(pSignal);
2312 + /* note: it is safe to touch pReq since we own
2313 + * the completion routine for synch transfers */
2315 + /* check signal wait status */
2316 + if (!SDIO_SUCCESS(status)) {
2317 + DBG_PRINT(SDDBG_TRACE,
2318 + ("SDIO Bus Driver - IssueRequestToHCD: Synch transfer - signal wait failed, cancelling req 0X%X\n",
2320 + pReq->Status = SDIO_STATUS_CANCELED;
2321 + status = SDIO_STATUS_CANCELED;
2324 + DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Sync-Op woke up\n"));
2325 + /* return the completion status of the request */
2326 + status = pReq->Status;
2328 + DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Async operation Pending \n"));
2333 + /* see if we need to clean up failed submissions */
2334 + if (handleFailedReqSubmit) {
2335 + /* make sure this is cleared */
2336 + AtomicTest_Clear(&pReq->InternalFlags, SDBD_PENDING);
2337 + /* the request processing failed before it was submitted to the HCD */
2338 + /* note: since it never made it to the queue we can touch pReq */
2339 + if (pReq->Flags & SDREQ_FLAGS_TRANS_ASYNC) {
2340 + /* for ASYNC requests, we need to call the completion routine */
2341 + DoRequestCompletion(pReq, pHcd);
2342 + /* return pending for all ASYNC requests */
2343 + status = SDIO_STATUS_PENDING;
2347 + /* check if we need to clean up the signal */
2348 + if (pSignal != NULL) {
2349 + /* make sure this is freed */
2350 + FreeSignal(pSignal);
2352 + /* return status */
2356 +/* documentation for configuration requests */
2357 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2358 + @function: Enable or Disable the SDIO Function
2360 + @function name: SDCONFIG_FUNC_ENABLE_DISABLE
2361 + @prototype: SDCONFIG_FUNC_ENABLE_DISABLE
2362 + @category: PD_Reference
2364 + @input: SDCONFIG_FUNC_ENABLE_DISABLE_DATA - Enable Data structure
2368 + @return: SDIO Status
2370 + @notes: This command code is used in the SDLIB_IssueConfig() API. The command
2371 + uses the SDCONFIG_FUNC_ENABLE_DISABLE_DATA structure. The caller must set the
2372 + EnableFlags and specify the TimeOut value in milliseconds. The TimeOut
2373 + value is used for polling the I/O ready bit. This command returns a status
2374 + of SDIO_STATUS_FUNC_ENABLE_TIMEOUT if the ready bit was not set/cleared
2375 + by the card within the timeout period.
2377 + @example: Example of enabling an I/O function:
2378 + fData.EnableFlags = SDCONFIG_ENABLE_FUNC;
2379 + fData.TimeOut = 500;
2380 + status = SDLIB_IssueConfig(pInstance->pDevice,
2381 + SDCONFIG_FUNC_ENABLE_DISABLE,
2385 + @see also: SDLIB_IssueConfig
2386 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2389 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2390 + @function: Unmask the function's IRQ
2392 + @function name: SDCONFIG_FUNC_UNMASK_IRQ
2393 + @prototype: SDCONFIG_FUNC_UNMASK_IRQ
2394 + @category: PD_Reference
2400 + @return: SDIO Status
2402 + @notes: This command code is used in the SDLIB_IssueConfig() API. The command
2403 + unmasks the IRQ for the I/O function. This request sets the function's
2404 + interrupt enable bit in the INTENABLE register in the
2405 + common register space.
2407 + @example: Example of unmasking interrupt :
2408 + status = SDLIB_IssueConfig(pInstance->pDevice,
2409 + SDCONFIG_FUNC_UNMASK_IRQ,
2413 + @see also: SDCONFIG_FUNC_MASK_IRQ
2414 + @see also: SDLIB_IssueConfig
2416 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2418 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2419 + @function: Mask the function's IRQ
2421 + @function name: SDCONFIG_FUNC_MASK_IRQ
2422 + @prototype: SDCONFIG_FUNC_MASK_IRQ
2423 + @category: PD_Reference
2429 + @return: SDIO Status
2431 + @notes: This command code is used in the SDLIB_IssueConfig() API. The command
2432 + masks the IRQ for the I/O function.
2434 + @example: Example of unmasking interrupt :
2435 + status = SDLIB_IssueConfig(pInstance->pDevice,
2436 + SDCONFIG_FUNC_MASK_IRQ,
2440 + @see also: SDCONFIG_FUNC_UNMASK_IRQ
2441 + @see also: SDLIB_IssueConfig
2443 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2445 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2446 + @function: Acknowledge that the function's IRQ has been handled
2448 + @function name: SDCONFIG_FUNC_ACK_IRQ
2449 + @prototype: SDCONFIG_FUNC_ACK_IRQ
2450 + @category: PD_Reference
2456 + @return: SDIO Status
2458 + @notes: This command code is used in the SDLIB_IssueConfig() API. The command
2459 + indicates to the bus driver that the function driver has handled the
2460 + interrupt. The bus driver will notify the host controller to unmask the
2461 + interrupt source. SDIO interrupts are level triggered and are masked at the
2462 + host controller level until all function drivers have indicated that they
2463 + have handled their respective interrupt. This command can be issued in either
2464 + the IRQ handler or asynchronous IRQ handler.
2466 + @example: Example of acknowledging an interrupt :
2467 + status = SDLIB_IssueConfig(pInstance->pDevice,
2468 + SDCONFIG_FUNC_ACK_IRQ,
2472 + @see also: SDLIB_IssueConfig
2474 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2476 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2477 + @function: Disable SD/MMC/SDIO card CRC checking.
2479 + @function name: SDCONFIG_FUNC_SPI_MODE_DISABLE_CRC
2480 + @prototype: SDCONFIG_FUNC_SPI_MODE_DISABLE_CRC
2481 + @category: PD_Reference
2487 + @return: SDIO Status
2489 + @notes: This command code is used in the SDLIB_IssueConfig() API. The command
2490 + issues CMD59 to disable SPI-CRC checking and requests the host controller
2491 + driver to stop checking the CRC. This is typically used in systems where
2492 + CRC checking is not required and performance is improved if the CRC checking
2493 + is ommitted (i.e. SPI implementations without hardware CRC support).
2495 + @example: Example of disabling SPI CRC checking:
2496 + status = SDLIB_IssueConfig(pInstance->pDevice,
2497 + SDCONFIG_FUNC_SPI_MODE_DISABLE_CRC,
2501 + @see also: SDCONFIG_FUNC_SPI_MODE_ENABLE_CRC
2502 + @see also: SDLIB_IssueConfig
2504 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2506 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2507 + @function: Enable SD/MMC/SDIO card CRC checking.
2509 + @function name: SDCONFIG_FUNC_SPI_MODE_ENABLE_CRC
2510 + @prototype: SDCONFIG_FUNC_SPI_MODE_ENABLE_CRC
2511 + @category: PD_Reference
2517 + @return: SDIO Status
2519 + @notes: This command code is used in the SDLIB_IssueConfig() API. The command
2520 + issues CMD59 to enable SPI-CRC checking and requests the host controller
2521 + driver to generate valid CRCs for commands and data as well as
2522 + check the CRC in responses and incomming data blocks.
2524 + @example: Example of enabling SPI CRC checking:
2525 + status = SDLIB_IssueConfig(pInstance->pDevice,
2526 + SDCONFIG_FUNC_SPI_MODE_ENABLE_CRC,
2530 + @see also: SDCONFIG_FUNC_SPI_MODE_DISABLE_CRC
2531 + @see also: SDLIB_IssueConfig
2533 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2535 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2536 + @function: Allocate slot current for a card function.
2538 + @function name: SDCONFIG_FUNC_ALLOC_SLOT_CURRENT
2539 + @prototype: SDCONFIG_FUNC_ALLOC_SLOT_CURRENT
2540 + @category: PD_Reference
2542 + @input: SDCONFIG_FUNC_SLOT_CURRENT_DATA
2544 + @output: SDCONFIG_FUNC_SLOT_CURRENT_DATA
2546 + @return: SDIO Status
2548 + @notes: This command code is used in the SDLIB_IssueConfig() API. The command
2549 + requests an allocation of slot current to satisfy the power requirements
2550 + of the function. The command uses the SDCONFIG_FUNC_SLOT_CURRENT_DATA
2551 + data structure to pass the required current in mA. Slot current allocation
2552 + is not cummulative and this command should only be issued once by each function
2553 + driver with the worse case slot current usage.
2554 + The command returns SDIO_STATUS_NO_RESOURCES if the
2555 + requirement cannot be met by the host hardware. The SlotCurrent field will
2556 + contain the remaining current available to the slot. The slot current should
2557 + be allocated before the function is enabled using SDCONFIG_FUNC_ENABLE_DISABLE.
2558 + When a function driver is unloaded it should free the slot current allocation
2559 + by using the SDCONFIG_FUNC_FREE_SLOT_CURRENT command.
2561 + @example: Example of allocating slot current:
2562 + slotCurrent.SlotCurrent = 150; // 150 mA
2563 + status = SDLIB_IssueConfig(pInstance->pDevice,
2564 + SDCONFIG_FUNC_ALLOC_SLOT_CURRENT,
2566 + sizeof(slotCurrent));
2569 + @see also: SDCONFIG_FUNC_FREE_SLOT_CURRENT
2570 + @see also: SDLIB_IssueConfig
2572 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2574 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2575 + @function: Free slot current for a card function.
2577 + @function name: SDCONFIG_FUNC_FREE_SLOT_CURRENT
2578 + @prototype: SDCONFIG_FUNC_FREE_SLOT_CURRENT
2579 + @category: PD_Reference
2585 + @return: SDIO Status
2587 + @notes: This command code is used in the SDLIB_IssueConfig() API. The command
2588 + frees the allocated current for a card function. This command should be
2589 + issued only once (per function) and only after an allocation was successfully made.
2591 + @example: Example of freeing slot current:
2592 + status = SDLIB_IssueConfig(pInstance->pDevice,
2593 + SDCONFIG_FUNC_FREE_SLOT_CURRENT,
2597 + @see also: SDCONFIG_FUNC_ALLOC_SLOT_CURRENT
2598 + @see also: SDLIB_IssueConfig
2600 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2602 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2603 + @function: Set the bus mode for the SD/SDIO card.
2605 + @function name: SDCONFIG_FUNC_CHANGE_BUS_MODE
2606 + @prototype: SDCONFIG_FUNC_CHANGE_BUS_MODE
2607 + @category: PD_Reference
2613 + @return: SDIO Status
2615 + @notes: This command code is used in the SDLIB_IssueConfig() API. The command
2616 + alters the card's bus mode (width and clock rate) to a driver specified
2617 + value. The driver must read the current bus mode flags, modify if necessary
2618 + and pass the value in the SDCONFIG_BUS_MODE_DATA structure.
2619 + If the bus width is changed (1 or 4 bit) the caller must adjust the mode flags
2620 + for the new width. Cards cannot be switched between 1/4 bit and SPI mode.
2621 + Switching to or from SPI mode requires a power cycle. Adjustments to the clock
2622 + rate is immediate on the next bus transaction. The actual clock rate value is
2623 + limited by the host controller and is reported in the ClockRate field when the
2624 + command completes successfully.
2625 + The bus mode change is card wide and may affect other SDIO functions on
2626 + multi-function cards. Use this feature with caution. This feature should NOT be
2627 + used to dynamically control clock rates during runtime and should only be used
2628 + at card initialization. Changing the bus mode must be done with SDIO function
2629 + interrupts masked.
2630 + This request can block and must only be called from a schedulable context.
2632 + @example: Example of changing the clock rate:
2633 + SDCONFIG_BUS_MODE_DATA busSettings;
2634 + ZERO_OBJECT(busSettings);
2635 + // get current bus flags and keep the same bus width
2636 + busSettings.BusModeFlags = SDDEVICE_GET_BUSMODE_FLAGS(pInstance->pDevice);
2637 + busSettings.ClockRate = 8000000; // adjust clock to 8 Mhz
2638 + // issue config request to override clock rate
2639 + status = SDLIB_IssueConfig(pInstance->pDevice,
2640 + SDCONFIG_FUNC_CHANGE_BUS_MODE,
2642 + sizeof(SDCONFIG_BUS_MODE_DATA));
2644 + @see also: SDDEVICE_GET_BUSMODE_FLAGS
2645 + @see also: SDLIB_IssueConfig
2647 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2649 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2650 + @function: Get the debug level of the underlying host controller driver.
2652 + @function name: SDCONFIG_GET_HCD_DEBUG
2653 + @prototype: SDCONFIG_GET_HCD_DEBUG
2654 + @category: PD_Reference
2658 + @output: CT_DEBUG_LEVEL
2660 + @return: SDIO Status
2662 + @notes: This command code is used in the SDLIB_IssueConfig() API. The command
2663 + requests the current debug level of the HCD driver. This API is useful for
2664 + saving the current debug level of the HCD prior to issuing SDCONFIG_SET_HCD_DEBUG
2665 + in order to increase the verbosity of the HCD. This API should be used only for
2666 + debugging purposes. If multiple functions attempt to save and set the HCD debug
2667 + level simultanously, the final debug level will be unknown. Not all HCDs support
2670 + @example: Example of saving the debug level:
2671 + CT_DEBUG_LEVEL savedDebug;
2672 + status = SDLIB_IssueConfig(pInstance->pDevice,
2673 + SDCONFIG_GET_HCD_DEBUG,
2675 + sizeof(savedDebug));
2677 + @see also: SDCONFIG_SET_HCD_DEBUG
2678 + @see also: SDLIB_IssueConfig
2680 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2682 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2683 + @function: Set the debug level of the underlying host controller driver.
2685 + @function name: SDCONFIG_SET_HCD_DEBUG
2686 + @prototype: SDCONFIG_SET_HCD_DEBUG
2687 + @category: PD_Reference
2689 + @input: CT_DEBUG_LEVEL
2693 + @return: SDIO Status
2695 + @notes: This command code is used in the SDLIB_IssueConfig() API. The command
2696 + sets the current debug level of the HCD driver. This API is useful for
2697 + setting the debug level of the HCD programatically for debugging purposes.
2698 + If multiple functions attempt to save and set the HCD debug
2699 + level simultanously, the final debug level will be unknown. Not all HCDs support
2702 + @example: Example of setting the debug level:
2703 + CT_DEBUG_LEVEL setDebug = 15;
2704 + status = SDLIB_IssueConfig(pInstance->pDevice,
2705 + SDCONFIG_GET_HCD_DEBUG,
2707 + sizeof(setDebug));
2709 + @see also: SDCONFIG_GET_HCD_DEBUG
2710 + @see also: SDLIB_IssueConfig
2712 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2714 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2715 + @function: Instruct the bus driver to not check the SDIO card interrupt pending
2716 + register on card interrupts, if possible.
2718 + @function name: SDCONFIG_FUNC_NO_IRQ_PEND_CHECK
2719 + @prototype: SDCONFIG_FUNC_NO_IRQ_PEND_CHECK
2720 + @category: PD_Reference
2726 + @return: SDIO Status
2728 + @notes: This command code is used in the SDLIB_IssueConfig() API. The command instructs the
2729 + bus driver to skip checking the card interrupt pending register on each card
2730 + interrupt. The bus driver will assume the function is interrupting and immediately start
2731 + the interrupt processing stage. This option is only valid for single function cards.
2732 + The bus driver will reject the command for a card with more than 1 function.
2733 + For single function cards, this can improve interrupt response time.
2735 + @example: Example of skipping IRQ pending checks:
2737 + status = SDLIB_IssueConfig(pInstance->pDevice,
2738 + SDCONFIG_FUNC_NO_IRQ_PEND_CHECK,
2742 + @see also: SDLIB_IssueConfig
2744 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2745 diff --git a/drivers/sdio/stack/busdriver/sdio_bus_events.c b/drivers/sdio/stack/busdriver/sdio_bus_events.c
2746 new file mode 100644
2747 index 0000000..5b3148d
2749 +++ b/drivers/sdio/stack/busdriver/sdio_bus_events.c
2751 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2752 +@file: sdio_bus_events.c
2754 +@abstract: OS independent bus driver support
2756 +#notes: this file contains various event handlers and helpers
2758 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
2762 + * This program is free software; you can redistribute it and/or modify
2763 + * it under the terms of the GNU General Public License version 2 as
2764 + * published by the Free Software Foundation;
2766 + * Software distributed under the License is distributed on an "AS
2767 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
2768 + * implied. See the License for the specific language governing
2769 + * rights and limitations under the License.
2771 + * Portions of this code were developed with information supplied from the
2772 + * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply:
2774 + * The following conditions apply to the release of the SD simplified specification (�Simplified
2775 + * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete
2776 + * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided
2777 + * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified
2778 + * Specification may require a license from the SD Card Association or other third parties.
2780 + * The information contained in the Simplified Specification is presented only as a standard
2781 + * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any
2782 + * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for
2783 + * any damages, any infringements of patents or other right of the SD Card Association or any third
2784 + * parties, which may result from its use. No license is granted by implication, estoppel or otherwise
2785 + * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall
2786 + * be construed as an obligation by the SD Card Association to disclose or distribute any technical
2787 + * information, know-how or other confidential information to any third party.
2790 + * The initial developers of the original code are Seung Yi and Paul Lever
2792 + * sdio@atheros.com
2796 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2797 +#define MODULE_NAME SDBUSDRIVER
2798 +#include <linux/sdio/ctsystem.h>
2799 +#include <linux/sdio/sdio_busdriver.h>
2800 +#include <linux/sdio/sdio_lib.h>
2801 +#include "_busdriver.h"
2802 +#include <linux/sdio/_sdio_defs.h>
2803 +#include <linux/sdio/mmc_defs.h>
2805 +static SDIO_STATUS ScanSlotForCard(PSDHCD pHcd,
2806 + PBOOL pCardPresent);
2807 +static void GetPendingIrqComplete(PSDREQUEST pReq);
2808 +static void ProcessPendingIrqs(PSDHCD pHcd, UINT8 IntPendingMsk);
2811 + * DeviceDetach - tell core a device was removed from a slot
2813 +SDIO_STATUS DeviceDetach(PSDHCD pHcd)
2815 + SDCONFIG_SDIO_INT_CTRL_DATA irqData;
2817 + ZERO_OBJECT(irqData);
2819 + DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: DeviceDetach\n"));
2820 + /* tell any function drivers we are gone */
2821 + RemoveHcdFunctions(pHcd);
2822 + /* delete the devices associated with this HCD */
2823 + DeleteDevices(pHcd);
2824 + /* check and see if there are any IRQs that were left enabled */
2825 + if (pHcd->IrqsEnabled) {
2826 + irqData.SlotIRQEnable = FALSE;
2827 + /* turn off IRQ detection in HCD */
2828 + _IssueConfig(pHcd,SDCONFIG_SDIO_INT_CTRL,(PVOID)&irqData, sizeof(irqData));
2831 + /* reset hcd state */
2832 + ResetHcdState(pHcd);
2834 + DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: DeviceDetach\n"));
2835 + return SDIO_STATUS_SUCCESS;
2839 + * DeviceAttach - tell core a device was inserted into a slot
2841 +SDIO_STATUS DeviceAttach(PSDHCD pHcd)
2843 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
2844 + PSDDEVICE pDevice = NULL;
2848 + if (IS_CARD_PRESENT(pHcd)) {
2849 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: DeviceAttach called on occupied slot!\n"));
2850 + return SDIO_STATUS_ERROR;
2853 + DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: DeviceAttach bdctxt:0x%X \n", (UINT32)pBusContext));
2855 + if (IS_HCD_RAW(pHcd)) {
2856 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: RAW HCD (%s) device attach \n",pHcd->pName));
2857 + /* this is a raw HCD */
2858 + memset(&pHcd->CardProperties,0,sizeof(pHcd->CardProperties));
2859 + pHcd->CardProperties.Flags = CARD_RAW;
2860 + pHcd->CardProperties.IOFnCount = 0;
2861 + /* for raw HCD, set up minimum parameters
2862 + * since we cannot determine these values using any standard, use values
2863 + * reported by the HCD */
2864 + /* the operational rate is just the max clock rate reported */
2865 + pHcd->CardProperties.OperBusClock = pHcd->MaxClockRate;
2866 + /* the max bytes per data transfer is just the max bytes per block */
2867 + pHcd->CardProperties.OperBlockLenLimit = pHcd->MaxBytesPerBlock;
2868 + /* if the raw HCD uses blocks to transfer, report the operational size
2869 + * from the HCD max value */
2870 + pHcd->CardProperties.OperBlockCountLimit = pHcd->MaxBlocksPerTrans;
2871 + /* set the slot preferred voltage */
2872 + pHcd->CardProperties.CardVoltage = pHcd->SlotVoltagePreferred;
2874 + /* initialize this card and get card properties */
2875 + if (!SDIO_SUCCESS((status = SDInitializeCard(pHcd)))) {
2876 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: DeviceAttach, failed to initialize card, %d\n",
2882 + /* check for SD or MMC, this must be done first as the query may involve
2883 + * de-selecting the card */
2885 + if (!(pHcd->CardProperties.Flags & (CARD_MMC | CARD_SD | CARD_RAW))) {
2886 + /* none of these were discovered */
2889 + pDevice = AllocateDevice(pHcd);
2890 + if (NULL == pDevice) {
2893 + if (pHcd->CardProperties.Flags & CARD_RAW) {
2894 + /* set function number to 1 for IRQ processing */
2895 + SDDEVICE_SET_SDIO_FUNCNO(pDevice,1);
2897 + /* get the ID info for the SD/MMC Card */
2898 + if (!SDIO_SUCCESS((status = SDQuerySDMMCInfo(pDevice)))) {
2899 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: DeviceAttach, query SDMMC Info failed \n"));
2900 + FreeDevice(pDevice);
2904 + AddDeviceToList(pDevice);
2905 + /* look for a function driver to handle this card */
2906 + ProbeForFunction(pDevice, pHcd);
2909 + /* create a device for each I/O function */
2910 + for(ii= 1; ii <= pHcd->CardProperties.IOFnCount; ii++) {
2911 + pDevice = AllocateDevice(pHcd);
2912 + if (NULL == pDevice) {
2915 + /* set the function number */
2916 + SDDEVICE_SET_SDIO_FUNCNO(pDevice,ii);
2917 + /* get the ID info for each I/O function */
2918 + if (!SDIO_SUCCESS((status = SDQuerySDIOInfo(pDevice)))) {
2919 + DBG_PRINT(SDDBG_ERROR,
2920 + ("SDIO Bus Driver: DeviceAttach, could not query SDIO Info, funcNo:%d status:%d \n",
2922 + FreeDevice(pDevice);
2923 + /* keep loading other functions */
2926 + AddDeviceToList(pDevice);
2927 + /* look for a function driver to handle this card */
2928 + ProbeForFunction(pDevice, pHcd);
2932 + DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: DeviceAttach \n"));
2936 +static INLINE void CompleteRequestCheckCancel(PSDHCD pHcd, PSDREQUEST pReqToComplete)
2938 + BOOL cancel = FALSE;
2939 + PSDFUNCTION pFunc = NULL;
2941 + /* handle cancel of current request */
2942 + if (pReqToComplete->Flags & SDREQ_FLAGS_CANCELED) {
2943 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - _SDIO_HandleHcdEvent: cancelling req 0X%X\n", (UINT)pReqToComplete));
2945 + pReqToComplete->Status = SDIO_STATUS_CANCELED;
2946 + pFunc = pReqToComplete->pFunction;
2947 + DBG_ASSERT(pFunc != NULL);
2950 + DoRequestCompletion(pReqToComplete, pHcd);
2953 + SignalSet(&pFunc->CleanupReqSig);
2957 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2958 + @function: Indicate to the SDIO bus driver (core) of an event in the host controller
2961 + @function name: SDIO_HandleHcdEvent
2962 + @prototype: SDIO_STATUS SDIO_HandleHcdEvent(PSDHCD pHcd, HCD_EVENT Event)
2963 + @category: HD_Reference
2965 + @input: pHcd - the host controller structure that was registered
2966 + HCD_EVENT - event code
2970 + @return: SDIO_STATUS
2973 + The host controller driver can indicate asynchronous events by calling this
2974 + function with an appropriate event code. Refer to the HDK help manual for
2975 + more information on the event types
2977 + @example: Example of indicating a card insertion event:
2978 + SDIO_HandleHcdEvent(&Hcd, EVENT_HCD_ATTACH);
2980 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2981 +SDIO_STATUS _SDIO_HandleHcdEvent(PSDHCD pHcd, HCD_EVENT Event)
2984 + PSDREQUEST pReqToComplete = NULL;
2985 + PSDREQUEST pNextReq = NULL;
2986 + SDIO_STATUS status;
2987 + CT_DECLARE_IRQ_SYNC_CONTEXT();
2989 + DBG_PRINT(SDIODBG_HCD_EVENTS, ("SDIO Bus Driver: _SDIO_HandleHcdEvent, event type 0x%X, HCD:0x%X\n",
2990 + Event, (UINT)pHcd));
2992 + if (Event == EVENT_HCD_TRANSFER_DONE) {
2993 + pReq = GET_CURRENT_REQUEST(pHcd);
2994 + if (NULL == pReq) {
2995 + DBG_ASSERT(FALSE);
2996 + return SDIO_STATUS_ERROR;
2999 + status = _AcquireHcdLock(pHcd);
3000 + if (SDIO_SUCCESS(status)) {
3001 + /* null out the current request */
3002 + SET_CURRENT_REQUEST(pHcd, NULL);
3003 + status = _ReleaseHcdLock(pHcd);
3005 + DBG_PRINT(SDDBG_ERROR,
3006 + ("SDIO Bus Driver: SDIO_HandleHcdEvent Failed to acquire HCD lock \n"));
3007 + return SDIO_STATUS_ERROR;
3010 + /* note: the queue is still marked busy to prevent other threads/tasks from starting
3011 + * new requests while we are handling completion , some completed requests are
3012 + * marked as barrier requests which must be handled atomically */
3014 + status = pReq->Status;
3015 + DBG_PRINT(SDIODBG_REQUESTS,
3016 + ("+SDIO Bus Driver: Handling Transfer Done (CMD:%d, Status:%d) from HCD:0x%08X \n",
3017 + pReq->Command, status, (INT)pHcd));
3018 + /* check SPI mode conversion */
3019 + if (IS_HCD_BUS_MODE_SPI(pHcd) && SDIO_SUCCESS(status)) {
3020 + if (!(pReq->Flags & SDREQ_FLAGS_RESP_SKIP_SPI_FILT) && !(pReq->Flags & SDREQ_FLAGS_PSEUDO) &&
3021 + (GET_SDREQ_RESP_TYPE(pReq->Flags) != SDREQ_FLAGS_NO_RESP)) {
3022 + ConvertSPI_Response(pReq, NULL);
3026 + DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Completing Request:0x%08X \n",(INT)pReq));
3028 + if (!SDIO_SUCCESS(status) &&
3029 + (status != SDIO_STATUS_CANCELED) &&
3030 + !(pReq->Flags & SDREQ_FLAGS_CANCELED) &&
3031 + (pReq->RetryCount > 0)) {
3032 + /* retry the request if it failed, was NOT cancelled and the retry count
3033 + * is greater than zero */
3034 + pReq->RetryCount--;
3035 + pReqToComplete = NULL;
3036 + /* clear SPI converted flag */
3037 + pReq->Flags &= ~SDREQ_FLAGS_RESP_SPI_CONVERTED;
3040 + /* complete the request */
3041 + if (pReq->Flags & SDREQ_FLAGS_BARRIER) {
3042 + /* a barrier request must be completed before the next bus request is
3044 + CompleteRequestCheckCancel(pHcd, pReq);
3045 + if (!ForceAllRequestsAsync()) {
3046 + if (CHECK_API_VERSION_COMPAT(pHcd,2,6)) {
3047 + /* the request was completed, decrement recursion count */
3048 + status = _AcquireHcdLock(pHcd);
3049 + if (!SDIO_SUCCESS(status)) {
3052 + pHcd->Recursion--;
3053 + DBG_ASSERT(pHcd->Recursion >= 0);
3054 + status = _ReleaseHcdLock(pHcd);
3057 + AtomicTest_Clear(&pHcd->HcdFlags, HCD_REQUEST_CALL_BIT);
3060 + pReqToComplete = NULL;
3062 + /* complete this after the next request has
3064 + pReqToComplete = pReq;
3068 + /* acquire the hcd lock to look at the queues */
3069 + status = _AcquireHcdLock(pHcd);
3070 + if (SDIO_SUCCESS(status)) {
3071 + if (pReqToComplete != NULL) {
3072 + /* queue the request that was completed */
3073 + QueueRequest(&pHcd->CompletedRequestQueue, pReqToComplete);
3075 + if (NULL == pNextReq) {
3076 + /* check the queue for the next request */
3077 + DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Checking queue.. \n"));
3078 + /* check to see if the HCD was already working on one. This occurs if
3079 + * the current request being completed was a barrier request and the
3080 + * barrier completion routine submitted a new request to the head of the
3082 + if (GET_CURRENT_REQUEST(pHcd) == NULL) {
3083 + pNextReq = DequeueRequest(&pHcd->RequestQueue);
3084 + if (NULL == pNextReq) {
3085 + /* nothing in the queue, mark it not busy */
3086 + MarkQueueNotBusy(&pHcd->RequestQueue);
3087 + DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Queue idle \n"));
3089 + DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Next request in queue: 0x%X \n",
3093 + DBG_PRINT(SDIODBG_REQUESTS,
3094 + ("SDIO Bus Driver: Busy Queue from barrier request \n"));
3098 + if (pNextReq != NULL) {
3099 + /* a new request will be submitted to the HCD below,
3100 + * check recursion while we have the lock */
3101 + if (CHECK_API_VERSION_COMPAT(pHcd,2,6)) {
3102 + CHECK_HCD_RECURSE(pHcd,pNextReq);
3105 + status = _ReleaseHcdLock(pHcd);
3107 + DBG_PRINT(SDDBG_ERROR,
3108 + ("SDIO Bus Driver: SDIO_HandleHcdEvent Failed to acquire HCD lock \n"));
3109 + return SDIO_STATUS_ERROR;
3111 + /* check for the next request to issue */
3112 + if (pNextReq != NULL) {
3113 + DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Starting Next Request: 0x%X \n",
3115 + SET_CURRENT_REQUEST(pHcd,pNextReq);
3116 + status = CallHcdRequest(pHcd);
3117 + /* check and see if the HCD completed the request in the callback */
3118 + if (status != SDIO_STATUS_PENDING) {
3119 + /* recurse and process the request */
3120 + _SDIO_HandleHcdEvent(pHcd, EVENT_HCD_TRANSFER_DONE);
3124 + /* now empty the completed request queue
3125 + * - this guarantees in-order completion even during recursion */
3126 + status = _AcquireHcdLock(pHcd);
3127 + if (SDIO_SUCCESS(status)) {
3129 + pReqToComplete = DequeueRequest(&pHcd->CompletedRequestQueue);
3130 + status = _ReleaseHcdLock(pHcd);
3131 + if (pReqToComplete != NULL) {
3132 + CompleteRequestCheckCancel(pHcd, pReqToComplete);
3133 + if (!CHECK_API_VERSION_COMPAT(pHcd,2,6)) {
3134 + if (!ForceAllRequestsAsync()) {
3136 + AtomicTest_Clear(&pHcd->HcdFlags, HCD_REQUEST_CALL_BIT);
3139 + /* re-acquire lock */
3140 + status = _AcquireHcdLock(pHcd);
3141 + if (!SDIO_SUCCESS(status)) {
3142 + return SDIO_STATUS_ERROR;
3144 + if (CHECK_API_VERSION_COMPAT(pHcd,2,6)) {
3145 + if (!ForceAllRequestsAsync()) {
3146 + /* while we have the lock, decrement recursion count each time
3147 + * we complete a request */
3148 + pHcd->Recursion--;
3149 + DBG_ASSERT(pHcd->Recursion >= 0);
3158 + DBG_PRINT(SDDBG_ERROR,
3159 + ("SDIO Bus Driver: SDIO_HandleHcdEvent Failed to acquire HCD lock \n"));
3160 + return SDIO_STATUS_ERROR;
3162 + DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: Transfer Done Handled \n"));
3163 + return SDIO_STATUS_SUCCESS;
3167 + case EVENT_HCD_ATTACH:
3168 + case EVENT_HCD_DETACH:
3169 + /* card detect helper does the actual attach detach */
3170 + return PostCardDetectEvent(pBusContext,Event,pHcd);
3171 + case EVENT_HCD_SDIO_IRQ_PENDING:
3172 + return DeviceInterrupt(pHcd);
3174 + DBG_PRINT(SDDBG_ERROR, ("-SDIO Bus Driver: SDIO_HandleHcdEvent, invalid event type 0x%X, HCD:0x%X\n",
3175 + Event, (UINT)pHcd));
3176 + return SDIO_STATUS_INVALID_PARAMETER;
3181 +/* card detect helper function */
3182 +THREAD_RETURN CardDetectHelperFunction(POSKERNEL_HELPER pHelper)
3184 + SDIO_STATUS status;
3185 + HCD_EVENT_MESSAGE message;
3188 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - CardDetectHelperFunction starting up: 0x%X \n", (INT)pHelper));
3192 + /* wait for wake up event */
3193 + status = SD_WAIT_FOR_WAKEUP(pHelper);
3194 + if (!SDIO_SUCCESS(status)) {
3195 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver - Card Detect Helper Semaphore Pend Error:%d \n",
3200 + if (SD_IS_HELPER_SHUTTING_DOWN(pHelper)) {
3201 + /* cleanup message queue on shutdown */
3203 + length = sizeof(message);
3204 + /* get a message */
3205 + status = SDLIB_GetMessage(pBusContext->pCardDetectMsgQueue,
3206 + &message, &length);
3207 + if (!SDIO_SUCCESS(status)) {
3210 + if (message.pHcd != NULL) {
3211 + /* decrement HCD reference count */
3212 + OS_DecHcdReference(message.pHcd);
3220 + length = sizeof(message);
3221 + /* get a message */
3222 + status = SDLIB_GetMessage(pBusContext->pCardDetectMsgQueue,
3223 + &message, &length);
3224 + if (!SDIO_SUCCESS(status)) {
3228 + switch (message.Event) {
3229 + case EVENT_HCD_ATTACH:
3230 + DeviceAttach(message.pHcd);
3232 + case EVENT_HCD_DETACH:
3233 + DeviceDetach(message.pHcd);
3235 + case EVENT_HCD_CD_POLLING:
3236 + /* run detector */
3240 + DBG_ASSERT(FALSE);
3244 + if (message.pHcd != NULL) {
3245 + /* message was processed, decrement reference count */
3246 + OS_DecHcdReference(message.pHcd);
3251 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - Card Detect Helper Exiting.. \n"));
3256 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3257 + RunCardDetect - run card detect on host controller slots that require polling
3261 + Notes: This function is called from the card detect timer thread
3262 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
3263 +void RunCardDetect(void)
3265 + BOOL CDPollingRequired = FALSE;
3266 + PSDLIST pListItem;
3270 + DBG_PRINT(SDIODBG_CD_TIMER, ("+SDIO Bus Driver: RunCardDetect\n"));
3272 + /* protect the HCD list */
3273 + if (!SDIO_SUCCESS(SemaphorePendInterruptable(&pBusContext->HcdListSem))) {
3274 + DBG_ASSERT(FALSE);
3275 + return; /* wait interrupted */
3277 + /* while we are running the detector we are blocking HCD removal*/
3278 + SDITERATE_OVER_LIST(&pBusContext->HcdList, pListItem) {
3279 + pHcd = CONTAINING_STRUCT(pListItem, SDHCD, SDList);
3280 + /* does the HCD require polling ? */
3281 + if (pHcd->Attributes & SDHCD_ATTRIB_SLOT_POLLING) {
3282 + DBG_PRINT(SDIODBG_CD_TIMER, ("SDIO Bus Driver: Found HCD requiring polling \n"));
3283 + /* set flag to queue the timer */
3284 + CDPollingRequired = TRUE;
3285 + if (IS_CARD_PRESENT(pHcd)) {
3286 + /* there is a device in the slot */
3287 + cardPresent = TRUE;
3288 + if (SDIO_SUCCESS(ScanSlotForCard(pHcd,&cardPresent))) {
3289 + if (!cardPresent) {
3290 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver CD Polling.. Card Removal Detected\n"));
3291 + DeviceDetach(pHcd);
3295 + cardPresent = FALSE;
3296 + if (SDIO_SUCCESS(ScanSlotForCard(pHcd,&cardPresent))) {
3297 + if (cardPresent) {
3298 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver CD Polling.. Card Detected\n"));
3299 + DeviceAttach(pHcd);
3305 + DBG_PRINT(SDIODBG_CD_TIMER, ("SDIO Bus Driver: moving to next hcd:0x%X \n",
3306 + (INT)pListItem->pNext));
3309 + /* check if we need to queue the timer */
3310 + if (CDPollingRequired && !pBusContext->CDTimerQueued) {
3311 + pBusContext->CDTimerQueued = TRUE;
3312 + DBG_PRINT(SDIODBG_CD_TIMER, ("SDIO Bus Driver: Queuing Card detect timer \n"));
3313 + if (!SDIO_SUCCESS(
3314 + QueueTimer(SDIOBUS_CD_TIMER_ID, pBusContext->CDPollingInterval))) {
3315 + DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: failed to queue CD timer \n"));
3316 + pBusContext->CDTimerQueued = FALSE;
3319 + /* release HCD list lock */
3320 + SemaphorePost(&pBusContext->HcdListSem);
3321 + DBG_PRINT(SDIODBG_CD_TIMER, ("-SDIO Bus Driver: RunCardDetect\n"));
3325 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3326 + ScanSlotForCard - scan slot for a card
3327 + Input: pHcd - the hcd
3328 + Output: pCardPresent - card present flag (set/cleared on return)
3331 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
3332 +static SDIO_STATUS ScanSlotForCard(PSDHCD pHcd,PBOOL pCardPresent)
3334 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
3337 + DBG_PRINT(SDIODBG_CD_TIMER, ("+SDIO Bus Driver: ScanSlotForCard\n"));
3340 + if (!IS_CARD_PRESENT(pHcd)) {
3342 + dbgLvl = DBG_GET_DEBUG_LEVEL();
3343 + DBG_SET_DEBUG_LEVEL(SDDBG_WARN);
3344 + status = CardInitSetup(pHcd);
3345 + DBG_SET_DEBUG_LEVEL(dbgLvl);
3346 + if (!SDIO_SUCCESS(status)) {
3349 + /* issue go-idle */
3350 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
3351 + _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_RESP_R1,NULL);
3353 + _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_NO_RESP,NULL);
3356 + status = TestPresence(pHcd,CARD_SDIO,NULL);
3357 + if (SDIO_SUCCESS(status)) {
3358 + *pCardPresent = TRUE;
3361 + /* issue go-idle */
3362 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
3363 + _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_RESP_R1,NULL);
3365 + _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_NO_RESP,NULL);
3368 + status = TestPresence(pHcd,CARD_SD,NULL);
3369 + if (SDIO_SUCCESS(status)) {
3370 + *pCardPresent = TRUE;
3373 + /* issue go-idle */
3374 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
3375 + _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_RESP_R1,NULL);
3377 + _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_NO_RESP,NULL);
3380 + status = TestPresence(pHcd,CARD_MMC,NULL);
3381 + if (SDIO_SUCCESS(status)) {
3382 + *pCardPresent = TRUE;
3386 + if (pHcd->CardProperties.Flags & CARD_SDIO) {
3387 +#ifdef DUMP_INT_PENDING
3389 + /* handy debug prints to check interrupt status and print pending register */
3390 + status = Cmd52ReadByteCommon(pHcd->pPseudoDev, SDIO_INT_ENABLE_REG, &temp);
3391 + if (SDIO_SUCCESS(status) && (temp != 0)) {
3392 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: INT Enable Reg: 0x%2.2X\n", temp));
3393 + status = Cmd52ReadByteCommon(pHcd->pPseudoDev, SDIO_INT_PENDING_REG, &temp);
3394 + if (SDIO_SUCCESS(status)) {
3395 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: INT Pend Reg: 0x%2.2X\n", temp));
3399 + /* for SDIO cards, read the revision register */
3400 + status = Cmd52ReadByteCommon(pHcd->pPseudoDev, CCCR_SDIO_REVISION_REG, &temp);
3401 + } else if (pHcd->CardProperties.Flags & (CARD_SD | CARD_MMC)) {
3402 + /* for SD/MMC cards, issue SEND_STATUS */
3403 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
3404 + /* SPI uses the SPI R2 response */
3405 + status = _IssueSimpleBusRequest(pHcd,
3408 + SDREQ_FLAGS_RESP_R2,
3411 + status = _IssueSimpleBusRequest(pHcd,
3413 + (pHcd->CardProperties.RCA << 16),
3414 + SDREQ_FLAGS_RESP_R1,NULL);
3417 + DBG_ASSERT(FALSE);
3419 + if (!SDIO_SUCCESS(status)) {
3420 + /* card is gone */
3421 + *pCardPresent = FALSE;
3426 + if (status == SDIO_STATUS_BUS_RESP_TIMEOUT) {
3427 + status = SDIO_STATUS_SUCCESS;
3430 + DBG_PRINT(SDIODBG_CD_TIMER, ("-SDIO Bus Driver: ScanSlotForCard status:%d\n",
3436 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3437 + DeviceInterrupt - handle device interrupt
3438 + Input: pHcd - host controller
3442 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
3443 +SDIO_STATUS DeviceInterrupt(PSDHCD pHcd)
3445 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
3446 + SDIO_STATUS status2;
3447 + PSDREQUEST pReq = NULL;
3448 + CT_DECLARE_IRQ_SYNC_CONTEXT();
3450 + DBG_PRINT(SDIODBG_FUNC_IRQ, ("+SDIO Bus Driver: DeviceInterrupt\n"));
3452 + if (!IS_CARD_PRESENT(pHcd)) {
3453 + DBG_PRINT(SDDBG_ERROR, ("-SDIO Bus Driver: Device interrupt asserted on empty slot!\n"));
3454 + return SDIO_STATUS_ERROR;
3458 + /* for RAW HCDs or HCDs flagged for single-function IRQ optimization */
3459 + if (IS_HCD_RAW(pHcd) || (pHcd->HcdFlags & (1 << HCD_IRQ_NO_PEND_CHECK))) {
3460 + status = _AcquireHcdLock(pHcd);
3461 + if (!SDIO_SUCCESS(status)) {
3464 + if (pHcd->IrqProcState != SDHCD_IDLE) {
3465 + status = SDIO_STATUS_ERROR;
3466 + status2 = _ReleaseHcdLock(pHcd);
3468 + DBG_PRINT(SDIODBG_FUNC_IRQ, ("SDIO Bus Driver : Device Interrupt \n"));
3469 + /* mark that we are processing */
3470 + pHcd->IrqProcState = SDHCD_IRQ_PENDING;
3471 + status2 = _ReleaseHcdLock(pHcd);
3472 + /* process Irqs for raw hcds or HCDs with the single function optimization */
3473 + /* force processing of function 1 interrupt */
3474 + ProcessPendingIrqs(pHcd, (1 << 1));
3476 + DBG_PRINT(SDIODBG_FUNC_IRQ, ("-SDIO Bus Driver: DeviceInterrupt: %d\n", status));
3477 + /* done with RAW irqs */
3481 + /* pre-allocate a request to get the pending bits, we have to do this outside the
3482 + * hcd lock acquisition */
3483 + pReq = AllocateRequest();
3485 + if (NULL == pReq) {
3486 + status = SDIO_STATUS_NO_RESOURCES;
3490 + status = _AcquireHcdLock(pHcd);
3492 + if (!SDIO_SUCCESS(status)) {
3496 + if (pHcd->IrqProcState != SDHCD_IDLE) {
3497 + status = SDIO_STATUS_ERROR;
3499 + /* mark that we are processing */
3500 + pHcd->IrqProcState = SDHCD_IRQ_PENDING;
3501 + /* build argument to read IRQ pending register */
3502 + SDIO_SET_CMD52_READ_ARG(pReq->Argument,0,SDIO_INT_PENDING_REG);
3503 + pReq->Command = CMD52;
3504 + pReq->Flags = SDREQ_FLAGS_TRANS_ASYNC | SDREQ_FLAGS_RESP_SDIO_R5;
3505 + pReq->pCompleteContext = (PVOID)pHcd;
3506 + pReq->pCompletion = GetPendingIrqComplete;
3507 + pReq->RetryCount = SDBUS_MAX_RETRY;
3510 + status2 = _ReleaseHcdLock(pHcd);
3512 + if (!SDIO_SUCCESS(status2)) {
3513 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: lock release error: %d\n", status2));
3518 + if (SDIO_SUCCESS(status)) {
3519 + DBG_ASSERT(pReq != NULL);
3520 + IssueRequestToHCD(pHcd,pReq);
3521 + status = SDIO_STATUS_PENDING;
3523 + if (pReq != NULL) {
3524 + FreeRequest(pReq);
3528 + DBG_PRINT(SDIODBG_FUNC_IRQ, ("-SDIO Bus Driver: DeviceInterrupt: %d\n", status));
3533 +/* SDIO IRQ helper */
3534 +THREAD_RETURN SDIOIrqHelperFunction(POSKERNEL_HELPER pHelper)
3537 + SDIO_STATUS status;
3538 + PSDLIST pListItem;
3539 + PSDDEVICE pDevice;
3541 + PSDDEVICE pDeviceIRQ[7];
3542 + UINT deviceIrqCount = 0;
3545 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - SDIOIrqHelperFunction starting up \n"));
3547 + pHcd = (PSDHCD)pHelper->pContext;
3548 + DBG_ASSERT(pHcd != NULL);
3552 + /* wait for wake up event */
3553 + status = SD_WAIT_FOR_WAKEUP(pHelper);
3555 + if (!SDIO_SUCCESS(status)) {
3556 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver - SDIOIrqHelperFunction Pend Error:%d \n",
3561 + if (SD_IS_HELPER_SHUTTING_DOWN(pHelper)) {
3565 + DBG_PRINT(SDIODBG_FUNC_IRQ, ("SDIO Bus Driver - Pending IRQs:0x%X \n",
3566 + pHcd->PendingHelperIrqs));
3568 + /* take the device list lock as we iterate through the list, this blocks
3569 + * device removals */
3570 + status = SemaphorePendInterruptable(&pBusContext->DeviceListSem);
3571 + if (!SDIO_SUCCESS(status)) {
3574 + /* walk through the device list matching HCD and interrupting function */
3575 + SDITERATE_OVER_LIST(&pBusContext->DeviceList, pListItem) {
3576 + pDevice = CONTAINING_STRUCT(pListItem, SDDEVICE, SDList);
3577 + /* check if device belongs to the HCD */
3578 + if (pDevice->pHcd != pHcd){
3579 + /* not on this hcd */
3582 + funcMask = 1 << SDDEVICE_GET_SDIO_FUNCNO(pDevice);
3583 + /* check device function against the pending mask */
3584 + if (!(funcMask & pHcd->PendingHelperIrqs)) {
3585 + /* this one is not scheduled for the helper */
3589 + pHcd->PendingHelperIrqs &= ~funcMask;
3590 + /* check for sync IRQ and call handler */
3591 + if (pDevice->pIrqFunction != NULL) {
3592 + DBG_PRINT(SDIODBG_FUNC_IRQ, ("SDIO Bus Driver: Calling IRQ Handler. Fn:%d\n",
3593 + SDDEVICE_GET_SDIO_FUNCNO(pDevice)));
3594 + /* save the device so we can process it without holding any locks */
3595 + pDeviceIRQ[deviceIrqCount++] = pDevice;
3597 + /* this is actually okay if the device is removing, the callback
3598 + * is NULLed out */
3599 + DBG_PRINT(SDIODBG_FUNC_IRQ, ("SDIO Bus Driver: No IRQ handler Fn:%d\n",
3600 + SDDEVICE_GET_SDIO_FUNCNO(pDevice)));
3603 + /* should have handled all these */
3604 + DBG_ASSERT(pHcd->PendingHelperIrqs == 0);
3605 + pHcd->PendingHelperIrqs = 0;
3606 + SemaphorePost(&pBusContext->DeviceListSem);
3607 + for (ii = 0; ii < deviceIrqCount; ii++) {
3608 + /* now call the function */
3609 + SDDEVICE_CALL_IRQ_HANDLER(pDeviceIRQ[ii]);
3611 + deviceIrqCount = 0;
3614 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - SDIOIrqHelperFunction Exiting.. \n"));
3618 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3619 + GetPendingIrqComplete - completion routine for getting pending IRQs
3620 + Input: pRequest - completed request
3624 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
3625 +static void GetPendingIrqComplete(PSDREQUEST pReq)
3627 + UINT8 intPendingMsk;
3631 + pHcd = (PSDHCD)pReq->pCompleteContext;
3632 + DBG_ASSERT(pHcd != NULL);
3634 + if (!SDIO_SUCCESS(pReq->Status)) {
3635 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get Interrupt pending register Err:%d\n",
3640 + if (SD_R5_GET_RESP_FLAGS(pReq->Response) & SD_R5_ERRORS) {
3641 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: CMD52 resp error: 0x%X \n",
3642 + SD_R5_GET_RESP_FLAGS(pReq->Response)));
3645 + /* extract the pending mask */
3646 + intPendingMsk = SD_R5_GET_READ_DATA(pReq->Response) & SDIO_INT_PEND_MASK;
3647 + /* process them */
3648 + ProcessPendingIrqs(pHcd, intPendingMsk);
3652 + FreeRequest(pReq);
3654 + DBG_PRINT(SDIODBG_FUNC_IRQ, ("-SDIO Bus Driver: GetPendingIrqComplete \n"));
3657 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3658 + ProcessPendingIrqs - processing pending Irqs
3659 + Input: pHcd - host controller
3660 + Input: IntPendingMsk - pending irq bit mask
3664 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
3665 +static void ProcessPendingIrqs(PSDHCD pHcd, UINT8 IntPendingMsk)
3667 + PSDLIST pListItem;
3668 + PSDDEVICE pDevice;
3670 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
3671 + CT_DECLARE_IRQ_SYNC_CONTEXT();
3673 + DBG_PRINT(SDIODBG_FUNC_IRQ, ("+SDIO Bus Driver: ProcessPendingIrqs \n"));
3675 + /* acquire lock to protect configuration and irq enables */
3676 + status = _AcquireHcdLock(pHcd);
3677 + if (!SDIO_SUCCESS(status)) {
3681 + /* sanity check */
3682 + if ((IntPendingMsk & pHcd->IrqsEnabled) != IntPendingMsk) {
3683 + DBG_PRINT(SDDBG_ERROR,
3684 + ("SDIO Bus Driver: IRQs asserting when not enabled : curr:0x%X , card reports: 0x%X\n",
3685 + pHcd->IrqsEnabled, IntPendingMsk));
3686 + /* remove the pending IRQs that are not enabled */
3687 + IntPendingMsk &= pHcd->IrqsEnabled;
3688 + /* fall through */
3691 + if (!IntPendingMsk) {
3692 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: No interrupts on HCD:0x%X \n", (INT)pHcd));
3693 + pHcd->IrqProcState = SDHCD_IDLE;
3694 + if (pHcd->IrqsEnabled) {
3695 + /* only re-arm if there are IRQs enabled */
3696 + _IssueConfig(pHcd,SDCONFIG_SDIO_REARM_INT,NULL,0);
3698 + status = _ReleaseHcdLock(pHcd);
3701 + /* reset helper IRQ bits */
3702 + pHcd->PendingHelperIrqs = 0;
3703 + /* save pending IRQ acks */
3704 + pHcd->PendingIrqAcks = IntPendingMsk;
3705 + status = _ReleaseHcdLock(pHcd);
3706 + DBG_PRINT(SDIODBG_FUNC_IRQ, ("SDIO Bus Driver: INTs Pending - 0x%2.2X \n", IntPendingMsk));
3707 + /* take the device list lock as we iterate through the list, this blocks
3708 + * device removals */
3709 + status = SemaphorePendInterruptable(&pBusContext->DeviceListSem);
3710 + if (!SDIO_SUCCESS(status)) {
3713 + /* walk through the device list matching HCD and interrupting function */
3714 + SDITERATE_OVER_LIST(&pBusContext->DeviceList, pListItem) {
3715 + pDevice = CONTAINING_STRUCT(pListItem, SDDEVICE, SDList);
3716 + /* check if device belongs to the HCD */
3717 + if (pDevice->pHcd != pHcd){
3718 + /* not on this hcd */
3721 + funcMask = 1 << SDDEVICE_GET_SDIO_FUNCNO(pDevice);
3722 + /* check device function against the pending mask */
3723 + if (!(funcMask & IntPendingMsk)) {
3724 + /* this one is not interrupting */
3727 + /* check for async IRQ and call handler */
3728 + if (pDevice->pIrqAsyncFunction != NULL) {
3729 + DBG_PRINT(SDIODBG_FUNC_IRQ, ("SDIO Bus Driver: Calling Async IRQ Handler. Fn:%d\n",
3730 + SDDEVICE_GET_SDIO_FUNCNO(pDevice)));
3731 + SDDEVICE_CALL_IRQ_ASYNC_HANDLER(pDevice);
3733 + /* this one needs the helper */
3734 + pHcd->PendingHelperIrqs |= funcMask;
3735 + DBG_PRINT(SDIODBG_FUNC_IRQ, ("SDIO Bus Driver: No Async IRQ, Pending Helper Fn:%d\n",
3736 + SDDEVICE_GET_SDIO_FUNCNO(pDevice)));
3739 + /* release HCD list lock */
3740 + SemaphorePost(&pBusContext->DeviceListSem);
3741 + /* check for helper IRQs */
3742 + if (pHcd->PendingHelperIrqs) {
3743 + pHcd->IrqProcState = SDHCD_IRQ_HELPER;
3744 + DBG_PRINT(SDIODBG_FUNC_IRQ, ("SDIO Bus Driver: Waking IRQ Helper \n"));
3745 + if (!SDIO_SUCCESS(SD_WAKE_OS_HELPER(&pHcd->SDIOIrqHelper))) {
3746 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: failed to wake helper! \n"));
3751 + DBG_PRINT(SDIODBG_FUNC_IRQ, ("-SDIO Bus Driver: ProcessPendingIrqs \n"));
3754 +SDIO_STATUS TryNoIrqPendingCheck(PSDDEVICE pDevice)
3756 + if (pDevice->pHcd->CardProperties.IOFnCount > 1) {
3757 + /* not supported on multi-function cards */
3758 + DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: IRQ Pending Check cannot be bypassed, (Funcs:%d)\n",
3759 + pDevice->pHcd->CardProperties.IOFnCount));
3760 + return SDIO_STATUS_UNSUPPORTED;
3763 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: pending IRQ check bypassed \n"));
3764 + /* set flag to optimize this */
3765 + AtomicTest_Set(&pDevice->pHcd->HcdFlags, HCD_IRQ_NO_PEND_CHECK);
3766 + return SDIO_STATUS_SUCCESS;
3770 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3771 + SDIO_NotifyTimerTriggered - notification handler that a timer expired
3772 + Input: TimerID - ID of timer that expired
3776 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
3777 +void SDIO_NotifyTimerTriggered(INT TimerID)
3780 + switch (TimerID) {
3781 + case SDIOBUS_CD_TIMER_ID:
3782 + pBusContext->CDTimerQueued = FALSE;
3783 + /* post an HCD polling event to the helper thread */
3784 + PostCardDetectEvent(pBusContext, EVENT_HCD_CD_POLLING, NULL);
3787 + DBG_ASSERT(FALSE);
3791 diff --git a/drivers/sdio/stack/busdriver/sdio_bus_misc.c b/drivers/sdio/stack/busdriver/sdio_bus_misc.c
3792 new file mode 100644
3793 index 0000000..c5c7381
3795 +++ b/drivers/sdio/stack/busdriver/sdio_bus_misc.c
3797 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3798 +@file: sdio_bus_misc.c
3800 +@abstract: OS independent bus driver support
3802 +#notes: this file contains miscellaneous control functions
3804 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
3808 + * This program is free software; you can redistribute it and/or modify
3809 + * it under the terms of the GNU General Public License version 2 as
3810 + * published by the Free Software Foundation;
3812 + * Software distributed under the License is distributed on an "AS
3813 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
3814 + * implied. See the License for the specific language governing
3815 + * rights and limitations under the License.
3817 + * Portions of this code were developed with information supplied from the
3818 + * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply:
3820 + * The following conditions apply to the release of the SD simplified specification (�Simplified
3821 + * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete
3822 + * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided
3823 + * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified
3824 + * Specification may require a license from the SD Card Association or other third parties.
3826 + * The information contained in the Simplified Specification is presented only as a standard
3827 + * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any
3828 + * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for
3829 + * any damages, any infringements of patents or other right of the SD Card Association or any third
3830 + * parties, which may result from its use. No license is granted by implication, estoppel or otherwise
3831 + * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall
3832 + * be construed as an obligation by the SD Card Association to disclose or distribute any technical
3833 + * information, know-how or other confidential information to any third party.
3836 + * The initial developers of the original code are Seung Yi and Paul Lever
3838 + * sdio@atheros.com
3842 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
3843 +#define MODULE_NAME SDBUSDRIVER
3844 +#include <linux/sdio/ctsystem.h>
3845 +#include <linux/sdio/sdio_busdriver.h>
3846 +#include <linux/sdio/sdio_lib.h>
3847 +#include "_busdriver.h"
3848 +#include <linux/sdio/_sdio_defs.h>
3849 +#include <linux/sdio/mmc_defs.h>
3852 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3853 + IssueBusRequestBd - issue a bus request
3854 + Input: pHcd - HCD object
3855 + Cmd - command to issue
3856 + Argument - command argument
3857 + Flags - request flags
3859 + Output: pReqToUse - request to use (if caller wants response data)
3860 + Return: SDIO Status
3861 + Notes: This function only issues 1 block data transfers
3862 + This function issues the request synchronously
3863 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
3864 +SDIO_STATUS _IssueBusRequestBd(PSDHCD pHcd,
3867 + SDREQUEST_FLAGS Flags,
3868 + PSDREQUEST pReqToUse,
3872 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
3875 + if (NULL == pReqToUse) {
3876 + /* caller doesn't care about the response data, allocate locally */
3877 + pReq = AllocateRequest();
3878 + if (NULL == pReq) {
3879 + return SDIO_STATUS_NO_RESOURCES;
3882 + /* use the caller's request buffer */
3886 + pReq->Argument = Argument;
3887 + pReq->Flags = Flags;
3888 + pReq->Command = Cmd;
3889 + if (pReq->Flags & SDREQ_FLAGS_DATA_TRANS) {
3890 + pReq->pDataBuffer = pData;
3891 + pReq->BlockCount = 1;
3892 + pReq->BlockLen = Length;
3895 + status = IssueRequestToHCD(pHcd,pReq);
3897 + if (NULL == pReqToUse) {
3898 + DBG_ASSERT(pReq != NULL);
3899 + FreeRequest(pReq);
3904 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3905 + ConvertVoltageCapsToOCRMask - initialize card
3906 + Input: VoltageCaps - voltage cap to look up
3907 + Return: 32 bit OCR mask
3908 + Notes: this function sets voltage for +- 10%
3910 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
3911 +static UINT32 ConvertVoltageCapsToOCRMask(SLOT_VOLTAGE_MASK VoltageCaps)
3917 + if (VoltageCaps & SLOT_POWER_3_3V) {
3918 + ocrMask |= SD_OCR_3_2_TO_3_3_VDD | SD_OCR_3_3_TO_3_4_VDD;
3920 + if (VoltageCaps & SLOT_POWER_3_0V) {
3921 + ocrMask |= SD_OCR_2_9_TO_3_0_VDD | SD_OCR_3_0_TO_3_1_VDD;
3923 + if (VoltageCaps & SLOT_POWER_2_8V) {
3924 + ocrMask |= SD_OCR_2_7_TO_2_8_VDD | SD_OCR_2_8_TO_2_9_VDD;
3926 + if (VoltageCaps & SLOT_POWER_2_0V) {
3927 + ocrMask |= SD_OCR_1_9_TO_2_0_VDD | SD_OCR_2_0_TO_2_1_VDD;
3929 + if (VoltageCaps & SLOT_POWER_1_8V) {
3930 + ocrMask |= SD_OCR_1_7_TO_1_8_VDD | SD_OCR_1_8_TO_1_9_VDD;
3932 + if (VoltageCaps & SLOT_POWER_1_6V) {
3933 + ocrMask |= SD_OCR_1_6_TO_1_7_VDD;
3939 +static UINT32 GetUsableOCRValue(UINT32 CardOCR, UINT32 SlotOCRMask)
3944 + for (i = 0; i < 32; i++) {
3946 + if ((SlotOCRMask & mask) && (CardOCR & mask)) {
3954 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3955 + GetPowerSetting - power up the SDIO card
3956 + Input: pHcd - HCD object
3957 + pOCRvalue - OCR value of the card
3958 + Output: pOCRvalue - OCR to actually use
3959 + Return: power setting for HCD based on card's OCR, zero indicates unsupported
3962 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
3963 +static SLOT_VOLTAGE_MASK GetPowerSetting(PSDHCD pHcd, UINT32 *pOCRvalue)
3966 + SLOT_VOLTAGE_MASK hcdVoltage = 0;
3967 + SLOT_VOLTAGE_MASK hcdVMask;
3970 + /* check preferred value */
3971 + ocrMask = ConvertVoltageCapsToOCRMask(pHcd->SlotVoltagePreferred);
3972 + if (ocrMask & *pOCRvalue) {
3973 + /* using preferred voltage */
3974 + *pOCRvalue = GetUsableOCRValue(*pOCRvalue, ocrMask);
3975 + hcdVoltage = pHcd->SlotVoltagePreferred;
3977 + /* walk through the slot voltage caps and find a match */
3978 + for (i = 0; i < 8; i++) {
3979 + hcdVMask = (1 << i);
3980 + if (hcdVMask & pHcd->SlotVoltageCaps) {
3981 + ocrMask = ConvertVoltageCapsToOCRMask((SLOT_VOLTAGE_MASK)(pHcd->SlotVoltageCaps & hcdVMask));
3982 + if (ocrMask & *pOCRvalue) {
3983 + /* found a match */
3984 + *pOCRvalue = GetUsableOCRValue(*pOCRvalue, ocrMask);
3985 + hcdVoltage = pHcd->SlotVoltageCaps & hcdVMask;
3992 + return hcdVoltage;
3995 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3996 + TestPresence - test the presence of a card/function
3997 + Input: pHcd - HCD object
3998 + TestType - type of test to perform
3999 + Output: pReq - Request to use (optional)
4003 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4004 +SDIO_STATUS TestPresence(PSDHCD pHcd,
4005 + CARD_INFO_FLAGS TestType,
4008 + SDIO_STATUS status = SDIO_STATUS_ERROR;
4010 + switch (TestType) {
4013 + status = _IssueSimpleBusRequest(pHcd,CMD5,0,
4014 + SDREQ_FLAGS_RESP_SDIO_R4 | SDREQ_FLAGS_RESP_SKIP_SPI_FILT,pReq);
4017 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
4018 + /* ACMD41 just starts initialization when in SPI mode, argument is ignored
4019 + * Note: In SPI mode ACMD41 uses an R1 response */
4020 + status = _IssueSimpleBusRequest(pHcd,ACMD41,0,
4021 + SDREQ_FLAGS_APP_CMD | SDREQ_FLAGS_RESP_R1,pReq);
4024 + /* issue ACMD41 with OCR value of zero */
4025 + /* ACMD41 on SD uses an R3 response */
4026 + status = _IssueSimpleBusRequest(pHcd,ACMD41,0,
4027 + SDREQ_FLAGS_APP_CMD | SDREQ_FLAGS_RESP_R3,pReq);
4032 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
4033 + /* note: in SPI mode an R1 response is used */
4034 + status = _IssueSimpleBusRequest(pHcd,CMD1,0,SDREQ_FLAGS_RESP_R1,pReq);
4036 + status = _IssueSimpleBusRequest(pHcd,CMD1,0,SDREQ_FLAGS_RESP_R3,pReq);
4040 + DBG_ASSERT(FALSE);
4046 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4047 + ReadOCR - read the OCR
4048 + Input: pHcd - HCD object
4049 + ReadType - type of read to perform
4050 + OCRValue - OCR value to use as an argument
4051 + Output: pReq - Request to use
4052 + pOCRValueRd - OCR value read back (can be NULL)
4056 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4057 +static SDIO_STATUS ReadOCR(PSDHCD pHcd,
4058 + CARD_INFO_FLAGS ReadType,
4061 + UINT32 *pOCRValueRd)
4063 + SDIO_STATUS status = SDIO_STATUS_ERROR;
4065 + switch (ReadType) {
4067 + /* CMD5 for SDIO cards */
4068 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
4069 + /* skip the SPI filter, we will decode the response here */
4070 + status = _IssueSimpleBusRequest(pHcd,CMD5,
4072 + SDREQ_FLAGS_RESP_SDIO_R4 |
4073 + SDREQ_FLAGS_RESP_SKIP_SPI_FILT,
4077 + status = _IssueSimpleBusRequest(pHcd,CMD5,
4079 + SDREQ_FLAGS_RESP_SDIO_R4,
4084 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
4085 + /* CMD58 is used to read the OCR */
4086 + status = _IssueSimpleBusRequest(pHcd,CMD58,
4087 + 0, /* argument ignored */
4088 + (SDREQ_FLAGS_RESP_R3 | SDREQ_FLAGS_RESP_SKIP_SPI_FILT),
4091 + /* SD Native uses ACMD41 */
4092 + status = _IssueSimpleBusRequest(pHcd,ACMD41,
4094 + SDREQ_FLAGS_APP_CMD | SDREQ_FLAGS_RESP_R3,
4099 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
4100 + /* CMD58 is used to read the OCR */
4101 + status = _IssueSimpleBusRequest(pHcd,CMD58,
4102 + 0, /* argument ignored */
4103 + (SDREQ_FLAGS_RESP_R3 | SDREQ_FLAGS_RESP_SKIP_SPI_FILT),
4106 + /* MMC Native uses CMD1 */
4107 + status = _IssueSimpleBusRequest(pHcd,CMD1,
4108 + OCRValue, SDREQ_FLAGS_RESP_R3,
4113 + DBG_ASSERT(FALSE);
4117 + if (SDIO_SUCCESS(status) && (pOCRValueRd != NULL)) {
4119 + /* someone wants the OCR read back */
4120 + switch (ReadType) {
4122 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
4123 + *pOCRValueRd = SPI_SDIO_R4_GET_OCR(pReq->Response);
4125 + *pOCRValueRd = SD_SDIO_R4_GET_OCR(pReq->Response);
4130 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
4131 + *pOCRValueRd = SPI_R3_GET_OCR(pReq->Response);
4133 + *pOCRValueRd = SD_R3_GET_OCR(pReq->Response);
4137 + DBG_ASSERT(FALSE);
4144 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4145 + PollCardReady - poll card till it's ready
4146 + Input: pHcd - HCD object
4147 + OCRValue - OCR value to poll with
4148 + PollType - polling type (based on card type)
4153 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4154 +SDIO_STATUS PollCardReady(PSDHCD pHcd, UINT32 OCRValue, CARD_INFO_FLAGS PollType)
4156 + INT cardReadyRetry;
4157 + SDIO_STATUS status;
4160 + if (!((PollType == CARD_SDIO) || (PollType == CARD_SD) || (PollType == CARD_MMC))) {
4161 + DBG_ASSERT(FALSE);
4162 + return SDIO_STATUS_INVALID_PARAMETER;
4165 + pReq = AllocateRequest();
4166 + if (NULL == pReq) {
4167 + return SDIO_STATUS_NO_RESOURCES;
4170 + status = SDIO_STATUS_SUCCESS;
4171 + cardReadyRetry = pBusContext->CardReadyPollingRetry;
4172 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Polling card ready, Using OCR:0x%8.8X, Poll Type:0x%X\n",
4173 + OCRValue,PollType));
4175 + /* now issue CMD with the actual OCR as an argument until the card is ready */
4176 + while (cardReadyRetry) {
4177 + if (IS_HCD_BUS_MODE_SPI(pHcd) && !(PollType == CARD_SDIO)) {
4178 + if (PollType == CARD_MMC) {
4179 + /* under SPI mode for MMC cards, we need to issue CMD1 and
4180 + * check the response for the "in-idle" bit */
4181 + status = _IssueSimpleBusRequest(pHcd,
4184 + SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_RESP_SKIP_SPI_FILT,
4186 + } else if (PollType == CARD_SD) {
4187 + /* under SPI mode for SD cards, we need to issue ACMD41 and
4188 + * check the response for the "in-idle" bit */
4189 + status = _IssueSimpleBusRequest(pHcd,
4192 + SDREQ_FLAGS_RESP_R1 |
4193 + SDREQ_FLAGS_APP_CMD |
4194 + SDREQ_FLAGS_RESP_SKIP_SPI_FILT,
4197 + DBG_ASSERT(FALSE);
4200 + /* for SD/MMC in native mode and SDIO (all modes) we need to read the OCR register */
4201 + /* read the OCR using the supplied OCR value as an argument, we don't care about the
4202 + * actual OCR read-back, but we are interested in the response */
4203 + status = ReadOCR(pHcd,PollType,pReq,OCRValue,NULL);
4206 + if (!SDIO_SUCCESS(status)) {
4207 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to issue CMD to poll ready \n"));
4210 + if (PollType == CARD_SDIO) {
4211 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
4212 + if (SPI_SDIO_R4_IS_CARD_READY(pReq->Response)) {
4213 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SDIO Card Ready! (SPI) \n"));
4217 + if (SD_SDIO_R4_IS_CARD_READY(pReq->Response)) {
4218 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SDIO Card Ready! \n"));
4222 + } else if ((PollType == CARD_SD) || (PollType == CARD_MMC)) {
4223 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
4224 + /* check response when MMC or SD cards operate in SPI mode */
4225 + if (!(GET_SPI_R1_RESP_TOKEN(pReq->Response) & SPI_CS_STATE_IDLE)) {
4226 + /* card is no longer in idle */
4227 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD/MMC Card (SPI mode) is ready! \n"));
4231 + /* check the OCR busy bit */
4232 + if (SD_R3_IS_CARD_READY(pReq->Response)) {
4233 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD/MMC (Native Mode) Card Ready! \n"));
4238 + DBG_ASSERT(FALSE);
4242 + status = OSSleep(OCR_READY_CHECK_DELAY_MS);
4243 + if (!SDIO_SUCCESS(status)){
4248 + if (0 == cardReadyRetry) {
4249 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Card Ready timeout! \n"));
4250 + status = SDIO_STATUS_DEVICE_ERROR;
4253 + FreeRequest(pReq);
4258 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4259 + AdjustSlotPower - adjust slot power
4260 + Input: pHcd - HCD object
4261 + Output: pOCRvalue - ocr value to use
4265 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4266 +static SDIO_STATUS AdjustSlotPower(PSDHCD pHcd, UINT32 *pOCRvalue)
4268 + SDCONFIG_POWER_CTRL_DATA pwrSetting;
4269 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
4271 + ZERO_OBJECT(pwrSetting);
4272 + DBG_PRINT(SDDBG_TRACE,
4273 + ("SDIO Bus Driver: Adjusting Slot Power, Requesting adjustment for OCR:0x%8.8X \n",
4277 + pwrSetting.SlotPowerEnable = TRUE;
4278 + /* get optimal power setting */
4279 + pwrSetting.SlotPowerVoltageMask = GetPowerSetting(pHcd, pOCRvalue);
4280 + if (0 == pwrSetting.SlotPowerVoltageMask) {
4281 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: No matching voltage for OCR \n"));
4282 + status = SDIO_STATUS_DEVICE_ERROR;
4286 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Slot Pwr Mask 0x%X for OCR:0x%8.8X \n",
4287 + pwrSetting.SlotPowerVoltageMask,*pOCRvalue));
4288 + status = _IssueConfig(pHcd,SDCONFIG_POWER_CTRL,&pwrSetting,sizeof(pwrSetting));
4289 + if (!SDIO_SUCCESS(status)) {
4290 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set power in hcd \n"));
4293 + /* delay for power to settle */
4294 + OSSleep(pBusContext->PowerSettleDelay);
4295 + /* save off for drivers */
4296 + pHcd->CardProperties.CardVoltage = pwrSetting.SlotPowerVoltageMask;
4303 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4304 + ConvertEncodedTransSpeed - convert encoded TRANS_SPEED value to a clock rate
4305 + Input: TransSpeedValue - encoded transfer speed value
4307 + Return: appropriate SD clock rate
4308 + Notes: This function returns a rate of 0, if it could not be determined.
4309 + This function can check tran speed values for SD,SDIO and MMC cards
4310 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4311 +static SD_BUSCLOCK_RATE ConvertEncodedTransSpeed(UINT8 TransSpeedValue)
4313 + SD_BUSCLOCK_RATE transfMul = 0;
4314 + UINT8 timeVal = 0;
4316 + switch (TransSpeedValue & TRANSFER_UNIT_MULTIPIER_MASK) {
4318 + transfMul = 10000;
4321 + transfMul = 100000;
4324 + transfMul = 1000000;
4327 + transfMul = 10000000;
4331 + DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: Card transfer multipler is wrong (val=0x%X)! \n",
4332 + TransSpeedValue));
4336 + switch ((TransSpeedValue & TIME_VALUE_MASK) >> TIME_VALUE_SHIFT) {
4337 + case 1: timeVal = 10; break;
4338 + case 2: timeVal = 12; break;
4339 + case 3: timeVal = 13; break;
4340 + case 4: timeVal = 15; break;
4341 + case 5: timeVal = 20; break;
4342 + case 6: timeVal = 25; break;
4343 + case 7: timeVal = 30; break;
4344 + case 8: timeVal = 35; break;
4345 + case 9: timeVal = 40; break;
4346 + case 10: timeVal = 45; break;
4347 + case 11: timeVal = 50; break;
4348 + case 12: timeVal = 55; break;
4349 + case 13: timeVal = 60; break;
4350 + case 14: timeVal = 70; break;
4351 + case 15: timeVal = 80; break;
4352 + default: timeVal = 0;
4353 + DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: Card time value is wrong (val=0x%X)! \n",
4354 + TransSpeedValue));
4358 + if ((transfMul != 0) && (timeVal != 0)) {
4359 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Card Reported Max: %d Hz (0x%X) \n",
4360 + (timeVal*transfMul), TransSpeedValue));
4361 + return timeVal*transfMul;
4367 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4368 + SelectDeselectCard - Select or deselect a card
4369 + Input: pHcd - HCD object
4370 + Select - select the card
4375 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4376 +static SDIO_STATUS SelectDeselectCard(PSDHCD pHcd, BOOL Select)
4378 + SDIO_STATUS status;
4380 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
4381 + /* SPI mode cards do not support selection */
4382 + status = SDIO_STATUS_SUCCESS;
4385 + /* deselect, note that deselecting a card does not return a response */
4386 + status = _IssueSimpleBusRequest(pHcd,
4388 + SDREQ_FLAGS_NO_RESP,NULL);
4391 + status = _IssueSimpleBusRequest(pHcd,
4392 + CMD7,(pHcd->CardProperties.RCA << 16),
4393 + SDREQ_FLAGS_RESP_R1B,NULL);
4397 + if (!SDIO_SUCCESS(status)) {
4398 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Failed to %s card, RCA:0x%X Err:%d \n",
4399 + (Select ? "Select":"Deselect"), pHcd->CardProperties.RCA, status));
4404 +/* reorder a buffer by swapping MSB with LSB */
4405 +static void ReorderBuffer(UINT8 *pBuffer, INT Bytes)
4410 + DBG_ASSERT(!(Bytes & 1));
4411 + /* point to the end */
4412 + pEnd = &pBuffer[Bytes - 1];
4413 + /* divide in half */
4414 + Bytes = Bytes >> 1;
4427 +#define ADJUST_OPER_CLOCK(pBusMode,Clock) \
4428 + (pBusMode)->ClockRate = min((SD_BUSCLOCK_RATE)(Clock),(pBusMode)->ClockRate)
4429 +#define ADJUST_OPER_BLOCK_LEN(pCaps,Length) \
4430 + (pCaps)->OperBlockLenLimit = min((UINT16)(Length),(pCaps)->OperBlockLenLimit)
4431 +#define ADJUST_OPER_BLOCK_COUNT(pCaps,Count) \
4432 + (pCaps)->OperBlockCountLimit = min((UINT16)(Count),(pCaps)->OperBlockCountLimit)
4434 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4435 + GetBusParameters - Get bus parameters for a card
4436 + Input: pHcd - HCD object
4437 + pBusMode - current bus mode on entry
4438 + Output: pBusMode - new adjusted bus mode
4442 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4443 +static SDIO_STATUS GetBusParameters(PSDHCD pHcd, PSDCONFIG_BUS_MODE_DATA pBusMode)
4445 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
4448 + struct SDIO_FUNC_EXT_COMMON_TPL func0ext;
4449 + UINT8 scrRegister[SD_SCR_BYTES];
4450 + SD_BUSCLOCK_RATE cardReportedRate = 0;
4451 + PSDREQUEST pReq = NULL;
4452 + BOOL spiMode = FALSE;
4455 + if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_SPI) {
4460 + /* set highest bus mode bus driver is allowing (non-SPI), the code below will
4461 + * adjust to lower or equal settings */
4462 + pBusMode->BusModeFlags = pBusContext->DefaultBusMode;
4464 + /* set operational parameters */
4465 + pBusMode->ClockRate = pBusContext->DefaultOperClock;
4466 + pHcd->CardProperties.OperBlockLenLimit = pBusContext->DefaultOperBlockLen;
4467 + pHcd->CardProperties.OperBlockCountLimit = pBusContext->DefaultOperBlockCount;
4469 + /* adjust operational block counts and length to match HCD */
4470 + ADJUST_OPER_BLOCK_LEN(&pHcd->CardProperties,pHcd->MaxBytesPerBlock);
4471 + ADJUST_OPER_BLOCK_COUNT(&pHcd->CardProperties,pHcd->MaxBlocksPerTrans);
4472 + /* limit operational clock to the max clock rate */
4473 + ADJUST_OPER_CLOCK(pBusMode,pHcd->MaxClockRate);
4476 + /* check HCD bus mode */
4477 + if (!(pHcd->Attributes & SDHCD_ATTRIB_BUS_4BIT) ||
4478 + ((pHcd->CardProperties.Flags & CARD_SDIO) &&
4479 + (pHcd->Attributes & SDHCD_ATTRIB_NO_4BIT_IRQ)) ) {
4481 + if (pHcd->Attributes & SDHCD_ATTRIB_BUS_4BIT) {
4482 + DBG_PRINT(SDDBG_WARN,
4483 + ("SDIO Card Detected, but host does not support IRQs in 4 bit mode - dropping to 1 bit. \n"));
4485 + /* force to 1 bit mode */
4486 + SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_1_BIT);
4490 + /* now do various card inquiries to drop the bus mode or clock
4491 + * none of these checks can raise the bus mode or clock higher that what
4492 + * was initialized above */
4494 + if (pHcd->CardProperties.Flags & (CARD_SD | CARD_MMC)) {
4495 + /* allocate a request for response data we'll need */
4496 + pReq = AllocateRequest();
4497 + if (NULL == pReq) {
4498 + status = SDIO_STATUS_NO_RESOURCES;
4503 + if (!spiMode && (pHcd->CardProperties.Flags & CARD_MMC)) {
4504 + /* MMC cards all run in 1 bit mode */
4505 + SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_1_BIT);
4508 + if (pHcd->CardProperties.Flags & CARD_SD) {
4509 + DBG_ASSERT(pReq != NULL);
4510 + DBG_PRINT(SDDBG_TRACE, ("Getting SCR from SD Card..\n"));
4511 + /* read SCR (requires data transfer) to get supported modes */
4512 + status = _IssueBusRequestBd(pHcd,ACMD51,0,
4513 + SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_APP_CMD |
4514 + SDREQ_FLAGS_DATA_TRANS,
4515 + pReq,&scrRegister,SD_SCR_BYTES);
4516 + if (!SDIO_SUCCESS(status)) {
4517 + DBG_PRINT(SDDBG_WARN, ("SD card does not have SCR. \n"));
4519 + /* switch it to 1 bit mode */
4520 + SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_1_BIT);
4522 + status = SDIO_STATUS_SUCCESS;
4524 + /* we have to reorder this buffer since the SCR is sent MSB first on the data
4526 + ReorderBuffer(scrRegister,SD_SCR_BYTES);
4528 + DBG_PRINT(SDDBG_TRACE, ("SD SCR StructRev:0x%X, Flags:0x%X \n",
4529 + GET_SD_SCR_STRUCT_VER(scrRegister),
4530 + GET_SD_SCR_BUSWIDTHS_FLAGS(scrRegister)));
4531 + /* set the revision */
4532 + switch (GET_SD_SCR_SDSPEC_VER(scrRegister)) {
4533 + case SCR_SD_SPEC_1_00:
4534 + DBG_PRINT(SDDBG_TRACE, ("SD Spec Revision 1.01 \n"));
4535 + pHcd->CardProperties.SD_MMC_Revision = SD_REVISION_1_01;
4537 + case SCR_SD_SPEC_1_10:
4538 + DBG_PRINT(SDDBG_TRACE, ("SD Spec Revision 1.10 \n"));
4539 + pHcd->CardProperties.SD_MMC_Revision = SD_REVISION_1_10;
4542 + DBG_PRINT(SDDBG_WARN, ("SD Spec Revision is greater than 1.10 \n"));
4543 + pHcd->CardProperties.SD_MMC_Revision = SD_REVISION_1_10;
4547 + if (!(GET_SD_SCR_BUSWIDTHS(scrRegister) & SCR_BUS_SUPPORTS_4_BIT)) {
4549 + DBG_PRINT(SDDBG_WARN, ("SD SCR reports 1bit only Mode \n"));
4550 + /* switch it to 1 bit mode */
4551 + SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_1_BIT);
4557 + if (pHcd->CardProperties.Flags & (CARD_SD | CARD_MMC)) {
4558 + DBG_ASSERT(pReq != NULL);
4559 + /* de-select the card in order to get the CSD */
4560 + status = SelectDeselectCard(pHcd,FALSE);
4561 + if (!SDIO_SUCCESS(status)) {
4562 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to deselect card before getting CSD \n"));
4565 + /* Get CSD for SD or MMC cards */
4567 + /* in SPI mode, getting the CSD requires a read data transfer */
4568 + status = _IssueBusRequestBd(pHcd,CMD9,0,
4569 + SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_DATA_TRANS,
4571 + pHcd->CardProperties.CardCSD,
4572 + MAX_CSD_CID_BYTES);
4573 + if (SDIO_SUCCESS(status)) {
4574 + /* when the CSD is sent over in SPI data mode, it comes to us in MSB first
4575 + * and thus is not ordered correctly as defined in the SD spec */
4576 + ReorderBuffer(pHcd->CardProperties.CardCSD,MAX_CSD_CID_BYTES);
4579 + status = _IssueSimpleBusRequest(pHcd,
4581 + (pHcd->CardProperties.RCA << 16),
4582 + SDREQ_FLAGS_RESP_R2,
4584 + if (SDIO_SUCCESS(status)) {
4585 + /* save the CSD */
4586 + memcpy(pHcd->CardProperties.CardCSD,pReq->Response,MAX_CARD_RESPONSE_BYTES);
4590 + if (!SDIO_SUCCESS(status)) {
4591 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get CSD, Err:%d \n",
4595 + /* for MMC cards, the spec version is in the CSD */
4596 + if (pHcd->CardProperties.Flags & CARD_MMC) {
4597 + DBG_PRINT(SDDBG_TRACE, ("MMC Spec version : (0x%2.2X) \n",
4598 + GET_MMC_SPEC_VERSION(pHcd->CardProperties.CardCSD)));
4599 + switch (GET_MMC_SPEC_VERSION(pHcd->CardProperties.CardCSD)) {
4600 + case MMC_SPEC_1_0_TO_1_2:
4601 + case MMC_SPEC_1_4:
4602 + case MMC_SPEC_2_0_TO_2_2:
4603 + DBG_PRINT(SDDBG_WARN, ("MMC Spec version less than 3.1 \n"));
4604 + pHcd->CardProperties.SD_MMC_Revision = MMC_REVISION_1_0_2_2;
4606 + case MMC_SPEC_3_1:
4607 + DBG_PRINT(SDDBG_TRACE, ("MMC Spec version 3.1 \n"));
4608 + pHcd->CardProperties.SD_MMC_Revision = MMC_REVISION_3_1;
4610 + case MMC_SPEC_4_0_TO_4_1:
4611 + DBG_PRINT(SDDBG_TRACE, ("MMC Spec version 4.0-4.1 \n"));
4612 + pHcd->CardProperties.SD_MMC_Revision = MMC_REVISION_4_0;
4615 + pHcd->CardProperties.SD_MMC_Revision = MMC_REVISION_3_1;
4616 + DBG_PRINT(SDDBG_WARN, ("MMC Spec version greater than 4.1\n"));
4620 + /* re-select the card */
4621 + status = SelectDeselectCard(pHcd,TRUE);
4622 + if (!SDIO_SUCCESS(status)) {
4623 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to re-select card after getting CSD \n"));
4628 + if ((pHcd->CardProperties.Flags & CARD_SD) &&
4629 + !(pHcd->CardProperties.Flags & CARD_SDIO) &&
4630 + SDDEVICE_IS_SD_REV_GTEQ_1_10(pHcd->pPseudoDev) &&
4631 + (pHcd->Attributes & SDHCD_ATTRIB_SD_HIGH_SPEED) &&
4634 + PUINT8 pSwitchStatusBlock = KernelAlloc(SD_SWITCH_FUNC_STATUS_BLOCK_BYTES);
4636 + if (NULL == pSwitchStatusBlock) {
4637 + status = SDIO_STATUS_NO_RESOURCES;
4641 + arg = SD_SWITCH_FUNC_ARG_GROUP_CHECK(SD_SWITCH_HIGH_SPEED_GROUP,
4642 + SD_SWITCH_HIGH_SPEED_FUNC_NO);
4644 + /* for 1.10 SD cards, check if high speed mode is supported */
4645 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Checking SD Card for switchable functions (CMD6 arg:0x%X)\n",arg));
4647 + /* issue simple data transfer request to read the switch status */
4648 + status = _IssueBusRequestBd(pHcd,
4651 + SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_DATA_TRANS,
4653 + pSwitchStatusBlock,
4654 + SD_SWITCH_FUNC_STATUS_BLOCK_BYTES);
4656 + if (SDIO_SUCCESS(status)) {
4657 + UINT16 switchGroupMask;
4658 + /* need to reorder this since cards send this MSB first */
4659 + ReorderBuffer(pSwitchStatusBlock,SD_SWITCH_FUNC_STATUS_BLOCK_BYTES);
4660 + switchGroupMask = SD_SWITCH_FUNC_STATUS_GET_GRP_BIT_MASK(pSwitchStatusBlock,SD_SWITCH_HIGH_SPEED_GROUP);
4661 + DBG_PRINT(SDDBG_TRACE, ("SD Card Switch Status Group1 Mask:0x%X Max Current:%d\n",
4662 + switchGroupMask, SD_SWITCH_FUNC_STATUS_GET_MAX_CURRENT(pSwitchStatusBlock) ));
4663 + if (SD_SWITCH_FUNC_STATUS_GET_MAX_CURRENT(pSwitchStatusBlock) == 0) {
4664 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: SD Switch Status block has zero max current \n"));
4665 + SDLIB_PrintBuffer(pSwitchStatusBlock,
4666 + SD_SWITCH_FUNC_STATUS_BLOCK_BYTES,
4667 + "SDIO Bus Driver: SD Switch Status Block Error");
4669 + /* check HS support */
4670 + if (switchGroupMask & (1 << SD_SWITCH_HIGH_SPEED_FUNC_NO)) {
4671 + DBG_PRINT(SDDBG_TRACE, ("SD Card Supports High Speed Mode\n"));
4672 + /* set the rate, this will override the CSD value */
4673 + cardReportedRate = SD_HS_MAX_BUS_CLOCK;
4674 + pBusMode->BusModeFlags |= SDCONFIG_BUS_MODE_SD_HS;
4678 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get SD Switch Status block (%d)\n", status));
4679 + /* just fall through, we'll handle this like a normal SD card */
4680 + status = SDIO_STATUS_SUCCESS;
4683 + KernelFree(pSwitchStatusBlock);
4686 + if ((pHcd->CardProperties.Flags & CARD_MMC) &&
4687 + SDDEVICE_IS_MMC_REV_GTEQ_4_0(pHcd->pPseudoDev) &&
4688 + (pHcd->Attributes & SDHCD_ATTRIB_MMC_HIGH_SPEED) &&
4690 + /* for MMC cards, get the Extended CSD to get the High speed and
4691 + * wide bus paramaters */
4693 + PUINT8 pExtData = KernelAlloc(MMC_EXT_CSD_SIZE);
4695 + if (NULL == pExtData) {
4696 + status = SDIO_STATUS_NO_RESOURCES;
4699 + /* issue simple data transfer request to read the extended CSD */
4700 + status = _IssueBusRequestBd(pHcd,MMC_CMD8,0,
4701 + SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_DATA_TRANS,
4704 + MMC_EXT_CSD_SIZE);
4705 + if (SDIO_SUCCESS(status)) {
4706 + DBG_PRINT(SDDBG_TRACE, ("MMC Ext CSD Version: 0x%X Card Type: 0x%X\n",
4707 + pExtData[MMC_EXT_VER_OFFSET],pExtData[MMC_EXT_CARD_TYPE_OFFSET]));
4708 + /* check HS support */
4709 + if (pExtData[MMC_EXT_CARD_TYPE_OFFSET] & MMC_EXT_CARD_TYPE_HS_52) {
4711 + cardReportedRate = 52000000;
4712 + pBusMode->BusModeFlags |= SDCONFIG_BUS_MODE_MMC_HS;
4713 + } else if (pExtData[MMC_EXT_CARD_TYPE_OFFSET] & MMC_EXT_CARD_TYPE_HS_26) {
4715 + cardReportedRate = 26000000;
4716 + pBusMode->BusModeFlags |= SDCONFIG_BUS_MODE_MMC_HS;
4718 + /* doesn't report high speed capable */
4719 + cardReportedRate = 0;
4722 + if (cardReportedRate && !spiMode) {
4723 + /* figure out the bus mode */
4724 + if (pHcd->Attributes & SDHCD_ATTRIB_BUS_MMC8BIT) {
4725 + SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_MMC8_BIT);
4726 + } else if (pHcd->Attributes & SDHCD_ATTRIB_BUS_4BIT) {
4727 + SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_4_BIT);
4729 + /* we leave it to default to 1 bit mode */
4733 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get MMC Extended CSD \n"));
4734 + /* just fall through, we'll do without the extended information
4735 + * and run it like a legacy MMC card */
4736 + status = SDIO_STATUS_SUCCESS;
4739 + KernelFree(pExtData);
4742 + if (pHcd->CardProperties.Flags & (CARD_SD | CARD_MMC)) {
4744 + if (0 == cardReportedRate) {
4745 + /* extract rate from CSD only if it was not set by earlier tests */
4746 + cardReportedRate = ConvertEncodedTransSpeed(
4747 + GET_SD_CSD_TRANS_SPEED(pHcd->CardProperties.CardCSD));
4748 + /* fall through and test for zero again */
4751 + if (cardReportedRate != 0) {
4752 + /* adjust clock based on what the card can handle */
4753 + ADJUST_OPER_CLOCK(pBusMode,cardReportedRate);
4755 + /* something is wrong with the CSD */
4756 + if (DBG_GET_DEBUG_LEVEL() >= SDDBG_TRACE) {
4757 + SDLIB_PrintBuffer(pHcd->CardProperties.CardCSD,
4758 + MAX_CARD_RESPONSE_BYTES,
4759 + "SDIO Bus Driver: CSD Dump");
4761 + /* can't figure out the card rate, so set reasonable defaults */
4762 + if (pHcd->CardProperties.Flags & CARD_SD) {
4763 + ADJUST_OPER_CLOCK(pBusMode,SD_MAX_BUS_CLOCK);
4765 + ADJUST_OPER_CLOCK(pBusMode,MMC_MAX_BUS_CLOCK);
4770 + /* note, we do SDIO card "after" SD in case this is a combo card */
4771 + if (pHcd->CardProperties.Flags & CARD_SDIO) {
4772 + /* read card capabilities */
4773 + status = Cmd52ReadByteCommon(pHcd->pPseudoDev,
4774 + SDIO_CARD_CAPS_REG,
4775 + &pHcd->CardProperties.SDIOCaps);
4776 + if (!SDIO_SUCCESS(status)) {
4779 + DBG_PRINT(SDDBG_TRACE, ("SDIO Card Caps: 0x%X \n",pHcd->CardProperties.SDIOCaps));
4780 + if (pHcd->CardProperties.SDIOCaps & SDIO_CAPS_LOW_SPEED) {
4781 + /* adjust max clock for LS device */
4782 + ADJUST_OPER_CLOCK(pBusMode,SDIO_LOW_SPEED_MAX_BUS_CLOCK);
4783 + /* adjust bus if LS device does not support 4 bit mode */
4784 + if (!(pHcd->CardProperties.SDIOCaps & SDIO_CAPS_4BIT_LS)) {
4786 + /* low speed device does not support 4 bit mode, force us to 1 bit */
4787 + SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags,
4788 + SDCONFIG_BUS_WIDTH_1_BIT);
4793 + /* check if 1.2 card supports high speed mode, checking HCD as well*/
4794 + if (SDDEVICE_IS_SDIO_REV_GTEQ_1_20(pHcd->pPseudoDev) &&
4795 + (pHcd->Attributes & SDHCD_ATTRIB_SD_HIGH_SPEED) &&
4797 + UCHAR hsControl = 0;
4799 + status = Cmd52ReadByteCommon(pHcd->pPseudoDev,
4800 + SDIO_HS_CONTROL_REG,
4803 + if (!SDIO_SUCCESS(status)) {
4804 + DBG_PRINT(SDDBG_TRACE,
4805 + ("SDIO Failed to read high speed control (%d) \n",status));
4806 + /* reset status and continue */
4807 + status = SDIO_STATUS_SUCCESS;
4809 + if (hsControl & SDIO_HS_CONTROL_SHS) {
4810 + DBG_PRINT(SDDBG_TRACE, ("SDIO Card Supports High Speed Mode\n"));
4811 + pBusMode->BusModeFlags |= SDCONFIG_BUS_MODE_SD_HS;
4817 + cardReportedRate = 0;
4818 + temp = sizeof(func0ext);
4819 + tplAddr = pHcd->CardProperties.CommonCISPtr;
4820 + /* get the FUNCE tuple */
4821 + status = SDLIB_FindTuple(pHcd->pPseudoDev,
4824 + (PUINT8)&func0ext,
4826 + if (!SDIO_SUCCESS(status) || (temp < sizeof(func0ext))) {
4827 + DBG_PRINT(SDDBG_WARN, ("SDIO Function 0 Ext. Tuple Missing (Got size:%d) \n", temp));
4828 + /* reset status */
4829 + status = SDIO_STATUS_SUCCESS;
4831 + /* convert encoded value to rate */
4832 + cardReportedRate = ConvertEncodedTransSpeed(func0ext.MaxTransSpeed);
4835 + if (cardReportedRate != 0) {
4836 + if (pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_SD_HS) {
4837 + if (cardReportedRate <= SD_MAX_BUS_CLOCK) {
4838 + DBG_PRINT(SDDBG_WARN,
4839 + ("SDIO Function tuple reports clock:%d Hz, with advertised High Speed support \n", cardReportedRate));
4840 + /* back off high speed support */
4841 + pBusMode->BusModeFlags &= ~SDCONFIG_BUS_MODE_SD_HS;
4844 + if (cardReportedRate > SD_MAX_BUS_CLOCK) {
4845 + DBG_PRINT(SDDBG_WARN,
4846 + ("SDIO Function tuple reports clock:%d Hz, without advertising High Speed support..using 25Mhz \n", cardReportedRate));
4847 + cardReportedRate = SD_MAX_BUS_CLOCK;
4850 + /* adjust clock based on what the card can handle */
4851 + ADJUST_OPER_CLOCK(pBusMode,cardReportedRate);
4854 + /* set a reasonable default */
4855 + ADJUST_OPER_CLOCK(pBusMode,SD_MAX_BUS_CLOCK);
4860 + if (pReq != NULL) {
4861 + FreeRequest(pReq);
4866 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4867 + SetOperationalBusMode - set operational bus mode
4868 + Input: pDevice - pDevice that is requesting the change
4869 + pBusMode - operational bus mode
4870 + Output: pBusMode - on return will have the actual clock rate set
4874 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4875 +SDIO_STATUS SetOperationalBusMode(PSDDEVICE pDevice,
4876 + PSDCONFIG_BUS_MODE_DATA pBusMode)
4878 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
4882 + PSDHCD pHcd = pDevice->pHcd;
4884 + /* synchronize access for updating bus mode settings */
4885 + status = SemaphorePendInterruptable(&pDevice->pHcd->ConfigureOpsSem);
4886 + if (!SDIO_SUCCESS(status)) {
4892 + if (!IS_CARD_PRESENT(pHcd)) {
4893 + /* for an empty slot (a Pseudo dev was passed in) we still allow the
4894 + * bus mode to be set for the card detect
4896 + status = _IssueConfig(pHcd,SDCONFIG_BUS_MODE_CTRL,pBusMode,sizeof(SDCONFIG_BUS_MODE_DATA));
4897 + if (!SDIO_SUCCESS(status)) {
4898 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set bus mode in hcd : Err:%d \n",
4901 + /* nothing more to do */
4906 + if ((pBusMode->BusModeFlags == SDDEVICE_GET_BUSMODE_FLAGS(pDevice)) &&
4907 + (pBusMode->ClockRate == SDDEVICE_GET_OPER_CLOCK(pDevice))) {
4908 + DBG_PRINT(SDDBG_TRACE,
4909 + ("SDIO Bus Driver: Bus mode already set, nothing to do\n"));
4910 + pBusMode->ActualClockRate = SDDEVICE_GET_OPER_CLOCK(pDevice);
4914 + if (pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_MMC_HS) {
4915 + if (!(pHcd->Attributes & SDHCD_ATTRIB_MMC_HIGH_SPEED)) {
4916 + status = SDIO_STATUS_INVALID_PARAMETER;
4917 + DBG_PRINT(SDDBG_ERROR,
4918 + ("SDIO Bus Driver: HCD does not support MMC High Speed\n"));
4923 + if (pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_SD_HS) {
4924 + if (!(pHcd->Attributes & SDHCD_ATTRIB_SD_HIGH_SPEED)) {
4925 + status = SDIO_STATUS_INVALID_PARAMETER;
4926 + DBG_PRINT(SDDBG_ERROR,
4927 + ("SDIO Bus Driver: HCD does not support SD High Speed\n"));
4932 + /* before we set the operational clock and mode, configure the clock for high
4933 + * speed mode on the card , if necessary */
4934 + if ((pHcd->CardProperties.Flags & CARD_MMC) &&
4935 + (pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_MMC_HS) &&
4936 + !(SDDEVICE_GET_BUSMODE_FLAGS(pDevice) & SDCONFIG_BUS_MODE_MMC_HS)) {
4938 + switcharg = MMC_SWITCH_BUILD_ARG(MMC_SWITCH_CMD_SET0,
4939 + MMC_SWITCH_WRITE_BYTE,
4940 + MMC_EXT_HS_TIMING_OFFSET,
4941 + MMC_EXT_HS_TIMING_ENABLE);
4942 + status = _IssueSimpleBusRequest(pHcd,
4945 + SDREQ_FLAGS_RESP_R1B,
4947 + if (!SDIO_SUCCESS(status)) {
4948 + DBG_PRINT(SDDBG_ERROR,
4949 + ("SDIO Bus Driver: Failed to switch MMC High Speed Mode (arg:0x%X): %d \n",
4950 + switcharg, status));
4954 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: High Speed MMC enabled (arg:0x%X)\n",
4958 + /* before setting bus mode and clock in the HCD, switch card to high speed mode
4960 + if ((pHcd->CardProperties.Flags & CARD_SD) &&
4961 + (pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_SD_HS) &&
4962 + !(SDDEVICE_GET_BUSMODE_FLAGS(pDevice) & SDCONFIG_BUS_MODE_SD_HS)) {
4964 + PUINT8 pSwitchStatusBlock;
4966 + pSwitchStatusBlock = KernelAlloc(SD_SWITCH_FUNC_STATUS_BLOCK_BYTES);
4968 + if (NULL == pSwitchStatusBlock) {
4969 + status = SDIO_STATUS_NO_RESOURCES;
4973 + /* set high speed group */
4974 + arg = SD_SWITCH_FUNC_ARG_GROUP_SET(SD_SWITCH_HIGH_SPEED_GROUP,
4975 + SD_SWITCH_HIGH_SPEED_FUNC_NO);
4977 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Setting SD Card for High Speed mode (CMD6 arg:0x%X)\n",arg));
4979 + /* issue simple data transfer request to switch modes */
4980 + status = _IssueBusRequestBd(pHcd,
4983 + SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_DATA_TRANS,
4985 + pSwitchStatusBlock,
4986 + SD_SWITCH_FUNC_STATUS_BLOCK_BYTES);
4988 + if (SDIO_SUCCESS(status)) {
4989 + ReorderBuffer(pSwitchStatusBlock,SD_SWITCH_FUNC_STATUS_BLOCK_BYTES);
4990 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD High Speed Result, Got Max Current:%d mA, SwitchResult:0x%X \n",
4991 + SD_SWITCH_FUNC_STATUS_GET_MAX_CURRENT(pSwitchStatusBlock),
4992 + SDSwitchGetSwitchResult(pSwitchStatusBlock, SD_SWITCH_HIGH_SPEED_GROUP)));
4993 + if (SD_SWITCH_FUNC_STATUS_GET_MAX_CURRENT(pSwitchStatusBlock) == 0) {
4994 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Error in Status Block after High Speed Switch (current==0) \n"));
4995 + status = SDIO_STATUS_DEVICE_ERROR;
4997 + if (SDSwitchGetSwitchResult(pSwitchStatusBlock, SD_SWITCH_HIGH_SPEED_GROUP) !=
4998 + SD_SWITCH_HIGH_SPEED_FUNC_NO) {
4999 + DBG_PRINT(SDDBG_ERROR,
5000 + ("SDIO Bus Driver: Error in Status Block after High Speed Switch (Group1 did not switch) \n"));
5001 + status = SDIO_STATUS_DEVICE_ERROR;
5003 + if (SDIO_SUCCESS(status)) {
5004 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD High Speed Mode Enabled \n"));
5006 + SDLIB_PrintBuffer(pSwitchStatusBlock,
5007 + SD_SWITCH_FUNC_STATUS_BLOCK_BYTES,
5008 + "SDIO Bus Driver: SD Switch Status Block Error");
5011 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to Set SD High Speed Mode (%d) \n",status));
5013 + KernelFree(pSwitchStatusBlock);
5015 + if (!SDIO_SUCCESS(status)) {
5020 + /* enable/disable high speed mode for SDIO card */
5021 + if (pHcd->CardProperties.Flags & CARD_SDIO) {
5022 + BOOL doSet = TRUE;
5024 + if ((pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_SD_HS) &&
5025 + !(SDDEVICE_GET_BUSMODE_FLAGS(pDevice) & SDCONFIG_BUS_MODE_SD_HS)) {
5027 + regData = SDIO_HS_CONTROL_EHS;
5028 + } else if (!(pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_SD_HS) &&
5029 + (SDDEVICE_GET_BUSMODE_FLAGS(pDevice) & SDCONFIG_BUS_MODE_SD_HS)) {
5038 + status = Cmd52WriteByteCommon(pDevice,
5039 + SDIO_HS_CONTROL_REG,
5042 + if (!SDIO_SUCCESS(status)) {
5043 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to %s HS mode in SDIO card : Err:%d\n",
5044 + (SDIO_HS_CONTROL_EHS == regData) ? "enable":"disable" , status));
5047 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver:SDIO Card %s for High Speed mode \n",
5048 + (SDIO_HS_CONTROL_EHS == regData) ? "enabled":"disabled" ));
5053 + /* use synchronize-with-bus request version, this may have been requested by a
5054 + * function driver */
5055 + status = SDLIB_IssueConfig(pDevice,
5056 + SDCONFIG_BUS_MODE_CTRL,
5058 + sizeof(SDCONFIG_BUS_MODE_DATA));
5060 + if (!SDIO_SUCCESS(status)) {
5061 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set bus mode in hcd : Err:%d \n",
5066 + /* check requested bus width against the current mode */
5067 + if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) ==
5068 + SDCONFIG_GET_BUSWIDTH(pHcd->CardProperties.BusMode)) {
5069 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Bus mode set, no width change\n"));
5073 + if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_SPI) {
5074 + /* nothing more to do for SPI */
5078 + /* set the bus width for SD and combo cards */
5079 + if (pHcd->CardProperties.Flags & CARD_SD) {
5080 + if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_4_BIT) {
5081 + /* turn off card detect resistor */
5082 + status = _IssueSimpleBusRequest(pHcd,
5084 + 0, /* disable CD */
5085 + SDREQ_FLAGS_APP_CMD | SDREQ_FLAGS_RESP_R1,
5087 + if (!SDIO_SUCCESS(status)) {
5088 + DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: Failed to disable CD Res: %d \n",
5089 + status)); /* this should be okay */
5091 + arg = SD_ACMD6_BUS_WIDTH_4_BIT;
5093 + /* don't need to turn off CD in 1 bit mode, just set mode */
5094 + arg = SD_ACMD6_BUS_WIDTH_1_BIT;
5097 + /* set the bus width */
5098 + status = _IssueSimpleBusRequest(pHcd,
5100 + arg, /* set bus mode */
5101 + SDREQ_FLAGS_APP_CMD | SDREQ_FLAGS_RESP_R1,
5103 + if (!SDIO_SUCCESS(status)) {
5104 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set bus width: %d \n",
5109 + /* set bus width for SDIO cards */
5110 + if (pHcd->CardProperties.Flags & CARD_SDIO) {
5112 + regData = CARD_DETECT_DISABLE | SDIO_BUS_WIDTH_1_BIT;
5114 + if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_4_BIT) {
5115 + /* turn off card detect resistor and set buswidth */
5116 + regData = CARD_DETECT_DISABLE | SDIO_BUS_WIDTH_4_BIT;
5117 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Enabling 4 bit mode on card \n"));
5119 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Enabling 1 bit mode on card \n"));
5121 + status = Cmd52WriteByteCommon(pDevice,
5124 + if (!SDIO_SUCCESS(status)) {
5125 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set bus mode in Card : Err:%d\n",
5130 + /* check for 4-bit interrupt detect mode */
5131 + if ((SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_4_BIT) &&
5132 + (pHcd->CardProperties.SDIOCaps & SDIO_CAPS_INT_MULTI_BLK) &&
5133 + (pHcd->Attributes & SDHCD_ATTRIB_MULTI_BLK_IRQ)) {
5134 + /* enable interrupts between blocks, this doesn't actually turn on interrupts
5135 + * it merely allows interrupts to be asserted in the inter-block gap */
5136 + pHcd->CardProperties.SDIOCaps |= SDIO_CAPS_ENB_INT_MULTI_BLK;
5138 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: 4-Bit Multi-blk Interrupt support enabled\n"));
5140 + /* make sure this is disabled */
5141 + pHcd->CardProperties.SDIOCaps &= ~SDIO_CAPS_ENB_INT_MULTI_BLK;
5144 + status = Cmd52WriteByteCommon(pDevice,
5145 + SDIO_CARD_CAPS_REG,
5146 + &pHcd->CardProperties.SDIOCaps);
5147 + if (!SDIO_SUCCESS(status)) {
5148 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to update Card Caps register Err:%d\n",
5154 + /* set data bus width for MMC */
5155 + if (pHcd->CardProperties.Flags & CARD_MMC) {
5156 + UINT8 buswidth = 0;
5158 + if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_4_BIT) {
5159 + buswidth = MMC_EXT_BUS_WIDTH_4_BIT;
5160 + } else if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_MMC8_BIT) {
5161 + buswidth = MMC_EXT_BUS_WIDTH_8_BIT;
5163 + /* normal 1 bit mode .. nothing to do */
5166 + /* now set the bus mode on the card */
5167 + switcharg = MMC_SWITCH_BUILD_ARG(MMC_SWITCH_CMD_SET0,
5168 + MMC_SWITCH_WRITE_BYTE,
5169 + MMC_EXT_BUS_WIDTH_OFFSET,
5172 + status = _IssueSimpleBusRequest(pHcd,
5175 + SDREQ_FLAGS_RESP_R1B,
5177 + if (!SDIO_SUCCESS(status)) {
5178 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set MMC bus width (arg:0x%X): %d \n",
5179 + switcharg, status));
5183 + if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_4_BIT) {
5184 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: 4 bit MMC mode enabled (arg:0x%X) \n",
5186 + } else if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_MMC8_BIT) {
5187 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: 8-Bit MMC mode enabled (arg:0x%X) \n",
5194 + if (SDIO_SUCCESS(status)) {
5195 + /* set the operating mode */
5196 + pHcd->CardProperties.BusMode = pBusMode->BusModeFlags;
5197 + /* set the actual clock rate */
5198 + pHcd->CardProperties.OperBusClock = pBusMode->ActualClockRate;
5201 + SemaphorePost(&pDevice->pHcd->ConfigureOpsSem);
5206 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5207 + CardInitSetup - setup host for card initialization
5208 + Input: pHcd - HCD object
5213 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
5214 +SDIO_STATUS CardInitSetup(PSDHCD pHcd)
5216 + SDCONFIG_INIT_CLOCKS_DATA initClocks;
5217 + SDCONFIG_BUS_MODE_DATA busMode;
5219 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
5221 + ZERO_OBJECT(initClocks);
5222 + ZERO_OBJECT(busMode);
5223 + /* setup defaults */
5224 + initClocks.NumberOfClocks = SDMMC_MIN_INIT_CLOCKS;
5225 + busMode.ClockRate = SD_INIT_BUS_CLOCK;
5227 + /* check for SPI only */
5228 + if (pHcd->Attributes & SDHCD_ATTRIB_BUS_SPI) {
5229 + /* SPI cards startup in non-CRC mode with the exception of CMD0, the
5230 + * HCDs must issue CMD0 with the correct CRC , the spec shows that a
5231 + * CMD 0 sequence is 0x40,0x00,0x00,0x00,0x00,0x95 */
5232 + busMode.BusModeFlags = SDCONFIG_BUS_WIDTH_SPI | SDCONFIG_BUS_MODE_SPI_NO_CRC;
5234 + /* check if host supports 1 bit mode */
5235 + /* TODO : if host supports power switching, we can
5236 + * could initialize cards in SPI mode first */
5237 + if (pHcd->Attributes & SDHCD_ATTRIB_BUS_1BIT) {
5238 + busMode.BusModeFlags = SDCONFIG_BUS_WIDTH_1_BIT;
5241 + /* set initial VDD, starting at the highest allowable voltage and working
5243 + if (pHcd->SlotVoltageCaps & SLOT_POWER_3_3V) {
5244 + OCRvalue = SD_OCR_3_2_TO_3_3_VDD;
5245 + } else if (pHcd->SlotVoltageCaps & SLOT_POWER_3_0V) {
5246 + OCRvalue = SD_OCR_2_9_TO_3_0_VDD;
5247 + } else if (pHcd->SlotVoltageCaps & SLOT_POWER_2_8V) {
5248 + OCRvalue = SD_OCR_2_7_TO_2_8_VDD;
5249 + } else if (pHcd->SlotVoltageCaps & SLOT_POWER_2_0V) {
5250 + OCRvalue = SD_OCR_1_9_TO_2_0_VDD;
5251 + } else if (pHcd->SlotVoltageCaps & SLOT_POWER_1_8V) {
5252 + OCRvalue = SD_OCR_1_7_TO_1_8_VDD;
5253 + } else if (pHcd->SlotVoltageCaps & SLOT_POWER_1_6V) {
5254 + OCRvalue = SD_OCR_1_6_TO_1_7_VDD;
5256 + DBG_ASSERT(FALSE);
5261 + /* power up the card */
5262 + status = AdjustSlotPower(pHcd, &OCRvalue);
5263 + if (!SDIO_SUCCESS(status)) {
5264 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to adjust slot power \n"));
5267 + status = SetOperationalBusMode(pHcd->pPseudoDev,&busMode);
5268 + if (!SDIO_SUCCESS(status)) {
5269 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set bus mode \n"));
5272 + status = _IssueConfig(pHcd,SDCONFIG_SEND_INIT_CLOCKS,&initClocks,sizeof(initClocks));
5273 + if (!SDIO_SUCCESS(status)) {
5274 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to send init clocks in hcd \n"));
5283 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5284 + SDInitializeCard - initialize card
5285 + Input: pHcd - HCD object
5286 + Output: pProperties - card properties
5290 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
5291 +SDIO_STATUS SDInitializeCard(PSDHCD pHcd)
5293 + SDCONFIG_BUS_MODE_DATA busMode;
5294 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
5295 + PSDREQUEST pReq = NULL;
5299 + struct SDIO_MANFID_TPL manfid;
5300 + SDCONFIG_WP_VALUE wpValue;
5301 + UINT8 cisBuffer[3];
5306 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
5307 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Initializing card in SPI mode \n"));
5309 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Initializing card in MMC/SD mode \n"));
5312 + pReq = AllocateRequest();
5313 + if (NULL == pReq) {
5314 + status = SDIO_STATUS_NO_RESOURCES;
5315 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: failed to allocate bus request \n"));
5318 + memset(pReq, 0, sizeof(SDREQUEST));
5320 + status = CardInitSetup(pHcd);
5321 + if (!SDIO_SUCCESS(status)) {
5322 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to setup card \n"));
5325 + status = _IssueConfig(pHcd,SDCONFIG_GET_WP,&wpValue,sizeof(wpValue));
5326 + if (!SDIO_SUCCESS(status)) {
5327 + DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: host doesn't support Write Protect \n"));
5330 + pHcd->CardProperties.Flags |= CARD_SD_WP;
5331 + DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: SD WP switch is on \n"));
5335 + if (!(pHcd->Attributes & SDHCD_ATTRIB_SLOT_POLLING) &&
5336 + IS_HCD_BUS_MODE_SPI(pHcd)) {
5337 + /* for non-slot polling HCDs operating in SPI mode
5338 + * issue CMD0 to reset card state and to place the card
5339 + * in SPI mode. If slot polling is used, the polling thread
5340 + * will have already issued a CMD0 to place the card in SPI mode*/
5341 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
5343 + status = SDIO_STATUS_ERROR;
5344 + /* if the CMD0 fails, retry it. Some cards have a hard time getting into SPI mode.*/
5345 + while ((!SDIO_SUCCESS(status)) && (ii-- >= 0)) {
5346 + status = _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_RESP_R1,pReq);
5349 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: cmd0 go SPI retries:(256) %d\n", ii));
5352 + status = _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_NO_RESP,pReq);
5354 + if (!SDIO_SUCCESS(status)) {
5355 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: go-idle failed! \n"));
5360 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Looking for SDIO.. \n"));
5361 + /* check for SDIO card by trying to read it's OCR */
5362 + status = ReadOCR(pHcd,CARD_SDIO,pReq,0,&OCRvalue);
5363 + if (SDIO_SUCCESS(status)) {
5364 + /* we got a response, this is an SDIO card */
5365 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
5367 + pHcd->CardProperties.IOFnCount = SPI_SDIO_R4_GET_IO_FUNC_COUNT(pReq->Response);
5368 + if (SPI_SDIO_R4_IS_MEMORY_PRESENT(pReq->Response)) {
5369 + /* flag an SD function exists */
5370 + pHcd->CardProperties.Flags |= CARD_SD;
5373 + /* handle native SD */
5374 + pHcd->CardProperties.IOFnCount = SD_SDIO_R4_GET_IO_FUNC_COUNT(pReq->Response);
5375 + if (SD_SDIO_R4_IS_MEMORY_PRESENT(pReq->Response)) {
5376 + /* flag an SD function exists */
5377 + pHcd->CardProperties.Flags |= CARD_SD;
5381 + if (0 == pHcd->CardProperties.IOFnCount) {
5382 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SDIO Card reports no functions \n"));
5383 + status = SDIO_STATUS_DEVICE_ERROR;
5384 + pHcd->CardProperties.Flags = 0;
5387 + pHcd->CardProperties.Flags |= CARD_SDIO;
5389 + DBG_PRINT(SDDBG_TRACE,
5390 + ("SDIO Bus Driver: SDIO Card, Functions: %d Card Info Flags:0x%X OCR:0x%8.8X\n",
5391 + pHcd->CardProperties.IOFnCount, pHcd->CardProperties.Flags, OCRvalue));
5392 + /* adjust slot power for this SDIO card */
5393 + status = AdjustSlotPower(pHcd, &OCRvalue);
5394 + if (!SDIO_SUCCESS(status)) {
5395 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set power in hcd \n"));
5398 + /* poll for SDIO card ready */
5399 + status = PollCardReady(pHcd,OCRvalue,CARD_SDIO);
5400 + if (!SDIO_SUCCESS(status)) {
5403 + } else if (status != SDIO_STATUS_BUS_RESP_TIMEOUT){
5404 + /* major error in hcd, bail */
5408 + /* check if this is an SDIO-only card before continuing */
5409 + if (!(pHcd->CardProperties.Flags & CARD_SD) && (pHcd->CardProperties.Flags & CARD_SDIO)) {
5410 + /* this is an SDIO card with no memory function */
5414 + if (!(pHcd->CardProperties.Flags & CARD_SDIO)) {
5415 + /* issue go idle only if we did not find an SDIO function in our earlier test */
5416 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
5417 + status = _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_RESP_R1,pReq);
5419 + status = _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_NO_RESP,pReq);
5421 + if (!SDIO_SUCCESS(status)) {
5422 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: go-idle failed! \n"));
5427 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Looking for SD Memory.. \n"));
5428 + /* SD Memory Card checking */
5429 + /* test for present of SD card (stand-alone or combo card) */
5430 + status = TestPresence(pHcd, CARD_SD, pReq);
5431 + if (SDIO_SUCCESS(status)) {
5432 + /* there is an SD Card present, could be part of a combo system */
5433 + pHcd->CardProperties.Flags |= CARD_SD;
5434 + if (0 == OCRvalue) {
5435 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD Memory card detected. \n"));
5436 + /* no OCR value on entry this is a stand-alone card, go and get it*/
5437 + status = ReadOCR(pHcd,CARD_SD,pReq,0,&OCRvalue);
5438 + if (!SDIO_SUCCESS(status) || (OCRvalue == 0)) {
5439 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get OCR (status:%d) \n",
5443 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD Card Reports OCR:0x%8.8X \n", OCRvalue));
5444 + status = AdjustSlotPower(pHcd, &OCRvalue);
5445 + if (!SDIO_SUCCESS(status)) {
5446 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to adjust power \n"));
5450 + DBG_ASSERT((pHcd->CardProperties.Flags & (CARD_SD | CARD_SDIO)));
5451 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SDIO Combo Card detected \n"));
5453 + /* poll for SD card ready */
5454 + status = PollCardReady(pHcd,OCRvalue,CARD_SD);
5455 + if (!SDIO_SUCCESS(status)) {
5456 + /* check if this card has an SDIO function */
5457 + if (pHcd->CardProperties.Flags & CARD_SDIO) {
5458 + DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: Combo Detected but SD memory function failed \n"));
5459 + /* allow SDIO functions to load normally */
5460 + status = SDIO_STATUS_SUCCESS;
5461 + /* remove SD flag */
5462 + pHcd->CardProperties.Flags &= ~CARD_SD;
5467 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD Memory ready. \n"));
5469 + /* we're done, no need to check for MMC */
5471 + } else if (status != SDIO_STATUS_BUS_RESP_TIMEOUT){
5472 + /* major error in hcd, bail */
5476 + /* MMC card checking */
5477 + /* if we get here, these better not be set */
5478 + DBG_ASSERT(!(pHcd->CardProperties.Flags & (CARD_SD | CARD_SDIO)));
5479 + /* issue go idle */
5480 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
5481 + status = _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_RESP_R1,pReq);
5483 + status = _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_NO_RESP,pReq);
5485 + if (!SDIO_SUCCESS(status)) {
5486 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: go-idle failed! \n"));
5490 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Looking for MMC.. \n"));
5491 + status = TestPresence(pHcd, CARD_MMC, pReq);
5492 + if (!SDIO_SUCCESS(status)) {
5493 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: unknown card detected \n"));
5496 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: MMC Card Detected \n"));
5497 + pHcd->CardProperties.Flags |= CARD_MMC;
5498 + /* read the OCR value */
5499 + status = ReadOCR(pHcd,CARD_MMC,pReq,0,&OCRvalue);
5500 + if (!SDIO_SUCCESS(status) || (OCRvalue == 0)) {
5501 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Failed to get OCR (status:%d)",
5505 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: MMC Card Reports OCR:0x%8.8X \n", OCRvalue));
5506 + /* adjust power */
5507 + status = AdjustSlotPower(pHcd, &OCRvalue);
5508 + if (!SDIO_SUCCESS(status)) {
5509 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to adjust power \n"));
5512 + /* poll for MMC card ready */
5513 + status = PollCardReady(pHcd,OCRvalue,CARD_MMC);
5514 + if (!SDIO_SUCCESS(status)) {
5517 + /* fall through and prepare MMC card */
5520 + /* we're done figuring out what was inserted, and setting up
5521 + * optimal slot voltage, now we need to prepare the card */
5522 + if (!IS_HCD_BUS_MODE_SPI(pHcd) &&
5523 + (pHcd->CardProperties.Flags & (CARD_SD | CARD_MMC))) {
5524 + /* non-SPI SD or MMC cards need to be moved to the "ident" state before we can get the
5525 + * RCA or select the card using the new RCA */
5526 + status = _IssueSimpleBusRequest(pHcd,CMD2,0,SDREQ_FLAGS_RESP_R2,pReq);
5527 + if (!SDIO_SUCCESS(status)){
5528 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: failed to move SD/MMC card into ident state \n"));
5533 + if (!IS_HCD_BUS_MODE_SPI(pHcd)) {
5534 + /* non-SPI mode cards need their RCA's setup */
5535 + if (pHcd->CardProperties.Flags & (CARD_SD | CARD_SDIO)) {
5536 + /* issue CMD3 to get RCA on SD/SDIO cards */
5537 + status = _IssueSimpleBusRequest(pHcd,CMD3,0,SDREQ_FLAGS_RESP_R6,pReq);
5538 + if (!SDIO_SUCCESS(status)){
5539 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: failed to get RCA for SD/SDIO card \n"));
5542 + pHcd->CardProperties.RCA = SD_R6_GET_RCA(pReq->Response);
5543 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD/SDIO RCA:0x%X \n",
5544 + pHcd->CardProperties.RCA));
5545 + } else if (pHcd->CardProperties.Flags & CARD_MMC) {
5546 + /* for MMC cards, we have to assign a relative card address */
5547 + /* just a non-zero number */
5548 + pHcd->CardProperties.RCA = 1;
5549 + /* issue CMD3 to set the RCA for MMC cards */
5550 + status = _IssueSimpleBusRequest(pHcd,
5551 + CMD3,(pHcd->CardProperties.RCA << 16),
5552 + SDREQ_FLAGS_RESP_R1,pReq);
5553 + if (!SDIO_SUCCESS(status)){
5554 + DBG_PRINT(SDDBG_ERROR,
5555 + ("SDIO Bus Driver: failed to set RCA for MMC card! (err=%d) \n",status));
5559 + DBG_ASSERT(FALSE);
5562 + /* select the card in order to get the rest of the card info, applies
5563 + * to SDIO/SD/MMC cards*/
5564 + status = SelectDeselectCard(pHcd, TRUE);
5565 + if (!SDIO_SUCCESS(status)) {
5566 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: failed to select card! \n"));
5569 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver, Card now Selected.. \n"));
5571 + if (pHcd->CardProperties.Flags & CARD_SDIO) {
5572 + /* read SDIO revision register */
5573 + status = Cmd52ReadByteCommon(pHcd->pPseudoDev, CCCR_SDIO_REVISION_REG, &temp);
5574 + if (!SDIO_SUCCESS(status)) {
5577 + DBG_PRINT(SDDBG_TRACE, ("SDIO Revision Reg: 0x%X \n", temp));
5578 + switch (temp & SDIO_REV_MASK) {
5579 + case SDIO_REV_1_00:
5580 + DBG_PRINT(SDDBG_TRACE, ("SDIO Spec Revision 1.00 \n"));
5581 + pHcd->CardProperties.SDIORevision = SDIO_REVISION_1_00;
5583 + case SDIO_REV_1_10:
5584 + DBG_PRINT(SDDBG_TRACE, ("SDIO Spec Revision 1.10 \n"));
5585 + pHcd->CardProperties.SDIORevision = SDIO_REVISION_1_10;
5587 + case SDIO_REV_1_20:
5588 + DBG_PRINT(SDDBG_TRACE, ("SDIO Spec Revision 1.20 \n"));
5589 + pHcd->CardProperties.SDIORevision = SDIO_REVISION_1_20;
5592 + DBG_PRINT(SDDBG_WARN, ("SDIO Warning: unknown SDIO revision, treating like 1.0 device \n"));
5593 + pHcd->CardProperties.SDIORevision = SDIO_REVISION_1_00;
5596 + /* get the common CIS ptr */
5597 + status = Cmd52ReadMultipleCommon(pHcd->pPseudoDev,
5598 + SDIO_CMN_CIS_PTR_LOW_REG,
5601 + if (!SDIO_SUCCESS(status)) {
5602 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get CIS ptr, Err:%d", status));
5605 + /* this is endian-safe*/
5606 + pHcd->CardProperties.CommonCISPtr = ((UINT32)cisBuffer[0]) |
5607 + (((UINT32)cisBuffer[1]) << 8) |
5608 + (((UINT32)cisBuffer[2]) << 16);
5610 + DBG_PRINT(SDDBG_TRACE, ("SDIO Card CIS Ptr: 0x%X \n", pHcd->CardProperties.CommonCISPtr));
5611 + temp = sizeof(manfid);
5612 + tplAddr = pHcd->CardProperties.CommonCISPtr;
5613 + /* get the MANFID tuple */
5614 + status = SDLIB_FindTuple(pHcd->pPseudoDev,
5619 + if (!SDIO_SUCCESS(status)) {
5620 + DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: Failed to get MANFID tuple err:%d \n", status));
5621 + status = SDIO_STATUS_SUCCESS;
5623 + /* save this off so that it can be copied into each SDIO Func's SDDEVICE structure */
5624 + pHcd->CardProperties.SDIO_ManufacturerCode =
5625 + CT_LE16_TO_CPU_ENDIAN(manfid.ManufacturerCode);
5626 + pHcd->CardProperties.SDIO_ManufacturerID =
5627 + CT_LE16_TO_CPU_ENDIAN(manfid.ManufacturerInfo);
5628 + DBG_PRINT(SDDBG_TRACE, ("SDIO MANFID:0x%X, MANFINFO:0x%X \n",
5629 + pHcd->CardProperties.SDIO_ManufacturerID,
5630 + pHcd->CardProperties.SDIO_ManufacturerCode));
5633 + if (pHcd->CardProperties.SDIORevision >= SDIO_REVISION_1_10) {
5634 + /* read power control */
5635 + status = Cmd52ReadByteCommon(pHcd->pPseudoDev, SDIO_POWER_CONTROL_REG, &temp);
5636 + if (SDIO_SUCCESS(status)) {
5637 + /* check for power control support which indicates the card may use more
5639 + if (temp & SDIO_POWER_CONTROL_SMPC) {
5640 + /* check that the host can support this. */
5641 + if (pHcd->MaxSlotCurrent >= SDIO_EMPC_CURRENT_THRESHOLD) {
5642 + temp = SDIO_POWER_CONTROL_EMPC;
5643 + /* enable power control on the card */
5644 + status = Cmd52WriteByteCommon(pHcd->pPseudoDev, SDIO_POWER_CONTROL_REG, &temp);
5645 + if (!SDIO_SUCCESS(status)) {
5646 + DBG_PRINT(SDDBG_ERROR,
5647 + ("SDIO Busdriver: failed to enable power control (%d) \n",status));
5650 + /* mark that the card is high power */
5651 + pHcd->CardProperties.Flags |= CARD_HIPWR;
5653 + DBG_PRINT(SDDBG_TRACE,
5654 + ("SDIO Busdriver: Power Control Enabled on SDIO (1.10 or greater) card \n"));
5656 + DBG_PRINT(SDDBG_WARN,
5657 + ("SDIO Busdriver: Card can operate higher than 200mA, host cannot (max:%d) \n",
5658 + pHcd->MaxSlotCurrent));
5659 + /* this is not fatal, the card should operate at a reduced rate */
5662 + DBG_PRINT(SDDBG_TRACE,
5663 + ("SDIO Busdriver: SDIO 1.10 (or greater) card draws less than 200mA \n"));
5666 + DBG_PRINT(SDDBG_WARN,
5667 + ("SDIO Busdriver: failed to get POWER CONTROL REG (%d) \n",status));
5668 + /* fall through and continue on at reduced mode */
5672 + /* get the current bus parameters */
5673 + busMode.BusModeFlags = pHcd->CardProperties.BusMode;
5674 + busMode.ClockRate = pHcd->CardProperties.OperBusClock;
5675 + /* get the rest of the bus parameters like clock and supported bus width */
5676 + status = GetBusParameters(pHcd,&busMode);
5677 + if (!SDIO_SUCCESS(status)) {
5681 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
5682 + /* check HCD if it wants to run without SPI CRC */
5683 + if (pHcd->Attributes & SDHCD_ATTRIB_NO_SPI_CRC) {
5684 + /* hcd would rather not run with CRC we don't need to tell the card since SPI mode
5685 + * cards power up with CRC initially disabled */
5686 + busMode.BusModeFlags |= SDCONFIG_BUS_MODE_SPI_NO_CRC;
5688 + /* first enable SPI CRC checking if the HCD can handle it */
5689 + status = SDSPIModeEnableDisableCRC(pHcd->pPseudoDev, TRUE);
5690 + if (!SDIO_SUCCESS(status)) {
5691 + DBG_PRINT(SDDBG_ERROR,
5692 + ("SDIO Bus Driver: Failed to set Enable SPI CRC on card \n"));
5698 + status = SetOperationalBusMode(pHcd->pPseudoDev, &busMode);
5700 + if (!SDIO_SUCCESS(status)) {
5701 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set operational bus mode\n"));
5705 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Oper. Mode: Clock:%d, Bus:0x%X \n",
5706 + pHcd->CardProperties.OperBusClock,pHcd->CardProperties.BusMode));
5707 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Card in TRANS state, Ready: CardInfo Flags 0x%X \n",
5708 + pHcd->CardProperties.Flags));
5712 + if (pReq != NULL) {
5713 + FreeRequest(pReq);
5719 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5720 + SDQuerySDMMCInfo - query MMC card info
5721 + Input: pDevice - device
5726 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
5727 +SDIO_STATUS SDQuerySDMMCInfo(PSDDEVICE pDevice)
5729 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
5730 + PSDREQUEST pReq = NULL;
5731 + UINT8 CID[MAX_CSD_CID_BYTES];
5734 + pReq = AllocateRequest();
5735 + if (NULL == pReq) {
5736 + status = SDIO_STATUS_NO_RESOURCES;
5739 + /* de-select the card */
5740 + status = SelectDeselectCard(pDevice->pHcd,FALSE);
5741 + if (!SDIO_SUCCESS(status)) {
5742 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to deselect card before getting CID \n"));
5746 + if (SDDEVICE_IS_BUSMODE_SPI(pDevice)) {
5747 + /* in SPI mode, getting the CSD requires a data transfer */
5748 + status = _IssueBusRequestBd(pDevice->pHcd,CMD10,0,
5749 + SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_DATA_TRANS,
5752 + MAX_CSD_CID_BYTES);
5753 + if (SDIO_SUCCESS(status)) {
5754 + /* in SPI mode we need to reorder to the CID since SPI data comes in MSB first*/
5755 + ReorderBuffer(CID,MAX_CSD_CID_BYTES);
5759 + status = _IssueSimpleBusRequest(pDevice->pHcd,
5761 + (SDDEVICE_GET_CARD_RCA(pDevice) << 16),
5762 + SDREQ_FLAGS_RESP_R2,
5764 + if (SDIO_SUCCESS(status)) {
5765 + /* extract it from the reponse */
5766 + memcpy(CID,pReq->Response,MAX_CSD_CID_BYTES);
5770 + if (!SDIO_SUCCESS(status)) {
5771 + DBG_PRINT(SDDBG_WARN, ("SDQuerySDMMCInfo: failed to get CID. \n"));
5772 + status = SDIO_STATUS_SUCCESS;
5774 + pDevice->pId[0].SDMMC_ManfacturerID = GET_SD_CID_MANFID(CID);
5775 + pDevice->pId[0].SDMMC_OEMApplicationID = GET_SD_CID_OEMID(CID);
5780 + pBuf[0] = GET_SD_CID_PN_1(CID);
5781 + pBuf[1] = GET_SD_CID_PN_2(CID);
5782 + pBuf[2] = GET_SD_CID_PN_3(CID);
5783 + pBuf[3] = GET_SD_CID_PN_4(CID);
5784 + pBuf[4] = GET_SD_CID_PN_5(CID);
5785 + if (pDevice->pHcd->CardProperties.Flags & CARD_MMC) {
5786 + pBuf[5] = GET_SD_CID_PN_6(CID);
5791 + DBG_PRINT(SDDBG_TRACE, ("SDQuerySDMMCInfo: Product String: %s\n", pBuf));
5794 + DBG_PRINT(SDDBG_TRACE, ("SDQuerySDMMCInfo: ManfID: 0x%X, OEMID:0x%X \n",
5795 + pDevice->pId[0].SDMMC_ManfacturerID, pDevice->pId[0].SDMMC_OEMApplicationID));
5797 + /* re-select card */
5798 + status = SelectDeselectCard(pDevice->pHcd,TRUE);
5799 + if (!SDIO_SUCCESS(status)) {
5800 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to re-select card after getting CID \n"));
5805 + if (pReq != NULL) {
5806 + FreeRequest(pReq);
5812 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5813 + SDQuerySDIOInfo - query SDIO card info
5814 + Input: pDevice - the device
5819 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
5820 +SDIO_STATUS SDQuerySDIOInfo(PSDDEVICE pDevice)
5822 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
5827 + UINT8 cisPtrBuffer[3];
5828 + struct SDIO_FUNC_EXT_FUNCTION_TPL_1_1 funcTuple;
5830 + /* use the card-wide SDIO manufacturer code and ID previously read.*/
5831 + pDevice->pId[0].SDIO_ManufacturerCode = pDevice->pHcd->CardProperties.SDIO_ManufacturerCode;
5832 + pDevice->pId[0].SDIO_ManufacturerID = pDevice->pHcd->CardProperties.SDIO_ManufacturerID;
5834 + /* calculate function base address */
5835 + faddress = CalculateFBROffset(SDDEVICE_GET_SDIO_FUNCNO(pDevice));
5836 + DBG_ASSERT(faddress != 0);
5839 + status = Cmd52ReadByteCommon(pDevice,
5840 + FBR_FUNC_INFO_REG_OFFSET(faddress),
5842 + if (!SDIO_SUCCESS(status)) {
5843 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get function info, Err:%d , using Class:UNKNOWN\n", status));
5845 + pDevice->pId[0].SDIO_FunctionClass = 0;
5846 + status = SDIO_STATUS_SUCCESS;
5848 + pDevice->pId[0].SDIO_FunctionClass = fInfo & FUNC_INFO_DEVICE_CODE_MASK;
5851 + if ((FUNC_INFO_DEVICE_CODE_LAST == pDevice->pId[0].SDIO_FunctionClass) &&
5852 + SDDEVICE_IS_SDIO_REV_GTEQ_1_10(pDevice)) {
5853 + /* if the device code is the last one, check for 1.1 revision and get the
5854 + * extended code */
5855 + status = Cmd52ReadByteCommon(pDevice,
5856 + FBR_FUNC_EXT_DEVICE_CODE_OFFSET(faddress),
5857 + &(pDevice->pId[0].SDIO_FunctionClass));
5858 + if (!SDIO_SUCCESS(status)) {
5859 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get 1.1 extended DC, Err:%d\n",
5865 + /* get the function CIS ptr */
5866 + status = Cmd52ReadMultipleCommon(pDevice,
5867 + FBR_FUNC_CIS_LOW_OFFSET(faddress),
5870 + if (!SDIO_SUCCESS(status)) {
5871 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get FN CIS ptr, Err:%d\n", status));
5875 + pDevice->DeviceInfo.AsSDIOInfo.FunctionCISPtr = ((UINT32)cisPtrBuffer[0]) |
5876 + (((UINT32)cisPtrBuffer[1]) << 8) |
5877 + (((UINT32)cisPtrBuffer[2]) << 16);
5879 + DBG_PRINT(SDDBG_TRACE, ("SDIO Function:%d, Class:%d FnCISPtr:0x%X \n",
5880 + SDDEVICE_GET_SDIO_FUNCNO(pDevice),
5881 + pDevice->pId[0].SDIO_FunctionClass,pDevice->DeviceInfo.AsSDIOInfo.FunctionCISPtr));
5883 + if (fInfo & FUNC_INFO_SUPPORTS_CSA_MASK) {
5884 + /* get the function CSA ptr */
5885 + status = Cmd52ReadMultipleCommon(pDevice,
5886 + FBR_FUNC_CSA_LOW_OFFSET(faddress),
5889 + if (!SDIO_SUCCESS(status)) {
5890 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get FN CSA ptr, Err:%d \n", status));
5894 + pDevice->DeviceInfo.AsSDIOInfo.FunctionCSAPtr = ((UINT32)cisPtrBuffer[0]) |
5895 + (((UINT32)cisPtrBuffer[1]) << 8) |
5896 + (((UINT32)cisPtrBuffer[2]) << 16);
5900 + nextTpl = SDDEVICE_GET_SDIO_FUNC_CISPTR(pDevice);
5901 + /* look for the funce TPL */
5902 + tplLength = sizeof(funcTuple);
5903 + /* go get the func CE tuple */
5904 + status = SDLIB_FindTuple(pDevice,
5907 + (PUINT8)&funcTuple,
5910 + if (!SDIO_SUCCESS(status)){
5911 + /* handles case of bad CIS or missing tupple, allow function driver to handle */
5912 + DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: Failed to get FuncCE Tuple: %d \n", status));
5913 + status = SDIO_STATUS_SUCCESS;
5916 + /* set the max block size */
5917 + pDevice->DeviceInfo.AsSDIOInfo.FunctionMaxBlockSize =
5918 + CT_LE16_TO_CPU_ENDIAN(funcTuple.CommonInfo.MaxBlockSize);
5920 + DBG_PRINT(SDDBG_TRACE, ("SDIO Function:%d, MaxBlocks:%d \n",
5921 + SDDEVICE_GET_SDIO_FUNCNO(pDevice),
5922 + pDevice->DeviceInfo.AsSDIOInfo.FunctionMaxBlockSize));
5924 + /* check for MANFID function tuple (SDIO 1.1 or greater) */
5925 + if (SDDEVICE_IS_SDIO_REV_GTEQ_1_10(pDevice)) {
5926 + struct SDIO_MANFID_TPL manfid;
5927 + nextTpl = SDDEVICE_GET_SDIO_FUNC_CISPTR(pDevice);
5928 + tplLength = sizeof(manfid);
5929 + /* get the MANFID tuple */
5930 + status = SDLIB_FindTuple(pDevice,
5935 + if (SDIO_SUCCESS(status)) {
5936 + /* this function has a MANFID tuple */
5937 + pDevice->pId[0].SDIO_ManufacturerCode =
5938 + CT_LE16_TO_CPU_ENDIAN(manfid.ManufacturerCode);
5939 + pDevice->pId[0].SDIO_ManufacturerID =
5940 + CT_LE16_TO_CPU_ENDIAN(manfid.ManufacturerInfo);
5941 + DBG_PRINT(SDDBG_TRACE, ("SDIO 1.1 (Function Specific) MANFID:0x%X, MANFINFO:0x%X \n",
5942 + pDevice->pId[0].SDIO_ManufacturerID,
5943 + pDevice->pId[0].SDIO_ManufacturerCode));
5945 + DBG_PRINT(SDDBG_WARN, ("SDIO 1.1, No CISTPL_MANFID Tuple in FUNC CIS \n"));
5946 + status = SDIO_STATUS_SUCCESS;
5954 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5955 + SDEnableFunction - enable function
5956 + Input: pDevice - the device/function
5957 + pEnData - enable data;
5960 + Notes: Note, this performs synchronous calls
5961 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
5962 +SDIO_STATUS SDEnableFunction(PSDDEVICE pDevice, PSDCONFIG_FUNC_ENABLE_DISABLE_DATA pEnData)
5964 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
5965 + UINT8 registerValue;
5967 + FUNC_ENABLE_TIMEOUT retry;
5969 + /* take the configure op lock to make this atomic */
5970 + status = SemaphorePendInterruptable(&pDevice->pHcd->ConfigureOpsSem);
5971 + if (!SDIO_SUCCESS(status)) {
5975 + status = SDIO_STATUS_INVALID_PARAMETER;
5977 + if (!(pDevice->pHcd->CardProperties.Flags & CARD_SDIO)){
5978 + /* nothing to do if it's not an SDIO card */
5982 + if (!((SDDEVICE_GET_SDIO_FUNCNO(pDevice) >= SDIO_FIRST_FUNCTION_NUMBER) &&
5983 + (SDDEVICE_GET_SDIO_FUNCNO(pDevice) <= SDIO_LAST_FUNCTION_NUMBER))){
5984 + DBG_ASSERT(FALSE);
5987 + /* make sure there is a timeout value */
5988 + if (0 == pEnData->TimeOut) {
5992 + mask = 1 << SDDEVICE_GET_SDIO_FUNCNO(pDevice);
5993 + /* read the enable register */
5994 + status = Cmd52ReadByteCommon(pDevice, SDIO_ENABLE_REG, ®isterValue);
5995 + if (!SDIO_SUCCESS(status)){
5998 + if (pEnData->EnableFlags & SDCONFIG_ENABLE_FUNC) {
5999 + /* set the enable register bit */
6000 + registerValue |= mask;
6002 + /* clear the bit */
6003 + registerValue &= ~mask;
6006 + DBG_PRINT(SDDBG_TRACE,
6007 + ("SDIO Bus Driver %s Function, Mask:0x%X Enable Reg Value:0x%2.2X\n",
6008 + (pEnData->EnableFlags & SDCONFIG_ENABLE_FUNC) ? "Enabling":"Disabling",
6012 + /* write it back out */
6013 + status = Cmd52WriteByteCommon(pDevice, SDIO_ENABLE_REG, ®isterValue);
6014 + if (!SDIO_SUCCESS(status)){
6017 + /* now poll the ready bit until it sets or clears */
6018 + retry = pEnData->TimeOut;
6019 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Function Enable/Disable Polling: %d retries \n",
6022 + status = Cmd52ReadByteCommon(pDevice, SDIO_READY_REG, ®isterValue);
6023 + if (!SDIO_SUCCESS(status)){
6026 + if (pEnData->EnableFlags & SDCONFIG_ENABLE_FUNC) {
6027 + /* if the bit is set, the device is ready */
6028 + if (registerValue & mask) {
6029 + /* device ready */
6033 + if (!(registerValue & mask)) {
6034 + /* device is no longer ready */
6038 + /* sleep before trying again */
6039 + status = OSSleep(1);
6040 + if (!SDIO_SUCCESS(status)) {
6041 + DBG_PRINT(SDDBG_ERROR, ("OSSleep Failed! \n"));
6048 + status = SDIO_STATUS_FUNC_ENABLE_TIMEOUT;
6054 + SemaphorePost(&pDevice->pHcd->ConfigureOpsSem);
6058 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6059 + SDAllocFreeSlotCurrent - allocate or free slot current
6060 + Input: pDevice - the device/function
6061 + Allocate - Allocate current, else free
6062 + pData - slotcurrent data (non-NULL if Allocate is TRUE)
6065 + Notes: if the function returns SDIO_STATUS_NO_RESOURCES, the pData->SlotCurrent field is
6066 + updated with the available current
6067 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
6068 +SDIO_STATUS SDAllocFreeSlotCurrent(PSDDEVICE pDevice, BOOL Allocate, PSDCONFIG_FUNC_SLOT_CURRENT_DATA pData)
6070 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
6072 + DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: SDAllocFreeSlotCurrent\n"));
6074 + /* take the configure op lock to make this atomic */
6075 + status = SemaphorePendInterruptable(&pDevice->pHcd->ConfigureOpsSem);
6076 + if (!SDIO_SUCCESS(status)) {
6080 + status = SDIO_STATUS_INVALID_PARAMETER;
6082 + /* check the current budget and allocate */
6084 + if (0 == pData->SlotCurrent) {
6085 + /* caller must specify current requirement for the power mode */
6088 + if (pDevice->SlotCurrentAlloc != 0) {
6089 + /* slot current has already been allocated, caller needs to free
6091 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Slot Current Already allocated! \n"));
6094 + if (((UINT32)pDevice->pHcd->SlotCurrentAllocated + (UINT32)pData->SlotCurrent) >
6095 + (UINT32)pDevice->pHcd->MaxSlotCurrent) {
6096 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Slot Current Budget exceeded, Requesting: %d, Allocated already: %d, Max: %d \n",
6097 + pData->SlotCurrent, pDevice->pHcd->SlotCurrentAllocated,
6098 + pDevice->pHcd->MaxSlotCurrent));
6099 + status = SDIO_STATUS_NO_RESOURCES;
6100 + /* return remaining */
6101 + pData->SlotCurrent = pDevice->pHcd->MaxSlotCurrent -
6102 + pDevice->pHcd->SlotCurrentAllocated;
6105 + /* bump up allocation */
6106 + pDevice->pHcd->SlotCurrentAllocated += pData->SlotCurrent;
6107 + /* save this off for the call to free slot current */
6108 + pDevice->SlotCurrentAlloc = pData->SlotCurrent;
6109 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Slot Current Requested: %d, New Total: %d, Max: %d \n",
6110 + pData->SlotCurrent, pDevice->pHcd->SlotCurrentAllocated,
6111 + pDevice->pHcd->MaxSlotCurrent));
6114 + if (0 == pDevice->SlotCurrentAlloc) {
6115 + /* no allocation */
6118 + /* return the allocation back */
6119 + if (pDevice->SlotCurrentAlloc <= pDevice->pHcd->SlotCurrentAllocated) {
6120 + pDevice->pHcd->SlotCurrentAllocated -= pDevice->SlotCurrentAlloc;
6121 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Slot Current Freed: %d, New Total: %d, Max: %d \n",
6122 + pDevice->SlotCurrentAlloc, pDevice->pHcd->SlotCurrentAllocated,
6123 + pDevice->pHcd->MaxSlotCurrent));
6125 + DBG_ASSERT(FALSE);
6128 + /* make sure this is zeroed */
6129 + pDevice->SlotCurrentAlloc = 0;
6132 + status = SDIO_STATUS_SUCCESS;
6136 + SemaphorePost(&pDevice->pHcd->ConfigureOpsSem);
6137 + DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: SDAllocFreeSlotCurrent, %d\n", status));
6141 +static void RawHcdIrqControl(PSDHCD pHcd, BOOL Enable)
6143 + SDIO_STATUS status;
6144 + SDCONFIG_SDIO_INT_CTRL_DATA irqData;
6145 + CT_DECLARE_IRQ_SYNC_CONTEXT();
6147 + ZERO_OBJECT(irqData);
6149 + status = _AcquireHcdLock(pHcd);
6150 + if (!SDIO_SUCCESS(status)) {
6155 + /* for raw devices, we simply enable/disable in the HCD only */
6157 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver (RAW) Unmasking Int \n"));
6158 + irqData.IRQDetectMode = IRQ_DETECT_RAW;
6159 + irqData.SlotIRQEnable = TRUE;
6161 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver (RAW) Masking Int \n"));
6162 + irqData.SlotIRQEnable = FALSE;
6165 + status = _IssueConfig(pHcd,SDCONFIG_SDIO_INT_CTRL,
6166 + (PVOID)&irqData, sizeof(irqData));
6168 + if (!SDIO_SUCCESS(status)){
6169 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver failed to enable/disable IRQ in (RAW) hcd :%d\n",
6175 + status = _ReleaseHcdLock(pHcd);
6178 +static void RawHcdEnableIrqPseudoComplete(PSDREQUEST pReq)
6180 + if (SDIO_SUCCESS(pReq->Status)) {
6181 + RawHcdIrqControl((PSDHCD)pReq->pCompleteContext, TRUE);
6183 + FreeRequest(pReq);
6186 +static void RawHcdDisableIrqPseudoComplete(PSDREQUEST pReq)
6188 + RawHcdIrqControl((PSDHCD)pReq->pCompleteContext, FALSE);
6189 + FreeRequest(pReq);
6192 +static void HcdIrqControl(PSDHCD pHcd, BOOL Enable)
6194 + SDIO_STATUS status;
6195 + SDCONFIG_SDIO_INT_CTRL_DATA irqData;
6196 + CT_DECLARE_IRQ_SYNC_CONTEXT();
6198 + ZERO_OBJECT(irqData);
6200 + status = _AcquireHcdLock(pHcd);
6201 + if (!SDIO_SUCCESS(status)) {
6206 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: HcdIrqControl (%s), IrqsEnabled:0x%X \n",
6207 + Enable ? "Enable":"Disable",pHcd->IrqsEnabled ));
6210 + irqData.SlotIRQEnable = TRUE;
6212 + irqData.SlotIRQEnable = FALSE;
6214 + /* setup HCD to enable/disable it's detection hardware */
6215 + if (irqData.SlotIRQEnable) {
6216 + /* set the IRQ detection mode */
6217 + switch (SDCONFIG_GET_BUSWIDTH(pHcd->CardProperties.BusMode)) {
6218 + case SDCONFIG_BUS_WIDTH_SPI:
6219 + irqData.IRQDetectMode = IRQ_DETECT_SPI;
6221 + case SDCONFIG_BUS_WIDTH_1_BIT:
6222 + irqData.IRQDetectMode = IRQ_DETECT_1_BIT;
6224 + case SDCONFIG_BUS_WIDTH_4_BIT:
6225 + irqData.IRQDetectMode = IRQ_DETECT_4_BIT;
6226 + /* check card and HCD for 4bit multi-block interrupt support */
6227 + if ((pHcd->CardProperties.SDIOCaps & SDIO_CAPS_INT_MULTI_BLK) &&
6228 + (pHcd->Attributes & SDHCD_ATTRIB_MULTI_BLK_IRQ)) {
6229 + /* note: during initialization of the card, the mult-blk IRQ support
6230 + * is enabled in card caps register */
6231 + irqData.IRQDetectMode |= IRQ_DETECT_MULTI_BLK;
6232 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver enabling IRQ in multi-block mode:\n"));
6236 + DBG_ASSERT(FALSE);
6240 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver enabling IRQ in HCD Mode:0x%X\n",
6241 + irqData.IRQDetectMode));
6244 + status = _IssueConfig(pHcd,SDCONFIG_SDIO_INT_CTRL,
6245 + (PVOID)&irqData, sizeof(irqData));
6246 + if (!SDIO_SUCCESS(status)){
6247 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver failed to enable/disable IRQ in hcd %d\n",
6253 + status = _ReleaseHcdLock(pHcd);
6256 +static BOOL CheckWriteIntEnableSuccess(PSDREQUEST pReq)
6258 + if (!SDIO_SUCCESS(pReq->Status)){
6259 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get write INT Enable register Err:%d\n",
6264 + if (SD_R5_GET_RESP_FLAGS(pReq->Response) & SD_R5_ERRORS) {
6265 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: WriteIntEnableComplete CMD52 resp error: 0x%X \n",
6266 + SD_R5_GET_RESP_FLAGS(pReq->Response)));
6273 +static void HcdIrqEnableComplete(PSDREQUEST pReq)
6275 + if (CheckWriteIntEnableSuccess(pReq)) {
6276 + /* configure HCD */
6277 + HcdIrqControl((PSDHCD)pReq->pCompleteContext, TRUE);
6279 + FreeRequest(pReq);
6282 +static void HcdIrqDisableComplete(PSDREQUEST pReq)
6284 + CheckWriteIntEnableSuccess(pReq);
6285 + HcdIrqControl((PSDHCD)pReq->pCompleteContext, FALSE);
6286 + FreeRequest(pReq);
6289 +static void WriteIntEnableComplete(PSDREQUEST pReq)
6291 + if (CheckWriteIntEnableSuccess(pReq)) {
6292 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Wrote INT Enable value:0x%X \n",
6293 + (INT)pReq->pCompleteContext));
6295 + FreeRequest(pReq);
6298 +static void HcdAckComplete(PSDREQUEST pReq)
6300 + SDIO_STATUS status;
6301 + DBG_PRINT(SDIODBG_FUNC_IRQ, ("SDIO Bus Driver: Hcd (0x%X) Irq Ack \n",
6302 + (INT)pReq->pCompleteContext));
6303 + /* re-arm the HCD */
6304 + status = _IssueConfig((PSDHCD)pReq->pCompleteContext,SDCONFIG_SDIO_REARM_INT,NULL,0);
6306 + if (!SDIO_SUCCESS(status)) {
6307 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: HCD Re-Arm failed : %d\n",
6310 + FreeRequest(pReq);
6312 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6313 + SDFunctionAckInterrupt - handle device interrupt acknowledgement
6314 + Input: pDevice - the device
6318 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
6319 +SDIO_STATUS SDFunctionAckInterrupt(PSDDEVICE pDevice)
6321 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
6323 + PSDREQUEST pReq = NULL;
6324 + BOOL setHcd = FALSE;
6325 + SDIO_STATUS status2;
6326 + CT_DECLARE_IRQ_SYNC_CONTEXT();
6328 + pReq = AllocateRequest();
6329 + if (NULL == pReq) {
6330 + return SDIO_STATUS_NO_RESOURCES;
6333 + status = _AcquireHcdLock(pDevice->pHcd);
6335 + if (!SDIO_SUCCESS(status)) {
6336 + FreeRequest(pReq);
6341 + if (!((SDDEVICE_GET_SDIO_FUNCNO(pDevice) >= SDIO_FIRST_FUNCTION_NUMBER) &&
6342 + (SDDEVICE_GET_SDIO_FUNCNO(pDevice) <= SDIO_LAST_FUNCTION_NUMBER))){
6343 + status = SDIO_STATUS_INVALID_PARAMETER;
6344 + DBG_ASSERT(FALSE);
6347 + mask = 1 << SDDEVICE_GET_SDIO_FUNCNO(pDevice);
6348 + if (pDevice->pHcd->PendingIrqAcks & mask) {
6349 + /* clear the ack bit in question */
6350 + pDevice->pHcd->PendingIrqAcks &= ~mask;
6351 + if (0 == pDevice->pHcd->PendingIrqAcks) {
6352 + pDevice->pHcd->IrqProcState = SDHCD_IDLE;
6353 + /* no pending acks, so re-arm if irqs are stilled enabled */
6354 + if (pDevice->pHcd->IrqsEnabled) {
6356 + /* issue pseudo request to sync this with bus requests */
6357 + pReq->Status = SDIO_STATUS_SUCCESS;
6358 + pReq->pCompletion = HcdAckComplete;
6359 + pReq->pCompleteContext = pDevice->pHcd;
6360 + pReq->Flags = SD_PSEUDO_REQ_FLAGS;
6364 + DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: AckInterrupt: no IRQ pending on Function :%d, \n",
6365 + SDDEVICE_GET_SDIO_FUNCNO(pDevice)));
6369 + status2 = ReleaseHcdLock(pDevice);
6371 + if (pReq != NULL) {
6372 + if (SDIO_SUCCESS(status) && (setHcd)) {
6373 + /* issue request */
6374 + IssueRequestToHCD(pDevice->pHcd,pReq);
6376 + FreeRequest(pReq);
6383 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6384 + SDMaskUnmaskFunctionIRQ - mask/unmask function IRQ
6385 + Input: pDevice - the device/function
6386 + MaskInt - mask interrupt
6389 + Notes: Note, this function can be called from an ISR or completion context
6390 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
6391 +SDIO_STATUS SDMaskUnmaskFunctionIRQ(PSDDEVICE pDevice, BOOL MaskInt)
6393 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
6397 + PSDREQUEST pReq = NULL;
6398 + SDIO_STATUS status2;
6400 + CT_DECLARE_IRQ_SYNC_CONTEXT();
6404 + pReq = AllocateRequest();
6405 + if (NULL == pReq) {
6406 + return SDIO_STATUS_NO_RESOURCES;
6409 + status = _AcquireHcdLock(pDevice->pHcd);
6411 + if (!SDIO_SUCCESS(status)) {
6412 + FreeRequest(pReq);
6418 + if (pDevice->pHcd->CardProperties.Flags & CARD_RAW) {
6420 + if (!pDevice->pHcd->IrqsEnabled) {
6421 + pReq->pCompletion = RawHcdEnableIrqPseudoComplete;
6423 + pDevice->pHcd->IrqsEnabled = 1 << 1;
6426 + if (pDevice->pHcd->IrqsEnabled) {
6427 + pReq->pCompletion = RawHcdDisableIrqPseudoComplete;
6429 + pDevice->pHcd->IrqsEnabled = 0;
6434 + /* hcd IRQ control requests must be synched with outstanding
6435 + * bus requests so we issue a pseudo bus request */
6436 + pReq->pCompleteContext = pDevice->pHcd;
6437 + pReq->Flags = SD_PSEUDO_REQ_FLAGS;
6438 + pReq->Status = SDIO_STATUS_SUCCESS;
6440 + /* no request to submit, just free it */
6441 + FreeRequest(pReq);
6444 + /* we're done, submit the bus request if any */
6448 + if (!(pDevice->pHcd->CardProperties.Flags & CARD_SDIO)){
6449 + /* nothing to do if it's not an SDIO card */
6450 + DBG_ASSERT(FALSE);
6451 + status = SDIO_STATUS_INVALID_PARAMETER;
6455 + if (!((SDDEVICE_GET_SDIO_FUNCNO(pDevice) >= SDIO_FIRST_FUNCTION_NUMBER) &&
6456 + (SDDEVICE_GET_SDIO_FUNCNO(pDevice) <= SDIO_LAST_FUNCTION_NUMBER))){
6457 + status = SDIO_STATUS_INVALID_PARAMETER;
6458 + DBG_ASSERT(FALSE);
6462 + mask = 1 << SDDEVICE_GET_SDIO_FUNCNO(pDevice);
6464 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver Unmasking Int, Mask:0x%X\n", mask));
6465 + /* check interrupts that were enabled on entry */
6466 + if (0 == pDevice->pHcd->IrqsEnabled) {
6467 + /* need to turn on interrupts in HCD */
6469 + /* use this completion routine */
6470 + pReq->pCompletion = HcdIrqEnableComplete;
6472 + /* set the enable bit, in the shadow register */
6473 + pDevice->pHcd->IrqsEnabled |= mask;
6474 + /* make sure control value includes the master enable */
6475 + controlVal = pDevice->pHcd->IrqsEnabled | SDIO_INT_MASTER_ENABLE;
6477 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver Masking Int, Mask:0x%X\n", mask));
6478 + /* clear the bit */
6479 + pDevice->pHcd->IrqsEnabled &= ~mask;
6480 + /* check and see if this clears all the bits */
6481 + if (0 == pDevice->pHcd->IrqsEnabled){
6482 + /* if none of the functions are enabled, clear this register */
6484 + /* disable in host */
6486 + /* use this completion routine */
6487 + pReq->pCompletion = HcdIrqDisableComplete;
6489 + /* set control value making sure master enable is left on */
6490 + controlVal = pDevice->pHcd->IrqsEnabled | SDIO_INT_MASTER_ENABLE;
6494 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver INT_ENABLE_REG value:0x%X\n", controlVal));
6495 + /* setup bus request to update the mask register */
6496 + SDIO_SET_CMD52_WRITE_ARG(pReq->Argument,0,SDIO_INT_ENABLE_REG,controlVal);
6497 + pReq->Command = CMD52;
6498 + pReq->Flags = SDREQ_FLAGS_TRANS_ASYNC | SDREQ_FLAGS_RESP_SDIO_R5;
6501 + /* make this a barrier request and set context*/
6502 + pReq->Flags |= SDREQ_FLAGS_BARRIER;
6503 + pReq->pCompleteContext = pDevice->pHcd;
6505 + /* does not require an update to the HCD */
6506 + pReq->pCompleteContext = (PVOID)(UINT32)controlVal;
6507 + pReq->pCompletion = WriteIntEnableComplete;
6512 + status2 = _ReleaseHcdLock(pDevice->pHcd);
6514 + if (pReq != NULL) {
6515 + if (SDIO_SUCCESS(status)) {
6516 + /* issue request */
6517 + IssueRequestToHCD(pDevice->pHcd,pReq);
6519 + FreeRequest(pReq);
6527 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6528 + SDSPIModeEnableDisableCRC - Enable/Disable SPI Mode CRC checking
6529 + Input: pDevice - the device/function
6530 + Enable - Enable CRC
6533 + Notes: Note, this function can be called from an ISR or completion context
6534 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
6535 +SDIO_STATUS SDSPIModeEnableDisableCRC(PSDDEVICE pDevice,BOOL Enable)
6537 + SDCONFIG_BUS_MODE_DATA busMode;
6538 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
6539 + UINT32 cmdARG = 0;
6541 + if (!SDDEVICE_IS_BUSMODE_SPI(pDevice)) {
6542 + return SDIO_STATUS_INVALID_PARAMETER;
6544 + //??we should make these atomic using a barrier
6546 + /* get the current mode and clock */
6547 + busMode.BusModeFlags = pDevice->pHcd->CardProperties.BusMode;
6548 + busMode.ClockRate = pDevice->pHcd->CardProperties.OperBusClock;
6551 + /* clear the no-CRC flag */
6552 + busMode.BusModeFlags &= ~SDCONFIG_BUS_MODE_SPI_NO_CRC;
6553 + cmdARG = SD_CMD59_CRC_ON;
6555 + busMode.BusModeFlags |= SDCONFIG_BUS_MODE_SPI_NO_CRC;
6556 + cmdARG = SD_CMD59_CRC_OFF;
6560 + /* issue CMD59 to turn on/off CRC */
6561 + status = _IssueSimpleBusRequest(pDevice->pHcd,
6564 + SDREQ_FLAGS_RESP_R1,
6566 + if (!SDIO_SUCCESS(status)) {
6567 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed issue CMD59 (arg=0x%X) Err:%d \n",
6572 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: CRC Enabled in SPI mode \n"));
6574 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: CRC Disabled in SPI mode \n"));
6576 + status = SetOperationalBusMode(pDevice,&busMode);
6577 + if (!SDIO_SUCCESS(status)) {
6578 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set SPI NO CRC mode in hcd : Err:%d \n",
6588 +static UINT32 ConvertSPIStatusToSDCardStatus(UINT8 SpiR1, UINT8 SpiR2)
6590 + UINT32 cardStatus = 0;
6593 + /* convert the error */
6594 + if (SpiR1 & SPI_CS_ERASE_RESET) {
6595 + cardStatus |= SD_CS_ERASE_RESET;
6597 + if (SpiR1 & SPI_CS_ILLEGAL_CMD) {
6598 + cardStatus |= SD_CS_ILLEGAL_CMD_ERR;
6600 + if (SpiR1 & SPI_CS_CMD_CRC_ERR) {
6601 + cardStatus |= SD_CS_PREV_CMD_CRC_ERR;
6603 + if (SpiR1 & SPI_CS_ERASE_SEQ_ERR) {
6604 + cardStatus |= SD_CS_ERASE_SEQ_ERR;
6606 + if (SpiR1 & SPI_CS_ADDRESS_ERR) {
6607 + cardStatus |= SD_CS_ADDRESS_ERR;
6609 + if (SpiR1 & SPI_CS_PARAM_ERR) {
6610 + cardStatus |= SD_CS_CMD_OUT_OF_RANGE;
6615 + /* convert the error */
6616 + if (SpiR2 & SPI_CS_CARD_IS_LOCKED) {
6617 + cardStatus |= SD_CS_CARD_LOCKED;
6619 + if (SpiR2 & SPI_CS_LOCK_UNLOCK_FAILED) {
6620 + /* this bit is shared, just set both */
6621 + cardStatus |= (SD_CS_LK_UNLK_FAILED | SD_CS_WP_ERASE_SKIP);
6623 + if (SpiR2 & SPI_CS_ERROR) {
6624 + cardStatus |= SD_CS_GENERAL_ERR;
6626 + if (SpiR2 & SPI_CS_INTERNAL_ERROR) {
6627 + cardStatus |= SD_CS_CARD_INTERNAL_ERR;
6629 + if (SpiR2 & SPI_CS_ECC_FAILED) {
6630 + cardStatus |= SD_CS_ECC_FAILED;
6632 + if (SpiR2 & SPI_CS_WP_VIOLATION) {
6633 + cardStatus |= SD_CS_WP_ERR;
6635 + if (SpiR2 & SPI_CS_ERASE_PARAM_ERR) {
6636 + cardStatus |= SD_CS_ERASE_PARAM_ERR;
6638 + if (SpiR2 & SPI_CS_OUT_OF_RANGE) {
6639 + cardStatus |= SD_CS_CMD_OUT_OF_RANGE;
6643 + return cardStatus;
6645 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6646 + ConvertSPI_Response - filter the SPI response and convert it to an SD Response
6647 + Input: pReq - request
6648 + Output: pReq - modified response, if pRespBuffer is not NULL
6649 + pRespBuffer - converted response (optional)
6651 + Notes: This function converts a SPI response into an SD response. A caller
6652 + can supply a buffer instead.
6653 + For SPI bus operation the HCD must send the SPI response as
6654 + a stream of bytes, the highest byte contains the first received byte from the
6655 + card. This function only filters simple responses (R1 primarily).
6656 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
6657 +void ConvertSPI_Response(PSDREQUEST pReq, UINT8 *pRespBuffer)
6660 + UINT32 cardStatus;
6662 + if (pReq->Flags & SDREQ_FLAGS_RESP_SPI_CONVERTED) {
6663 + /* already converted */
6666 + if (NULL == pRespBuffer) {
6667 + pRespBuffer = pReq->Response;
6670 + switch (GET_SDREQ_RESP_TYPE(pReq->Flags)) {
6671 + case SDREQ_FLAGS_RESP_R1:
6672 + case SDREQ_FLAGS_RESP_R1B:
6673 + cardStatus = ConvertSPIStatusToSDCardStatus(GET_SPI_R1_RESP_TOKEN(pReq->Response),
6675 + if (CMD55 == pReq->Command) {
6676 + /* we emulate this since SPI does not have such a bit */
6677 + cardStatus |= SD_CS_APP_CMD;
6679 + /* stuff the SD card status */
6680 + SD_R1_SET_CMD_STATUS(pRespBuffer,cardStatus);
6681 + /* stuff the command */
6682 + SD_R1_SET_CMD(pRespBuffer,pReq->Command);
6683 + pReq->Flags |= SDREQ_FLAGS_RESP_SPI_CONVERTED;
6685 + case SDREQ_FLAGS_RESP_SDIO_R5:
6690 + readData = GET_SPI_SDIO_R5_RESPONSE_RDATA(pReq->Response);
6691 + respFlags = GET_SPI_SDIO_R5_RESP_TOKEN(pReq->Response);
6693 + pRespBuffer[SD_R5_RESP_FLAGS_OFFSET] = 0;
6694 + if (respFlags != 0) {
6695 + if (respFlags & SPI_R5_ILLEGAL_CMD) {
6696 + pRespBuffer[SD_R5_RESP_FLAGS_OFFSET] |= SD_R5_ILLEGAL_CMD;
6698 + if (respFlags & SPI_R5_CMD_CRC) {
6699 + pRespBuffer[SD_R5_RESP_FLAGS_OFFSET] |= SD_R5_RESP_CMD_ERR;
6701 + if (respFlags & SPI_R5_FUNC_ERR) {
6702 + pRespBuffer[SD_R5_RESP_FLAGS_OFFSET] |= SD_R5_INVALID_FUNC;
6704 + if (respFlags & SPI_R5_PARAM_ERR) {
6705 + pRespBuffer[SD_R5_RESP_FLAGS_OFFSET] |= SD_R5_ARG_RANGE_ERR;
6708 + /* stuff read data */
6709 + pRespBuffer[SD_SDIO_R5_READ_DATA_OFFSET] = readData;
6710 + /* stuff the command */
6711 + SD_R5_SET_CMD(pRespBuffer,pReq->Command);
6713 + pReq->Flags |= SDREQ_FLAGS_RESP_SPI_CONVERTED;
6715 + case SDREQ_FLAGS_RESP_R2:
6716 + /* for CMD13 and ACMD13 , SPI uses it's own R2 response format (2 bytes) */
6717 + /* the issue of CMD13 needs to change the response flag to R2 */
6718 + if (CMD13 == pReq->Command) {
6719 + cardStatus = ConvertSPIStatusToSDCardStatus(
6720 + GET_SPI_R2_RESP_TOKEN(pReq->Response),
6721 + GET_SPI_R2_STATUS_TOKEN(pReq->Response));
6722 + /* stuff the SD card status */
6723 + SD_R1_SET_CMD_STATUS(pRespBuffer,cardStatus);
6724 + /* stuff the command */
6725 + SD_R1_SET_CMD(pRespBuffer,pReq->Command);
6726 + pReq->Flags |= SDREQ_FLAGS_RESP_SPI_CONVERTED;
6729 + /* no other commands should be using R2 when using SPI, if they are
6730 + * they should be bypassing the filter */
6731 + DBG_ASSERT(FALSE);
6734 + /* for all others:
6736 + * SDREQ_FLAGS_RESP_R6 - SPI mode does not use RCA
6737 + * SDREQ_FLAGS_RESP_R3 - bus driver handles this internally
6738 + * SDREQ_FLAGS_RESP_SDIO_R4 - bus driver handles this internally
6741 + DBG_PRINT(SDDBG_ERROR, ("ConvertSPI_Response - invalid response type:0x%2.2X",
6742 + GET_SDREQ_RESP_TYPE(pReq->Flags)));
6743 + DBG_ASSERT(FALSE);
6748 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6749 + @function: Check an SD/MMC/SDIO response.
6751 + @function name: SDIO_CheckResponse
6752 + @prototype: SDIO_STATUS SDIO_CheckResponse(PSDHCD pHcd, PSDREQUEST pReq, SDHCD_RESPONSE_CHECK_MODE CheckMode)
6753 + @category: HD_Reference
6755 + @input: pHcd - the host controller definition structure.
6756 + @input: pReq - request containing the response
6757 + @input: CheckMode - mode
6759 + @return: SDIO_STATUS
6761 + @notes: Host controller drivers must call into this function to validate various command
6762 + responses before continuing with data transfers or for decoding received SPI tokens.
6763 + The CheckMode option determines the type of validation to perform.
6764 + if (CheckMode == SDHCD_CHECK_DATA_TRANS_OK) :
6765 + The host controller must check the card response to determine whether it
6766 + is safe to perform a data transfer. This API only checks commands that
6767 + involve data transfers and checks various status fields in the command response.
6768 + If the card cannot accept data, this function will return a non-successful status that
6769 + should be treated as a request failure. The host driver should complete the request with the
6770 + returned status. Host controller should only call this function in preparation for a
6772 + if (CheckMode == SDHCD_CHECK_SPI_TOKEN) :
6773 + This API checks the SPI token and returns a timeout status if the illegal command bit is
6774 + set. This simulates the behavior of SD 1/4 bit operation where illegal commands result in
6775 + a command timeout. A driver that supports SPI mode should pass every response to this
6776 + function to determine the appropriate error status to complete the request with. If the
6777 + API returns success, the response indicates that the card accepted the command.
6779 + @example: Checking the response before starting the data transfer :
6780 + if (SDIO_SUCCESS(status) && (pReq->Flags & SDREQ_FLAGS_DATA_TRANS)) {
6781 + // check the response to see if we should continue with data
6782 + status = SDIO_CheckResponse(pHcd, pReq, SDHCD_CHECK_DATA_TRANS_OK);
6783 + if (SDIO_SUCCESS(status)) {
6784 + .... start data transfer phase
6786 + ... card response indicates that the card cannot handle data
6787 + // set completion status
6788 + pRequest->Status = status;
6792 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
6793 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6794 + _SDIO_CheckResponse - check response on behalf of the host controller
6795 + Input: pHcd - host controller
6796 + pReq - request containing the response
6802 + CheckMode == SDHCD_CHECK_DATA_TRANS_OK :
6803 + The host controller requests a check on the response to determine whether it
6804 + is okay to perform a data transfer. This function only filters on commands that
6805 + involve data. Host controller should only call this function in preparation for a
6808 + CheckMode == SDHCD_CHECK_SPI_TOKEN :
6809 + The bus driver checks the SPI token and returns a timeout status if the illegal command bit is
6810 + set. This simulates the behavior of SD native operation.
6812 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
6813 +SDIO_STATUS _SDIO_CheckResponse(PSDHCD pHcd, PSDREQUEST pReq, SDHCD_RESPONSE_CHECK_MODE CheckMode)
6815 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
6817 + if (CheckMode == SDHCD_CHECK_DATA_TRANS_OK) {
6818 + UINT32 cardStatus;
6820 + UINT8 convertedResponse[MAX_CARD_RESPONSE_BYTES];
6822 + if (!(pReq->Flags & SDREQ_FLAGS_DATA_TRANS) ||
6823 + (pReq->Flags & SDREQ_FLAGS_DATA_SKIP_RESP_CHK) ||
6824 + (GET_SDREQ_RESP_TYPE(pReq->Flags) == SDREQ_FLAGS_NO_RESP)) {
6825 + return SDIO_STATUS_SUCCESS;
6827 + pResponse = pReq->Response;
6828 + /* check SPI mode */
6829 + if (IS_HCD_BUS_MODE_SPI(pHcd)) {
6830 + if (!(pReq->Flags & SDREQ_FLAGS_RESP_SKIP_SPI_FILT)) {
6831 + /* apply conversion */
6832 + ConvertSPI_Response(pReq, NULL);
6834 + /* temporarily convert the response, without altering the original */
6835 + ConvertSPI_Response(pReq, convertedResponse);
6836 + /* point to the converted one */
6837 + pResponse = convertedResponse;
6841 + switch (GET_SDREQ_RESP_TYPE(pReq->Flags)) {
6842 + case SDREQ_FLAGS_RESP_R1:
6843 + case SDREQ_FLAGS_RESP_R1B:
6844 + cardStatus = SD_R1_GET_CARD_STATUS(pResponse);
6845 + if (!(cardStatus &
6846 + (SD_CS_ILLEGAL_CMD_ERR | SD_CS_CARD_INTERNAL_ERR | SD_CS_GENERAL_ERR))) {
6847 + /* okay for data */
6850 + /* figure out what it was */
6851 + if (cardStatus & SD_CS_ILLEGAL_CMD_ERR) {
6852 + status = SDIO_STATUS_DATA_STATE_INVALID;
6854 + status = SDIO_STATUS_DATA_ERROR_UNKNOWN;
6856 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Check Response Error. R1 CardStatus:0x%X \n",
6859 + case SDREQ_FLAGS_RESP_SDIO_R5:
6860 + cardStatus = SD_R5_GET_RESP_FLAGS(pResponse);
6861 + if (!(cardStatus & SD_R5_CURRENT_CMD_ERRORS)){
6866 + status = ConvertCMD52ResponseToSDIOStatus((UINT8)cardStatus);
6867 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Check Response Error. R5 CardStatus:0x%X \n",
6880 + /* handle SPI token validation */
6881 + switch (GET_SDREQ_RESP_TYPE(pReq->Flags)) {
6882 + case SDREQ_FLAGS_RESP_R2:
6883 + spiToken = GET_SPI_R2_RESP_TOKEN(pReq->Response);
6885 + case SDREQ_FLAGS_RESP_SDIO_R5:
6886 + spiToken = GET_SPI_SDIO_R5_RESP_TOKEN(pReq->Response);
6888 + case SDREQ_FLAGS_RESP_R3:
6889 + spiToken = GET_SPI_R3_RESP_TOKEN(pReq->Response);
6891 + case SDREQ_FLAGS_RESP_SDIO_R4:
6892 + spiToken = GET_SPI_SDIO_R4_RESP_TOKEN(pReq->Response);
6895 + /* all other tokesn are SPI R1 type */
6896 + spiToken = GET_SPI_R1_RESP_TOKEN(pReq->Response);
6900 + if ((GET_SDREQ_RESP_TYPE(pReq->Flags) == SDREQ_FLAGS_RESP_SDIO_R5) ||
6901 + (GET_SDREQ_RESP_TYPE(pReq->Flags) == SDREQ_FLAGS_RESP_SDIO_R4)) {
6902 + /* handle SDIO status tokens */
6903 + if ((spiToken & SPI_R5_ILLEGAL_CMD) ||
6904 + (spiToken & SPI_R5_CMD_CRC)) {
6905 + status = SDIO_STATUS_BUS_RESP_TIMEOUT;
6908 + /* handle all other status tokens */
6909 + if ((spiToken & SPI_CS_ILLEGAL_CMD) ||
6910 + (spiToken & SPI_CS_CMD_CRC_ERR)) {
6911 + status = SDIO_STATUS_BUS_RESP_TIMEOUT;
6919 diff --git a/drivers/sdio/stack/busdriver/sdio_bus_os.c b/drivers/sdio/stack/busdriver/sdio_bus_os.c
6920 new file mode 100644
6921 index 0000000..dbdb955
6923 +++ b/drivers/sdio/stack/busdriver/sdio_bus_os.c
6925 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6926 +@file: sdio_bus_os.c
6928 +@abstract: Linux implementation module
6930 +#notes: includes module load and unload functions
6932 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
6936 + * This program is free software; you can redistribute it and/or modify
6937 + * it under the terms of the GNU General Public License version 2 as
6938 + * published by the Free Software Foundation;
6940 + * Software distributed under the License is distributed on an "AS
6941 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
6942 + * implied. See the License for the specific language governing
6943 + * rights and limitations under the License.
6945 + * Portions of this code were developed with information supplied from the
6946 + * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply:
6948 + * The following conditions apply to the release of the SD simplified specification (�Simplified
6949 + * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete
6950 + * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided
6951 + * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified
6952 + * Specification may require a license from the SD Card Association or other third parties.
6954 + * The information contained in the Simplified Specification is presented only as a standard
6955 + * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any
6956 + * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for
6957 + * any damages, any infringements of patents or other right of the SD Card Association or any third
6958 + * parties, which may result from its use. No license is granted by implication, estoppel or otherwise
6959 + * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall
6960 + * be construed as an obligation by the SD Card Association to disclose or distribute any technical
6961 + * information, know-how or other confidential information to any third party.
6964 + * The initial developers of the original code are Seung Yi and Paul Lever
6966 + * sdio@atheros.com
6970 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
6971 +/* debug level for this module*/
6972 +#define DBG_DECLARE 3;
6974 +#include <linux/sdio/ctsystem.h>
6975 +#include <linux/kernel.h>
6976 +#include <linux/module.h>
6977 +#include <linux/version.h>
6978 +#include <linux/init.h>
6979 +#include <linux/workqueue.h>
6980 +#include <linux/delay.h>
6981 +#include <linux/kthread.h>
6982 +#include <linux/pnp.h>
6983 +void pnp_remove_card_device(struct pnp_dev *dev);
6984 +#include <linux/sdio/sdio_busdriver.h>
6985 +#include <linux/sdio/sdio_lib.h>
6986 +#include "_busdriver.h"
6988 +#define DESCRIPTION "SDIO Bus Driver"
6989 +#define AUTHOR "Atheros Communications, Inc."
6991 +/* debug print parameter */
6992 +/* configuration and default parameters */
6993 +static int RequestRetries = SDMMC_DEFAULT_CMD_RETRIES;
6994 +module_param(RequestRetries, int, 0644);
6995 +MODULE_PARM_DESC(RequestRetries, "number of command retries");
6996 +static int CardReadyPollingRetry = SDMMC_DEFAULT_CARD_READY_RETRIES;
6997 +module_param(CardReadyPollingRetry, int, 0644);
6998 +MODULE_PARM_DESC(CardReadyPollingRetry, "number of card ready retries");
6999 +static int PowerSettleDelay = SDMMC_POWER_SETTLE_DELAY;
7000 +module_param(PowerSettleDelay, int, 0644);
7001 +MODULE_PARM_DESC(PowerSettleDelay, "delay in ms for power to settle after power changes");
7002 +static int DefaultOperClock = 52000000;
7003 +module_param(DefaultOperClock, int, 0644);
7004 +MODULE_PARM_DESC(DefaultOperClock, "maximum operational clock limit");
7005 +static int DefaultBusMode = SDCONFIG_BUS_WIDTH_4_BIT;
7006 +module_param(DefaultBusMode, int, 0644);
7007 +MODULE_PARM_DESC(DefaultBusMode, "default bus mode: see SDCONFIG_BUS_WIDTH_xxx");
7008 +static int RequestListSize = SDBUS_DEFAULT_REQ_LIST_SIZE;
7009 +module_param(RequestListSize, int, 0644);
7010 +MODULE_PARM_DESC(RequestListSize, "");
7011 +static int SignalSemListSize = SDBUS_DEFAULT_REQ_SIG_SIZE;
7012 +module_param(SignalSemListSize, int, 0644);
7013 +MODULE_PARM_DESC(SignalSemListSize, "");
7014 +static int CDPollingInterval = SDBUS_DEFAULT_CD_POLLING_INTERVAL;
7015 +module_param(CDPollingInterval, int, 0644);
7016 +MODULE_PARM_DESC(CDPollingInterval, "");
7017 +static int DefaultOperBlockLen = SDMMC_DEFAULT_BYTES_PER_BLOCK;
7018 +module_param(DefaultOperBlockLen, int, 0644);
7019 +MODULE_PARM_DESC(DefaultOperBlockLen, "operational block length");
7020 +static int DefaultOperBlockCount = SDMMC_DEFAULT_BLOCKS_PER_TRANS;
7021 +module_param(DefaultOperBlockCount, int, 0644);
7022 +MODULE_PARM_DESC(DefaultOperBlockCount, "operational block count");
7023 +static int ConfigFlags = BD_DEFAULT_CONFIG_FLAGS;
7024 +module_param(ConfigFlags, int, 0644);
7025 +MODULE_PARM_DESC(ConfigFlags, "config flags");
7027 +static int HcdRCount = MAX_HCD_REQ_RECURSION;
7028 +module_param(HcdRCount, int, 0644);
7029 +MODULE_PARM_DESC(HcdRCount, "HCD request recursion count");
7031 +static void CardDetect_WorkItem(
7032 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
7035 +struct work_struct *ignored);
7037 +static void CardDetect_TimerFunc(unsigned long Context);
7038 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
7039 +static DECLARE_WORK(CardDetectPollWork, CardDetect_WorkItem
7040 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
7046 +static int RegisterDriver(PSDFUNCTION pFunction);
7047 +static int UnregisterDriver(PSDFUNCTION pFunction);
7049 +static struct timer_list CardDetectTimer;
7051 +#define SDDEVICE_FROM_OSDEVICE(pOSDevice) container_of(pOSDevice, SDDEVICE, Device)
7052 +#define SDFUNCTION_FROM_OSDRIVER(pOSDriver) container_of(pOSDriver, SDFUNCTION, Driver)
7056 + * SDIO_RegisterHostController - register a host controller bus driver
7058 +SDIO_STATUS SDIO_RegisterHostController(PSDHCD pHcd) {
7059 + /* we are the exported verison, call the internal verison */
7060 + return _SDIO_RegisterHostController(pHcd);
7064 + * SDIO_UnregisterHostController - unregister a host controller bus driver
7066 +SDIO_STATUS SDIO_UnregisterHostController(PSDHCD pHcd) {
7067 + /* we are the exported verison, call the internal verison */
7068 + return _SDIO_UnregisterHostController(pHcd);
7072 + * SDIO_RegisterFunction - register a function driver
7074 +SDIO_STATUS SDIO_RegisterFunction(PSDFUNCTION pFunction) {
7076 + SDIO_STATUS status;
7078 + DBG_PRINT(SDDBG_TRACE, ("SDIO BusDriver - SDIO_RegisterFunction\n"));
7080 + /* since we do PnP registration first, we need to check the version */
7081 + if (!CHECK_FUNCTION_DRIVER_VERSION(pFunction)) {
7082 + DBG_PRINT(SDDBG_ERROR,
7083 + ("SDIO Bus Driver: Function Major Version Mismatch (hcd = %d, bus driver = %d)\n",
7084 + GET_SDIO_STACK_VERSION_MAJOR(pFunction), CT_SDIO_STACK_VERSION_MAJOR(g_Version)));
7085 + return SDIO_STATUS_INVALID_PARAMETER;
7088 + /* we are the exported verison, call the internal verison after registering with the bus
7089 + we handle probes internally to the bus driver */
7090 + if ((error = RegisterDriver(pFunction)) < 0) {
7091 + DBG_PRINT(SDDBG_ERROR,
7092 + ("SDIO BusDriver - SDIO_RegisterFunction, failed to register with system bus driver: %d\n",
7094 + status = OSErrorToSDIOError(error);
7096 + status = _SDIO_RegisterFunction(pFunction);
7097 + if (!SDIO_SUCCESS(status)) {
7098 + UnregisterDriver(pFunction);
7106 + * SDIO_UnregisterFunction - unregister a function driver
7108 +SDIO_STATUS SDIO_UnregisterFunction(PSDFUNCTION pFunction) {
7109 + SDIO_STATUS status;
7110 + /* we are the exported verison, call the internal verison */
7111 + status = _SDIO_UnregisterFunction(pFunction);
7112 + UnregisterDriver(pFunction);
7117 + * SDIO_HandleHcdEvent - tell core an event occurred
7119 +SDIO_STATUS SDIO_HandleHcdEvent(PSDHCD pHcd, HCD_EVENT Event) {
7120 + /* we are the exported verison, call the internal verison */
7121 + DBG_PRINT(SDIODBG_HCD_EVENTS, ("SDIO Bus Driver: SDIO_HandleHcdEvent, event type 0x%X, HCD:0x%X\n",
7122 + Event, (UINT)pHcd));
7123 + return _SDIO_HandleHcdEvent(pHcd, Event);
7126 +/* get default settings */
7127 +SDIO_STATUS _SDIO_BusGetDefaultSettings(PBDCONTEXT pBdc)
7129 + /* these defaults are module params */
7130 + pBdc->RequestRetries = RequestRetries;
7131 + pBdc->CardReadyPollingRetry = CardReadyPollingRetry;
7132 + pBdc->PowerSettleDelay = PowerSettleDelay;
7133 + pBdc->DefaultOperClock = DefaultOperClock;
7134 + pBdc->DefaultBusMode = DefaultBusMode;
7135 + pBdc->RequestListSize = RequestListSize;
7136 + pBdc->SignalSemListSize = SignalSemListSize;
7137 + pBdc->CDPollingInterval = CDPollingInterval;
7138 + pBdc->DefaultOperBlockLen = DefaultOperBlockLen;
7139 + pBdc->DefaultOperBlockCount = DefaultOperBlockCount;
7140 + pBdc->ConfigFlags = ConfigFlags;
7141 + pBdc->MaxHcdRecursion = HcdRCount;
7142 + return SDIO_STATUS_SUCCESS;
7145 +static void CardDetect_TimerFunc(unsigned long Context)
7147 + DBG_PRINT(SDIODBG_CD_TIMER, ("+ SDIO BusDriver Card Detect Timer\n"));
7149 + /* timers run in an ISR context and cannot block or sleep, so we need
7150 + * to queue a work item to call the bus driver timer notification */
7151 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
7152 + if (schedule_work(&CardDetectPollWork) <= 0) {
7153 + DBG_PRINT(SDDBG_ERROR, ("Failed to queue Card Detect timer!\n"));
7156 + CardDetect_WorkItem(NULL);
7158 + DBG_PRINT(SDIODBG_CD_TIMER, ("- SDIO BusDriver Card Detect Timer\n"));
7162 + * Initialize any timers we are using
7164 +SDIO_STATUS InitializeTimers(void)
7166 + init_timer(&CardDetectTimer);
7167 + CardDetectTimer.function = CardDetect_TimerFunc;
7168 + CardDetectTimer.data = 0;
7169 + return SDIO_STATUS_SUCCESS;
7175 +SDIO_STATUS CleanupTimers(void)
7177 + del_timer(&CardDetectTimer);
7178 + return SDIO_STATUS_SUCCESS;
7183 + * Queue a timer, Timeout is in milliseconds
7185 +SDIO_STATUS QueueTimer(INT TimerID, UINT32 TimeOut)
7189 + /* convert timeout to ticks */
7190 + delta = (TimeOut * HZ)/1000;
7194 + DBG_PRINT(SDIODBG_CD_TIMER, ("SDIO BusDriver - SDIO_QueueTimer System Ticks Per Sec:%d \n",HZ));
7195 + DBG_PRINT(SDIODBG_CD_TIMER, ("SDIO BusDriver - SDIO_QueueTimer TimerID: %d TimeOut:%d MS, requires %d Ticks\n",
7196 + TimerID,TimeOut,delta));
7197 + switch (TimerID) {
7198 + case SDIOBUS_CD_TIMER_ID:
7199 + CardDetectTimer.expires = jiffies + delta;
7200 + add_timer(&CardDetectTimer);
7203 + return SDIO_STATUS_INVALID_PARAMETER;
7206 + return SDIO_STATUS_SUCCESS;
7209 +/* check a response on behalf of the host controller, to allow it to proceed with a
7210 + * data transfer */
7211 +SDIO_STATUS SDIO_CheckResponse(PSDHCD pHcd, PSDREQUEST pReq, SDHCD_RESPONSE_CHECK_MODE CheckMode)
7213 + return _SDIO_CheckResponse(pHcd,pReq,CheckMode);
7217 + * CardDetect_WorkItem - the work item for handling card detect polling interrupt
7219 +static void CardDetect_WorkItem(
7220 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
7223 +struct work_struct *ignored)
7226 + /* call bus driver function */
7227 + SDIO_NotifyTimerTriggered(SDIOBUS_CD_TIMER_ID);
7231 + * OS_IncHcdReference - increment host controller driver reference count
7233 +SDIO_STATUS Do_OS_IncHcdReference(PSDHCD pHcd)
7235 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
7238 + if (NULL == pHcd->pModule) {
7239 + /* hcds that are 2.3 or higher should set this */
7240 + DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: HCD:%s should set module ptr!\n",
7241 + (pHcd->pName != NULL) ? pHcd->pName : "Unknown"));
7245 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
7246 + if (!try_module_get(pHcd->pModule)) {
7247 + status = SDIO_STATUS_ERROR;
7250 + if (!try_inc_mod_count(pHcd->pModule)) {
7251 + status = SDIO_STATUS_ERROR;
7257 + if (!SDIO_SUCCESS(status)) {
7258 + DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: HCD:%s failed to get module\n",
7259 + (pHcd->pName != NULL) ? pHcd->pName : "Unknown"));
7266 + * OS_DecHcdReference - decrement host controller driver reference count
7268 +SDIO_STATUS Do_OS_DecHcdReference(PSDHCD pHcd)
7270 + if (pHcd->pModule != NULL) {
7271 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
7272 + module_put(pHcd->pModule);
7274 + /* 2.4 or lower */
7275 + __MOD_DEC_USE_COUNT(pHcd->pModule);
7278 + return SDIO_STATUS_SUCCESS;
7281 +/****************************************************************************************/
7283 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
7284 +#include <linux/pnp.h>
7286 +#if !defined(CONFIG_PNP)
7287 +#error "CONFIG_PNP not defined"
7290 +static ULONG InUseDevices = 0;
7291 +static spinlock_t InUseDevicesLock = SPIN_LOCK_UNLOCKED;
7293 +static const struct pnp_device_id pnp_idtable[] = {
7296 +static int sdio_get_resources(struct pnp_dev * pDev, struct pnp_resource_table * res)
7298 + DBG_PRINT(SDDBG_TRACE,
7299 + ("SDIO BusDriver - sdio_get_resources: %s\n",
7300 + pDev->dev.bus_id));
7303 +static int sdio_set_resources(struct pnp_dev * pDev, struct pnp_resource_table * res)
7305 + DBG_PRINT(SDDBG_TRACE,
7306 + ("SDIO BusDriver - sdio_set_resources: %s\n",
7307 + pDev->dev.bus_id));
7311 +static int sdio_disable_resources(struct pnp_dev *pDev)
7313 + DBG_PRINT(SDDBG_TRACE,
7314 + ("SDIO BusDriver - sdio_disable_resources: %s\n",
7315 + pDev->dev.bus_id));
7316 + if (pDev != NULL) {
7321 +void release(struct device * pDev) {
7322 + DBG_PRINT(SDDBG_TRACE,
7323 + ("SDIO BusDriver - release: %s\n",
7327 +struct pnp_protocol sdio_protocol = {
7329 + .get = sdio_get_resources,
7330 + .set = sdio_set_resources,
7331 + .disable = sdio_disable_resources,
7332 + .dev.release = release,
7336 + * driver_probe - probe for OS based driver
7338 +static int driver_probe(struct pnp_dev* pOSDevice, const struct pnp_device_id *pId)
7340 + PSDDEVICE pDevice = SDDEVICE_FROM_OSDEVICE(pOSDevice);
7341 + PSDFUNCTION pFunction = pDevice->Device.dev.driver_data;
7343 + if (pFunction == NULL) {
7347 + if (strcmp(pFunction->pName, pOSDevice->dev.driver->name) == 0) {
7348 + DBG_PRINT(SDDBG_TRACE,
7349 + ("SDIO BusDriver - driver_probe, match: %s/%s driver: %s\n",
7350 + pOSDevice->dev.bus_id, pFunction->pName, pOSDevice->dev.driver->name));
7353 + DBG_PRINT(SDDBG_TRACE,
7354 + ("SDIO BusDriver - driver_probe, no match: %s/%s driver: %s\n",
7355 + pOSDevice->dev.bus_id, pFunction->pName, pOSDevice->dev.driver->name));
7358 +/* if (pOSDevice->id != NULL) {
7359 + if (strcmp(pOSDevice->id->id, pId->id) == 0) {
7360 + DBG_PRINT(SDDBG_TRACE,
7361 + ("SDIO BusDriver - driver_probe, match: %s/%s\n",
7362 + pOSDevice->dev.bus_id, pId->id));
7365 + DBG_PRINT(SDDBG_TRACE,
7366 + ("SDIO BusDriver - driver_probe, did not match: %s/%s/%s\n",
7367 + pOSDevice->dev.bus_id, pId->id, pOSDevice->id->id));
7369 + DBG_PRINT(SDDBG_TRACE,
7370 + ("SDIO BusDriver - driver_probe, did not match: %s/%s\n",
7371 + pOSDevice->dev.bus_id, pId->id));
7375 +//?? if (pDevice->Device.dev.driver_data != NULL) {
7376 +//?? if (pDevice->Device.dev.driver_data == pFunction) {
7377 +//?? if (pDevice->Device.data != NULL) {
7378 +//?? if (pDevice->Device.data == pFunction) {
7379 +//?? DBG_PRINT(SDDBG_TRACE,
7380 +//?? ("SDIO BusDriver - driver_probe, match: %s\n",
7381 +//?? pOSDevice->dev.bus_id));
7385 + DBG_PRINT(SDDBG_TRACE,
7386 + ("SDIO BusDriver - driver_probe, match: %s\n",
7387 + pOSDevice->dev.bus_id));
7391 +static int RegisterDriver(PSDFUNCTION pFunction)
7393 + memset(&pFunction->Driver, 0, sizeof(pFunction->Driver));
7394 + pFunction->Driver.name = pFunction->pName;
7395 + pFunction->Driver.probe = driver_probe;
7396 + pFunction->Driver.id_table = pnp_idtable;
7397 + pFunction->Driver.flags = PNP_DRIVER_RES_DO_NOT_CHANGE;
7399 + DBG_PRINT(SDDBG_TRACE,
7400 + ("SDIO BusDriver - SDIO_RegisterFunction, registering driver: %s\n",
7401 + pFunction->Driver.name));
7402 + return pnp_register_driver(&pFunction->Driver);
7405 +static int UnregisterDriver(PSDFUNCTION pFunction)
7407 + DBG_PRINT(SDDBG_TRACE,
7408 + ("+SDIO BusDriver - UnregisterDriver, driver: %s\n",
7409 + pFunction->Driver.name));
7410 + pnp_unregister_driver(&pFunction->Driver);
7411 + DBG_PRINT(SDDBG_TRACE,
7412 + ("-SDIO BusDriver - UnregisterDriver\n"));
7417 + * OS_InitializeDevice - initialize device that will be registered
7419 +SDIO_STATUS OS_InitializeDevice(PSDDEVICE pDevice, PSDFUNCTION pFunction)
7421 + struct pnp_id *pFdname;
7422 + memset(&pDevice->Device, 0, sizeof(pDevice->Device));
7423 + pDevice->Device.dev.driver_data = (PVOID)pFunction;
7424 +//?? pDevice->Device.data = (PVOID)pFunction;
7425 +//?? pDevice->Device.dev.driver = &pFunction->Driver.driver;
7426 +//?? pDevice->Device.driver = &pFunction->Driver;
7427 +//?? pDevice->Device.dev.release = release;
7428 + /* get a unique device number, must be done with locks held */
7429 + spin_lock(&InUseDevicesLock);
7430 + pDevice->Device.number = FirstClearBit(&InUseDevices);
7431 + SetBit(&InUseDevices, pDevice->Device.number);
7432 + spin_unlock(&InUseDevicesLock);
7433 + pDevice->Device.capabilities = PNP_REMOVABLE | PNP_DISABLE;
7434 + pDevice->Device.protocol = &sdio_protocol;
7435 + pDevice->Device.active = 1;
7437 + pnp_init_resource_table(&pDevice->Device.res);
7439 + pFdname = KernelAlloc(sizeof(struct pnp_id));
7441 + if (NULL == pFdname) {
7442 + return SDIO_STATUS_NO_RESOURCES;
7444 + /* set the id as slot number/function number */
7445 + snprintf(pFdname->id, sizeof(pFdname->id), "SD_%02X%02X",
7446 + pDevice->pHcd->SlotNumber, (UINT)SDDEVICE_GET_SDIO_FUNCNO(pDevice));
7447 + pFdname->next = NULL;
7448 + DBG_PRINT(SDDBG_TRACE, ("SDIO BusDriver - OS_InitializeDevice adding id: %s\n",
7450 + pnp_add_id(pFdname, &pDevice->Device);
7452 + /* deal with DMA settings */
7453 + if (pDevice->pHcd->pDmaDescription != NULL) {
7454 + pDevice->Device.dev.dma_mask = &pDevice->pHcd->pDmaDescription->Mask;
7455 + pDevice->Device.dev.coherent_dma_mask = pDevice->pHcd->pDmaDescription->Mask;
7458 + return SDIO_STATUS_SUCCESS;
7462 + * OS_AddDevice - must be pre-initialized with OS_InitializeDevice
7464 +SDIO_STATUS OS_AddDevice(PSDDEVICE pDevice, PSDFUNCTION pFunction)
7467 + DBG_PRINT(SDDBG_TRACE, ("SDIO BusDriver - OS_AddDevice adding function: %s\n",
7468 + pFunction->pName));
7469 + error = pnp_add_device(&pDevice->Device);
7471 + DBG_PRINT(SDDBG_ERROR, ("SDIO BusDriver - OS_AddDevice failed pnp_add_device: %d\n",
7474 + /* replace the buggy pnp's release */
7475 + pDevice->Device.dev.release = release;
7477 + return OSErrorToSDIOError(error);
7481 + * OS_RemoveDevice - unregister device with driver and bus
7483 +void OS_RemoveDevice(PSDDEVICE pDevice)
7485 + DBG_PRINT(SDDBG_TRACE, ("SDIO BusDriver - OS_RemoveDevice \n"));
7486 + pnp_remove_card_device(&pDevice->Device);
7487 + spin_lock(&InUseDevicesLock);
7488 + ClearBit(&InUseDevices, pDevice->Device.number);
7489 + spin_unlock(&InUseDevicesLock);
7491 + if (pDevice->Device.id != NULL) {
7492 + KernelFree(pDevice->Device.id);
7493 + pDevice->Device.id = NULL;
7497 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7498 + @function: Add OS device to bus driver.
7500 + @function name: SDIO_BusAddOSDevice
7501 + @category: HD_Reference
7503 + @output: pDma - descrip[tion of support DMA or NULL
7504 + @output: pDriver - assigned driver object
7505 + @output: pDevice - assigned device object
7507 + @return: SDIO_STATUS - SDIO_STATUS_SUCCESS when successful.
7509 + @notes: If the HCD does not register with the driver sub-system directly (like in the PCI case),
7510 + then it should register with the bus driver to obtain OS dependent device objects.
7511 + All input structures should be maintained throughout the life of the driver.
7513 + @example: getting device objects:
7514 + typedef struct _SDHCD_DRIVER {
7515 + OS_PNPDEVICE HcdDevice; / * the OS device for this HCD * /
7516 + OS_PNPDRIVER HcdDriver; / * the OS driver for this HCD * /
7517 + SDDMA_DESCRIPTION Dma; / * driver DMA description * /
7518 + }SDHCD_DRIVER, *PSDHCD_DRIVER;
7520 + typedef struct _SDHCD_DRIVER_CONTEXT {
7521 + PTEXT pDescription; / * human readable device decsription * /
7522 + SDLIST DeviceList; / * the list of current devices handled by this driver * /
7523 + OS_SEMAPHORE DeviceListSem; / * protection for the DeviceList * /
7524 + UINT DeviceCount; / * number of devices currently installed * /
7525 + SDHCD_DRIVER Driver; / * OS dependent driver specific info * /
7526 + }SDHCD_DRIVER_CONTEXT, *PSDHCD_DRIVER_CONTEXT;
7528 + static SDHCD_DRIVER_CONTEXT HcdContext = {
7529 + .pDescription = DESCRIPTION,
7531 + .Driver.HcdDevice.name = "sdio_xxx_hcd",
7532 + .Driver.HcdDriver.name = "sdio_xxx_hcd",
7535 + status = SDIO_BusAddOSDevice(NULL, &HcdContext.Driver, &HcdContext.Device);
7536 + if (SDIO_SUCCESS(status) {
7537 + return Probe(&HcdContext.Device);
7539 + return SDIOErrorToOSError(status);
7541 + @see also: SDIO_BusRemoveOSDevice
7543 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
7544 +SDIO_STATUS SDIO_BusAddOSDevice(PSDDMA_DESCRIPTION pDma, POS_PNPDRIVER pDriver, POS_PNPDEVICE pDevice)
7547 + struct pnp_id *pFdname;
7548 + struct pnp_device_id *pFdid;
7549 + static int slotNumber = 0; /* we just use an increasing count for the slots number */
7551 + if (pDma != NULL) {
7552 + pDevice->dev.dma_mask = &pDma->Mask;
7553 + pDevice->dev.coherent_dma_mask = pDma->Mask;
7555 + DBG_PRINT(SDDBG_ERROR,
7556 + ("SDIO BusDriver - SDIO_GetBusOSDevice, registering driver: %s DMAmask: 0x%x\n",
7557 + pDriver->name, (UINT)*pDevice->dev.dma_mask));
7558 + pFdid = KernelAlloc(sizeof(struct pnp_device_id)*2);
7559 + /* set the id as slot number/function number */
7560 + snprintf(pFdid[0].id, sizeof(pFdid[0].id), "SD_%02X08",
7562 + pFdid[0].driver_data = 0;
7563 + pFdid[1].id[0] = '\0';
7564 + pFdid[1].driver_data = 0;
7566 + pDriver->id_table = pFdid;
7567 + pDriver->flags = PNP_DRIVER_RES_DO_NOT_CHANGE;
7568 + err = pnp_register_driver(pDriver);
7570 + DBG_PRINT(SDDBG_ERROR,
7571 + ("SDIO BusDriver - SDIO_GetBusOSDevice, failed registering driver: %s, err: %d\n",
7572 + pDriver->name, err));
7573 + return OSErrorToSDIOError(err);
7576 + pDevice->protocol = &sdio_protocol;
7577 + pDevice->capabilities = PNP_REMOVABLE | PNP_DISABLE;
7578 + pDevice->active = 1;
7580 + pFdname = KernelAlloc(sizeof(struct pnp_id));
7581 + /* set the id as slot number/function number */
7582 + snprintf(pFdname->id, sizeof(pFdname->id), "SD_%02X08",
7583 + 0); //??pDevice->pHcd->SlotNumber);//?????fix this, slotnumber isn't vaialble yet
7584 + pFdname->next = NULL;
7585 + pnp_add_id(pFdname, pDevice);
7587 + /* get a unique device number */
7588 + spin_lock(&InUseDevicesLock);
7589 + pDevice->number = FirstClearBit(&InUseDevices);
7590 + SetBit(&InUseDevices, pDevice->number);
7591 + spin_unlock(&InUseDevicesLock);
7592 + pnp_init_resource_table(&pDevice->res);
7593 + err = pnp_add_device(pDevice);
7595 + DBG_PRINT(SDDBG_ERROR, ("SDIO BusDriver - SDIO_GetBusOSDevice failed pnp_device_add: %d\n",
7597 + pnp_unregister_driver(pDriver);
7599 + /* replace the buggy pnp's release */
7600 + pDevice->dev.release = release;
7601 + return OSErrorToSDIOError(err);
7604 +/**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7605 + @function: Return OS device from bus driver.
7607 + @function name: SDIO_BusRemoveOSDevice
7608 + @category: HD_Reference
7610 + @input: pDriver - setup PNP driver object
7611 + @input: pDevice - setup PNP device object
7616 + @example: returning device objects:
7617 + SDIO_BusRemoveOSDevice(&HcdContext.Driver, &HcdContext.Device);
7620 + @see also: SDIO_BusAddOSDevice
7622 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
7623 +void SDIO_BusRemoveOSDevice(POS_PNPDRIVER pDriver, POS_PNPDEVICE pDevice)
7625 + DBG_PRINT(SDDBG_ERROR,
7626 + ("SDIO BusDriver - SDIO_PutBusOSDevice, unregistering driver: %s\n",
7629 + pnp_remove_card_device(pDevice);
7630 + if (pDevice->id != NULL) {
7631 + KernelFree(pDevice->id);
7632 + pDevice->id = NULL;
7635 + spin_lock(&InUseDevicesLock);
7636 + ClearBit(&InUseDevices, pDevice->number);
7637 + spin_unlock(&InUseDevicesLock);
7639 + pnp_unregister_driver(pDriver);
7640 + if (pDriver->id_table != NULL) {
7641 + KernelFree((void *)pDriver->id_table);
7642 + pDriver->id_table = NULL;
7651 +static int __init sdio_busdriver_init(void) {
7652 + SDIO_STATUS status;
7654 + REL_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: loaded\n"));
7655 + if (!SDIO_SUCCESS((status = _SDIO_BusDriverInitialize()))) {
7656 + return SDIOErrorToOSError(status);
7658 + /* register the sdio bus */
7659 + error = pnp_register_protocol(&sdio_protocol);
7661 + REL_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: failed to register bus device, %d\n", error));
7662 + _SDIO_BusDriverCleanup();
7671 +static void __exit sdio_busdriver_cleanup(void) {
7672 + REL_PRINT(SDDBG_TRACE, ("SDIO unloaded\n"));
7673 + _SDIO_BusDriverCleanup();
7674 + pnp_unregister_protocol(&sdio_protocol);
7675 +DBG_PRINT(SDDBG_TRACE,
7676 + ("SDIO BusDriver - unloaded 1\n"));
7678 +EXPORT_SYMBOL(SDIO_BusAddOSDevice);
7679 +EXPORT_SYMBOL(SDIO_BusRemoveOSDevice);
7681 +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
7683 +static int RegisterDriver(PSDFUNCTION pFunction)
7688 +static int UnregisterDriver(PSDFUNCTION pFunction)
7690 + DBG_PRINT(SDDBG_TRACE,
7691 + ("+-SDIO BusDriver - UnregisterDriver, driver: \n"));
7696 + * OS_InitializeDevice - initialize device that will be registered
7698 +SDIO_STATUS OS_InitializeDevice(PSDDEVICE pDevice, PSDFUNCTION pFunction)
7700 + return SDIO_STATUS_SUCCESS;
7704 + * OS_AddDevice - must be pre-initialized with OS_InitializeDevice
7706 +SDIO_STATUS OS_AddDevice(PSDDEVICE pDevice, PSDFUNCTION pFunction)
7708 + DBG_PRINT(SDDBG_TRACE, ("SDIO BusDriver - OS_AddDevice adding function: %s\n",
7709 + pFunction->pName));
7710 + return SDIO_STATUS_SUCCESS;
7715 + * OS_RemoveDevice - unregister device with driver and bus
7717 +void OS_RemoveDevice(PSDDEVICE pDevice)
7719 + DBG_PRINT(SDDBG_TRACE, ("SDIO BusDriver - OS_RemoveDevice \n"));
7725 +static int __init sdio_busdriver_init(void) {
7726 + SDIO_STATUS status;
7727 + REL_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: loaded\n"));
7728 + if (!SDIO_SUCCESS((status = _SDIO_BusDriverInitialize()))) {
7729 + return SDIOErrorToOSError(status);
7737 +static void __exit sdio_busdriver_cleanup(void) {
7738 + REL_PRINT(SDDBG_TRACE, ("SDIO unloaded\n"));
7739 + _SDIO_BusDriverCleanup();
7741 +#else ////KERNEL_VERSION
7742 +#error "unsupported kernel version: "UTS_RELEASE
7743 +#endif //KERNEL_VERSION
7745 +MODULE_LICENSE("GPL and additional rights");
7746 +MODULE_DESCRIPTION(DESCRIPTION);
7747 +MODULE_AUTHOR(AUTHOR);
7749 +module_init(sdio_busdriver_init);
7750 +module_exit(sdio_busdriver_cleanup);
7751 +EXPORT_SYMBOL(SDIO_RegisterHostController);
7752 +EXPORT_SYMBOL(SDIO_UnregisterHostController);
7753 +EXPORT_SYMBOL(SDIO_HandleHcdEvent);
7754 +EXPORT_SYMBOL(SDIO_CheckResponse);
7755 +EXPORT_SYMBOL(SDIO_RegisterFunction);
7756 +EXPORT_SYMBOL(SDIO_UnregisterFunction);
7757 diff --git a/drivers/sdio/stack/busdriver/sdio_function.c b/drivers/sdio/stack/busdriver/sdio_function.c
7758 new file mode 100644
7759 index 0000000..78b8e17
7761 +++ b/drivers/sdio/stack/busdriver/sdio_function.c
7763 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7764 +@file: sdio_function.c
7766 +@abstract: OS independent bus driver support for function drivers
7768 +@notes: This file supports the interface between SDIO function drivers and the bus driver.
7770 +@notice: Copyright (c), 2004-2005 Atheros Communications, Inc.
7774 + * This program is free software; you can redistribute it and/or modify
7775 + * it under the terms of the GNU General Public License version 2 as
7776 + * published by the Free Software Foundation;
7778 + * Software distributed under the License is distributed on an "AS
7779 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
7780 + * implied. See the License for the specific language governing
7781 + * rights and limitations under the License.
7783 + * Portions of this code were developed with information supplied from the
7784 + * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply:
7786 + * The following conditions apply to the release of the SD simplified specification (�Simplified
7787 + * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete
7788 + * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided
7789 + * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified
7790 + * Specification may require a license from the SD Card Association or other third parties.
7792 + * The information contained in the Simplified Specification is presented only as a standard
7793 + * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any
7794 + * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for
7795 + * any damages, any infringements of patents or other right of the SD Card Association or any third
7796 + * parties, which may result from its use. No license is granted by implication, estoppel or otherwise
7797 + * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall
7798 + * be construed as an obligation by the SD Card Association to disclose or distribute any technical
7799 + * information, know-how or other confidential information to any third party.
7802 + * The initial developers of the original code are Seung Yi and Paul Lever
7804 + * sdio@atheros.com
7808 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
7809 +#define MODULE_NAME SDBUSDRIVER
7810 +#include <linux/sdio/ctsystem.h>
7811 +#include <linux/sdio/sdio_busdriver.h>
7812 +#include <linux/sdio/sdio_lib.h>
7813 +#include "_busdriver.h"
7815 +static SDIO_STATUS ProbeForDevice(PSDFUNCTION pFunction);
7817 +#ifdef CT_MAN_CODE_CHECK
7818 +static UINT16 ManCodeCheck = CT_MAN_CODE_CHECK;
7821 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7822 + @function: Register a function driver with the bus driver.
7824 + @function name: SDIO_RegisterFunction
7825 + @prototype: SDIO_STATUS SDIO_RegisterFunction(PSDFUNCTION pFunction)
7826 + @category: PD_Reference
7827 + @input: pFunction - the function definition structure.
7831 + @return: SDIO_STATUS - SDIO_STATUS_SUCCESS when succesful.
7833 + @notes: Each function driver must register with the bus driver once upon loading.
7834 + The calling function must be prepared to receive a Probe callback before
7835 + this function returns. This will occur when an perpheral device is already
7836 + pluugged in that is supported by this function.
7837 + The function driver should unregister itself when exiting.
7838 + The bus driver checks for possible function drivers to support a device
7839 + in reverse registration order.
7841 + @example: Registering a function driver:
7842 + //list of devices supported by this function driver
7843 + static SD_PNP_INFO Ids[] = {
7844 + {.SDIO_ManufacturerID = 0xaa55,
7845 + .SDIO_ManufacturerCode = 0x5555,
7846 + .SDIO_FunctionNo = 1},
7847 + {} //list is null termintaed
7849 + static GENERIC_FUNCTION_CONTEXT FunctionContext = {
7850 + .Function.pName = "sdio_generic", //name of the device
7851 + .Function.Version = CT_SDIO_STACK_VERSION_CODE, // set stack version
7852 + .Function.MaxDevices = 1, //maximum number of devices supported by this driver
7853 + .Function.NumDevices = 0, //current number of devices, always zero to start
7854 + .Function.pIds = Ids, //the list of devices supported by this device
7855 + .Function.pProbe = Probe, //pointer to the function drivers Probe function
7856 + // that will be called when a possibly supported device
7858 + .Function.pRemove = Remove, //pointer to the function drivers Remove function
7859 + / that will be called when a device is removed.
7860 + .Function.pContext = &FunctionContext, //data value that will be passed into Probe and
7861 + // Remove callbacks.
7863 + SDIO_STATUS status;
7864 + status = SDIO_RegisterFunction(&FunctionContext.Function)
7865 + if (!SDIO_SUCCESS(status)) {
7866 + ...failed to register
7869 + @see also: SDIO_UnregisterFunction
7871 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
7872 +SDIO_STATUS _SDIO_RegisterFunction(PSDFUNCTION pFunction)
7874 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
7876 +#ifdef CT_MAN_CODE_CHECK
7877 + DBG_PRINT(SDDBG_TRACE,
7878 + ("SDIO Bus Driver: _SDIO_RegisterFunction: WARNING, this version is locked to Memory cards and SDIO cards with JEDEC IDs of: 0x%X\n",
7881 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: _SDIO_RegisterFunction\n"));
7884 + DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: Function Driver Stack Version: %d.%d \n",
7885 + GET_SDIO_STACK_VERSION_MAJOR(pFunction),GET_SDIO_STACK_VERSION_MINOR(pFunction)));
7887 + if (!CHECK_FUNCTION_DRIVER_VERSION(pFunction)) {
7888 + DBG_PRINT(SDDBG_ERROR,
7889 + ("SDIO Bus Driver: Function Major Version Mismatch (hcd = %d, bus driver = %d)\n",
7890 + GET_SDIO_STACK_VERSION_MAJOR(pFunction), CT_SDIO_STACK_VERSION_MAJOR(g_Version)));
7891 + return SDIO_STATUS_INVALID_PARAMETER;
7895 + /* sanity check the driver */
7896 + if ((pFunction == NULL) ||
7897 + (pFunction->pProbe == NULL) ||
7898 + (pFunction->pIds == NULL)) {
7899 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_RegisterFunction, invalid registration data\n"));
7900 + return SDIO_STATUS_INVALID_PARAMETER;
7902 + /* protect the function list and add the function */
7903 + if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->FunctionListSem)))) {
7904 + goto cleanup; /* wait interrupted */
7906 + SignalInitialize(&pFunction->CleanupReqSig);
7907 + SDLIST_INIT(&pFunction->DeviceList);
7908 + SDListAdd(&pBusContext->FunctionList, &pFunction->SDList);
7909 + if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->FunctionListSem)))) {
7910 + goto cleanup; /* wait interrupted */
7913 + /* see if we have devices for this new function driver */
7914 + ProbeForDevice(pFunction);
7918 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_RegisterFunction, error exit 0x%X\n", status));
7922 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7923 + @function: Unregister a function driver with the bus driver.
7925 + @function name: SDIO_UnregisterFunction
7926 + @prototype: SDIO_STATUS SDIO_UnregisterFunction(PSDFUNCTION pFunction)
7927 + @category: PD_Reference
7929 + @input: pFunction - the function definition structure.
7933 + @return: SDIO_STATUS - SDIO_STATUS_SUCCESS when succesful.
7935 + @notes: Each function driver must unregister from the bus driver when the function driver
7937 + A function driver must disconnect from any interrupts before calling this function.
7939 + @example: Unregistering a function driver:
7940 + SDIO_UnregisterFunction(&FunctionContext.Function);
7942 + @see also: SDIO_RegisterFunction
7944 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
7945 +SDIO_STATUS _SDIO_UnregisterFunction(PSDFUNCTION pFunction)
7947 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
7948 + PSDDEVICE pDevice;
7950 + DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: _SDIO_UnregisterFunction\n"));
7952 + /* protect the function list and synchronize with Probe() and Remove()*/
7953 + if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->FunctionListSem)))) {
7954 + goto cleanup; /* wait interrupted */
7956 + /* remove this function from the function list */
7957 + SDListRemove(&pFunction->SDList);
7958 + /* now remove this function as the handler for any of its devices */
7959 + SDITERATE_OVER_LIST_ALLOW_REMOVE(&pFunction->DeviceList, pDevice, SDDEVICE,FuncListLink) {
7960 + if (pDevice->pFunction == pFunction) {
7961 + /* notify removal */
7962 + NotifyDeviceRemove(pDevice);
7966 + SignalDelete(&pFunction->CleanupReqSig);
7968 + if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->FunctionListSem)))) {
7969 + goto cleanup; /* wait interrupted */
7971 + DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: _SDIO_UnregisterFunction\n"));
7975 + DBG_PRINT(SDDBG_ERROR, ("-SDIO Bus Driver: _SDIO_UnregisterFunction, error exit 0x%X\n", status));
7979 +/* documentation headers only for Probe and Remove */
7980 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7981 + @function: This function is called by the Busdriver when a device is inserted that can be supported by this function driver.
7983 + @function name: Probe
7984 + @prototype: BOOL (*pProbe)(struct _SDFUNCTION *pFunction, struct _SDDEVICE *pDevice)
7985 + @category: PD_Reference
7987 + @input: pFunction - the function definition structure that was passed to Busdriver
7988 + via the SDIO_RegisterFunction.
7989 + @input: pDevice - the description of the newly inserted device.
7993 + @return: TRUE - this function driver will suport this device
7994 + FALSE - this function driver will not support this device
7996 + @notes: The Busdriver calls the Probe function of a function driver to inform it that device is
7997 + available for the function driver to control. The function driver should initialize the
7998 + device and be pepared to acceopt any interrupts from the device before returning.
8000 + @example: Example of typical Probe function callback:
8001 + static BOOL Probe(PSDFUNCTION pFunction, PSDDEVICE pDevice) {
8002 + ...get the our context info passed into the SDIO_RegisterFunction
8003 + PSDXXX_DRIVER_CONTEXT pFunctionContext =
8004 + (PSDXXX_DRIVER_CONTEXT)pFunction->pContext;
8005 + SDIO_STATUS status;
8006 + //test the identification of this device and ensure we want to support it
8007 + // we can test based on class, or use more specific tests on SDIO_ManufacturerID, etc.
8008 + if (pDevice->pId[0].SDIO_FunctionClass == XXX) {
8009 + DBG_PRINT(SDDBG_TRACE, ("SDIO XXX Function: Probe - card matched (0x%X/0x%X/0x%X)\n",
8010 + pDevice->pId[0].SDIO_ManufacturerID,
8011 + pDevice->pId[0].SDIO_ManufacturerCode,
8012 + pDevice->pId[0].SDIO_FunctionNo));
8015 + @see also: SDIO_RegisterFunction
8018 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8020 +BOOL FilterPnpInfo(PSDDEVICE pDevice)
8022 +#ifdef CT_MAN_CODE_CHECK
8023 + if (pDevice->pId[0].CardFlags & CARD_SDIO) {
8024 + if (pDevice->pId[0].SDIO_ManufacturerCode != ManCodeCheck) {
8025 + DBG_PRINT(SDDBG_ERROR,
8026 + ("SDIO Card with JEDEC ID:0x%X , not Allowed! Driver check halted. "
8027 + "Please Contact sales@codetelligence.com.\n",
8028 + pDevice->pId[0].SDIO_ManufacturerCode));
8038 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8039 + @function: This function is called by the Busdriver when a device controlled by this function
8040 + function driver is removed.
8042 + @function name: Remove
8043 + @prototype: void (*pRemove)(struct _SDFUNCTION *pFunction, struct _SDDEVICE *pDevice)
8044 + @category: PD_Reference
8046 + @input: pFunction - the function definition structure that was passed to Busdriver
8047 + via the SDIO_RegisterFunction.
8048 + @input: pDevice - the description of the device being removed.
8054 + @notes: The Busdriver calls the Remove function of a function driver to inform it that device it
8055 + was supporting has been removed. The device has already been removed, so no further I/O
8056 + to the device can be performed.
8058 + @example: Example of typical Remove function callback:
8059 + void Remove(PSDFUNCTION pFunction, PSDDEVICE pDevice) {
8060 + // get the our context info passed into the SDIO_RegisterFunction
8061 + PSDXXX_DRIVER_CONTEXT pFunctionContext =
8062 + (PSDXXX_DRIVER_CONTEXT)pFunction->pContext;
8063 + ...free any acquired resources.
8065 + @see also: SDIO_RegisterFunction
8068 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8071 + * ProbeForFunction - look for a function driver to handle this card
8074 +SDIO_STATUS ProbeForFunction(PSDDEVICE pDevice, PSDHCD pHcd) {
8075 + SDIO_STATUS status;
8077 + PSDFUNCTION pFunction;
8079 + DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: ProbeForFunction\n"));
8080 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: ProbeForFunction - Dump of Device PNP Data: \n"));
8081 + DBG_PRINT(SDDBG_TRACE, (" Card Flags 0x%X \n", pDevice->pId[0].CardFlags));
8082 + if (pDevice->pId[0].CardFlags & CARD_SDIO) {
8083 + DBG_PRINT(SDDBG_TRACE, (" SDIO MANF: 0x%X \n", pDevice->pId[0].SDIO_ManufacturerID));
8084 + DBG_PRINT(SDDBG_TRACE, (" SDIO MANFCODE: 0x%X \n", pDevice->pId[0].SDIO_ManufacturerCode));
8085 + DBG_PRINT(SDDBG_TRACE, (" SDIO FuncNo: %d \n", pDevice->pId[0].SDIO_FunctionNo));
8086 + DBG_PRINT(SDDBG_TRACE, (" SDIO FuncClass: %d \n", pDevice->pId[0].SDIO_FunctionClass));
8088 + if (pDevice->pId[0].CardFlags & (CARD_MMC | CARD_SD)) {
8089 + DBG_PRINT(SDDBG_TRACE, (" SDMMC MANFID: 0x%X \n",pDevice->pId[0].SDMMC_ManfacturerID));
8090 + DBG_PRINT(SDDBG_TRACE, (" SDMMC OEMID: 0x%X \n",pDevice->pId[0].SDMMC_OEMApplicationID));
8093 + if (!FilterPnpInfo(pDevice)) {
8094 + status = SDIO_STATUS_SUCCESS;
8098 + /* protect the function list */
8099 + if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->FunctionListSem)))) {
8100 + goto cleanup; /* wait interrupted */
8103 + /* protect against ProbeForDevice */
8104 + if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->DeviceListSem)))) {
8105 + /* release the function list semaphore we just took */
8106 + SemaphorePost(&pBusContext->FunctionListSem);
8110 + if (pDevice->pFunction != NULL) {
8111 + /* device already has a function driver handling it */
8112 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: ProbeForFunction, device already has function\n"));
8113 + /* release function list */
8114 + SemaphorePost(&pBusContext->DeviceListSem);
8115 + /* release function list */
8116 + SemaphorePost(&pBusContext->FunctionListSem);
8117 + /* just return success */
8118 + status = SDIO_STATUS_SUCCESS;
8122 + /* release device list */
8123 + SemaphorePost(&pBusContext->DeviceListSem);
8125 + /* walk functions looking for one that can handle this device */
8126 + SDITERATE_OVER_LIST(&pBusContext->FunctionList, pList) {
8127 + pFunction = CONTAINING_STRUCT(pList, SDFUNCTION, SDList);
8128 + if (pFunction->NumDevices >= pFunction->MaxDevices) {
8129 + /* function can't support any more devices */
8132 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: ProbeForFunction - checking: %s \n",
8133 + pFunction->pName));
8135 + /* see if this function handles this device */
8136 + if (IsPotentialIdMatch(pDevice->pId, pFunction->pIds)) {
8137 + if (!FilterPnpInfo(pDevice)) {
8140 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: ProbeForFunction -Got Match, probing: %s \n",
8141 + pFunction->pName));
8142 + /* we need to setup with the OS bus driver before the probe, so probe can
8143 + do OS operations. */
8144 + OS_InitializeDevice(pDevice, pFunction);
8145 + if (!SDIO_SUCCESS(OS_AddDevice(pDevice, pFunction))) {
8148 + /* close enough match, ask the function driver if it supports us */
8149 + if (pFunction->pProbe(pFunction, pDevice)) {
8150 + /* she accepted the device, add to list */
8151 + pDevice->pFunction = pFunction;
8152 + SDListAdd(&pFunction->DeviceList, &pDevice->FuncListLink);
8153 + pFunction->NumDevices++;
8156 + DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: %s did not claim the device \n",
8157 + pFunction->pName));
8158 + /* didn't take this device */
8159 + OS_RemoveDevice(pDevice);
8164 + if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->FunctionListSem)))) {
8165 + goto cleanup; /* wait interrupted */
8167 + DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: ProbeForFunction\n"));
8170 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: ProbeForFunction, error exit 0x%X\n", status));
8175 + * ProbeForDevice - look for a device that this function driver supports
8178 +static SDIO_STATUS ProbeForDevice(PSDFUNCTION pFunction) {
8179 + SDIO_STATUS status;
8181 + PSDDEVICE pDevice;
8183 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: ProbeForDevice\n"));
8184 + if (pFunction->NumDevices >= pFunction->MaxDevices) {
8185 + /* function can't support any more devices */
8186 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: ProbeForDevice, too many devices in function\n"));
8187 + return SDIO_STATUS_SUCCESS;
8190 + /* protect the driver list */
8191 + if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->DeviceListSem)))) {
8192 + goto cleanup; /* wait interrupted */
8194 + /* walk device list */
8195 + SDITERATE_OVER_LIST(&pBusContext->DeviceList, pList) {
8196 + pDevice = CONTAINING_STRUCT(pList, SDDEVICE, SDList);
8197 + if (pDevice->pFunction != NULL) {
8198 + /* device already has a function driver handling it */
8199 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: ProbeForDevice, device already has function\n"));
8202 + /* see if this function handles this device */
8203 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: ProbeForDevice, matching ID:%d %d class:%d\n",
8204 + pDevice->pId[0].SDIO_ManufacturerID,
8205 + pDevice->pId[0].SDIO_FunctionNo,
8206 + pDevice->pId[0].SDIO_FunctionClass));
8207 + if (IsPotentialIdMatch(pDevice->pId, pFunction->pIds)) {
8208 + if (!FilterPnpInfo(pDevice)) {
8211 + /* we need to setup with the OS bus driver before the probe, so probe can
8212 + do OS operations. */
8213 + OS_InitializeDevice(pDevice, pFunction);
8214 + if (!SDIO_SUCCESS(OS_AddDevice(pDevice, pFunction))) {
8217 + /* close enough match, ask the function driver if it supports us */
8218 + if (pFunction->pProbe(pFunction, pDevice)) {
8219 + /* she accepted the device, add to list */
8220 + pDevice->pFunction = pFunction;
8221 + SDListAdd(&pFunction->DeviceList, &pDevice->FuncListLink);
8222 + pFunction->NumDevices++;
8225 + DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: %s did not claim the device \n",
8226 + pFunction->pName));
8227 + /* didn't take this device */
8228 + OS_RemoveDevice(pDevice);
8232 + if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->DeviceListSem)))) {
8233 + goto cleanup; /* wait interrupted */
8238 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: ProbeForDevice, error exit 0x%X\n", status));
8243 +static void DumpPnpEntry(PSD_PNP_INFO pInfo)
8245 + DBG_PRINT(SDDBG_TRACE, ("Function PnpInfo Dump: \n"));
8246 + DBG_PRINT(SDDBG_TRACE, (" Card Flags 0x%X \n", pInfo->CardFlags));
8247 + DBG_PRINT(SDDBG_TRACE, (" SDIO MANF: 0x%X \n", pInfo->SDIO_ManufacturerID));
8248 + DBG_PRINT(SDDBG_TRACE, (" SDIO MANFCODE: 0x%X \n", pInfo->SDIO_ManufacturerCode));
8249 + DBG_PRINT(SDDBG_TRACE, (" SDIO FuncNo: %d \n", pInfo->SDIO_FunctionNo));
8250 + DBG_PRINT(SDDBG_TRACE, (" SDIO FuncClass: %d \n", pInfo->SDIO_FunctionClass));
8251 + DBG_PRINT(SDDBG_TRACE, (" SDMMC MANFID: 0x%X \n", pInfo->SDMMC_ManfacturerID));
8252 + DBG_PRINT(SDDBG_TRACE, (" SDMMC OEMID: 0x%X \n", pInfo->SDMMC_OEMApplicationID));
8256 + * IsPotentialIdMatch - test for potential device match
8259 +BOOL IsPotentialIdMatch(PSD_PNP_INFO pIdsDev, PSD_PNP_INFO pIdsFuncList) {
8260 + PSD_PNP_INFO pTFn;
8261 + BOOL match = FALSE;
8263 + for (pTFn = pIdsFuncList;!IS_LAST_SDPNPINFO_ENTRY(pTFn);pTFn++) {
8264 + //DumpPnpEntry(pTFn);
8265 + /* check specific SDIO Card manufacturer ID, Code and Function number */
8266 + if ((pIdsDev->SDIO_ManufacturerID != 0) &&
8267 + (pTFn->SDIO_ManufacturerID != 0) &&
8268 + (pIdsDev->SDIO_ManufacturerID == pTFn->SDIO_ManufacturerID) &&
8269 + (pIdsDev->SDIO_ManufacturerCode == pTFn->SDIO_ManufacturerCode) &&
8270 + ((pIdsDev->SDIO_FunctionNo == pTFn->SDIO_FunctionNo) ||
8271 + (pTFn->SDIO_FunctionNo == 0)) ) {
8275 + /* check generic function class */
8276 + if ((pIdsDev->SDIO_FunctionClass != 0) &&
8277 + (pTFn->SDIO_FunctionClass != 0) &&
8278 + (pIdsDev->SDIO_FunctionClass == pTFn->SDIO_FunctionClass)) {
8282 + /* check specific SDMMC MANFID and APPLICATION ID, NOTE SANDISK
8283 + * uses a MANFID of zero! */
8284 + if ((pTFn->SDMMC_OEMApplicationID != 0) &&
8285 + (pIdsDev->SDMMC_ManfacturerID == pTFn->SDMMC_ManfacturerID) &&
8286 + (pIdsDev->SDMMC_OEMApplicationID == pTFn->SDMMC_OEMApplicationID)) {
8291 + /* check generic SD Card */
8292 + if ((pIdsDev->CardFlags & CARD_SD) &&
8293 + (pTFn->CardFlags & CARD_SD)){
8298 + /* check generic MMC Card */
8299 + if ((pIdsDev->CardFlags & CARD_MMC) &&
8300 + (pTFn->CardFlags & CARD_MMC)){
8305 + /* check raw Card */
8306 + if ((pIdsDev->CardFlags & CARD_RAW) &&
8307 + (pTFn->CardFlags & CARD_RAW)){
8317 + * NotifyDeviceRemove - tell function driver on this device that the device is being removed
8320 +SDIO_STATUS NotifyDeviceRemove(PSDDEVICE pDevice) {
8321 + SDIO_STATUS status;
8322 + SDREQUESTQUEUE cancelQueue;
8324 + CT_DECLARE_IRQ_SYNC_CONTEXT();
8326 + InitializeRequestQueue(&cancelQueue);
8328 + if ((pDevice->pFunction != NULL) &&
8329 + (pDevice->pFunction->pRemove != NULL)){
8330 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: removing device 0x%X\n", (INT)pDevice));
8331 + /* fail any outstanding requests for this device */
8332 + /* acquire lock for request queue */
8333 + status = _AcquireHcdLock(pDevice->pHcd);
8334 + if (!SDIO_SUCCESS(status)) {
8337 + /* mark the function to block any more requests comming down */
8338 + pDevice->pFunction->Flags |= SDFUNCTION_FLAG_REMOVING;
8339 + /* walk through HCD queue and remove this function's requests */
8340 + SDITERATE_OVER_LIST_ALLOW_REMOVE(&pDevice->pHcd->RequestQueue.Queue, pReq, SDREQUEST, SDList) {
8341 + if (pReq->pFunction == pDevice->pFunction) {
8342 + /* cancel this request, as this device or function is being removed */
8343 + /* note that these request are getting completed out of order */
8344 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - NotifyDeviceRemove: canceling req 0x%X\n", (UINT)pReq));
8345 + pReq->Status = SDIO_STATUS_CANCELED;
8346 + /* remove it from the HCD queue */
8347 + SDListRemove(&pReq->SDList);
8348 + /* add it to the cancel queue */
8349 + QueueRequest(&cancelQueue, pReq);
8353 + status = _ReleaseHcdLock(pDevice->pHcd);
8355 + /* now empty the cancel queue if anything is in there */
8357 + pReq = DequeueRequest(&cancelQueue);
8358 + if (NULL == pReq) {
8361 + /* complete the request */
8362 + DoRequestCompletion(pReq, pDevice->pHcd);
8364 + /* re-acquire the lock to deal with the current request */
8365 + status = _AcquireHcdLock(pDevice->pHcd);
8366 + if (!SDIO_SUCCESS(status)) {
8369 + /* now deal with the current request */
8370 + pReq = GET_CURRENT_REQUEST(pDevice->pHcd);
8371 + if ((pReq !=NULL) && (pReq->pFunction == pDevice->pFunction) && (pReq->pFunction != NULL)) {
8372 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - NotifyDeviceRemove: Outstanding Req 0x%X on HCD: 0x%X.. waiting...\n",
8373 + (UINT)pReq, (UINT)pDevice->pHcd));
8374 + /* the outstanding request on this device is for the function being removed */
8375 + pReq->Flags |= SDREQ_FLAGS_CANCELED;
8376 + /* wait for this request to get completed normally */
8377 + status = _ReleaseHcdLock(pDevice->pHcd);
8378 + SignalWait(&pDevice->pFunction->CleanupReqSig);
8379 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - NotifyDeviceRemove: Outstanding HCD Req 0x%X completed \n", (UINT)pReq));
8381 + /* release lock */
8382 + status = _ReleaseHcdLock(pDevice->pHcd);
8385 + /* synchronize with ISR SYNC Handlers */
8386 + status = SemaphorePendInterruptable(&pBusContext->DeviceListSem);
8387 + if (!SDIO_SUCCESS(status)) {
8390 + /* call this devices Remove function */
8391 + pDevice->pFunction->pRemove(pDevice->pFunction,pDevice);
8392 + pDevice->pFunction->NumDevices--;
8393 + /* make sure the sync handler is NULLed out */
8394 + pDevice->pIrqFunction = NULL;
8395 + SemaphorePost(&pBusContext->DeviceListSem);
8397 + OS_RemoveDevice(pDevice);
8398 + /* detach this device from the function list it belongs to */
8399 + SDListRemove(&pDevice->FuncListLink);
8400 + pDevice->pFunction->Flags &= ~SDFUNCTION_FLAG_REMOVING;
8401 + pDevice->pFunction = NULL;
8403 + return SDIO_STATUS_SUCCESS;
8408 + * RemoveHcdFunctions - remove all functions attached to an HCD
8411 +SDIO_STATUS RemoveHcdFunctions(PSDHCD pHcd) {
8412 + SDIO_STATUS status;
8414 + PSDFUNCTION pFunction;
8415 + PSDDEVICE pDevice;
8416 + DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: RemoveHcdFunctions\n"));
8418 + /* walk through the functions and remove the ones associated with this HCD */
8419 + /* protect the driver list */
8420 + if (!SDIO_SUCCESS((status = SemaphorePend(&pBusContext->FunctionListSem)))) {
8421 + goto cleanup; /* wait interrupted */
8423 + /* mark that card is being removed */
8424 + pHcd->CardProperties.CardState |= CARD_STATE_REMOVED;
8425 + SDITERATE_OVER_LIST(&pBusContext->FunctionList, pList) {
8426 + pFunction = CONTAINING_STRUCT(pList, SDFUNCTION, SDList);
8427 + DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: scanning function 0x%X, %s\n", (INT)pFunction,
8428 + (pFunction == NULL)?"NULL":pFunction->pName));
8430 + /* walk the devices on this function and look for a match */
8431 + SDITERATE_OVER_LIST_ALLOW_REMOVE(&pFunction->DeviceList, pDevice, SDDEVICE,FuncListLink) {
8432 + if (pDevice->pHcd == pHcd) {
8433 + /* match, remove it */
8434 + NotifyDeviceRemove(pDevice);
8438 + if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->FunctionListSem)))) {
8439 + goto cleanup; /* wait interrupted */
8441 + DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: RemoveHcdFunctions\n"));
8442 + return SDIO_STATUS_SUCCESS;
8445 + DBG_PRINT(SDDBG_ERROR, ("-SDIO Bus Driver: RemoveHcdFunctions, error exit 0x%X\n", status));
8450 + * RemoveAllFunctions - remove all functions attached
8453 +SDIO_STATUS RemoveAllFunctions()
8455 + SDIO_STATUS status;
8459 + /* walk through the HCDs */
8460 + /* protect the driver list */
8461 + if (!SDIO_SUCCESS((status = SemaphorePend(&pBusContext->HcdListSem)))) {
8462 + goto cleanup; /* wait interrupted */
8464 + SDITERATE_OVER_LIST(&pBusContext->HcdList, pList) {
8465 + pHcd = CONTAINING_STRUCT(pList, SDHCD, SDList);
8466 + /* remove the functions */
8467 + RemoveHcdFunctions(pHcd);
8469 + if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->HcdListSem)))) {
8470 + goto cleanup; /* wait interrupted */
8472 + return SDIO_STATUS_SUCCESS;
8474 + DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: RemoveAllFunctions, error exit 0x%X\n", status));
8478 diff --git a/drivers/sdio/stack/lib/Makefile b/drivers/sdio/stack/lib/Makefile
8479 new file mode 100644
8480 index 0000000..44fa038
8482 +++ b/drivers/sdio/stack/lib/Makefile
8484 +obj-$(CONFIG_SDIO) += sdio_lib.o
8485 +sdio_lib-objs := sdio_lib_c.o sdio_lib_os.o
8486 diff --git a/drivers/sdio/stack/lib/_sdio_lib.h b/drivers/sdio/stack/lib/_sdio_lib.h
8487 new file mode 100644
8488 index 0000000..28762b0
8490 +++ b/drivers/sdio/stack/lib/_sdio_lib.h
8492 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8495 +@abstract: SDIO Lib internal include
8499 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
8503 + * This program is free software; you can redistribute it and/or modify
8504 + * it under the terms of the GNU General Public License version 2 as
8505 + * published by the Free Software Foundation;
8507 + * Software distributed under the License is distributed on an "AS
8508 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
8509 + * implied. See the License for the specific language governing
8510 + * rights and limitations under the License.
8512 + * Portions of this code were developed with information supplied from the
8513 + * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply:
8515 + * The following conditions apply to the release of the SD simplified specification (�Simplified
8516 + * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete
8517 + * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided
8518 + * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified
8519 + * Specification may require a license from the SD Card Association or other third parties.
8521 + * The information contained in the Simplified Specification is presented only as a standard
8522 + * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any
8523 + * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for
8524 + * any damages, any infringements of patents or other right of the SD Card Association or any third
8525 + * parties, which may result from its use. No license is granted by implication, estoppel or otherwise
8526 + * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall
8527 + * be construed as an obligation by the SD Card Association to disclose or distribute any technical
8528 + * information, know-how or other confidential information to any third party.
8531 + * The initial developers of the original code are Seung Yi and Paul Lever
8533 + * sdio@atheros.com
8537 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8538 +#ifndef ___SDIO_LIB_H___
8539 +#define ___SDIO_LIB_H___
8541 +#endif /* ___SDIO_LIB_H___*/
8542 diff --git a/drivers/sdio/stack/lib/sdio_lib_c.c b/drivers/sdio/stack/lib/sdio_lib_c.c
8543 new file mode 100644
8544 index 0000000..4bc5a83
8546 +++ b/drivers/sdio/stack/lib/sdio_lib_c.c
8548 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8549 +@file: sdio_lib_c.c
8551 +@abstract: OS independent SDIO library functions
8552 +@category abstract: Support_Reference Support Functions.
8554 +@notes: Support functions for device I/O
8556 +@notice: Copyright (c), 2004-2005 Atheros Communications, Inc.
8560 + * This program is free software; you can redistribute it and/or modify
8561 + * it under the terms of the GNU General Public License version 2 as
8562 + * published by the Free Software Foundation;
8564 + * Software distributed under the License is distributed on an "AS
8565 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
8566 + * implied. See the License for the specific language governing
8567 + * rights and limitations under the License.
8569 + * Portions of this code were developed with information supplied from the
8570 + * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply:
8572 + * The following conditions apply to the release of the SD simplified specification (�Simplified
8573 + * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete
8574 + * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided
8575 + * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified
8576 + * Specification may require a license from the SD Card Association or other third parties.
8578 + * The information contained in the Simplified Specification is presented only as a standard
8579 + * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any
8580 + * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for
8581 + * any damages, any infringements of patents or other right of the SD Card Association or any third
8582 + * parties, which may result from its use. No license is granted by implication, estoppel or otherwise
8583 + * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall
8584 + * be construed as an obligation by the SD Card Association to disclose or distribute any technical
8585 + * information, know-how or other confidential information to any third party.
8588 + * The initial developers of the original code are Seung Yi and Paul Lever
8590 + * sdio@atheros.com
8594 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8595 +#define MODULE_NAME SDLIB_
8597 +#include <linux/sdio/ctsystem.h>
8598 +#include <linux/sdio/sdio_busdriver.h>
8599 +#include <linux/sdio/_sdio_defs.h>
8600 +#include <linux/sdio/sdio_lib.h>
8601 +#include "_sdio_lib.h"
8603 +#define _Cmd52WriteByteCommon(pDev, Address, pValue) \
8604 + _SDLIB_IssueCMD52((pDev),0,(Address),(pValue),1,TRUE)
8605 +#define _Cmd52ReadByteCommon(pDev, Address, pValue) \
8606 + _SDLIB_IssueCMD52((pDev),0,(Address),pValue,1,FALSE)
8607 +#define _Cmd52ReadMultipleCommon(pDev, Address, pBuf,length) \
8608 + _SDLIB_IssueCMD52((pDev),0,(Address),(pBuf),(length),FALSE)
8610 +/* inline version */
8611 +static INLINE void _iSDLIB_SetupCMD52Request(UINT8 FuncNo,
8615 + PSDREQUEST pRequest) {
8617 + SDIO_SET_CMD52_ARG(pRequest->Argument,CMD52_WRITE,
8619 + CMD52_NORMAL_WRITE,Address,WriteData);
8621 + SDIO_SET_CMD52_ARG(pRequest->Argument,CMD52_READ,FuncNo,0,Address,0x00);
8624 + pRequest->Flags = SDREQ_FLAGS_RESP_SDIO_R5;
8625 + pRequest->Command = CMD52;
8628 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8629 + @function: Setup cmd52 requests
8631 + @function name: SDLIB_SetupCMD52Request
8632 + @prototype: void SDLIB_SetupCMD52Request(UINT8 FuncNo,
8636 + PSDREQUEST pRequest)
8637 + @category: PD_Reference
8639 + @input: FunctionNo - function number.
8640 + @input: Address - I/O address, 17-bit register address.
8641 + @input: Write - TRUE if a write operation, FALSE for reads.
8642 + @input: WriteData - write data, byte to write if write operation.
8644 + @output: pRequest - request is updated with cmd52 parameters
8648 + @notes: This function does not perform any I/O. For register reads, the completion
8649 + routine can use the SD_R5_GET_READ_DATA() macro to extract the register value.
8650 + The routine should also extract the response flags using the SD_R5_GET_RESP_FLAGS()
8651 + macro and check the flags with the SD_R5_ERRORS mask.
8653 + @example: Getting the register value from the completion routine:
8654 + flags = SD_R5_GET_RESP_FLAGS(pRequest->Response);
8655 + if (flags & SD_R5_ERRORS) {
8658 + registerValue = SD_R5_GET_READ_DATA(pRequest->Response);
8661 + @see also: SDLIB_IssueCMD52
8662 + @see also: SDDEVICE_CALL_REQUEST_FUNC
8664 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8665 +void _SDLIB_SetupCMD52Request(UINT8 FuncNo,
8669 + PSDREQUEST pRequest)
8671 + _iSDLIB_SetupCMD52Request(FuncNo,Address,Write,WriteData,pRequest);
8674 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8675 + @function: Issue a CMD52 to read or write a register
8677 + @function name: SDLIB_IssueCMD52
8678 + @prototype: SDIO_STATUS SDLIB_IssueCMD52(PSDDEVICE pDevice,
8684 + @category: PD_Reference
8685 + @input: pDevice - the device that is the target of the command.
8686 + @input: FunctionNo - function number of the target.
8687 + @input: Address - 17-bit register address.
8688 + @input: ByteCount - number of bytes to read or write,
8689 + @input: Write - TRUE if a write operation, FALSE for reads.
8690 + @input: pData - data buffer for writes.
8692 + @output: pData - data buffer for writes.
8694 + @return: SDIO Status
8696 + @notes: This function will allocate a request and issue multiple byte reads or writes
8697 + to satisfy the ByteCount requested. This function is fully synchronous and will block
8700 + @see also: SDLIB_SetupCMD52Request
8702 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8703 +SDIO_STATUS _SDLIB_IssueCMD52(PSDDEVICE pDevice,
8710 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
8712 + PSDREQUEST pReq = NULL;
8714 + pReq = SDDeviceAllocRequest(pDevice);
8716 + if (NULL == pReq) {
8717 + return SDIO_STATUS_NO_RESOURCES;
8720 + while (ByteCount) {
8721 + _iSDLIB_SetupCMD52Request(FuncNo,Address,Write,*pData,pReq);
8722 + status = SDDEVICE_CALL_REQUEST_FUNC(pDevice,pReq);
8723 + if (!SDIO_SUCCESS(status)) {
8727 + status = ConvertCMD52ResponseToSDIOStatus(SD_R5_GET_RESP_FLAGS(pReq->Response));
8728 + if (!SDIO_SUCCESS(status)) {
8729 + DBG_PRINT(SDDBG_TRACE, ("SDIO Library: CMD52 resp error: 0x%X \n",
8730 + SD_R5_GET_RESP_FLAGS(pReq->Response)));
8734 + /* store the byte */
8735 + *pData = SD_R5_GET_READ_DATA(pReq->Response);
8742 + SDDeviceFreeRequest(pDevice,pReq);
8748 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8749 + @function: Find a device's tuple.
8751 + @function name: SDLIB_FindTuple
8752 + @prototype: SDIO_STATUS SDLIB_FindTuple(PSDDEVICE pDevice,
8754 + UINT32 *pTupleScanAddress,
8758 + @category: PD_Reference
8759 + @input: pDevice - the device that is the target of the command.
8760 + @input: Tuple - 8-bit ID of tuple to find
8761 + @input: pTupleScanAddress - On entry pTupleScanAddress is the adddress to start scanning
8762 + @input: pLength - length of pBuffer
8764 + @output: pBuffer - storage for tuple
8765 + @output: pTupleScanAddress - address of the next tuple
8766 + @output: pLength - length of tuple read
8770 + @notes: It is possible to have the same tuple ID multiple times with different lengths. This function
8771 + blocks and is fully synchronous.
8773 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8774 +SDIO_STATUS _SDLIB_FindTuple(PSDDEVICE pDevice,
8776 + UINT32 *pTupleScanAddress,
8780 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
8781 + UINT32 scanStart = *pTupleScanAddress;
8785 + /* sanity check */
8786 + if (scanStart < SDIO_CIS_AREA_BEGIN) {
8787 + return SDIO_STATUS_CIS_OUT_OF_RANGE;
8791 + /* check for end */
8792 + if (scanStart > SDIO_CIS_AREA_END) {
8793 + status = SDIO_STATUS_TUPLE_NOT_FOUND;
8796 + /* get the code */
8797 + status = _Cmd52ReadByteCommon(pDevice, scanStart, &tupleCode);
8798 + if (!SDIO_SUCCESS(status)) {
8801 + if (CISTPL_END == tupleCode) {
8802 + /* found the end */
8803 + status = SDIO_STATUS_TUPLE_NOT_FOUND;
8806 + /* bump past tuple code */
8808 + /* get the tuple link value */
8809 + status = _Cmd52ReadByteCommon(pDevice, scanStart, &tupleLink);
8810 + if (!SDIO_SUCCESS(status)) {
8813 + /* bump past tuple link*/
8815 + /* check tuple we just found */
8816 + if (tupleCode == Tuple) {
8817 + DBG_PRINT(SDDBG_TRACE, ("SDIO Library: Tuple:0x%2.2X Found at Address:0x%X, TupleLink:0x%X \n",
8818 + Tuple, (scanStart - 2), tupleLink));
8819 + if (tupleLink != CISTPL_LINK_END) {
8820 + /* return the next scan address to the caller */
8821 + *pTupleScanAddress = scanStart + tupleLink;
8823 + /* the tuple link is an end marker */
8824 + *pTupleScanAddress = 0xFFFFFFFF;
8826 + /* go get the tuple */
8827 + status = _Cmd52ReadMultipleCommon(pDevice, scanStart,pBuffer,min(*pLength,tupleLink));
8828 + if (SDIO_SUCCESS(status)) {
8829 + /* set the actual return length */
8830 + *pLength = min(*pLength,tupleLink);
8832 + /* break out of loop */
8835 + /*increment past this entire tuple */
8836 + scanStart += tupleLink;
8842 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8843 + @function: Issue an SDIO configuration command.
8845 + @function name: SDLIB_IssueConfig
8846 + @prototype: SDIO_STATUS _SDLIB_IssueConfig(PSDDEVICE pDevice,
8847 + SDCONFIG_COMMAND Command,
8851 + @category: PD_Reference
8852 + @input: pDevice - the device that is the target of the command.
8853 + @input: Command - command to send, see example.
8854 + @input: pData - command's data
8855 + @input: Length length of pData
8857 + @output: pData - updated on commands that return data.
8859 + @return: SDIO Status
8861 + @example: Command and data pairs:
8863 + SDCONFIG_GET_WP SDCONFIG_WP_VALUE
8864 + SDCONFIG_SEND_INIT_CLOCKS none
8865 + SDCONFIG_SDIO_INT_CTRL SDCONFIG_SDIO_INT_CTRL_DATA
8866 + SDCONFIG_SDIO_REARM_INT none
8867 + SDCONFIG_BUS_MODE_CTRL SDCONFIG_BUS_MODE_DATA
8868 + SDCONFIG_POWER_CTRL SDCONFIG_POWER_CTRL_DATA
8872 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8873 +SDIO_STATUS _SDLIB_IssueConfig(PSDDEVICE pDevice,
8874 + SDCONFIG_COMMAND Command,
8878 + SDCONFIG configHdr;
8879 + SET_SDCONFIG_CMD_INFO(&configHdr,Command,pData,Length);
8880 + return SDDEVICE_CALL_CONFIG_FUNC(pDevice,&configHdr);
8883 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8884 + @function: Set function block size
8886 + @function name: SDLIB_SetFunctionBlockSize
8887 + @prototype: SDIO_STATUS SDLIB_SetFunctionBlockSize(PSDDEVICE pDevice,
8890 + @category: PD_Reference
8891 + @input: pDevice - the device that is the target of the command.
8892 + @input: BlockSize - block size to set in function
8896 + @return: SDIO Status
8898 + @notes: Issues CMD52 to set the block size. This function is fully synchronous and may
8901 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8902 +SDIO_STATUS _SDLIB_SetFunctionBlockSize(PSDDEVICE pDevice,
8908 + data[0] = (UINT8)BlockSize;
8909 + data[1] = (UINT8)(BlockSize >> 8);
8910 + /* write the function blk size control register */
8911 + return _SDLIB_IssueCMD52(pDevice,
8912 + 0, /* function 0 register space */
8913 + FBR_FUNC_BLK_SIZE_LOW_OFFSET(CalculateFBROffset(
8914 + SDDEVICE_GET_SDIO_FUNCNO(pDevice))),
8920 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8921 + @function: Print a buffer to the debug output
8923 + @function name: SDLIB_PrintBuffer
8924 + @prototype: void SDLIB_PrintBuffer(PUCHAR pBuffer, INT Length, PTEXT pDescription)
8925 + @category: Support_Reference
8927 + @input: pBuffer - Hex buffer to be printed.
8928 + @input: Length - length of pBuffer.
8929 + @input: pDescription - String title to be printed above the dump.
8935 + @notes: Prints the buffer by converting to ASCII and using REL_PRINT() with 16
8938 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8939 +void _SDLIB_PrintBuffer(PUCHAR pBuffer, INT Length, PTEXT pDescription)
8947 + USHORT offset = 0;
8950 + ("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"));
8951 + if (pDescription != NULL) {
8952 + REL_PRINT(0, ("Description: %s \n\n",pDescription));
8954 + REL_PRINT(0, ("Description: NONE \n\n"));
8957 + ("Offset Data ASCII \n"));
8959 + ("--------------------------------------------------------------------------\n"));
8962 + line[0] = (TEXT)0;
8963 + ascii[0] = (TEXT)0;
8964 + address[0] = (TEXT)0;
8965 + sprintf(address,"%4.4X",offset);
8966 + for (i = 0; i < 16; i++) {
8967 + if (Length != 0) {
8969 + sprintf(temp,"%2.2X ",num);
8970 + strcat(line,temp);
8971 + if ((num >= 0x20) && (num <= 0x7E)) {
8972 + sprintf(temp,"%c",*pBuffer);
8974 + sprintf(temp,"%c",0x2e);
8976 + strcat(ascii,temp);
8980 + /* pad partial line with spaces */
8982 + strcat(ascii," ");
8985 + REL_PRINT(0,("%s %s %s\n", address, line, ascii));
8989 + ("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"));
8993 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8994 + @function: Get default operational current
8996 + @function name: SDLIB_GetDefaultOpCurrent
8997 + @prototype: SDIO_STATUS SDLIB_GetDefaultOpCurrent(PSDDEVICE pDevice, SD_SLOT_CURRENT *pOpCurrent)
8998 + @category: PD_Reference
9000 + @input: pDevice - the device that is the target of the command.
9002 + @output: pOpCurrent - operational current in mA.
9004 + @return: SDIO_STATUS
9006 + @notes: This routine reads the function's CISTPL_FUNCE tuple for the default operational
9007 + current. For SDIO 1.0 devices this value is read from the 8-bit TPLFE_OP_MAX_PWR
9008 + field. For SDIO 1.1 devices, the HP MAX power field is used only if the device is
9009 + operating in HIPWR mode. Otherwise the 8-bit TPLFE_OP_MAX_PWR field is used.
9010 + Some systems may restrict high power/current mode and force cards to operate in a
9011 + legacy (< 200mA) mode. This function is fully synchronous and will block the caller.
9013 + @example: Getting the default operational current for this function:
9014 + // get default operational current
9015 + status = SDLIB_GetDefaultOpCurrent(pDevice, &slotCurrent);
9016 + if (!SDIO_SUCCESS(status)) {
9020 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9021 +SDIO_STATUS _SDLIB_GetDefaultOpCurrent(PSDDEVICE pDevice, SD_SLOT_CURRENT *pOpCurrent)
9025 + struct SDIO_FUNC_EXT_FUNCTION_TPL_1_1 funcTuple;
9026 + SDIO_STATUS status;
9028 + /* get the FUNCE tuple */
9029 + nextTpl = SDDEVICE_GET_SDIO_FUNC_CISPTR(pDevice);
9030 + tplLength = sizeof(funcTuple);
9031 + /* go get the function Extension tuple */
9032 + status = _SDLIB_FindTuple(pDevice,
9035 + (PUINT8)&funcTuple,
9038 + if (!SDIO_SUCCESS(status)) {
9039 + DBG_PRINT(SDDBG_ERROR, ("SDLIB_GetDefaultOpCurrent: Failed to get FuncE Tuple: %d \n", status));
9042 + /* use the operational power (8-bit) value of current in mA as default*/
9043 + *pOpCurrent = funcTuple.CommonInfo.OpMaxPwr;
9044 + if ((tplLength >= sizeof(funcTuple)) && (SDDEVICE_IS_SDIO_REV_GTEQ_1_10(pDevice))) {
9045 + /* we have a 1.1 tuple */
9046 + /* check for HIPWR mode */
9047 + if (SDDEVICE_GET_CARD_FLAGS(pDevice) & CARD_HIPWR) {
9048 + /* use the maximum operational power (16 bit ) from the tuple */
9049 + *pOpCurrent = CT_LE16_TO_CPU_ENDIAN(funcTuple.HiPwrMaxPwr);
9052 + return SDIO_STATUS_SUCCESS;
9056 +static INLINE void FreeMessageBlock(PSDMESSAGE_QUEUE pQueue, PSDMESSAGE_BLOCK pMsg) {
9057 + SDListInsertHead(&pQueue->FreeMessageList, &pMsg->SDList);
9059 +static INLINE void QueueMessageBlock(PSDMESSAGE_QUEUE pQueue, PSDMESSAGE_BLOCK pMsg) {
9060 + SDListInsertTail(&pQueue->MessageList, &pMsg->SDList);
9062 +static INLINE void QueueMessageToHead(PSDMESSAGE_QUEUE pQueue, PSDMESSAGE_BLOCK pMsg) {
9063 + SDListInsertHead(&pQueue->MessageList, &pMsg->SDList);
9066 +static INLINE PSDMESSAGE_BLOCK GetFreeMessageBlock(PSDMESSAGE_QUEUE pQueue) {
9067 + PSDLIST pItem = SDListRemoveItemFromHead(&pQueue->FreeMessageList);
9068 + if (pItem != NULL) {
9069 + return CONTAINING_STRUCT(pItem, SDMESSAGE_BLOCK , SDList);
9073 +static INLINE PSDMESSAGE_BLOCK GetQueuedMessage(PSDMESSAGE_QUEUE pQueue) {
9074 + PSDLIST pItem = SDListRemoveItemFromHead(&pQueue->MessageList);
9075 + if (pItem != NULL) {
9076 + return CONTAINING_STRUCT(pItem, SDMESSAGE_BLOCK , SDList);
9081 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9082 + @function: Create a message queue
9084 + @function name: SDLIB_CreateMessageQueue
9085 + @prototype: PSDMESSAGE_QUEUE SDLIB_CreateMessageQueue(INT MaxMessages, INT MaxMessageLength)
9086 + @category: Support_Reference
9088 + @input: MaxMessages - Maximum number of messages this queue supports
9089 + @input: MaxMessageLength - Maximum size of each message
9091 + @return: Message queue object, NULL on failure
9093 + @notes: This function creates a simple first-in-first-out message queue. The caller must determine
9094 + the maximum number of messages the queue supports and the size of each message. This
9095 + function will pre-allocate memory for each message. A producer of data posts a message
9096 + using SDLIB_PostMessage with a user defined data structure. A consumer of this data
9097 + can retrieve the message (in FIFO order) using SDLIB_GetMessage. A message queue does not
9098 + provide a signaling mechanism for notifying a consumer of data. Notifying a consumer is
9101 + @see also: SDLIB_DeleteMessageQueue, SDLIB_GetMessage, SDLIB_PostMessage.
9103 + @example: Creating a message queue:
9104 + typedef struct _MyMessage {
9106 + PVOID pDataBuffer;
9108 + // create message queue, 16 messages max.
9109 + pMsgQueue = SDLIB_CreateMessageQueue(16,sizeof(MyMessage));
9110 + if (NULL == pMsgQueue) {
9114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9115 +PSDMESSAGE_QUEUE _CreateMessageQueue(INT MaxMessages, INT MaxMessageLength)
9117 + PSDMESSAGE_QUEUE pQueue = NULL;
9118 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
9120 + PSDMESSAGE_BLOCK pMsg;
9123 + pQueue = (PSDMESSAGE_QUEUE)KernelAlloc(sizeof(SDMESSAGE_QUEUE));
9125 + if (NULL == pQueue) {
9126 + status = SDIO_STATUS_NO_RESOURCES;
9129 + SDLIST_INIT(&pQueue->MessageList);
9130 + SDLIST_INIT(&pQueue->FreeMessageList);
9131 + pQueue->MaxMessageLength = MaxMessageLength;
9132 + status = CriticalSectionInit(&pQueue->MessageCritSection);
9133 + if (!SDIO_SUCCESS(status)) {
9136 + /* allocate message blocks */
9137 + for (ii = 0; ii < MaxMessages; ii++) {
9138 + pMsg = (PSDMESSAGE_BLOCK)KernelAlloc(sizeof(SDMESSAGE_BLOCK) + MaxMessageLength -1);
9139 + if (NULL == pMsg) {
9142 + FreeMessageBlock(pQueue, pMsg);
9146 + status = SDIO_STATUS_NO_RESOURCES;
9152 + if (!SDIO_SUCCESS(status)) {
9153 + if (pQueue != NULL) {
9154 + _DeleteMessageQueue(pQueue);
9161 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9162 + @function: Delete a message queue
9164 + @function name: SDLIB_DeleteMessageQueue
9165 + @prototype: void SDLIB_DeleteMessageQueue(PSDMESSAGE_QUEUE pQueue)
9166 + @category: Support_Reference
9168 + @input: pQueue - message queue to delete
9170 + @notes: This function flushes the message queue and frees all memory allocated for
9173 + @see also: SDLIB_CreateMessageQueue
9175 + @example: Deleting a message queue:
9176 + if (pMsgQueue != NULL) {
9177 + SDLIB_DeleteMessageQueue(pMsgQueue);
9180 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9181 +void _DeleteMessageQueue(PSDMESSAGE_QUEUE pQueue)
9183 + PSDMESSAGE_BLOCK pMsg;
9184 + SDIO_STATUS status;
9185 + CT_DECLARE_IRQ_SYNC_CONTEXT();
9187 + status = CriticalSectionAcquireSyncIrq(&pQueue->MessageCritSection);
9189 + /* cleanup free list */
9191 + pMsg = GetFreeMessageBlock(pQueue);
9192 + if (pMsg != NULL) {
9198 + /* cleanup any in the queue */
9200 + pMsg = GetQueuedMessage(pQueue);
9201 + if (pMsg != NULL) {
9208 + status = CriticalSectionReleaseSyncIrq(&pQueue->MessageCritSection);
9209 + CriticalSectionDelete(&pQueue->MessageCritSection);
9210 + KernelFree(pQueue);
9214 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9215 + @function: Post a message queue
9217 + @function name: SDLIB_PostMessage
9218 + @prototype: SDIO_STATUS SDLIB_PostMessage(PSDMESSAGE_QUEUE pQueue, PVOID pMessage, INT MessageLength)
9219 + @category: Support_Reference
9221 + @input: pQueue - message queue to post to
9222 + @input: pMessage - message to post
9223 + @input: MessageLength - length of message (for validation)
9225 + @return: SDIO_STATUS
9227 + @notes: The message queue uses an internal list of user defined message structures. When
9228 + posting a message the message is copied into an allocated structure and queued. The memory
9229 + pointed to by pMessage does not need to be allocated and can reside on the stack.
9230 + The length of the message to post can be smaller that the maximum message size. This allows
9231 + for variable length messages up to the maximum message size. This
9232 + function returns SDIO_STATUS_NO_RESOURCES, if the message queue is full. This
9233 + function returns SDIO_STATUS_BUFFER_TOO_SMALL, if the message size exceeds the maximum
9234 + size of a message. Posting and getting messsages from a message queue is safe in any
9237 + @see also: SDLIB_CreateMessageQueue , SDLIB_GetMessage
9239 + @example: Posting a message
9240 + MyMessage message;
9242 + message.code = MESSAGE_DATA_READY;
9243 + message.pData = pInstance->pDataBuffers[currentIndex];
9245 + status = SDLIB_PostMessage(pInstance->pReadQueue,&message,sizeof(message));
9246 + if (!SDIO_SUCCESS(status)) {
9250 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9251 +SDIO_STATUS _PostMessage(PSDMESSAGE_QUEUE pQueue, PVOID pMessage, INT MessageLength)
9253 + SDIO_STATUS status2;
9254 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
9255 + PSDMESSAGE_BLOCK pMsg;
9256 + CT_DECLARE_IRQ_SYNC_CONTEXT();
9258 + if (MessageLength > pQueue->MaxMessageLength) {
9259 + return SDIO_STATUS_BUFFER_TOO_SMALL;
9262 + status = CriticalSectionAcquireSyncIrq(&pQueue->MessageCritSection);
9263 + if (!SDIO_SUCCESS(status)) {
9268 + /* get a message block */
9269 + pMsg = GetFreeMessageBlock(pQueue);
9270 + if (NULL == pMsg) {
9271 + status = SDIO_STATUS_NO_RESOURCES;
9274 + /* copy the message */
9275 + memcpy(pMsg->MessageStart,pMessage,MessageLength);
9276 + /* set the length of the message */
9277 + pMsg->MessageLength = MessageLength;
9278 + /* queue the message to the list */
9279 + QueueMessageBlock(pQueue,pMsg);
9282 + status2 = CriticalSectionReleaseSyncIrq(&pQueue->MessageCritSection);
9286 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9287 + @function: Get a message from a message queue
9289 + @function name: SDLIB_GetMessage
9290 + @prototype: SDIO_STATUS SDLIB_GetMessage(PSDMESSAGE_QUEUE pQueue, PVOID pData, INT *pBufferLength)
9291 + @category: Support_Reference
9293 + @input: pQueue - message queue to retreive a message from
9294 + @input: pBufferLength - on entry, the length of the data buffer
9295 + @output: pData - buffer to hold the message
9296 + @output: pBufferLength - on return, contains the number of bytes copied
9298 + @return: SDIO_STATUS
9300 + @notes: The message queue uses an internal list of user defined message structures. The message is
9301 + dequeued (FIFO order) and copied to the callers buffer. The internal allocation for the message
9302 + is returned back to the message queue. This function returns SDIO_STATUS_NO_MORE_MESSAGES
9303 + if the message queue is empty. If the length of the buffer is smaller than the length of
9304 + the message at the head of the queue,this function returns SDIO_STATUS_BUFFER_TOO_SMALL and
9305 + returns the required length in pBufferLength.
9307 + @see also: SDLIB_CreateMessageQueue , SDLIB_PostMessage
9309 + @example: Getting a message
9310 + MyMessage message;
9313 + length = sizeof(message);
9315 + status = SDLIB_GetMessage(pInstance->pReadQueue,&message,&length);
9316 + if (!SDIO_SUCCESS(status)) {
9320 + @example: Checking queue for a message and getting the size of the message
9322 + // use zero length to get the size of the message
9324 + status = SDLIB_GetMessage(pInstance->pReadQueue,NULL,&length);
9325 + if (status == SDIO_STATUS_NO_MORE_MESSAGES) {
9326 + // no messages in queue
9327 + } else if (status == SDIO_STATUS_BUFFER_TOO_SMALL) {
9328 + // message exists in queue and length of message is returned
9329 + messageSizeInQueue = length;
9331 + // some other failure
9334 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9335 +SDIO_STATUS _GetMessage(PSDMESSAGE_QUEUE pQueue, PVOID pData, INT *pBufferLength)
9337 + SDIO_STATUS status2;
9338 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
9339 + PSDMESSAGE_BLOCK pMsg;
9340 + CT_DECLARE_IRQ_SYNC_CONTEXT();
9342 + status = CriticalSectionAcquireSyncIrq(&pQueue->MessageCritSection);
9343 + if (!SDIO_SUCCESS(status)) {
9348 + pMsg = GetQueuedMessage(pQueue);
9349 + if (NULL == pMsg) {
9350 + status = SDIO_STATUS_NO_MORE_MESSAGES;
9353 + if (*pBufferLength < pMsg->MessageLength) {
9354 + /* caller buffer is too small */
9355 + *pBufferLength = pMsg->MessageLength;
9356 + /* stick it back to the front */
9357 + QueueMessageToHead(pQueue, pMsg);
9358 + status = SDIO_STATUS_BUFFER_TOO_SMALL;
9361 + /* copy the message to the callers buffer */
9362 + memcpy(pData,pMsg->MessageStart,pMsg->MessageLength);
9363 + /* return actual length */
9364 + *pBufferLength = pMsg->MessageLength;
9365 + /* return this message block back to the free list */
9366 + FreeMessageBlock(pQueue, pMsg);
9370 + status2 = CriticalSectionReleaseSyncIrq(&pQueue->MessageCritSection);
9375 +/* the following documents the OS helper APIs */
9377 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9378 + @function: Create an OS-specific helper task/thread
9380 + @function name: SDLIB_OSCreateHelper
9381 + @prototype: SDIO_STATUS SDLIB_OSCreateHelper(POSKERNEL_HELPER pHelper,
9382 + PHELPER_FUNCTION pFunction,
9384 + @category: Support_Reference
9386 + @input: pHelper - caller allocated helper object
9387 + @input: pFunction - helper function
9388 + @input: pContext - helper context
9390 + @return: SDIO_STATUS
9392 + @notes: This function creates a helper task/thread that runs in a new execution context. The newly
9393 + created task/thread invokes the helper function. The thread/task exits when the helper
9394 + function returns. The helper function has the prototype of:
9395 + THREAD_RETURN HelperFunction(POSKERNEL_HELPER pHelper)
9396 + The helper function usually implements a while loop and suspends execution using
9397 + SD_WAIT_FOR_WAKEUP(). On exit the helper function can return an OS-specific THREAD_RETURN
9398 + code (usually zero). The helper function executes in a fully schedule-able context and
9399 + can block on semaphores and sleep.
9401 + @see also: SDLIB_OSDeleteHelper , SD_WAIT_FOR_WAKEUP
9403 + @example: A thread helper function:
9404 + THREAD_RETURN HelperFunction(POSKERNEL_HELPER pHelper)
9406 + SDIO_STATUS status;
9407 + PMYCONTEXT pContext = (PMYCONTEXT)SD_GET_OS_HELPER_CONTEXT(pHelper);
9408 + // wait for wake up
9410 + status = SD_WAIT_FOR_WAKEUP(pHelper);
9411 + if (!SDIO_SUCCESS(status)) {
9414 + if (SD_IS_HELPER_SHUTTING_DOWN(pHelper)) {
9415 + //... shutting down
9418 + // handle wakeup...
9423 + @example: Creating a helper:
9424 + status = SDLIB_OSCreateHelper(&pInstance->OSHelper,HelperFunction,pInstance);
9425 + if (!SDIO_SUCCESS(status)) {
9429 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9431 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9432 + @function: Delete an OS helper task/thread
9434 + @function name: SDLIB_OSDeleteHelper
9435 + @prototype: void SDLIB_OSDeleteHelper(POSKERNEL_HELPER pHelper)
9436 + @category: Support_Reference
9438 + @input: pHelper - caller allocated helper object
9440 + @notes: This function wakes the helper and waits(blocks) until the helper exits. The caller can
9441 + only pass an OS helper structure that was initialized sucessfully by
9442 + SDLIB_OSCreateHelper. The caller must be in a schedulable context.
9444 + @see also: SDLIB_OSCreateHelper
9446 + @example: Deleting a helper:
9447 + if (pInstance->HelperCreated) {
9448 + // clean up the helper if we successfully created it
9449 + SDLIB_OSDeleteHelper(&pInstance->OSHelper);
9453 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9456 diff --git a/drivers/sdio/stack/lib/sdio_lib_os.c b/drivers/sdio/stack/lib/sdio_lib_os.c
9457 new file mode 100644
9458 index 0000000..55363d0
9460 +++ b/drivers/sdio/stack/lib/sdio_lib_os.c
9462 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9463 +@file: sdio_function_os.c
9465 +@abstract: Linux implementation module for SDIO library
9467 +#notes: includes module load and unload functions
9469 +@notice: Copyright (c), 2004 Atheros Communications, Inc.
9473 + * This program is free software; you can redistribute it and/or modify
9474 + * it under the terms of the GNU General Public License version 2 as
9475 + * published by the Free Software Foundation;
9477 + * Software distributed under the License is distributed on an "AS
9478 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9479 + * implied. See the License for the specific language governing
9480 + * rights and limitations under the License.
9482 + * Portions of this code were developed with information supplied from the
9483 + * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply:
9485 + * The following conditions apply to the release of the SD simplified specification (�Simplified
9486 + * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete
9487 + * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided
9488 + * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified
9489 + * Specification may require a license from the SD Card Association or other third parties.
9491 + * The information contained in the Simplified Specification is presented only as a standard
9492 + * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any
9493 + * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for
9494 + * any damages, any infringements of patents or other right of the SD Card Association or any third
9495 + * parties, which may result from its use. No license is granted by implication, estoppel or otherwise
9496 + * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall
9497 + * be construed as an obligation by the SD Card Association to disclose or distribute any technical
9498 + * information, know-how or other confidential information to any third party.
9501 + * The initial developers of the original code are Seung Yi and Paul Lever
9503 + * sdio@atheros.com
9507 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9508 +/* debug level for this module*/
9509 +#define DBG_DECLARE 4;
9510 +#include <linux/sdio/ctsystem.h>
9512 +#include <linux/module.h>
9513 +#include <linux/init.h>
9514 +#include <linux/kthread.h>
9516 +#include <linux/sdio/sdio_busdriver.h>
9517 +#include <linux/sdio/sdio_lib.h>
9518 +#include "_sdio_lib.h"
9520 +#define DESCRIPTION "SDIO Kernel Library"
9521 +#define AUTHOR "Atheros Communications, Inc."
9524 +SDIO_STATUS SDLIB_IssueCMD52(PSDDEVICE pDevice,
9531 + return _SDLIB_IssueCMD52(pDevice,FuncNo,Address,pData,ByteCount,Write);
9534 +SDIO_STATUS SDLIB_FindTuple(PSDDEVICE pDevice,
9536 + UINT32 *pTupleScanAddress,
9540 + return _SDLIB_FindTuple(pDevice,Tuple,pTupleScanAddress,pBuffer,pLength);
9543 +SDIO_STATUS SDLIB_IssueConfig(PSDDEVICE pDevice,
9544 + SDCONFIG_COMMAND Command,
9548 + return _SDLIB_IssueConfig(pDevice,Command,pData,Length);
9551 +void SDLIB_PrintBuffer(PUCHAR pBuffer,INT Length,PTEXT pDescription)
9553 + _SDLIB_PrintBuffer(pBuffer,Length,pDescription);
9556 +SDIO_STATUS SDLIB_SetFunctionBlockSize(PSDDEVICE pDevice,
9559 + return _SDLIB_SetFunctionBlockSize(pDevice,BlockSize);
9562 +void SDLIB_SetupCMD52Request(UINT8 FuncNo,
9566 + PSDREQUEST pRequest)
9568 + _SDLIB_SetupCMD52Request(FuncNo,Address,Write,WriteData,pRequest);
9571 +SDIO_STATUS SDLIB_GetDefaultOpCurrent(PSDDEVICE pDevice, SD_SLOT_CURRENT *pOpCurrent)
9573 + return _SDLIB_GetDefaultOpCurrent(pDevice,pOpCurrent);
9576 +/* helper function launcher */
9577 +INT HelperLaunch(PVOID pContext)
9580 + /* call function */
9581 + exit = ((POSKERNEL_HELPER)pContext)->pHelperFunc((POSKERNEL_HELPER)pContext);
9582 + complete_and_exit(&((POSKERNEL_HELPER)pContext)->Completion, exit);
9587 + * OSCreateHelper - create a worker kernel thread
9589 +SDIO_STATUS SDLIB_OSCreateHelper(POSKERNEL_HELPER pHelper,
9590 + PHELPER_FUNCTION pFunction,
9593 + SDIO_STATUS status = SDIO_STATUS_SUCCESS;
9595 + memset(pHelper,0,sizeof(OSKERNEL_HELPER));
9598 + pHelper->pContext = pContext;
9599 + pHelper->pHelperFunc = pFunction;
9600 + status = SignalInitialize(&pHelper->WakeSignal);
9601 + if (!SDIO_SUCCESS(status)) {
9604 + init_completion(&pHelper->Completion);
9605 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
9606 + pHelper->pTask = kthread_create(HelperLaunch,
9609 + if (NULL == pHelper->pTask) {
9610 + status = SDIO_STATUS_NO_RESOURCES;
9613 + wake_up_process(pHelper->pTask);
9616 + pHelper->pTask = kernel_thread(HelperLaunch,
9618 + (CLONE_FS | CLONE_FILES | SIGCHLD));
9619 + if (pHelper->pTask < 0) {
9620 + DBG_PRINT(SDDBG_TRACE,
9621 + ("SDIO BusDriver - OSCreateHelper, failed to create thread\n"));
9627 + if (!SDIO_SUCCESS(status)) {
9628 + SDLIB_OSDeleteHelper(pHelper);
9634 + * OSDeleteHelper - delete thread created with OSCreateHelper
9636 +void SDLIB_OSDeleteHelper(POSKERNEL_HELPER pHelper)
9639 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
9640 + if (pHelper->pTask != NULL) {
9643 + if (pHelper->pTask >= 0) {
9645 + pHelper->ShutDown = TRUE;
9646 + SignalSet(&pHelper->WakeSignal);
9647 + /* wait for thread to exit */
9648 + wait_for_completion(&pHelper->Completion);
9649 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
9650 + pHelper->pTask = NULL;
9653 + pHelper->pTask = 0;
9657 + SignalDelete(&pHelper->WakeSignal);
9663 +static int __init sdio_lib_init(void) {
9664 + REL_PRINT(SDDBG_TRACE, ("SDIO Library load\n"));
9671 +static void __exit sdio_lib_cleanup(void) {
9672 + REL_PRINT(SDDBG_TRACE, ("SDIO Library unload\n"));
9675 +PSDMESSAGE_QUEUE SDLIB_CreateMessageQueue(INT MaxMessages, INT MaxMessageLength)
9677 + return _CreateMessageQueue(MaxMessages,MaxMessageLength);
9680 +void SDLIB_DeleteMessageQueue(PSDMESSAGE_QUEUE pQueue)
9682 + _DeleteMessageQueue(pQueue);
9685 +SDIO_STATUS SDLIB_PostMessage(PSDMESSAGE_QUEUE pQueue, PVOID pMessage, INT MessageLength)
9687 + return _PostMessage(pQueue,pMessage,MessageLength);
9690 +SDIO_STATUS SDLIB_GetMessage(PSDMESSAGE_QUEUE pQueue, PVOID pData, INT *pBufferLength)
9692 + return _GetMessage(pQueue,pData,pBufferLength);
9695 +MODULE_LICENSE("GPL and additional rights");
9696 +MODULE_DESCRIPTION(DESCRIPTION);
9697 +MODULE_AUTHOR(AUTHOR);
9698 +module_init(sdio_lib_init);
9699 +module_exit(sdio_lib_cleanup);
9700 +EXPORT_SYMBOL(SDLIB_IssueCMD52);
9701 +EXPORT_SYMBOL(SDLIB_FindTuple);
9702 +EXPORT_SYMBOL(SDLIB_IssueConfig);
9703 +EXPORT_SYMBOL(SDLIB_PrintBuffer);
9704 +EXPORT_SYMBOL(SDLIB_SetFunctionBlockSize);
9705 +EXPORT_SYMBOL(SDLIB_SetupCMD52Request);
9706 +EXPORT_SYMBOL(SDLIB_GetDefaultOpCurrent);
9707 +EXPORT_SYMBOL(SDLIB_OSCreateHelper);
9708 +EXPORT_SYMBOL(SDLIB_OSDeleteHelper);
9709 +EXPORT_SYMBOL(SDLIB_CreateMessageQueue);
9710 +EXPORT_SYMBOL(SDLIB_DeleteMessageQueue);
9711 +EXPORT_SYMBOL(SDLIB_PostMessage);
9712 +EXPORT_SYMBOL(SDLIB_GetMessage);
9713 diff --git a/drivers/sdio/stack/platform/Makefile b/drivers/sdio/stack/platform/Makefile
9714 new file mode 100644
9715 index 0000000..14b3612
9717 +++ b/drivers/sdio/stack/platform/Makefile
9719 +obj-$(CONFIG_SDIO) += sdio_platform.o
9720 +sdio_platform-objs := sdioplatformdriver.o
9721 \ No newline at end of file
9722 diff --git a/drivers/sdio/stack/platform/sdioplatformdriver.c b/drivers/sdio/stack/platform/sdioplatformdriver.c
9723 new file mode 100644
9724 index 0000000..d5520fc
9726 +++ b/drivers/sdio/stack/platform/sdioplatformdriver.c
9728 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9729 +@file: sdioplatformdriver.c
9731 +@abstract: Linux implementation module for SDIO pltaform driver
9735 +@notice: Copyright (c), 2006 Atheros Communications, Inc.
9737 +@license: This program is free software; you can redistribute it and/or modify
9738 + it under the terms of the GNU General Public License version 2 as
9739 + published by the Free Software Foundation.
9744 + * This program is free software; you can redistribute it and/or modify
9745 + * it under the terms of the GNU General Public License version 2 as
9746 + * published by the Free Software Foundation;
9748 + * Software distributed under the License is distributed on an "AS
9749 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9750 + * implied. See the License for the specific language governing
9751 + * rights and limitations under the License.
9753 + * Portions of this code were developed with information supplied from the
9754 + * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply:
9756 + * The following conditions apply to the release of the SD simplified specification (�Simplified
9757 + * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete
9758 + * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided
9759 + * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified
9760 + * Specification may require a license from the SD Card Association or other third parties.
9762 + * The information contained in the Simplified Specification is presented only as a standard
9763 + * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any
9764 + * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for
9765 + * any damages, any infringements of patents or other right of the SD Card Association or any third
9766 + * parties, which may result from its use. No license is granted by implication, estoppel or otherwise
9767 + * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall
9768 + * be construed as an obligation by the SD Card Association to disclose or distribute any technical
9769 + * information, know-how or other confidential information to any third party.
9772 + * The initial developers of the original code are Seung Yi and Paul Lever
9774 + * sdio@atheros.com
9778 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9780 +#define DESCRIPTION "SDIO Platform Driver"
9781 +#define AUTHOR "Atheros Communications, Inc."
9785 +struct sdioplatform_peripheral {
9786 + struct list_head node;
9787 + struct sdioplatform_controller *controller;
9788 + struct device dev;
9790 +struct sdioplatform_driver {
9791 + struct device_driver drv;
9792 + int (*probe)(struct sdioplatform_peripheral *);
9793 + void (*remove)(struct sdioplatform_peripheral *);
9794 + int (*suspend)(struct sdioplatform_peripheral *, pm_message_t);
9795 + int (*resume)(struct sdioplatform_peripheral *);
9799 +struct sdioplatform_controller {
9800 + struct device *dev;
9802 +struct sdioplatform_controller_driver {
9803 + struct device_driver drv;
9804 + int (*probe)(struct sdioplatform_controller *);
9805 + void (*remove)(struct sdioplatform_controller *);
9806 + int (*suspend)(struct sdioplatform_controller *, pm_message_t);
9807 + int (*resume)(struct sdioplatform_controller *);
9812 +#define device_to_sdioplatform_peripheral(d) container_of(d, struct sdioplatform_peripheral, dev)
9813 +#define driver_to_sdioplatform_driver(d) container_of(d, struct sdioplatform_driver, drv)
9815 +#define device_to_sdioplatform_controller(d) container_of(d, struct sdioplatform_controller, dev)
9816 +#define driver_to_sdioplatform_controller_driver(d) container_of(d, struct sdioplatform_controller_driver, drv)
9818 +#define SDIOPLATFORM_ATTR(name, fmt, args...) \
9819 +static ssize_t sdio_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \
9821 + struct sdioplatform_peripheral *peripheral = device_to_sdioplatform_peripheral(dev); \
9822 + return sprintf(buf, fmt, args); \
9825 +SDIOPLATFORM_ATTR(bus_id, "%s\n", bus_id);
9826 +#define SDIOPLATFORM_ATTR_RO(name) __ATTR(name, S_IRUGO, sdioplatform_##name##_show, NULL)
9828 +static struct device_attribute sdioplatform_dev_attrs[] = {
9829 + SDIOPLATFORM_ATTR_RO(bus_id),
9833 +static struct bus_type sdioplatform_bus_type = {
9834 + .name = "sdioplatform",
9835 + .dev_attrs = sdioplatform_dev_attrs,
9836 + .match = sdioplatform_bus_match,
9838 + .suspend = sdioplatform_bus_suspend,
9839 + .resume = sdioplatform_bus_resume,
9843 +/* controller functions */
9844 +static int sdioplatform_controllerdrv_probe(struct device *dev)
9846 + struct sdioplatform_controller_driver *drv = driver_to_sdioplatform_controller_driver(dev->driver);
9847 + struct sdioplatform_controller *controller = device_to_sdioplatform_controller(dev);
9849 + return drv->probe(controller);
9852 +static int sdioplatform_controllerdrv_remove(struct device *dev)
9854 + struct sdioplatform_controller_driver *drv = driver_to_sdioplatform_controller_driver(dev->driver);
9855 + struct sdioplatform_controller *controller = device_to_sdioplatform_controller(dev);
9857 + return drv->remove(controller);
9861 + * sdioplatform_register_controller_driver - register a controller driver
9863 +int sdioplatform_register_controller_driver(struct sdioplatform_controller_driver *drv)
9865 + drv->drv.bus = &sdioplatform_bus_type;
9866 + drv->drv.probe = sdioplatform_controllerdrv_probe;
9867 + drv->drv.remove = sdioplatform_controllerdrv_remove;
9868 + return driver_register(&drv->drv);
9872 + * sdioplatform_unregister_controller_driver - unregister a controller driver
9874 +void sdioplatform_unregister_controller_driver(struct sdioplatform_driver *drv)
9876 + driver_unregister(&drv->drv);
9880 + * sdioplatform_add_controller - register a controller device
9882 +int sdioplatform_add_controller(char *name, struct sdioplatform_controller *dev)
9887 + strncpy(dev->dev.bus_id, BUS_ID_SIZE, name);
9888 + return device_register(&dev->dev);
9892 + * sdioplatform_remove_controller - unregister a controller device
9894 +int sdioplatform_remove_controller(char *name, struct sdioplatform_controller *dev)
9899 + return device_unregister(&dev->dev);
9902 +/* peripheral functions */
9903 +static int sdioplatform_drv_probe(struct device *dev)
9905 + struct sdioplatform_driver *drv = driver_to_sdioplatform_driver(dev->driver);
9906 + struct sdioplatform_peripheral *peripheral = device_to_sdioplatform_peripheral(dev);
9908 + return drv->probe(peripheral);
9911 +static int sdioplatform_controllerdrv_remove(struct device *dev)
9913 + struct sdioplatform_controller_driver *drv = driver_to_sdioplatform_controller_driver(dev->driver);
9914 + struct sdioplatform_controller *controller = device_to_sdioplatform_controller(dev);
9916 + return drv->remove(controller);
9920 + * sdioplatform_register_driver - register a driver
9922 +int sdioplatform_register_driver(struct sdioplatform_driver *drv)
9924 + drv->drv.bus = &sdioplatform_bus_type;
9925 + drv->drv.probe = sdioplatform_drv_probe;
9926 + drv->drv.remove = sdioplatform_drv_remove;
9927 + return driver_register(&drv->drv);
9931 + * sdioplatform_unregister_driver - unregister a driver
9933 +void sdioplatform_unregister_driver(struct sdioplatform_driver *drv)
9935 + driver_unregister(&drv->drv);
9939 + * sdioplatform_add_peripheral - register a peripheral device
9941 +int sdioplatform_add_peripheral(char *name, struct sdioplatform_peripheral *dev)
9946 + strncpy(dev->dev.bus_id, BUS_ID_SIZE, name);
9947 + return device_register(&dev->dev);
9951 + * sdioplatform_remove_peripheral - unregister a peripheral device
9953 +int sdioplatform_remove_peripheral(char *name, struct sdioplatform_peripheral *dev)
9958 + return device_unregister(&dev->dev);
9965 +static int sdioplatform_bus_match(struct device *dev, struct device_driver *drv)
9967 + /* probes handle the matching */
9971 +static int sdioplatform_bus_suspend(struct device *dev, pm_message_t state)
9973 + struct sdioplatform_driver *drv = driver_to_sdioplatform_driver(dev->driver);
9974 + struct sdioplatform_peripheral *peripheral = device_to_sdioplatform_peripheral(dev);
9977 + if (peripheral->driver && drv->suspend) {
9978 + ret = drv->suspend(peripheral, state);
9983 +static int sdioplatform_bus_resume(struct device *dev)
9985 + struct sdioplatform_driver *drv = driver_to_sdioplatform_driver(dev->driver);
9986 + struct sdioplatform_peripheral *peripheral = device_to_sdioplatform_peripheral(dev);
9989 + if (peripheral->driver && drv->resume) {
9990 + ret = drv->resume(card);
9998 +static int __init sdio_platformdriver_init(void) {
9999 + int ret = bus_register(&sdioplatform_bus_type);
10006 +static void __exit sdio_platformdriver_cleanup(void) {
10007 + REL_PRINT(SDDBG_TRACE, ("SDIO unloaded\n"));
10008 + _SDIO_BusDriverCleanup();
10011 +MODULE_LICENSE("GPL");
10012 +MODULE_DESCRIPTION(DESCRIPTION);
10013 +MODULE_AUTHOR(AUTHOR);
10015 +module_init(sdio_platformdriver_init);
10016 +module_exit(sdio_platformdriver_cleanup);
10017 +EXPORT_SYMBOL(sdioplatform_register_controller_driver);
10018 +EXPORT_SYMBOL(sdioplatform_unregister_controller_driver);
10019 +EXPORT_SYMBOL(sdioplatform_add_controller);
10020 +EXPORT_SYMBOL(sdioplatform_remove_controller);
10021 +EXPORT_SYMBOL(sdioplatform_register_driver);
10022 +EXPORT_SYMBOL(sdioplatform_unregister_driver);
10023 +EXPORT_SYMBOL(sdioplatform_add_peripheral);
10024 +EXPORT_SYMBOL(sdioplatform_remove_peripheral);
10028 diff --git a/include/linux/sdio/_sdio_defs.h b/include/linux/sdio/_sdio_defs.h
10029 new file mode 100644
10030 index 0000000..a3f5542
10032 +++ b/include/linux/sdio/_sdio_defs.h
10034 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10035 +@file: _sdio_defs.h
10037 +@abstract: SD/SDIO definitions
10039 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
10043 + * This program is free software; you can redistribute it and/or modify
10044 + * it under the terms of the GNU General Public License version 2 as
10045 + * published by the Free Software Foundation;
10047 + * Software distributed under the License is distributed on an "AS
10048 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
10049 + * implied. See the License for the specific language governing
10050 + * rights and limitations under the License.
10052 + * Portions of this code were developed with information supplied from the
10053 + * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply:
10055 + * The following conditions apply to the release of the SD simplified specification (�Simplified
10056 + * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete
10057 + * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided
10058 + * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified
10059 + * Specification may require a license from the SD Card Association or other third parties.
10061 + * The information contained in the Simplified Specification is presented only as a standard
10062 + * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any
10063 + * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for
10064 + * any damages, any infringements of patents or other right of the SD Card Association or any third
10065 + * parties, which may result from its use. No license is granted by implication, estoppel or otherwise
10066 + * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall
10067 + * be construed as an obligation by the SD Card Association to disclose or distribute any technical
10068 + * information, know-how or other confidential information to any third party.
10071 + * The initial developers of the original code are Seung Yi and Paul Lever
10073 + * sdio@atheros.com
10077 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
10078 +#ifndef ___SDIO_DEFS_H___
10079 +#define ___SDIO_DEFS_H___
10081 +#define SD_INIT_BUS_CLOCK 100000 /* initialization clock in hz */
10082 +#define SPI_INIT_BUS_CLOCK 100000 /* initialization clock in hz */
10083 +#define SD_MAX_BUS_CLOCK 25000000 /* max clock speed in hz */
10084 +#define SD_HS_MAX_BUS_CLOCK 50000000 /* SD high speed max clock speed in hz */
10085 +#define SDIO_LOW_SPEED_MAX_BUS_CLOCK 400000 /* max low speed clock in hz */
10086 +#define SDMMC_MIN_INIT_CLOCKS 80 /* minimun number of initialization clocks */
10087 +#define SDIO_EMPC_CURRENT_THRESHOLD 300 /* SDIO 1.10 , EMPC (mA) threshold, we add some overhead */
10130 +#define SD_ACMD6_BUS_WIDTH_1_BIT 0x00
10131 +#define SD_ACMD6_BUS_WIDTH_4_BIT 0x02
10133 +#define SD_CMD59_CRC_OFF 0x00000000
10134 +#define SD_CMD59_CRC_ON 0x00000001
10136 +/* SD/SPI max response size */
10137 +#define SD_MAX_CMD_RESPONSE_BYTES SD_R2_RESPONSE_BYTES
10139 +#define SD_R1_RESPONSE_BYTES 6
10140 +#define SD_R1B_RESPONSE_BYTES SD_R1_RESPONSE_BYTES
10141 +#define SD_R1_GET_CMD(pR) ((pR)[5] & 0xC0))
10142 +#define SD_R1_SET_CMD(pR,cmd) (pR)[5] = (cmd) & 0xC0
10143 +#define SD_R1_GET_CARD_STATUS(pR) (((UINT32)((pR)[1])) | \
10144 + (((UINT32)((pR)[2])) << 8) | \
10145 + (((UINT32)((pR)[3])) << 16) | \
10146 + (((UINT32)((pR)[4])) << 24) )
10147 +#define SD_R1_SET_CMD_STATUS(pR,status) \
10149 + (pR)[1] = (UINT8)(status); \
10150 + (pR)[2] = (UINT8)((status) >> 8); \
10151 + (pR)[3] = (UINT8)((status) >> 16); \
10152 + (pR)[4] = (UINT8)((status) >> 24); \
10155 +/* SD R1 card status bit masks */
10156 +#define SD_CS_CMD_OUT_OF_RANGE ((UINT32)(1 << 31))
10157 +#define SD_CS_ADDRESS_ERR (1 << 30)
10158 +#define SD_CS_BLK_LEN_ERR (1 << 29)
10159 +#define SD_CS_ERASE_SEQ_ERR (1 << 28)
10160 +#define SD_CS_ERASE_PARAM_ERR (1 << 27)
10161 +#define SD_CS_WP_ERR (1 << 26)
10162 +#define SD_CS_CARD_LOCKED (1 << 25)
10163 +#define SD_CS_LK_UNLK_FAILED (1 << 24)
10164 +#define SD_CS_PREV_CMD_CRC_ERR (1 << 23)
10165 +#define SD_CS_ILLEGAL_CMD_ERR (1 << 22)
10166 +#define SD_CS_ECC_FAILED (1 << 21)
10167 +#define SD_CS_CARD_INTERNAL_ERR (1 << 20)
10168 +#define SD_CS_GENERAL_ERR (1 << 19)
10169 +#define SD_CS_CSD_OVERWR_ERR (1 << 16)
10170 +#define SD_CS_WP_ERASE_SKIP (1 << 15)
10171 +#define SD_CS_ECC_DISABLED (1 << 14)
10172 +#define SD_CS_ERASE_RESET (1 << 13)
10173 +#define SD_CS_GET_STATE(status) (((status) >> 9) & 0x0f)
10174 +#define SD_CS_SET_STATE(status, state) \
10176 + (status) &= ~(0x0F << 9); \
10177 + (status) |= (state) << 9 \
10180 +#define SD_CS_TRANSFER_ERRORS \
10181 + ( SD_CS_ADDRESS_ERR | \
10182 + SD_CS_BLK_LEN_ERR | \
10183 + SD_CS_ERASE_SEQ_ERR | \
10184 + SD_CS_ERASE_PARAM_ERR | \
10186 + SD_CS_ECC_FAILED | \
10187 + SD_CS_CARD_INTERNAL_ERR | \
10188 + SD_CS_GENERAL_ERR )
10190 +#define SD_CS_STATE_IDLE 0
10191 +#define SD_CS_STATE_READY 1
10192 +#define SD_CS_STATE_IDENT 2
10193 +#define SD_CS_STATE_STBY 3
10194 +#define SD_CS_STATE_TRANS 4
10195 +#define SD_CS_STATE_DATA 5
10196 +#define SD_CS_STATE_RCV 6
10197 +#define SD_CS_STATE_PRG 7
10198 +#define SD_CS_STATE_DIS 8
10199 +#define SD_CS_READY_FOR_DATA (1 << 8)
10200 +#define SD_CS_APP_CMD (1 << 5)
10201 +#define SD_CS_AKE_SEQ_ERR (1 << 3)
10203 +/* SD R2 response */
10204 +#define SD_R2_RESPONSE_BYTES 17
10205 +#define MAX_CSD_CID_BYTES 16
10206 +#define SD_R2_SET_STUFF_BITS(pR) (pR)[16] = 0x3F
10207 +#define GET_SD_CSD_TRANS_SPEED(pR) (pR)[12]
10208 +#define GET_SD_CID_MANFID(pR) (pR)[15]
10209 +#define GET_SD_CID_PN_1(pR) (pR)[12]
10210 +#define GET_SD_CID_PN_2(pR) (pR)[11]
10211 +#define GET_SD_CID_PN_3(pR) (pR)[10]
10212 +#define GET_SD_CID_PN_4(pR) (pR)[9]
10213 +#define GET_SD_CID_PN_5(pR) (pR)[8]
10214 +#define GET_SD_CID_PN_6(pR) (pR)[7]
10216 +#define GET_SD_CID_OEMID(pR) ((((UINT16)(pR)[14]) << 8 )| (UINT16)((pR)[13]))
10217 +#define SDMMC_OCR_VOLTAGE_MASK 0x7FFFFFFF
10218 +/* SD R3 response */
10219 +#define SD_R3_RESPONSE_BYTES 6
10220 +#define SD_R3_GET_OCR(pR) ((((UINT32)((pR)[1])) | \
10221 + (((UINT32)((pR)[2])) << 8) | \
10222 + (((UINT32)((pR)[3])) << 16) | \
10223 + (((UINT32)((pR)[4])) << 24)) & SDMMC_OCR_VOLTAGE_MASK)
10224 +#define SD_R3_IS_CARD_READY(pR) (((pR)[4] & 0x80) == 0x80)
10226 +/* OCR bit definitions */
10227 +#define SD_OCR_CARD_PWR_UP_STATUS ((UINT32)(1 << 31))
10228 +#define SD_OCR_3_5_TO_3_6_VDD (1 << 23)
10229 +#define SD_OCR_3_4_TO_3_5_VDD (1 << 22)
10230 +#define SD_OCR_3_3_TO_3_4_VDD (1 << 21)
10231 +#define SD_OCR_3_2_TO_3_3_VDD (1 << 20)
10232 +#define SD_OCR_3_1_TO_3_2_VDD (1 << 19)
10233 +#define SD_OCR_3_0_TO_3_1_VDD (1 << 18)
10234 +#define SD_OCR_2_9_TO_3_0_VDD (1 << 17)
10235 +#define SD_OCR_2_8_TO_2_9_VDD (1 << 16)
10236 +#define SD_OCR_2_7_TO_2_8_VDD (1 << 15)
10237 +#define SD_OCR_2_6_TO_2_7_VDD (1 << 14)
10238 +#define SD_OCR_2_5_TO_2_6_VDD (1 << 13)
10239 +#define SD_OCR_2_4_TO_2_5_VDD (1 << 12)
10240 +#define SD_OCR_2_3_TO_2_4_VDD (1 << 11)
10241 +#define SD_OCR_2_2_TO_2_3_VDD (1 << 10)
10242 +#define SD_OCR_2_1_TO_2_2_VDD (1 << 9)
10243 +#define SD_OCR_2_0_TO_2_1_VDD (1 << 8)
10244 +#define SD_OCR_1_9_TO_2_0_VDD (1 << 7)
10245 +#define SD_OCR_1_8_TO_1_9_VDD (1 << 6)
10246 +#define SD_OCR_1_7_TO_1_8_VDD (1 << 5)
10247 +#define SD_OCR_1_6_TO_1_7_VDD (1 << 4)
10249 +/* SD Status data block */
10250 +#define SD_STATUS_DATA_BYTES 64
10251 +#define SDS_GET_DATA_WIDTH(buffer) ((buffer)[0] & 0xC0)
10252 +#define SDS_BUS_1_BIT 0x00
10253 +#define SDS_BUS_4_BIT 0x80
10254 +#define SDS_GET_SECURE_MODE(buffer) ((buffer)[0] & 0x20)
10255 +#define SDS_CARD_SECURE_MODE 0x20
10256 +#define SDS_GET_CARD_TYPE(buffer) ((buffer)[60] & 0x0F)
10257 +#define SDS_SD_CARD_RW 0x00
10258 +#define SDS_SD_CARD_ROM 0x01
10260 +/* SD R6 response */
10261 +#define SD_R6_RESPONSE_BYTES 6
10262 +#define SD_R6_GET_RCA(pR) ((UINT16)((pR)[3]) | (((UINT16)((pR)[4])) << 8))
10263 +#define SD_R6_GET_CS(pR) ((UINT16)((pR)[1]) | (((UINT16)((pR)[2])) << 8))
10265 +/* SD Configuration Register (SCR) */
10266 +#define SD_SCR_BYTES 8
10267 +#define SCR_REV_1_0 0x00
10268 +#define SCR_SD_SPEC_1_00 0x00
10269 +#define SCR_SD_SPEC_1_10 0x01
10270 +#define SCR_BUS_SUPPORTS_1_BIT 0x01
10271 +#define SCR_BUS_SUPPORTS_4_BIT 0x04
10272 +#define SCR_SD_SECURITY_MASK 0x70
10273 +#define SCR_SD_NO_SECURITY 0x00
10274 +#define SCR_SD_SECURITY_1_0 0x10
10275 +#define SCR_SD_SECURITY_2_0 0x20
10276 +#define SCR_DATA_STATUS_1_AFTER_ERASE 0x80
10278 +#define GET_SD_SCR_STRUCT_VER(pB) ((pB)[7] >> 4)
10279 +#define GET_SD_SCR_SDSPEC_VER(pB) ((pB)[7] & 0x0F)
10280 +#define GET_SD_SCR_BUSWIDTHS(pB) ((pB)[6] & 0x0F)
10281 +#define GET_SD_SCR_BUSWIDTHS_FLAGS(pB) (pB)[6]
10282 +#define GET_SD_SCR_SECURITY(pB) (((pB)[6] >> 4) & 0x07)
10283 +#define GET_SD_SCR_DATA_STAT_AFTER_ERASE(pB) (((pB)[6] >> 7) & 0x01)
10285 +/* SDIO R4 Response */
10286 +#define SD_SDIO_R4_RESPONSE_BYTES 6
10287 +#define SD_SDIO_R4_GET_OCR(pR) ((UINT32)((pR)[1]) | \
10288 + (((UINT32)(pR)[2]) << 8) | \
10289 + (((UINT32)(pR)[3]) << 16))
10290 +#define SD_SDIO_R4_IS_MEMORY_PRESENT(pR) (((pR)[4] & 0x08) == 0x08)
10291 +#define SD_SDIO_R4_GET_IO_FUNC_COUNT(pR) (((pR)[4] >> 4) & 0x07)
10292 +#define SD_SDIO_R4_IS_CARD_READY(pR) (((pR)[4] & 0x80) == 0x80)
10294 +/* SDIO R5 response */
10295 +#define SD_SDIO_R5_RESPONSE_BYTES 6
10296 +#define SD_SDIO_R5_READ_DATA_OFFSET 1
10297 +#define SD_R5_GET_READ_DATA(pR) (pR)[SD_SDIO_R5_READ_DATA_OFFSET]
10298 +#define SD_R5_RESP_FLAGS_OFFSET 2
10299 +#define SD_R5_GET_RESP_FLAGS(pR) (pR)[SD_R5_RESP_FLAGS_OFFSET]
10300 +#define SD_R5_SET_CMD(pR,cmd) (pR)[5] = (cmd) & 0xC0
10301 +#define SD_R5_RESP_CMD_ERR (1 << 7) /* for previous cmd */
10302 +#define SD_R5_ILLEGAL_CMD (1 << 6)
10303 +#define SD_R5_GENERAL_ERR (1 << 3)
10304 +#define SD_R5_INVALID_FUNC (1 << 1)
10305 +#define SD_R5_ARG_RANGE_ERR (1 << 0)
10306 +#define SD_R5_CURRENT_CMD_ERRORS (SD_R5_ILLEGAL_CMD | SD_R5_GENERAL_ERR \
10307 + | SD_R5_INVALID_FUNC | SD_R5_ARG_RANGE_ERR)
10308 +#define SD_R5_ERRORS (SD_R5_CURRENT_CMD_ERRORS)
10310 +#define SD_R5_GET_IO_STATE(pR) (((pR)[2] >> 4) & 0x03)
10311 +#define SD_R5_STATE_DIS 0x00
10312 +#define SD_R5_STATE_CMD 0x01
10313 +#define SD_R5_STATE_TRN 0x02
10315 +/* SDIO Modified R6 Response */
10316 +#define SD_SDIO_R6_RESPONSE_BYTES 6
10317 +#define SD_SDIO_R6_GET_RCA(pR) ((UINT16)((pR)[3]) | ((UINT16)((pR)[4]) << 8))
10318 +#define SD_SDIO_R6_GET_CSTAT(pR)((UINT16)((pR)[1]) | ((UINT16)((pR)[2]) << 8))
10320 +/* SPI mode R1 response */
10321 +#define SPI_R1_RESPONSE_BYTES 1
10322 +#define GET_SPI_R1_RESP_TOKEN(pR) (pR)[0]
10323 +#define SPI_CS_STATE_IDLE 0x01
10324 +#define SPI_CS_ERASE_RESET (1 << 1)
10325 +#define SPI_CS_ILLEGAL_CMD (1 << 2)
10326 +#define SPI_CS_CMD_CRC_ERR (1 << 3)
10327 +#define SPI_CS_ERASE_SEQ_ERR (1 << 4)
10328 +#define SPI_CS_ADDRESS_ERR (1 << 5)
10329 +#define SPI_CS_PARAM_ERR (1 << 6)
10330 +#define SPI_CS_ERR_MASK 0x7c
10332 +/* SPI mode R2 response */
10333 +#define SPI_R2_RESPONSE_BYTES 2
10334 +#define GET_SPI_R2_RESP_TOKEN(pR) (pR)[1]
10335 +#define GET_SPI_R2_STATUS_TOKEN(pR) (pR)[0]
10336 +/* the first response byte is defined above */
10337 +/* the second response byte is defined below */
10338 +#define SPI_CS_CARD_IS_LOCKED (1 << 0)
10339 +#define SPI_CS_LOCK_UNLOCK_FAILED (1 << 1)
10340 +#define SPI_CS_ERROR (1 << 2)
10341 +#define SPI_CS_INTERNAL_ERROR (1 << 3)
10342 +#define SPI_CS_ECC_FAILED (1 << 4)
10343 +#define SPI_CS_WP_VIOLATION (1 << 5)
10344 +#define SPI_CS_ERASE_PARAM_ERR (1 << 6)
10345 +#define SPI_CS_OUT_OF_RANGE (1 << 7)
10347 +/* SPI mode R3 response */
10348 +#define SPI_R3_RESPONSE_BYTES 5
10349 +#define SPI_R3_GET_OCR(pR) ((((UINT32)((pR)[0])) | \
10350 + (((UINT32)((pR)[1])) << 8) | \
10351 + (((UINT32)((pR)[2])) << 16) | \
10352 + (((UINT32)((pR)[3])) << 24)) & SDMMC_OCR_VOLTAGE_MASK)
10353 +#define SPI_R3_IS_CARD_READY(pR) (((pR)[3] & 0x80) == 0x80)
10354 +#define GET_SPI_R3_RESP_TOKEN(pR) (pR)[4]
10356 +/* SPI mode SDIO R4 response */
10357 +#define SPI_SDIO_R4_RESPONSE_BYTES 5
10358 +#define SPI_SDIO_R4_GET_OCR(pR) ((UINT32)((pR)[0]) | \
10359 + (((UINT32)(pR)[1]) << 8) | \
10360 + (((UINT32)(pR)[2]) << 16))
10361 +#define SPI_SDIO_R4_IS_MEMORY_PRESENT(pR) (((pR)[3] & 0x08) == 0x08)
10362 +#define SPI_SDIO_R4_GET_IO_FUNC_COUNT(pR) (((pR)[3] >> 4) & 0x07)
10363 +#define SPI_SDIO_R4_IS_CARD_READY(pR) (((pR)[3] & 0x80) == 0x80)
10364 +#define GET_SPI_SDIO_R4_RESP_TOKEN(pR) (pR)[4]
10366 +/* SPI Mode SDIO R5 response */
10367 +#define SPI_SDIO_R5_RESPONSE_BYTES 2
10368 +#define GET_SPI_SDIO_R5_RESP_TOKEN(pR) (pR)[1]
10369 +#define GET_SPI_SDIO_R5_RESPONSE_RDATA(pR) (pR)[0]
10370 +#define SPI_R5_IDLE_STATE 0x01
10371 +#define SPI_R5_ILLEGAL_CMD (1 << 2)
10372 +#define SPI_R5_CMD_CRC (1 << 3)
10373 +#define SPI_R5_FUNC_ERR (1 << 4)
10374 +#define SPI_R5_PARAM_ERR (1 << 6)
10376 +/* SDIO COMMAND 52 Definitions */
10377 +#define CMD52_READ 0
10378 +#define CMD52_WRITE 1
10379 +#define CMD52_READ_AFTER_WRITE 1
10380 +#define CMD52_NORMAL_WRITE 0
10381 +#define SDIO_SET_CMD52_ARG(arg,rw,func,raw,address,writedata) \
10382 + (arg) = (((rw) & 1) << 31) | \
10383 + (((func) & 0x7) << 28) | \
10384 + (((raw) & 1) << 27) | \
10386 + (((address) & 0x1FFFF) << 9) | \
10388 + ((writedata) & 0xFF)
10389 +#define SDIO_SET_CMD52_READ_ARG(arg,func,address) \
10390 + SDIO_SET_CMD52_ARG(arg,CMD52_READ,(func),0,address,0x00)
10391 +#define SDIO_SET_CMD52_WRITE_ARG(arg,func,address,value) \
10392 + SDIO_SET_CMD52_ARG(arg,CMD52_WRITE,(func),CMD52_NORMAL_WRITE,address,value)
10394 +/* SDIO COMMAND 53 Definitions */
10395 +#define CMD53_READ 0
10396 +#define CMD53_WRITE 1
10397 +#define CMD53_BLOCK_BASIS 1
10398 +#define CMD53_BYTE_BASIS 0
10399 +#define CMD53_FIXED_ADDRESS 0
10400 +#define CMD53_INCR_ADDRESS 1
10401 +#define SDIO_SET_CMD53_ARG(arg,rw,func,mode,opcode,address,bytes_blocks) \
10402 + (arg) = (((rw) & 1) << 31) | \
10403 + (((func) & 0x7) << 28) | \
10404 + (((mode) & 1) << 27) | \
10405 + (((opcode) & 1) << 26) | \
10406 + (((address) & 0x1FFFF) << 9) | \
10407 + ((bytes_blocks) & 0x1FF)
10409 +#define SDIO_MAX_LENGTH_BYTE_BASIS 512
10410 +#define SDIO_MAX_BLOCKS_BLOCK_BASIS 511
10411 +#define SDIO_MAX_BYTES_PER_BLOCK 2048
10412 +#define SDIO_COMMON_AREA_FUNCTION_NUMBER 0
10413 +#define SDIO_FIRST_FUNCTION_NUMBER 1
10414 +#define SDIO_LAST_FUNCTION_NUMBER 7
10416 +#define CMD53_CONVERT_BYTE_BASIS_BLK_LENGTH_PARAM(b) (((b) < SDIO_MAX_LENGTH_BYTE_BASIS) ? (b) : 0)
10417 +#define CMD53_CONVERT_BLOCK_BASIS_BLK_COUNT_PARAM(b) (((b) <= SDIO_MAX_BLOCKS_BLOCK_BASIS) ? (b) : 0)
10420 +/* SDIO COMMON Registers */
10422 +/* revision register */
10423 +#define CCCR_SDIO_REVISION_REG 0x00
10424 +#define CCCR_REV_MASK 0x0F
10425 +#define CCCR_REV_1_0 0x00
10426 +#define CCCR_REV_1_1 0x01
10427 +#define SDIO_REV_MASK 0xF0
10428 +#define SDIO_REV_1_00 0x00
10429 +#define SDIO_REV_1_10 0x10
10430 +#define SDIO_REV_1_20 0x20
10431 +/* SD physical spec revision */
10432 +#define SD_SPEC_REVISION_REG 0x01
10433 +#define SD_REV_MASK 0x0F
10434 +#define SD_REV_1_01 0x00
10435 +#define SD_REV_1_10 0x01
10437 +#define SDIO_ENABLE_REG 0x02
10439 +#define SDIO_READY_REG 0x03
10440 +/* Interrupt Enable */
10441 +#define SDIO_INT_ENABLE_REG 0x04
10442 +#define SDIO_INT_MASTER_ENABLE 0x01
10443 +#define SDIO_INT_ALL_ENABLE 0xFE
10444 +/* Interrupt Pending */
10445 +#define SDIO_INT_PENDING_REG 0x05
10446 +#define SDIO_INT_PEND_MASK 0xFE
10448 +#define SDIO_IO_ABORT_REG 0x06
10449 +#define SDIO_IO_RESET (1 << 3)
10450 +/* Bus Interface */
10451 +#define SDIO_BUS_IF_REG 0x07
10452 +#define CARD_DETECT_DISABLE 0x80
10453 +#define SDIO_BUS_WIDTH_1_BIT 0x00
10454 +#define SDIO_BUS_WIDTH_4_BIT 0x02
10455 +/* Card Capabilities */
10456 +#define SDIO_CARD_CAPS_REG 0x08
10457 +#define SDIO_CAPS_CMD52_WHILE_DATA 0x01 /* card can issue CMD52 while data transfer */
10458 +#define SDIO_CAPS_MULTI_BLOCK 0x02 /* card supports multi-block data transfers */
10459 +#define SDIO_CAPS_READ_WAIT 0x04 /* card supports read-wait protocol */
10460 +#define SDIO_CAPS_SUSPEND_RESUME 0x08 /* card supports I/O function suspend/resume */
10461 +#define SDIO_CAPS_INT_MULTI_BLK 0x10 /* interrupts between multi-block data capable */
10462 +#define SDIO_CAPS_ENB_INT_MULTI_BLK 0x20 /* enable ints between muli-block data */
10463 +#define SDIO_CAPS_LOW_SPEED 0x40 /* low speed card */
10464 +#define SDIO_CAPS_4BIT_LS 0x80 /* 4 bit low speed card */
10465 +/* Common CIS pointer */
10466 +#define SDIO_CMN_CIS_PTR_LOW_REG 0x09
10467 +#define SDIO_CMN_CIS_PTR_MID_REG 0x0a
10468 +#define SDIO_CMN_CIS_PTR_HI_REG 0x0b
10470 +#define SDIO_BUS_SUSPEND_REG 0x0c
10471 +#define SDIO_FUNC_SUSPEND_STATUS_MASK 0x01 /* selected function is suspended */
10472 +#define SDIO_SUSPEND_FUNCTION 0x02 /* suspend the current selected function */
10473 +/* Function select (for bus suspension) */
10474 +#define SDIO_FUNCTION_SELECT_REG 0x0d
10475 +#define SDIO_SUSPEND_FUNCTION_0 0x00
10476 +#define SDIO_SUSPEND_MEMORY_FUNC_MASK 0x08
10477 +/* Function Execution */
10478 +#define SDIO_FUNCTION_EXEC_REG 0x0e
10479 +#define SDIO_MEMORY_FUNC_EXEC_MASK 0x01
10480 +/* Function Ready */
10481 +#define SDIO_FUNCTION_READY_REG 0x0f
10482 +#define SDIO_MEMORY_FUNC_BUSY_MASK 0x01
10484 +/* power control 1.10 only */
10485 +#define SDIO_POWER_CONTROL_REG 0x12
10486 +#define SDIO_POWER_CONTROL_SMPC 0x01
10487 +#define SDIO_POWER_CONTROL_EMPC 0x02
10489 +/* high speed control , 1.20 only */
10490 +#define SDIO_HS_CONTROL_REG 0x13
10491 +#define SDIO_HS_CONTROL_SHS 0x01
10492 +#define SDIO_HS_CONTROL_EHS 0x02
10494 +/* Function Base Registers */
10495 +#define xFUNCTION_FBR_OFFSET(funcNo) (0x100*(funcNo))
10496 +/* offset calculation that does not use multiplication */
10497 +static INLINE UINT32 CalculateFBROffset(UCHAR FuncNo) {
10498 + UCHAR i = FuncNo;
10499 + UINT32 offset = 0;
10506 +/* Function info */
10507 +#define FBR_FUNC_INFO_REG_OFFSET(fbr) ((fbr) + 0x00)
10508 +#define FUNC_INFO_SUPPORTS_CSA_MASK 0x40
10509 +#define FUNC_INFO_ENABLE_CSA 0x80
10510 +#define FUNC_INFO_DEVICE_CODE_MASK 0x0F
10511 +#define FUNC_INFO_DEVICE_CODE_LAST 0x0F
10512 +#define FBR_FUNC_EXT_DEVICE_CODE_OFFSET(fbr) ((fbr) + 0x01)
10513 +/* Function Power selection */
10514 +#define FBR_FUNC_POWER_SELECT_OFFSET(fbr) ((fbr) + 0x02)
10515 +#define FUNC_POWER_SELECT_SPS 0x01
10516 +#define FUNC_POWER_SELECT_EPS 0x02
10517 +/* Function CIS ptr */
10518 +#define FBR_FUNC_CIS_LOW_OFFSET(fbr) ((fbr) + 0x09)
10519 +#define FBR_FUNC_CIS_MID_OFFSET(fbr) ((fbr) + 0x0a)
10520 +#define FBR_FUNC_CIS_HI_OFFSET(fbr) ((fbr) + 0x0b)
10521 +/* Function CSA ptr */
10522 +#define FBR_FUNC_CSA_LOW_OFFSET(fbr) ((fbr) + 0x0c)
10523 +#define FBR_FUNC_CSA_MID_OFFSET(fbr) ((fbr) + 0x0d)
10524 +#define FBR_FUNC_CSA_HI_OFFSET(fbr) ((fbr) + 0x0e)
10525 +/* Function CSA data window */
10526 +#define FBR_FUNC_CSA_DATA_OFFSET(fbr) ((fbr) + 0x0f)
10527 +/* Function Block Size Control */
10528 +#define FBR_FUNC_BLK_SIZE_LOW_OFFSET(fbr) ((fbr) + 0x10)
10529 +#define FBR_FUNC_BLK_SIZE_HI_OFFSET(fbr) ((fbr) + 0x11)
10530 +#define SDIO_CIS_AREA_BEGIN 0x00001000
10531 +#define SDIO_CIS_AREA_END 0x00017fff
10532 +/* Tuple definitions */
10533 +#define CISTPL_NULL 0x00
10534 +#define CISTPL_CHECKSUM 0x10
10535 +#define CISTPL_VERS_1 0x15
10536 +#define CISTPL_ALTSTR 0x16
10537 +#define CISTPL_MANFID 0x20
10538 +#define CISTPL_FUNCID 0x21
10539 +#define CISTPL_FUNCE 0x22
10540 +#define CISTPL_VENDOR 0x91
10541 +#define CISTPL_END 0xff
10542 +#define CISTPL_LINK_END 0xff
10545 +/* these structures must be packed */
10547 +/* Manufacturer ID tuple */
10548 +struct SDIO_MANFID_TPL {
10549 + UINT16 ManufacturerCode; /* jedec code */
10550 + UINT16 ManufacturerInfo; /* manufacturer specific code */
10553 +/* Function ID Tuple */
10554 +struct SDIO_FUNC_ID_TPL {
10555 + UINT8 DeviceCode; /* device code */
10556 + UINT8 InitMask; /* system initialization mask (not used) */
10559 + /* Extended Function Tuple (Common) */
10560 +struct SDIO_FUNC_EXT_COMMON_TPL {
10561 + UINT8 Type; /* type */
10562 + UINT16 Func0_MaxBlockSize; /* max function 0 block transfer size */
10563 + UINT8 MaxTransSpeed; /* max transfer speed (encoded) */
10564 +#define TRANSFER_UNIT_MULTIPIER_MASK 0x07
10565 +#define TIME_VALUE_MASK 0x78
10566 +#define TIME_VALUE_SHIFT 3
10569 +/* Extended Function Tuple (Per Function) */
10570 +struct SDIO_FUNC_EXT_FUNCTION_TPL {
10571 + UINT8 Type; /* type */
10572 +#define SDIO_FUNC_INFO_WAKEUP_SUPPORT 0x01
10573 + UINT8 FunctionInfo; /* function info */
10574 + UINT8 SDIORev; /* revision */
10575 + UINT32 CardPSN; /* product serial number */
10576 + UINT32 CSASize; /* CSA size */
10577 + UINT8 CSAProperties; /* CSA properties */
10578 + UINT16 MaxBlockSize; /* max block size for block transfers */
10579 + UINT32 FunctionOCR; /* optimal function OCR */
10580 + UINT8 OpMinPwr; /* operational min power */
10581 + UINT8 OpAvgPwr; /* operational average power */
10582 + UINT8 OpMaxPwr; /* operation maximum power */
10583 + UINT8 SbMinPwr; /* standby minimum power */
10584 + UINT8 SbAvgPwr; /* standby average power */
10585 + UINT8 SbMaxPwr; /* standby maximum power */
10586 + UINT16 MinBandWidth; /* minimum bus bandwidth */
10587 + UINT16 OptBandWidth; /* optimalbus bandwitdh */
10590 +struct SDIO_FUNC_EXT_FUNCTION_TPL_1_1 {
10591 + struct SDIO_FUNC_EXT_FUNCTION_TPL CommonInfo; /* from 1.0*/
10592 + UINT16 EnableTimeOut; /* timeout for enable */
10593 + UINT16 OperPwrMaxPwr;
10594 + UINT16 OperPwrAvgPwr;
10595 + UINT16 HiPwrMaxPwr;
10596 + UINT16 HiPwrAvgPwr;
10597 + UINT16 LowPwrMaxPwr;
10598 + UINT16 LowPwrAvgPwr;
10601 +static INLINE SDIO_STATUS ConvertCMD52ResponseToSDIOStatus(UINT8 CMD52ResponseFlags) {
10602 + if (!(CMD52ResponseFlags & SD_R5_ERRORS)) {
10603 + return SDIO_STATUS_SUCCESS;
10605 + if (CMD52ResponseFlags & SD_R5_ILLEGAL_CMD) {
10606 + return SDIO_STATUS_DATA_STATE_INVALID;
10607 + } else if (CMD52ResponseFlags & SD_R5_INVALID_FUNC) {
10608 + return SDIO_STATUS_INVALID_FUNC;
10609 + } else if (CMD52ResponseFlags & SD_R5_ARG_RANGE_ERR) {
10610 + return SDIO_STATUS_FUNC_ARG_ERROR;
10612 + return SDIO_STATUS_DATA_ERROR_UNKNOWN;
10616 +/* CMD6 mode switch definitions */
10618 +#define SD_SWITCH_FUNC_CHECK 0
10619 +#define SD_SWITCH_FUNC_SET ((UINT32)(1 << 31))
10620 +#define SD_FUNC_NO_SELECT_MASK 0x00FFFFFF
10621 +#define SD_SWITCH_GRP_1 0
10622 +#define SD_SWITCH_GRP_2 1
10623 +#define SD_SWITCH_GRP_3 2
10624 +#define SD_SWITCH_GRP_4 3
10625 +#define SD_SWITCH_GRP_5 4
10626 +#define SD_SWITCH_GRP_6 5
10628 +#define SD_SWITCH_HIGH_SPEED_GROUP SD_SWITCH_GRP_1
10629 +#define SD_SWITCH_HIGH_SPEED_FUNC_NO 1
10631 +#define SD_SWITCH_MAKE_SHIFT(grp) ((grp) * 4)
10633 +#define SD_SWITCH_MAKE_GRP_PATTERN(FuncGrp,FuncNo) \
10634 + ((SD_FUNC_NO_SELECT_MASK & (~(0xF << SD_SWITCH_MAKE_SHIFT(FuncGrp)))) | \
10635 + (((FuncNo) & 0xF) << SD_SWITCH_MAKE_SHIFT(FuncGrp))) \
10637 +#define SD_SWITCH_FUNC_ARG_GROUP_CHECK(FuncGrp,FuncNo) \
10638 + (SD_SWITCH_FUNC_CHECK | SD_SWITCH_MAKE_GRP_PATTERN(FuncGrp,FuncNo))
10640 +#define SD_SWITCH_FUNC_ARG_GROUP_SET(FuncGrp,FuncNo) \
10641 + (SD_SWITCH_FUNC_SET | SD_SWITCH_MAKE_GRP_PATTERN(FuncGrp,FuncNo))
10643 +#define SD_SWITCH_FUNC_STATUS_BLOCK_BYTES 64
10645 +#define SD_SWITCH_FUNC_STATUS_GET_GRP_BIT_MASK(pBuffer,FuncGrp) \
10646 + (USHORT)((pBuffer)[50 + ((FuncGrp)*2)] | ((pBuffer)[51 + ((FuncGrp)*2)] << 8))
10648 +#define SD_SWITCH_FUNC_STATUS_GET_MAX_CURRENT(pBuffer) \
10649 + (USHORT)((pBuffer)[62] | ((pBuffer)[63] << 8))
10651 +static INLINE UINT8 SDSwitchGetSwitchResult(PUINT8 pBuffer, UINT8 FuncGrp)
10653 + switch (FuncGrp) {
10655 + return (pBuffer[47] & 0xF);
10657 + return (pBuffer[47] >> 4);
10659 + return (pBuffer[48] & 0xF);
10661 + return (pBuffer[48] >> 4);
10663 + return (pBuffer[49] & 0xF);
10665 + return (pBuffer[49] >> 4);
10672 diff --git a/include/linux/sdio/ctsystem.h b/include/linux/sdio/ctsystem.h
10673 new file mode 100644
10674 index 0000000..4f72739
10676 +++ b/include/linux/sdio/ctsystem.h
10678 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10681 +@abstract: common system include file.
10683 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
10687 + * This program is free software; you can redistribute it and/or modify
10688 + * it under the terms of the GNU General Public License version 2 as
10689 + * published by the Free Software Foundation;
10691 + * Software distributed under the License is distributed on an "AS
10692 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
10693 + * implied. See the License for the specific language governing
10694 + * rights and limitations under the License.
10696 + * Portions of this code were developed with information supplied from the
10697 + * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply:
10699 + * The following conditions apply to the release of the SD simplified specification (�Simplified
10700 + * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete
10701 + * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided
10702 + * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified
10703 + * Specification may require a license from the SD Card Association or other third parties.
10705 + * The information contained in the Simplified Specification is presented only as a standard
10706 + * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any
10707 + * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for
10708 + * any damages, any infringements of patents or other right of the SD Card Association or any third
10709 + * parties, which may result from its use. No license is granted by implication, estoppel or otherwise
10710 + * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall
10711 + * be construed as an obligation by the SD Card Association to disclose or distribute any technical
10712 + * information, know-how or other confidential information to any third party.
10715 + * The initial developers of the original code are Seung Yi and Paul Lever
10717 + * sdio@atheros.com
10721 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
10722 +#ifndef __CPSYSTEM_H___
10723 +#define __CPSYSTEM_H___
10725 +/* SDIO stack status defines */
10726 +/* < 0 error, >0 warning, 0 success */
10727 +#define SDIO_IS_WARNING(status) ((status) > 0)
10728 +#define SDIO_IS_ERROR(status) ((status) < 0)
10729 +#define SDIO_SUCCESS(status) ((SDIO_STATUS)(status) >= 0)
10730 +#define SDIO_STATUS_SUCCESS 0
10731 +#define SDIO_STATUS_ERROR -1
10732 +#define SDIO_STATUS_INVALID_PARAMETER -2
10733 +#define SDIO_STATUS_PENDING 3
10734 +#define SDIO_STATUS_DEVICE_NOT_FOUND -4
10735 +#define SDIO_STATUS_DEVICE_ERROR -5
10736 +#define SDIO_STATUS_INTERRUPTED -6
10737 +#define SDIO_STATUS_NO_RESOURCES -7
10738 +#define SDIO_STATUS_CANCELED -8
10739 +#define SDIO_STATUS_BUFFER_TOO_SMALL -9
10740 +#define SDIO_STATUS_NO_MORE_MESSAGES -10
10741 +#define SDIO_STATUS_BUS_RESP_TIMEOUT -20 /* response timed-out */
10742 +#define SDIO_STATUS_BUS_READ_TIMEOUT -21 /* read data timed-out */
10743 +#define SDIO_STATUS_BUS_READ_CRC_ERR -22 /* data CRC failed */
10744 +#define SDIO_STATUS_BUS_WRITE_ERROR -23 /* write failed */
10745 +#define SDIO_STATUS_BUS_RESP_CRC_ERR -24 /* response received with a CRC error */
10746 +#define SDIO_STATUS_INVALID_TUPLE_LENGTH -25 /* tuple length was invalid */
10747 +#define SDIO_STATUS_TUPLE_NOT_FOUND -26 /* tuple could not be found */
10748 +#define SDIO_STATUS_CIS_OUT_OF_RANGE -27 /* CIS is out of range in the tuple scan */
10749 +#define SDIO_STATUS_FUNC_ENABLE_TIMEOUT -28 /* card timed out enabling or disabling */
10750 +#define SDIO_STATUS_DATA_STATE_INVALID -29 /* card is in an invalid state for data */
10751 +#define SDIO_STATUS_DATA_ERROR_UNKNOWN -30 /* card cannot process data transfer */
10752 +#define SDIO_STATUS_INVALID_FUNC -31 /* sdio request is not valid for the function */
10753 +#define SDIO_STATUS_FUNC_ARG_ERROR -32 /* sdio request argument is invalid or out of range */
10754 +#define SDIO_STATUS_INVALID_COMMAND -33 /* SD COMMAND is invalid for the card state */
10755 +#define SDIO_STATUS_SDREQ_QUEUE_FAILED -34 /* request failed to insert into queue */
10756 +#define SDIO_STATUS_BUS_RESP_TIMEOUT_SHIFTABLE -35 /* response timed-out, possibily shiftable to correct */
10757 +#define SDIO_STATUS_UNSUPPORTED -36 /* not supported */
10758 +#define SDIO_STATUS_PROGRAM_TIMEOUT -37 /* memory card programming timeout */
10759 +#define SDIO_STATUS_PROGRAM_STATUS_ERROR -38 /* memory card programming errors */
10761 +#include <linux/sdio/ctsystem_linux.h>
10763 +/* get structure from contained field */
10764 +#define CONTAINING_STRUCT(address, struct_type, field_name)\
10765 + ((struct_type *)((ULONG_PTR)(address) - (ULONG_PTR)(&((struct_type *)0)->field_name)))
10767 +#define ZERO_OBJECT(obj) memset(&(obj),0,sizeof(obj))
10768 +#define ZERO_POBJECT(pObj) memset((pObj),0,sizeof(*(pObj)))
10771 +/* bit field support functions */
10772 +static INLINE void SetBit(PULONG pField, UINT position) {
10773 + *pField |= 1 << position;
10775 +static INLINE void ClearBit(PULONG pField, UINT position) {
10776 + *pField &= ~(1 << position);
10778 +static INLINE BOOL IsBitSet(PULONG pField, UINT position) {
10779 + return (*pField & (1 << position));
10781 +static INLINE INT FirstClearBit(PULONG pField) {
10783 + for(ii = 0; ii < sizeof(ULONG)*8; ii++) {
10784 + if (!IsBitSet(pField, ii)) {
10788 + /* no clear bits found */
10792 +#endif /* __CPSYSTEM_H___ */
10793 diff --git a/include/linux/sdio/ctsystem_linux.h b/include/linux/sdio/ctsystem_linux.h
10794 new file mode 100644
10795 index 0000000..0de89a6
10797 +++ b/include/linux/sdio/ctsystem_linux.h
10799 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10800 +@file: ctsystem_linux.h
10802 +@abstract: common system include file for Linux.
10804 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
10808 + * This program is free software; you can redistribute it and/or modify
10809 + * it under the terms of the GNU General Public License version 2 as
10810 + * published by the Free Software Foundation;
10812 + * Software distributed under the License is distributed on an "AS
10813 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
10814 + * implied. See the License for the specific language governing
10815 + * rights and limitations under the License.
10817 + * Portions of this code were developed with information supplied from the
10818 + * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply:
10820 + * The following conditions apply to the release of the SD simplified specification (�Simplified
10821 + * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete
10822 + * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided
10823 + * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified
10824 + * Specification may require a license from the SD Card Association or other third parties.
10826 + * The information contained in the Simplified Specification is presented only as a standard
10827 + * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any
10828 + * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for
10829 + * any damages, any infringements of patents or other right of the SD Card Association or any third
10830 + * parties, which may result from its use. No license is granted by implication, estoppel or otherwise
10831 + * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall
10832 + * be construed as an obligation by the SD Card Association to disclose or distribute any technical
10833 + * information, know-how or other confidential information to any third party.
10836 + * The initial developers of the original code are Seung Yi and Paul Lever
10838 + * sdio@atheros.com
10842 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
10843 +#ifndef __CPSYSTEM_LINUX_H___
10844 +#define __CPSYSTEM_LINUX_H___
10846 +/* #define DBG_TIMESTAMP 1 */
10847 +#define SD_TRACK_REQ 1
10849 +/* LINUX support */
10850 +#include <linux/version.h>
10852 +#ifndef KERNEL_VERSION
10853 + #error KERNEL_VERSION macro not defined!
10856 +#ifndef LINUX_VERSION_CODE
10857 + #error LINUX_VERSION_CODE macro not defined!
10860 +#include <linux/autoconf.h>
10861 +#include <linux/kernel.h>
10862 +#include <linux/init.h>
10863 +#include <linux/types.h>
10864 +#include <linux/spinlock.h>
10865 +#include <linux/module.h>
10867 +#include <linux/interrupt.h>
10868 +#include <linux/pnp.h>
10869 +#include <asm/hardirq.h>
10870 +#include <asm/semaphore.h>
10871 +#include <asm/io.h>
10872 +#include <asm/scatterlist.h>
10873 +#ifdef DBG_TIMESTAMP
10874 +#include <asm/timex.h>
10875 +#endif /* DBG_TIMESTAMP */
10877 + /* released version of 2.6.9 */
10878 +#include <linux/hardirq.h>
10880 +#include <linux/delay.h>
10881 +#include <linux/device.h>
10883 +/* generic types */
10884 +typedef unsigned char UCHAR;
10885 +typedef unsigned char * PUCHAR;
10886 +typedef char TEXT;
10887 +typedef char * PTEXT;
10888 +typedef unsigned short USHORT;
10889 +typedef unsigned short* PUSHORT;
10890 +typedef unsigned int UINT;
10891 +typedef unsigned int* PUINT;
10893 +typedef int* PINT;
10894 +typedef unsigned long ULONG;
10895 +typedef unsigned long* PULONG;
10897 +typedef u16 UINT16;
10898 +typedef u32 UINT32;
10899 +typedef u8* PUINT8;
10900 +typedef u16* PUINT16;
10901 +typedef u32* PUINT32;
10902 +typedef unsigned char * ULONG_PTR;
10903 +typedef void* PVOID;
10904 +typedef unsigned char BOOL;
10905 +typedef BOOL* PBOOL;
10906 +typedef int SDIO_STATUS;
10907 +typedef int SYSTEM_STATUS;
10908 +typedef unsigned int EVENT_TYPE;
10909 +typedef unsigned int EVENT_ARG;
10910 +typedef unsigned int* PEVENT_TYPE;
10911 +typedef struct semaphore OS_SEMAPHORE;
10912 +typedef struct semaphore* POS_SEMAPHORE;
10913 +typedef struct semaphore OS_SIGNAL; /* OS signals are just semaphores */
10914 +typedef struct semaphore* POS_SIGNAL;
10915 +typedef spinlock_t OS_CRITICALSECTION;
10916 +typedef spinlock_t *POS_CRITICALSECTION;
10917 +typedef int SDPOWER_STATE;
10918 +typedef unsigned long ATOMIC_FLAGS;
10919 +typedef INT THREAD_RETURN;
10920 +typedef dma_addr_t DMA_ADDRESS;
10921 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
10922 +typedef struct task_struct* PKERNEL_TASK;
10923 +typedef struct device_driver OS_DRIVER;
10924 +typedef struct device_driver* POS_DRIVER;
10925 +typedef struct device OS_DEVICE;
10926 +typedef struct device* POS_DEVICE;
10927 +typedef struct pnp_driver OS_PNPDRIVER;
10928 +typedef struct pnp_driver* POS_PNPDRIVER;
10929 +typedef struct pnp_dev OS_PNPDEVICE;
10930 +typedef struct pnp_dev* POS_PNPDEVICE;
10931 +typedef struct module* POS_MODULE;
10934 +typedef int PKERNEL_TASK;
10935 +typedef PVOID OS_DRIVER;
10936 +typedef PVOID* POS_DRIVER;
10937 +typedef PVOID OS_DEVICE;
10938 +typedef PVOID* POS_DEVICE;
10939 +typedef PVOID OS_PNPDRIVER;
10940 +typedef PVOID* POS_PNPDRIVER;
10941 +typedef PVOID OS_PNPDEVICE;
10942 +typedef PVOID* POS_PNPDEVICE;
10943 +typedef struct module* POS_MODULE;
10944 +#define module_param(a,b,c) MODULE_PARM(a, "i")
10947 +typedef int CT_DEBUG_LEVEL;
10957 +#define NULL ((PVOID)0)
10959 +#define SDDMA_DESCRIPTION_FLAG_DMA 0x1 /* DMA enabled */
10960 +#define SDDMA_DESCRIPTION_FLAG_SGDMA 0x2 /* Scatter-Gather DMA enabled */
10961 +typedef struct _SDDMA_DESCRIPTION {
10962 + UINT16 Flags; /* SDDMA_DESCRIPTION_FLAG_xxx */
10963 + UINT16 MaxDescriptors; /* number of supported scatter gather entries */
10964 + UINT32 MaxBytesPerDescriptor; /* maximum bytes in a DMA descriptor entry */
10965 + u64 Mask; /* dma address mask */
10966 + UINT32 AddressAlignment; /* dma address alignment mask, least significant bits indicate illegal address bits */
10967 + UINT32 LengthAlignment; /* dma buffer length alignment mask, least significant bits indicate illegal length bits */
10968 +}SDDMA_DESCRIPTION, *PSDDMA_DESCRIPTION;
10969 +typedef struct scatterlist SDDMA_DESCRIPTOR, *PSDDMA_DESCRIPTOR;
10971 +#define INLINE inline
10972 +#define CT_PACK_STRUCT __attribute__ ((packed))
10974 +#define CT_DECLARE_MODULE_PARAM_INTEGER(p) module_param(p, int, 0644);
10976 +/* debug print macros */
10977 +//#define SDDBG_KERNEL_PRINT_LEVEL KERN_DEBUG
10978 +#define SDDBG_KERNEL_PRINT_LEVEL KERN_ALERT
10979 +#define DBG_MASK_NONE 0x0
10980 +#define DBG_MASK_HCD 0x100
10981 +#define DBG_MASK_LIB 0x200
10982 +#define DBG_MASK_BUS 0x400
10984 +/* debug output levels, this must be order low number to higher */
10985 +#define SDDBG_ERROR 3
10986 +#define SDDBG_WARN 4
10987 +#define SDDBG_DEBUG 6
10988 +#define SDDBG_TRACE 7
10989 +#define SDDBG_ALL 0xff
10991 +#define DBG_LEVEL_NONE 0
10992 +#define DBG_LEVEL_ERROR SDDBG_ERROR
10993 +#define DBG_LEVEL_WARN SDDBG_WARN
10994 +#define DBG_LEVEL_DEBUG SDDBG_DEBUG
10995 +#define DBG_LEVEL_TRACE SDDBG_TRACE
10996 +#define DBG_LEVEL_ALL SDDBG_ALL
10998 +#define DBG_GET_LEVEL(lvl) ((lvl) & 0xff)
10999 +#define DBG_GET_MASK(lvl) (((lvl) & 0xff00))
11001 +#define DBG_SDIO_MASK (DBG_MASK_NONE | DBG_LEVEL_DEBUG)
11007 +#define DBG_ASSERT(test) \
11010 + DBG_PRINT(SDDBG_ERROR, ("Debug Assert Caught, File %s, Line: %d, Test:%s \n",__FILE__, __LINE__,#test)); \
11013 +#define DBG_ASSERT_WITH_MSG(test,s) \
11016 + DBG_PRINT(SDDBG_ERROR, ("Assert:%s File %s, Line: %d \n",(s),__FILE__, __LINE__)); \
11020 +#define DBG_PRINT(lvl, args)\
11022 + if (DBG_GET_LEVEL(lvl) <= (DBG_SDIO_MASK & 0xff)) \
11023 + printk(_DBG_PRINTX_ARG args); \
11028 +#define DBG_PRINT(lvl, str)
11029 +#define DBG_ASSERT(test)
11030 +#define DBG_ASSERT_WITH_MSG(test,s)
11031 +#endif /* DEBUG */
11033 +#define _DBG_PRINTX_ARG(arg...) arg /* unroll the parens around the var args*/
11034 +#define DBG_GET_DEBUG_LEVEL() DBG_GET_LEVEL(DBG_SDIO_MASK)
11035 +#define DBG_SET_DEBUG_LEVEL(v)
11036 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11037 + @function: Print a string to the debugger or console
11039 + @function name: REL_PRINT
11040 + @prototype: void REL_PRINT(INT Level, string)
11041 + @category: Support_Reference
11042 + @input: Level - debug level for the print
11048 + @notes: If Level is less than the current debug level, the print will be
11049 + issued. This print cannot be conditionally compiled.
11050 + @see also: DBG_PRINT
11052 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11053 +#define REL_PRINT(lvl, args)\
11054 + {if (lvl <= DBG_GET_DEBUG_LEVEL())\
11055 + printk(SDDBG_KERNEL_PRINT_LEVEL _DBG_PRINTX_ARG args);\
11057 +/* debug output levels, this must be order low number to higher */
11058 +#define SDDBG_ERROR 3
11059 +#define SDDBG_WARN 4
11060 +#define SDDBG_DEBUG 6
11061 +#define SDDBG_TRACE 7
11063 +#ifdef DBG_CRIT_SECTION_RECURSE
11064 + /* this macro thows an exception if the lock is recursively taken
11065 + * the kernel must be configured with: CONFIG_DEBUG_SPINLOCK=y */
11066 +#define call_spin_lock(pCrit) \
11068 + UINT32 unlocked = 1; \
11069 + if ((pCrit)->lock) {unlocked = 0;} \
11070 + spin_lock_bh(pCrit); \
11071 + if (!unlocked) { \
11072 + unlocked = 0x01; \
11073 + unlocked = *((volatile UINT32 *)unlocked); \
11077 +#define call_spin_lock_irqsave(pCrit,isc) \
11079 + UINT32 unlocked = 1; \
11080 + if ((pCrit)->lock) {unlocked = 0;} \
11081 + spin_lock_irqsave(pCrit,isc); \
11082 + if (!unlocked) { \
11083 + unlocked = 0x01; \
11084 + unlocked = *((volatile UINT32 *)unlocked); \
11089 +#define call_spin_lock(s) spin_lock_bh(s)
11090 +#define call_spin_lock_irqsave(s,isc) spin_lock_irqsave(s,isc)
11093 +#define call_spin_unlock(s) spin_unlock_bh((s))
11094 +#define call_spin_unlock_irqrestore(s,isc) spin_unlock_irqrestore(s,isc)
11096 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
11097 +#define NonSchedulable() (in_atomic() || irqs_disabled())
11099 +#define NonSchedulable() (irqs_disabled())
11101 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11102 + @function: Initialize a critical section object.
11104 + @function name: CriticalSectionInit
11105 + @prototype: SDIO_STATUS CriticalSectionInit(POS_CRITICALSECTION pCrit)
11106 + @category: Support_Reference
11107 + @output: pCrit - pointer to critical section to initialize
11109 + @return: SDIO_STATUS_SUCCESS on success.
11111 + @notes: CriticalSectionDelete() must be called to cleanup any resources
11112 + associated with the critical section.
11114 + @see also: CriticalSectionDelete, CriticalSectionAcquire, CriticalSectionRelease
11115 + @example: To initialize a critical section:
11116 + status = CriticalSectionInit(&pDevice->ListLock);
11117 + if (!SDIO_SUCCESS(status)) {
11122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11123 +static inline SDIO_STATUS CriticalSectionInit(POS_CRITICALSECTION pCrit) {
11124 + spin_lock_init(pCrit);
11125 + return SDIO_STATUS_SUCCESS;
11128 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11129 + @function: Acquire a critical section lock.
11131 + @function name: CriticalSectionAcquire
11132 + @prototype: SDIO_STATUS CriticalSectionAcquire(POS_CRITICALSECTION pCrit)
11133 + @category: Support_Reference
11135 + @input: pCrit - pointer to critical section that was initialized
11137 + @return: SDIO_STATUS_SUCCESS on success.
11139 + @notes: The critical section lock is acquired when this function returns
11140 + SDIO_STATUS_SUCCESS. Use CriticalSectionRelease() to release
11141 + the critical section lock.
11143 + @see also: CriticalSectionRelease
11145 + @example: To acquire a critical section lock:
11146 + status = CriticalSectionAcquire(&pDevice->ListLock);
11147 + if (!SDIO_SUCCESS(status)) {
11151 + ... access protected data
11153 + status = CriticalSectionRelease(&pDevice->ListLock);
11154 + if (!SDIO_SUCCESS(status)) {
11159 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11160 +static inline SDIO_STATUS CriticalSectionAcquire(POS_CRITICALSECTION pCrit) {
11161 + call_spin_lock(pCrit);
11162 + return SDIO_STATUS_SUCCESS;
11165 +// macro-tized versions
11166 +#define CriticalSectionAcquire_M(pCrit) \
11167 + SDIO_STATUS_SUCCESS; call_spin_lock(pCrit)
11168 +#define CriticalSectionRelease_M(pCrit) \
11169 + SDIO_STATUS_SUCCESS; call_spin_unlock(pCrit)
11171 +#define CT_DECLARE_IRQ_SYNC_CONTEXT() unsigned long _ctSyncFlags
11173 +#define CriticalSectionAcquireSyncIrq(pCrit) \
11174 + SDIO_STATUS_SUCCESS; call_spin_lock_irqsave(pCrit,_ctSyncFlags)
11176 +#define CriticalSectionReleaseSyncIrq(pCrit) \
11177 + SDIO_STATUS_SUCCESS; call_spin_unlock_irqrestore(pCrit,_ctSyncFlags)
11181 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11182 + @function: Release a critical section lock.
11184 + @function name: CriticalSectionRelease
11185 + @prototype: SDIO_STATUS CriticalSectionRelease(POS_CRITICALSECTION pCrit)
11186 + @category: Support_Reference
11188 + @input: pCrit - pointer to critical section that was initialized
11190 + @return: SDIO_STATUS_SUCCESS on success.
11192 + @notes: The critical section lock is released when this function returns
11193 + SDIO_STATUS_SUCCESS.
11195 + @see also: CriticalSectionAcquire
11197 + @example: see CriticalSectionAcquire
11199 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11200 +static inline SDIO_STATUS CriticalSectionRelease(POS_CRITICALSECTION pCrit) {
11201 + call_spin_unlock(pCrit);
11202 + return SDIO_STATUS_SUCCESS;
11205 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11206 + @function: Cleanup a critical section object
11208 + @function name: CriticalSectionDelete
11209 + @prototype: void CriticalSectionDelete(POS_CRITICALSECTION pCrit)
11210 + @category: Support_Reference
11212 + @input: pCrit - an initialized critical section object
11214 + @return: SDIO_STATUS_SUCCESS on success.
11218 + @see also: CriticalSectionInit, CriticalSectionAcquire, CriticalSectionRelease
11220 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11221 +static inline void CriticalSectionDelete(POS_CRITICALSECTION pCrit) {
11225 +/* internal use */
11226 +static inline SDIO_STATUS SignalInitialize(POS_SIGNAL pSignal) {
11227 + sema_init(pSignal, 0);
11228 + return SDIO_STATUS_SUCCESS;
11230 +/* internal use */
11231 +static inline void SignalDelete(POS_SIGNAL pSignal) {
11234 +/* internal use */
11235 +static inline SDIO_STATUS SignalWaitInterruptible(POS_SIGNAL pSignal) {
11236 + DBG_ASSERT_WITH_MSG(!NonSchedulable(),"SignalWaitInterruptible not allowed\n");
11237 + if (down_interruptible(pSignal) == 0) {
11238 + return SDIO_STATUS_SUCCESS;
11240 + return SDIO_STATUS_INTERRUPTED;
11243 +/* internal use */
11244 +static inline SDIO_STATUS SignalWait(POS_SIGNAL pSignal) {
11245 + DBG_ASSERT_WITH_MSG(!NonSchedulable(),"SignalWait not allowed\n");
11247 + return SDIO_STATUS_SUCCESS;
11250 +/* internal use */
11251 +static inline SDIO_STATUS SignalSet(POS_SIGNAL pSignal) {
11253 + return SDIO_STATUS_SUCCESS;
11256 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11257 + @function: Initialize a semaphore object.
11259 + @function name: SemaphoreInitialize
11260 + @prototype: SDIO_STATUS SemaphoreInitialize(POS_SEMAPHORE pSem, UINT value)
11261 + @category: Support_Reference
11263 + @input: value - initial value of the semaphore
11265 + @output: pSem - pointer to a semaphore object to initialize
11267 + @return: SDIO_STATUS_SUCCESS on success.
11269 + @notes: SemaphoreDelete() must be called to cleanup any resources
11270 + associated with the semaphore
11272 + @see also: SemaphoreDelete, SemaphorePend, SemaphorePendInterruptable
11274 + @example: To initialize a semaphore:
11275 + status = SemaphoreInitialize(&pDevice->ResourceSem,1);
11276 + if (!SDIO_SUCCESS(status)) {
11281 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11282 +static inline SDIO_STATUS SemaphoreInitialize(POS_SEMAPHORE pSem, UINT value) {
11283 + sema_init(pSem, value);
11284 + return SDIO_STATUS_SUCCESS;
11286 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11287 + @function: Cleanup a semaphore object.
11289 + @function name: SemaphoreDelete
11290 + @prototype: void SemaphoreDelete(POS_SEMAPHORE pSem)
11291 + @category: Support_Reference
11293 + @input: pSem - pointer to a semaphore object to cleanup
11299 + @see also: SemaphoreInitialize
11300 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11301 +static inline void SemaphoreDelete(POS_SEMAPHORE pSem) {
11304 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11305 + @function: Acquire the semaphore or pend if the resource is not available
11307 + @function name: SemaphorePend
11308 + @prototype: SDIO_STATUS SemaphorePend(POS_SEMAPHORE pSem)
11309 + @category: Support_Reference
11311 + @input: pSem - pointer to an initialized semaphore object
11313 + @return: SDIO_STATUS_SUCCESS on success.
11315 + @notes: If the semaphore count is zero this function blocks until the count
11316 + becomes non-zero, otherwise the count is decremented and execution
11317 + continues. While waiting, the task/thread cannot be interrupted.
11318 + If the task or thread should be interruptible, use SemaphorePendInterruptible.
11319 + On some OSes SemaphorePend and SemaphorePendInterruptible behave the same.
11321 + @see also: SemaphorePendInterruptable, SemaphorePost
11322 + @example: To wait for a resource using a semaphore:
11323 + status = SemaphorePend(&pDevice->ResourceSem);
11324 + if (!SDIO_SUCCESS(status)) {
11328 + ... resource acquired
11329 + SemaphorePost(&pDevice->ResourceSem);
11331 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11332 +static inline SDIO_STATUS SemaphorePend(POS_SEMAPHORE pSem) {
11333 + DBG_ASSERT_WITH_MSG(!NonSchedulable(),"SemaphorePend not allowed\n");
11335 + return SDIO_STATUS_SUCCESS;
11337 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11338 + @function: Acquire the semaphore or pend if the resource is not available
11340 + @function name: SemaphorePendInterruptable
11341 + @prototype: SDIO_STATUS SemaphorePendInterruptable(POS_SEMAPHORE pSem)
11342 + @category: Support_Reference
11344 + @input: pSem - pointer to an initialized semaphore object
11346 + @return: SDIO_STATUS_SUCCESS on success.
11348 + @notes: If the semaphore count is zero this function blocks until the count
11349 + becomes non-zero, otherwise the count is decremented and execution
11350 + continues. While waiting, the task/thread can be interrupted.
11351 + If the task or thread should not be interruptible, use SemaphorePend.
11353 + @see also: SemaphorePend, SemaphorePost
11354 + @example: To wait for a resource using a semaphore:
11355 + status = SemaphorePendInterruptable(&pDevice->ResourceSem);
11356 + if (!SDIO_SUCCESS(status)) {
11357 + .. failed, could have been interrupted
11360 + ... resource acquired
11361 + SemaphorePost(&pDevice->ResourceSem);
11363 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11364 +static inline SDIO_STATUS SemaphorePendInterruptable(POS_SEMAPHORE pSem) {
11365 + DBG_ASSERT_WITH_MSG(!NonSchedulable(),"SemaphorePendInterruptable not allowed\n");
11366 + if (down_interruptible(pSem) == 0) {
11367 + return SDIO_STATUS_SUCCESS;
11369 + return SDIO_STATUS_INTERRUPTED;
11372 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11373 + @function: Post a semaphore.
11375 + @function name: SemaphorePost
11376 + @prototype: SDIO_STATUS SemaphorePost(POS_SEMAPHORE pSem)
11377 + @category: Support_Reference
11379 + @input: pSem - pointer to an initialized semaphore object
11381 + @return: SDIO_STATUS_SUCCESS on success.
11383 + @notes: This function increments the semaphore count.
11385 + @see also: SemaphorePend, SemaphorePendInterruptable.
11386 + @example: Posting a semaphore:
11387 + status = SemaphorePendInterruptable(&pDevice->ResourceSem);
11388 + if (!SDIO_SUCCESS(status)) {
11389 + .. failed, could have been interrupted
11392 + ... resource acquired
11393 + // post the semaphore
11394 + SemaphorePost(&pDevice->ResourceSem);
11396 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11397 +static inline SDIO_STATUS SemaphorePost(POS_SEMAPHORE pSem) {
11398 + DBG_ASSERT_WITH_MSG(!NonSchedulable(),"SemaphorePost not allowed\n");
11400 + return SDIO_STATUS_SUCCESS;
11404 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11405 + @function: Allocate a block of kernel accessible memory
11407 + @function name: KernelAlloc
11408 + @prototype: PVOID KernelAlloc(UINT size)
11409 + @category: Support_Reference
11411 + @input: size - size of memory block to allocate
11413 + @return: pointer to the allocated memory, NULL if allocation failed
11415 + @notes: For operating systems that use paging, the allocated memory is always
11416 + non-paged memory. Caller should only use KernelFree() to release the
11417 + block of memory. This call can potentially block and should only be called
11418 + from a schedulable context. Use KernelAllocIrqSafe() if the allocation
11419 + must be made from a non-schedulable context.
11421 + @see also: KernelFree, KernelAllocIrqSafe
11422 + @example: allocating memory:
11423 + pBlock = KernelAlloc(1024);
11424 + if (pBlock == NULL) {
11425 + .. failed, no memory
11426 + return SDIO_STATUS_INSUFFICIENT_RESOURCES;
11429 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11430 +static inline PVOID KernelAlloc(UINT size) {
11431 + PVOID pMem = kmalloc(size, GFP_KERNEL);
11432 + if (pMem != NULL) { memset(pMem,0,size); }
11435 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11436 + @function: Free a block of kernel accessible memory.
11438 + @function name: KernelFree
11439 + @prototype: void KernelFree(PVOID ptr)
11440 + @category: Support_Reference
11442 + @input: ptr - pointer to memory allocated with KernelAlloc()
11446 + @notes: Caller should only use KernelFree() to release memory that was allocated
11447 + with KernelAlloc().
11449 + @see also: KernelAlloc
11450 + @example: KernelFree(pBlock);
11452 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11453 +static inline void KernelFree(PVOID ptr) {
11457 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11458 + @function: Allocate a block of kernel accessible memory in an IRQ-safe manner
11460 + @function name: KernelAllocIrqSafe
11461 + @prototype: PVOID KernelAllocIrqSafe(UINT size)
11462 + @category: Support_Reference
11464 + @input: size - size of memory block to allocate
11466 + @return: pointer to the allocated memory, NULL if allocation failed
11468 + @notes: This variant of KernelAlloc allows the allocation of small blocks of
11469 + memory from an ISR or from a context where scheduling has been disabled.
11470 + The allocations should be small as the memory is typically allocated
11471 + from a critical heap. The caller should only use KernelFreeIrqSafe()
11472 + to release the block of memory.
11474 + @see also: KernelAlloc, KernelFreeIrqSafe
11475 + @example: allocating memory:
11476 + pBlock = KernelAllocIrqSafe(16);
11477 + if (pBlock == NULL) {
11478 + .. failed, no memory
11479 + return SDIO_STATUS_INSUFFICIENT_RESOURCES;
11482 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11483 +static inline PVOID KernelAllocIrqSafe(UINT size) {
11484 + return kmalloc(size, GFP_ATOMIC);
11487 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11488 + @function: Free a block of kernel accessible memory.
11490 + @function name: KernelFreeIrqSafe
11491 + @prototype: void KernelFreeIrqSafe(PVOID ptr)
11492 + @category: Support_Reference
11494 + @input: ptr - pointer to memory allocated with KernelAllocIrqSafe()
11498 + @notes: Caller should only use KernelFreeIrqSafe() to release memory that was allocated
11499 + with KernelAllocIrqSafe().
11501 + @see also: KernelAllocIrqSafe
11502 + @example: KernelFreeIrqSafe(pBlock);
11504 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11505 +static inline void KernelFreeIrqSafe(PVOID ptr) {
11509 +/* error status conversions */
11510 +static inline SYSTEM_STATUS SDIOErrorToOSError(SDIO_STATUS status) {
11511 + switch (status) {
11512 + case SDIO_STATUS_SUCCESS:
11514 + case SDIO_STATUS_INVALID_PARAMETER:
11516 + case SDIO_STATUS_PENDING:
11517 + return -EAGAIN; /* try again */
11518 + case SDIO_STATUS_DEVICE_NOT_FOUND:
11520 + case SDIO_STATUS_DEVICE_ERROR:
11522 + case SDIO_STATUS_INTERRUPTED:
11524 + case SDIO_STATUS_NO_RESOURCES:
11526 + case SDIO_STATUS_ERROR:
11531 +static inline SDIO_STATUS OSErrorToSDIOError(SYSTEM_STATUS status) {
11532 + if (status >=0) {
11533 + return SDIO_STATUS_SUCCESS;
11535 + switch (status) {
11537 + return SDIO_STATUS_INVALID_PARAMETER;
11539 + return SDIO_STATUS_DEVICE_NOT_FOUND;
11541 + return SDIO_STATUS_DEVICE_ERROR;
11543 + return SDIO_STATUS_INTERRUPTED;
11545 + return SDIO_STATUS_NO_RESOURCES;
11547 + return SDIO_STATUS_ERROR;
11549 + return SDIO_STATUS_ERROR;
11553 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11554 + @function: Sleep or delay the execution context for a number of milliseconds.
11556 + @function name: OSSleep
11557 + @prototype: SDIO_STATUS OSSleep(INT SleepInterval)
11558 + @category: Support_Reference
11560 + @input: SleepInterval - time in milliseconds to put the execution context to sleep
11562 + @return: SDIO_STATUS_SUCCESS if sleep succeeded.
11564 + @notes: Caller should be in a context that allows it to sleep or block. The
11565 + minimum duration of sleep may be greater than 1 MS on some platforms and OSes.
11567 + @see also: OSSleep
11568 + @example: Using sleep to delay
11569 + EnableSlotPower(pSlot);
11570 + // wait for power to settle
11571 + status = OSSleep(100);
11572 + if (!SDIO_SUCCESS(status)){
11577 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11578 +static inline SDIO_STATUS OSSleep(INT SleepInterval) {
11581 + DBG_ASSERT_WITH_MSG(!NonSchedulable(),"OSSleep not allowed\n");
11582 + /* convert timeout to ticks */
11583 + delta = (SleepInterval * HZ)/1000;
11584 + if (delta == 0) {
11587 + set_current_state(TASK_INTERRUPTIBLE);
11588 + if (schedule_timeout(delta) != 0) {
11589 + return SDIO_STATUS_INTERRUPTED;
11591 + return SDIO_STATUS_SUCCESS;
11594 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11595 + @function: get the OSs device object
11597 + @function name: SD_GET_OS_DEVICE
11598 + @prototype: POS_DEVICE SD_GET_OS_DEVICE(PSDDEVICE pDevice)
11599 + @category: Support_Reference
11601 + @input: pDevice - the device on the HCD
11603 + @return: pointer to the OSs device
11606 + @example: obtain low level device
11607 + pFunctionContext->GpsDevice.Port.dev = SD_GET_OS_DEVICE(pDevice);
11610 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11611 +#define SD_GET_OS_DEVICE(pDevice) &((pDevice)->Device.dev)
11615 + /* new type checking in 2.6.9 */
11616 + /* I/O Access macros */
11617 +#define _READ_DWORD_REG(reg) \
11618 + readl((const volatile void __iomem *)(reg))
11619 +#define _READ_WORD_REG(reg) \
11620 + readw((const volatile void __iomem *)(reg))
11621 +#define _READ_BYTE_REG(reg) \
11622 + readb((const volatile void __iomem *)(reg))
11623 +#define _WRITE_DWORD_REG(reg,value) \
11624 + writel((value),(volatile void __iomem *)(reg))
11625 +#define _WRITE_WORD_REG(reg,value) \
11626 + writew((value),(volatile void __iomem *)(reg))
11627 +#define _WRITE_BYTE_REG(reg,value) \
11628 + writeb((value),(volatile void __iomem *)(reg))
11630 + /* I/O Access macros */
11631 +#define _READ_DWORD_REG(reg) \
11633 +#define _READ_WORD_REG(reg) \
11635 +#define _READ_BYTE_REG(reg) \
11637 +#define _WRITE_DWORD_REG(reg,value) \
11638 + writel((value),(reg))
11639 +#define _WRITE_WORD_REG(reg,value) \
11640 + writew((value),(reg))
11641 +#define _WRITE_BYTE_REG(reg,value) \
11642 + writeb((value),(reg))
11644 + /* atomic operators */
11645 +static inline ATOMIC_FLAGS AtomicTest_Set(volatile ATOMIC_FLAGS *pValue, INT BitNo) {
11646 + return test_and_set_bit(BitNo,(ATOMIC_FLAGS *)pValue);
11648 +static inline ATOMIC_FLAGS AtomicTest_Clear(volatile ATOMIC_FLAGS *pValue, INT BitNo) {
11649 + return test_and_clear_bit(BitNo,(ATOMIC_FLAGS *)pValue);
11652 +struct _OSKERNEL_HELPER;
11654 +typedef THREAD_RETURN (*PHELPER_FUNCTION)(struct _OSKERNEL_HELPER *);
11656 +typedef struct _OSKERNEL_HELPER {
11657 + PKERNEL_TASK pTask;
11659 + OS_SIGNAL WakeSignal;
11660 + struct completion Completion;
11662 + PHELPER_FUNCTION pHelperFunc;
11663 +}OSKERNEL_HELPER, *POSKERNEL_HELPER;
11665 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11666 + @function: Wake the helper thread
11668 + @function name: SD_WAKE_OS_HELPER
11669 + @prototype: SD_WAKE_OS_HELPER(POSKERNEL_HELPER pOSHelper)
11670 + @category: Support_Reference
11672 + @input: pOSHelper - the OS helper object
11674 + @return: SDIO_STATUS
11676 + @see also: SDLIB_OSCreateHelper
11678 + @example: Waking up a helper thread
11679 + status = SD_WAKE_OS_HELPER(&pInstance->OSHelper);
11682 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11683 +#define SD_WAKE_OS_HELPER(p) SignalSet(&(p)->WakeSignal)
11684 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11685 + @function: Obtains the context for the helper function
11687 + @function name: SD_GET_OS_HELPER_CONTEXT
11688 + @prototype: SD_GET_OS_HELPER_CONTEXT(POSKERNEL_HELPER pOSHelper)
11689 + @category: Support_Reference
11691 + @input: pOSHelper - the OS helper object
11693 + @return: helper specific context
11695 + @notes: This macro should only be called by the function associated with
11696 + the helper object.
11698 + @see also: SDLIB_OSCreateHelper
11700 + @example: Getting the helper specific context
11701 + PMYCONTEXT pContext = (PMYCONTEXT)SD_GET_OS_HELPER_CONTEXT(pHelper);
11704 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11705 +#define SD_GET_OS_HELPER_CONTEXT(p) (p)->pContext
11706 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11707 + @function: Check helper function shut down flag.
11709 + @function name: SD_IS_HELPER_SHUTTING_DOWN
11710 + @prototype: SD_IS_HELPER_SHUTTING_DOWN(POSKERNEL_HELPER pOSHelper)
11711 + @category: Support_Reference
11713 + @input: pOSHelper - the OS helper object
11715 + @return: TRUE if shutting down, else FALSE
11717 + @notes: This macro should only be called by the function associated with
11718 + the helper object. The function should call this macro when it
11719 + unblocks from the call to SD_WAIT_FOR_WAKEUP(). If this function
11720 + returns TRUE, the function should clean up and exit.
11722 + @see also: SDLIB_OSCreateHelper , SD_WAIT_FOR_WAKEUP
11724 + @example: Checking for shutdown
11726 + status = SD_WAIT_FOR_WAKEUP(pHelper);
11727 + if (!SDIO_SUCCESS(status)) {
11730 + if (SD_IS_HELPER_SHUTTING_DOWN(pHelper)) {
11731 + ... shutting down
11736 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11737 +#define SD_IS_HELPER_SHUTTING_DOWN(p) (p)->ShutDown
11738 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11739 + @function: Suspend and wait for wakeup signal
11741 + @function name: SD_WAIT_FOR_WAKEUP
11742 + @prototype: SD_WAIT_FOR_WAKEUP(POSKERNEL_HELPER pOSHelper)
11743 + @category: Support_Reference
11745 + @input: pOSHelper - the OS helper object
11747 + @return: SDIO_STATUS
11749 + @notes: This macro should only be called by the function associated with
11750 + the helper object. The function should call this function to suspend (block)
11751 + itself and wait for a wake up signal. The function should always check
11752 + whether the function should exit by calling SD_IS_HELPER_SHUTTING_DOWN.
11754 + @see also: SDLIB_OSCreateHelper , SD_IS_HELPER_SHUTTING_DOWN
11756 + @example: block on the wake signal
11758 + status = SD_WAIT_FOR_WAKEUP(pHelper);
11759 + if (!SDIO_SUCCESS(status)) {
11762 + if (SD_IS_HELPER_SHUTTING_DOWN(pHelper)) {
11763 + ... shutting down
11768 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11769 +#define SD_WAIT_FOR_WAKEUP(p) SignalWait(&(p)->WakeSignal);
11771 +#define CT_LE16_TO_CPU_ENDIAN(x) __le16_to_cpu(x)
11772 +#define CT_LE32_TO_CPU_ENDIAN(x) __le32_to_cpu(x)
11773 +#define CT_CPU_ENDIAN_TO_LE16(x) __cpu_to_le16(x)
11774 +#define CT_CPU_ENDIAN_TO_LE32(x) __cpu_to_le32(x)
11776 +#define CT_CPU_ENDIAN_TO_BE16(x) __cpu_to_be16(x)
11777 +#define CT_CPU_ENDIAN_TO_BE32(x) __cpu_to_be32(x)
11778 +#define CT_BE16_TO_CPU_ENDIAN(x) __be16_to_cpu(x)
11779 +#define CT_BE32_TO_CPU_ENDIAN(x) __be32_to_cpu(x)
11780 +#endif /* __CPSYSTEM_LINUX_H___ */
11782 diff --git a/include/linux/sdio/mmc_defs.h b/include/linux/sdio/mmc_defs.h
11783 new file mode 100644
11784 index 0000000..576ebd7
11786 +++ b/include/linux/sdio/mmc_defs.h
11788 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11791 +@abstract: MMC definitions not already defined in _sdio_defs.h
11793 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
11797 + * This program is free software; you can redistribute it and/or modify
11798 + * it under the terms of the GNU General Public License version 2 as
11799 + * published by the Free Software Foundation;
11801 + * Software distributed under the License is distributed on an "AS
11802 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11803 + * implied. See the License for the specific language governing
11804 + * rights and limitations under the License.
11806 + * Portions of this code were developed with information supplied from the
11807 + * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply:
11809 + * The following conditions apply to the release of the SD simplified specification (�Simplified
11810 + * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete
11811 + * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided
11812 + * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified
11813 + * Specification may require a license from the SD Card Association or other third parties.
11815 + * The information contained in the Simplified Specification is presented only as a standard
11816 + * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any
11817 + * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for
11818 + * any damages, any infringements of patents or other right of the SD Card Association or any third
11819 + * parties, which may result from its use. No license is granted by implication, estoppel or otherwise
11820 + * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall
11821 + * be construed as an obligation by the SD Card Association to disclose or distribute any technical
11822 + * information, know-how or other confidential information to any third party.
11825 + * The initial developers of the original code are Seung Yi and Paul Lever
11827 + * sdio@atheros.com
11831 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11832 +#ifndef ___MMC_DEFS_H___
11833 +#define ___MMC_DEFS_H___
11835 +#define MMC_MAX_BUS_CLOCK 20000000 /* max clock speed in hz */
11836 +#define MMC_HS_MAX_BUS_CLOCK 52000000 /* MMC PLUS (high speed) max clock rate in hz */
11838 +/* R2 (CSD) macros */
11839 +#define GET_MMC_CSD_TRANS_SPEED(pR) (pR)[12]
11840 +#define GET_MMC_SPEC_VERSION(pR) (((pR)[15] >> 2) & 0x0F)
11841 +#define MMC_SPEC_1_0_TO_1_2 0x00
11842 +#define MMC_SPEC_1_4 0x01
11843 +#define MMC_SPEC_2_0_TO_2_2 0x02
11844 +#define MMC_SPEC_3_1 0x03
11845 +#define MMC_SPEC_4_0_TO_4_1 0x04
11847 +#define MMC_CMD_SWITCH 6
11848 +#define MMC_CMD8 8
11850 +#define MMC_SWITCH_CMD_SET 0
11851 +#define MMC_SWITCH_SET_BITS 1
11852 +#define MMC_SWITCH_CLEAR_BITS 2
11853 +#define MMC_SWITCH_WRITE_BYTE 3
11854 +#define MMC_SWITCH_CMD_SET0 0
11855 +#define MMC_SWITCH_BUILD_ARG(cmdset,access,index,value) \
11856 + (((cmdset) & 0x07) | (((access) & 0x03) << 24) | (((index) & 0xFF) << 16) | (((value) & 0xFF) << 8))
11858 +#define MMC_EXT_CSD_SIZE 512
11860 +#define MMC_EXT_S_CMD_SET_OFFSET 504
11861 +#define MMC_EXT_MIN_PERF_W_8_52_OFFSET 210
11862 +#define MMC_EXT_MIN_PERF_R_8_52_OFFSET 209
11863 +#define MMC_EXT_MIN_PERF_W_8_26_4_52_OFFSET 208
11864 +#define MMC_EXT_MIN_PERF_R_8_26_4_52_OFFSET 207
11865 +#define MMC_EXT_MIN_PERF_W_4_26_OFFSET 206
11866 +#define MMC_EXT_MIN_PERF_R_4_56_OFFSET 205
11867 +#define MMC_EXT_PWR_CL_26_360_OFFSET 203
11868 +#define MMC_EXT_PWR_CL_52_360_OFFSET 202
11869 +#define MMC_EXT_PWR_CL_26_195_OFFSET 201
11870 +#define MMC_EXT_PWR_CL_52_195_OFFSET 200
11871 +#define MMC_EXT_GET_PWR_CLASS(reg) ((reg) & 0xF)
11872 +#define MMC_EXT_MAX_PWR_CLASSES 16
11873 +#define MMC_EXT_CARD_TYPE_OFFSET 196
11874 +#define MMC_EXT_CARD_TYPE_HS_52 (1 << 1)
11875 +#define MMC_EXT_CARD_TYPE_HS_26 (1 << 0)
11876 +#define MMC_EXT_CSD_VER_OFFSET 194
11877 +#define MMC_EXT_VER_OFFSET 192
11878 +#define MMC_EXT_VER_1_0 0
11879 +#define MMC_EXT_VER_1_1 1
11880 +#define MMC_EXT_CMD_SET_OFFSET 191
11881 +#define MMC_EXT_CMD_SET_REV_OFFSET 189
11882 +#define MMC_EXT_PWR_CLASS_OFFSET 187
11883 +#define MMC_EXT_HS_TIMING_OFFSET 185
11884 +#define MMC_EXT_HS_TIMING_ENABLE 0x01
11885 +#define MMC_EXT_BUS_WIDTH_OFFSET 183
11886 +#define MMC_EXT_BUS_WIDTH_1_BIT 0x00
11887 +#define MMC_EXT_BUS_WIDTH_4_BIT 0x01
11888 +#define MMC_EXT_BUS_WIDTH_8_BIT 0x02
11891 diff --git a/include/linux/sdio/sdio_busdriver.h b/include/linux/sdio/sdio_busdriver.h
11892 new file mode 100644
11893 index 0000000..b431d3d
11895 +++ b/include/linux/sdio/sdio_busdriver.h
11897 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11898 +@file: sdio_busdriver.h
11900 +@abstract: include file for registration of SDIO function drivers
11901 + and SDIO host controller bus drivers.
11903 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
11907 + * This program is free software; you can redistribute it and/or modify
11908 + * it under the terms of the GNU General Public License version 2 as
11909 + * published by the Free Software Foundation;
11911 + * Software distributed under the License is distributed on an "AS
11912 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11913 + * implied. See the License for the specific language governing
11914 + * rights and limitations under the License.
11916 + * Portions of this code were developed with information supplied from the
11917 + * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply:
11919 + * The following conditions apply to the release of the SD simplified specification (�Simplified
11920 + * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete
11921 + * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided
11922 + * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified
11923 + * Specification may require a license from the SD Card Association or other third parties.
11925 + * The information contained in the Simplified Specification is presented only as a standard
11926 + * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any
11927 + * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for
11928 + * any damages, any infringements of patents or other right of the SD Card Association or any third
11929 + * parties, which may result from its use. No license is granted by implication, estoppel or otherwise
11930 + * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall
11931 + * be construed as an obligation by the SD Card Association to disclose or distribute any technical
11932 + * information, know-how or other confidential information to any third party.
11935 + * The initial developers of the original code are Seung Yi and Paul Lever
11937 + * sdio@atheros.com
11941 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11942 +#ifndef __SDIO_BUSDRIVER_H___
11943 +#define __SDIO_BUSDRIVER_H___
11945 +typedef UINT8 CT_VERSION_CODE;
11946 +#define CT_SDIO_STACK_VERSION_CODE ((CT_VERSION_CODE)0x26) /* version code that must be set in various structures */
11947 +#define CT_SDIO_STACK_VERSION_MAJOR(v) (((v) & 0xF0) >> 4)
11948 +#define CT_SDIO_STACK_VERSION_MINOR(v) (((v) & 0x0F))
11949 +#define SET_SDIO_STACK_VERSION(p) (p)->Version = CT_SDIO_STACK_VERSION_CODE
11950 +#define GET_SDIO_STACK_VERSION(p) (p)->Version
11951 +#define GET_SDIO_STACK_VERSION_MAJOR(p) CT_SDIO_STACK_VERSION_MAJOR(GET_SDIO_STACK_VERSION(p))
11952 +#define GET_SDIO_STACK_VERSION_MINOR(p) CT_SDIO_STACK_VERSION_MINOR(GET_SDIO_STACK_VERSION(p))
11953 +#include "sdlist.h"
11956 +typedef UINT16 CARD_INFO_FLAGS;
11957 +#define CARD_MMC 0x0001 /* Multi-media card */
11958 +#define CARD_SD 0x0002 /* SD-Memory present */
11959 +#define CARD_SDIO 0x0004 /* SDIO present */
11960 +#define CARD_RAW 0x0008 /* Raw card */
11961 +#define CARD_COMBO (CARD_SD | CARD_SDIO) /* SDIO with SD */
11962 +#define CARD_TYPE_MASK 0x000F /* card type mask */
11963 +#define CARD_SD_WP 0x0010 /* SD WP on */
11964 +#define CARD_PSEUDO 0x0020 /* pseudo card (internal use) */
11965 +#define CARD_HIPWR 0x0040 /* card can use more than 200mA (SDIO 1.1 or greater)*/
11966 +#define GET_CARD_TYPE(flags) ((flags) & CARD_TYPE_MASK)
11968 +/* bus mode and clock rate */
11969 +typedef UINT32 SD_BUSCLOCK_RATE; /* clock rate in hz */
11970 +typedef UINT16 SD_BUSMODE_FLAGS;
11971 +#define SDCONFIG_BUS_WIDTH_RESERVED 0x00
11972 +#define SDCONFIG_BUS_WIDTH_SPI 0x01
11973 +#define SDCONFIG_BUS_WIDTH_1_BIT 0x02
11974 +#define SDCONFIG_BUS_WIDTH_4_BIT 0x03
11975 +#define SDCONFIG_BUS_WIDTH_MMC8_BIT 0x04
11976 +#define SDCONFIG_BUS_WIDTH_MASK 0x0F
11977 +#define SDCONFIG_SET_BUS_WIDTH(flags,width) \
11979 + (flags) &= ~SDCONFIG_BUS_WIDTH_MASK; \
11980 + (flags) |= (width); \
11982 +#define SDCONFIG_GET_BUSWIDTH(flags) ((flags) & SDCONFIG_BUS_WIDTH_MASK)
11983 +#define SDCONFIG_BUS_MODE_SPI_NO_CRC 0x40 /* SPI bus is operating with NO CRC */
11984 +#define SDCONFIG_BUS_MODE_SD_HS 0x80 /* set interface to SD high speed mode */
11985 +#define SDCONFIG_BUS_MODE_MMC_HS 0x20 /* set interface to MMC high speed mode */
11987 +typedef UINT16 SD_SLOT_CURRENT; /* slot current in mA */
11989 +typedef UINT8 SLOT_VOLTAGE_MASK; /* slot voltage */
11990 +#define SLOT_POWER_3_3V 0x01
11991 +#define SLOT_POWER_3_0V 0x02
11992 +#define SLOT_POWER_2_8V 0x04
11993 +#define SLOT_POWER_2_0V 0x08
11994 +#define SLOT_POWER_1_8V 0x10
11995 +#define SLOT_POWER_1_6V 0x20
11997 +#define MAX_CARD_RESPONSE_BYTES 17
11999 +/* plug and play information for SD cards */
12000 +typedef struct _SD_PNP_INFO {
12001 + UINT16 SDIO_ManufacturerCode; /* JEDEC Code */
12002 + UINT16 SDIO_ManufacturerID; /* manf-specific ID */
12003 + UINT8 SDIO_FunctionNo; /* function number 1-7 */
12004 + UINT8 SDIO_FunctionClass; /* function class */
12005 + UINT8 SDMMC_ManfacturerID; /* card CID's MANF-ID */
12006 + UINT16 SDMMC_OEMApplicationID; /* card CID's OEMAPP-ID */
12007 + CARD_INFO_FLAGS CardFlags; /* card flags */
12008 +}SD_PNP_INFO, *PSD_PNP_INFO;
12010 +#define IS_LAST_SDPNPINFO_ENTRY(id)\
12011 + (((id)->SDIO_ManufacturerCode == 0) &&\
12012 + ((id)->SDIO_ManufacturerID == 0) &&\
12013 + ((id)->SDIO_FunctionNo == 0) &&\
12014 + ((id)->SDIO_FunctionClass == 0) &&\
12015 + ((id)->SDMMC_OEMApplicationID == 0) && \
12016 + ((id)->CardFlags == 0))
12018 +/* card properties */
12019 +typedef struct _CARD_PROPERTIES {
12020 + UINT8 IOFnCount; /* number of I/O functions */
12021 + UINT8 SDIORevision; /* SDIO revision */
12022 +#define SDIO_REVISION_1_00 0x00
12023 +#define SDIO_REVISION_1_10 0x01
12024 +#define SDIO_REVISION_1_20 0x02
12025 + UINT8 SD_MMC_Revision; /* SD or MMC revision */
12026 +#define SD_REVISION_1_01 0x00
12027 +#define SD_REVISION_1_10 0x01
12028 +#define MMC_REVISION_1_0_2_2 0x00
12029 +#define MMC_REVISION_3_1 0x01
12030 +#define MMC_REVISION_4_0 0x02
12031 + UINT16 SDIO_ManufacturerCode; /* JEDEC Code */
12032 + UINT16 SDIO_ManufacturerID; /* manf-specific ID */
12033 + UINT32 CommonCISPtr; /* common CIS ptr */
12034 + UINT16 RCA; /* relative card address */
12035 + UINT8 SDIOCaps; /* SDIO card capabilities (refer to SDIO spec for decoding) */
12036 + UINT8 CardCSD[MAX_CARD_RESPONSE_BYTES]; /* for SD/MMC cards */
12037 + CARD_INFO_FLAGS Flags; /* card flags */
12038 + SD_BUSCLOCK_RATE OperBusClock; /* operational bus clock (based on HCD limit)*/
12039 + SD_BUSMODE_FLAGS BusMode; /* current card bus mode */
12040 + UINT16 OperBlockLenLimit; /* operational bytes per block length limit*/
12041 + UINT16 OperBlockCountLimit; /* operational number of blocks per transfer limit */
12042 + UINT8 CardState; /* card state flags */
12043 + SLOT_VOLTAGE_MASK CardVoltage; /* card operational voltage */
12044 +#define CARD_STATE_REMOVED 0x01
12045 +}CARD_PROPERTIES, *PCARD_PROPERTIES;
12047 +/* SDREQUEST request flags */
12048 +typedef UINT32 SDREQUEST_FLAGS;
12049 +/* write operation */
12050 +#define SDREQ_FLAGS_DATA_WRITE 0x8000
12051 +/* has data (read or write) */
12052 +#define SDREQ_FLAGS_DATA_TRANS 0x4000
12053 +/* command is an atomic APP command, requiring CMD55 to be issued */
12054 +#define SDREQ_FLAGS_APP_CMD 0x2000
12055 +/* transfer should be handled asynchronously */
12056 +#define SDREQ_FLAGS_TRANS_ASYNC 0x1000
12057 +/* host should skip the SPI response filter for this command */
12058 +#define SDREQ_FLAGS_RESP_SKIP_SPI_FILT 0x0800
12059 +/* host should skip the response check for this data transfer */
12060 +#define SDREQ_FLAGS_DATA_SKIP_RESP_CHK 0x0400
12061 +/* flag requesting a CMD12 be automatically issued by host controller */
12062 +#define SDREQ_FLAGS_AUTO_CMD12 0x0200
12063 +/* flag indicating that the data buffer meets HCD's DMA restrictions */
12064 +#define SDREQ_FLAGS_DATA_DMA 0x0010
12065 +/* indicate to host that this is a short and quick transfer, the HCD may optimize
12066 + * this request to reduce interrupt overhead */
12067 +#define SDREQ_FLAGS_DATA_SHORT_TRANSFER 0x00010000
12068 +/* indicate to the host that this is a raw request */
12069 +#define SDREQ_FLAGS_RAW 0x00020000
12070 +/* auto data transfer status check for MMC and Memory cards */
12071 +#define SDREQ_FLAGS_AUTO_TRANSFER_STATUS 0x00100000
12073 +#define SDREQ_FLAGS_UNUSED1 0x00200000
12074 +#define SDREQ_FLAGS_UNUSED2 0x00400000
12075 +#define SDREQ_FLAGS_UNUSED3 0x00800000
12076 +#define SDREQ_FLAGS_UNUSED4 0x01000000
12077 +#define SDREQ_FLAGS_UNUSED5 0x02000000
12079 +/* the following flags are internal use only */
12080 +#define SDREQ_FLAGS_FORCE_DEFERRED_COMPLETE 0x0100
12081 +/* flag indicating that response has been converted (internal use) */
12082 +#define SDREQ_FLAGS_RESP_SPI_CONVERTED 0x0040
12083 +/* request was cancelled - internal use only */
12084 +#define SDREQ_FLAGS_CANCELED 0x0020
12085 +/* a barrier operation */
12086 +#define SDREQ_FLAGS_BARRIER 0x00040000
12087 +/* a pseudo bus request */
12088 +#define SDREQ_FLAGS_PSEUDO 0x00080000
12089 +/* queue to the head */
12090 +#define SDREQ_FLAGS_QUEUE_HEAD 0x04000000
12092 +#define SDREQ_FLAGS_I_UNUSED1 0x08000000
12093 +#define SDREQ_FLAGS_I_UNUSED2 0x10000000
12094 +#define SDREQ_FLAGS_I_UNUSED3 0x20000000
12095 +#define SDREQ_FLAGS_I_UNUSED4 0x40000000
12096 +#define SDREQ_FLAGS_I_UNUSED5 0x80000000
12098 +/* response type mask */
12099 +#define SDREQ_FLAGS_RESP_MASK 0x000F
12100 +#define GET_SDREQ_RESP_TYPE(flags) ((flags) & SDREQ_FLAGS_RESP_MASK)
12101 +#define IS_SDREQ_WRITE_DATA(flags) ((flags) & SDREQ_FLAGS_DATA_WRITE)
12102 +#define IS_SDREQ_DATA_TRANS(flags) ((flags) & SDREQ_FLAGS_DATA_TRANS)
12103 +#define IS_SDREQ_RAW(flags) ((flags) & SDREQ_FLAGS_RAW)
12104 +#define IS_SDREQ_FORCE_DEFERRED_COMPLETE(flags) ((flags) & SDREQ_FLAGS_FORCE_DEFERRED_COMPLETE)
12105 +#define SDREQ_FLAGS_NO_RESP 0x0000
12106 +#define SDREQ_FLAGS_RESP_R1 0x0001
12107 +#define SDREQ_FLAGS_RESP_R1B 0x0002
12108 +#define SDREQ_FLAGS_RESP_R2 0x0003
12109 +#define SDREQ_FLAGS_RESP_R3 0x0004
12110 +#define SDREQ_FLAGS_RESP_MMC_R4 0x0005 /* not supported, for future use */
12111 +#define SDREQ_FLAGS_RESP_MMC_R5 0x0006 /* not supported, for future use */
12112 +#define SDREQ_FLAGS_RESP_R6 0x0007
12113 +#define SDREQ_FLAGS_RESP_SDIO_R4 0x0008
12114 +#define SDREQ_FLAGS_RESP_SDIO_R5 0x0009
12116 +struct _SDREQUEST;
12117 +struct _SDFUNCTION;
12119 +typedef void (*PSDEQUEST_COMPLETION)(struct _SDREQUEST *);
12121 +/* defines SD/MMC and SDIO requests for the RAW-mode API */
12122 +typedef struct _SDREQUEST {
12123 + SDLIST SDList; /* internal use list*/
12124 + UINT32 Argument; /* SD/SDIO/MMC 32 bit argument */
12125 + SDREQUEST_FLAGS Flags; /* request flags */
12126 + ATOMIC_FLAGS InternalFlags; /* internal use flags */
12127 + UINT8 Command; /* SD/SDIO/MMC 8 bit command */
12128 + UINT8 Response[MAX_CARD_RESPONSE_BYTES]; /* buffer for CMD response */
12129 + UINT16 BlockCount; /* number of blocks to send/rcv */
12130 + UINT16 BlockLen; /* length of each block */
12131 + UINT16 DescriptorCount; /* number of DMA descriptor entries in pDataBuffer if DMA */
12132 + PVOID pDataBuffer; /* starting address of buffer (or ptr to PSDDMA_DESCRIPTOR*/
12133 + UINT32 DataRemaining; /* number of bytes remaining in the transfer (internal use) */
12134 + PVOID pHcdContext; /* internal use context */
12135 + PSDEQUEST_COMPLETION pCompletion; /* function driver completion routine */
12136 + PVOID pCompleteContext; /* function driver completion context */
12137 + SDIO_STATUS Status; /* completion status */
12138 + struct _SDFUNCTION* pFunction; /* function driver that generated request (internal use)*/
12139 + INT RetryCount; /* number of times to retry on error, non-data cmds only */
12140 + PVOID pBdRsv1; /* reserved */
12143 +}SDREQUEST, *PSDREQUEST;
12145 + /* a request queue */
12146 +typedef struct _SDREQUESTQUEUE {
12147 + SDLIST Queue; /* the queue of requests */
12148 + BOOL Busy; /* busy flag */
12149 +}SDREQUESTQUEUE, *PSDREQUESTQUEUE;
12152 +typedef UINT16 SDCONFIG_COMMAND;
12153 +/* SDCONFIG request flags */
12154 +/* get operation */
12155 +#define SDCONFIG_FLAGS_DATA_GET 0x8000
12156 +/* put operation */
12157 +#define SDCONFIG_FLAGS_DATA_PUT 0x4000
12158 +/* host controller */
12159 +#define SDCONFIG_FLAGS_HC_CONFIG 0x2000
12161 +#define SDCONFIG_FLAGS_DATA_BOTH (SDCONFIG_FLAGS_DATA_GET | SDCONFIG_FLAGS_DATA_PUT)
12163 +#define SDCONFIG_FLAGS_DATA_NONE 0x0000
12165 +/* SDCONFIG commands */
12166 +#define SDCONFIG_GET_HCD_DEBUG (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_GET | 275)
12167 +#define SDCONFIG_SET_HCD_DEBUG (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_PUT | 276)
12169 +/* custom hcd commands */
12170 +#define SDCONFIG_GET_HOST_CUSTOM (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_GET | 300)
12171 +#define SDCONFIG_PUT_HOST_CUSTOM (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_PUT | 301)
12173 +/* function commands */
12174 +#define SDCONFIG_FUNC_ENABLE_DISABLE (SDCONFIG_FLAGS_DATA_PUT | 18)
12175 +#define SDCONFIG_FUNC_UNMASK_IRQ (SDCONFIG_FLAGS_DATA_NONE | 21)
12176 +#define SDCONFIG_FUNC_MASK_IRQ (SDCONFIG_FLAGS_DATA_NONE | 22)
12177 +#define SDCONFIG_FUNC_ACK_IRQ (SDCONFIG_FLAGS_DATA_NONE | 23)
12178 +#define SDCONFIG_FUNC_SPI_MODE_DISABLE_CRC (SDCONFIG_FLAGS_DATA_NONE | 24)
12179 +#define SDCONFIG_FUNC_SPI_MODE_ENABLE_CRC (SDCONFIG_FLAGS_DATA_NONE | 25)
12180 +#define SDCONFIG_FUNC_ALLOC_SLOT_CURRENT (SDCONFIG_FLAGS_DATA_PUT | 26)
12181 +#define SDCONFIG_FUNC_FREE_SLOT_CURRENT (SDCONFIG_FLAGS_DATA_NONE | 27)
12182 +#define SDCONFIG_FUNC_CHANGE_BUS_MODE (SDCONFIG_FLAGS_DATA_BOTH | 28)
12183 +#define SDCONFIG_FUNC_CHANGE_BUS_MODE_ASYNC (SDCONFIG_FLAGS_DATA_BOTH | 29)
12184 +#define SDCONFIG_FUNC_NO_IRQ_PEND_CHECK (SDCONFIG_FLAGS_DATA_NONE | 30)
12186 +typedef UINT8 FUNC_ENABLE_DISABLE_FLAGS;
12187 +typedef UINT32 FUNC_ENABLE_TIMEOUT;
12189 + /* function enable */
12190 +typedef struct _SDCONFIG_FUNC_ENABLE_DISABLE_DATA {
12191 +#define SDCONFIG_DISABLE_FUNC 0x0000
12192 +#define SDCONFIG_ENABLE_FUNC 0x0001
12193 + FUNC_ENABLE_DISABLE_FLAGS EnableFlags; /* enable flags*/
12194 + FUNC_ENABLE_TIMEOUT TimeOut; /* timeout in milliseconds */
12195 + void (*pOpComplete)(PVOID Context, SDIO_STATUS status); /* reserved */
12196 + PVOID pOpCompleteContext; /* reserved */
12197 +}SDCONFIG_FUNC_ENABLE_DISABLE_DATA, *PSDCONFIG_FUNC_ENABLE_DISABLE_DATA;
12199 + /* slot current allocation data */
12200 +typedef struct _SDCONFIG_FUNC_SLOT_CURRENT_DATA {
12201 + SD_SLOT_CURRENT SlotCurrent; /* slot current to request in mA*/
12202 +}SDCONFIG_FUNC_SLOT_CURRENT_DATA, *PSDCONFIG_FUNC_SLOT_CURRENT_DATA;
12204 +/* slot bus mode configuration */
12205 +typedef struct _SDCONFIG_BUS_MODE_DATA {
12206 + SD_BUSCLOCK_RATE ClockRate; /* clock rate in Hz */
12207 + SD_BUSMODE_FLAGS BusModeFlags; /* bus mode flags */
12208 + SD_BUSCLOCK_RATE ActualClockRate; /* actual rate in KHz */
12209 +}SDCONFIG_BUS_MODE_DATA, *PSDCONFIG_BUS_MODE_DATA;
12211 +/* defines configuration requests for the HCD */
12212 +typedef struct _SDCONFIG {
12213 + SDCONFIG_COMMAND Cmd; /* configuration command */
12214 + PVOID pData; /* configuration data */
12215 + INT DataLength; /* config data length */
12216 +}SDCONFIG, *PSDCONFIG;
12218 +#define SET_SDCONFIG_CMD_INFO(pHdr,cmd,pC,len) \
12220 + (pHdr)->Cmd = (cmd); \
12221 + (pHdr)->pData = (PVOID)(pC); \
12222 + (pHdr)->DataLength = (len); \
12225 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12226 + @function: Get a pointer to the configuration command data.
12228 + @function name: GET_SDCONFIG_CMD
12229 + @prototype: UNIT16 GET_SDCONFIG_CMD (PSDCONFIG pCommand)
12230 + @category: HD_Reference
12232 + @input: pCommand - config command structure.
12234 + @return: command code
12236 + @notes: Implemented as a macro. This macro returns the command code for this
12237 + configuration request.
12239 + @example: getting the command code:
12240 + cmd = GET_SDCONFIG_CMD(pConfig);
12242 + case SDCONFIG_GET_WP:
12243 + .. get write protect switch position
12248 + @see also: GET_SDCONFIG_CMD_LEN, GET_SDCONFIG_CMD_DATA
12250 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12251 +#define GET_SDCONFIG_CMD(pBuffer) ((pBuffer)->Cmd)
12252 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12253 + @function: Get a pointer to the configuration command data.
12255 + @function name: GET_SDCONFIG_CMD_LEN
12256 + @prototype: INT GET_SDCONFIG_CMD_LEN (PSDCONFIG pCommand)
12257 + @category: HD_Reference
12259 + @input: pCommand - config command structure.
12261 + @return: length of config command data
12263 + @notes: Implemented as a macro. Host controller drivers can use this macro to extract
12264 + the number of bytes of command specific data. This can be used to validate the
12265 + config data buffer size.
12267 + @example: getting the data length:
12268 + length = GET_SDCONFIG_CMD_LEN(pConfig);
12269 + if (length < CUSTOM_COMMAND_XXX_SIZE) {
12270 + ... invalid length
12273 + @see also: GET_SDCONFIG_CMD, GET_SDCONFIG_CMD_DATA
12275 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12276 +#define GET_SDCONFIG_CMD_LEN(pBuffer) ((pBuffer)->DataLength)
12277 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12278 + @function: Get a pointer to the configuration command data.
12280 + @function name: GET_SDCONFIG_CMD_DATA
12281 + @prototype: (casted ptr) GET_SDCONFIG_CMD_DATA (type, PSDCONFIG pCommand)
12282 + @category: HD_Reference
12284 + @input: type - pointer type to cast the returned pointer to.
12285 + pCommand - config command structure.
12287 + @return: type-casted pointer to the command's data
12289 + @notes: Implemented as a macro. Host controller drivers can use this macro to extract
12290 + a pointer to the command specific data in an HCD configuration request.
12292 + @example: getting the pointer:
12293 + // get interrupt control data
12294 + pIntControl = GET_SDCONFIG_CMD_DATA(PSDCONFIG_SDIO_INT_CTRL_DATA,pConfig);
12295 + if (pIntControl->SlotIRQEnable) {
12296 + ... enable slot IRQ detection
12299 + @see also: GET_SDCONFIG_CMD, GET_SDCONFIG_CMD_LEN
12301 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12302 +#define GET_SDCONFIG_CMD_DATA(type,pBuffer) ((type)((pBuffer)->pData))
12303 +#define IS_SDCONFIG_CMD_GET(pBuffer) ((pBuffer)->Cmd & SDCONFIG_FLAGS_DATA_GET)
12304 +#define IS_SDCONFIG_CMD_PUT(pBuffer) ((pBuffer)->Cmd & SDCONFIG_FLAGS_DATA_PUT)
12309 +typedef UINT8 SD_FUNCTION_FLAGS;
12310 +#define SDFUNCTION_FLAG_REMOVING 0x01
12312 +/* function driver registration structure */
12313 +typedef struct _SDFUNCTION {
12314 + CT_VERSION_CODE Version; /* version code of the SDIO stack */
12315 + SDLIST SDList; /* internal use list*/
12316 + PTEXT pName; /* name of registering driver */
12317 + UINT MaxDevices; /* maximum number of devices supported by this function */
12318 + UINT NumDevices; /* number of devices supported by this function */
12319 + PSD_PNP_INFO pIds; /* null terminated table of supported devices*/
12320 + BOOL (*pProbe)(struct _SDFUNCTION *pFunction, struct _SDDEVICE *pDevice);/* New device inserted */
12321 + /* Device removed (NULL if not a hot-plug capable driver) */
12322 + void (*pRemove)(struct _SDFUNCTION *pFunction, struct _SDDEVICE *pDevice);
12323 + SDIO_STATUS (*pSuspend)(struct _SDFUNCTION *pFunction, SDPOWER_STATE state); /* Device suspended */
12324 + SDIO_STATUS (*pResume)(struct _SDFUNCTION *pFunction); /* Device woken up */
12325 + /* Enable wake event */
12326 + SDIO_STATUS (*pWake) (struct _SDFUNCTION *pFunction, SDPOWER_STATE state, BOOL enable);
12327 + PVOID pContext; /* function driver use data */
12328 + OS_PNPDRIVER Driver; /* driver registration with base system */
12329 + SDLIST DeviceList; /* the list of devices this driver is using*/
12330 + OS_SIGNAL CleanupReqSig; /* wait for requests completion on cleanup (internal use) */
12331 + SD_FUNCTION_FLAGS Flags; /* internal flags (internal use) */
12332 +}SDFUNCTION, *PSDFUNCTION;
12334 +typedef UINT8 HCD_EVENT;
12336 + /* device info for SDIO functions */
12337 +typedef struct _SDIO_DEVICE_INFO {
12338 + UINT32 FunctionCISPtr; /* function's CIS ptr */
12339 + UINT32 FunctionCSAPtr; /* function's CSA ptr */
12340 + UINT16 FunctionMaxBlockSize; /* function's reported max block size */
12341 +}SDIO_DEVICE_INFO, *PSDIO_DEVICE_INFO;
12343 + /* device info for SD/MMC card functions */
12344 +typedef struct _SDMMC_INFO{
12345 + UINT8 Unused; /* reserved */
12346 +}SDMMC_INFO, *PSDMMC_INFO;
12348 + /* union of SDIO function and device info */
12349 +typedef union _SDDEVICE_INFO {
12350 + SDIO_DEVICE_INFO AsSDIOInfo;
12351 + SDMMC_INFO AsSDMMCInfo;
12352 +}SDDEVICE_INFO, *PSDDEVICE_INFO;
12355 +typedef UINT8 SD_DEVICE_FLAGS;
12356 +#define SDDEVICE_FLAG_REMOVING 0x01
12358 +/* inserted device description, describes an inserted card */
12359 +typedef struct _SDDEVICE {
12360 + SDLIST SDList; /* internal use list*/
12361 + SDLIST FuncListLink; /* internal use list */
12362 + /* read/write request function */
12363 + SDIO_STATUS (*pRequest)(struct _SDDEVICE *pDev, PSDREQUEST req);
12364 + /* get/set configuration */
12365 + SDIO_STATUS (*pConfigure)(struct _SDDEVICE *pDev, PSDCONFIG config);
12366 + PSDREQUEST (*AllocRequest)(struct _SDDEVICE *pDev); /* allocate a request */
12367 + void (*FreeRequest)(struct _SDDEVICE *pDev, PSDREQUEST pReq); /* free the request */
12368 + void (*pIrqFunction)(PVOID pContext); /* interrupt routine, synchronous calls allowed */
12369 + void (*pIrqAsyncFunction)(PVOID pContext); /* async IRQ function , asynch only calls */
12370 + PVOID IrqContext; /* irq context */
12371 + PVOID IrqAsyncContext; /* irq async context */
12372 + PSDFUNCTION pFunction; /* function driver supporting this device */
12373 + struct _SDHCD *pHcd; /* host controller this device is on (internal use) */
12374 + SDDEVICE_INFO DeviceInfo; /* device info */
12375 + SD_PNP_INFO pId[1]; /* id of this device */
12376 + OS_PNPDEVICE Device; /* device registration with base system */
12377 + SD_SLOT_CURRENT SlotCurrentAlloc; /* allocated slot current for this device/function (internal use) */
12378 + SD_DEVICE_FLAGS Flags; /* internal use flags */
12379 + CT_VERSION_CODE Version; /* version code of the bus driver */
12380 +}SDDEVICE, *PSDDEVICE;
12382 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12383 + @function: Get SDIO Bus Driver Version Major number
12385 + @function name: SDDEVICE_GET_VERSION_MAJOR
12386 + @prototype: INT SDDEVICE_GET_VERSION_MAJOR(PSDDEVICE pDevice)
12387 + @category: PD_Reference
12389 + @input: pDevice - the target device for this request
12393 + @return: integer value for the major version
12395 + @notes: Implemented as a macro.
12397 + @see also: SDDEVICE_GET_VERSION_MINOR
12399 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12400 +#define SDDEVICE_GET_VERSION_MAJOR(pDev) (GET_SDIO_STACK_VERSION_MAJOR(pDev))
12402 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12403 + @function: Get SDIO Bus Driver Version Minor number
12405 + @function name: SDDEVICE_GET_VERSION_MINOR
12406 + @prototype: INT SDDEVICE_GET_VERSION_MINOR(PSDDEVICE pDevice)
12407 + @category: PD_Reference
12409 + @input: pDevice - the target device for this request
12413 + @return: integer value for the minor version
12415 + @notes: Implemented as a macro.
12417 + @see also: SDDEVICE_GET_VERSION_MAJOR
12419 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12420 +#define SDDEVICE_GET_VERSION_MINOR(pDev) (GET_SDIO_STACK_VERSION_MINOR(pDev))
12422 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12423 + @function: Test the SDIO revision for greater than or equal to 1.10
12425 + @function name: SDDEVICE_IS_SDIO_REV_GTEQ_1_10
12426 + @prototype: BOOL SDDEVICE_IS_SDIO_REV_GTEQ_1_10(PSDDEVICE pDevice)
12427 + @category: PD_Reference
12429 + @input: pDevice - the target device for this request
12433 + @return: TRUE if the revision is greater than or equal to 1.10
12435 + @notes: Implemented as a macro.
12437 + @see also: SDDEVICE_IS_SD_REV_GTEQ_1_10
12438 + @see also: SDDEVICE_IS_MMC_REV_GTEQ_4_0
12440 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12441 +#define SDDEVICE_IS_SDIO_REV_GTEQ_1_10(pDev) ((pDev)->pHcd->CardProperties.SDIORevision >= SDIO_REVISION_1_10)
12443 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12444 + @function: Test the SDIO revision for greater than or equal to 1.20
12446 + @function name: SDDEVICE_IS_SDIO_REV_GTEQ_1_20
12447 + @prototype: BOOL SDDEVICE_IS_SDIO_REV_GTEQ_1_20(PSDDEVICE pDevice)
12448 + @category: PD_Reference
12450 + @input: pDevice - the target device for this request
12454 + @return: TRUE if the revision is greater than or equal to 1.20
12456 + @notes: Implemented as a macro.
12458 + @see also: SDDEVICE_IS_SD_REV_GTEQ_1_10
12459 + @see also: SDDEVICE_IS_SDIO_REV_GTEQ_1_10
12461 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12462 +#define SDDEVICE_IS_SDIO_REV_GTEQ_1_20(pDev) ((pDev)->pHcd->CardProperties.SDIORevision >= SDIO_REVISION_1_20)
12464 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12465 + @function: Test the SD revision for greater than or equal to 1.10
12467 + @function name: SDDEVICE_IS_SD_REV_GTEQ_1_10
12468 + @prototype: BOOL SDDEVICE_IS_SD_REV_GTEQ_1_10(PSDDEVICE pDevice)
12469 + @category: PD_Reference
12471 + @input: pDevice - the target device for this request
12475 + @return: TRUE if the revision is greater than or equal to 1.10
12477 + @notes: Implemented as a macro.
12479 + @see also: SDDEVICE_IS_SDIO_REV_GTEQ_1_10
12480 + @see also: SDDEVICE_IS_MMC_REV_GTEQ_4_0
12482 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12483 +#define SDDEVICE_IS_SD_REV_GTEQ_1_10(pDev) ((pDev)->pHcd->CardProperties.SD_MMC_Revision >= SD_REVISION_1_10)
12485 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12486 + @function: Test the MMC revision for greater than or equal to 4.0
12488 + @function name: SDDEVICE_IS_MMC_REV_GTEQ_4_0
12489 + @prototype: BOOL SDDEVICE_IS_MMC_REV_GTEQ_4_0(PSDDEVICE pDevice)
12490 + @category: PD_Reference
12492 + @input: pDevice - the target device for this request
12496 + @return: TRUE if the revision is greater than or equal to 4.0
12498 + @notes: Implemented as a macro.
12500 + @see also: SDDEVICE_IS_SDIO_REV_GTEQ_1_10
12501 + @see also: SDDEVICE_IS_SD_REV_GTEQ_1_10
12503 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12504 +#define SDDEVICE_IS_MMC_REV_GTEQ_4_0(pDev) ((pDev)->pHcd->CardProperties.SD_MMC_Revision >= MMC_REVISION_4_0)
12506 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12507 + @function: Test for write protect enabled
12509 + @function name: SDDEVICE_IS_CARD_WP_ON
12510 + @prototype: BOOL SDDEVICE_IS_CARD_WP_ON(PSDDEVICE pDevice)
12511 + @category: PD_Reference
12513 + @input: pDevice - the target device for this request
12517 + @return: TRUE if device is write protected.
12519 + @notes: Implemented as a macro.
12521 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12522 +#define SDDEVICE_IS_CARD_WP_ON(pDev) ((pDev)->pHcd->CardProperties.Flags & CARD_SD_WP)
12525 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12526 + @function: Get the device's manufacturer specific ID
12528 + @function name: SDDEVICE_GET_SDIO_MANFID
12529 + @prototype: UINT16 SDDEVICE_GET_SDIO_MANFID(PSDDEVICE pDevice)
12530 + @category: PD_Reference
12532 + @input: pDevice - the target device for this request
12536 + @return: function number
12538 + @notes: Implemented as a macro.
12540 + @see also: SDDEVICE_GET_SDIO_MANFCODE
12542 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12543 +#define SDDEVICE_GET_SDIO_MANFID(pDev) (pDev)->pId[0].SDIO_ManufacturerID
12545 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12546 + @function: Get the device's manufacturer code
12548 + @function name: SDDEVICE_GET_SDIO_MANFCODE
12549 + @prototype: UINT16 SDDEVICE_GET_SDIO_MANFCODE(PSDDEVICE pDevice)
12550 + @category: PD_Reference
12552 + @input: pDevice - the target device for this request
12556 + @return: function number
12558 + @notes: Implemented as a macro.
12560 + @see also: SDDEVICE_GET_SDIO_MANFID
12562 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12563 +#define SDDEVICE_GET_SDIO_MANFCODE(pDev) (pDev)->pId[0].SDIO_ManufacturerCode
12565 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12566 + @function: Get the device's function number
12568 + @function name: SDDEVICE_GET_SDIO_FUNCNO
12569 + @prototype: UINT8 SDDEVICE_GET_SDIO_FUNCNO(PSDDEVICE pDevice)
12570 + @category: PD_Reference
12572 + @input: pDevice - the target device for this request
12576 + @return: function number
12578 + @notes: Implemented as a macro.
12580 + @see also: SDDEVICE_GET_SDIO_FUNC_CLASS
12582 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12583 +#define SDDEVICE_GET_SDIO_FUNCNO(pDev) (pDev)->pId[0].SDIO_FunctionNo
12585 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12586 + @function: Get the functions's class
12588 + @function name: SDDEVICE_GET_SDIO_FUNC_CLASS
12589 + @prototype: UINT8 SDDEVICE_GET_SDIO_FUNC_CLASS(PSDDEVICE pDevice)
12590 + @category: PD_Reference
12592 + @input: pDevice - the target device for this request
12596 + @return: class number
12598 + @notes: Implemented as a macro.
12600 + @see also: SDDEVICE_GET_SDIO_FUNCNO
12602 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12603 +#define SDDEVICE_GET_SDIO_FUNC_CLASS(pDev) (pDev)->pId[0].SDIO_FunctionClass
12605 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12606 + @function: Get the functions's Card Information Structure pointer
12608 + @function name: SDDEVICE_GET_SDIO_FUNC_CISPTR
12609 + @prototype: UINT32 SDDEVICE_GET_SDIO_FUNC_CISPTR(PSDDEVICE pDevice)
12610 + @category: PD_Reference
12612 + @input: pDevice - the target device for this request
12616 + @return: CIS offset
12618 + @notes: Implemented as a macro.
12620 + @see also: SDDEVICE_GET_SDIO_FUNC_CSAPTR
12621 + @see also: SDDEVICE_GET_SDIO_COMMON_CISPTR
12623 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12624 +#define SDDEVICE_GET_SDIO_FUNC_CISPTR(pDev)(pDev)->DeviceInfo.AsSDIOInfo.FunctionCISPtr
12626 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12627 + @function: Get the functions's Code Stoarge Area pointer
12629 + @function name: SDDEVICE_GET_SDIO_FUNC_CSAPTR
12630 + @prototype: UINT32 SDDEVICE_GET_SDIO_FUNC_CSAPTR(PSDDEVICE pDevice)
12631 + @category: PD_Reference
12633 + @input: pDevice - the target device for this request
12637 + @return: CSA offset
12639 + @notes: Implemented as a macro.
12641 + @see also: SDDEVICE_GET_SDIO_FUNC_CISPTR
12643 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12644 +#define SDDEVICE_GET_SDIO_FUNC_CSAPTR(pDev)(pDev)->DeviceInfo.AsSDIOInfo.FunctionCSAPtr
12646 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12647 + @function: Get the functions's maximum reported block size
12649 + @function name: SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE
12650 + @prototype: UINT16 SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(PSDDEVICE pDevice)
12651 + @category: PD_Reference
12653 + @input: pDevice - the target device for this request
12657 + @return: block size
12659 + @notes: Implemented as a macro.
12663 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12664 +#define SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(pDev) (pDev)->DeviceInfo.AsSDIOInfo.FunctionMaxBlockSize
12666 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12667 + @function: Get the common Card Information Structure pointer
12669 + @function name: SDDEVICE_GET_SDIO_COMMON_CISPTR
12670 + @prototype: UINT32 SDDEVICE_GET_SDIO_COMMON_CISPTR(PSDDEVICE pDevice)
12671 + @category: PD_Reference
12673 + @input: pDevice - the target device for this request
12677 + @return: Common CIS Address (in SDIO address space)
12679 + @notes: Implemented as a macro.
12681 + @see also: SDDEVICE_GET_SDIO_FUNC_CSAPTR
12683 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12684 +#define SDDEVICE_GET_SDIO_COMMON_CISPTR(pDev) (pDev)->pHcd->CardProperties.CommonCISPtr
12686 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12687 + @function: Get the card capabilities
12689 + @function name: SDDEVICE_GET_SDIO_CARD_CAPS
12690 + @prototype: UINT8 SDDEVICE_GET_SDIO_CARD_CAPS(PSDDEVICE pDevice)
12691 + @category: PD_Reference
12693 + @input: pDevice - the target device for this request
12697 + @return: 8-bit card capabilities register
12699 + @notes: Implemented as a macro. Refer to SDIO spec for decoding.
12701 + @see also: SDDEVICE_GET_CARD_FLAGS
12702 + @see also: SDDEVICE_GET_SDIOCARD_CAPS
12704 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12705 +#define SDDEVICE_GET_SDIO_CARD_CAPS(pDev) (pDev)->pHcd->CardProperties.SDIOCaps
12707 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12708 + @function: Get the card flags
12710 + @function name: SDDEVICE_GET_CARD_FLAGS
12711 + @prototype: CARD_INFO_FLAGS SDDEVICE_GET_CARD_FLAGS(PSDDEVICE pDevice)
12712 + @category: PD_Reference
12714 + @input: pDevice - the target device for this request
12720 + @notes: Implemented as a macro.
12722 + @example: Get card type:
12723 + CARD_INFO_FLAGS flags;
12724 + flags = SDDEVICE_GET_CARD_FLAGS(pDevice);
12725 + switch(GET_CARD_TYPE(flags)) {
12726 + case CARD_MMC: // Multi-media card
12728 + case CARD_SD: // SD-Memory present
12730 + case CARD_SDIO: // SDIO card present
12732 + case CARD_COMBO: //SDIO card with SD
12735 + if (flags & CARD_SD_WP) {
12736 + ...SD write protect on
12739 + @see also: SDDEVICE_GET_SDIO_CARD_CAPS
12741 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12742 +#define SDDEVICE_GET_CARD_FLAGS(pDev) (pDev)->pHcd->CardProperties.Flags
12744 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12745 + @function: Get the Relative Card Address register
12747 + @function name: SDDEVICE_GET_CARD_RCA
12748 + @prototype: UINT16 SDDEVICE_GET_CARD_RCA(PSDDEVICE pDevice)
12749 + @category: PD_Reference
12751 + @input: pDevice - the target device for this request
12755 + @return: register address
12757 + @notes: Implemented as a macro. Refer to SDIO spec for decoding.
12759 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12760 +#define SDDEVICE_GET_CARD_RCA(pDev) (pDev)->pHcd->CardProperties.RCA
12762 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12763 + @function: Get operational bus clock
12765 + @function name: SDDEVICE_GET_OPER_CLOCK
12766 + @prototype: SD_BUSCLOCK_RATE SDDEVICE_GET_OPER_CLOCK(PSDDEVICE pDevice)
12767 + @category: PD_Reference
12769 + @input: pDevice - the target device for this request
12773 + @return: clock rate
12775 + @notes: Implemented as a macro. Returns the current bus clock rate.
12776 + This may be lower than reported by the card due to Host Controller,
12777 + Bus driver, or power management limitations.
12779 + @see also: SDDEVICE_GET_MAX_CLOCK
12781 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12782 +#define SDDEVICE_GET_OPER_CLOCK(pDev) (pDev)->pHcd->CardProperties.OperBusClock
12784 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12785 + @function: Get maximum bus clock
12787 + @function name: SDDEVICE_GET_MAX_CLOCK
12788 + @prototype: SD_BUSCLOCK_RATE SDDEVICE_GET_MAX_CLOCK(PSDDEVICE pDevice)
12789 + @category: PD_Reference
12791 + @input: pDevice - the target device for this request
12795 + @return: clock rate
12797 + @notes: To obtain the current maximum clock rate use SDDEVICE_GET_OPER_CLOCK().
12798 + This rate my be lower than the host controllers maximum obtained using
12799 + SDDEVICE_GET_MAX_CLOCK().
12801 + @see also: SDDEVICE_GET_OPER_CLOCK
12803 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12804 +#define SDDEVICE_GET_MAX_CLOCK(pDev) (pDev)->pHcd->MaxClockRate
12806 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12807 + @function: Get operational maximum block length.
12809 + @function name: SDDEVICE_GET_OPER_BLOCK_LEN
12810 + @prototype: UINT16 SDDEVICE_GET_OPER_BLOCK_LEN(PSDDEVICE pDevice)
12811 + @category: PD_Reference
12813 + @input: pDevice - the target device for this request
12817 + @return: block size in bytes
12819 + @notes: Implemented as a macro. Returns the maximum current block length.
12820 + This may be lower than reported by the card due to Host Controller,
12821 + Bus driver, or power management limitations.
12823 + @see also: SDDEVICE_GET_MAX_BLOCK_LEN
12825 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12826 +#define SDDEVICE_GET_OPER_BLOCK_LEN(pDev) (pDev)->pHcd->CardProperties.OperBlockLenLimit
12828 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12829 + @function: Get maximum block length.
12831 + @function name: SDDEVICE_GET_MAX_BLOCK_LEN
12832 + @prototype: UINT16 SDDEVICE_GET_MAX_BLOCK_LEN(PSDDEVICE pDevice)
12833 + @category: PD_Reference
12835 + @input: pDevice - the target device for this request
12839 + @return: block size in bytes
12841 + @notes: Implemented as a macro. Use SDDEVICE_GET_OPER_BLOCK_LEN to obtain
12842 + the current block length.
12844 + @see also: SDDEVICE_GET_OPER_BLOCK_LEN
12846 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12847 +#define SDDEVICE_GET_MAX_BLOCK_LEN(pDev) (pDev)->pHcd->MaxBytesPerBlock
12849 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12850 + @function: Get operational maximum block count.
12852 + @function name: SDDEVICE_GET_OPER_BLOCKS
12853 + @prototype: UINT16 SDDEVICE_GET_OPER_BLOCKS(PSDDEVICE pDevice)
12854 + @category: PD_Reference
12856 + @input: pDevice - the target device for this request
12860 + @return: maximum number of blocks per transaction.
12862 + @notes: Implemented as a macro. Returns the maximum current block count.
12863 + This may be lower than reported by the card due to Host Controller,
12864 + Bus driver, or power management limitations.
12866 + @see also: SDDEVICE_GET_MAX_BLOCK_LEN
12868 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12869 +#define SDDEVICE_GET_OPER_BLOCKS(pDev) (pDev)->pHcd->CardProperties.OperBlockCountLimit
12871 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12872 + @function: Get maximum block count.
12874 + @function name: SDDEVICE_GET_MAX_BLOCKS
12875 + @prototype: UINT16 SDDEVICE_GET_MAX_BLOCKS(PSDDEVICE pDevice)
12876 + @category: PD_Reference
12878 + @input: pDevice - the target device for this request
12882 + @return: maximum number of blocks per transaction.
12884 + @notes: Implemented as a macro. Use SDDEVICE_GET_OPER_BLOCKS to obtain
12885 + the current block count.
12887 + @see also: SDDEVICE_GET_OPER_BLOCKS
12889 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12890 +#define SDDEVICE_GET_MAX_BLOCKS(pDev) (pDev)->pHcd->MaxBlocksPerTrans
12892 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12893 + @function: Get applied slot voltage
12895 + @function name: SDDEVICE_GET_SLOT_VOLTAGE_MASK
12896 + @prototype: SLOT_VOLTAGE_MASK SDDEVICE_GET_SLOT_VOLTAGE_MASK(PSDDEVICE pDevice)
12897 + @category: PD_Reference
12899 + @input: pDevice - the target device for this request
12903 + @return: slot voltage mask
12905 + @notes: This function returns the applied voltage on the slot. The voltage value is a
12906 + mask having the following values:
12914 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12915 +#define SDDEVICE_GET_SLOT_VOLTAGE_MASK(pDev) (pDev)->pHcd->CardProperties.CardVoltage
12917 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12918 + @function: Get the Card Specific Data Register.
12920 + @function name: SDDEVICE_GET_CARDCSD
12921 + @prototype: PUINT8 SDDEVICE_GET_CARDCSD(PSDDEVICE pDevice)
12922 + @category: PD_Reference
12924 + @input: pDevice - the target device for this request
12928 + @return: UINT8 CardCSD[MAX_CARD_RESPONSE_BYTES] array of CSD data.
12930 + @notes: Implemented as a macro.
12932 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12933 +#define SDDEVICE_GET_CARDCSD(pDev) (pDev)->pHcd->CardProperties.CardCSD
12935 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12936 + @function: Get the bus mode flags
12938 + @function name: SDDEVICE_GET_BUSMODE_FLAGS
12939 + @prototype: SD_BUSMODE_FLAGS SDDEVICE_GET_BUSMODE_FLAGS(PSDDEVICE pDevice)
12940 + @category: PD_Reference
12942 + @input: pDevice - the target device for this request
12948 + @notes: Implemented as a macro. This function returns the raw bus mode flags. This
12949 + is useful for function drivers that wish to override the bus clock without
12950 + modifying the current bus mode.
12952 + @see also: SDDEVICE_GET_BUSWIDTH
12953 + @see also: SDCONFIG_BUS_MODE_CTRL
12955 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12956 +#define SDDEVICE_GET_BUSMODE_FLAGS(pDev) (pDev)->pHcd->CardProperties.BusMode
12959 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12960 + @function: Get the bus width.
12962 + @function name: SDDEVICE_GET_BUSWIDTH
12963 + @prototype: UINT8 SDDEVICE_GET_BUSWIDTH(PSDDEVICE pDevice)
12964 + @category: PD_Reference
12966 + @input: pDevice - the target device for this request
12970 + @return: bus width: SDCONFIG_BUS_WIDTH_SPI, SDCONFIG_BUS_WIDTH_1_BIT, SDCONFIG_BUS_WIDTH_4_BIT
12972 + @notes: Implemented as a macro.
12974 + @see also: SDDEVICE_IS_BUSMODE_SPI
12976 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12977 +#define SDDEVICE_GET_BUSWIDTH(pDev) SDCONFIG_GET_BUSWIDTH((pDev)->pHcd->CardProperties.BusMode)
12979 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12980 + @function: Is bus in SPI mode.
12982 + @function name: SDDEVICE_IS_BUSMODE_SPI
12983 + @prototype: BOOL SDDEVICE_IS_BUSMODE_SPI(PSDDEVICE pDevice)
12984 + @category: PD_Reference
12986 + @input: pDevice - the target device for this request
12990 + @return: TRUE, SPI mode.
12992 + @notes: Implemented as a macro.
12994 + @see also: SDDEVICE_GET_BUSWIDTH
12996 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12997 +#define SDDEVICE_IS_BUSMODE_SPI(pDev) (SDDEVICE_GET_BUSWIDTH(pDev) == SDCONFIG_BUS_WIDTH_SPI)
12999 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13000 + @function: Send a request to a device.
13002 + @function name: SDDEVICE_CALL_REQUEST_FUNC
13003 + @prototype: SDIO_STATUS SDDEVICE_CALL_REQUEST_FUNC(PSDDEVICE pDevice, PSDREQUEST pRequest)
13004 + @category: PD_Reference
13006 + @input: pDevice - the target device for this request
13007 + @input: pRequest - the request to be sent
13011 + @return: SDIO_STATUS
13013 + @notes: Sends a request to the specified device. If the request is successfully sent, then
13014 + the response flags can be checked to detemine the result of the request.
13016 + @example: Example of sending a request to a device:
13017 + PSDREQUEST pReq = NULL;
13018 + //allocate a request
13019 + pReq = SDDeviceAllocRequest(pDevice);
13020 + if (NULL == pReq) {
13021 + return SDIO_STATUS_NO_RESOURCES;
13023 + //initialize the request
13024 + SDLIB_SetupCMD52Request(FuncNo, Address, Write, *pData, pReq);
13025 + //send the request to the target
13026 + status = SDDEVICE_CALL_REQUEST_FUNC(pDevice,pReq);
13027 + if (!SDIO_SUCCESS(status)) {
13030 + //check the request response (based on the request type)
13031 + if (SD_R5_GET_RESP_FLAGS(pReq->Response) & SD_R5_ERRORS) {
13035 + // store the byte
13036 + *pData = SD_R5_GET_READ_DATA(pReq->Response);
13038 + //free the request
13039 + SDDeviceFreeRequest(pDevice,pReq);
13042 + @see also: SDDeviceAllocRequest
13043 + @see also: SDDEVICE_CALL_CONFIG_FUNC
13045 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13046 +#define SDDEVICE_CALL_REQUEST_FUNC(pDev,pReq) (pDev)->pRequest((pDev),(pReq))
13048 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13049 + @function: Send configuration to a device.
13051 + @function name: SDDEVICE_CALL_CONFIG_FUNC
13052 + @prototype: SDIO_STATUS SDDEVICE_CALL_CONFIG_FUNC(PSDDEVICE pDevice, PSDCONFIG pConfigure)
13053 + @category: PD_Reference
13055 + @input: pDevice - the target device for this request
13056 + @input: pConfigure - configuration request
13060 + @return: SDIO_STATUS
13062 + @notes: Sends a configuration request to the specified device.
13064 + @example: Example of sending a request to a device:
13065 + SDCONFIG configHdr;
13066 + SDCONFIG_FUNC_ENABLE_DISABLE_DATA fData;
13067 + fData.EnableFlags = SDCONFIG_ENABLE_FUNC;
13068 + fData.TimeOut = 500;
13069 + SET_SDCONFIG_CMD_INFO(&configHdr, SDCONFIG_FUNC_ENABLE_DISABLE, fData, sizeof(fData));
13070 + return SDDEVICE_CALL_CONFIG_FUNC(pDevice, &configHdr);
13072 + @see also: SDLIB_IssueConfig
13074 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13075 +#define SDDEVICE_CALL_CONFIG_FUNC(pDev,pCfg) (pDev)->pConfigure((pDev),(pCfg))
13077 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13078 + @function: Allocate a request structure.
13080 + @function name: SDDeviceAllocRequest
13081 + @prototype: PSDREQUEST SDDeviceAllocRequest(PSDDEVICE pDevice)
13082 + @category: PD_Reference
13084 + @input: pDevice - the target device for this request
13088 + @return: request pointer or NULL if not available.
13090 + @notes: This function must not be called in a non-schedulable (interrupts off) context.
13091 + Allocating memory on some OSes may block.
13093 + @see also: SDDEVICE_CALL_REQUEST_FUNC
13094 + @see also: SDDeviceFreeRequest
13096 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13097 +#define SDDeviceAllocRequest(pDev) (pDev)->AllocRequest((pDev))
13099 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13100 + @function: Free a request structure.
13102 + @function name: SDDeviceFreeRequest
13103 + @prototype: void SDDeviceFreeRequest(PSDDEVICE pDevice, PSDREQUEST pRequest)
13104 + @category: PD_Reference
13106 + @input: pDevice - the target device for this request
13107 + @input: pRequest - request allocated by SDDeviceAllocRequest().
13113 + @notes: This function must not be called in a non-schedulable (interrupts off) context.
13114 + Freeing memory on some OSes may block.
13116 + @see also: SDDEVICE_CALL_REQUEST_FUNC
13117 + @see also: SDDeviceAllocRequest
13119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13120 +#define SDDeviceFreeRequest(pDev,pReq) (pDev)->FreeRequest((pDev),pReq)
13122 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13123 + @function: Register an interrupt handler for a device.
13125 + @function name: SDDEVICE_SET_IRQ_HANDLER
13126 + @prototype: void SDDEVICE_SET_IRQ_HANDLER(PSDDEVICE pDevice,
13127 + void (*pIrqFunction)(PVOID pContext),
13129 + @category: PD_Reference
13131 + @input: pDevice - the target device for this request
13132 + @input: pIrqFunction - the interrupt function to execute.
13133 + @input: pContext - context value passed into interrupt routine.
13139 + @notes: The registered routine will be called upon each card interrupt.
13140 + The interrupt function should acknowledge the interrupt when it is
13141 + ready to handle more interrupts using:
13142 + SDLIB_IssueConfig(pDevice, SDCONFIG_FUNC_ACK_IRQ, NULL, 0);
13143 + The interrupt handler can perform synchronous request calls.
13145 + @see also: SDDEVICE_SET_ASYNC_IRQ_HANDLER
13147 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13148 +#define SDDEVICE_SET_IRQ_HANDLER(pDev,pFn,pContext) \
13150 + (pDev)->pIrqFunction = (pFn); \
13151 + (pDev)->IrqContext = (PVOID)(pContext); \
13154 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13155 + @function: Register an asynchronous interrupt handler for a device.
13157 + @function name: SDDEVICE_SET_ASYNC_IRQ_HANDLER
13158 + @prototype: void SDDEVICE_SET_ASYNC_IRQ_HANDLER(PSDDEVICE pDevice,
13159 + void (*pIrqAsyncFunction)(PVOID pContext),
13161 + @category: PD_Reference
13163 + @input: pDevice - the target device for this request
13164 + @input: pIrqAsyncFunction - the interrupt function to execute.
13165 + @input: pContext - context value passed into interrupt routine.
13171 + @notes: The registered routine will be called upon each card interrupt.
13172 + The interrupt function should acknowledge the interrupt when it is
13173 + ready to handle more interrupts using:
13174 + SDLIB_IssueConfig(pDevice, SDCONFIG_FUNC_ACK_IRQ, NULL, 0);
13175 + The interrupt handler can not perform any synchronous request calls.
13176 + Using this call provides a faster interrupt dispatch, but limits all
13177 + requests to asynchronous mode.
13179 + @see also: SDDEVICE_SET_IRQ_HANDLER
13181 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13182 +#define SDDEVICE_SET_ASYNC_IRQ_HANDLER(pDev,pFn,pContext) \
13184 + (pDev)->pIrqAsyncFunction = (pFn); \
13185 + (pDev)->IrqAsyncContext = (PVOID)(pContext); \
13188 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13189 + @function: Get the SDIO capabilities rgeister.
13191 + @function name: SDDEVICE_GET_SDIOCARD_CAPS
13192 + @prototype: UINT8 SDDEVICE_GET_SDIOCARD_CAPS(PSDDEVICE pDevice)
13193 + @category: PD_Reference
13195 + @input: pDevice - the target device for this request
13199 + @return: SD capabilities
13201 + @notes: See SD specification for decoding of these capabilities.
13203 + @see also: SDDEVICE_GET_SDIO_CARD_CAPS
13205 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13206 +#define SDDEVICE_GET_SDIOCARD_CAPS(pDev) (pDev)->pHcd->CardProperties.SDIOCaps
13208 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13209 + @function: Get HCD driver name
13211 + @function name: SDDEVICE_GET_HCDNAME
13212 + @prototype: PTEXT SDDEVICE_GET_HCDNAME(PSDDEVICE pDevice)
13213 + @category: PD_Reference
13215 + @input: pDevice - the target device for this request
13219 + @return: pointer to a string containing the name of the underlying HCD
13221 + @notes: Implemented as a macro.
13223 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13224 +#define SDDEVICE_GET_HCDNAME(pDev) (pDev)->pHcd->pName
13227 +#define SDDEVICE_CALL_IRQ_HANDLER(pDev) (pDev)->pIrqFunction((pDev)->IrqContext)
13228 +#define SDDEVICE_CALL_IRQ_ASYNC_HANDLER(pDev) (pDev)->pIrqAsyncFunction((pDev)->IrqAsyncContext)
13231 +#define SDDEVICE_SET_SDIO_FUNCNO(pDev,Num) (pDev)->pId[0].SDIO_FunctionNo = (Num)
13232 +#define SDDEVICE_IS_CARD_REMOVED(pDev) ((pDev)->pHcd->CardProperties.CardState & \
13233 + CARD_STATE_REMOVED)
13236 +typedef enum _SDHCD_IRQ_PROC_STATE {
13238 + SDHCD_IRQ_PENDING = 1,
13239 + SDHCD_IRQ_HELPER = 2
13240 +}SDHCD_IRQ_PROC_STATE, *PSDHCD_IRQ_PROC_STATE;
13242 +/* host controller bus driver registration structure */
13243 +typedef struct _SDHCD {
13244 + CT_VERSION_CODE Version; /* version code of the SDIO stack */
13245 + SDLIST SDList; /* internal use list*/
13246 + PTEXT pName; /* name of registering host/slot driver */
13247 + UINT32 Attributes; /* attributes of host controller */
13248 + UINT16 MaxBytesPerBlock; /* max bytes per block */
13249 + UINT16 MaxBlocksPerTrans; /* max blocks per transaction */
13250 + SD_SLOT_CURRENT MaxSlotCurrent; /* max current per slot in milli-amps */
13251 + UINT8 SlotNumber; /* sequential slot number for this HCD, set by bus driver */
13252 + SD_BUSCLOCK_RATE MaxClockRate; /* max clock rate in hz */
13253 + SLOT_VOLTAGE_MASK SlotVoltageCaps; /* slot voltage capabilities */
13254 + SLOT_VOLTAGE_MASK SlotVoltagePreferred; /* preferred slot voltage */
13255 + PVOID pContext; /* host controller driver use data */
13256 + SDIO_STATUS (*pRequest)(struct _SDHCD *pHcd);
13257 + /* get/set configuration */
13258 + SDIO_STATUS (*pConfigure)(struct _SDHCD *pHcd, PSDCONFIG pConfig);
13259 + /* everything below this line is for bus driver use */
13260 + OS_SEMAPHORE ConfigureOpsSem; /* semaphore to make specific configure ops atomic, internal use */
13261 + OS_CRITICALSECTION HcdCritSection; /* critical section to protect hcd data structures (internal use) */
13262 + SDREQUESTQUEUE RequestQueue; /* request queue, internal use */
13263 + PSDREQUEST pCurrentRequest; /* current request we are working on */
13264 + CARD_PROPERTIES CardProperties; /* properties for the currently inserted card*/
13265 + OSKERNEL_HELPER SDIOIrqHelper; /* synch IRQ helper, internal use */
13266 + SDDEVICE *pPseudoDev; /* pseudo device used for initialization (internal use) */
13267 + UINT8 PendingHelperIrqs; /* IRQ helper pending IRQs */
13268 + UINT8 PendingIrqAcks; /* pending IRQ acks from function drivers */
13269 + UINT8 IrqsEnabled; /* current irq enabled mask */
13270 + SDHCD_IRQ_PROC_STATE IrqProcState; /* irq processing state */
13271 + POS_DEVICE pDevice; /* device registration with base system */
13272 + SD_SLOT_CURRENT SlotCurrentAllocated; /* slot current allocated (internal use ) */
13273 + ATOMIC_FLAGS HcdFlags; /* HCD Flags */
13274 +#define HCD_REQUEST_CALL_BIT 0
13275 +#define HCD_IRQ_NO_PEND_CHECK 1 /* HCD flag to bypass interrupt pending register
13276 + check, typically done on single function cards */
13277 + SDREQUESTQUEUE CompletedRequestQueue; /* completed request queue, internal use */
13278 + PSDDMA_DESCRIPTION pDmaDescription; /* description of HCD's DMA capabilities */
13279 + POS_MODULE pModule; /* OS-specific module information */
13280 + INT Recursion; /* recursion level */
13285 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13286 + @function: Get a pointer to the HCD's DMA description
13288 + @function name: SDGET_DMA_DESCRIPTION
13289 + @prototype: PSDDMA_DESCRIPTION SDGET_DMA_DESCRIPTION(PSDDEVICE pDevice)
13290 + @category: PD_Reference
13292 + @input: pDevice - device structure
13294 + @return: PSDDMA_DESCRIPTION or NULL if no DMA support
13296 + @notes: Implemented as a macro.
13298 + @example: getting the current request:
13299 + PSDDMA_DESCRIPTION pDmaDescrp = SDGET_DMA_DESCRIPTION(pDevice);
13301 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13302 +#define SDGET_DMA_DESCRIPTION(pDevice) (pDevice)->pHcd->pDmaDescription
13305 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13306 + @function: Get the logical slot number the device is assigned to.
13308 + @function name: SDDEVICE_GET_SLOT_NUMBER
13309 + @prototype: UINT8 SDDEVICE_GET_SLOT_NUMBER(PSDDEVICE pDevice)
13310 + @category: PD_Reference
13312 + @input: pDevice - device structure
13314 + @return: unsigned number representing the slot number
13316 + @notes: Implemented as a macro. This value is unique for each physical slot in the system
13317 + and assigned by the bus driver. Devices on a multi-function card will share the same
13320 + @example: getting the slot number:
13321 + UINT8 thisSlot = SDDEVICE_GET_SLOT_NUMBER(pDevice);
13323 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13324 +#define SDDEVICE_GET_SLOT_NUMBER(pDevice) (pDevice)->pHcd->SlotNumber
13326 +/* for function use */
13327 +SDIO_STATUS SDIO_RegisterFunction(PSDFUNCTION pFunction);
13328 +SDIO_STATUS SDIO_UnregisterFunction(PSDFUNCTION pFunction);
13330 +#include "sdio_hcd_defs.h"
13331 +#endif /* __SDIO_BUSDRIVER_H___ */
13332 diff --git a/include/linux/sdio/sdio_hcd_defs.h b/include/linux/sdio/sdio_hcd_defs.h
13333 new file mode 100644
13334 index 0000000..1782469
13336 +++ b/include/linux/sdio/sdio_hcd_defs.h
13338 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13339 +@file: sdio_hcd_defs.h
13341 +@abstract: host controller driver definitions
13343 +@notice: Copyright (c), 2005-2006 Atheros Communications, Inc.
13347 + * This program is free software; you can redistribute it and/or modify
13348 + * it under the terms of the GNU General Public License version 2 as
13349 + * published by the Free Software Foundation;
13351 + * Software distributed under the License is distributed on an "AS
13352 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
13353 + * implied. See the License for the specific language governing
13354 + * rights and limitations under the License.
13356 + * Portions of this code were developed with information supplied from the
13357 + * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply:
13359 + * The following conditions apply to the release of the SD simplified specification (�Simplified
13360 + * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete
13361 + * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided
13362 + * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified
13363 + * Specification may require a license from the SD Card Association or other third parties.
13365 + * The information contained in the Simplified Specification is presented only as a standard
13366 + * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any
13367 + * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for
13368 + * any damages, any infringements of patents or other right of the SD Card Association or any third
13369 + * parties, which may result from its use. No license is granted by implication, estoppel or otherwise
13370 + * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall
13371 + * be construed as an obligation by the SD Card Association to disclose or distribute any technical
13372 + * information, know-how or other confidential information to any third party.
13375 + * The initial developers of the original code are Seung Yi and Paul Lever
13377 + * sdio@atheros.com
13381 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13382 +#ifndef __SDIO_HCD_DEFS_H___
13383 +#define __SDIO_HCD_DEFS_H___
13385 + /* write protect switch position data */
13386 +typedef UINT8 SDCONFIG_WP_VALUE;
13388 + /* HC commands */
13389 +#define SDCONFIG_SEND_INIT_CLOCKS (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_PUT | 1)
13390 +#define SDCONFIG_SDIO_INT_CTRL (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_PUT | 2)
13391 +#define SDCONFIG_SDIO_REARM_INT (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_NONE | 3)
13392 +#define SDCONFIG_BUS_MODE_CTRL (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_BOTH | 4)
13393 +#define SDCONFIG_POWER_CTRL (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_PUT | 5)
13394 +#define SDCONFIG_GET_WP (SDCONFIG_FLAGS_HC_CONFIG | SDCONFIG_FLAGS_DATA_GET | 6)
13396 + /* slot init clocks control */
13397 +typedef struct _SDCONFIG_INIT_CLOCKS_DATA {
13398 + UINT16 NumberOfClocks; /* number of clocks to issue in the current bus mode*/
13399 +}SDCONFIG_INIT_CLOCKS_DATA, *PSDCONFIG_INIT_CLOCKS_DATA;
13401 +/* slot power control */
13402 +typedef struct _SDCONFIG_POWER_CTRL_DATA {
13403 + BOOL SlotPowerEnable; /* turn on/off slot power */
13404 + SLOT_VOLTAGE_MASK SlotPowerVoltageMask; /* slot power voltage mask */
13405 +}SDCONFIG_POWER_CTRL_DATA, *PSDCONFIG_POWER_CTRL_DATA;
13407 +typedef UINT8 SDIO_IRQ_MODE_FLAGS;
13408 +/* SDIO Interrupt control */
13409 +typedef struct _SDCONFIG_SDIO_INT_CTRL_DATA {
13410 + BOOL SlotIRQEnable; /* turn on/off Slot IRQ detection */
13411 + SDIO_IRQ_MODE_FLAGS IRQDetectMode; /* slot IRQ detect mode , only valid if Enabled = TRUE */
13412 +#define IRQ_DETECT_RAW 0x00
13413 +#define IRQ_DETECT_MULTI_BLK 0x01
13414 +#define IRQ_DETECT_4_BIT 0x02
13415 +#define IRQ_DETECT_1_BIT 0x04
13416 +#define IRQ_DETECT_SPI 0x08
13417 +}SDCONFIG_SDIO_INT_CTRL_DATA, *PSDCONFIG_SDIO_INT_CTRL_DATA;
13420 +#define EVENT_HCD_ATTACH 1
13422 +#define EVENT_HCD_DETACH 2
13423 +/* card slot interrupt */
13424 +#define EVENT_HCD_SDIO_IRQ_PENDING 3
13425 +/* transfer done */
13426 +#define EVENT_HCD_TRANSFER_DONE 4
13427 +/* (internal use only) */
13428 +#define EVENT_HCD_CD_POLLING 5
13430 +#define EVENT_HCD_NOP 0
13432 +/* attrib_flags */
13433 +#define SDHCD_ATTRIB_SUPPORTS_POWER 0x0001 /* host controller driver supports power managment */
13434 +#define SDHCD_ATTRIB_BUS_1BIT 0x0002 /* SD Native 1 - bit mode */
13435 +#define SDHCD_ATTRIB_BUS_4BIT 0x0004 /* SD Native 4 - bit mode */
13436 +#define SDHCD_ATTRIB_BUS_SPI 0x0008 /* SPI mode capable */
13437 +#define SDHCD_ATTRIB_READ_WAIT 0x0010 /* read wait supported (SD-only) */
13438 +#define SDHCD_ATTRIB_MULTI_BLK_IRQ 0x0020 /* interrupts between multi-block capable (SD-only) */
13439 +#define SDHCD_ATTRIB_BUS_MMC8BIT 0x0040 /* MMC 8-bit */
13440 +#define SDHCD_ATTRIB_SLOT_POLLING 0x0080 /* requires slot polling for Card Detect */
13441 +#define SDHCD_ATTRIB_POWER_SWITCH 0x0100 /* host has power switch control, must be set if SPI
13442 + mode can be switched to 1 or 4 bit mode */
13443 +#define SDHCD_ATTRIB_NO_SPI_CRC 0x0200 /* when in SPI mode,
13444 + host wants to run without SPI CRC */
13445 +#define SDHCD_ATTRIB_AUTO_CMD12 0x0400 /* host controller supports auto CMD12 */
13446 +#define SDHCD_ATTRIB_NO_4BIT_IRQ 0x0800 /* host controller does not support 4 bit IRQ mode*/
13447 +#define SDHCD_ATTRIB_RAW_MODE 0x1000 /* host controller is a raw mode hcd*/
13448 +#define SDHCD_ATTRIB_SD_HIGH_SPEED 0x2000 /* host controller supports SD high speed interface */
13449 +#define SDHCD_ATTRIB_MMC_HIGH_SPEED 0x4000 /* host controller supports MMC high speed interface */
13451 +#define IS_CARD_PRESENT(pHcd) ((pHcd)->CardProperties.Flags & CARD_TYPE_MASK)
13452 +#define SET_CURRENT_REQUEST(pHcd,Req) (pHcd)->pCurrentRequest = (Req)
13453 +#define IS_HCD_RAW(pHcd) ((pHcd)->Attributes & SDHCD_ATTRIB_RAW_MODE)
13454 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13455 + @function: Get a pointer to the current bus request for a host controller
13457 + @function name: GET_CURRENT_REQUEST
13458 + @prototype: PSDREQUEST GET_CURRENT_REQUEST (PSDHCD pHcd)
13459 + @category: HD_Reference
13461 + @input: pHcd - host structure
13463 + @return: current SD/SDIO bus request being worked on
13465 + @notes: Implemented as a macro. This macro returns the current SD request that is
13468 + @example: getting the current request:
13469 + pReq = GET_CURRENT_REQUEST(&pHct->Hcd);
13471 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13472 +#define GET_CURRENT_REQUEST(pHcd) (pHcd)->pCurrentRequest
13473 +#define GET_CURRENT_BUS_WIDTH(pHcd) SDCONFIG_GET_BUSWIDTH((pHcd)->CardProperties.BusMode)
13475 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13476 + @function: Get host controller's current operational bus clock
13478 + @function name: SDHCD_GET_OPER_CLOCK
13479 + @prototype: SD_BUSCLOCK_RATE SDHCD_GET_OPER_CLOCK(PSDHCD pHcd)
13480 + @category: HD_Reference
13482 + @input: pHcd - the registered host structure
13486 + @return: clock rate
13488 + @notes: Implemented as a macro. Returns the current bus clock rate.
13490 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13491 +#define SDHCD_GET_OPER_CLOCK(pHcd) (pHcd)->CardProperties.OperBusClock
13492 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13493 + @function: Is host controller operating in SPI mode
13495 + @function name: IS_HCD_BUS_MODE_SPI
13496 + @prototype: BOOL IS_HCD_BUS_MODE_SPI (PSDHCD pHcd)
13497 + @category: HD_Reference
13499 + @input: pHcd - host structure
13501 + @return: TRUE if in SPI mode
13503 + @notes: Implemented as a macro. Host controllers that operate in SPI mode
13504 + dynamically can use this macro to check for SPI operation.
13506 + @example: testing for SPI mode:
13507 + if (IS_HCD_BUS_MODE_SPI(&pHct->Hcd)) {
13511 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13512 +#define IS_HCD_BUS_MODE_SPI(pHcd) (GET_CURRENT_BUS_WIDTH(pHcd) == SDCONFIG_BUS_WIDTH_SPI)
13514 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13515 + @function: Is host controller using SPI in non-CRC mode
13517 + @function name: IS_HCD_BUS_MODE_SPI_NO_CRC
13518 + @prototype: BOOL IS_HCD_BUS_MODE_SPI_NO_CRC(PSDHCD pHcd)
13519 + @category: HD_Reference
13521 + @input: pHcd - host structure
13523 + @return: TRUE if CRC mode is off
13525 + @notes: Implemented as a macro. SPI-capable cards and systems can operate in
13526 + non-CRC protected mode. In this mode the host controller should ignore
13527 + CRC fields and/or disable CRC generation when issuing command or data
13528 + packets. This option is useful for software based SPI mode where CRC
13529 + should be turned off in order to reduce processing overhead.
13531 + @example: test for non-CRC SPI mode:
13532 + if (IS_HCD_BUS_MODE_SPI_NO_CRC(&pHct->Hcd)) {
13533 + .. disable CRC checking in hardware.
13536 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13537 +#define IS_HCD_BUS_MODE_SPI_NO_CRC(pHcd) ((pHcd)->CardProperties.BusMode & \
13538 + SDCONFIG_BUS_MODE_SPI_NO_CRC)
13540 +typedef UINT8 SDHCD_RESPONSE_CHECK_MODE;
13541 +/* have SDIO core check the response token and see if it is okay to continue with
13542 + * the data portion */
13543 +#define SDHCD_CHECK_DATA_TRANS_OK 0x01
13544 +/* have SDIO core check the SPI token received */
13545 +#define SDHCD_CHECK_SPI_TOKEN 0x02
13549 +SDIO_STATUS SDIO_RegisterHostController(PSDHCD pHcd);
13550 +SDIO_STATUS SDIO_UnregisterHostController(PSDHCD pHcd);
13551 +SDIO_STATUS SDIO_HandleHcdEvent(PSDHCD pHcd, HCD_EVENT Event);
13552 +SDIO_STATUS SDIO_CheckResponse(PSDHCD pHcd, PSDREQUEST pReq, SDHCD_RESPONSE_CHECK_MODE CheckMode);
13553 +SDIO_STATUS SDIO_BusAddOSDevice(PSDDMA_DESCRIPTION pDma, POS_PNPDRIVER pDriver, POS_PNPDEVICE pDevice);
13554 +void SDIO_BusRemoveOSDevice(POS_PNPDRIVER pDriver, POS_PNPDEVICE pDevice);
13556 +#endif /* __SDIO_BUSDRIVER_H___ */
13557 diff --git a/include/linux/sdio/sdio_lib.h b/include/linux/sdio/sdio_lib.h
13558 new file mode 100644
13559 index 0000000..ac0cbd7
13561 +++ b/include/linux/sdio/sdio_lib.h
13563 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13566 +@abstract: SDIO Library include
13570 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
13574 + * This program is free software; you can redistribute it and/or modify
13575 + * it under the terms of the GNU General Public License version 2 as
13576 + * published by the Free Software Foundation;
13578 + * Software distributed under the License is distributed on an "AS
13579 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
13580 + * implied. See the License for the specific language governing
13581 + * rights and limitations under the License.
13583 + * Portions of this code were developed with information supplied from the
13584 + * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply:
13586 + * The following conditions apply to the release of the SD simplified specification (�Simplified
13587 + * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete
13588 + * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided
13589 + * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified
13590 + * Specification may require a license from the SD Card Association or other third parties.
13592 + * The information contained in the Simplified Specification is presented only as a standard
13593 + * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any
13594 + * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for
13595 + * any damages, any infringements of patents or other right of the SD Card Association or any third
13596 + * parties, which may result from its use. No license is granted by implication, estoppel or otherwise
13597 + * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall
13598 + * be construed as an obligation by the SD Card Association to disclose or distribute any technical
13599 + * information, know-how or other confidential information to any third party.
13602 + * The initial developers of the original code are Seung Yi and Paul Lever
13604 + * sdio@atheros.com
13608 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13609 +#ifndef __SDIO_LIB_H___
13610 +#define __SDIO_LIB_H___
13613 +#include "wince\sdio_lib_wince.h"
13614 +#endif /* WINCE */
13616 +#define CMD52_DO_READ FALSE
13617 +#define CMD52_DO_WRITE TRUE
13619 + /* read/write macros to any function */
13620 +#define Cmd52WriteByteFunc(pDev,Func,Address,pValue) \
13621 + SDLIB_IssueCMD52((pDev),(Func),(Address),(pValue),1,CMD52_DO_WRITE)
13622 +#define Cmd52ReadByteFunc(pDev,Func,Address,pValue) \
13623 + SDLIB_IssueCMD52((pDev),(Func),(Address),pValue,1,CMD52_DO_READ)
13624 +#define Cmd52ReadMultipleFunc(pDev,Func, Address, pBuf,length) \
13625 + SDLIB_IssueCMD52((pDev),(Func),(Address),(pBuf),(length),CMD52_DO_READ)
13627 + /* macros to access common registers */
13628 +#define Cmd52WriteByteCommon(pDev, Address, pValue) \
13629 + Cmd52WriteByteFunc((pDev),0,(Address),(pValue))
13630 +#define Cmd52ReadByteCommon(pDev, Address, pValue) \
13631 + Cmd52ReadByteFunc((pDev),0,(Address),(pValue))
13632 +#define Cmd52ReadMultipleCommon(pDev, Address, pBuf,length) \
13633 + Cmd52ReadMultipleFunc((pDev),0,(Address),(pBuf),(length))
13635 +#define SDLIB_SetupCMD52RequestAsync(f,a,w,wd,pR) \
13637 + SDLIB_SetupCMD52Request((f),(a),(w),(wd),(pR)); \
13638 + (pR)->Flags |= SDREQ_FLAGS_TRANS_ASYNC; \
13641 + /* a message block */
13642 +typedef struct _SDMESSAGE_BLOCK {
13643 + SDLIST SDList; /* list entry */
13644 + INT MessageLength; /* number of bytes in this message */
13645 + UINT8 MessageStart[1]; /* message start */
13646 +}SDMESSAGE_BLOCK, *PSDMESSAGE_BLOCK;
13648 + /* message queue */
13649 +typedef struct _SDMESSAGE_QUEUE {
13650 + SDLIST MessageList; /* message list */
13651 + OS_CRITICALSECTION MessageCritSection; /* message semaphore */
13652 + SDLIST FreeMessageList; /* free message list */
13653 + INT MaxMessageLength; /* max message block length */
13654 +}SDMESSAGE_QUEUE, *PSDMESSAGE_QUEUE;
13656 +/* internal library prototypes that can be proxied */
13657 +SDIO_STATUS _SDLIB_IssueCMD52(PSDDEVICE pDevice,
13663 +SDIO_STATUS _SDLIB_FindTuple(PSDDEVICE pDevice,
13665 + UINT32 *pTupleScanAddress,
13668 +SDIO_STATUS _SDLIB_IssueConfig(PSDDEVICE pDevice,
13669 + SDCONFIG_COMMAND Command,
13672 +void _SDLIB_PrintBuffer(PUCHAR pBuffer, INT Length,PTEXT pDescription);
13673 +void _SDLIB_SetupCMD52Request(UINT8 FuncNo,
13677 + PSDREQUEST pRequest);
13678 +SDIO_STATUS _SDLIB_SetFunctionBlockSize(PSDDEVICE pDevice,
13679 + UINT16 BlockSize);
13681 +SDIO_STATUS _SDLIB_GetDefaultOpCurrent(PSDDEVICE pDevice,
13682 + SD_SLOT_CURRENT *pOpCurrent);
13683 +PSDMESSAGE_QUEUE _CreateMessageQueue(INT MaxMessages, INT MaxMessageLength);
13684 +void _DeleteMessageQueue(PSDMESSAGE_QUEUE pQueue);
13685 +SDIO_STATUS _PostMessage(PSDMESSAGE_QUEUE pQueue, PVOID pMessage, INT MessageLength);
13686 +SDIO_STATUS _GetMessage(PSDMESSAGE_QUEUE pQueue, PVOID pData, INT *pBufferLength);
13688 +#ifdef CTSYSTEM_NO_FUNCTION_PROXIES
13689 + /* OS port requires no proxy functions, use methods directly from the library */
13690 +#define SDLIB_IssueCMD52 _SDLIB_IssueCMD52
13691 +#define SDLIB_SetupCMD52Request _SDLIB_SetupCMD52Request
13692 +#define SDLIB_FindTuple _SDLIB_FindTuple
13693 +#define SDLIB_IssueConfig _SDLIB_IssueConfig
13694 +#define SDLIB_SetFunctionBlockSize _SDLIB_SetFunctionBlockSize
13695 +#define SDLIB_GetDefaultOpCurrent _SDLIB_GetDefaultOpCurrent
13696 +#define SDLIB_CreateMessageQueue _CreateMessageQueue
13697 +#define SDLIB_DeleteMessageQueue _DeleteMessageQueue
13698 +#define SDLIB_PostMessage _PostMessage
13699 +#define SDLIB_GetMessage _GetMessage
13700 +#define SDLIB_PrintBuffer _SDLIB_PrintBuffer
13703 +/* proxied versions */
13704 +SDIO_STATUS SDLIB_IssueCMD52(PSDDEVICE pDevice,
13711 +void SDLIB_SetupCMD52Request(UINT8 FuncNo,
13715 + PSDREQUEST pRequest);
13717 +SDIO_STATUS SDLIB_FindTuple(PSDDEVICE pDevice,
13719 + UINT32 *pTupleScanAddress,
13723 +SDIO_STATUS SDLIB_IssueConfig(PSDDEVICE pDevice,
13724 + SDCONFIG_COMMAND Command,
13728 +SDIO_STATUS SDLIB_SetFunctionBlockSize(PSDDEVICE pDevice,
13729 + UINT16 BlockSize);
13731 +void SDLIB_PrintBuffer(PUCHAR pBuffer, INT Length,PTEXT pDescription);
13733 +SDIO_STATUS SDLIB_GetDefaultOpCurrent(PSDDEVICE pDevice, SD_SLOT_CURRENT *pOpCurrent);
13735 +PSDMESSAGE_QUEUE SDLIB_CreateMessageQueue(INT MaxMessages, INT MaxMessageLength);
13737 +void SDLIB_DeleteMessageQueue(PSDMESSAGE_QUEUE pQueue);
13739 +SDIO_STATUS SDLIB_PostMessage(PSDMESSAGE_QUEUE pQueue, PVOID pMessage, INT MessageLength);
13741 +SDIO_STATUS SDLIB_GetMessage(PSDMESSAGE_QUEUE pQueue, PVOID pData, INT *pBufferLength);
13742 +#endif /* CTSYSTEM_NO_FUNCTION_PROXIES */
13745 +SDIO_STATUS SDLIB_OSCreateHelper(POSKERNEL_HELPER pHelper,
13746 + PHELPER_FUNCTION pFunction,
13749 +void SDLIB_OSDeleteHelper(POSKERNEL_HELPER pHelper);
13751 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13752 + @function: Check message queue is empty
13754 + @function name: SDLIB_IsQueueEmpty
13755 + @prototype: BOOL SDLIB_IsQueueEmpty(PSDMESSAGE_QUEUE pQueue)
13756 + @category: Support_Reference
13758 + @input: pQueue - message queue to check
13760 + @return: TRUE if empty else false
13762 + @see also: SDLIB_CreateMessageQueue
13764 + @example: Check message queue :
13765 + if (SDLIB_IsQueueEmpty(pInstance->pQueue)) {
13766 + .. message queue is empty
13768 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13769 +static INLINE BOOL SDLIB_IsQueueEmpty(PSDMESSAGE_QUEUE pQueue) {
13770 + return SDLIST_IS_EMPTY(&pQueue->MessageList);
13774 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13775 + @function: Issue an I/O abort request
13777 + @function name: SDLIB_IssueIOAbort
13778 + @prototype: SDIO_STATUS SDLIB_IssueIOAbort(PSDDEVICE pDevice)
13779 + @category: PD_Reference
13781 + @input: pDevice - the device that is the target of this request
13783 + @return: SDIO_STATUS
13785 + @notes: This procedure can be called to issue an I/O abort request to an I/O function.
13786 + This procedure cannot be used to abort a data (block) transfer already in progress.
13787 + It is intended to be used when a data (block) transfer completes with an error and only if
13788 + the I/O function requires an abort action. Some I/O functions may automatically
13789 + recover from such failures and not require this action. This function issues
13790 + the abort command synchronously and can potentially block.
13791 + If an async request is required, you must allocate a request and use
13792 + SDLIB_SetupIOAbortAsync() to prepare the request.
13794 + @example: Issuing I/O Abort synchronously :
13795 + .. check status from last block operation:
13796 + if (status == SDIO_STATUS_BUS_READ_TIMEOUT) {
13797 + .. on failure, issue I/O abort
13798 + status2 = SDLIB_IssueIOAbort(pDevice);
13800 + Issuing I/O Abort asynchronously:
13801 + ... allocate a request
13802 + ... setup the request:
13803 + SDLIB_SetupIOAbortAsync(pDevice,pReq);
13804 + pReq->pCompletion = myIOAbortCompletion;
13805 + pReq->pCompleteContext = pDevice;
13806 + status = SDDEVICE_CALL_REQUEST_FUNC(pDevice,pReq);
13808 + @see also: SDLIB_SetupIOAbortAsync
13809 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13810 +static INLINE SDIO_STATUS SDLIB_IssueIOAbort(PSDDEVICE pDevice) {
13811 + UINT8 value = SDDEVICE_GET_SDIO_FUNCNO(pDevice);
13812 + return Cmd52WriteByteCommon(pDevice,0x06,&value);
13815 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13816 + @function: Setup an I/O abort request for async operation
13818 + @function name: SDLIB_SetupIOAbortAsync
13819 + @prototype: SDLIB_SetupIOAbortAsync(PSDDEVICE pDevice, PSDREQUEST pRequest)
13820 + @category: PD_Reference
13822 + @input: pDevice - the device that is the target of this request
13823 + pRequest - the request to set up
13825 + @see also: SDLIB_IssueIOAbort
13827 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13828 +#define SDLIB_SetupIOAbortAsync(pDevice, pReq) \
13829 + SDLIB_SetupCMD52RequestAsync(0,0x06,TRUE,SDDEVICE_GET_SDIO_FUNCNO(pDevice),(pReq))
13832 +#endif /* __SDIO_LIB_H___*/
13833 diff --git a/include/linux/sdio/sdlist.h b/include/linux/sdio/sdlist.h
13834 new file mode 100644
13835 index 0000000..dc35e1c
13837 +++ b/include/linux/sdio/sdlist.h
13839 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13842 +@abstract: OS independent list functions
13844 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
13848 + * This program is free software; you can redistribute it and/or modify
13849 + * it under the terms of the GNU General Public License version 2 as
13850 + * published by the Free Software Foundation;
13852 + * Software distributed under the License is distributed on an "AS
13853 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
13854 + * implied. See the License for the specific language governing
13855 + * rights and limitations under the License.
13857 + * Portions of this code were developed with information supplied from the
13858 + * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply:
13860 + * The following conditions apply to the release of the SD simplified specification (�Simplified
13861 + * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete
13862 + * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided
13863 + * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified
13864 + * Specification may require a license from the SD Card Association or other third parties.
13866 + * The information contained in the Simplified Specification is presented only as a standard
13867 + * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any
13868 + * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for
13869 + * any damages, any infringements of patents or other right of the SD Card Association or any third
13870 + * parties, which may result from its use. No license is granted by implication, estoppel or otherwise
13871 + * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall
13872 + * be construed as an obligation by the SD Card Association to disclose or distribute any technical
13873 + * information, know-how or other confidential information to any third party.
13876 + * The initial developers of the original code are Seung Yi and Paul Lever
13878 + * sdio@atheros.com
13882 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13883 +#ifndef __SDLIST_H___
13884 +#define __SDLIST_H___
13886 +/* list functions */
13887 +/* pointers for the list */
13888 +typedef struct _SDLIST {
13889 + struct _SDLIST *pPrev;
13890 + struct _SDLIST *pNext;
13891 +}SDLIST, *PSDLIST;
13893 + * SDLIST_INIT , circular list
13895 +#define SDLIST_INIT(pList)\
13896 + {(pList)->pPrev = pList; (pList)->pNext = pList;}
13897 +#define SDLIST_INIT_DECLARE(List)\
13898 + SDLIST List = {&List, &List}
13901 +#define SDLIST_IS_EMPTY(pList) (((pList)->pPrev == (pList)) && ((pList)->pNext == (pList)))
13902 +#define SDLIST_GET_ITEM_AT_HEAD(pList) (pList)->pNext
13903 +#define SDLIST_GET_ITEM_AT_TAIL(pList) (pList)->pPrev
13905 + * SDITERATE_OVER_LIST pStart is the list, pTemp is a temp list member
13906 + * NOT: do not use this function if the items in the list are deleted inside the
13909 +#define SDITERATE_OVER_LIST(pStart, pTemp) \
13910 + for((pTemp) =(pStart)->pNext; pTemp != (pStart); (pTemp) = (pTemp)->pNext)
13913 +/* safe iterate macro that allows the item to be removed from the list
13914 + * the iteration continues to the next item in the list
13916 +#define SDITERATE_OVER_LIST_ALLOW_REMOVE(pStart,pItem,st,offset) \
13919 + pTemp = (pStart)->pNext; \
13920 + while (pTemp != (pStart)) { \
13921 + (pItem) = CONTAINING_STRUCT(pTemp,st,offset); \
13922 + pTemp = pTemp->pNext; \
13924 +#define SDITERATE_END }}
13927 + * SDListInsertTail - insert pAdd to the end of the list
13929 +static INLINE PSDLIST SDListInsertTail(PSDLIST pList, PSDLIST pAdd) {
13930 + /* this assert catches when an item is added twice */
13931 + DBG_ASSERT(pAdd->pNext != pList);
13932 + /* insert at tail */
13933 + pAdd->pPrev = pList->pPrev;
13934 + pAdd->pNext = pList;
13935 + pList->pPrev->pNext = pAdd;
13936 + pList->pPrev = pAdd;
13941 + * SDListInsertHead - insert pAdd into the head of the list
13943 +static INLINE PSDLIST SDListInsertHead(PSDLIST pList, PSDLIST pAdd) {
13944 + /* this assert catches when an item is added twice */
13945 + DBG_ASSERT(pAdd->pPrev != pList);
13946 + /* insert at head */
13947 + pAdd->pPrev = pList;
13948 + pAdd->pNext = pList->pNext;
13949 + pList->pNext->pPrev = pAdd;
13950 + pList->pNext = pAdd;
13954 +#define SDListAdd(pList,pItem) SDListInsertHead((pList),(pItem))
13956 + * SDListRemove - remove pDel from list
13958 +static INLINE PSDLIST SDListRemove(PSDLIST pDel) {
13959 + pDel->pNext->pPrev = pDel->pPrev;
13960 + pDel->pPrev->pNext = pDel->pNext;
13961 + /* point back to itself just to be safe, incase remove is called again */
13962 + pDel->pNext = pDel;
13963 + pDel->pPrev = pDel;
13968 + * SDListRemoveItemFromHead - get a list item from the head
13970 +static INLINE PSDLIST SDListRemoveItemFromHead(PSDLIST pList) {
13971 + PSDLIST pItem = NULL;
13972 + if (pList->pNext != pList) {
13973 + pItem = pList->pNext;
13974 + /* remove the first item from head */
13975 + SDListRemove(pItem);
13979 +#endif /* __SDLIST_H___ */