add support for target 3c24xx (more known as Openmoko GTA02 "Freerunner") and merge...
[openwrt.git] / target / linux / s3c24xx / patches / 0055-atheros_2_0_sdio_stack.patch.patch
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
5
6 ---
7  arch/arm/Kconfig                                 |    2 +
8  drivers/Kconfig                                  |    2 +
9  drivers/Makefile                                 |    1 +
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
59
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"
65  
66  source "drivers/usb/Kconfig"
67  
68 +source "drivers/sdio/Kconfig"
69 +
70  source "drivers/mmc/Kconfig"
71  
72  source "drivers/leds/Kconfig"
73 diff --git a/drivers/Kconfig b/drivers/Kconfig
74 index 59f33fa..f5900b7 100644
75 --- a/drivers/Kconfig
76 +++ b/drivers/Kconfig
77 @@ -78,6 +78,8 @@ source "drivers/hid/Kconfig"
78  
79  source "drivers/usb/Kconfig"
80  
81 +source "drivers/sdio/Kconfig"
82 +
83  source "drivers/mmc/Kconfig"
84  
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
99 new file mode 100644
100 index 0000000..14bf5e3
101 --- /dev/null
102 +++ b/drivers/sdio/Kconfig
103 @@ -0,0 +1,17 @@
104 +#
105 +# SDIO driver and host controller support
106 +#
107 +
108 +menu "SDIO support"
109 +
110 +config SDIO
111 +        tristate "SDIO support"
112 +        default m
113 +        ---help---
114 +          good luck.
115 +
116 +source "drivers/sdio/hcd/Kconfig"
117 +
118 +source "drivers/sdio/function/Kconfig"
119 +
120 +endmenu
121 diff --git a/drivers/sdio/Makefile b/drivers/sdio/Makefile
122 new file mode 100644
123 index 0000000..f56aa0f
124 --- /dev/null
125 +++ b/drivers/sdio/Makefile
126 @@ -0,0 +1,4 @@
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
132 new file mode 100644
133 index 0000000..ff0e24d
134 --- /dev/null
135 +++ b/drivers/sdio/stack/Makefile
136 @@ -0,0 +1 @@
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
140 new file mode 100644
141 index 0000000..1130e2d
142 --- /dev/null
143 +++ b/drivers/sdio/stack/busdriver/Makefile
144 @@ -0,0 +1,2 @@
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
148 new file mode 100644
149 index 0000000..a85aed1
150 --- /dev/null
151 +++ b/drivers/sdio/stack/busdriver/_busdriver.h
152 @@ -0,0 +1,466 @@
153 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
154 +@file: _busdriver.h
155 +
156 +@abstract: internal include file for busdriver
157 +
158 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
159 +
160 +
161 + *
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;
165 + *
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.
170 + *
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:
173 + *
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.
179 + *   Disclaimers:
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.
188 + *
189 + *
190 + *  The initial developers of the original code are Seung Yi and Paul Lever
191 + *
192 + *  sdio@atheros.com
193 + *
194 + *
195 +
196 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
197 +#ifndef ___BUSDRIVER_H___
198 +#define ___BUSDRIVER_H___
199 +#include <linux/sdio/sdio_lib.h>
200 +
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)
205 +
206 +#define SDIOBUS_CD_TIMER_ID 0
207 +
208 +#define SDBUS_MAX_RETRY   3
209 +
210 +/* Notes on list linkages:
211 + *  list heads are held in BDCONTEXT
212 + *  HcdList - SDHCD
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
226 + *
227 + *
228 +*/
229 +
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
244 +
245 +    /* internal signalling item */
246 +typedef struct _SIGNAL_ITEM{
247 +    SDLIST       SDList;        /* list link*/
248 +    OS_SIGNAL    Signal;        /* signal */
249 +}SIGNAL_ITEM, *PSIGNAL_ITEM;
250 +
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;
255 +
256 +/* internal data for bus driver */
257 +typedef struct _BDCONTEXT {
258 +
259 +    /* list of SD requests and signalling semaphores and a semaphore to protect it */
260 +    SDLIST  RequestList;
261 +    SDLIST  SignalList;
262 +    OS_CRITICALSECTION RequestListCritSection;
263 +    /* list of host controller bus drivers, sempahore to protect it */
264 +    SDLIST HcdList;
265 +    OS_SEMAPHORE HcdListSem;
266 +    /* list of inserted devices, semaphore to protect it */
267 +    SDLIST DeviceList;
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;
299 +
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
304 +
305 +#define CLEAR_INTERNAL_REQ_FLAGS(pReq) (pReq)->Flags &= ~(UINT)((SDREQ_FLAGS_RESP_SPI_CONVERTED | \
306 +                                                          SDREQ_FLAGS_FORCE_DEFERRED_COMPLETE))
307 +
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)
311 +
312 +/* macros to remove an item from the head of the queue */
313 +static INLINE PSDREQUEST DequeueRequest(PSDREQUESTQUEUE pRequestQueue) {
314 +    PSDLIST pItem;
315 +    pItem = SDListRemoveItemFromHead(&pRequestQueue->Queue);
316 +    if (pItem != NULL) {
317 +        return CONTAINING_STRUCT(pItem, SDREQUEST, SDList);
318 +    }
319 +    return NULL;
320 +};
321 +
322 +static INLINE SDIO_STATUS InitializeRequestQueue(PSDREQUESTQUEUE pRequestQueue) {
323 +    SDLIST_INIT(&pRequestQueue->Queue);
324 +    MarkQueueNotBusy(pRequestQueue);
325 +    return SDIO_STATUS_SUCCESS;
326 +}
327 +
328 +static INLINE void CleanupRequestQueue(PSDREQUESTQUEUE pRequestQueue) {
329 +
330 +}
331 +
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,
378 +                         PSDREQUEST      pReq);
379 +#define _IssueSimpleBusRequest(pHcd,Cmd,Arg,Flags,pReqToUse) \
380 +          _IssueBusRequestBd((pHcd),(Cmd),(Arg),(Flags),(pReqToUse),NULL,0)
381 +
382 +SDIO_STATUS Do_OS_IncHcdReference(PSDHCD pHcd);
383 +SDIO_STATUS Do_OS_DecHcdReference(PSDHCD pHcd);
384 +SDIO_STATUS TryNoIrqPendingCheck(PSDDEVICE pDev);
385 +
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)))
397 +
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);
403 +    }
404 +    return SDIO_STATUS_SUCCESS;
405 +}
406 +
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);
412 +    }
413 +    return SDIO_STATUS_SUCCESS;
414 +}
415 +
416 +SDIO_STATUS _IssueBusRequestBd(PSDHCD           pHcd,
417 +                               UINT8            Cmd,
418 +                               UINT32           Argument,
419 +                               SDREQUEST_FLAGS  Flags,
420 +                               PSDREQUEST       pReqToUse,
421 +                               PVOID            pData,
422 +                               INT              Length);
423 +
424 +SDIO_STATUS IssueRequestToHCD(PSDHCD pHcd,PSDREQUEST pReq);
425 +
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);
430 +}
431 +
432 +static INLINE SDIO_STATUS CallHcdRequest(PSDHCD pHcd) {
433 +
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;
439 +    }
440 +
441 +    if (ForceAllRequestsAsync()) {
442 +            /* all requests must be completed(indicated) in a separate context */
443 +        pHcd->pCurrentRequest->Flags |= SDREQ_FLAGS_FORCE_DEFERRED_COMPLETE;
444 +    } else {
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)) {
448 +
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;
454 +        }
455 +    }
456 + #if DEBUG
457 +    {
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);
465 +        }
466 +        return status;
467 +    }
468 + #else
469 +    return pHcd->pRequest(pHcd);
470 + #endif
471 +
472 +}
473 +
474 +/* note the caller of this macro must take the HCD lock to protect the count */
475 +#define CHECK_HCD_RECURSE(pHcd,pReq)   \
476 +{                                      \
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; \
482 +    }                                                         \
483 +}
484 +
485 +/* InternalFlags bit number settings */
486 +#define SDBD_INIT        1
487 +#define SDBD_PENDING    15
488 +#define SDBD_ALLOC_IRQ_SAFE     2
489 +
490 +#define SDBD_ALLOC_IRQ_SAFE_MASK (1 << SDBD_ALLOC_IRQ_SAFE)
491 +
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);
500 +    } else {
501 +            /* mark request reusable */
502 +        AtomicTest_Clear(&pReq->InternalFlags, SDBD_PENDING);
503 +    }
504 +}
505 +
506 +THREAD_RETURN CardDetectHelperFunction(POSKERNEL_HELPER pHelper);
507 +THREAD_RETURN SDIOIrqHelperFunction(POSKERNEL_HELPER pHelper);
508 +
509 +void ConvertSPI_Response(PSDREQUEST pReq, UINT8 *pRespBuffer);
510 +
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;
516 +
517 +    if (pHcd != NULL) {
518 +            /* increment HCD reference count to process this HCD message */
519 +        status = OS_IncHcdReference(pHcd);
520 +        if (!SDIO_SUCCESS(status)) {
521 +            return status;
522 +        }
523 +    }
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);
531 +        }
532 +        return status;
533 +    }
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);
537 +};
538 +
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);
553 +}
554 +
555 +/* de-initialize device fields */
556 +static INLINE void DeinitDeviceData(PSDDEVICE pDevice) {
557 +}
558 +
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;
570 +}
571 +
572 +static INLINE SDIO_STATUS _IssueConfig(PSDHCD           pHcd,
573 +                                       SDCONFIG_COMMAND Command,
574 +                                       PVOID            pData,
575 +                                       INT              Length){
576 +    SDCONFIG  configHdr;
577 +    SET_SDCONFIG_CMD_INFO(&configHdr,Command,pData,Length);
578 +    return CALL_HCD_CONFIG(pHcd,&configHdr);
579 +}
580 +
581 +/* prototypes */
582 +#define _AcquireHcdLock(pHcd)CriticalSectionAcquireSyncIrq(&(pHcd)->HcdCritSection)
583 +#define _ReleaseHcdLock(pHcd)CriticalSectionReleaseSyncIrq(&(pHcd)->HcdCritSection)
584 +
585 +#define AcquireHcdLock(pDev) CriticalSectionAcquireSyncIrq(&(pDev)->pHcd->HcdCritSection)
586 +#define ReleaseHcdLock(pDev) CriticalSectionReleaseSyncIrq(&(pDev)->pHcd->HcdCritSection)
587 +
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);
595 +
596 +
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))
601 +
602 +/* CLARIFICATION on SDREQ_FLAGS_PSEUDO and SDREQ_FLAGS_BARRIER flags :
603 + *
604 + * A request marked as PSEUDO is synchronized with bus requests and is not a true request
605 + * that is issued to an HCD.
606 + *
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.
611 + *
612 + *
613 + *
614 + * */
615 +#define SD_PSEUDO_REQ_FLAGS \
616 +      (SDREQ_FLAGS_PSEUDO | SDREQ_FLAGS_BARRIER | SDREQ_FLAGS_TRANS_ASYNC)
617 +
618 +#endif /*___BUSDRIVER_H___*/
619 diff --git a/drivers/sdio/stack/busdriver/sdio_bus.c b/drivers/sdio/stack/busdriver/sdio_bus.c
620 new file mode 100644
621 index 0000000..ffc1e9f
622 --- /dev/null
623 +++ b/drivers/sdio/stack/busdriver/sdio_bus.c
624 @@ -0,0 +1,2120 @@
625 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
626 +@file: sdio_bus.c
627 +
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.
632 +
633 +#notes: this file supports the HCD's and generic functions
634 +
635 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
636 +
637 +
638 + *
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;
642 + *
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.
647 + *
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:
650 + *
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.
656 + *   Disclaimers:
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.
665 + *
666 + *
667 + *  The initial developers of the original code are Seung Yi and Paul Lever
668 + *
669 + *  sdio@atheros.com
670 + *
671 + *
672 +
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"
681 +
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);
688 +
689 +const CT_VERSION_CODE g_Version = CT_SDIO_STACK_VERSION_CODE;
690 +/*
691 + * _SDIO_BusDriverInitialize - call once on driver loading
692 + *
693 +*/
694 +SDIO_STATUS _SDIO_BusDriverInitialize(void)
695 +{
696 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
697 +
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)));
700 +
701 +    DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: enter _SDIO_BusDriverInitialize\n"));
702 +
703 +    do {
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;
709 +            break;
710 +        }
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);
717 +
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;
732 +
733 +            /* get overrides for the defaults */
734 +        status = _SDIO_BusGetDefaultSettings(pBusContext);
735 +        if (!SDIO_SUCCESS(status)) {
736 +            break;
737 +        }
738 +
739 +        pBusContext->MaxRequestAllocations = pBusContext->RequestListSize << 1;
740 +        pBusContext->MaxSignalAllocations = pBusContext->SignalSemListSize << 1;
741 +
742 +        status = CriticalSectionInit(&pBusContext->RequestListCritSection);
743 +        if (!SDIO_SUCCESS(status)) {
744 +            DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't CriticalSectionInit.\n"));
745 +            break;
746 +        }
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"));
750 +            break;
751 +        }
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"));
755 +            break;
756 +        }
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"));
760 +            break;
761 +        }
762 +        status = AllocateBusResources();
763 +        if (!SDIO_SUCCESS(status)) {
764 +            DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't AllocateBusResources.\n"));
765 +            break;
766 +        }
767 +
768 +        pBusContext->InitMask |= RESOURCE_INIT;
769 +
770 +        pBusContext->pCardDetectMsgQueue = SDLIB_CreateMessageQueue(MAX_CARD_DETECT_MSGS,
771 +                                                                   sizeof(HCD_EVENT_MESSAGE));
772 +
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;
776 +            break;
777 +        }
778 +
779 +        status = SDLIB_OSCreateHelper(&pBusContext->CardDetectHelper,
780 +                                      CardDetectHelperFunction,
781 +                                      NULL);
782 +
783 +        if (!SDIO_SUCCESS(status)) {
784 +            DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't OSCreateHelper.\n"));
785 +            break;
786 +        }
787 +
788 +        pBusContext->InitMask |= HELPER_INIT;
789 +
790 +        status = InitializeTimers();
791 +        if (!SDIO_SUCCESS(status)) {
792 +            DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_BusDriverInitialize can't InitializeTimers.\n"));
793 +            break;
794 +        }
795 +        pBusContext->InitMask |= BD_TIMER_INIT;
796 +    } while(FALSE);
797 +
798 +    if (!SDIO_SUCCESS(status)) {
799 +        _SDIO_BusDriverCleanup();
800 +    }
801 +
802 +    return status;
803 +}
804 +
805 +
806 +/*
807 + * _SDIO_BusDriverBusDriverCleanup - call once on driver unloading
808 + *
809 +*/
810 +void _SDIO_BusDriverCleanup(void) {
811 +    DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: _SDIO_BusDriverCleanup\n"));
812 +
813 +    if (pBusContext->InitMask & BD_TIMER_INIT) {
814 +        CleanupTimers();
815 +    }
816 +
817 +    if (pBusContext->InitMask & HELPER_INIT) {
818 +        SDLIB_OSDeleteHelper(&pBusContext->CardDetectHelper);
819 +    }
820 +
821 +    if (pBusContext->pCardDetectMsgQueue != NULL) {
822 +        SDLIB_DeleteMessageQueue(pBusContext->pCardDetectMsgQueue);
823 +        pBusContext->pCardDetectMsgQueue = NULL;
824 +    }
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"));
837 +}
838 +
839 +
840 +/* cleanup hcd */
841 +static void CleanupHcd(PSDHCD pHcd)
842 +{
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;
852 +    }
853 +}
854 +
855 +/* set up the hcd */
856 +static SDIO_STATUS SetupHcd(PSDHCD pHcd)
857 +{
858 +    SDIO_STATUS status;
859 +
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;
867 +
868 +    do {
869 +
870 +        pHcd->pPseudoDev = AllocateDevice(pHcd);
871 +
872 +        if (NULL == pHcd->pPseudoDev) {
873 +            status = SDIO_STATUS_NO_RESOURCES;
874 +            break;
875 +        }
876 +
877 +        ResetHcdState(pHcd);
878 +
879 +        status = SemaphoreInitialize(&pHcd->ConfigureOpsSem,1);
880 +        if (!SDIO_SUCCESS(status)) {
881 +            break;
882 +        }
883 +        status = CriticalSectionInit(&pHcd->HcdCritSection);
884 +        if (!SDIO_SUCCESS(status)) {
885 +            break;
886 +        }
887 +        status = InitializeRequestQueue(&pHcd->RequestQueue);
888 +        if (!SDIO_SUCCESS(status)) {
889 +            break;
890 +        }
891 +        status = InitializeRequestQueue(&pHcd->CompletedRequestQueue);
892 +        if (!SDIO_SUCCESS(status)) {
893 +            break;
894 +        }
895 +            /* create SDIO Irq helper */
896 +        status = SDLIB_OSCreateHelper(&pHcd->SDIOIrqHelper,
897 +                                      SDIOIrqHelperFunction,
898 +                                     (PVOID)pHcd);
899 +    } while(FALSE);
900 +
901 +    if (!SDIO_SUCCESS(status)) {
902 +            /* undo what we did */
903 +        CleanupHcd(pHcd);
904 +    }
905 +    return status;
906 +}
907 +
908 +
909 +/*
910 + * _SDIO_RegisterHostController - register a host controller bus driver
911 + *
912 +*/
913 +
914 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
915 +  @function: Register a host controller driver with the bus driver.
916 +
917 +  @function name: SDIO_RegisterHostController
918 +  @prototype: SDIO_STATUS SDIO_RegisterHostController (PSDHCD pHcd)
919 +  @category: HD_Reference
920 +
921 +  @input:  pHcd - the host controller definition structure.
922 +
923 +  @output: none
924 +
925 +  @return: SDIO_STATUS - SDIO_STATUS_SUCCESS when successful.
926 +
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
934 +          shutting down.
935 +
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
952 +    };
953 +    if (!SDIO_SUCCESS((status = SDIO_RegisterHostController(&Hcd)))) {
954 +         DBG_PRINT(SDDBG_ERROR, ("SDIO HCD - failed to register with host, status =%d\n",
955 +                                    status));
956 +    }
957 +
958 +  @see also: SDIO_UnregisterHostController
959 +
960 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
961 +SDIO_STATUS _SDIO_RegisterHostController(PSDHCD pHcd) {
962 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
963 +
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)));
967 +
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;
973 +    }
974 +        /* setup hcd */
975 +    status = SetupHcd(pHcd);
976 +    if (!SDIO_SUCCESS(status)) {
977 +        return status;
978 +    }
979 +
980 +    do {
981 +        INT slotNumber;
982 +
983 +            /* protect the HCD list */
984 +        if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->HcdListSem)))) {
985 +            break;  /* wait interrupted */
986 +        }
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 */
992 +            slotNumber = 31;
993 +        }
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 */
1000 +        }
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);
1004 +        }
1005 +    } while (FALSE);
1006 +
1007 +    if (!SDIO_SUCCESS(status)) {
1008 +       CleanupHcd(pHcd);
1009 +       DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_RegisterHostController, error 0x%X.\n", status));
1010 +    }
1011 +    DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: _SDIO_RegisterHostController\n"));
1012 +    return status;
1013 +}
1014 +
1015 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1016 +  @function: Unregister a host controller driver with the bus driver.
1017 +
1018 +  @function name: SDIO_UnregisterHostController
1019 +  @prototype: SDIO_STATUS SDIO_UnregisterHostController (PSDHCD pHcd)
1020 +  @category: HD_Reference
1021 +
1022 +  @input:  pHcd - the host controller definition structure that was registered.
1023 +
1024 +  @output: none
1025 +
1026 +  @return: SDIO_STATUS - SDIO_STATUS_SUCCESS when successful.
1027 +
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.
1032 +
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",
1036 +                                    status));
1037 +    }
1038 +
1039 +  @see also: SDIO_RegisterHostController
1040 +
1041 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
1042 +SDIO_STATUS _SDIO_UnregisterHostController(PSDHCD pHcd) {
1043 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
1044 +
1045 +    DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: _SDIO_UnregisterHostController\n"));
1046 +
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
1052 +       to this device */
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"));
1056 +        OSSleep(250);
1057 +    }
1058 +
1059 +    /* protect the HCD list */
1060 +    if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->HcdListSem)))) {
1061 +        goto cleanup;   /* wait interrupted */
1062 +    }
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 */
1068 +    }
1069 +        /* cleanup anything we allocated */
1070 +    CleanupHcd(pHcd);
1071 +    DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: _SDIO_UnregisterHostController\n"));
1072 +    return status;
1073 +cleanup:
1074 +    DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_UnregisterHostController, error 0x%X.\n", status));
1075 +    return status;
1076 +}
1077 +
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
1084 +
1085 +  @input:  pHcd - the host controller structure that was registered
1086 +
1087 +  @output: none
1088 +
1089 +  @return: SDIO_STATUS
1090 +
1091 +  @notes:
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
1099 +          request.
1100 +
1101 +  @example: Example of a typical Request callback:
1102 +  SDIO_STATUS HcdRequest(PSDHCD pHcd)
1103 +  {
1104 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
1105 +    PSDHCD_DRIVER_CONTEXT pHct = (PSDHCD_DRIVER_CONTEXT)pHcd->pContext;
1106 +    UINT32                temp = 0;
1107 +    PSDREQUEST            pReq;
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:
1114 +            break;
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;
1121 +            break;
1122 +        case SDREQ_FLAGS_RESP_R1B:
1123 +            temp |= (CMDDAT_RES_R1_R4_R5 | CMDAT_RES_BUSY);
1124 +            break;
1125 +        case SDREQ_FLAGS_RESP_R2:
1126 +            temp |= CMDDAT_RES_R2;
1127 +            break;
1128 +        case SDREQ_FLAGS_RESP_R3:
1129 +        case SDREQ_FLAGS_RESP_SDIO_R4:
1130 +            temp |= CMDDAT_RES_R3;
1131 +            break;
1132 +    }
1133 +        // check for data
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
1143 +        }
1144 +    }
1145 +    // .... program hardware, interrupt handler will complete request
1146 +    return SDIO_STATUS_PENDING;
1147 +  }
1148 +
1149 +  @see also: SDIO_HandleHcdEvent
1150 +
1151 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
1152 +
1153 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1154 +  @function: The bus driver calls the configure callback to set various options
1155 +             and modes in the host controller hardware.
1156 +
1157 +  @function name: Configure
1158 +  @prototype: SDIO_STATUS (*pConfigure) (struct _SDHCD *pHcd, PSDCONFIG pConfig)
1159 +  @category: HD_Reference
1160 +
1161 +  @input:  pHcd - the host controller structure that was registered
1162 +  @input:  pConfig - configuration request structure
1163 +
1164 +  @output: none
1165 +
1166 +  @return: SDIO_STATUS
1167 +
1168 +  @notes:
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.
1173 +
1174 +  @example: Example of a typical configure callback:
1175 +  SDIO_STATUS HcdConfig(PSDHCD pHcd, PSDCONFIG pConfig)
1176 +  {
1177 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
1178 +    PSDHCD_DRIVER_CONTEXT pHct = (PSDHCD_DRIVER_CONTEXT)pHcd->pContext;
1179 +    UINT16      command;
1180 +        // get command
1181 +    command = GET_SDCONFIG_CMD(pConfig);
1182 +        // decode command
1183 +    switch (command){
1184 +        case SDCONFIG_GET_WP:
1185 +            if (GetGpioPinLevel(pHct,SDIO_CARD_WP_GPIO) == WP_POLARITY) {
1186 +                *((SDCONFIG_WP_VALUE *)pConfig->pData) = 1;
1187 +            } else {
1188 +                *((SDCONFIG_WP_VALUE *)pConfig->pData) = 0;
1189 +            }
1190 +            break;
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);
1196 +            break;
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
1200 +            } else {
1201 +                // request to disable IRQ detectioon
1202 +            }
1203 +            break;
1204 +        case SDCONFIG_SDIO_REARM_INT:
1205 +                // request to re-arm the card IRQ detection logic
1206 +            break;
1207 +        case SDCONFIG_BUS_MODE_CTRL:
1208 +                // request to set bus mode
1209 +            {
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
1216 +            }
1217 +            break;
1218 +        case SDCONFIG_POWER_CTRL:
1219 +                // request to set power/voltage
1220 +            {
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
1225 +                    //
1226 +                } else {
1227 +                    // turn off slot power
1228 +                }
1229 +                DBG_PRINT(PXA_TRACE_CONFIG, ("SDIO PXA255 PwrControl: En:%d, VCC:0x%X \n",
1230 +                      pPowerSetting->SlotPowerEnable,
1231 +                      pPowerSetting->SlotPowerVoltageMask));
1232 +            }
1233 +            break;
1234 +        default:
1235 +            // unsupported
1236 +            status = SDIO_STATUS_INVALID_PARAMETER;
1237 +    }
1238 +    return status;
1239 + }
1240 +
1241 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
1242 +
1243 +
1244 +/*
1245 + * Allocate a Device instance
1246 + */
1247 +PSDDEVICE AllocateDevice(PSDHCD pHcd)
1248 +{
1249 +    PSDDEVICE pDevice;
1250 +
1251 +    pDevice = KernelAlloc(sizeof(SDDEVICE));
1252 +    if (pDevice != NULL) {
1253 +        InitDeviceData(pHcd,pDevice);
1254 +    }
1255 +    return pDevice;
1256 +}
1257 +
1258 +
1259 +/*
1260 + * Free a Device instance
1261 + */
1262 +void FreeDevice(PSDDEVICE pDevice)
1263 +{
1264 +    DeinitDeviceData(pDevice);
1265 +    KernelFree(pDevice);
1266 +}
1267 +/*
1268 + * add this device to the list
1269 + */
1270 +BOOL AddDeviceToList(PSDDEVICE pDevice)
1271 +{
1272 +    BOOL success = FALSE;
1273 +
1274 +    do {
1275 +            /* protect the driver list */
1276 +        if (!SDIO_SUCCESS(SemaphorePendInterruptable(&pBusContext->DeviceListSem))) {
1277 +            break;   /* wait interrupted */
1278 +        }
1279 +
1280 +            /* add new device to the internal list */
1281 +        SDListAdd(&pBusContext->DeviceList , &pDevice->SDList);
1282 +
1283 +        if (!SDIO_SUCCESS(SemaphorePost(&pBusContext->DeviceListSem))) {
1284 +            break;
1285 +        }
1286 +
1287 +        success = TRUE;
1288 +    } while (FALSE);
1289 +
1290 +    return success;
1291 +}
1292 +
1293 +/*
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!
1297 + */
1298 +SDIO_STATUS DeleteDevices(PSDHCD pHcd)
1299 +{
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 */
1306 +    }
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);
1313 +        }
1314 +    }SDITERATE_END;
1315 +    if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->DeviceListSem)))) {
1316 +        goto cleanup;   /* wait interrupted */
1317 +    }
1318 +    DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: DeleteDevices \n"));
1319 +    return status;
1320 +cleanup:
1321 +    DBG_PRINT(SDDBG_ERROR, ("-SDIO Bus Driver: DeleteDevice, error exit 0x%X\n", status));
1322 +    return status;
1323 +}
1324 +
1325 +
1326 +static SDIO_STATUS AllocateBusResources(void)
1327 +{
1328 +    INT                 ii;
1329 +    PSDREQUEST          pReq;
1330 +    PSIGNAL_ITEM        pSignal;
1331 +
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));
1338 +
1339 +        /* allocate some initial requests */
1340 +    for (ii = 0; ii < pBusContext->RequestListSize; ii++) {
1341 +        pReq = AllocateRequest();
1342 +        if (pReq == NULL) {
1343 +            break;
1344 +        }
1345 +            /* free requests adds the request to the list */
1346 +        FreeRequest(pReq);
1347 +    }
1348 +
1349 +    for (ii = 0; ii < pBusContext->SignalSemListSize; ii++) {
1350 +        pSignal = AllocateSignal();
1351 +        if (pSignal == NULL) {
1352 +            break;
1353 +        }
1354 +            /* freeing it adds it to the list */
1355 +        FreeSignal(pSignal);
1356 +    }
1357 +
1358 +    DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: AllocateBusResources\n"));
1359 +    return SDIO_STATUS_SUCCESS;
1360 +}
1361 +
1362 +
1363 +/* cleanup bus resources */
1364 +static void CleanUpBusResources(void)
1365 +{
1366 +    PSDLIST      pItem;
1367 +    PSDREQUEST   pReq;
1368 +    PSIGNAL_ITEM pSignal;
1369 +
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));
1373 +
1374 +    while(1) {
1375 +        pItem = SDListRemoveItemFromHead(&pBusContext->RequestList);
1376 +        if (NULL == pItem) {
1377 +            break;
1378 +        }
1379 +            /* free the request */
1380 +        pReq = CONTAINING_STRUCT(pItem, SDREQUEST, SDList);
1381 +        if (pReq->InternalFlags & SDBD_ALLOC_IRQ_SAFE_MASK) {
1382 +            KernelFreeIrqSafe(pReq);
1383 +        } else {
1384 +            KernelFree(pReq);
1385 +        }
1386 +        pBusContext->CurrentRequestAllocations--;
1387 +    }
1388 +
1389 +    if (pBusContext->CurrentRequestAllocations != 0) {
1390 +        DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Request allocations are not ZERO! (CR:%d)\n",
1391 +             pBusContext->CurrentRequestAllocations));
1392 +    }
1393 +
1394 +    while(1) {
1395 +        pItem = SDListRemoveItemFromHead(&pBusContext->SignalList);
1396 +        if (NULL == pItem) {
1397 +            break;
1398 +        }
1399 +        pSignal = CONTAINING_STRUCT(pItem, SIGNAL_ITEM, SDList);
1400 +        DestroySignal(pSignal);
1401 +        pBusContext->CurrentSignalAllocations--;
1402 +    }
1403 +
1404 +    if (pBusContext->CurrentSignalAllocations != 0) {
1405 +        DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Signal allocations are not ZERO! (CR:%d)\n",
1406 +             pBusContext->CurrentRequestAllocations));
1407 +    }
1408 +
1409 +    DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: CleanUpBusResources\n"));
1410 +}
1411 +
1412 +
1413 +/* free a request to the lookaside list */
1414 +void FreeRequest(PSDREQUEST pReq)
1415 +{
1416 +    SDIO_STATUS status;
1417 +    CT_DECLARE_IRQ_SYNC_CONTEXT();
1418 +
1419 +    status = CriticalSectionAcquireSyncIrq(&pBusContext->RequestListCritSection);
1420 +        /* protect request list */
1421 +    if (!SDIO_SUCCESS(status)) {
1422 +        return;
1423 +    }
1424 +
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 */
1430 +        pReq = NULL;
1431 +    } else {
1432 +            /* decrement count */
1433 +        pBusContext->CurrentRequestAllocations--;
1434 +    }
1435 +
1436 +    status = CriticalSectionReleaseSyncIrq(&pBusContext->RequestListCritSection);
1437 +
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);
1443 +        } else {
1444 +                /* we should never free the ones that were normally allocated */
1445 +            DBG_ASSERT(FALSE);
1446 +        }
1447 +    }
1448 +}
1449 +
1450 +/* allocate a request from the lookaside list */
1451 +PSDREQUEST AllocateRequest(void)
1452 +{
1453 +    PSDLIST  pItem;
1454 +    SDIO_STATUS status;
1455 +    PSDREQUEST pReq = NULL;
1456 +    ATOMIC_FLAGS internalflags;
1457 +    CT_DECLARE_IRQ_SYNC_CONTEXT();
1458 +
1459 +
1460 +    status = CriticalSectionAcquireSyncIrq(&pBusContext->RequestListCritSection);
1461 +
1462 +    if (!SDIO_SUCCESS(status)) {
1463 +        return NULL;
1464 +    }
1465 +
1466 +    if (pBusContext->InitMask & RESOURCE_INIT) {
1467 +            /* check the list, we are now running... */
1468 +        pItem = SDListRemoveItemFromHead(&pBusContext->RequestList);
1469 +    } else {
1470 +            /* we are loading the list with requests at initialization */
1471 +        pItem = NULL;
1472 +    }
1473 +    status = CriticalSectionReleaseSyncIrq(&pBusContext->RequestListCritSection);
1474 +
1475 +    if (pItem != NULL) {
1476 +        pReq = CONTAINING_STRUCT(pItem, SDREQUEST, SDList);
1477 +    } else {
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;
1486 +        } else {
1487 +                /* use the normal allocation since we are called at initialization */
1488 +            pReq = (PSDREQUEST)KernelAlloc(sizeof(SDREQUEST));
1489 +            internalflags = 0;
1490 +        }
1491 +
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);
1498 +        }
1499 +    }
1500 +
1501 +
1502 +    if (pReq != NULL) {
1503 +            /* preserve internal flags */
1504 +        internalflags = pReq->InternalFlags;
1505 +        ZERO_POBJECT(pReq);
1506 +        pReq->InternalFlags = internalflags;
1507 +    }
1508 +
1509 +    return pReq;
1510 +}
1511 +
1512 +void DestroySignal(PSIGNAL_ITEM pSignal)
1513 +{
1514 +   SignalDelete(&pSignal->Signal);
1515 +   KernelFree(pSignal);
1516 +}
1517 +
1518 +PSIGNAL_ITEM BuildSignal(void)
1519 +{
1520 +    PSIGNAL_ITEM pSignal;
1521 +
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);
1527 +            pSignal = NULL;
1528 +        }
1529 +    }
1530 +    return pSignal;
1531 +}
1532 +/* free a signal*/
1533 +void FreeSignal(PSIGNAL_ITEM pSignal)
1534 +{
1535 +    SDIO_STATUS status;
1536 +    CT_DECLARE_IRQ_SYNC_CONTEXT();
1537 +
1538 +    status = CriticalSectionAcquireSyncIrq(&pBusContext->RequestListCritSection);
1539 +
1540 +    if (!SDIO_SUCCESS(status)) {
1541 +        return;
1542 +    }
1543 +
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 */
1548 +        pSignal = NULL;
1549 +    } else {
1550 +            /* decrement count */
1551 +        pBusContext->CurrentSignalAllocations--;
1552 +    }
1553 +
1554 +    status = CriticalSectionReleaseSyncIrq(&pBusContext->RequestListCritSection);
1555 +
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);
1560 +    }
1561 +}
1562 +
1563 +/* allocate a signal from the list */
1564 +PSIGNAL_ITEM AllocateSignal(void)
1565 +{
1566 +    PSDLIST         pItem;
1567 +    PSIGNAL_ITEM    pSignal;
1568 +    SDIO_STATUS status;
1569 +    CT_DECLARE_IRQ_SYNC_CONTEXT();
1570 +
1571 +    status = CriticalSectionAcquireSyncIrq(&pBusContext->RequestListCritSection);
1572 +
1573 +    if (!SDIO_SUCCESS(status)) {
1574 +        return NULL;
1575 +    }
1576 +
1577 +    if (pBusContext->InitMask & RESOURCE_INIT) {
1578 +            /* check the list */
1579 +        pItem = SDListRemoveItemFromHead(&pBusContext->SignalList);
1580 +    } else {
1581 +            /* we are loading the list */
1582 +        pItem = NULL;
1583 +    }
1584 +
1585 +    status = CriticalSectionReleaseSyncIrq(&pBusContext->RequestListCritSection);
1586 +    if (pItem != NULL) {
1587 +            /* return the one from the list */
1588 +        pSignal = CONTAINING_STRUCT(pItem, SIGNAL_ITEM, SDList);
1589 +    } else {
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));
1593 +        }
1594 +            /* just allocate one */
1595 +        pSignal = BuildSignal();
1596 +        status = CriticalSectionAcquireSyncIrq(&pBusContext->RequestListCritSection);
1597 +        if (pSignal != NULL) {
1598 +            pBusContext->CurrentSignalAllocations++;
1599 +        }
1600 +        status = CriticalSectionReleaseSyncIrq(&pBusContext->RequestListCritSection);
1601 +    }
1602 +
1603 +
1604 +    return pSignal;
1605 +}
1606 +
1607 +/*
1608 + * Issus Bus Request (exposed to function drivers)
1609 +*/
1610 +PSDREQUEST IssueAllocRequest(PSDDEVICE pDev)
1611 +{
1612 +    return AllocateRequest();
1613 +}
1614 +
1615 +/*
1616 + * Free Request (exposed to function drivers)
1617 +*/
1618 +void IssueFreeRequest(PSDDEVICE pDev, PSDREQUEST pReq)
1619 +{
1620 +    FreeRequest(pReq);
1621 +}
1622 +
1623 +/*
1624 + * Issus Bus Request (exposed to function drivers)
1625 +*/
1626 +SDIO_STATUS IssueBusRequest(PSDDEVICE pDev, PSDREQUEST pReq)
1627 +{
1628 +    pReq->pFunction = pDev->pFunction;
1629 +    return IssueRequestToHCD(pDev->pHcd,pReq);
1630 +}
1631 +
1632 +
1633 +    /* completion routine for HCD configs, this is synchronized with normal bus requests */
1634 +static void HcdConfigComplete(PSDREQUEST pReq)
1635 +{
1636 +
1637 +    pReq->Status = CALL_HCD_CONFIG((PSDHCD)pReq->pDataBuffer, (PSDCONFIG)pReq->pCompleteContext);
1638 +
1639 +    SignalSet(&((PSIGNAL_ITEM)pReq->pHcdContext)->Signal);
1640 +}
1641 +
1642 +SDIO_STATUS SendSyncedHcdBusConfig(PSDDEVICE pDevice, PSDCONFIG pConfig)
1643 +{
1644 +    SDIO_STATUS     status = SDIO_STATUS_SUCCESS;
1645 +    PSDREQUEST      pReq = NULL;
1646 +    PSIGNAL_ITEM    pSignal = NULL;
1647 +
1648 +    do {
1649 +
1650 +        pSignal = AllocateSignal();
1651 +        if (NULL == pSignal) {
1652 +            status = SDIO_STATUS_NO_RESOURCES;
1653 +            break;
1654 +        }
1655 +
1656 +        pReq = AllocateRequest();
1657 +        if (NULL == pReq) {
1658 +            status = SDIO_STATUS_NO_RESOURCES;
1659 +            break;
1660 +        }
1661 +
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;
1672 +
1673 +            /* issue request */
1674 +        status = IssueRequestToHCD(pDevice->pHcd,pReq);
1675 +
1676 +    } while (FALSE);
1677 +
1678 +    if (SDIO_SUCCESS(status)) {
1679 +        DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Config Request Sync-Op waiting....\n"));
1680 +        status = SignalWait(&pSignal->Signal);
1681 +
1682 +        if (SDIO_SUCCESS(status)) {
1683 +                /* return the result of the configuration request */
1684 +            status = pReq->Status;
1685 +        }
1686 +    }
1687 +
1688 +        /* cleanup */
1689 +    if (pReq != NULL) {
1690 +        FreeRequest(pReq);
1691 +    }
1692 +
1693 +    if (pSignal != NULL) {
1694 +        FreeSignal(pSignal);
1695 +    }
1696 +
1697 +    return status;
1698 +}
1699 +
1700 +/*
1701 + * Issus bus Configuration  (exposed to function drivers)
1702 +*/
1703 +SDIO_STATUS IssueBusConfig(PSDDEVICE pDev, PSDCONFIG pConfig)
1704 +{
1705 +    SDIO_STATUS status;
1706 +    INT         cmdLength;
1707 +    UINT8       debugLevel = SDDBG_ERROR;
1708 +
1709 +    cmdLength = GET_SDCONFIG_CMD_LEN(pConfig);
1710 +    status = SDIO_STATUS_INVALID_PARAMETER;
1711 +
1712 +    do {
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)) {
1716 +                break;
1717 +            }
1718 +        }
1719 +
1720 +        switch (GET_SDCONFIG_CMD(pConfig)) {
1721 +            case SDCONFIG_FUNC_ACK_IRQ:
1722 +                status = SDFunctionAckInterrupt(pDev);
1723 +                break;
1724 +            case SDCONFIG_FUNC_ENABLE_DISABLE:
1725 +                if (cmdLength < sizeof(SDCONFIG_FUNC_ENABLE_DISABLE_DATA)) {
1726 +                    break;
1727 +                }
1728 +                status = SDEnableFunction(pDev,
1729 +                           GET_SDCONFIG_CMD_DATA(PSDCONFIG_FUNC_ENABLE_DISABLE_DATA,pConfig));
1730 +                break;
1731 +            case SDCONFIG_FUNC_UNMASK_IRQ:
1732 +                status = SDMaskUnmaskFunctionIRQ(pDev,FALSE);
1733 +                break;
1734 +            case SDCONFIG_FUNC_MASK_IRQ:
1735 +                status = SDMaskUnmaskFunctionIRQ(pDev,TRUE);
1736 +                break;
1737 +            case SDCONFIG_FUNC_SPI_MODE_DISABLE_CRC:
1738 +                status = SDSPIModeEnableDisableCRC(pDev,FALSE);
1739 +                break;
1740 +            case SDCONFIG_FUNC_SPI_MODE_ENABLE_CRC:
1741 +                status = SDSPIModeEnableDisableCRC(pDev,TRUE);
1742 +                break;
1743 +            case SDCONFIG_FUNC_ALLOC_SLOT_CURRENT:
1744 +                status = SDAllocFreeSlotCurrent(pDev,
1745 +                                                TRUE,
1746 +                                   GET_SDCONFIG_CMD_DATA(PSDCONFIG_FUNC_SLOT_CURRENT_DATA,pConfig));
1747 +                break;
1748 +            case SDCONFIG_FUNC_FREE_SLOT_CURRENT:
1749 +                status = SDAllocFreeSlotCurrent(pDev, FALSE, NULL);
1750 +                break;
1751 +            case SDCONFIG_FUNC_CHANGE_BUS_MODE:
1752 +
1753 +                status = SetOperationalBusMode(pDev,
1754 +                                               GET_SDCONFIG_CMD_DATA(PSDCONFIG_BUS_MODE_DATA,
1755 +                                               pConfig));
1756 +                break;
1757 +            case SDCONFIG_FUNC_NO_IRQ_PEND_CHECK:
1758 +                status = TryNoIrqPendingCheck(pDev);
1759 +                break;
1760 +            default:
1761 +
1762 +                if (GET_SDCONFIG_CMD(pConfig) & SDCONFIG_FLAGS_HC_CONFIG) {
1763 +                        /* synchronize config requests with busrequests */
1764 +                    status = SendSyncedHcdBusConfig(pDev,pConfig);
1765 +                } else {
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;
1770 +                }
1771 +                break;
1772 +        }
1773 +    } while(FALSE);
1774 +
1775 +    if (!SDIO_SUCCESS(status)) {
1776 +
1777 +           if(status == SDIO_STATUS_FUNC_ENABLE_TIMEOUT ){ /* reduce debug level to avoid timeout error messages */
1778 +                debugLevel = SDDBG_TRACE;
1779 +         }
1780 +
1781 +
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));
1787 +    }
1788 +    return status;
1789 +}
1790 +
1791 +/* start a request */
1792 +static INLINE SDIO_STATUS StartHcdRequest(PSDHCD pHcd, PSDREQUEST pReq)
1793 +{
1794 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
1795 +    CT_DECLARE_IRQ_SYNC_CONTEXT();
1796 +
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;
1802 +    }
1803 +
1804 +    status = _AcquireHcdLock(pHcd);
1805 +
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;
1810 +    }
1811 +
1812 +    if (pReq->Flags & SDREQ_FLAGS_QUEUE_HEAD) {
1813 +            /* caller wants this request queued to the head */
1814 +
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);
1820 +    } else {
1821 +            /* insert in queue at tail */
1822 +        QueueRequest(&pHcd->RequestQueue,pReq);
1823 +
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;
1830 +        }
1831 +            /* mark it as busy */
1832 +        MarkQueueBusy(&pHcd->RequestQueue);
1833 +    }
1834 +
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);
1839 +    }
1840 +        /* release lock */
1841 +    status = _ReleaseHcdLock(pHcd);
1842 +        /* controller was not busy, call into HCD to process current request */
1843 +    status = CallHcdRequest(pHcd);
1844 +    return status;
1845 +}
1846 +
1847 +
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)
1851 +
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)
1855 +
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)
1859 +
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)
1863 +
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)
1867 +
1868 +static void CMD13CompletionBarrier(PSDREQUEST pReq);
1869 +
1870 +static INLINE void SetupCMD13(PSDHCD pHcd, PSDREQUEST pReq)
1871 +{
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;
1878 +    } else {
1879 +        pReq->Flags |= SDREQ_FLAGS_RESP_R1;
1880 +        pReq->Argument |= pHcd->CardProperties.RCA << 16;
1881 +    }
1882 +        /* insert completion */
1883 +    pReq->pCompletion = CMD13CompletionBarrier;
1884 +}
1885 +
1886 +/* CMD13 (GET STATUS) completion */
1887 +static void CMD13CompletionBarrier(PSDREQUEST pReq)
1888 +{
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;
1894 +
1895 +    DBG_ASSERT(pOrigCompletion != NULL);
1896 +    DBG_ASSERT(pHcd != NULL);
1897 +    DBG_PRINT(SDIODBG_REQUESTS, ("+SDIO Bus Driver: CMD13CompletionBarrier (cnt:%d) \n",pollingCount));
1898 +
1899 +    do {
1900 +        if (!SDIO_SUCCESS(pReq->Status)) {
1901 +            break;
1902 +        }
1903 +
1904 +        cardStatus = SD_R1_GET_CARD_STATUS(pReq->Response);
1905 +
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;
1909 +            break;
1910 +        }
1911 +
1912 +        if (SD_CS_GET_STATE(cardStatus) != SD_CS_STATE_PRG) {
1913 +            DBG_PRINT(SDIODBG_REQUESTS,("SDIO Bus Driver: Card programming done \n"));
1914 +            break;
1915 +        }
1916 +
1917 +        DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Card still programming.. \n"));
1918 +        pollingCount--;
1919 +
1920 +        if (pollingCount < 0) {
1921 +            pReq->Status = SDIO_STATUS_PROGRAM_TIMEOUT;
1922 +            DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: card programming timeout!\n"));
1923 +            break;
1924 +        }
1925 +
1926 +        doCompletion = FALSE;
1927 +            /* keep trying */
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"));
1931 +            /* re-issue */
1932 +        IssueRequestToHCD(pHcd, pReq);
1933 +
1934 +    } while (FALSE);
1935 +
1936 +
1937 +    if (doCompletion) {
1938 +            /* restore original completion routine */
1939 +        pReq->pCompletion = pOrigCompletion;
1940 +            /* call original completion routine */
1941 +        pOrigCompletion(pReq);
1942 +    }
1943 +
1944 +    DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: CMD13CompletionBarrier \n"));
1945 +}
1946 +
1947 +/* command 13 (GET STATUS) preparation */
1948 +static void PrepCMD13Barrier(PSDREQUEST pReq)
1949 +{
1950 +    SDIO_STATUS status = pReq->Status;
1951 +    PSDHCD      pHcd = GET_BD_RSV_HCD(pReq);
1952 +    INT         pollingCount;
1953 +    PSDEQUEST_COMPLETION pOrigCompletion = GET_BD_RSV_REQUEST_COMPLETION(pReq);
1954 +
1955 +    DBG_ASSERT(pHcd != NULL);
1956 +    DBG_ASSERT(pOrigCompletion != NULL);
1957 +
1958 +    DBG_PRINT(SDIODBG_REQUESTS, ("+SDIO Bus Driver: PrepCMD13Barrier \n"));
1959 +
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);
1971 +    } else {
1972 +        DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Request Failure (%d) , CMD13 bypassed.\n",status));
1973 +            /* call the original completion routine */
1974 +        pOrigCompletion(pReq);
1975 +    }
1976 +
1977 +    DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: PrepCMD13Barrier (%d) \n",status));
1978 +}
1979 +
1980 +/* CMD12 completion */
1981 +static void CMD12Completion(PSDREQUEST pReq)
1982 +{
1983 +    PSDEQUEST_COMPLETION pOrigCompletion = GET_BD_RSV_REQUEST_COMPLETION(pReq);
1984 +
1985 +    DBG_ASSERT(pOrigCompletion != NULL);
1986 +
1987 +    DBG_PRINT(SDIODBG_REQUESTS, ("+SDIO Bus Driver: CMD12Completion \n"));
1988 +
1989 +        /* restore original completion routine */
1990 +    pReq->pCompletion = pOrigCompletion;
1991 +
1992 +    if (SDIO_SUCCESS(pReq->Status)) {
1993 +            /* if CMD12 succeeds, we want to return the result of the original
1994 +             * request */
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));
1998 +    }
1999 +        /* call original completion routine */
2000 +    pOrigCompletion(pReq);
2001 +
2002 +    DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: CMD12Completion \n"));
2003 +}
2004 +
2005 +/* CMD12 preparation */
2006 +static void PrepCMD12Barrier(PSDREQUEST pReq)
2007 +{
2008 +
2009 +    SDIO_STATUS status = pReq->Status;
2010 +    PSDHCD               pHcd = GET_BD_RSV_HCD(pReq);
2011 +    PSDEQUEST_COMPLETION pOrigCompletion = GET_BD_RSV_REQUEST_COMPLETION(pReq);
2012 +
2013 +    DBG_ASSERT(pHcd != NULL);
2014 +    DBG_ASSERT(pOrigCompletion != NULL);
2015 +
2016 +    DBG_PRINT(SDIODBG_REQUESTS, ("+SDIO Bus Driver: PrepCMD12Barrier \n"));
2017 +
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);
2027 +            }
2028 +        }
2029 +            /* re-use the request for CMD12 */
2030 +        pReq->Command = CMD12;
2031 +        pReq->Argument = 0;
2032 +
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;
2043 +        } else {
2044 +            pReq->Flags = SDREQ_FLAGS_RESP_R1B | SDREQ_FLAGS_QUEUE_HEAD | SDREQ_FLAGS_TRANS_ASYNC;
2045 +            pReq->pCompletion = CMD12Completion;
2046 +        }
2047 +
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);
2052 +    } else {
2053 +        DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Request Failure (%d) , CMD12 bypassed.\n",status));
2054 +            /* call the original completion routine */
2055 +        pOrigCompletion(pReq);
2056 +    }
2057 +
2058 +    DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: PrepCMD12Barrier (%d) \n",status));
2059 +}
2060 +
2061 +
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)
2065 +{
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;
2070 +
2071 +    DBG_ASSERT(pOrigReq != NULL);
2072 +    DBG_ASSERT(pHcd != NULL);
2073 +
2074 +    DBG_PRINT(SDIODBG_REQUESTS, ("+SDIO Bus Driver: CMD55Completion \n"));
2075 +
2076 +    do {
2077 +
2078 +        if (!SDIO_SUCCESS(status)) {
2079 +                /* command 55 failed */
2080 +            pOrigReq->Status = status;
2081 +            doCompletion = TRUE;
2082 +            break;
2083 +        }
2084 +
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;
2090 +            break;
2091 +        }
2092 +
2093 +        if (!CHECK_API_VERSION_COMPAT(pHcd,2,6)) {
2094 +            if (!ForceAllRequestsAsync()) {
2095 +                AtomicTest_Clear(&pHcd->HcdFlags, HCD_REQUEST_CALL_BIT);
2096 +            }
2097 +        }
2098 +
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);
2104 +
2105 +        if (SDIO_STATUS_PENDING == status) {
2106 +            break;
2107 +        }
2108 +
2109 +        pOrigReq->Status = status;
2110 +
2111 +        if (SDIO_STATUS_SDREQ_QUEUE_FAILED == status) {
2112 +                /* never made it to the queue */
2113 +            doCompletion = TRUE;
2114 +            break;
2115 +        }
2116 +
2117 +            /* request completed in-line */
2118 +        _SDIO_HandleHcdEvent(pHcd, EVENT_HCD_TRANSFER_DONE);
2119 +
2120 +    } while (FALSE);
2121 +
2122 +    if (doCompletion) {
2123 +        DoRequestCompletion(pOrigReq, pHcd);
2124 +    }
2125 +
2126 +        /* free the CMD55 request */
2127 +    FreeRequest(pReq);
2128 +
2129 +    DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: CMD55Completion \n"));
2130 +}
2131 +
2132 +
2133 +/* synch completion routine */
2134 +static void SynchCompletion(PSDREQUEST pRequest)
2135 +{
2136 +    PSIGNAL_ITEM pSignal;
2137 +
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"));
2142 +    }
2143 +
2144 +}
2145 +
2146 +/*
2147 + * Issue a request to the host controller
2148 + *
2149 + *
2150 + * The following flags are handled internally by the bus driver to guarantee atomicity.
2151 + *
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
2156 + *                                       using CMD13
2157 + *
2158 + *    These request flags require additional commands prepended or appended to the original command
2159 + *
2160 + *    The order of command execution :
2161 + *
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
2168 +*/
2169 +SDIO_STATUS IssueRequestToHCD(PSDHCD pHcd, PSDREQUEST pReq)
2170 +{
2171 +    SDIO_STATUS     status = SDIO_STATUS_SUCCESS;
2172 +    PSIGNAL_ITEM    pSignal = NULL;
2173 +    BOOL            handleFailedReqSubmit = FALSE;
2174 +
2175 +    CLEAR_INTERNAL_REQ_FLAGS(pReq);
2176 +
2177 +    do {
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));
2184 +        }
2185 +
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 */
2195 +                break;
2196 +            }
2197 +            pReq->pCompleteContext = (PVOID)pSignal;
2198 +        }
2199 +
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;
2215 +        }
2216 +
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;
2230 +            }
2231 +        }
2232 +
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 */
2244 +                break;
2245 +            }
2246 +                /* first submit CMD55 */
2247 +                /* set RCA */
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
2259 +                 * atomically */
2260 +            status = IssueRequestToHCD(pHcd, pCmd55);
2261 +
2262 +        } else {
2263 +                /* start the normal request */
2264 +            status = StartHcdRequest(pHcd,pReq);
2265 +        }
2266 +
2267 +
2268 +        if (SDIO_STATUS_SDREQ_QUEUE_FAILED == status) {
2269 +            handleFailedReqSubmit = TRUE;
2270 +                /* no need to continue, clean up at the end */
2271 +            break;
2272 +        }
2273 +
2274 +            /* at this point, the request was either queued or was processed by the
2275 +             * HCD */
2276 +
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));
2279 +
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;
2289 +
2290 +            } else {
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;
2294 +            }
2295 +                /* process this completed transfer on behalf of the HCD */
2296 +            _SDIO_HandleHcdEvent(pHcd, EVENT_HCD_TRANSFER_DONE);
2297 +
2298 +                /* done processing */
2299 +            break;
2300 +        }
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);
2310 +            pSignal = NULL;
2311 +
2312 +            /* note: it is safe to touch pReq since we own
2313 +             * the completion routine for synch transfers */
2314 +
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",
2319 +                (UINT)pReq));
2320 +                pReq->Status = SDIO_STATUS_CANCELED;
2321 +                status = SDIO_STATUS_CANCELED;
2322 +                break;
2323 +            }
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;
2327 +        } else {
2328 +            DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Async operation Pending \n"));
2329 +        }
2330 +
2331 +    } while (FALSE);
2332 +
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;
2344 +        }
2345 +    }
2346 +
2347 +        /* check if we need to clean up the signal */
2348 +    if (pSignal != NULL) {
2349 +            /* make sure this is freed */
2350 +        FreeSignal(pSignal);
2351 +    }
2352 +        /* return status */
2353 +    return status;
2354 +}
2355 +
2356 +/* documentation for configuration requests */
2357 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2358 +  @function: Enable or Disable the SDIO Function
2359 +
2360 +  @function name: SDCONFIG_FUNC_ENABLE_DISABLE
2361 +  @prototype: SDCONFIG_FUNC_ENABLE_DISABLE
2362 +  @category: PD_Reference
2363 +
2364 +  @input:  SDCONFIG_FUNC_ENABLE_DISABLE_DATA - Enable Data structure
2365 +
2366 +  @output: none
2367 +
2368 +  @return: SDIO Status
2369 +
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.
2376 +
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,
2382 +                                   &fData,
2383 +                                   sizeof(fData));
2384 +
2385 +  @see also: SDLIB_IssueConfig
2386 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2387 +
2388 +
2389 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2390 +  @function: Unmask the function's IRQ
2391 +
2392 +  @function name: SDCONFIG_FUNC_UNMASK_IRQ
2393 +  @prototype: SDCONFIG_FUNC_UNMASK_IRQ
2394 +  @category: PD_Reference
2395 +
2396 +  @input:  none
2397 +
2398 +  @output: none
2399 +
2400 +  @return: SDIO Status
2401 +
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.
2406 +
2407 +  @example: Example of unmasking interrupt :
2408 +        status = SDLIB_IssueConfig(pInstance->pDevice,
2409 +                                   SDCONFIG_FUNC_UNMASK_IRQ,
2410 +                                   NULL,
2411 +                                   0);
2412 +
2413 +  @see also: SDCONFIG_FUNC_MASK_IRQ
2414 +  @see also: SDLIB_IssueConfig
2415 +
2416 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2417 +
2418 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2419 +  @function: Mask the function's IRQ
2420 +
2421 +  @function name: SDCONFIG_FUNC_MASK_IRQ
2422 +  @prototype: SDCONFIG_FUNC_MASK_IRQ
2423 +  @category: PD_Reference
2424 +
2425 +  @input:  none
2426 +
2427 +  @output: none
2428 +
2429 +  @return: SDIO Status
2430 +
2431 +  @notes: This command code is used in the SDLIB_IssueConfig() API.  The command
2432 +          masks the IRQ for the I/O function.
2433 +
2434 +  @example: Example of unmasking interrupt :
2435 +        status = SDLIB_IssueConfig(pInstance->pDevice,
2436 +                                   SDCONFIG_FUNC_MASK_IRQ,
2437 +                                   NULL,
2438 +                                   0);
2439 +
2440 +  @see also: SDCONFIG_FUNC_UNMASK_IRQ
2441 +  @see also: SDLIB_IssueConfig
2442 +
2443 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2444 +
2445 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2446 +  @function: Acknowledge that the function's IRQ has been handled
2447 +
2448 +  @function name: SDCONFIG_FUNC_ACK_IRQ
2449 +  @prototype: SDCONFIG_FUNC_ACK_IRQ
2450 +  @category: PD_Reference
2451 +
2452 +  @input:  none
2453 +
2454 +  @output: none
2455 +
2456 +  @return: SDIO Status
2457 +
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.
2465 +
2466 +  @example: Example of acknowledging an interrupt :
2467 +        status = SDLIB_IssueConfig(pInstance->pDevice,
2468 +                                   SDCONFIG_FUNC_ACK_IRQ,
2469 +                                   NULL,
2470 +                                   0);
2471 +
2472 +  @see also: SDLIB_IssueConfig
2473 +
2474 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2475 +
2476 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2477 +  @function: Disable SD/MMC/SDIO card CRC checking.
2478 +
2479 +  @function name: SDCONFIG_FUNC_SPI_MODE_DISABLE_CRC
2480 +  @prototype: SDCONFIG_FUNC_SPI_MODE_DISABLE_CRC
2481 +  @category: PD_Reference
2482 +
2483 +  @input:  none
2484 +
2485 +  @output: none
2486 +
2487 +  @return: SDIO Status
2488 +
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).
2494 +
2495 +  @example: Example of disabling SPI CRC checking:
2496 +        status = SDLIB_IssueConfig(pInstance->pDevice,
2497 +                                   SDCONFIG_FUNC_SPI_MODE_DISABLE_CRC,
2498 +                                   NULL,
2499 +                                   0);
2500 +
2501 +  @see also: SDCONFIG_FUNC_SPI_MODE_ENABLE_CRC
2502 +  @see also: SDLIB_IssueConfig
2503 +
2504 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2505 +
2506 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2507 +  @function: Enable SD/MMC/SDIO card CRC checking.
2508 +
2509 +  @function name: SDCONFIG_FUNC_SPI_MODE_ENABLE_CRC
2510 +  @prototype: SDCONFIG_FUNC_SPI_MODE_ENABLE_CRC
2511 +  @category: PD_Reference
2512 +
2513 +  @input:  none
2514 +
2515 +  @output: none
2516 +
2517 +  @return: SDIO Status
2518 +
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.
2523 +
2524 +  @example: Example of enabling SPI CRC checking:
2525 +        status = SDLIB_IssueConfig(pInstance->pDevice,
2526 +                                   SDCONFIG_FUNC_SPI_MODE_ENABLE_CRC,
2527 +                                   NULL,
2528 +                                   0);
2529 +
2530 +  @see also: SDCONFIG_FUNC_SPI_MODE_DISABLE_CRC
2531 +  @see also: SDLIB_IssueConfig
2532 +
2533 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2534 +
2535 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2536 +  @function: Allocate slot current for a card function.
2537 +
2538 +  @function name: SDCONFIG_FUNC_ALLOC_SLOT_CURRENT
2539 +  @prototype: SDCONFIG_FUNC_ALLOC_SLOT_CURRENT
2540 +  @category: PD_Reference
2541 +
2542 +  @input:  SDCONFIG_FUNC_SLOT_CURRENT_DATA
2543 +
2544 +  @output: SDCONFIG_FUNC_SLOT_CURRENT_DATA
2545 +
2546 +  @return: SDIO Status
2547 +
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.
2560 +
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,
2565 +                                   &slotCurrent,
2566 +                                   sizeof(slotCurrent));
2567 +
2568 +
2569 +  @see also: SDCONFIG_FUNC_FREE_SLOT_CURRENT
2570 +  @see also: SDLIB_IssueConfig
2571 +
2572 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2573 +
2574 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2575 +  @function: Free slot current for a card function.
2576 +
2577 +  @function name: SDCONFIG_FUNC_FREE_SLOT_CURRENT
2578 +  @prototype: SDCONFIG_FUNC_FREE_SLOT_CURRENT
2579 +  @category: PD_Reference
2580 +
2581 +  @input:  none
2582 +
2583 +  @output: none
2584 +
2585 +  @return: SDIO Status
2586 +
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.
2590 +
2591 +  @example: Example of freeing slot current:
2592 +        status = SDLIB_IssueConfig(pInstance->pDevice,
2593 +                                   SDCONFIG_FUNC_FREE_SLOT_CURRENT,
2594 +                                   NULL,
2595 +                                   0);
2596 +
2597 +  @see also: SDCONFIG_FUNC_ALLOC_SLOT_CURRENT
2598 +  @see also: SDLIB_IssueConfig
2599 +
2600 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2601 +
2602 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2603 +  @function: Set the bus mode for the SD/SDIO card.
2604 +
2605 +  @function name: SDCONFIG_FUNC_CHANGE_BUS_MODE
2606 +  @prototype: SDCONFIG_FUNC_CHANGE_BUS_MODE
2607 +  @category: PD_Reference
2608 +
2609 +  @input:  none
2610 +
2611 +  @output: none
2612 +
2613 +  @return: SDIO Status
2614 +
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.
2631 +
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,
2641 +                               &busSettings,
2642 +                               sizeof(SDCONFIG_BUS_MODE_DATA));
2643 +
2644 +  @see also: SDDEVICE_GET_BUSMODE_FLAGS
2645 +  @see also: SDLIB_IssueConfig
2646 +
2647 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2648 +
2649 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2650 +  @function: Get the debug level of the underlying host controller driver.
2651 +
2652 +  @function name: SDCONFIG_GET_HCD_DEBUG
2653 +  @prototype: SDCONFIG_GET_HCD_DEBUG
2654 +  @category: PD_Reference
2655 +
2656 +  @input:  none
2657 +
2658 +  @output: CT_DEBUG_LEVEL
2659 +
2660 +  @return: SDIO Status
2661 +
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
2668 +          this command.
2669 +
2670 +  @example: Example of saving the debug level:
2671 +        CT_DEBUG_LEVEL savedDebug;
2672 +        status = SDLIB_IssueConfig(pInstance->pDevice,
2673 +                                   SDCONFIG_GET_HCD_DEBUG,
2674 +                                   &savedDebug,
2675 +                                   sizeof(savedDebug));
2676 +
2677 +  @see also: SDCONFIG_SET_HCD_DEBUG
2678 +  @see also: SDLIB_IssueConfig
2679 +
2680 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2681 +
2682 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2683 +  @function: Set the debug level of the underlying host controller driver.
2684 +
2685 +  @function name: SDCONFIG_SET_HCD_DEBUG
2686 +  @prototype: SDCONFIG_SET_HCD_DEBUG
2687 +  @category: PD_Reference
2688 +
2689 +  @input:  CT_DEBUG_LEVEL
2690 +
2691 +  @output: none
2692 +
2693 +  @return: SDIO Status
2694 +
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
2700 +          this request.
2701 +
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,
2706 +                                   &setDebug,
2707 +                                   sizeof(setDebug));
2708 +
2709 +  @see also: SDCONFIG_GET_HCD_DEBUG
2710 +  @see also: SDLIB_IssueConfig
2711 +
2712 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2713 +
2714 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2715 +  @function: Instruct the bus driver to not check the SDIO card interrupt pending
2716 +             register on card interrupts, if possible.
2717 +
2718 +  @function name: SDCONFIG_FUNC_NO_IRQ_PEND_CHECK
2719 +  @prototype: SDCONFIG_FUNC_NO_IRQ_PEND_CHECK
2720 +  @category: PD_Reference
2721 +
2722 +  @input:  none
2723 +
2724 +  @output: none
2725 +
2726 +  @return: SDIO Status
2727 +
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.
2734 +
2735 +  @example: Example of skipping IRQ pending checks:
2736 +
2737 +        status = SDLIB_IssueConfig(pInstance->pDevice,
2738 +                                   SDCONFIG_FUNC_NO_IRQ_PEND_CHECK,
2739 +                                   NULL,
2740 +                                   0);
2741 +
2742 +  @see also: SDLIB_IssueConfig
2743 +
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
2748 --- /dev/null
2749 +++ b/drivers/sdio/stack/busdriver/sdio_bus_events.c
2750 @@ -0,0 +1,1040 @@
2751 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2752 +@file: sdio_bus_events.c
2753 +
2754 +@abstract: OS independent bus driver support
2755 +
2756 +#notes: this file contains various event handlers and helpers
2757 +
2758 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
2759 +
2760 +
2761 + *
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;
2765 + *
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.
2770 + *
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:
2773 + *
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.
2779 + *   Disclaimers:
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.
2788 + *
2789 + *
2790 + *  The initial developers of the original code are Seung Yi and Paul Lever
2791 + *
2792 + *  sdio@atheros.com
2793 + *
2794 + *
2795 +
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>
2804 +
2805 +static SDIO_STATUS ScanSlotForCard(PSDHCD pHcd,
2806 +                                   PBOOL  pCardPresent);
2807 +static void GetPendingIrqComplete(PSDREQUEST pReq);
2808 +static void ProcessPendingIrqs(PSDHCD  pHcd, UINT8 IntPendingMsk);
2809 +
2810 +/*
2811 + * DeviceDetach - tell core a device was removed from a slot
2812 +*/
2813 +SDIO_STATUS DeviceDetach(PSDHCD pHcd)
2814 +{
2815 +    SDCONFIG_SDIO_INT_CTRL_DATA irqData;
2816 +
2817 +    ZERO_OBJECT(irqData);
2818 +
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));
2829 +    }
2830 +
2831 +        /* reset hcd state */
2832 +    ResetHcdState(pHcd);
2833 +
2834 +    DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: DeviceDetach\n"));
2835 +    return SDIO_STATUS_SUCCESS;
2836 +}
2837 +
2838 +/*
2839 + * DeviceAttach - tell core a device was inserted into a slot
2840 +*/
2841 +SDIO_STATUS DeviceAttach(PSDHCD pHcd)
2842 +{
2843 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
2844 +    PSDDEVICE pDevice = NULL;
2845 +    UINT      ii;
2846 +
2847 +
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;
2851 +    }
2852 +
2853 +    DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: DeviceAttach bdctxt:0x%X \n", (UINT32)pBusContext));
2854 +
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;
2873 +    } else {
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",
2877 +                                   status));
2878 +            return status;
2879 +        }
2880 +    }
2881 +
2882 +        /* check for SD or MMC, this must be done first as the query may involve
2883 +         * de-selecting the card */
2884 +    do {
2885 +        if (!(pHcd->CardProperties.Flags & (CARD_MMC | CARD_SD | CARD_RAW))) {
2886 +                /* none of these were discovered */
2887 +            break;
2888 +        }
2889 +        pDevice = AllocateDevice(pHcd);
2890 +        if (NULL == pDevice) {
2891 +            break;
2892 +        }
2893 +        if (pHcd->CardProperties.Flags & CARD_RAW) {
2894 +                /* set function number to 1 for IRQ processing */
2895 +            SDDEVICE_SET_SDIO_FUNCNO(pDevice,1);
2896 +        } else {
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);
2901 +                break;
2902 +            }
2903 +        }
2904 +        AddDeviceToList(pDevice);
2905 +            /* look for a function driver to handle this card */
2906 +        ProbeForFunction(pDevice, pHcd);
2907 +    } while (FALSE);
2908 +
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) {
2913 +            break;
2914 +        }
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",
2921 +                    ii, status));
2922 +            FreeDevice(pDevice);
2923 +                /* keep loading other functions */
2924 +            continue;
2925 +        }
2926 +        AddDeviceToList(pDevice);
2927 +            /* look for a function driver to handle this card */
2928 +        ProbeForFunction(pDevice, pHcd);
2929 +    }
2930 +
2931 +
2932 +    DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: DeviceAttach \n"));
2933 +    return status;
2934 +}
2935 +
2936 +static INLINE void CompleteRequestCheckCancel(PSDHCD pHcd, PSDREQUEST pReqToComplete)
2937 +{
2938 +    BOOL cancel = FALSE;
2939 +    PSDFUNCTION pFunc = NULL;
2940 +
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));
2944 +        cancel = TRUE;
2945 +        pReqToComplete->Status = SDIO_STATUS_CANCELED;
2946 +        pFunc = pReqToComplete->pFunction;
2947 +        DBG_ASSERT(pFunc != NULL);
2948 +    }
2949 +
2950 +    DoRequestCompletion(pReqToComplete, pHcd);
2951 +
2952 +    if (cancel) {
2953 +        SignalSet(&pFunc->CleanupReqSig);
2954 +    }
2955 +}
2956 +
2957 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2958 +  @function: Indicate to the SDIO bus driver (core) of an event in the host controller
2959 +             driver.
2960 +
2961 +  @function name: SDIO_HandleHcdEvent
2962 +  @prototype: SDIO_STATUS SDIO_HandleHcdEvent(PSDHCD pHcd, HCD_EVENT Event)
2963 +  @category: HD_Reference
2964 +
2965 +  @input:  pHcd - the host controller structure that was registered
2966 +           HCD_EVENT - event code
2967 +
2968 +  @output: none
2969 +
2970 +  @return: SDIO_STATUS
2971 +
2972 +  @notes:
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
2976 +
2977 +  @example: Example of indicating a card insertion event:
2978 +            SDIO_HandleHcdEvent(&Hcd, EVENT_HCD_ATTACH);
2979 +
2980 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2981 +SDIO_STATUS _SDIO_HandleHcdEvent(PSDHCD pHcd, HCD_EVENT Event)
2982 +{
2983 +    PSDREQUEST       pReq;
2984 +    PSDREQUEST       pReqToComplete = NULL;
2985 +    PSDREQUEST       pNextReq = NULL;
2986 +    SDIO_STATUS      status;
2987 +    CT_DECLARE_IRQ_SYNC_CONTEXT();
2988 +
2989 +    DBG_PRINT(SDIODBG_HCD_EVENTS, ("SDIO Bus Driver: _SDIO_HandleHcdEvent, event type 0x%X, HCD:0x%X\n",
2990 +                         Event, (UINT)pHcd));
2991 +
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;
2997 +        }
2998 +
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);
3004 +        } else {
3005 +            DBG_PRINT(SDDBG_ERROR,
3006 +              ("SDIO Bus Driver: SDIO_HandleHcdEvent Failed to acquire HCD lock \n"));
3007 +            return SDIO_STATUS_ERROR;
3008 +        }
3009 +
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 */
3013 +
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);
3023 +            }
3024 +        }
3025 +
3026 +        DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Completing Request:0x%08X \n",(INT)pReq));
3027 +
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;
3038 +            pNextReq = pReq;
3039 +        } else {
3040 +                /* complete the request */
3041 +            if (pReq->Flags & SDREQ_FLAGS_BARRIER) {
3042 +                    /* a barrier request must be completed before the next bus request is
3043 +                     * started */
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)) {
3050 +                            return status;
3051 +                        }
3052 +                        pHcd->Recursion--;
3053 +                        DBG_ASSERT(pHcd->Recursion >= 0);
3054 +                        status = _ReleaseHcdLock(pHcd);
3055 +                    } else {
3056 +                            /* reset bit */
3057 +                        AtomicTest_Clear(&pHcd->HcdFlags, HCD_REQUEST_CALL_BIT);
3058 +                    }
3059 +                }
3060 +                pReqToComplete = NULL;
3061 +            } else {
3062 +                    /* complete this after the next request has
3063 +                     * been started */
3064 +                pReqToComplete = pReq;
3065 +            }
3066 +        }
3067 +
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);
3074 +            }
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
3081 +                     * queue */
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"));
3088 +                    } else {
3089 +                        DBG_PRINT(SDIODBG_REQUESTS, ("SDIO Bus Driver: Next request in queue: 0x%X \n",
3090 +                            (INT)pNextReq));
3091 +                    }
3092 +                } else {
3093 +                    DBG_PRINT(SDIODBG_REQUESTS,
3094 +                        ("SDIO Bus Driver: Busy Queue from barrier request \n"));
3095 +                }
3096 +            }
3097 +
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);
3103 +                }
3104 +            }
3105 +            status = _ReleaseHcdLock(pHcd);
3106 +        } else {
3107 +            DBG_PRINT(SDDBG_ERROR,
3108 +              ("SDIO Bus Driver: SDIO_HandleHcdEvent Failed to acquire HCD lock \n"));
3109 +            return SDIO_STATUS_ERROR;
3110 +        }
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",
3114 +                        (INT)pNextReq));
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);
3121 +            }
3122 +        }
3123 +
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)) {
3128 +            while (1) {
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()) {
3135 +                                /* reset bit */
3136 +                            AtomicTest_Clear(&pHcd->HcdFlags, HCD_REQUEST_CALL_BIT);
3137 +                        }
3138 +                    }
3139 +                        /* re-acquire lock */
3140 +                    status = _AcquireHcdLock(pHcd);
3141 +                    if (!SDIO_SUCCESS(status)) {
3142 +                        return SDIO_STATUS_ERROR;
3143 +                    }
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);
3150 +                        }
3151 +                    }
3152 +                }  else {
3153 +                        /* we're done */
3154 +                    break;
3155 +                }
3156 +            }
3157 +        } else {
3158 +            DBG_PRINT(SDDBG_ERROR,
3159 +              ("SDIO Bus Driver: SDIO_HandleHcdEvent Failed to acquire HCD lock \n"));
3160 +            return SDIO_STATUS_ERROR;
3161 +        }
3162 +        DBG_PRINT(SDIODBG_REQUESTS, ("-SDIO Bus Driver: Transfer Done Handled \n"));
3163 +        return SDIO_STATUS_SUCCESS;
3164 +    }
3165 +
3166 +    switch(Event) {
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);
3173 +        default:
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;
3177 +    }
3178 +
3179 +}
3180 +
3181 +/* card detect helper function */
3182 +THREAD_RETURN CardDetectHelperFunction(POSKERNEL_HELPER pHelper)
3183 +{
3184 +    SDIO_STATUS       status;
3185 +    HCD_EVENT_MESSAGE message;
3186 +    INT               length;
3187 +
3188 +    DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - CardDetectHelperFunction starting up: 0x%X \n", (INT)pHelper));
3189 +
3190 +    while (1) {
3191 +
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",
3196 +                                    status));
3197 +            break;
3198 +        }
3199 +
3200 +        if (SD_IS_HELPER_SHUTTING_DOWN(pHelper)) {
3201 +                /* cleanup message queue on shutdown */
3202 +            while (1) {
3203 +                length = sizeof(message);
3204 +                    /* get a message */
3205 +                status = SDLIB_GetMessage(pBusContext->pCardDetectMsgQueue,
3206 +                                          &message, &length);
3207 +                if (!SDIO_SUCCESS(status)) {
3208 +                    break;
3209 +                }
3210 +                if (message.pHcd != NULL) {
3211 +                        /* decrement HCD reference count */
3212 +                    OS_DecHcdReference(message.pHcd);
3213 +                }
3214 +            }
3215 +
3216 +            break;
3217 +        }
3218 +
3219 +        while (1) {
3220 +            length = sizeof(message);
3221 +                /* get a message */
3222 +            status = SDLIB_GetMessage(pBusContext->pCardDetectMsgQueue,
3223 +                                      &message, &length);
3224 +            if (!SDIO_SUCCESS(status)) {
3225 +                break;
3226 +            }
3227 +
3228 +            switch (message.Event) {
3229 +                case EVENT_HCD_ATTACH:
3230 +                    DeviceAttach(message.pHcd);
3231 +                    break;
3232 +                case EVENT_HCD_DETACH:
3233 +                    DeviceDetach(message.pHcd);
3234 +                    break;
3235 +                case EVENT_HCD_CD_POLLING:
3236 +                        /* run detector */
3237 +                    RunCardDetect();
3238 +                    break;
3239 +                default:
3240 +                    DBG_ASSERT(FALSE);
3241 +                    break;
3242 +            }
3243 +
3244 +            if (message.pHcd != NULL) {
3245 +                    /* message was processed, decrement reference count */
3246 +                OS_DecHcdReference(message.pHcd);
3247 +            }
3248 +        }
3249 +    }
3250 +
3251 +    DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - Card Detect Helper Exiting.. \n"));
3252 +    return 0;
3253 +}
3254 +
3255 +
3256 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3257 +  RunCardDetect - run card detect on host controller slots that require polling
3258 +  Input:
3259 +  Output:
3260 +  Return:
3261 +  Notes: This function is called from the card detect timer thread
3262 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
3263 +void RunCardDetect(void)
3264 +{
3265 +    BOOL       CDPollingRequired = FALSE;
3266 +    PSDLIST    pListItem;
3267 +    PSDHCD     pHcd;
3268 +    BOOL       cardPresent;
3269 +
3270 +    DBG_PRINT(SDIODBG_CD_TIMER, ("+SDIO Bus Driver: RunCardDetect\n"));
3271 +
3272 +       /* protect the HCD list */
3273 +    if (!SDIO_SUCCESS(SemaphorePendInterruptable(&pBusContext->HcdListSem))) {
3274 +        DBG_ASSERT(FALSE);
3275 +        return;  /* wait interrupted */
3276 +    }
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);
3292 +                    }
3293 +                }
3294 +            } else {
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);
3300 +                    }
3301 +                }
3302 +            }
3303 +        }
3304 +
3305 +        DBG_PRINT(SDIODBG_CD_TIMER, ("SDIO Bus Driver: moving to next hcd:0x%X \n",
3306 +                                     (INT)pListItem->pNext));
3307 +    }
3308 +
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;
3317 +        }
3318 +    }
3319 +        /* release HCD list lock */
3320 +    SemaphorePost(&pBusContext->HcdListSem);
3321 +    DBG_PRINT(SDIODBG_CD_TIMER, ("-SDIO Bus Driver: RunCardDetect\n"));
3322 +}
3323 +
3324 +
3325 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3326 +  ScanSlotForCard - scan slot for a card
3327 +  Input:  pHcd - the hcd
3328 +  Output: pCardPresent - card present flag (set/cleared on return)
3329 +  Return:
3330 +  Notes:
3331 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
3332 +static SDIO_STATUS ScanSlotForCard(PSDHCD pHcd,PBOOL pCardPresent)
3333 +{
3334 +    SDIO_STATUS         status = SDIO_STATUS_SUCCESS;
3335 +    UINT8               temp;
3336 +
3337 +    DBG_PRINT(SDIODBG_CD_TIMER, ("+SDIO Bus Driver: ScanSlotForCard\n"));
3338 +
3339 +    do {
3340 +        if (!IS_CARD_PRESENT(pHcd)) {
3341 +            INT   dbgLvl;
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)) {
3347 +                break;
3348 +            }
3349 +                /* issue go-idle */
3350 +            if (IS_HCD_BUS_MODE_SPI(pHcd)) {
3351 +                _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_RESP_R1,NULL);
3352 +            } else {
3353 +                _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_NO_RESP,NULL);
3354 +            }
3355 +                /* try SDIO */
3356 +            status = TestPresence(pHcd,CARD_SDIO,NULL);
3357 +            if (SDIO_SUCCESS(status)) {
3358 +                *pCardPresent = TRUE;
3359 +                break;
3360 +            }
3361 +                /* issue go-idle */
3362 +            if (IS_HCD_BUS_MODE_SPI(pHcd)) {
3363 +                _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_RESP_R1,NULL);
3364 +            } else {
3365 +                _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_NO_RESP,NULL);
3366 +            }
3367 +                /* try SD */
3368 +            status = TestPresence(pHcd,CARD_SD,NULL);
3369 +            if (SDIO_SUCCESS(status)) {
3370 +                *pCardPresent = TRUE;
3371 +                break;
3372 +            }
3373 +                /* issue go-idle */
3374 +            if (IS_HCD_BUS_MODE_SPI(pHcd)) {
3375 +                _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_RESP_R1,NULL);
3376 +            } else {
3377 +                _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_NO_RESP,NULL);
3378 +            }
3379 +                /* try MMC */
3380 +            status = TestPresence(pHcd,CARD_MMC,NULL);
3381 +            if (SDIO_SUCCESS(status)) {
3382 +                *pCardPresent = TRUE;
3383 +                break;
3384 +            }
3385 +        } else {
3386 +            if (pHcd->CardProperties.Flags & CARD_SDIO) {
3387 +#ifdef DUMP_INT_PENDING
3388 +                temp = 0;
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));
3396 +                    }
3397 +                }
3398 +#endif
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,
3406 +                                                    CMD13,
3407 +                                                    0,
3408 +                                                    SDREQ_FLAGS_RESP_R2,
3409 +                                                    NULL);
3410 +                } else {
3411 +                    status = _IssueSimpleBusRequest(pHcd,
3412 +                                                    CMD13,
3413 +                                                    (pHcd->CardProperties.RCA << 16),
3414 +                                                    SDREQ_FLAGS_RESP_R1,NULL);
3415 +                }
3416 +            } else {
3417 +                DBG_ASSERT(FALSE);
3418 +            }
3419 +            if (!SDIO_SUCCESS(status)) {
3420 +                    /* card is gone */
3421 +                *pCardPresent = FALSE;
3422 +            }
3423 +        }
3424 +    } while (FALSE);
3425 +
3426 +    if (status == SDIO_STATUS_BUS_RESP_TIMEOUT) {
3427 +        status = SDIO_STATUS_SUCCESS;
3428 +    }
3429 +
3430 +    DBG_PRINT(SDIODBG_CD_TIMER, ("-SDIO Bus Driver: ScanSlotForCard status:%d\n",
3431 +                                 status));
3432 +
3433 +    return status;
3434 +}
3435 +
3436 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3437 +  DeviceInterrupt - handle device interrupt
3438 +  Input:  pHcd -  host controller
3439 +  Output:
3440 +  Return:
3441 +  Notes:
3442 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
3443 +SDIO_STATUS DeviceInterrupt(PSDHCD pHcd)
3444 +{
3445 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
3446 +    SDIO_STATUS status2;
3447 +    PSDREQUEST pReq = NULL;
3448 +    CT_DECLARE_IRQ_SYNC_CONTEXT();
3449 +
3450 +    DBG_PRINT(SDIODBG_FUNC_IRQ, ("+SDIO Bus Driver: DeviceInterrupt\n"));
3451 +
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;
3455 +    }
3456 +
3457 +    do {
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)) {
3462 +                return status;
3463 +            }
3464 +            if (pHcd->IrqProcState != SDHCD_IDLE) {
3465 +                status = SDIO_STATUS_ERROR;
3466 +                status2 = _ReleaseHcdLock(pHcd);
3467 +            } else {
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));
3475 +            }
3476 +            DBG_PRINT(SDIODBG_FUNC_IRQ, ("-SDIO Bus Driver: DeviceInterrupt: %d\n", status));
3477 +                /* done with RAW irqs */
3478 +            return status;
3479 +        }
3480 +
3481 +            /* pre-allocate a request to get the pending bits, we have to do this outside the
3482 +              * hcd lock acquisition */
3483 +        pReq = AllocateRequest();
3484 +
3485 +        if (NULL == pReq) {
3486 +            status = SDIO_STATUS_NO_RESOURCES;
3487 +            break;
3488 +        }
3489 +
3490 +        status = _AcquireHcdLock(pHcd);
3491 +
3492 +        if (!SDIO_SUCCESS(status)) {
3493 +            break;
3494 +        }
3495 +
3496 +        if (pHcd->IrqProcState != SDHCD_IDLE) {
3497 +            status = SDIO_STATUS_ERROR;
3498 +        } else {
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;
3508 +        }
3509 +
3510 +        status2 = _ReleaseHcdLock(pHcd);
3511 +
3512 +        if (!SDIO_SUCCESS(status2)) {
3513 +            DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: lock release error: %d\n", status2));
3514 +        }
3515 +
3516 +    } while (FALSE);
3517 +
3518 +    if (SDIO_SUCCESS(status)) {
3519 +        DBG_ASSERT(pReq != NULL);
3520 +        IssueRequestToHCD(pHcd,pReq);
3521 +        status = SDIO_STATUS_PENDING;
3522 +    } else {
3523 +        if (pReq != NULL) {
3524 +            FreeRequest(pReq);
3525 +        }
3526 +    }
3527 +
3528 +    DBG_PRINT(SDIODBG_FUNC_IRQ, ("-SDIO Bus Driver: DeviceInterrupt: %d\n", status));
3529 +    return status;
3530 +}
3531 +
3532 +
3533 +/* SDIO IRQ helper */
3534 +THREAD_RETURN SDIOIrqHelperFunction(POSKERNEL_HELPER pHelper)
3535 +{
3536 +    PSDHCD            pHcd;
3537 +    SDIO_STATUS       status;
3538 +    PSDLIST           pListItem;
3539 +    PSDDEVICE         pDevice;
3540 +    UINT8             funcMask;
3541 +    PSDDEVICE         pDeviceIRQ[7];
3542 +    UINT              deviceIrqCount = 0;
3543 +    UINT              ii;
3544 +
3545 +    DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - SDIOIrqHelperFunction starting up \n"));
3546 +
3547 +    pHcd = (PSDHCD)pHelper->pContext;
3548 +    DBG_ASSERT(pHcd != NULL);
3549 +
3550 +    while (1) {
3551 +
3552 +            /* wait for wake up event */
3553 +        status = SD_WAIT_FOR_WAKEUP(pHelper);
3554 +
3555 +        if (!SDIO_SUCCESS(status)) {
3556 +            DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver - SDIOIrqHelperFunction Pend Error:%d \n",
3557 +                                    status));
3558 +            break;
3559 +        }
3560 +
3561 +        if (SD_IS_HELPER_SHUTTING_DOWN(pHelper)) {
3562 +            break;
3563 +        }
3564 +
3565 +        DBG_PRINT(SDIODBG_FUNC_IRQ, ("SDIO Bus Driver - Pending IRQs:0x%X \n",
3566 +                                     pHcd->PendingHelperIrqs));
3567 +
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)) {
3572 +            break;
3573 +        }
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 */
3580 +                continue;
3581 +            }
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 */
3586 +                continue;
3587 +            }
3588 +                /* clear bit */
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;
3596 +            } else {
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)));
3601 +            }
3602 +        }
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]);
3610 +        }
3611 +        deviceIrqCount = 0;
3612 +    }
3613 +
3614 +    DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver - SDIOIrqHelperFunction Exiting.. \n"));
3615 +    return 0;
3616 +}
3617 +
3618 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3619 +  GetPendingIrqComplete - completion routine for getting pending IRQs
3620 +  Input:  pRequest -  completed request
3621 +  Output:
3622 +  Return:
3623 +  Notes:
3624 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
3625 +static void GetPendingIrqComplete(PSDREQUEST pReq)
3626 +{
3627 +    UINT8       intPendingMsk;
3628 +    PSDHCD      pHcd;
3629 +
3630 +    do {
3631 +        pHcd = (PSDHCD)pReq->pCompleteContext;
3632 +        DBG_ASSERT(pHcd != NULL);
3633 +
3634 +        if (!SDIO_SUCCESS(pReq->Status)) {
3635 +            DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get Interrupt pending register Err:%d\n",
3636 +                                    pReq->Status));
3637 +            break;
3638 +        }
3639 +
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)));
3643 +            break;
3644 +        }
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);
3649 +
3650 +    } while (FALSE);
3651 +
3652 +    FreeRequest(pReq);
3653 +
3654 +    DBG_PRINT(SDIODBG_FUNC_IRQ, ("-SDIO Bus Driver: GetPendingIrqComplete \n"));
3655 +}
3656 +
3657 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3658 +  ProcessPendingIrqs - processing pending Irqs
3659 +  Input:  pHcd - host controller
3660 +  Input:  IntPendingMsk -  pending irq bit mask
3661 +  Output:
3662 +  Return:
3663 +  Notes:
3664 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
3665 +static void ProcessPendingIrqs(PSDHCD pHcd, UINT8 IntPendingMsk)
3666 +{
3667 +    PSDLIST     pListItem;
3668 +    PSDDEVICE   pDevice;
3669 +    UINT8       funcMask;
3670 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
3671 +    CT_DECLARE_IRQ_SYNC_CONTEXT();
3672 +
3673 +    DBG_PRINT(SDIODBG_FUNC_IRQ, ("+SDIO Bus Driver: ProcessPendingIrqs \n"));
3674 +    do {
3675 +            /* acquire lock to protect configuration and irq enables */
3676 +        status = _AcquireHcdLock(pHcd);
3677 +        if (!SDIO_SUCCESS(status)) {
3678 +            break;
3679 +        }
3680 +
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 */
3689 +        }
3690 +
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);
3697 +            }
3698 +            status = _ReleaseHcdLock(pHcd);
3699 +            break;
3700 +        }
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)) {
3711 +            break;
3712 +        }
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 */
3719 +                continue;
3720 +            }
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 */
3725 +                continue;
3726 +            }
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);
3732 +            } else {
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)));
3737 +            }
3738 +        }
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"));
3747 +            }
3748 +        }
3749 +    } while (FALSE);
3750 +
3751 +    DBG_PRINT(SDIODBG_FUNC_IRQ, ("-SDIO Bus Driver: ProcessPendingIrqs \n"));
3752 +}
3753 +
3754 +SDIO_STATUS TryNoIrqPendingCheck(PSDDEVICE pDevice)
3755 +{
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;
3761 +    }
3762 +
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;
3767 +}
3768 +
3769 +
3770 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3771 +  SDIO_NotifyTimerTriggered - notification handler that a timer expired
3772 +  Input:  TimerID - ID of timer that expired
3773 +  Output:
3774 +  Return:
3775 +  Notes:
3776 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
3777 +void SDIO_NotifyTimerTriggered(INT TimerID)
3778 +{
3779 +
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);
3785 +            break;
3786 +        default:
3787 +            DBG_ASSERT(FALSE);
3788 +    }
3789 +
3790 +}
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
3794 --- /dev/null
3795 +++ b/drivers/sdio/stack/busdriver/sdio_bus_misc.c
3796 @@ -0,0 +1,3122 @@
3797 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3798 +@file: sdio_bus_misc.c
3799 +
3800 +@abstract: OS independent bus driver support
3801 +
3802 +#notes: this file contains miscellaneous control functions
3803 +
3804 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
3805 +
3806 +
3807 + *
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;
3811 + *
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.
3816 + *
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:
3819 + *
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.
3825 + *   Disclaimers:
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.
3834 + *
3835 + *
3836 + *  The initial developers of the original code are Seung Yi and Paul Lever
3837 + *
3838 + *  sdio@atheros.com
3839 + *
3840 + *
3841 +
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>
3850 +
3851 +
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
3858 +
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,
3865 +                               UINT8            Cmd,
3866 +                               UINT32           Argument,
3867 +                               SDREQUEST_FLAGS  Flags,
3868 +                               PSDREQUEST       pReqToUse,
3869 +                               PVOID            pData,
3870 +                               INT              Length)
3871 +{
3872 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
3873 +    PSDREQUEST  pReq;
3874 +
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;
3880 +        }
3881 +    } else {
3882 +            /* use the caller's request buffer */
3883 +        pReq = pReqToUse;
3884 +    }
3885 +
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;
3893 +    }
3894 +
3895 +    status = IssueRequestToHCD(pHcd,pReq);
3896 +
3897 +    if (NULL == pReqToUse) {
3898 +        DBG_ASSERT(pReq != NULL);
3899 +        FreeRequest(pReq);
3900 +    }
3901 +    return status;
3902 +}
3903 +
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%
3909 +
3910 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
3911 +static UINT32 ConvertVoltageCapsToOCRMask(SLOT_VOLTAGE_MASK VoltageCaps)
3912 +{
3913 +    UINT32 ocrMask;
3914 +
3915 +    ocrMask = 0;
3916 +
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;
3919 +    }
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;
3922 +    }
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;
3925 +    }
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;
3928 +    }
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;
3931 +    }
3932 +    if (VoltageCaps & SLOT_POWER_1_6V) {
3933 +        ocrMask |= SD_OCR_1_6_TO_1_7_VDD;
3934 +    }
3935 +
3936 +    return ocrMask;
3937 +}
3938 +
3939 +static UINT32 GetUsableOCRValue(UINT32 CardOCR, UINT32 SlotOCRMask)
3940 +{
3941 +    INT    i;
3942 +    UINT32 mask = 0;
3943 +
3944 +    for (i = 0; i < 32; i++) {
3945 +        mask = 1 << i;
3946 +        if ((SlotOCRMask & mask) && (CardOCR & mask)) {
3947 +            return mask;
3948 +        }
3949 +    }
3950 +
3951 +    return mask;
3952 +}
3953 +
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
3960 +  Notes:
3961 +
3962 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
3963 +static SLOT_VOLTAGE_MASK GetPowerSetting(PSDHCD pHcd, UINT32 *pOCRvalue)
3964 +{
3965 +    UINT32                      ocrMask;
3966 +    SLOT_VOLTAGE_MASK           hcdVoltage = 0;
3967 +    SLOT_VOLTAGE_MASK           hcdVMask;
3968 +    INT                         i;
3969 +
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;
3976 +    } else {
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;
3986 +                    break;
3987 +                }
3988 +            }
3989 +        }
3990 +    }
3991 +
3992 +    return hcdVoltage;
3993 +}
3994 +
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)
4000 +  Return:
4001 +  Notes:
4002 +
4003 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4004 +SDIO_STATUS TestPresence(PSDHCD          pHcd,
4005 +                         CARD_INFO_FLAGS TestType,
4006 +                         PSDREQUEST      pReq)
4007 +{
4008 +    SDIO_STATUS status = SDIO_STATUS_ERROR;
4009 +
4010 +     switch (TestType) {
4011 +        case CARD_SDIO:
4012 +                /* issue CMD5 */
4013 +            status = _IssueSimpleBusRequest(pHcd,CMD5,0,
4014 +                        SDREQ_FLAGS_RESP_SDIO_R4 | SDREQ_FLAGS_RESP_SKIP_SPI_FILT,pReq);
4015 +            break;
4016 +        case CARD_SD:
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);
4022 +
4023 +            } else {
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);
4028 +            }
4029 +            break;
4030 +        case CARD_MMC:
4031 +                 /* issue CMD1 */
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);
4035 +            } else {
4036 +                status = _IssueSimpleBusRequest(pHcd,CMD1,0,SDREQ_FLAGS_RESP_R3,pReq);
4037 +            }
4038 +            break;
4039 +        default:
4040 +            DBG_ASSERT(FALSE);
4041 +            break;
4042 +    }
4043 +
4044 +    return status;
4045 +}
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)
4053 +  Return:
4054 +  Notes:
4055 +
4056 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4057 +static SDIO_STATUS ReadOCR(PSDHCD          pHcd,
4058 +                           CARD_INFO_FLAGS ReadType,
4059 +                           PSDREQUEST      pReq,
4060 +                           UINT32          OCRValue,
4061 +                           UINT32          *pOCRValueRd)
4062 +{
4063 +    SDIO_STATUS status = SDIO_STATUS_ERROR;
4064 +
4065 +     switch (ReadType) {
4066 +        case CARD_SDIO:
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,
4071 +                                                OCRValue,
4072 +                                                SDREQ_FLAGS_RESP_SDIO_R4 |
4073 +                                                SDREQ_FLAGS_RESP_SKIP_SPI_FILT,
4074 +                                                pReq);
4075 +            } else {
4076 +                    /* native SD */
4077 +                status = _IssueSimpleBusRequest(pHcd,CMD5,
4078 +                                                OCRValue,
4079 +                                                SDREQ_FLAGS_RESP_SDIO_R4,
4080 +                                                pReq);
4081 +            }
4082 +            break;
4083 +        case CARD_SD:
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),
4089 +                                                pReq);
4090 +            } else {
4091 +                    /* SD Native uses ACMD41 */
4092 +                status = _IssueSimpleBusRequest(pHcd,ACMD41,
4093 +                                                OCRValue,
4094 +                                                SDREQ_FLAGS_APP_CMD | SDREQ_FLAGS_RESP_R3,
4095 +                                                pReq);
4096 +            }
4097 +            break;
4098 +        case CARD_MMC:
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),
4104 +                                                pReq);
4105 +            } else {
4106 +                    /* MMC Native uses CMD1 */
4107 +                status = _IssueSimpleBusRequest(pHcd,CMD1,
4108 +                                                OCRValue, SDREQ_FLAGS_RESP_R3,
4109 +                                                pReq);
4110 +            }
4111 +            break;
4112 +        default:
4113 +            DBG_ASSERT(FALSE);
4114 +            break;
4115 +    }
4116 +
4117 +    if (SDIO_SUCCESS(status) && (pOCRValueRd != NULL)) {
4118 +        *pOCRValueRd = 0;
4119 +            /* someone wants the OCR read back */
4120 +        switch (ReadType) {
4121 +            case CARD_SDIO:
4122 +                if (IS_HCD_BUS_MODE_SPI(pHcd)) {
4123 +                    *pOCRValueRd = SPI_SDIO_R4_GET_OCR(pReq->Response);
4124 +                } else {
4125 +                    *pOCRValueRd = SD_SDIO_R4_GET_OCR(pReq->Response);
4126 +                }
4127 +                break;
4128 +            case CARD_SD:
4129 +            case CARD_MMC:
4130 +                if (IS_HCD_BUS_MODE_SPI(pHcd)) {
4131 +                    *pOCRValueRd = SPI_R3_GET_OCR(pReq->Response);
4132 +                } else {
4133 +                    *pOCRValueRd = SD_R3_GET_OCR(pReq->Response);
4134 +                }
4135 +                break;
4136 +            default:
4137 +                DBG_ASSERT(FALSE);
4138 +                break;
4139 +        }
4140 +    }
4141 +    return status;
4142 +}
4143 +
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)
4149 +  Output:
4150 +  Return:
4151 +  Notes:
4152 +
4153 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4154 +SDIO_STATUS PollCardReady(PSDHCD pHcd, UINT32 OCRValue, CARD_INFO_FLAGS PollType)
4155 +{
4156 +    INT             cardReadyRetry;
4157 +    SDIO_STATUS     status;
4158 +    PSDREQUEST      pReq;
4159 +
4160 +    if (!((PollType == CARD_SDIO) || (PollType == CARD_SD) || (PollType == CARD_MMC))) {
4161 +        DBG_ASSERT(FALSE);
4162 +        return SDIO_STATUS_INVALID_PARAMETER;
4163 +    }
4164 +
4165 +    pReq = AllocateRequest();
4166 +    if (NULL == pReq) {
4167 +        return SDIO_STATUS_NO_RESOURCES;
4168 +    }
4169 +
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));
4174 +
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,
4182 +                                                CMD1,
4183 +                                                0,
4184 +                                                SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_RESP_SKIP_SPI_FILT,
4185 +                                                pReq);
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,
4190 +                                                 ACMD41,
4191 +                                                 0,
4192 +                                                 SDREQ_FLAGS_RESP_R1 |
4193 +                                                 SDREQ_FLAGS_APP_CMD |
4194 +                                                 SDREQ_FLAGS_RESP_SKIP_SPI_FILT,
4195 +                                                 pReq);
4196 +            } else {
4197 +                DBG_ASSERT(FALSE);
4198 +            }
4199 +        } else {
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);
4204 +        }
4205 +
4206 +        if (!SDIO_SUCCESS(status)) {
4207 +            DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to issue CMD to poll ready \n"));
4208 +            break;
4209 +        }
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"));
4214 +                    break;
4215 +                }
4216 +            } else {
4217 +                if (SD_SDIO_R4_IS_CARD_READY(pReq->Response)) {
4218 +                    DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SDIO Card Ready! \n"));
4219 +                    break;
4220 +                }
4221 +            }
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"));
4228 +                    break;
4229 +                }
4230 +            } else {
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"));
4234 +                    break;
4235 +                }
4236 +            }
4237 +        } else {
4238 +            DBG_ASSERT(FALSE);
4239 +        }
4240 +        cardReadyRetry--;
4241 +            /* delay */
4242 +        status = OSSleep(OCR_READY_CHECK_DELAY_MS);
4243 +        if (!SDIO_SUCCESS(status)){
4244 +            break;
4245 +        }
4246 +    }
4247 +
4248 +    if (0 == cardReadyRetry) {
4249 +        DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Card Ready timeout! \n"));
4250 +        status = SDIO_STATUS_DEVICE_ERROR;
4251 +    }
4252 +
4253 +    FreeRequest(pReq);
4254 +
4255 +    return status;
4256 +}
4257 +
4258 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4259 +  AdjustSlotPower - adjust slot power
4260 +  Input:  pHcd - HCD object
4261 +  Output: pOCRvalue - ocr value to use
4262 +  Return:
4263 +  Notes:
4264 +
4265 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4266 +static SDIO_STATUS AdjustSlotPower(PSDHCD pHcd, UINT32 *pOCRvalue)
4267 +{
4268 +    SDCONFIG_POWER_CTRL_DATA    pwrSetting;
4269 +    SDIO_STATUS                 status = SDIO_STATUS_SUCCESS;
4270 +
4271 +    ZERO_OBJECT(pwrSetting);
4272 +    DBG_PRINT(SDDBG_TRACE,
4273 +        ("SDIO Bus Driver: Adjusting Slot Power, Requesting adjustment for OCR:0x%8.8X \n",
4274 +         *pOCRvalue));
4275 +
4276 +    do {
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;
4283 +            break;
4284 +        }
4285 +
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"));
4291 +            break;
4292 +        }
4293 +            /* delay for power to settle */
4294 +        OSSleep(pBusContext->PowerSettleDelay);
4295 +            /* save off for drivers */
4296 +        pHcd->CardProperties.CardVoltage  = pwrSetting.SlotPowerVoltageMask;
4297 +
4298 +    } while (FALSE);
4299 +
4300 +    return status;
4301 +}
4302 +
4303 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4304 +  ConvertEncodedTransSpeed - convert encoded TRANS_SPEED value to a clock rate
4305 +  Input:  TransSpeedValue - encoded transfer speed value
4306 +  Output:
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)
4312 +{
4313 +    SD_BUSCLOCK_RATE transfMul = 0;
4314 +    UINT8            timeVal = 0;
4315 +
4316 +    switch (TransSpeedValue & TRANSFER_UNIT_MULTIPIER_MASK) {
4317 +        case 0:
4318 +            transfMul = 10000;
4319 +            break;
4320 +        case 1:
4321 +            transfMul = 100000;
4322 +            break;
4323 +        case 2:
4324 +            transfMul = 1000000;
4325 +            break;
4326 +        case 3:
4327 +            transfMul = 10000000;
4328 +            break;
4329 +        default:
4330 +            transfMul = 0;
4331 +            DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: Card transfer multipler is wrong (val=0x%X)! \n",
4332 +                                   TransSpeedValue));
4333 +            break;
4334 +    }
4335 +
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));
4355 +        break;
4356 +    }
4357 +
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;
4362 +    }
4363 +
4364 +    return 0;
4365 +}
4366 +
4367 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4368 +  SelectDeselectCard - Select or deselect a card
4369 +  Input:  pHcd - HCD object
4370 +          Select - select the card
4371 +  Output:
4372 +  Return: status
4373 +  Notes:
4374 +
4375 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4376 +static SDIO_STATUS SelectDeselectCard(PSDHCD pHcd, BOOL Select)
4377 +{
4378 +    SDIO_STATUS status;
4379 +
4380 +    if (IS_HCD_BUS_MODE_SPI(pHcd)) {
4381 +            /* SPI mode cards do not support selection */
4382 +        status = SDIO_STATUS_SUCCESS;
4383 +    } else {
4384 +        if (!Select) {
4385 +                /* deselect, note that deselecting a card does not return a response */
4386 +            status = _IssueSimpleBusRequest(pHcd,
4387 +                                            CMD7,0,
4388 +                                            SDREQ_FLAGS_NO_RESP,NULL);
4389 +        } else {
4390 +                /* select */
4391 +            status = _IssueSimpleBusRequest(pHcd,
4392 +                                            CMD7,(pHcd->CardProperties.RCA << 16),
4393 +                                            SDREQ_FLAGS_RESP_R1B,NULL);
4394 +        }
4395 +    }
4396 +
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));
4400 +    }
4401 +    return status;
4402 +}
4403 +
4404 +/* reorder a buffer by swapping MSB with LSB */
4405 +static void ReorderBuffer(UINT8 *pBuffer, INT Bytes)
4406 +{
4407 +    UINT8 *pEnd;
4408 +    UINT8 temp;
4409 +
4410 +    DBG_ASSERT(!(Bytes & 1));
4411 +        /* point to the end */
4412 +    pEnd = &pBuffer[Bytes - 1];
4413 +        /* divide in half */
4414 +    Bytes = Bytes >> 1;
4415 +
4416 +    while (Bytes) {
4417 +        temp = *pBuffer;
4418 +            /* swap bytes */
4419 +        *pBuffer = *pEnd;
4420 +        *pEnd = temp;
4421 +        pBuffer++;
4422 +        pEnd--;
4423 +        Bytes--;
4424 +    }
4425 +}
4426 +
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)
4433 +
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
4439 +  Return: status
4440 +  Notes:
4441 +
4442 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4443 +static SDIO_STATUS GetBusParameters(PSDHCD pHcd, PSDCONFIG_BUS_MODE_DATA pBusMode)
4444 +{
4445 +    SDIO_STATUS                        status = SDIO_STATUS_SUCCESS;
4446 +    UINT8                              temp;
4447 +    UINT32                             tplAddr;
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;
4453 +
4454 +
4455 +    if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_SPI) {
4456 +        spiMode = TRUE;
4457 +    }
4458 +
4459 +    if (!spiMode) {
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;
4463 +    }
4464 +        /* set operational parameters */
4465 +    pBusMode->ClockRate = pBusContext->DefaultOperClock;
4466 +    pHcd->CardProperties.OperBlockLenLimit = pBusContext->DefaultOperBlockLen;
4467 +    pHcd->CardProperties.OperBlockCountLimit = pBusContext->DefaultOperBlockCount;
4468 +
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);
4474 +
4475 +    if (!spiMode) {
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)) ) {
4480 +
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"));
4484 +            }
4485 +                /* force to 1 bit mode */
4486 +            SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_1_BIT);
4487 +        }
4488 +    }
4489 +
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 */
4493 +    do {
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;
4499 +                break;
4500 +            }
4501 +        }
4502 +
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);
4506 +        }
4507 +
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"));
4518 +                if (!spiMode) {
4519 +                        /* switch it to 1 bit mode */
4520 +                    SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_1_BIT);
4521 +                }
4522 +                status = SDIO_STATUS_SUCCESS;
4523 +            } else {
4524 +                    /* we have to reorder this buffer since the SCR is sent MSB first on the data
4525 +                     * data bus */
4526 +                ReorderBuffer(scrRegister,SD_SCR_BYTES);
4527 +                    /* got the SCR */
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;
4536 +                        break;
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;
4540 +                        break;
4541 +                    default:
4542 +                        DBG_PRINT(SDDBG_WARN, ("SD Spec Revision is greater than 1.10 \n"));
4543 +                        pHcd->CardProperties.SD_MMC_Revision = SD_REVISION_1_10;
4544 +                        break;
4545 +                }
4546 +
4547 +                if (!(GET_SD_SCR_BUSWIDTHS(scrRegister) & SCR_BUS_SUPPORTS_4_BIT)) {
4548 +                    if (!spiMode) {
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);
4552 +                    }
4553 +                }
4554 +            }
4555 +        }
4556 +
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"));
4563 +                break;
4564 +            }
4565 +                /* Get CSD for SD or MMC cards */
4566 +            if (spiMode) {
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,
4570 +                                            pReq,
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);
4577 +                }
4578 +            } else {
4579 +                status = _IssueSimpleBusRequest(pHcd,
4580 +                                                CMD9,
4581 +                                                (pHcd->CardProperties.RCA << 16),
4582 +                                                SDREQ_FLAGS_RESP_R2,
4583 +                                                pReq);
4584 +                if (SDIO_SUCCESS(status)) {
4585 +                        /* save the CSD */
4586 +                    memcpy(pHcd->CardProperties.CardCSD,pReq->Response,MAX_CARD_RESPONSE_BYTES);
4587 +                }
4588 +            }
4589 +
4590 +            if (!SDIO_SUCCESS(status)) {
4591 +                DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get CSD, Err:%d \n",
4592 +                                        status));
4593 +                break;
4594 +            }
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;
4605 +                        break;
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;
4609 +                        break;
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;
4613 +                        break;
4614 +                    default:
4615 +                        pHcd->CardProperties.SD_MMC_Revision = MMC_REVISION_3_1;
4616 +                        DBG_PRINT(SDDBG_WARN, ("MMC Spec version greater than 4.1\n"));
4617 +                        break;
4618 +                }
4619 +            }
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"));
4624 +                break;
4625 +            }
4626 +        }
4627 +
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) &&
4632 +             !spiMode)  {
4633 +            UINT32 arg;
4634 +            PUINT8 pSwitchStatusBlock = KernelAlloc(SD_SWITCH_FUNC_STATUS_BLOCK_BYTES);
4635 +
4636 +            if (NULL == pSwitchStatusBlock) {
4637 +                status = SDIO_STATUS_NO_RESOURCES;
4638 +                break;
4639 +            }
4640 +
4641 +            arg = SD_SWITCH_FUNC_ARG_GROUP_CHECK(SD_SWITCH_HIGH_SPEED_GROUP,
4642 +                                                 SD_SWITCH_HIGH_SPEED_FUNC_NO);
4643 +
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));
4646 +
4647 +                /* issue simple data transfer request to read the switch status */
4648 +            status = _IssueBusRequestBd(pHcd,
4649 +                                        CMD6,
4650 +                                        arg,
4651 +                                        SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_DATA_TRANS,
4652 +                                        pReq,
4653 +                                        pSwitchStatusBlock,
4654 +                                        SD_SWITCH_FUNC_STATUS_BLOCK_BYTES);
4655 +
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");
4668 +                } else {
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;
4675 +                    }
4676 +                }
4677 +            } else {
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;
4681 +            }
4682 +
4683 +            KernelFree(pSwitchStatusBlock);
4684 +        }
4685 +
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) &&
4689 +             !spiMode)  {
4690 +                /* for MMC cards, get the Extended CSD to get the High speed and
4691 +                 * wide bus paramaters */
4692 +
4693 +            PUINT8 pExtData = KernelAlloc(MMC_EXT_CSD_SIZE);
4694 +
4695 +            if (NULL == pExtData) {
4696 +                status = SDIO_STATUS_NO_RESOURCES;
4697 +                break;
4698 +            }
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,
4702 +                                        pReq,
4703 +                                        pExtData,
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) {
4710 +                        /* try 52 Mhz */
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) {
4714 +                        /* try 26MHZ */
4715 +                    cardReportedRate = 26000000;
4716 +                    pBusMode->BusModeFlags |= SDCONFIG_BUS_MODE_MMC_HS;
4717 +                } else {
4718 +                        /* doesn't report high speed capable */
4719 +                    cardReportedRate = 0;
4720 +                }
4721 +
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);
4728 +                    } else {
4729 +                        /* we leave it to default to 1 bit mode */
4730 +                    }
4731 +                }
4732 +            } else {
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;
4737 +            }
4738 +
4739 +            KernelFree(pExtData);
4740 +        }
4741 +
4742 +        if (pHcd->CardProperties.Flags & (CARD_SD | CARD_MMC)) {
4743 +
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 */
4749 +            }
4750 +
4751 +            if (cardReportedRate != 0) {
4752 +                     /* adjust clock based on what the card can handle */
4753 +                ADJUST_OPER_CLOCK(pBusMode,cardReportedRate);
4754 +            } else {
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");
4760 +                }
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);
4764 +                } else {
4765 +                    ADJUST_OPER_CLOCK(pBusMode,MMC_MAX_BUS_CLOCK);
4766 +                }
4767 +            }
4768 +        }
4769 +
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)) {
4777 +                break;
4778 +            }
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)) {
4785 +                    if (!spiMode) {
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);
4789 +                    }
4790 +                }
4791 +            }
4792 +
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) &&
4796 +                !spiMode) {
4797 +                UCHAR hsControl = 0;
4798 +
4799 +                status = Cmd52ReadByteCommon(pHcd->pPseudoDev,
4800 +                                             SDIO_HS_CONTROL_REG,
4801 +                                             &hsControl);
4802 +
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;
4808 +                } else {
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;
4812 +                    }
4813 +                }
4814 +
4815 +            }
4816 +
4817 +            cardReportedRate = 0;
4818 +            temp = sizeof(func0ext);
4819 +            tplAddr = pHcd->CardProperties.CommonCISPtr;
4820 +                /* get the FUNCE tuple */
4821 +            status = SDLIB_FindTuple(pHcd->pPseudoDev,
4822 +                                     CISTPL_FUNCE,
4823 +                                     &tplAddr,
4824 +                                     (PUINT8)&func0ext,
4825 +                                     &temp);
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;
4830 +            } else {
4831 +                    /* convert encoded value to rate */
4832 +                cardReportedRate = ConvertEncodedTransSpeed(func0ext.MaxTransSpeed);
4833 +            }
4834 +
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;
4842 +                    }
4843 +                } else {
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;
4848 +                    }
4849 +                }
4850 +                    /* adjust clock based on what the card can handle */
4851 +                ADJUST_OPER_CLOCK(pBusMode,cardReportedRate);
4852 +
4853 +            } else {
4854 +                    /* set a reasonable default */
4855 +                ADJUST_OPER_CLOCK(pBusMode,SD_MAX_BUS_CLOCK);
4856 +            }
4857 +        }
4858 +    } while (FALSE);
4859 +
4860 +    if (pReq != NULL) {
4861 +        FreeRequest(pReq);
4862 +    }
4863 +    return status;
4864 +}
4865 +
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
4871 +  Return: status
4872 +  Notes:
4873 +
4874 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4875 +SDIO_STATUS SetOperationalBusMode(PSDDEVICE                pDevice,
4876 +                                  PSDCONFIG_BUS_MODE_DATA  pBusMode)
4877 +{
4878 +    SDIO_STATUS     status = SDIO_STATUS_SUCCESS;
4879 +    UCHAR           regData;
4880 +    UINT32          arg;
4881 +    UINT32          switcharg;
4882 +    PSDHCD          pHcd = pDevice->pHcd;
4883 +
4884 +        /* synchronize access for updating bus mode settings */
4885 +    status = SemaphorePendInterruptable(&pDevice->pHcd->ConfigureOpsSem);
4886 +    if (!SDIO_SUCCESS(status)) {
4887 +        return status;
4888 +    }
4889 +
4890 +    do {
4891 +
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
4895 +                 * polling */
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",
4899 +                                        status));
4900 +            }
4901 +                /* nothing more to do */
4902 +            break;
4903 +        }
4904 +
4905 +
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);
4911 +            break;
4912 +        }
4913 +
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"));
4919 +                break;
4920 +            }
4921 +        }
4922 +
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"));
4928 +                break;
4929 +            }
4930 +        }
4931 +
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)) {
4937 +
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,
4943 +                                            MMC_CMD_SWITCH,
4944 +                                            switcharg,
4945 +                                            SDREQ_FLAGS_RESP_R1B,
4946 +                                            NULL);
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));
4951 +                break;
4952 +            }
4953 +
4954 +            DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: High Speed MMC enabled (arg:0x%X)\n",
4955 +                switcharg));
4956 +        }
4957 +
4958 +            /* before setting bus mode and clock in the HCD, switch card to high speed mode
4959 +             * if necessary */
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)) {
4963 +            UINT32     arg;
4964 +            PUINT8     pSwitchStatusBlock;
4965 +
4966 +            pSwitchStatusBlock = KernelAlloc(SD_SWITCH_FUNC_STATUS_BLOCK_BYTES);
4967 +
4968 +            if (NULL == pSwitchStatusBlock) {
4969 +                status = SDIO_STATUS_NO_RESOURCES;
4970 +                break;
4971 +            }
4972 +
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);
4976 +
4977 +            DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Setting SD Card for High Speed mode (CMD6 arg:0x%X)\n",arg));
4978 +
4979 +                /* issue simple data transfer request to switch modes */
4980 +            status = _IssueBusRequestBd(pHcd,
4981 +                                        CMD6,
4982 +                                        arg,
4983 +                                        SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_DATA_TRANS,
4984 +                                        NULL,
4985 +                                        pSwitchStatusBlock,
4986 +                                        SD_SWITCH_FUNC_STATUS_BLOCK_BYTES);
4987 +
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;
4996 +                }
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;
5002 +                }
5003 +                if (SDIO_SUCCESS(status)) {
5004 +                    DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD High Speed Mode Enabled \n"));
5005 +                } else {
5006 +                    SDLIB_PrintBuffer(pSwitchStatusBlock,
5007 +                                      SD_SWITCH_FUNC_STATUS_BLOCK_BYTES,
5008 +                                       "SDIO Bus Driver: SD Switch Status Block Error");
5009 +                }
5010 +            } else {
5011 +                DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to Set SD High Speed Mode (%d) \n",status));
5012 +            }
5013 +            KernelFree(pSwitchStatusBlock);
5014 +
5015 +            if (!SDIO_SUCCESS(status)) {
5016 +                break;
5017 +            }
5018 +        }
5019 +
5020 +            /* enable/disable high speed mode for SDIO card */
5021 +        if (pHcd->CardProperties.Flags & CARD_SDIO) {
5022 +            BOOL doSet = TRUE;
5023 +
5024 +            if ((pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_SD_HS) &&
5025 +                !(SDDEVICE_GET_BUSMODE_FLAGS(pDevice) & SDCONFIG_BUS_MODE_SD_HS)) {
5026 +                    /* enable */
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)) {
5030 +                    /* disable */
5031 +                regData = 0;
5032 +            } else {
5033 +                    /* do nothing */
5034 +                doSet = FALSE;
5035 +            }
5036 +
5037 +            if (doSet) {
5038 +                status = Cmd52WriteByteCommon(pDevice,
5039 +                                              SDIO_HS_CONTROL_REG,
5040 +                                              &regData);
5041 +
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));
5045 +                    break;
5046 +                } else {
5047 +                    DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver:SDIO Card %s for High Speed mode \n",
5048 +                                    (SDIO_HS_CONTROL_EHS == regData) ? "enabled":"disabled" ));
5049 +                }
5050 +            }
5051 +        }
5052 +
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,
5057 +                                   pBusMode,
5058 +                                   sizeof(SDCONFIG_BUS_MODE_DATA));
5059 +
5060 +        if (!SDIO_SUCCESS(status)) {
5061 +            DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set bus mode in hcd : Err:%d \n",
5062 +                                    status));
5063 +            break;
5064 +        }
5065 +
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"));
5070 +            break;
5071 +        }
5072 +
5073 +        if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_SPI) {
5074 +                /* nothing more to do for SPI */
5075 +            break;
5076 +        }
5077 +
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,
5083 +                                                ACMD42,
5084 +                                                0, /* disable CD */
5085 +                                                SDREQ_FLAGS_APP_CMD | SDREQ_FLAGS_RESP_R1,
5086 +                                                NULL);
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 */
5090 +                }
5091 +                arg = SD_ACMD6_BUS_WIDTH_4_BIT;
5092 +            } else {
5093 +                    /* don't need to turn off CD in 1 bit mode, just set mode */
5094 +                arg = SD_ACMD6_BUS_WIDTH_1_BIT;
5095 +
5096 +            }
5097 +                /* set the bus width */
5098 +            status = _IssueSimpleBusRequest(pHcd,
5099 +                                            ACMD6,
5100 +                                            arg, /* set bus mode */
5101 +                                            SDREQ_FLAGS_APP_CMD | SDREQ_FLAGS_RESP_R1,
5102 +                                            NULL);
5103 +            if (!SDIO_SUCCESS(status)) {
5104 +                DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set bus width: %d \n",
5105 +                                        status));
5106 +                break;
5107 +            }
5108 +        }
5109 +            /* set bus width for SDIO cards */
5110 +        if (pHcd->CardProperties.Flags & CARD_SDIO) {
5111 +                /* default */
5112 +            regData = CARD_DETECT_DISABLE | SDIO_BUS_WIDTH_1_BIT;
5113 +
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"));
5118 +            } else {
5119 +                DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Enabling 1 bit mode on card \n"));
5120 +            }
5121 +            status = Cmd52WriteByteCommon(pDevice,
5122 +                                          SDIO_BUS_IF_REG,
5123 +                                          &regData);
5124 +            if (!SDIO_SUCCESS(status)) {
5125 +                DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set bus mode in Card : Err:%d\n",
5126 +                                        status));
5127 +                break;
5128 +            }
5129 +
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;
5137 +
5138 +                DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: 4-Bit Multi-blk Interrupt support enabled\n"));
5139 +            } else {
5140 +                    /* make sure this is disabled */
5141 +                pHcd->CardProperties.SDIOCaps &= ~SDIO_CAPS_ENB_INT_MULTI_BLK;
5142 +            }
5143 +
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",
5149 +                                        status));
5150 +                break;
5151 +            }
5152 +        }
5153 +
5154 +            /* set data bus width for MMC */
5155 +        if (pHcd->CardProperties.Flags & CARD_MMC) {
5156 +            UINT8  buswidth = 0;
5157 +
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;
5162 +            } else {
5163 +                /* normal 1 bit mode .. nothing to do */
5164 +                break;
5165 +            }
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,
5170 +                                             buswidth);
5171 +
5172 +            status = _IssueSimpleBusRequest(pHcd,
5173 +                                            MMC_CMD_SWITCH,
5174 +                                            switcharg,
5175 +                                            SDREQ_FLAGS_RESP_R1B,
5176 +                                            NULL);
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));
5180 +                break;
5181 +            }
5182 +
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",
5185 +                      switcharg));
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",
5188 +                      switcharg));
5189 +            }
5190 +        }
5191 +
5192 +    } while (FALSE);
5193 +
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;
5199 +    }
5200 +
5201 +    SemaphorePost(&pDevice->pHcd->ConfigureOpsSem);
5202 +
5203 +    return status;
5204 +}
5205 +
5206 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5207 +  CardInitSetup - setup host for card initialization
5208 +  Input:  pHcd - HCD object
5209 +  Output:
5210 +  Return:
5211 +  Notes:
5212 +
5213 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
5214 +SDIO_STATUS CardInitSetup(PSDHCD pHcd)
5215 +{
5216 +    SDCONFIG_INIT_CLOCKS_DATA   initClocks;
5217 +    SDCONFIG_BUS_MODE_DATA      busMode;
5218 +    UINT32                      OCRvalue;
5219 +    SDIO_STATUS                 status = SDIO_STATUS_SUCCESS;
5220 +
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;
5226 +
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;
5233 +    }
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;
5239 +    }
5240 +
5241 +        /* set initial VDD, starting at the highest allowable voltage and working
5242 +         * our way down */
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;
5255 +    } else {
5256 +        DBG_ASSERT(FALSE);
5257 +        OCRvalue = 0;
5258 +    }
5259 +
5260 +    do {
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"));
5265 +            break;
5266 +        }
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"));
5270 +            break;
5271 +        }
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"));
5275 +            break;
5276 +        }
5277 +
5278 +    } while(FALSE);
5279 +
5280 +    return status;
5281 +}
5282 +
5283 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5284 +  SDInitializeCard - initialize card
5285 +  Input:  pHcd - HCD object
5286 +  Output: pProperties - card properties
5287 +  Return:
5288 +  Notes:
5289 +
5290 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
5291 +SDIO_STATUS SDInitializeCard(PSDHCD pHcd)
5292 +{
5293 +    SDCONFIG_BUS_MODE_DATA      busMode;
5294 +    SDIO_STATUS                 status = SDIO_STATUS_SUCCESS;
5295 +    PSDREQUEST                  pReq = NULL;
5296 +    UINT32                      OCRvalue;
5297 +    UINT32                      tplAddr;
5298 +    UINT8                       temp;
5299 +    struct SDIO_MANFID_TPL      manfid;
5300 +    SDCONFIG_WP_VALUE           wpValue;
5301 +    UINT8                       cisBuffer[3];
5302 +
5303 +    OCRvalue = 0;
5304 +
5305 +    do {
5306 +        if (IS_HCD_BUS_MODE_SPI(pHcd)) {
5307 +            DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Initializing card in SPI mode \n"));
5308 +        } else {
5309 +            DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Initializing card in MMC/SD mode \n"));
5310 +        }
5311 +
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"));
5316 +            break;
5317 +        }
5318 +        memset(pReq, 0, sizeof(SDREQUEST));
5319 +
5320 +        status = CardInitSetup(pHcd);
5321 +        if (!SDIO_SUCCESS(status)) {
5322 +            DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to setup card \n"));
5323 +            break;
5324 +        }
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"));
5328 +        } else {
5329 +            if (wpValue) {
5330 +                pHcd->CardProperties.Flags |= CARD_SD_WP;
5331 +                DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: SD WP switch is on \n"));
5332 +            }
5333 +        }
5334 +
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)) {
5342 +                INT ii = 256;
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);
5347 +                    OSSleep(20);
5348 +                }
5349 +                DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: cmd0 go SPI retries:(256) %d\n", ii));
5350 +
5351 +            } else {
5352 +                status = _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_NO_RESP,pReq);
5353 +            }
5354 +            if (!SDIO_SUCCESS(status)) {
5355 +                DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: go-idle failed! \n"));
5356 +                break;
5357 +            }
5358 +        }
5359 +
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)) {
5366 +                    /* handle SPI */
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;
5371 +                }
5372 +            } else {
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;
5378 +                }
5379 +
5380 +            }
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;
5385 +                break;
5386 +            }
5387 +            pHcd->CardProperties.Flags |= CARD_SDIO;
5388 +
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"));
5396 +                break;
5397 +            }
5398 +                /* poll for SDIO card ready */
5399 +            status = PollCardReady(pHcd,OCRvalue,CARD_SDIO);
5400 +            if (!SDIO_SUCCESS(status)) {
5401 +                break;
5402 +            }
5403 +        } else if (status != SDIO_STATUS_BUS_RESP_TIMEOUT){
5404 +                /* major error in hcd, bail */
5405 +            break;
5406 +        }
5407 +
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 */
5411 +            goto prepareCard;
5412 +        }
5413 +
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);
5418 +            } else {
5419 +                status = _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_NO_RESP,pReq);
5420 +            }
5421 +            if (!SDIO_SUCCESS(status)) {
5422 +                DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: go-idle failed! \n"));
5423 +                break;
5424 +            }
5425 +        }
5426 +
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",
5440 +                                            status));
5441 +                    break;
5442 +                }
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"));
5447 +                    break;
5448 +                }
5449 +            } else {
5450 +                 DBG_ASSERT((pHcd->CardProperties.Flags & (CARD_SD | CARD_SDIO)));
5451 +                 DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SDIO Combo Card detected \n"));
5452 +            }
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;
5463 +                } else {
5464 +                    break;
5465 +                }
5466 +            } else {
5467 +                DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD Memory ready. \n"));
5468 +            }
5469 +                /* we're done, no need to check for MMC */
5470 +            goto prepareCard;
5471 +        } else if (status != SDIO_STATUS_BUS_RESP_TIMEOUT){
5472 +                /* major error in hcd, bail */
5473 +            break;
5474 +        }
5475 +
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);
5482 +        } else {
5483 +            status = _IssueSimpleBusRequest(pHcd,CMD0,0,SDREQ_FLAGS_NO_RESP,pReq);
5484 +        }
5485 +        if (!SDIO_SUCCESS(status)) {
5486 +            DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: go-idle failed! \n"));
5487 +            break;
5488 +        }
5489 +
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"));
5494 +            break;
5495 +        }
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)",
5502 +                                    status));
5503 +            break;
5504 +        }
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"));
5510 +             break;
5511 +        }
5512 +            /* poll for MMC card ready */
5513 +        status = PollCardReady(pHcd,OCRvalue,CARD_MMC);
5514 +        if (!SDIO_SUCCESS(status)) {
5515 +            break;
5516 +        }
5517 +            /* fall through and prepare MMC card */
5518 +
5519 +prepareCard:
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"));
5529 +                break;
5530 +            }
5531 +        }
5532 +
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"));
5540 +                    break;
5541 +                }
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));
5556 +                    break;
5557 +                }
5558 +            } else {
5559 +                DBG_ASSERT(FALSE);
5560 +            }
5561 +        }
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"));
5567 +            break;
5568 +        }
5569 +        DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver, Card now Selected.. \n"));
5570 +
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)) {
5575 +                break;
5576 +            }
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;
5582 +                    break;
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;
5586 +                    break;
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;
5590 +                    break;
5591 +                default:
5592 +                    DBG_PRINT(SDDBG_WARN, ("SDIO Warning: unknown SDIO revision, treating like 1.0 device \n"));
5593 +                    pHcd->CardProperties.SDIORevision = SDIO_REVISION_1_00;
5594 +                    break;
5595 +            }
5596 +                /* get the common CIS ptr */
5597 +            status = Cmd52ReadMultipleCommon(pHcd->pPseudoDev,
5598 +                                             SDIO_CMN_CIS_PTR_LOW_REG,
5599 +                                             cisBuffer,
5600 +                                             3);
5601 +            if (!SDIO_SUCCESS(status)) {
5602 +                DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get CIS ptr, Err:%d", status));
5603 +                break;
5604 +            }
5605 +                /* this is endian-safe*/
5606 +            pHcd->CardProperties.CommonCISPtr = ((UINT32)cisBuffer[0]) |
5607 +                                                (((UINT32)cisBuffer[1]) << 8) |
5608 +                                                (((UINT32)cisBuffer[2]) << 16);
5609 +
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,
5615 +                                     CISTPL_MANFID,
5616 +                                     &tplAddr,
5617 +                                     (PUINT8)&manfid,
5618 +                                     &temp);
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;
5622 +            } else {
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));
5631 +            }
5632 +
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
5638 +                         * than 200 mA */
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));
5648 +                                break;
5649 +                            }
5650 +                                /* mark that the card is high power */
5651 +                            pHcd->CardProperties.Flags |= CARD_HIPWR;
5652 +
5653 +                            DBG_PRINT(SDDBG_TRACE,
5654 +                               ("SDIO Busdriver: Power Control Enabled on SDIO (1.10 or greater) card \n"));
5655 +                        } else {
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 */
5660 +                        }
5661 +                    } else {
5662 +                        DBG_PRINT(SDDBG_TRACE,
5663 +                            ("SDIO Busdriver: SDIO 1.10 (or greater) card draws less than 200mA \n"));
5664 +                    }
5665 +                } else {
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 */
5669 +                }
5670 +            }
5671 +        }
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)) {
5678 +            break;
5679 +        }
5680 +
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;
5687 +            } else {
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"));
5693 +                    break;
5694 +                }
5695 +            }
5696 +        }
5697 +
5698 +        status = SetOperationalBusMode(pHcd->pPseudoDev, &busMode);
5699 +
5700 +        if (!SDIO_SUCCESS(status)) {
5701 +            DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set operational bus mode\n"));
5702 +            break;
5703 +        }
5704 +
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));
5709 +
5710 +    } while (FALSE);
5711 +
5712 +    if (pReq != NULL) {
5713 +        FreeRequest(pReq);
5714 +    }
5715 +
5716 +    return status;
5717 +}
5718 +
5719 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5720 +  SDQuerySDMMCInfo - query MMC card info
5721 +  Input:  pDevice - device
5722 +  Output:
5723 +  Return:
5724 +  Notes:
5725 +
5726 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
5727 +SDIO_STATUS SDQuerySDMMCInfo(PSDDEVICE pDevice)
5728 +{
5729 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
5730 +    PSDREQUEST  pReq = NULL;
5731 +    UINT8       CID[MAX_CSD_CID_BYTES];
5732 +
5733 +    do {
5734 +        pReq = AllocateRequest();
5735 +        if (NULL == pReq) {
5736 +            status = SDIO_STATUS_NO_RESOURCES;
5737 +            break;
5738 +        }
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"));
5743 +            break;
5744 +        }
5745 +
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,
5750 +                                        pReq,
5751 +                                        CID,
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);
5756 +            }
5757 +        } else {
5758 +                /* get the CID */
5759 +            status = _IssueSimpleBusRequest(pDevice->pHcd,
5760 +                                            CMD10,
5761 +                                            (SDDEVICE_GET_CARD_RCA(pDevice) << 16),
5762 +                                            SDREQ_FLAGS_RESP_R2,
5763 +                                            pReq);
5764 +            if (SDIO_SUCCESS(status)) {
5765 +                    /* extract it from the reponse */
5766 +                memcpy(CID,pReq->Response,MAX_CSD_CID_BYTES);
5767 +            }
5768 +        }
5769 +
5770 +        if (!SDIO_SUCCESS(status)) {
5771 +            DBG_PRINT(SDDBG_WARN, ("SDQuerySDMMCInfo: failed to get CID. \n"));
5772 +            status = SDIO_STATUS_SUCCESS;
5773 +        } else {
5774 +            pDevice->pId[0].SDMMC_ManfacturerID = GET_SD_CID_MANFID(CID);
5775 +            pDevice->pId[0].SDMMC_OEMApplicationID = GET_SD_CID_OEMID(CID);
5776 +#if DEBUG
5777 +            {
5778 +                char pBuf[7];
5779 +
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);
5787 +                    pBuf[6] = 0;
5788 +                } else {
5789 +                    pBuf[5] = 0;
5790 +                }
5791 +                DBG_PRINT(SDDBG_TRACE, ("SDQuerySDMMCInfo: Product String: %s\n", pBuf));
5792 +            }
5793 +#endif
5794 +            DBG_PRINT(SDDBG_TRACE, ("SDQuerySDMMCInfo: ManfID: 0x%X, OEMID:0x%X \n",
5795 +                       pDevice->pId[0].SDMMC_ManfacturerID, pDevice->pId[0].SDMMC_OEMApplicationID));
5796 +        }
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"));
5801 +            break;
5802 +        }
5803 +    } while (FALSE);
5804 +
5805 +    if (pReq != NULL) {
5806 +        FreeRequest(pReq);
5807 +    }
5808 +
5809 +    return status;
5810 +}
5811 +
5812 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5813 +  SDQuerySDIOInfo - query SDIO card info
5814 +  Input:  pDevice - the device
5815 +  Output:
5816 +  Return:
5817 +  Notes:
5818 +
5819 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
5820 +SDIO_STATUS SDQuerySDIOInfo(PSDDEVICE pDevice)
5821 +{
5822 +    SDIO_STATUS     status = SDIO_STATUS_SUCCESS;
5823 +    UINT32          faddress;
5824 +    UINT8           fInfo;
5825 +    UINT32          nextTpl;
5826 +    UINT8           tplLength;
5827 +    UINT8           cisPtrBuffer[3];
5828 +    struct SDIO_FUNC_EXT_FUNCTION_TPL_1_1 funcTuple;
5829 +
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;
5833 +
5834 +        /* calculate function base address */
5835 +    faddress = CalculateFBROffset(SDDEVICE_GET_SDIO_FUNCNO(pDevice));
5836 +    DBG_ASSERT(faddress != 0);
5837 +
5838 +    do {
5839 +        status = Cmd52ReadByteCommon(pDevice,
5840 +                                     FBR_FUNC_INFO_REG_OFFSET(faddress),
5841 +                                     &fInfo);
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));
5844 +            fInfo = 0;
5845 +            pDevice->pId[0].SDIO_FunctionClass = 0;
5846 +            status = SDIO_STATUS_SUCCESS;
5847 +        } else {
5848 +            pDevice->pId[0].SDIO_FunctionClass = fInfo & FUNC_INFO_DEVICE_CODE_MASK;
5849 +        }
5850 +
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",
5860 +                                        status));
5861 +                break;
5862 +            }
5863 +        }
5864 +
5865 +            /* get the function CIS ptr */
5866 +        status = Cmd52ReadMultipleCommon(pDevice,
5867 +                                         FBR_FUNC_CIS_LOW_OFFSET(faddress),
5868 +                                         cisPtrBuffer,
5869 +                                         3);
5870 +        if (!SDIO_SUCCESS(status)) {
5871 +            DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get FN CIS ptr, Err:%d\n", status));
5872 +            break;
5873 +        }
5874 +            /* endian safe */
5875 +        pDevice->DeviceInfo.AsSDIOInfo.FunctionCISPtr = ((UINT32)cisPtrBuffer[0]) |
5876 +                                                        (((UINT32)cisPtrBuffer[1]) << 8) |
5877 +                                                        (((UINT32)cisPtrBuffer[2]) << 16);
5878 +
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));
5882 +
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),
5887 +                                             cisPtrBuffer,
5888 +                                             3);
5889 +            if (!SDIO_SUCCESS(status)) {
5890 +                DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get FN CSA ptr, Err:%d \n", status));
5891 +                break;
5892 +            }
5893 +                /* endian safe */
5894 +            pDevice->DeviceInfo.AsSDIOInfo.FunctionCSAPtr = ((UINT32)cisPtrBuffer[0]) |
5895 +                                                            (((UINT32)cisPtrBuffer[1]) << 8) |
5896 +                                                            (((UINT32)cisPtrBuffer[2]) << 16);
5897 +
5898 +        }
5899 +
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,
5905 +                                 CISTPL_FUNCE,
5906 +                                 &nextTpl,
5907 +                                 (PUINT8)&funcTuple,
5908 +                                 &tplLength);
5909 +
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;
5914 +            break;
5915 +        }
5916 +            /* set the max block size */
5917 +        pDevice->DeviceInfo.AsSDIOInfo.FunctionMaxBlockSize =
5918 +                                CT_LE16_TO_CPU_ENDIAN(funcTuple.CommonInfo.MaxBlockSize);
5919 +
5920 +        DBG_PRINT(SDDBG_TRACE, ("SDIO Function:%d, MaxBlocks:%d \n",
5921 +                  SDDEVICE_GET_SDIO_FUNCNO(pDevice),
5922 +                  pDevice->DeviceInfo.AsSDIOInfo.FunctionMaxBlockSize));
5923 +
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,
5931 +                                     CISTPL_MANFID,
5932 +                                     &nextTpl,
5933 +                                     (PUINT8)&manfid,
5934 +                                     &tplLength);
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));
5944 +            } else {
5945 +                DBG_PRINT(SDDBG_WARN, ("SDIO 1.1, No CISTPL_MANFID Tuple in FUNC CIS \n"));
5946 +                status = SDIO_STATUS_SUCCESS;
5947 +            }
5948 +        }
5949 +    } while (FALSE);
5950 +
5951 +    return status;
5952 +}
5953 +
5954 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5955 +  SDEnableFunction - enable function
5956 +  Input:  pDevice - the device/function
5957 +          pEnData - enable data;
5958 +  Output:
5959 +  Return: status
5960 +  Notes: Note, this performs synchronous calls
5961 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
5962 +SDIO_STATUS SDEnableFunction(PSDDEVICE pDevice, PSDCONFIG_FUNC_ENABLE_DISABLE_DATA pEnData)
5963 +{
5964 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
5965 +    UINT8       registerValue;
5966 +    UINT8       mask;
5967 +    FUNC_ENABLE_TIMEOUT  retry;
5968 +
5969 +        /* take the configure op lock to make this atomic */
5970 +    status = SemaphorePendInterruptable(&pDevice->pHcd->ConfigureOpsSem);
5971 +    if (!SDIO_SUCCESS(status)) {
5972 +        return status;
5973 +    }
5974 +
5975 +    status = SDIO_STATUS_INVALID_PARAMETER;
5976 +    do {
5977 +        if (!(pDevice->pHcd->CardProperties.Flags & CARD_SDIO)){
5978 +                /* nothing to do if it's not an SDIO card */
5979 +            break;
5980 +        }
5981 +
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);
5985 +            break;
5986 +        }
5987 +            /* make sure there is a timeout value */
5988 +        if (0 == pEnData->TimeOut) {
5989 +            break;
5990 +        }
5991 +
5992 +        mask = 1 << SDDEVICE_GET_SDIO_FUNCNO(pDevice);
5993 +            /* read the enable register */
5994 +        status = Cmd52ReadByteCommon(pDevice, SDIO_ENABLE_REG, &registerValue);
5995 +        if (!SDIO_SUCCESS(status)){
5996 +            break;
5997 +        }
5998 +        if (pEnData->EnableFlags & SDCONFIG_ENABLE_FUNC) {
5999 +                /* set the enable register bit */
6000 +            registerValue |= mask;
6001 +        } else {
6002 +               /* clear the bit */
6003 +            registerValue &= ~mask;
6004 +        }
6005 +
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",
6009 +                 mask,
6010 +                 registerValue));
6011 +
6012 +            /* write it back out */
6013 +        status = Cmd52WriteByteCommon(pDevice, SDIO_ENABLE_REG, &registerValue);
6014 +        if (!SDIO_SUCCESS(status)){
6015 +            break;
6016 +        }
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",
6020 +                                retry));
6021 +        while (retry) {
6022 +            status = Cmd52ReadByteCommon(pDevice, SDIO_READY_REG, &registerValue);
6023 +            if (!SDIO_SUCCESS(status)){
6024 +                break;
6025 +            }
6026 +            if (pEnData->EnableFlags & SDCONFIG_ENABLE_FUNC) {
6027 +                    /* if the bit is set, the device is ready */
6028 +                if (registerValue & mask) {
6029 +                        /* device ready */
6030 +                    break;
6031 +                }
6032 +            } else {
6033 +                if (!(registerValue & mask)) {
6034 +                        /* device is no longer ready */
6035 +                    break;
6036 +                }
6037 +            }
6038 +                /* sleep before trying again */
6039 +            status = OSSleep(1);
6040 +            if (!SDIO_SUCCESS(status)) {
6041 +                DBG_PRINT(SDDBG_ERROR, ("OSSleep Failed! \n"));
6042 +                break;
6043 +            }
6044 +            retry--;
6045 +        }
6046 +
6047 +        if (0 == retry) {
6048 +            status = SDIO_STATUS_FUNC_ENABLE_TIMEOUT;
6049 +            break;
6050 +        }
6051 +
6052 +    } while (FALSE);
6053 +
6054 +    SemaphorePost(&pDevice->pHcd->ConfigureOpsSem);
6055 +    return status;
6056 +}
6057 +
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)
6063 +  Output:
6064 +  Return: status
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)
6069 +{
6070 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
6071 +
6072 +    DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: SDAllocFreeSlotCurrent\n"));
6073 +
6074 +        /* take the configure op lock to make this atomic */
6075 +    status = SemaphorePendInterruptable(&pDevice->pHcd->ConfigureOpsSem);
6076 +    if (!SDIO_SUCCESS(status)) {
6077 +        return status;
6078 +    }
6079 +
6080 +    status = SDIO_STATUS_INVALID_PARAMETER;
6081 +    do {
6082 +            /* check the current budget and allocate */
6083 +        if (Allocate) {
6084 +            if (0 == pData->SlotCurrent) {
6085 +                /* caller must specify current requirement for the power mode */
6086 +                break;
6087 +            }
6088 +            if (pDevice->SlotCurrentAlloc != 0) {
6089 +               /* slot current has already been allocated, caller needs to free
6090 +                * first */
6091 +                DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Slot Current Already allocated! \n"));
6092 +                break;
6093 +            }
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;
6103 +                break;
6104 +            }
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));
6112 +
6113 +        } else {
6114 +            if (0 == pDevice->SlotCurrentAlloc) {
6115 +                    /* no allocation */
6116 +                break;
6117 +            }
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));
6124 +            } else {
6125 +                DBG_ASSERT(FALSE);
6126 +            }
6127 +
6128 +                /* make sure this is zeroed */
6129 +            pDevice->SlotCurrentAlloc = 0;
6130 +        }
6131 +
6132 +        status = SDIO_STATUS_SUCCESS;
6133 +
6134 +    } while (FALSE);
6135 +
6136 +    SemaphorePost(&pDevice->pHcd->ConfigureOpsSem);
6137 +    DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: SDAllocFreeSlotCurrent, %d\n", status));
6138 +    return status;
6139 +}
6140 +
6141 +static void RawHcdIrqControl(PSDHCD pHcd, BOOL Enable)
6142 +{
6143 +    SDIO_STATUS status;
6144 +    SDCONFIG_SDIO_INT_CTRL_DATA irqData;
6145 +    CT_DECLARE_IRQ_SYNC_CONTEXT();
6146 +
6147 +    ZERO_OBJECT(irqData);
6148 +
6149 +    status = _AcquireHcdLock(pHcd);
6150 +    if (!SDIO_SUCCESS(status)) {
6151 +        return;
6152 +    }
6153 +
6154 +    do {
6155 +            /* for raw devices, we simply enable/disable in the HCD only */
6156 +        if (Enable) {
6157 +            DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver (RAW) Unmasking Int \n"));
6158 +            irqData.IRQDetectMode = IRQ_DETECT_RAW;
6159 +            irqData.SlotIRQEnable = TRUE;
6160 +        } else {
6161 +            DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver (RAW) Masking Int \n"));
6162 +            irqData.SlotIRQEnable = FALSE;
6163 +        }
6164 +
6165 +        status = _IssueConfig(pHcd,SDCONFIG_SDIO_INT_CTRL,
6166 +                              (PVOID)&irqData, sizeof(irqData));
6167 +
6168 +        if (!SDIO_SUCCESS(status)){
6169 +            DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver failed to enable/disable IRQ in (RAW) hcd :%d\n",
6170 +                                    status));
6171 +        }
6172 +
6173 +    } while (FALSE);
6174 +
6175 +    status = _ReleaseHcdLock(pHcd);
6176 +}
6177 +
6178 +static void RawHcdEnableIrqPseudoComplete(PSDREQUEST pReq)
6179 +{
6180 +    if (SDIO_SUCCESS(pReq->Status)) {
6181 +        RawHcdIrqControl((PSDHCD)pReq->pCompleteContext, TRUE);
6182 +    }
6183 +    FreeRequest(pReq);
6184 +}
6185 +
6186 +static void RawHcdDisableIrqPseudoComplete(PSDREQUEST pReq)
6187 +{
6188 +    RawHcdIrqControl((PSDHCD)pReq->pCompleteContext, FALSE);
6189 +    FreeRequest(pReq);
6190 +}
6191 +
6192 +static void HcdIrqControl(PSDHCD pHcd, BOOL Enable)
6193 +{
6194 +    SDIO_STATUS                 status;
6195 +    SDCONFIG_SDIO_INT_CTRL_DATA irqData;
6196 +    CT_DECLARE_IRQ_SYNC_CONTEXT();
6197 +
6198 +    ZERO_OBJECT(irqData);
6199 +
6200 +    status = _AcquireHcdLock(pHcd);
6201 +    if (!SDIO_SUCCESS(status)) {
6202 +        return;
6203 +    }
6204 +
6205 +    do {
6206 +        DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: HcdIrqControl (%s), IrqsEnabled:0x%X \n",
6207 +                        Enable ? "Enable":"Disable",pHcd->IrqsEnabled ));
6208 +
6209 +        if (Enable) {
6210 +            irqData.SlotIRQEnable = TRUE;
6211 +        } else {
6212 +            irqData.SlotIRQEnable = FALSE;
6213 +        }
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;
6220 +                    break;
6221 +                case SDCONFIG_BUS_WIDTH_1_BIT:
6222 +                    irqData.IRQDetectMode = IRQ_DETECT_1_BIT;
6223 +                    break;
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"));
6233 +                    }
6234 +                    break;
6235 +                default:
6236 +                    DBG_ASSERT(FALSE);
6237 +                    break;
6238 +            }
6239 +
6240 +            DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver enabling IRQ in HCD Mode:0x%X\n",
6241 +                                     irqData.IRQDetectMode));
6242 +        }
6243 +
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",
6248 +                                    status));
6249 +        }
6250 +
6251 +    } while (FALSE);
6252 +
6253 +    status = _ReleaseHcdLock(pHcd);
6254 +}
6255 +
6256 +static BOOL CheckWriteIntEnableSuccess(PSDREQUEST pReq)
6257 +{
6258 +    if (!SDIO_SUCCESS(pReq->Status)){
6259 +            DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get write INT Enable register Err:%d\n",
6260 +                                     pReq->Status));
6261 +        return FALSE;
6262 +    }
6263 +
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)));
6267 +        return FALSE;
6268 +    }
6269 +
6270 +    return TRUE;
6271 +}
6272 +
6273 +static void HcdIrqEnableComplete(PSDREQUEST pReq)
6274 +{
6275 +    if (CheckWriteIntEnableSuccess(pReq)) {
6276 +            /* configure HCD */
6277 +        HcdIrqControl((PSDHCD)pReq->pCompleteContext, TRUE);
6278 +    }
6279 +    FreeRequest(pReq);
6280 +}
6281 +
6282 +static void HcdIrqDisableComplete(PSDREQUEST pReq)
6283 +{
6284 +    CheckWriteIntEnableSuccess(pReq);
6285 +    HcdIrqControl((PSDHCD)pReq->pCompleteContext, FALSE);
6286 +    FreeRequest(pReq);
6287 +}
6288 +
6289 +static void WriteIntEnableComplete(PSDREQUEST pReq)
6290 +{
6291 +   if (CheckWriteIntEnableSuccess(pReq)) {
6292 +       DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Wrote INT Enable value:0x%X \n",
6293 +                    (INT)pReq->pCompleteContext));
6294 +   }
6295 +   FreeRequest(pReq);
6296 +}
6297 +
6298 +static void HcdAckComplete(PSDREQUEST pReq)
6299 +{
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);
6305 +
6306 +    if (!SDIO_SUCCESS(status)) {
6307 +        DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: HCD Re-Arm failed : %d\n",
6308 +                    status));
6309 +    }
6310 +    FreeRequest(pReq);
6311 +}
6312 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6313 +  SDFunctionAckInterrupt - handle device interrupt acknowledgement
6314 +  Input:  pDevice - the device
6315 +  Output:
6316 +  Return:
6317 +  Notes:
6318 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
6319 +SDIO_STATUS SDFunctionAckInterrupt(PSDDEVICE pDevice)
6320 +{
6321 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
6322 +    UCHAR       mask;
6323 +    PSDREQUEST  pReq = NULL;
6324 +    BOOL        setHcd = FALSE;
6325 +    SDIO_STATUS status2;
6326 +    CT_DECLARE_IRQ_SYNC_CONTEXT();
6327 +
6328 +    pReq = AllocateRequest();
6329 +    if (NULL == pReq) {
6330 +        return SDIO_STATUS_NO_RESOURCES;
6331 +    }
6332 +
6333 +    status = _AcquireHcdLock(pDevice->pHcd);
6334 +
6335 +    if (!SDIO_SUCCESS(status)) {
6336 +        FreeRequest(pReq);
6337 +        return status;
6338 +    }
6339 +
6340 +    do {
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);
6345 +            break;
6346 +        }
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) {
6355 +                    setHcd = TRUE;
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;
6361 +                }
6362 +            }
6363 +        } else {
6364 +            DBG_PRINT(SDDBG_WARN, ("SDIO Bus Driver: AckInterrupt: no IRQ pending on Function :%d, \n",
6365 +                        SDDEVICE_GET_SDIO_FUNCNO(pDevice)));
6366 +        }
6367 +    } while (FALSE);
6368 +
6369 +    status2 = ReleaseHcdLock(pDevice);
6370 +
6371 +    if (pReq != NULL) {
6372 +        if (SDIO_SUCCESS(status) && (setHcd)) {
6373 +                /* issue request */
6374 +            IssueRequestToHCD(pDevice->pHcd,pReq);
6375 +        } else {
6376 +            FreeRequest(pReq);
6377 +        }
6378 +    }
6379 +
6380 +    return status;
6381 +}
6382 +
6383 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6384 +  SDMaskUnmaskFunctionIRQ - mask/unmask function IRQ
6385 +  Input:  pDevice - the device/function
6386 +          MaskInt - mask interrupt
6387 +  Output:
6388 +  Return: status
6389 +  Notes:  Note, this function can be called from an ISR or completion context
6390 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
6391 +SDIO_STATUS SDMaskUnmaskFunctionIRQ(PSDDEVICE pDevice, BOOL MaskInt)
6392 +{
6393 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
6394 +    UINT8       mask;
6395 +    UINT8       controlVal;
6396 +    BOOL        setHcd;
6397 +    PSDREQUEST  pReq = NULL;
6398 +    SDIO_STATUS status2;
6399 +
6400 +    CT_DECLARE_IRQ_SYNC_CONTEXT();
6401 +
6402 +    setHcd = FALSE;
6403 +
6404 +    pReq = AllocateRequest();
6405 +    if (NULL == pReq) {
6406 +        return SDIO_STATUS_NO_RESOURCES;
6407 +    }
6408 +
6409 +    status = _AcquireHcdLock(pDevice->pHcd);
6410 +
6411 +    if (!SDIO_SUCCESS(status)) {
6412 +        FreeRequest(pReq);
6413 +        return status;
6414 +    }
6415 +
6416 +    do {
6417 +
6418 +        if (pDevice->pHcd->CardProperties.Flags & CARD_RAW) {
6419 +            if (!MaskInt) {
6420 +                if (!pDevice->pHcd->IrqsEnabled) {
6421 +                    pReq->pCompletion = RawHcdEnableIrqPseudoComplete;
6422 +                    setHcd = TRUE;
6423 +                    pDevice->pHcd->IrqsEnabled = 1 << 1;
6424 +                }
6425 +            } else {
6426 +                if (pDevice->pHcd->IrqsEnabled) {
6427 +                    pReq->pCompletion = RawHcdDisableIrqPseudoComplete;
6428 +                    setHcd = TRUE;
6429 +                    pDevice->pHcd->IrqsEnabled = 0;
6430 +                }
6431 +            }
6432 +
6433 +            if (setHcd) {
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;
6439 +            } else {
6440 +                    /* no request to submit, just free it */
6441 +                FreeRequest(pReq);
6442 +                pReq = NULL;
6443 +            }
6444 +                /* we're done, submit the bus request if any */
6445 +            break;
6446 +        }
6447 +
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;
6452 +            break;
6453 +        }
6454 +
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);
6459 +            break;
6460 +        }
6461 +
6462 +        mask = 1 << SDDEVICE_GET_SDIO_FUNCNO(pDevice);
6463 +        if (!MaskInt) {
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 */
6468 +                setHcd = TRUE;
6469 +                    /* use this completion routine */
6470 +                pReq->pCompletion = HcdIrqEnableComplete;
6471 +            }
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;
6476 +        } else {
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 */
6483 +                controlVal = 0;
6484 +                    /* disable in host */
6485 +                setHcd = TRUE;
6486 +                    /* use this completion routine */
6487 +                pReq->pCompletion = HcdIrqDisableComplete;
6488 +            } else {
6489 +                    /* set control value making sure master enable is left on */
6490 +                controlVal = pDevice->pHcd->IrqsEnabled | SDIO_INT_MASTER_ENABLE;
6491 +            }
6492 +        }
6493 +
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;
6499 +
6500 +        if (setHcd) {
6501 +                /* make this a barrier request and set context*/
6502 +            pReq->Flags |= SDREQ_FLAGS_BARRIER;
6503 +            pReq->pCompleteContext = pDevice->pHcd;
6504 +        } else {
6505 +                /* does not require an update to the HCD  */
6506 +            pReq->pCompleteContext = (PVOID)(UINT32)controlVal;
6507 +            pReq->pCompletion = WriteIntEnableComplete;
6508 +        }
6509 +
6510 +    } while (FALSE);
6511 +
6512 +    status2 = _ReleaseHcdLock(pDevice->pHcd);
6513 +
6514 +    if (pReq != NULL) {
6515 +        if (SDIO_SUCCESS(status)) {
6516 +                /* issue request */
6517 +            IssueRequestToHCD(pDevice->pHcd,pReq);
6518 +        } else {
6519 +            FreeRequest(pReq);
6520 +        }
6521 +    }
6522 +
6523 +    return status;
6524 +}
6525 +
6526 +
6527 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6528 +  SDSPIModeEnableDisableCRC - Enable/Disable SPI Mode CRC checking
6529 +  Input:  pDevice - the device/function
6530 +          Enable - Enable CRC
6531 +  Output:
6532 +  Return: status
6533 +  Notes:  Note, this function can be called from an ISR or completion context
6534 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
6535 +SDIO_STATUS SDSPIModeEnableDisableCRC(PSDDEVICE pDevice,BOOL Enable)
6536 +{
6537 +    SDCONFIG_BUS_MODE_DATA busMode;
6538 +    SDIO_STATUS            status = SDIO_STATUS_SUCCESS;
6539 +    UINT32                 cmdARG = 0;
6540 +
6541 +    if (!SDDEVICE_IS_BUSMODE_SPI(pDevice)) {
6542 +        return SDIO_STATUS_INVALID_PARAMETER;
6543 +    }
6544 +       //??we should make these atomic using a barrier
6545 +
6546 +        /* get the current mode and clock */
6547 +    busMode.BusModeFlags = pDevice->pHcd->CardProperties.BusMode;
6548 +    busMode.ClockRate = pDevice->pHcd->CardProperties.OperBusClock;
6549 +
6550 +    if (Enable) {
6551 +            /* clear the no-CRC flag */
6552 +        busMode.BusModeFlags &= ~SDCONFIG_BUS_MODE_SPI_NO_CRC;
6553 +        cmdARG = SD_CMD59_CRC_ON;
6554 +    } else {
6555 +        busMode.BusModeFlags |= SDCONFIG_BUS_MODE_SPI_NO_CRC;
6556 +        cmdARG = SD_CMD59_CRC_OFF;
6557 +    }
6558 +
6559 +    do {
6560 +            /* issue CMD59 to turn on/off CRC */
6561 +        status = _IssueSimpleBusRequest(pDevice->pHcd,
6562 +                                        CMD59,
6563 +                                        cmdARG,
6564 +                                        SDREQ_FLAGS_RESP_R1,
6565 +                                        NULL);
6566 +        if (!SDIO_SUCCESS(status)) {
6567 +            DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed issue CMD59 (arg=0x%X) Err:%d \n",
6568 +                                    cmdARG, status));
6569 +            break;
6570 +        }
6571 +        if (Enable) {
6572 +            DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: CRC Enabled in SPI mode \n"));
6573 +        } else {
6574 +            DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: CRC Disabled in SPI mode \n"));
6575 +        }
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",
6579 +                                    status));
6580 +            break;
6581 +        }
6582 +    } while (FALSE);
6583 +
6584 +    return status;
6585 +}
6586 +
6587 +
6588 +static UINT32 ConvertSPIStatusToSDCardStatus(UINT8 SpiR1, UINT8 SpiR2)
6589 +{
6590 +    UINT32 cardStatus = 0;
6591 +
6592 +    if (SpiR1 != 0) {
6593 +            /* convert the error */
6594 +        if (SpiR1 & SPI_CS_ERASE_RESET) {
6595 +            cardStatus |= SD_CS_ERASE_RESET;
6596 +        }
6597 +        if (SpiR1 & SPI_CS_ILLEGAL_CMD) {
6598 +            cardStatus |= SD_CS_ILLEGAL_CMD_ERR;
6599 +        }
6600 +        if (SpiR1 & SPI_CS_CMD_CRC_ERR) {
6601 +            cardStatus |= SD_CS_PREV_CMD_CRC_ERR;
6602 +        }
6603 +        if (SpiR1 & SPI_CS_ERASE_SEQ_ERR) {
6604 +            cardStatus |= SD_CS_ERASE_SEQ_ERR;
6605 +        }
6606 +        if (SpiR1 & SPI_CS_ADDRESS_ERR) {
6607 +            cardStatus |= SD_CS_ADDRESS_ERR;
6608 +        }
6609 +        if (SpiR1 & SPI_CS_PARAM_ERR) {
6610 +            cardStatus |= SD_CS_CMD_OUT_OF_RANGE;
6611 +        }
6612 +    }
6613 +
6614 +    if (SpiR2 != 0) {
6615 +            /* convert the error */
6616 +        if (SpiR2 & SPI_CS_CARD_IS_LOCKED) {
6617 +            cardStatus |= SD_CS_CARD_LOCKED;
6618 +        }
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);
6622 +        }
6623 +        if (SpiR2 & SPI_CS_ERROR) {
6624 +            cardStatus |= SD_CS_GENERAL_ERR;
6625 +        }
6626 +        if (SpiR2 & SPI_CS_INTERNAL_ERROR) {
6627 +            cardStatus |= SD_CS_CARD_INTERNAL_ERR;
6628 +        }
6629 +        if (SpiR2 & SPI_CS_ECC_FAILED) {
6630 +            cardStatus |= SD_CS_ECC_FAILED;
6631 +        }
6632 +        if (SpiR2 & SPI_CS_WP_VIOLATION) {
6633 +            cardStatus |= SD_CS_WP_ERR;
6634 +        }
6635 +        if (SpiR2 & SPI_CS_ERASE_PARAM_ERR) {
6636 +            cardStatus |= SD_CS_ERASE_PARAM_ERR;
6637 +        }
6638 +        if (SpiR2 & SPI_CS_OUT_OF_RANGE) {
6639 +            cardStatus |= SD_CS_CMD_OUT_OF_RANGE;
6640 +        }
6641 +    }
6642 +
6643 +    return cardStatus;
6644 +}
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)
6650 +  Return:
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)
6658 +{
6659 +
6660 +    UINT32  cardStatus;
6661 +
6662 +    if (pReq->Flags & SDREQ_FLAGS_RESP_SPI_CONVERTED) {
6663 +            /* already converted */
6664 +        return;
6665 +    }
6666 +    if (NULL == pRespBuffer) {
6667 +        pRespBuffer = pReq->Response;
6668 +    }
6669 +
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),
6674 +                                                        0);
6675 +            if (CMD55 == pReq->Command) {
6676 +                    /* we emulate this since SPI does not have such a bit */
6677 +                cardStatus |= SD_CS_APP_CMD;
6678 +            }
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;
6684 +            break;
6685 +        case SDREQ_FLAGS_RESP_SDIO_R5:
6686 +            {
6687 +                UINT8 respFlags;
6688 +                UINT8 readData;
6689 +
6690 +                readData = GET_SPI_SDIO_R5_RESPONSE_RDATA(pReq->Response);
6691 +                respFlags = GET_SPI_SDIO_R5_RESP_TOKEN(pReq->Response);
6692 +
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;
6697 +                    }
6698 +                    if (respFlags & SPI_R5_CMD_CRC) {
6699 +                        pRespBuffer[SD_R5_RESP_FLAGS_OFFSET] |= SD_R5_RESP_CMD_ERR;
6700 +                    }
6701 +                    if (respFlags & SPI_R5_FUNC_ERR) {
6702 +                        pRespBuffer[SD_R5_RESP_FLAGS_OFFSET] |= SD_R5_INVALID_FUNC;
6703 +                    }
6704 +                    if (respFlags & SPI_R5_PARAM_ERR) {
6705 +                        pRespBuffer[SD_R5_RESP_FLAGS_OFFSET] |= SD_R5_ARG_RANGE_ERR;
6706 +                    }
6707 +                }
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);
6712 +            }
6713 +            pReq->Flags |= SDREQ_FLAGS_RESP_SPI_CONVERTED;
6714 +            break;
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;
6727 +                break;
6728 +            }
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);
6732 +            break;
6733 +        default:
6734 +                /* for all others:
6735 +                 *
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
6739 +                 *
6740 +                 */
6741 +            DBG_PRINT(SDDBG_ERROR, ("ConvertSPI_Response - invalid response type:0x%2.2X",
6742 +                                    GET_SDREQ_RESP_TYPE(pReq->Flags)));
6743 +            DBG_ASSERT(FALSE);
6744 +            break;
6745 +    }
6746 +}
6747 +
6748 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6749 +  @function: Check an SD/MMC/SDIO response.
6750 +
6751 +  @function name: SDIO_CheckResponse
6752 +  @prototype: SDIO_STATUS SDIO_CheckResponse(PSDHCD pHcd, PSDREQUEST pReq, SDHCD_RESPONSE_CHECK_MODE CheckMode)
6753 +  @category: HD_Reference
6754 +
6755 +  @input:  pHcd - the host controller definition structure.
6756 +  @input:  pReq - request containing the response
6757 +  @input:  CheckMode - mode
6758 +
6759 +  @return: SDIO_STATUS
6760 +
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
6771 +          data transfer.
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.
6778 +
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
6785 +            } else {
6786 +               ... card response indicates that the card cannot handle data
6787 +                  // set completion status
6788 +               pRequest->Status = status;
6789 +            }
6790 +        }
6791 +
6792 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
6793 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6794 +  _SDIO_CheckResponse - check response on behalf of the host controller
6795 +  Input:  pHcd - host controller
6796 +          pReq - request containing the response
6797 +          CheckMode - mode
6798 +  Output:
6799 +  Return: status
6800 +  Notes:
6801 +
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
6806 +    data transfer.
6807 +
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.
6811 +
6812 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
6813 +SDIO_STATUS _SDIO_CheckResponse(PSDHCD pHcd, PSDREQUEST pReq, SDHCD_RESPONSE_CHECK_MODE CheckMode)
6814 +{
6815 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
6816 +
6817 +    if (CheckMode == SDHCD_CHECK_DATA_TRANS_OK) {
6818 +        UINT32      cardStatus;
6819 +        UINT8       *pResponse;
6820 +        UINT8       convertedResponse[MAX_CARD_RESPONSE_BYTES];
6821 +
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;
6826 +        }
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);
6833 +            } else {
6834 +                    /* temporarily convert the response, without altering the original */
6835 +                ConvertSPI_Response(pReq, convertedResponse);
6836 +                    /* point to the converted one */
6837 +                pResponse = convertedResponse;
6838 +            }
6839 +        }
6840 +
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 */
6848 +                    break;
6849 +                }
6850 +                    /* figure out what it was */
6851 +                if (cardStatus & SD_CS_ILLEGAL_CMD_ERR) {
6852 +                    status = SDIO_STATUS_DATA_STATE_INVALID;
6853 +                } else {
6854 +                    status = SDIO_STATUS_DATA_ERROR_UNKNOWN;
6855 +                }
6856 +                DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Check Response Error. R1 CardStatus:0x%X \n",
6857 +                                        cardStatus));
6858 +                break;
6859 +            case SDREQ_FLAGS_RESP_SDIO_R5:
6860 +                cardStatus = SD_R5_GET_RESP_FLAGS(pResponse);
6861 +                if (!(cardStatus & SD_R5_CURRENT_CMD_ERRORS)){
6862 +                        /* all okay */
6863 +                    break;
6864 +                }
6865 +
6866 +                status = ConvertCMD52ResponseToSDIOStatus((UINT8)cardStatus);
6867 +                DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Check Response Error. R5 CardStatus:0x%X \n",
6868 +                                        cardStatus));
6869 +                break;
6870 +            default:
6871 +                break;
6872 +        }
6873 +
6874 +        return status;
6875 +    }
6876 +
6877 +    {
6878 +        UINT8       spiToken;
6879 +
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);
6884 +                break;
6885 +            case SDREQ_FLAGS_RESP_SDIO_R5:
6886 +                spiToken = GET_SPI_SDIO_R5_RESP_TOKEN(pReq->Response);
6887 +                break;
6888 +            case SDREQ_FLAGS_RESP_R3:
6889 +                spiToken = GET_SPI_R3_RESP_TOKEN(pReq->Response);
6890 +                break;
6891 +            case SDREQ_FLAGS_RESP_SDIO_R4:
6892 +                spiToken = GET_SPI_SDIO_R4_RESP_TOKEN(pReq->Response);
6893 +                break;
6894 +            default:
6895 +                    /* all other tokesn are SPI R1 type */
6896 +                spiToken = GET_SPI_R1_RESP_TOKEN(pReq->Response);
6897 +                break;
6898 +        }
6899 +
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;
6906 +            }
6907 +        } else {
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;
6912 +            }
6913 +       }
6914 +    }
6915 +
6916 +    return status;
6917 +}
6918 +
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
6922 --- /dev/null
6923 +++ b/drivers/sdio/stack/busdriver/sdio_bus_os.c
6924 @@ -0,0 +1,832 @@
6925 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6926 +@file: sdio_bus_os.c
6927 +
6928 +@abstract: Linux implementation module
6929 +
6930 +#notes: includes module load and unload functions
6931 +
6932 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
6933 +
6934 +
6935 + *
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;
6939 + *
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.
6944 + *
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:
6947 + *
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.
6953 + *   Disclaimers:
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.
6962 + *
6963 + *
6964 + *  The initial developers of the original code are Seung Yi and Paul Lever
6965 + *
6966 + *  sdio@atheros.com
6967 + *
6968 + *
6969 +
6970 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
6971 +/* debug level for this module*/
6972 +#define DBG_DECLARE 3;
6973 +
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"
6987 +
6988 +#define DESCRIPTION "SDIO Bus Driver"
6989 +#define AUTHOR "Atheros Communications, Inc."
6990 +
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");
7026 +
7027 +static int HcdRCount = MAX_HCD_REQ_RECURSION;
7028 +module_param(HcdRCount, int, 0644);
7029 +MODULE_PARM_DESC(HcdRCount, "HCD request recursion count");
7030 +
7031 +static void CardDetect_WorkItem(
7032 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
7033 +void *context);
7034 +#else
7035 +struct work_struct *ignored);
7036 +#endif
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)
7041 +, 0);
7042 +#else
7043 +);
7044 +#endif
7045 +#endif
7046 +static int RegisterDriver(PSDFUNCTION pFunction);
7047 +static int UnregisterDriver(PSDFUNCTION pFunction);
7048 +
7049 +static struct timer_list CardDetectTimer;
7050 +
7051 +#define SDDEVICE_FROM_OSDEVICE(pOSDevice)  container_of(pOSDevice, SDDEVICE, Device)
7052 +#define SDFUNCTION_FROM_OSDRIVER(pOSDriver)  container_of(pOSDriver, SDFUNCTION, Driver)
7053 +
7054 +
7055 +/*
7056 + * SDIO_RegisterHostController - register a host controller bus driver
7057 +*/
7058 +SDIO_STATUS SDIO_RegisterHostController(PSDHCD pHcd) {
7059 +    /* we are the exported verison, call the internal verison */
7060 +    return _SDIO_RegisterHostController(pHcd);
7061 +}
7062 +
7063 +/*
7064 + * SDIO_UnregisterHostController - unregister a host controller bus driver
7065 +*/
7066 +SDIO_STATUS SDIO_UnregisterHostController(PSDHCD pHcd) {
7067 +    /* we are the exported verison, call the internal verison */
7068 +    return _SDIO_UnregisterHostController(pHcd);
7069 +}
7070 +
7071 +/*
7072 + * SDIO_RegisterFunction - register a function driver
7073 +*/
7074 +SDIO_STATUS SDIO_RegisterFunction(PSDFUNCTION pFunction) {
7075 +    int error;
7076 +    SDIO_STATUS status;
7077 +
7078 +    DBG_PRINT(SDDBG_TRACE, ("SDIO BusDriver - SDIO_RegisterFunction\n"));
7079 +
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;
7086 +    }
7087 +
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",
7093 +            error));
7094 +        status = OSErrorToSDIOError(error);
7095 +    } else {
7096 +        status = _SDIO_RegisterFunction(pFunction);
7097 +        if (!SDIO_SUCCESS(status)) {
7098 +            UnregisterDriver(pFunction);
7099 +        }
7100 +    }
7101 +
7102 +    return status;
7103 +}
7104 +
7105 +/*
7106 + * SDIO_UnregisterFunction - unregister a function driver
7107 +*/
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);
7113 +    return  status;
7114 +}
7115 +
7116 +/*
7117 + * SDIO_HandleHcdEvent - tell core an event occurred
7118 +*/
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);
7124 +}
7125 +
7126 +/* get default settings */
7127 +SDIO_STATUS _SDIO_BusGetDefaultSettings(PBDCONTEXT pBdc)
7128 +{
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;
7143 +}
7144 +
7145 +static void CardDetect_TimerFunc(unsigned long Context)
7146 +{
7147 +    DBG_PRINT(SDIODBG_CD_TIMER, ("+ SDIO BusDriver Card Detect Timer\n"));
7148 +
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"));
7154 +    }
7155 +#else
7156 +    CardDetect_WorkItem(NULL);
7157 +#endif
7158 +    DBG_PRINT(SDIODBG_CD_TIMER, ("- SDIO BusDriver  Card Detect Timer\n"));
7159 +}
7160 +
7161 +/*
7162 + * Initialize any timers we are using
7163 +*/
7164 +SDIO_STATUS InitializeTimers(void)
7165 +{
7166 +    init_timer(&CardDetectTimer);
7167 +    CardDetectTimer.function = CardDetect_TimerFunc;
7168 +    CardDetectTimer.data = 0;
7169 +    return SDIO_STATUS_SUCCESS;
7170 +}
7171 +
7172 +/*
7173 + * cleanup timers
7174 +*/
7175 +SDIO_STATUS CleanupTimers(void)
7176 +{
7177 +    del_timer(&CardDetectTimer);
7178 +    return SDIO_STATUS_SUCCESS;
7179 +}
7180 +
7181 +
7182 +/*
7183 + * Queue a timer, Timeout is in milliseconds
7184 +*/
7185 +SDIO_STATUS QueueTimer(INT TimerID, UINT32 TimeOut)
7186 +{
7187 +    UINT32 delta;
7188 +
7189 +        /* convert timeout to ticks */
7190 +    delta = (TimeOut * HZ)/1000;
7191 +    if (delta == 0) {
7192 +        delta = 1;
7193 +    }
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);
7201 +            break;
7202 +        default:
7203 +            return SDIO_STATUS_INVALID_PARAMETER;
7204 +    }
7205 +
7206 +    return SDIO_STATUS_SUCCESS;
7207 +}
7208 +
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)
7212 +{
7213 +    return _SDIO_CheckResponse(pHcd,pReq,CheckMode);
7214 +}
7215 +
7216 +/*
7217 + * CardDetect_WorkItem - the work item for handling card detect polling interrupt
7218 +*/
7219 +static void CardDetect_WorkItem(
7220 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
7221 +void *context)
7222 +#else
7223 +struct work_struct *ignored)
7224 +#endif
7225 +{
7226 +        /* call bus driver function */
7227 +    SDIO_NotifyTimerTriggered(SDIOBUS_CD_TIMER_ID);
7228 +}
7229 +
7230 +/*
7231 + * OS_IncHcdReference - increment host controller driver reference count
7232 +*/
7233 +SDIO_STATUS Do_OS_IncHcdReference(PSDHCD pHcd)
7234 +{
7235 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
7236 +
7237 +    do {
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"));
7242 +            break;
7243 +        }
7244 +
7245 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
7246 +        if (!try_module_get(pHcd->pModule)) {
7247 +            status = SDIO_STATUS_ERROR;
7248 +        }
7249 +#else
7250 +        if (!try_inc_mod_count(pHcd->pModule)) {
7251 +            status = SDIO_STATUS_ERROR;
7252 +        }
7253 +#endif
7254 +
7255 +    } while (FALSE);
7256 +
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"));
7260 +    }
7261 +
7262 +    return status;
7263 +}
7264 +
7265 +/*
7266 + * OS_DecHcdReference - decrement host controller driver reference count
7267 +*/
7268 +SDIO_STATUS Do_OS_DecHcdReference(PSDHCD pHcd)
7269 +{
7270 +    if (pHcd->pModule != NULL) {
7271 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
7272 +        module_put(pHcd->pModule);
7273 +#else
7274 +            /* 2.4 or lower */
7275 +        __MOD_DEC_USE_COUNT(pHcd->pModule);
7276 +#endif
7277 +    }
7278 +    return SDIO_STATUS_SUCCESS;
7279 +}
7280 +
7281 +/****************************************************************************************/
7282 +
7283 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
7284 +#include <linux/pnp.h>
7285 +
7286 +#if !defined(CONFIG_PNP)
7287 +#error "CONFIG_PNP not defined"
7288 +#endif
7289 +
7290 +static ULONG InUseDevices = 0;
7291 +static spinlock_t InUseDevicesLock = SPIN_LOCK_UNLOCKED;
7292 +
7293 +static const struct pnp_device_id pnp_idtable[] = {
7294 +    {"SD_XXXX",  0}
7295 +};
7296 +static int sdio_get_resources(struct pnp_dev * pDev, struct pnp_resource_table * res)
7297 +{
7298 +    DBG_PRINT(SDDBG_TRACE,
7299 +        ("SDIO BusDriver - sdio_get_resources: %s\n",
7300 +        pDev->dev.bus_id));
7301 +    return 0;
7302 +}
7303 +static int sdio_set_resources(struct pnp_dev * pDev, struct pnp_resource_table * res)
7304 +{
7305 +    DBG_PRINT(SDDBG_TRACE,
7306 +        ("SDIO BusDriver - sdio_set_resources: %s\n",
7307 +        pDev->dev.bus_id));
7308 +    return 0;
7309 +}
7310 +
7311 +static int sdio_disable_resources(struct pnp_dev *pDev)
7312 +{
7313 +    DBG_PRINT(SDDBG_TRACE,
7314 +        ("SDIO BusDriver - sdio_disable_resources: %s\n",
7315 +        pDev->dev.bus_id));
7316 +    if (pDev != NULL) {
7317 +        pDev->active = 0;
7318 +    }
7319 +    return 0;
7320 +}
7321 +void    release(struct device * pDev) {
7322 +    DBG_PRINT(SDDBG_TRACE,
7323 +        ("SDIO BusDriver - release: %s\n",
7324 +        pDev->bus_id));
7325 +    return;
7326 +}
7327 +struct pnp_protocol sdio_protocol = {
7328 +    .name   = "SDIO",
7329 +    .get    = sdio_get_resources,
7330 +    .set    = sdio_set_resources,
7331 +    .disable = sdio_disable_resources,
7332 +    .dev.release = release,
7333 +};
7334 +
7335 +/*
7336 + * driver_probe - probe for OS based driver
7337 +*/
7338 +static int driver_probe(struct pnp_dev* pOSDevice, const struct pnp_device_id *pId)
7339 +{
7340 +    PSDDEVICE pDevice = SDDEVICE_FROM_OSDEVICE(pOSDevice);
7341 +    PSDFUNCTION pFunction = pDevice->Device.dev.driver_data;
7342 +
7343 +    if (pFunction == NULL) {
7344 +        return -1;
7345 +    }
7346 +
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));
7351 +        return 1;
7352 +    } else {
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));
7356 +        return -1;
7357 +    }
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));
7363 +            return 1;
7364 +        }
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));
7368 +    } else {
7369 +        DBG_PRINT(SDDBG_TRACE,
7370 +            ("SDIO BusDriver - driver_probe, did not match: %s/%s\n",
7371 +            pOSDevice->dev.bus_id, pId->id));
7372 +    }
7373 +    return -1;
7374 +*/
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));
7382 +//??            return 1;
7383 +//??        }
7384 +//??    }
7385 +   DBG_PRINT(SDDBG_TRACE,
7386 +        ("SDIO BusDriver - driver_probe,  match: %s\n",
7387 +        pOSDevice->dev.bus_id));
7388 +    return 1;
7389 +}
7390 +
7391 +static int RegisterDriver(PSDFUNCTION pFunction)
7392 +{
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;
7398 +
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);
7403 +}
7404 +
7405 +static int UnregisterDriver(PSDFUNCTION pFunction)
7406 +{
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"));
7413 +   return 0;
7414 +}
7415 +
7416 +/*
7417 + * OS_InitializeDevice - initialize device that will be registered
7418 +*/
7419 +SDIO_STATUS OS_InitializeDevice(PSDDEVICE pDevice, PSDFUNCTION pFunction)
7420 +{
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;
7436 +
7437 +    pnp_init_resource_table(&pDevice->Device.res);
7438 +
7439 +    pFdname = KernelAlloc(sizeof(struct pnp_id));
7440 +
7441 +    if (NULL == pFdname) {
7442 +        return SDIO_STATUS_NO_RESOURCES;
7443 +    }
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",
7449 +                             pFdname->id));
7450 +    pnp_add_id(pFdname, &pDevice->Device);
7451 +
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;
7456 +    }
7457 +
7458 +    return SDIO_STATUS_SUCCESS;
7459 +}
7460 +
7461 +/*
7462 + * OS_AddDevice - must be pre-initialized with OS_InitializeDevice
7463 +*/
7464 +SDIO_STATUS OS_AddDevice(PSDDEVICE pDevice, PSDFUNCTION pFunction)
7465 +{
7466 +    int error;
7467 +    DBG_PRINT(SDDBG_TRACE, ("SDIO BusDriver - OS_AddDevice adding function: %s\n",
7468 +                               pFunction->pName));
7469 +    error = pnp_add_device(&pDevice->Device);
7470 +    if (error < 0) {
7471 +        DBG_PRINT(SDDBG_ERROR, ("SDIO BusDriver - OS_AddDevice failed pnp_add_device: %d\n",
7472 +                               error));
7473 +    }
7474 +        /* replace the buggy pnp's release */
7475 +    pDevice->Device.dev.release = release;
7476 +
7477 +    return OSErrorToSDIOError(error);
7478 +}
7479 +
7480 +/*
7481 + * OS_RemoveDevice - unregister device with driver and bus
7482 +*/
7483 +void OS_RemoveDevice(PSDDEVICE pDevice)
7484 +{
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);
7490 +
7491 +    if (pDevice->Device.id != NULL) {
7492 +        KernelFree(pDevice->Device.id);
7493 +        pDevice->Device.id = NULL;
7494 +    }
7495 +}
7496 +
7497 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7498 +  @function: Add OS device to bus driver.
7499 +
7500 +  @function name: SDIO_BusAddOSDevice
7501 +  @category: HD_Reference
7502 +
7503 +  @output: pDma    - descrip[tion of support DMA or NULL
7504 +  @output: pDriver - assigned driver object
7505 +  @output: pDevice - assigned device object
7506 +
7507 +  @return: SDIO_STATUS - SDIO_STATUS_SUCCESS when successful.
7508 +
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.
7512 +
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;
7519 +
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;
7527 +
7528 +    static SDHCD_DRIVER_CONTEXT HcdContext = {
7529 +        .pDescription  = DESCRIPTION,
7530 +        .DeviceCount   = 0,
7531 +        .Driver.HcdDevice.name = "sdio_xxx_hcd",
7532 +        .Driver.HcdDriver.name = "sdio_xxx_hcd",
7533 +    }
7534 +    .....
7535 +    status = SDIO_BusAddOSDevice(NULL, &HcdContext.Driver, &HcdContext.Device);
7536 +    if (SDIO_SUCCESS(status) {
7537 +        return Probe(&HcdContext.Device);
7538 +    }
7539 +    return SDIOErrorToOSError(status);
7540 +
7541 +  @see also: SDIO_BusRemoveOSDevice
7542 +
7543 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
7544 +SDIO_STATUS SDIO_BusAddOSDevice(PSDDMA_DESCRIPTION pDma, POS_PNPDRIVER pDriver, POS_PNPDEVICE pDevice)
7545 +{
7546 +    int err;
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 */
7550 +
7551 +    if (pDma != NULL) {
7552 +        pDevice->dev.dma_mask = &pDma->Mask;
7553 +        pDevice->dev.coherent_dma_mask = pDma->Mask;
7554 +    }
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",
7561 +             slotNumber++);
7562 +    pFdid[0].driver_data = 0;
7563 +    pFdid[1].id[0] = '\0';
7564 +    pFdid[1].driver_data = 0;
7565 +
7566 +    pDriver->id_table = pFdid;
7567 +    pDriver->flags = PNP_DRIVER_RES_DO_NOT_CHANGE;
7568 +    err = pnp_register_driver(pDriver);
7569 +    if (err < 0) {
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);
7574 +    }
7575 +
7576 +    pDevice->protocol = &sdio_protocol;
7577 +    pDevice->capabilities = PNP_REMOVABLE | PNP_DISABLE;
7578 +    pDevice->active = 1;
7579 +
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);
7586 +
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);
7594 +    if (err < 0) {
7595 +        DBG_PRINT(SDDBG_ERROR, ("SDIO BusDriver - SDIO_GetBusOSDevice failed pnp_device_add: %d\n",
7596 +                               err));
7597 +        pnp_unregister_driver(pDriver);
7598 +    }
7599 +    /* replace the buggy pnp's release */
7600 +    pDevice->dev.release = release;
7601 +    return OSErrorToSDIOError(err);
7602 +}
7603 +
7604 +/**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7605 +  @function: Return OS device from bus driver.
7606 +
7607 +  @function name: SDIO_BusRemoveOSDevice
7608 +  @category: HD_Reference
7609 +
7610 +  @input: pDriver - setup PNP driver object
7611 +  @input: pDevice - setup PNP device object
7612 +
7613 +  @return: none
7614 +
7615 +
7616 +  @example: returning device objects:
7617 +        SDIO_BusRemoveOSDevice(&HcdContext.Driver, &HcdContext.Device);
7618 +
7619 +
7620 +  @see also: SDIO_BusAddOSDevice
7621 +
7622 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
7623 +void SDIO_BusRemoveOSDevice(POS_PNPDRIVER pDriver, POS_PNPDEVICE pDevice)
7624 +{
7625 +    DBG_PRINT(SDDBG_ERROR,
7626 +            ("SDIO BusDriver - SDIO_PutBusOSDevice, unregistering driver: %s\n",
7627 +            pDriver->name));
7628 +
7629 +    pnp_remove_card_device(pDevice);
7630 +    if (pDevice->id != NULL) {
7631 +        KernelFree(pDevice->id);
7632 +        pDevice->id = NULL;
7633 +    }
7634 +
7635 +    spin_lock(&InUseDevicesLock);
7636 +    ClearBit(&InUseDevices, pDevice->number);
7637 +    spin_unlock(&InUseDevicesLock);
7638 +
7639 +    pnp_unregister_driver(pDriver);
7640 +    if (pDriver->id_table != NULL) {
7641 +        KernelFree((void *)pDriver->id_table);
7642 +        pDriver->id_table = NULL;
7643 +    }
7644 +
7645 +}
7646 +
7647 +
7648 +/*
7649 + * module init
7650 +*/
7651 +static int __init sdio_busdriver_init(void) {
7652 +    SDIO_STATUS status;
7653 +    int error;
7654 +    REL_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: loaded\n"));
7655 +    if (!SDIO_SUCCESS((status = _SDIO_BusDriverInitialize()))) {
7656 +        return SDIOErrorToOSError(status);
7657 +    }
7658 +    /* register the sdio bus */
7659 +    error = pnp_register_protocol(&sdio_protocol);
7660 +    if (error < 0) {
7661 +        REL_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: failed to register bus device, %d\n", error));
7662 +        _SDIO_BusDriverCleanup();
7663 +        return error;
7664 +    }
7665 +    return 0;
7666 +}
7667 +
7668 +/*
7669 + * module cleanup
7670 +*/
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"));
7677 +}
7678 +EXPORT_SYMBOL(SDIO_BusAddOSDevice);
7679 +EXPORT_SYMBOL(SDIO_BusRemoveOSDevice);
7680 +
7681 +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
7682 +    /* 2.4 */
7683 +static int RegisterDriver(PSDFUNCTION pFunction)
7684 +{
7685 +    return 0;
7686 +}
7687 +
7688 +static int UnregisterDriver(PSDFUNCTION pFunction)
7689 +{
7690 +    DBG_PRINT(SDDBG_TRACE,
7691 +            ("+-SDIO BusDriver - UnregisterDriver, driver: \n"));
7692 +   return 0;
7693 +}
7694 +
7695 +/*
7696 + * OS_InitializeDevice - initialize device that will be registered
7697 +*/
7698 +SDIO_STATUS OS_InitializeDevice(PSDDEVICE pDevice, PSDFUNCTION pFunction)
7699 +{
7700 +    return SDIO_STATUS_SUCCESS;
7701 +}
7702 +
7703 +/*
7704 + * OS_AddDevice - must be pre-initialized with OS_InitializeDevice
7705 +*/
7706 +SDIO_STATUS OS_AddDevice(PSDDEVICE pDevice, PSDFUNCTION pFunction)
7707 +{
7708 +    DBG_PRINT(SDDBG_TRACE, ("SDIO BusDriver - OS_AddDevice adding function: %s\n",
7709 +                               pFunction->pName));
7710 +    return SDIO_STATUS_SUCCESS;
7711 +
7712 +}
7713 +
7714 +/*
7715 + * OS_RemoveDevice - unregister device with driver and bus
7716 +*/
7717 +void OS_RemoveDevice(PSDDEVICE pDevice)
7718 +{
7719 +    DBG_PRINT(SDDBG_TRACE, ("SDIO BusDriver - OS_RemoveDevice \n"));
7720 +}
7721 +
7722 +/*
7723 + * module init
7724 +*/
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);
7730 +    }
7731 +    return 0;
7732 +}
7733 +
7734 +/*
7735 + * module cleanup
7736 +*/
7737 +static void __exit sdio_busdriver_cleanup(void) {
7738 +    REL_PRINT(SDDBG_TRACE, ("SDIO unloaded\n"));
7739 +    _SDIO_BusDriverCleanup();
7740 +}
7741 +#else  ////KERNEL_VERSION
7742 +#error "unsupported kernel version: "UTS_RELEASE
7743 +#endif //KERNEL_VERSION
7744 +
7745 +MODULE_LICENSE("GPL and additional rights");
7746 +MODULE_DESCRIPTION(DESCRIPTION);
7747 +MODULE_AUTHOR(AUTHOR);
7748 +
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
7760 --- /dev/null
7761 +++ b/drivers/sdio/stack/busdriver/sdio_function.c
7762 @@ -0,0 +1,715 @@
7763 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7764 +@file: sdio_function.c
7765 +
7766 +@abstract: OS independent bus driver support for function drivers
7767 +
7768 +@notes: This file supports the interface between SDIO function drivers and the bus driver.
7769 +
7770 +@notice: Copyright (c), 2004-2005 Atheros Communications, Inc.
7771 +
7772 +
7773 + *
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;
7777 + *
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.
7782 + *
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:
7785 + *
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.
7791 + *   Disclaimers:
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.
7800 + *
7801 + *
7802 + *  The initial developers of the original code are Seung Yi and Paul Lever
7803 + *
7804 + *  sdio@atheros.com
7805 + *
7806 + *
7807 +
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"
7814 +
7815 +static SDIO_STATUS ProbeForDevice(PSDFUNCTION pFunction);
7816 +
7817 +#ifdef CT_MAN_CODE_CHECK
7818 +static UINT16 ManCodeCheck = CT_MAN_CODE_CHECK;
7819 +#endif
7820 +
7821 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7822 +  @function: Register a function driver with the bus driver.
7823 +
7824 +  @function name: SDIO_RegisterFunction
7825 +  @prototype: SDIO_STATUS SDIO_RegisterFunction(PSDFUNCTION pFunction)
7826 +  @category: PD_Reference
7827 +  @input:  pFunction - the function definition structure.
7828 +
7829 +  @output: none
7830 +
7831 +  @return: SDIO_STATUS - SDIO_STATUS_SUCCESS when succesful.
7832 +
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.
7840 +
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
7848 +        };
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
7857 +                                         //  is inserted.
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.
7862 +        };
7863 +        SDIO_STATUS status;
7864 +        status = SDIO_RegisterFunction(&FunctionContext.Function)
7865 +        if (!SDIO_SUCCESS(status)) {
7866 +            ...failed to register
7867 +        }
7868 +
7869 +  @see also: SDIO_UnregisterFunction
7870 +
7871 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
7872 +SDIO_STATUS _SDIO_RegisterFunction(PSDFUNCTION pFunction)
7873 +{
7874 +       SDIO_STATUS status = SDIO_STATUS_SUCCESS;
7875 +
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",
7879 +            ManCodeCheck));
7880 +#else
7881 +    DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: _SDIO_RegisterFunction\n"));
7882 +#endif
7883 +
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)));
7886 +
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;
7892 +    }
7893 +
7894 +
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;
7901 +       }
7902 +    /* protect the function list and add the function */
7903 +    if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->FunctionListSem)))) {
7904 +      goto cleanup;   /* wait interrupted */
7905 +    }
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 */
7911 +    }
7912 +
7913 +       /* see if we have devices for this new function driver */
7914 +       ProbeForDevice(pFunction);
7915 +
7916 +       return status;
7917 +cleanup:
7918 +    DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: _SDIO_RegisterFunction, error exit 0x%X\n", status));
7919 +    return status;
7920 +}
7921 +
7922 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7923 +  @function: Unregister a function driver with the bus driver.
7924 +
7925 +  @function name: SDIO_UnregisterFunction
7926 +  @prototype: SDIO_STATUS SDIO_UnregisterFunction(PSDFUNCTION pFunction)
7927 +  @category: PD_Reference
7928 +
7929 +  @input:  pFunction - the function definition structure.
7930 +
7931 +  @output: none
7932 +
7933 +  @return: SDIO_STATUS - SDIO_STATUS_SUCCESS when succesful.
7934 +
7935 +  @notes: Each function driver must unregister from the bus driver when the function driver
7936 +          exits.
7937 +          A function driver must disconnect from any interrupts before calling this function.
7938 +
7939 +  @example: Unregistering a function driver:
7940 +        SDIO_UnregisterFunction(&FunctionContext.Function);
7941 +
7942 +  @see also: SDIO_RegisterFunction
7943 +
7944 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
7945 +SDIO_STATUS _SDIO_UnregisterFunction(PSDFUNCTION pFunction)
7946 +{
7947 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
7948 +    PSDDEVICE pDevice;
7949 +
7950 +    DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: _SDIO_UnregisterFunction\n"));
7951 +
7952 +    /* protect the function list and synchronize with Probe() and Remove()*/
7953 +    if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->FunctionListSem)))) {
7954 +        goto cleanup;   /* wait interrupted */
7955 +    }
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);
7963 +        }
7964 +    }SDITERATE_END;
7965 +
7966 +    SignalDelete(&pFunction->CleanupReqSig);
7967 +
7968 +    if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->FunctionListSem)))) {
7969 +        goto cleanup;   /* wait interrupted */
7970 +    }
7971 +    DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: _SDIO_UnregisterFunction\n"));
7972 +       return status;
7973 +
7974 +cleanup:
7975 +    DBG_PRINT(SDDBG_ERROR, ("-SDIO Bus Driver: _SDIO_UnregisterFunction, error exit 0x%X\n", status));
7976 +    return status;
7977 +}
7978 +
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.
7982 +
7983 +  @function name: Probe
7984 +  @prototype: BOOL (*pProbe)(struct _SDFUNCTION *pFunction, struct _SDDEVICE *pDevice)
7985 +  @category: PD_Reference
7986 +
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.
7990 +
7991 +  @output: none
7992 +
7993 +  @return: TRUE  - this function driver will suport this device
7994 +           FALSE - this function driver will not support this device
7995 +
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.
7999 +
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));
8013 +        ...
8014 +
8015 +  @see also: SDIO_RegisterFunction
8016 +  @see also: Remove
8017 +
8018 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8019 +
8020 +BOOL FilterPnpInfo(PSDDEVICE pDevice)
8021 +{
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));
8029 +            return FALSE;
8030 +        }
8031 +    }
8032 +    return TRUE;
8033 +#else
8034 +    return TRUE;
8035 +#endif
8036 +}
8037 +
8038 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8039 +  @function: This function is called by the Busdriver when a device controlled by this function
8040 +             function driver is removed.
8041 +
8042 +  @function name: Remove
8043 +  @prototype: void (*pRemove)(struct _SDFUNCTION *pFunction, struct _SDDEVICE *pDevice)
8044 +  @category: PD_Reference
8045 +
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.
8049 +
8050 +  @output: none
8051 +
8052 +  @return: none
8053 +
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.
8057 +
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.
8064 +
8065 +  @see also: SDIO_RegisterFunction
8066 +  @see also: Probe
8067 +
8068 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8069 +
8070 +/*
8071 + * ProbeForFunction - look for a function driver to handle this card
8072 + *
8073 +*/
8074 +SDIO_STATUS ProbeForFunction(PSDDEVICE pDevice, PSDHCD pHcd) {
8075 +    SDIO_STATUS status;
8076 +    PSDLIST pList;
8077 +    PSDFUNCTION pFunction;
8078 +
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));
8087 +    }
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));
8091 +    }
8092 +
8093 +    if (!FilterPnpInfo(pDevice)) {
8094 +        status = SDIO_STATUS_SUCCESS;
8095 +        goto cleanup;
8096 +    }
8097 +
8098 +    /* protect the function list */
8099 +    if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->FunctionListSem)))) {
8100 +        goto cleanup;   /* wait interrupted */
8101 +    }
8102 +
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);
8107 +        goto cleanup;
8108 +    }
8109 +
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;
8119 +        goto cleanup;
8120 +    }
8121 +
8122 +        /* release device list */
8123 +    SemaphorePost(&pBusContext->DeviceListSem);
8124 +
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 */
8130 +            continue;
8131 +        }
8132 +        DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: ProbeForFunction - checking: %s \n",
8133 +                                pFunction->pName));
8134 +
8135 +        /* see if this function handles this device */
8136 +        if (IsPotentialIdMatch(pDevice->pId, pFunction->pIds)) {
8137 +            if (!FilterPnpInfo(pDevice)) {
8138 +                break;
8139 +            }
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))) {
8146 +                break;
8147 +            }
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++;
8154 +                break;
8155 +            } else {
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);
8160 +            }
8161 +
8162 +        }
8163 +    }
8164 +    if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->FunctionListSem)))) {
8165 +        goto cleanup;   /* wait interrupted */
8166 +    }
8167 +    DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: ProbeForFunction\n"));
8168 +       return status;
8169 +cleanup:
8170 +    DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: ProbeForFunction, error exit 0x%X\n", status));
8171 +    return status;
8172 +}
8173 +
8174 +/*
8175 + * ProbeForDevice - look for a device that this function driver supports
8176 + *
8177 +*/
8178 +static SDIO_STATUS ProbeForDevice(PSDFUNCTION pFunction) {
8179 +    SDIO_STATUS status;
8180 +    PSDLIST pList;
8181 +    PSDDEVICE pDevice;
8182 +
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;
8188 +    }
8189 +
8190 +     /* protect the driver list */
8191 +    if (!SDIO_SUCCESS((status = SemaphorePendInterruptable(&pBusContext->DeviceListSem)))) {
8192 +      goto cleanup;   /* wait interrupted */
8193 +    }
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"));
8200 +            continue;
8201 +        }
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)) {
8209 +                break;
8210 +            }
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))) {
8215 +                break;
8216 +            }
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++;
8223 +                break;
8224 +            } else {
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);
8229 +            }
8230 +        }
8231 +    }
8232 +    if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->DeviceListSem)))) {
8233 +      goto cleanup;   /* wait interrupted */
8234 +    }
8235 +
8236 +       return status;
8237 +cleanup:
8238 +    DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: ProbeForDevice, error exit 0x%X\n", status));
8239 +    return status;
8240 +}
8241 +
8242 +#if 0
8243 +static void DumpPnpEntry(PSD_PNP_INFO pInfo)
8244 +{
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));
8253 +}
8254 +#endif
8255 +/*
8256 + * IsPotentialIdMatch - test for potential device match
8257 + *
8258 +*/
8259 +BOOL IsPotentialIdMatch(PSD_PNP_INFO pIdsDev, PSD_PNP_INFO pIdsFuncList) {
8260 +    PSD_PNP_INFO pTFn;
8261 +       BOOL match = FALSE;
8262 +
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)) ) {
8272 +                   match = TRUE;
8273 +            break;
8274 +               }
8275 +            /* check generic function class */
8276 +        if ((pIdsDev->SDIO_FunctionClass != 0) &&
8277 +            (pTFn->SDIO_FunctionClass != 0) &&
8278 +            (pIdsDev->SDIO_FunctionClass == pTFn->SDIO_FunctionClass)) {
8279 +            match = TRUE;
8280 +            break;
8281 +        }
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)) {
8287 +            match = TRUE;
8288 +            break;
8289 +        }
8290 +
8291 +            /* check generic SD Card */
8292 +        if ((pIdsDev->CardFlags & CARD_SD) &&
8293 +            (pTFn->CardFlags & CARD_SD)){
8294 +            match = TRUE;
8295 +            break;
8296 +        }
8297 +
8298 +            /* check generic MMC Card */
8299 +        if ((pIdsDev->CardFlags & CARD_MMC) &&
8300 +            (pTFn->CardFlags & CARD_MMC)){
8301 +            match = TRUE;
8302 +            break;
8303 +        }
8304 +
8305 +             /* check raw Card */
8306 +        if ((pIdsDev->CardFlags & CARD_RAW) &&
8307 +            (pTFn->CardFlags & CARD_RAW)){
8308 +            match = TRUE;
8309 +            break;
8310 +        }
8311 +       }
8312 +
8313 +    return match;
8314 +}
8315 +
8316 +/*
8317 + * NotifyDeviceRemove - tell function driver on this device that the device is being removed
8318 + *
8319 +*/
8320 +SDIO_STATUS NotifyDeviceRemove(PSDDEVICE pDevice) {
8321 +    SDIO_STATUS     status;
8322 +    SDREQUESTQUEUE  cancelQueue;
8323 +    PSDREQUEST      pReq;
8324 +    CT_DECLARE_IRQ_SYNC_CONTEXT();
8325 +
8326 +    InitializeRequestQueue(&cancelQueue);
8327 +
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)) {
8335 +            return status;
8336 +        }
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);
8350 +            }
8351 +        }SDITERATE_END;
8352 +
8353 +        status = _ReleaseHcdLock(pDevice->pHcd);
8354 +
8355 +           /* now empty the cancel queue if anything is in there */
8356 +        while (TRUE) {
8357 +            pReq = DequeueRequest(&cancelQueue);
8358 +            if (NULL == pReq) {
8359 +                break;
8360 +            }
8361 +                /* complete the request */
8362 +            DoRequestCompletion(pReq, pDevice->pHcd);
8363 +        }
8364 +            /* re-acquire the lock to deal with the current request */
8365 +        status = _AcquireHcdLock(pDevice->pHcd);
8366 +        if (!SDIO_SUCCESS(status)) {
8367 +            return status;
8368 +        }
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));
8380 +        }  else {
8381 +                /* release lock */
8382 +            status = _ReleaseHcdLock(pDevice->pHcd);
8383 +        }
8384 +
8385 +            /* synchronize with ISR SYNC Handlers */
8386 +               status = SemaphorePendInterruptable(&pBusContext->DeviceListSem);
8387 +        if (!SDIO_SUCCESS(status)) {
8388 +            return status;
8389 +        }
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);
8396 +
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;
8402 +       }
8403 +       return SDIO_STATUS_SUCCESS;
8404 +}
8405 +
8406 +
8407 +/*
8408 + * RemoveHcdFunctions - remove all functions attached to an HCD
8409 + *
8410 +*/
8411 +SDIO_STATUS RemoveHcdFunctions(PSDHCD pHcd) {
8412 +    SDIO_STATUS status;
8413 +    PSDLIST pList;
8414 +    PSDFUNCTION pFunction;
8415 +    PSDDEVICE pDevice;
8416 +    DBG_PRINT(SDDBG_TRACE, ("+SDIO Bus Driver: RemoveHcdFunctions\n"));
8417 +
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 */
8422 +    }
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));
8429 +
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);
8435 +            }
8436 +        SDITERATE_END;
8437 +    SDITERATE_END;
8438 +    if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->FunctionListSem)))) {
8439 +        goto cleanup;   /* wait interrupted */
8440 +    }
8441 +    DBG_PRINT(SDDBG_TRACE, ("-SDIO Bus Driver: RemoveHcdFunctions\n"));
8442 +    return SDIO_STATUS_SUCCESS;
8443 +
8444 +cleanup:
8445 +    DBG_PRINT(SDDBG_ERROR, ("-SDIO Bus Driver: RemoveHcdFunctions, error exit 0x%X\n", status));
8446 +    return status;
8447 +}
8448 +
8449 +/*
8450 + * RemoveAllFunctions - remove all functions attached
8451 + *
8452 +*/
8453 +SDIO_STATUS RemoveAllFunctions()
8454 +{
8455 +    SDIO_STATUS status;
8456 +    PSDLIST pList;
8457 +    PSDHCD pHcd;
8458 +
8459 +    /* walk through the HCDs  */
8460 +    /* protect the driver list */
8461 +    if (!SDIO_SUCCESS((status = SemaphorePend(&pBusContext->HcdListSem)))) {
8462 +        goto cleanup;   /* wait interrupted */
8463 +    }
8464 +    SDITERATE_OVER_LIST(&pBusContext->HcdList, pList) {
8465 +        pHcd = CONTAINING_STRUCT(pList, SDHCD, SDList);
8466 +            /* remove the functions */
8467 +        RemoveHcdFunctions(pHcd);
8468 +    }
8469 +    if (!SDIO_SUCCESS((status = SemaphorePost(&pBusContext->HcdListSem)))) {
8470 +        goto cleanup;   /* wait interrupted */
8471 +    }
8472 +    return SDIO_STATUS_SUCCESS;
8473 +cleanup:
8474 +    DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: RemoveAllFunctions, error exit 0x%X\n", status));
8475 +    return status;
8476 +}
8477 +
8478 diff --git a/drivers/sdio/stack/lib/Makefile b/drivers/sdio/stack/lib/Makefile
8479 new file mode 100644
8480 index 0000000..44fa038
8481 --- /dev/null
8482 +++ b/drivers/sdio/stack/lib/Makefile
8483 @@ -0,0 +1,2 @@
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
8489 --- /dev/null
8490 +++ b/drivers/sdio/stack/lib/_sdio_lib.h
8491 @@ -0,0 +1,50 @@
8492 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8493 +@file: _sdio_lib.h
8494 +
8495 +@abstract: SDIO Lib internal include
8496 +
8497 +#notes:
8498 +
8499 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
8500 +
8501 +
8502 + *
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;
8506 + *
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.
8511 + *
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:
8514 + *
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.
8520 + *   Disclaimers:
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.
8529 + *
8530 + *
8531 + *  The initial developers of the original code are Seung Yi and Paul Lever
8532 + *
8533 + *  sdio@atheros.com
8534 + *
8535 + *
8536 +
8537 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8538 +#ifndef ___SDIO_LIB_H___
8539 +#define ___SDIO_LIB_H___
8540 +
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
8545 --- /dev/null
8546 +++ b/drivers/sdio/stack/lib/sdio_lib_c.c
8547 @@ -0,0 +1,908 @@
8548 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8549 +@file: sdio_lib_c.c
8550 +
8551 +@abstract: OS independent SDIO library functions
8552 +@category abstract: Support_Reference Support Functions.
8553 +
8554 +@notes: Support functions for device I/O
8555 +
8556 +@notice: Copyright (c), 2004-2005 Atheros Communications, Inc.
8557 +
8558 +
8559 + *
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;
8563 + *
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.
8568 + *
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:
8571 + *
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.
8577 + *   Disclaimers:
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.
8586 + *
8587 + *
8588 + *  The initial developers of the original code are Seung Yi and Paul Lever
8589 + *
8590 + *  sdio@atheros.com
8591 + *
8592 + *
8593 +
8594 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8595 +#define MODULE_NAME  SDLIB_
8596 +
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"
8602 +
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)
8609 +
8610 +/* inline version */
8611 +static INLINE void _iSDLIB_SetupCMD52Request(UINT8         FuncNo,
8612 +                                             UINT32        Address,
8613 +                                             BOOL          Write,
8614 +                                             UINT8         WriteData,
8615 +                                             PSDREQUEST    pRequest) {
8616 +    if (Write) {
8617 +        SDIO_SET_CMD52_ARG(pRequest->Argument,CMD52_WRITE,
8618 +                           FuncNo,
8619 +                           CMD52_NORMAL_WRITE,Address,WriteData);
8620 +    } else {
8621 +        SDIO_SET_CMD52_ARG(pRequest->Argument,CMD52_READ,FuncNo,0,Address,0x00);
8622 +    }
8623 +
8624 +    pRequest->Flags = SDREQ_FLAGS_RESP_SDIO_R5;
8625 +    pRequest->Command = CMD52;
8626 +}
8627 +
8628 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8629 +  @function: Setup cmd52 requests
8630 +
8631 +  @function name: SDLIB_SetupCMD52Request
8632 +  @prototype: void SDLIB_SetupCMD52Request(UINT8         FuncNo,
8633 +                                           UINT32        Address,
8634 +                                           BOOL          Write,
8635 +                                           UINT8         WriteData,
8636 +                                           PSDREQUEST    pRequest)
8637 +  @category: PD_Reference
8638 +
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.
8643 +
8644 +  @output: pRequest - request is updated with cmd52 parameters
8645 +
8646 +  @return: none
8647 +
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.
8652 +
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) {
8656 +             ... errors
8657 +          } else {
8658 +             registerValue = SD_R5_GET_READ_DATA(pRequest->Response);
8659 +          }
8660 +
8661 +  @see also: SDLIB_IssueCMD52
8662 +  @see also: SDDEVICE_CALL_REQUEST_FUNC
8663 +
8664 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8665 +void _SDLIB_SetupCMD52Request(UINT8         FuncNo,
8666 +                              UINT32        Address,
8667 +                              BOOL          Write,
8668 +                              UINT8         WriteData,
8669 +                              PSDREQUEST    pRequest)
8670 +{
8671 +    _iSDLIB_SetupCMD52Request(FuncNo,Address,Write,WriteData,pRequest);
8672 +}
8673 +
8674 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8675 +  @function: Issue a CMD52 to read or write a register
8676 +
8677 +  @function name: SDLIB_IssueCMD52
8678 +  @prototype: SDIO_STATUS SDLIB_IssueCMD52(PSDDEVICE     pDevice,
8679 +                                           UINT8         FuncNo,
8680 +                                           UINT32        Address,
8681 +                                           PUINT8        pData,
8682 +                                           INT           ByteCount,
8683 +                                           BOOL          Write)
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.
8691 +
8692 +  @output: pData - data buffer for writes.
8693 +
8694 +  @return: SDIO Status
8695 +
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
8698 +           the caller.
8699 +
8700 +  @see also: SDLIB_SetupCMD52Request
8701 +
8702 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8703 +SDIO_STATUS _SDLIB_IssueCMD52(PSDDEVICE     pDevice,
8704 +                              UINT8         FuncNo,
8705 +                              UINT32        Address,
8706 +                              PUINT8        pData,
8707 +                              INT           ByteCount,
8708 +                              BOOL          Write)
8709 +{
8710 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
8711 +
8712 +    PSDREQUEST  pReq = NULL;
8713 +
8714 +    pReq = SDDeviceAllocRequest(pDevice);
8715 +
8716 +    if (NULL == pReq) {
8717 +        return SDIO_STATUS_NO_RESOURCES;
8718 +    }
8719 +
8720 +    while (ByteCount) {
8721 +        _iSDLIB_SetupCMD52Request(FuncNo,Address,Write,*pData,pReq);
8722 +        status = SDDEVICE_CALL_REQUEST_FUNC(pDevice,pReq);
8723 +        if (!SDIO_SUCCESS(status)) {
8724 +            break;
8725 +        }
8726 +
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)));
8731 +            break;
8732 +        }
8733 +        if (!Write) {
8734 +                /* store the byte */
8735 +            *pData =  SD_R5_GET_READ_DATA(pReq->Response);
8736 +        }
8737 +        pData++;
8738 +        Address++;
8739 +        ByteCount--;
8740 +    }
8741 +
8742 +    SDDeviceFreeRequest(pDevice,pReq);
8743 +    return status;
8744 +}
8745 +
8746 +
8747 +
8748 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8749 +  @function: Find a device's tuple.
8750 +
8751 +  @function name: SDLIB_FindTuple
8752 +  @prototype: SDIO_STATUS SDLIB_FindTuple(PSDDEVICE  pDevice,
8753 +                                          UINT8      Tuple,
8754 +                                          UINT32     *pTupleScanAddress,
8755 +                                          PUINT8     pBuffer,
8756 +                                          UINT8      *pLength)
8757 +
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
8763 +
8764 +  @output: pBuffer - storage for tuple
8765 +  @output: pTupleScanAddress - address of the next tuple
8766 +  @output: pLength - length of tuple read
8767 +
8768 +  @return: status
8769 +
8770 +  @notes: It is possible to have the same tuple ID multiple times with different lengths. This function
8771 +          blocks and is fully synchronous.
8772 +
8773 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8774 +SDIO_STATUS _SDLIB_FindTuple(PSDDEVICE  pDevice,
8775 +                             UINT8      Tuple,
8776 +                             UINT32     *pTupleScanAddress,
8777 +                             PUINT8     pBuffer,
8778 +                             UINT8      *pLength)
8779 +{
8780 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
8781 +    UINT32      scanStart = *pTupleScanAddress;
8782 +    UINT8       tupleCode;
8783 +    UINT8       tupleLink;
8784 +
8785 +        /* sanity check */
8786 +    if (scanStart < SDIO_CIS_AREA_BEGIN) {
8787 +        return SDIO_STATUS_CIS_OUT_OF_RANGE;
8788 +    }
8789 +
8790 +    while (TRUE) {
8791 +            /* check for end */
8792 +        if (scanStart > SDIO_CIS_AREA_END) {
8793 +            status = SDIO_STATUS_TUPLE_NOT_FOUND;
8794 +            break;
8795 +        }
8796 +            /* get the code */
8797 +        status = _Cmd52ReadByteCommon(pDevice, scanStart, &tupleCode);
8798 +        if (!SDIO_SUCCESS(status)) {
8799 +            break;
8800 +        }
8801 +        if (CISTPL_END == tupleCode) {
8802 +                /* found the end */
8803 +            status = SDIO_STATUS_TUPLE_NOT_FOUND;
8804 +            break;
8805 +        }
8806 +            /* bump past tuple code */
8807 +        scanStart++;
8808 +            /* get the tuple link value */
8809 +        status = _Cmd52ReadByteCommon(pDevice, scanStart, &tupleLink);
8810 +        if (!SDIO_SUCCESS(status)) {
8811 +            break;
8812 +        }
8813 +            /* bump past tuple link*/
8814 +        scanStart++;
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;
8822 +            } else {
8823 +                    /* the tuple link is an end marker */
8824 +                *pTupleScanAddress = 0xFFFFFFFF;
8825 +            }
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);
8831 +            }
8832 +                /* break out of loop */
8833 +            break;
8834 +        }
8835 +            /*increment past this entire tuple */
8836 +        scanStart += tupleLink;
8837 +    }
8838 +
8839 +    return status;
8840 +}
8841 +
8842 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8843 +  @function: Issue an SDIO configuration command.
8844 +
8845 +  @function name: SDLIB_IssueConfig
8846 +  @prototype: SDIO_STATUS _SDLIB_IssueConfig(PSDDEVICE        pDevice,
8847 +                                             SDCONFIG_COMMAND Command,
8848 +                                             PVOID            pData,
8849 +                                             INT              Length)
8850 +
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
8856 +
8857 +  @output: pData - updated on commands that return data.
8858 +
8859 +  @return: SDIO Status
8860 +
8861 +  @example: Command and data pairs:
8862 +            Type                               Data
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
8869 +
8870 +  @notes:
8871 +
8872 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8873 +SDIO_STATUS _SDLIB_IssueConfig(PSDDEVICE        pDevice,
8874 +                               SDCONFIG_COMMAND Command,
8875 +                               PVOID            pData,
8876 +                               INT              Length)
8877 +{
8878 +    SDCONFIG  configHdr;
8879 +    SET_SDCONFIG_CMD_INFO(&configHdr,Command,pData,Length);
8880 +    return SDDEVICE_CALL_CONFIG_FUNC(pDevice,&configHdr);
8881 +}
8882 +
8883 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8884 +  @function: Set function block size
8885 +
8886 +  @function name: SDLIB_SetFunctionBlockSize
8887 +  @prototype: SDIO_STATUS SDLIB_SetFunctionBlockSize(PSDDEVICE        pDevice,
8888 +                                                     UINT16           BlockSize)
8889 +
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
8893 +
8894 +  @output: none
8895 +
8896 +  @return: SDIO Status
8897 +
8898 +  @notes:  Issues CMD52 to set the block size.  This function is fully synchronous and may
8899 +           block.
8900 +
8901 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8902 +SDIO_STATUS _SDLIB_SetFunctionBlockSize(PSDDEVICE        pDevice,
8903 +                                        UINT16           BlockSize)
8904 +{
8905 +    UINT8   data[2];
8906 +
8907 +      /* endian safe */
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))),
8915 +                             data,
8916 +                             2,
8917 +                             TRUE);
8918 +}
8919 +
8920 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8921 +  @function: Print a buffer to the debug output
8922 +
8923 +  @function name: SDLIB_PrintBuffer
8924 +  @prototype: void SDLIB_PrintBuffer(PUCHAR pBuffer, INT Length, PTEXT pDescription)
8925 +  @category: Support_Reference
8926 +
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.
8930 +
8931 +  @output: none
8932 +
8933 +  @return: none
8934 +
8935 +  @notes:  Prints the buffer by converting to ASCII and using REL_PRINT() with 16
8936 +           bytes per line.
8937 +
8938 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8939 +void _SDLIB_PrintBuffer(PUCHAR pBuffer, INT Length, PTEXT pDescription)
8940 +{
8941 +    TEXT  line[49];
8942 +    TEXT  address[5];
8943 +    TEXT  ascii[17];
8944 +    TEXT  temp[5];
8945 +    INT   i;
8946 +    UCHAR num;
8947 +    USHORT offset = 0;
8948 +
8949 +    REL_PRINT(0,
8950 +              ("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"));
8951 +    if (pDescription != NULL) {
8952 +        REL_PRINT(0, ("Description: %s \n\n",pDescription));
8953 +    } else {
8954 +        REL_PRINT(0, ("Description: NONE \n\n"));
8955 +    }
8956 +    REL_PRINT(0,
8957 +              ("Offset                   Data                               ASCII        \n"));
8958 +    REL_PRINT(0,
8959 +              ("--------------------------------------------------------------------------\n"));
8960 +
8961 +    while (Length) {
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) {
8968 +                num = *pBuffer;
8969 +                sprintf(temp,"%2.2X ",num);
8970 +                strcat(line,temp);
8971 +                if ((num >= 0x20) && (num <= 0x7E)) {
8972 +                    sprintf(temp,"%c",*pBuffer);
8973 +                } else {
8974 +                    sprintf(temp,"%c",0x2e);
8975 +                }
8976 +                strcat(ascii,temp);
8977 +                pBuffer++;
8978 +                Length--;
8979 +            } else {
8980 +                    /* pad partial line with spaces */
8981 +                strcat(line,"   ");
8982 +                strcat(ascii," ");
8983 +            }
8984 +        }
8985 +        REL_PRINT(0,("%s    %s   %s\n", address, line, ascii));
8986 +        offset += 16;
8987 +    }
8988 +    REL_PRINT(0,
8989 +              ("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"));
8990 +
8991 +}
8992 +
8993 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8994 +  @function: Get default operational current
8995 +
8996 +  @function name: SDLIB_GetDefaultOpCurrent
8997 +  @prototype: SDIO_STATUS SDLIB_GetDefaultOpCurrent(PSDDEVICE  pDevice, SD_SLOT_CURRENT *pOpCurrent)
8998 +  @category: PD_Reference
8999 +
9000 +  @input: pDevice - the device that is the target of the command.
9001 +
9002 +  @output: pOpCurrent - operational current in mA.
9003 +
9004 +  @return: SDIO_STATUS
9005 +
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.
9012 +
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)) {
9017 +           .. failed
9018 +       }
9019 +
9020 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9021 +SDIO_STATUS _SDLIB_GetDefaultOpCurrent(PSDDEVICE  pDevice, SD_SLOT_CURRENT *pOpCurrent)
9022 +{
9023 +    UINT32              nextTpl;
9024 +    UINT8               tplLength;
9025 +    struct SDIO_FUNC_EXT_FUNCTION_TPL_1_1 funcTuple;
9026 +    SDIO_STATUS         status;
9027 +
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,
9033 +                              CISTPL_FUNCE,
9034 +                              &nextTpl,
9035 +                              (PUINT8)&funcTuple,
9036 +                              &tplLength);
9037 +
9038 +    if (!SDIO_SUCCESS(status)) {
9039 +        DBG_PRINT(SDDBG_ERROR, ("SDLIB_GetDefaultOpCurrent: Failed to get FuncE Tuple: %d \n", status));
9040 +        return status;
9041 +    }
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);
9050 +        }
9051 +    }
9052 +    return SDIO_STATUS_SUCCESS;
9053 +}
9054 +
9055 +
9056 +static INLINE void FreeMessageBlock(PSDMESSAGE_QUEUE pQueue, PSDMESSAGE_BLOCK pMsg) {
9057 +    SDListInsertHead(&pQueue->FreeMessageList, &pMsg->SDList);
9058 +}
9059 +static INLINE void QueueMessageBlock(PSDMESSAGE_QUEUE pQueue, PSDMESSAGE_BLOCK pMsg) {
9060 +    SDListInsertTail(&pQueue->MessageList, &pMsg->SDList);
9061 +}
9062 +static INLINE void QueueMessageToHead(PSDMESSAGE_QUEUE pQueue, PSDMESSAGE_BLOCK pMsg) {
9063 +    SDListInsertHead(&pQueue->MessageList, &pMsg->SDList);
9064 +}
9065 +
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);
9070 +    }
9071 +    return NULL;
9072 +}
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);
9077 +    }
9078 +    return NULL;
9079 +}
9080 +
9081 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9082 +  @function: Create a message queue
9083 +
9084 +  @function name: SDLIB_CreateMessageQueue
9085 +  @prototype: PSDMESSAGE_QUEUE SDLIB_CreateMessageQueue(INT MaxMessages, INT MaxMessageLength)
9086 +  @category: Support_Reference
9087 +
9088 +  @input: MaxMessages - Maximum number of messages this queue supports
9089 +  @input: MaxMessageLength - Maximum size of each message
9090 +
9091 +  @return: Message queue object, NULL on failure
9092 +
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
9099 +           user defined.
9100 +
9101 +  @see also: SDLIB_DeleteMessageQueue, SDLIB_GetMessage, SDLIB_PostMessage.
9102 +
9103 +  @example: Creating a message queue:
9104 +       typedef struct _MyMessage {
9105 +           UINT8 Code;
9106 +           PVOID pDataBuffer;
9107 +       } MyMessage;
9108 +            // create message queue, 16 messages max.
9109 +       pMsgQueue = SDLIB_CreateMessageQueue(16,sizeof(MyMessage));
9110 +       if (NULL == pMsgQueue) {
9111 +           .. failed
9112 +       }
9113 +
9114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9115 +PSDMESSAGE_QUEUE _CreateMessageQueue(INT MaxMessages, INT MaxMessageLength)
9116 +{
9117 +    PSDMESSAGE_QUEUE pQueue = NULL;
9118 +    SDIO_STATUS      status = SDIO_STATUS_SUCCESS;
9119 +    INT              ii;
9120 +    PSDMESSAGE_BLOCK pMsg;
9121 +
9122 +    do {
9123 +        pQueue = (PSDMESSAGE_QUEUE)KernelAlloc(sizeof(SDMESSAGE_QUEUE));
9124 +
9125 +        if (NULL == pQueue) {
9126 +            status = SDIO_STATUS_NO_RESOURCES;
9127 +            break;
9128 +        }
9129 +        SDLIST_INIT(&pQueue->MessageList);
9130 +        SDLIST_INIT(&pQueue->FreeMessageList);
9131 +        pQueue->MaxMessageLength = MaxMessageLength;
9132 +        status = CriticalSectionInit(&pQueue->MessageCritSection);
9133 +        if (!SDIO_SUCCESS(status)) {
9134 +            break;
9135 +        }
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) {
9140 +                break;
9141 +            }
9142 +            FreeMessageBlock(pQueue, pMsg);
9143 +        }
9144 +
9145 +        if (0 == ii) {
9146 +            status = SDIO_STATUS_NO_RESOURCES;
9147 +            break;
9148 +        }
9149 +
9150 +    } while (FALSE);
9151 +
9152 +    if (!SDIO_SUCCESS(status)) {
9153 +        if (pQueue != NULL) {
9154 +            _DeleteMessageQueue(pQueue);
9155 +            pQueue = NULL;
9156 +        }
9157 +    }
9158 +    return pQueue;
9159 +}
9160 +
9161 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9162 +  @function: Delete a message queue
9163 +
9164 +  @function name: SDLIB_DeleteMessageQueue
9165 +  @prototype: void SDLIB_DeleteMessageQueue(PSDMESSAGE_QUEUE pQueue)
9166 +  @category: Support_Reference
9167 +
9168 +  @input: pQueue - message queue to delete
9169 +
9170 +  @notes: This function flushes the message queue and frees all memory allocated for
9171 +          messages.
9172 +
9173 +  @see also: SDLIB_CreateMessageQueue
9174 +
9175 +  @example: Deleting a message queue:
9176 +       if (pMsgQueue != NULL) {
9177 +            SDLIB_DeleteMessageQueue(pMsgQueue);
9178 +       }
9179 +
9180 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9181 +void _DeleteMessageQueue(PSDMESSAGE_QUEUE pQueue)
9182 +{
9183 +    PSDMESSAGE_BLOCK pMsg;
9184 +    SDIO_STATUS     status;
9185 +    CT_DECLARE_IRQ_SYNC_CONTEXT();
9186 +
9187 +    status = CriticalSectionAcquireSyncIrq(&pQueue->MessageCritSection);
9188 +
9189 +        /* cleanup free list */
9190 +    while (1) {
9191 +        pMsg = GetFreeMessageBlock(pQueue);
9192 +        if (pMsg != NULL) {
9193 +            KernelFree(pMsg);
9194 +        } else {
9195 +            break;
9196 +        }
9197 +    }
9198 +        /* cleanup any in the queue */
9199 +    while (1) {
9200 +        pMsg = GetQueuedMessage(pQueue);
9201 +        if (pMsg != NULL) {
9202 +            KernelFree(pMsg);
9203 +        } else {
9204 +            break;
9205 +        }
9206 +    }
9207 +
9208 +    status = CriticalSectionReleaseSyncIrq(&pQueue->MessageCritSection);
9209 +    CriticalSectionDelete(&pQueue->MessageCritSection);
9210 +    KernelFree(pQueue);
9211 +
9212 +}
9213 +
9214 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9215 +  @function: Post a message queue
9216 +
9217 +  @function name: SDLIB_PostMessage
9218 +  @prototype: SDIO_STATUS SDLIB_PostMessage(PSDMESSAGE_QUEUE pQueue, PVOID pMessage, INT MessageLength)
9219 +  @category: Support_Reference
9220 +
9221 +  @input: pQueue - message queue to post to
9222 +  @input: pMessage - message to post
9223 +  @input: MessageLength - length of message (for validation)
9224 +
9225 +  @return: SDIO_STATUS
9226 +
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
9235 +          driver context.
9236 +
9237 +  @see also: SDLIB_CreateMessageQueue , SDLIB_GetMessage
9238 +
9239 +  @example: Posting a message
9240 +       MyMessage message;
9241 +           // set up message
9242 +       message.code = MESSAGE_DATA_READY;
9243 +       message.pData = pInstance->pDataBuffers[currentIndex];
9244 +           // post message
9245 +       status = SDLIB_PostMessage(pInstance->pReadQueue,&message,sizeof(message));
9246 +       if (!SDIO_SUCCESS(status)) {
9247 +           // failed
9248 +       }
9249 +
9250 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9251 +SDIO_STATUS _PostMessage(PSDMESSAGE_QUEUE pQueue, PVOID pMessage, INT MessageLength)
9252 +{
9253 +    SDIO_STATUS status2;
9254 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
9255 +    PSDMESSAGE_BLOCK pMsg;
9256 +    CT_DECLARE_IRQ_SYNC_CONTEXT();
9257 +
9258 +    if (MessageLength > pQueue->MaxMessageLength) {
9259 +        return SDIO_STATUS_BUFFER_TOO_SMALL;
9260 +    }
9261 +
9262 +    status = CriticalSectionAcquireSyncIrq(&pQueue->MessageCritSection);
9263 +    if (!SDIO_SUCCESS(status)) {
9264 +        return status;
9265 +    }
9266 +
9267 +    do {
9268 +            /* get a message block */
9269 +        pMsg = GetFreeMessageBlock(pQueue);
9270 +        if (NULL == pMsg) {
9271 +            status = SDIO_STATUS_NO_RESOURCES;
9272 +            break;
9273 +        }
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);
9280 +    } while (FALSE);
9281 +
9282 +    status2 = CriticalSectionReleaseSyncIrq(&pQueue->MessageCritSection);
9283 +    return status;
9284 +}
9285 +
9286 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9287 +  @function: Get a message from a message queue
9288 +
9289 +  @function name: SDLIB_GetMessage
9290 +  @prototype: SDIO_STATUS SDLIB_GetMessage(PSDMESSAGE_QUEUE pQueue, PVOID pData, INT *pBufferLength)
9291 +  @category: Support_Reference
9292 +
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
9297 +
9298 +  @return: SDIO_STATUS
9299 +
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.
9306 +
9307 +  @see also: SDLIB_CreateMessageQueue , SDLIB_PostMessage
9308 +
9309 +  @example: Getting a message
9310 +       MyMessage message;
9311 +       INT       length;
9312 +           // set length
9313 +       length = sizeof(message);
9314 +           // post message
9315 +       status = SDLIB_GetMessage(pInstance->pReadQueue,&message,&length);
9316 +       if (!SDIO_SUCCESS(status)) {
9317 +           // failed
9318 +       }
9319 +
9320 +  @example: Checking queue for a message and getting the size of the message
9321 +       INT       length;
9322 +           // use zero length to get the size of the message
9323 +       length = 0;
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;
9330 +       } else {
9331 +            // some other failure
9332 +       }
9333 +
9334 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9335 +SDIO_STATUS _GetMessage(PSDMESSAGE_QUEUE pQueue, PVOID pData, INT *pBufferLength)
9336 +{
9337 +    SDIO_STATUS status2;
9338 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
9339 +    PSDMESSAGE_BLOCK pMsg;
9340 +    CT_DECLARE_IRQ_SYNC_CONTEXT();
9341 +
9342 +    status = CriticalSectionAcquireSyncIrq(&pQueue->MessageCritSection);
9343 +    if (!SDIO_SUCCESS(status)) {
9344 +        return status;
9345 +    }
9346 +
9347 +    do {
9348 +        pMsg = GetQueuedMessage(pQueue);
9349 +        if (NULL == pMsg) {
9350 +            status = SDIO_STATUS_NO_MORE_MESSAGES;
9351 +            break;
9352 +        }
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;
9359 +            break;
9360 +        }
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);
9367 +
9368 +    } while (FALSE);
9369 +
9370 +    status2 = CriticalSectionReleaseSyncIrq(&pQueue->MessageCritSection);
9371 +
9372 +    return status;
9373 +}
9374 +
9375 +/* the following documents the OS helper APIs */
9376 +
9377 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9378 +  @function: Create an OS-specific helper task/thread
9379 +
9380 +  @function name: SDLIB_OSCreateHelper
9381 +  @prototype: SDIO_STATUS SDLIB_OSCreateHelper(POSKERNEL_HELPER pHelper,
9382 +                                               PHELPER_FUNCTION pFunction,
9383 +                                               PVOID            pContext)
9384 +  @category: Support_Reference
9385 +
9386 +  @input: pHelper - caller allocated helper object
9387 +  @input: pFunction - helper function
9388 +  @input: pContext - helper context
9389 +
9390 +  @return: SDIO_STATUS
9391 +
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.
9400 +
9401 +  @see also: SDLIB_OSDeleteHelper , SD_WAIT_FOR_WAKEUP
9402 +
9403 +  @example: A thread helper function:
9404 +       THREAD_RETURN HelperFunction(POSKERNEL_HELPER pHelper)
9405 +       {
9406 +           SDIO_STATUS status;
9407 +           PMYCONTEXT pContext = (PMYCONTEXT)SD_GET_OS_HELPER_CONTEXT(pHelper);
9408 +                // wait for wake up
9409 +           while(1) {
9410 +                  status = SD_WAIT_FOR_WAKEUP(pHelper);
9411 +                  if (!SDIO_SUCCESS(status)) {
9412 +                      break;
9413 +                  }
9414 +                  if (SD_IS_HELPER_SHUTTING_DOWN(pHelper)) {
9415 +                      //... shutting down
9416 +                      break;
9417 +                  }
9418 +                  // handle wakeup...
9419 +            }
9420 +            return 0;
9421 +       }
9422 +
9423 +  @example: Creating a helper:
9424 +       status = SDLIB_OSCreateHelper(&pInstance->OSHelper,HelperFunction,pInstance);
9425 +       if (!SDIO_SUCCESS(status)) {
9426 +           // failed
9427 +       }
9428 +
9429 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9430 +
9431 +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9432 +  @function: Delete an OS helper task/thread
9433 +
9434 +  @function name: SDLIB_OSDeleteHelper
9435 +  @prototype: void SDLIB_OSDeleteHelper(POSKERNEL_HELPER pHelper)
9436 +  @category: Support_Reference
9437 +
9438 +  @input: pHelper - caller allocated helper object
9439 +
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.
9443 +
9444 +  @see also: SDLIB_OSCreateHelper
9445 +
9446 +  @example: Deleting a helper:
9447 +       if (pInstance->HelperCreated) {
9448 +               // clean up the helper if we successfully created it
9449 +           SDLIB_OSDeleteHelper(&pInstance->OSHelper);
9450 +       }
9451 +
9452 +
9453 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9454 +
9455 +
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
9459 --- /dev/null
9460 +++ b/drivers/sdio/stack/lib/sdio_lib_os.c
9461 @@ -0,0 +1,251 @@
9462 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9463 +@file: sdio_function_os.c
9464 +
9465 +@abstract: Linux implementation module for SDIO library
9466 +
9467 +#notes: includes module load and unload functions
9468 +
9469 +@notice: Copyright (c), 2004 Atheros Communications, Inc.
9470 +
9471 +
9472 + *
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;
9476 + *
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.
9481 + *
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:
9484 + *
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.
9490 + *   Disclaimers:
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.
9499 + *
9500 + *
9501 + *  The initial developers of the original code are Seung Yi and Paul Lever
9502 + *
9503 + *  sdio@atheros.com
9504 + *
9505 + *
9506 +
9507 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9508 +/* debug level for this module*/
9509 +#define DBG_DECLARE 4;
9510 +#include <linux/sdio/ctsystem.h>
9511 +
9512 +#include <linux/module.h>
9513 +#include <linux/init.h>
9514 +#include <linux/kthread.h>
9515 +
9516 +#include <linux/sdio/sdio_busdriver.h>
9517 +#include <linux/sdio/sdio_lib.h>
9518 +#include "_sdio_lib.h"
9519 +
9520 +#define DESCRIPTION "SDIO Kernel Library"
9521 +#define AUTHOR "Atheros Communications, Inc."
9522 +
9523 +/* proxies */
9524 +SDIO_STATUS SDLIB_IssueCMD52(PSDDEVICE     pDevice,
9525 +                            UINT8         FuncNo,
9526 +                            UINT32        Address,
9527 +                            PUINT8        pData,
9528 +                            INT           ByteCount,
9529 +                            BOOL          Write)
9530 +{
9531 +    return _SDLIB_IssueCMD52(pDevice,FuncNo,Address,pData,ByteCount,Write);
9532 +}
9533 +
9534 +SDIO_STATUS SDLIB_FindTuple(PSDDEVICE  pDevice,
9535 +                         UINT8      Tuple,
9536 +                         UINT32     *pTupleScanAddress,
9537 +                         PUINT8     pBuffer,
9538 +                         UINT8      *pLength)
9539 +{
9540 +    return _SDLIB_FindTuple(pDevice,Tuple,pTupleScanAddress,pBuffer,pLength);
9541 +}
9542 +
9543 +SDIO_STATUS SDLIB_IssueConfig(PSDDEVICE        pDevice,
9544 +                              SDCONFIG_COMMAND Command,
9545 +                              PVOID            pData,
9546 +                              INT              Length)
9547 +{
9548 +    return _SDLIB_IssueConfig(pDevice,Command,pData,Length);
9549 +}
9550 +
9551 +void SDLIB_PrintBuffer(PUCHAR pBuffer,INT Length,PTEXT pDescription)
9552 +{
9553 +    _SDLIB_PrintBuffer(pBuffer,Length,pDescription);
9554 +}
9555 +
9556 +SDIO_STATUS SDLIB_SetFunctionBlockSize(PSDDEVICE        pDevice,
9557 +                                       UINT16           BlockSize)
9558 +{
9559 +    return _SDLIB_SetFunctionBlockSize(pDevice,BlockSize);
9560 +}
9561 +
9562 +void SDLIB_SetupCMD52Request(UINT8         FuncNo,
9563 +                             UINT32        Address,
9564 +                             BOOL          Write,
9565 +                             UINT8         WriteData,
9566 +                             PSDREQUEST    pRequest)
9567 +{
9568 +    _SDLIB_SetupCMD52Request(FuncNo,Address,Write,WriteData,pRequest);
9569 +}
9570 +
9571 +SDIO_STATUS SDLIB_GetDefaultOpCurrent(PSDDEVICE  pDevice, SD_SLOT_CURRENT *pOpCurrent)
9572 +{
9573 +    return _SDLIB_GetDefaultOpCurrent(pDevice,pOpCurrent);
9574 +}
9575 +
9576 +/* helper function launcher */
9577 +INT HelperLaunch(PVOID pContext)
9578 +{
9579 +    INT exit;
9580 +        /* call function */
9581 +    exit = ((POSKERNEL_HELPER)pContext)->pHelperFunc((POSKERNEL_HELPER)pContext);
9582 +    complete_and_exit(&((POSKERNEL_HELPER)pContext)->Completion, exit);
9583 +    return exit;
9584 +}
9585 +
9586 +/*
9587 + * OSCreateHelper - create a worker kernel thread
9588 +*/
9589 +SDIO_STATUS SDLIB_OSCreateHelper(POSKERNEL_HELPER pHelper,
9590 +                           PHELPER_FUNCTION pFunction,
9591 +                           PVOID            pContext)
9592 +{
9593 +    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
9594 +
9595 +    memset(pHelper,0,sizeof(OSKERNEL_HELPER));
9596 +
9597 +    do {
9598 +        pHelper->pContext = pContext;
9599 +        pHelper->pHelperFunc = pFunction;
9600 +        status = SignalInitialize(&pHelper->WakeSignal);
9601 +        if (!SDIO_SUCCESS(status)) {
9602 +            break;
9603 +        }
9604 +        init_completion(&pHelper->Completion);
9605 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
9606 +        pHelper->pTask = kthread_create(HelperLaunch,
9607 +                                       (PVOID)pHelper,
9608 +                                       "SDIO Helper");
9609 +        if (NULL == pHelper->pTask) {
9610 +            status = SDIO_STATUS_NO_RESOURCES;
9611 +            break;
9612 +        }
9613 +        wake_up_process(pHelper->pTask);
9614 +#else
9615 +    /* 2.4 */
9616 +        pHelper->pTask = kernel_thread(HelperLaunch,
9617 +                                       (PVOID)pHelper,
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"));
9622 +        }
9623 +#endif
9624 +
9625 +    } while (FALSE);
9626 +
9627 +    if (!SDIO_SUCCESS(status)) {
9628 +        SDLIB_OSDeleteHelper(pHelper);
9629 +    }
9630 +    return status;
9631 +}
9632 +
9633 +/*
9634 + * OSDeleteHelper - delete thread created with OSCreateHelper
9635 +*/
9636 +void SDLIB_OSDeleteHelper(POSKERNEL_HELPER pHelper)
9637 +{
9638 +
9639 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
9640 +    if (pHelper->pTask != NULL) {
9641 +#else
9642 +    /* 2.4 */
9643 +    if (pHelper->pTask >= 0) {
9644 +#endif
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;
9651 +#else
9652 +    /* 2.4 */
9653 +        pHelper->pTask = 0;
9654 +#endif
9655 +    }
9656 +
9657 +    SignalDelete(&pHelper->WakeSignal);
9658 +}
9659 +
9660 +/*
9661 + * module init
9662 +*/
9663 +static int __init sdio_lib_init(void) {
9664 +    REL_PRINT(SDDBG_TRACE, ("SDIO Library load\n"));
9665 +    return 0;
9666 +}
9667 +
9668 +/*
9669 + * module cleanup
9670 +*/
9671 +static void __exit sdio_lib_cleanup(void) {
9672 +    REL_PRINT(SDDBG_TRACE, ("SDIO Library unload\n"));
9673 +}
9674 +
9675 +PSDMESSAGE_QUEUE SDLIB_CreateMessageQueue(INT MaxMessages, INT MaxMessageLength)
9676 +{
9677 +    return _CreateMessageQueue(MaxMessages,MaxMessageLength);
9678 +
9679 +}
9680 +void SDLIB_DeleteMessageQueue(PSDMESSAGE_QUEUE pQueue)
9681 +{
9682 +    _DeleteMessageQueue(pQueue);
9683 +}
9684 +
9685 +SDIO_STATUS SDLIB_PostMessage(PSDMESSAGE_QUEUE pQueue, PVOID pMessage, INT MessageLength)
9686 +{
9687 +    return _PostMessage(pQueue,pMessage,MessageLength);
9688 +}
9689 +
9690 +SDIO_STATUS SDLIB_GetMessage(PSDMESSAGE_QUEUE pQueue, PVOID pData, INT *pBufferLength)
9691 +{
9692 +    return _GetMessage(pQueue,pData,pBufferLength);
9693 +}
9694 +
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
9716 --- /dev/null
9717 +++ b/drivers/sdio/stack/platform/Makefile
9718 @@ -0,0 +1,2 @@
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
9725 --- /dev/null
9726 +++ b/drivers/sdio/stack/platform/sdioplatformdriver.c
9727 @@ -0,0 +1,300 @@
9728 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9729 +@file: sdioplatformdriver.c
9730 +
9731 +@abstract: Linux implementation module for SDIO pltaform driver
9732 +
9733 +#notes:
9734 +
9735 +@notice: Copyright (c), 2006 Atheros Communications, Inc.
9736 +
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.
9740 +
9741 +
9742 +
9743 + *
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;
9747 + *
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.
9752 + *
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:
9755 + *
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.
9761 + *   Disclaimers:
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.
9770 + *
9771 + *
9772 + *  The initial developers of the original code are Seung Yi and Paul Lever
9773 + *
9774 + *  sdio@atheros.com
9775 + *
9776 + *
9777 +
9778 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9779 +
9780 +#define DESCRIPTION "SDIO Platform Driver"
9781 +#define AUTHOR "Atheros Communications, Inc."
9782 +
9783 +//??for .h
9784 +
9785 +struct sdioplatform_peripheral {
9786 +    struct list_head    node;
9787 +    struct sdioplatform_controller *controller;
9788 +    struct device       dev;
9789 +};
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 *);
9796 +};
9797 +
9798 +
9799 +struct sdioplatform_controller {
9800 +    struct device       *dev;
9801 +};
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 *);
9808 +};
9809 +
9810 +
9811 +
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)
9814 +
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)
9817 +
9818 +#define SDIOPLATFORM_ATTR(name, fmt, args...)                    \
9819 +static ssize_t sdio_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \
9820 +{                                   \
9821 +    struct sdioplatform_peripheral *peripheral = device_to_sdioplatform_peripheral(dev);  \
9822 +    return sprintf(buf, fmt, args);                 \
9823 +}
9824 +
9825 +SDIOPLATFORM_ATTR(bus_id, "%s\n", bus_id);
9826 +#define SDIOPLATFORM_ATTR_RO(name) __ATTR(name, S_IRUGO, sdioplatform_##name##_show, NULL)
9827 +
9828 +static struct device_attribute sdioplatform_dev_attrs[] = {
9829 +    SDIOPLATFORM_ATTR_RO(bus_id),
9830 +    __ATTR_NULL
9831 +};
9832 +
9833 +static struct bus_type sdioplatform_bus_type = {
9834 +    .name       = "sdioplatform",
9835 +    .dev_attrs  = sdioplatform_dev_attrs,
9836 +    .match      = sdioplatform_bus_match,
9837 +    .hotplug    = NULL,
9838 +    .suspend    = sdioplatform_bus_suspend,
9839 +    .resume     = sdioplatform_bus_resume,
9840 +};
9841 +
9842 +
9843 +/* controller functions */
9844 +static int sdioplatform_controllerdrv_probe(struct device *dev)
9845 +{
9846 +    struct sdioplatform_controller_driver *drv = driver_to_sdioplatform_controller_driver(dev->driver);
9847 +    struct sdioplatform_controller *controller = device_to_sdioplatform_controller(dev);
9848 +
9849 +    return drv->probe(controller);
9850 +}
9851 +
9852 +static int sdioplatform_controllerdrv_remove(struct device *dev)
9853 +{
9854 +    struct sdioplatform_controller_driver *drv = driver_to_sdioplatform_controller_driver(dev->driver);
9855 +    struct sdioplatform_controller *controller = device_to_sdioplatform_controller(dev);
9856 +
9857 +    return drv->remove(controller);
9858 +}
9859 +
9860 +/*
9861 + * sdioplatform_register_controller_driver - register a controller driver
9862 + */
9863 +int sdioplatform_register_controller_driver(struct sdioplatform_controller_driver *drv)
9864 +{
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);
9869 +}
9870 +
9871 +/*
9872 + *  sdioplatform_unregister_controller_driver - unregister a controller driver
9873 + */
9874 +void sdioplatform_unregister_controller_driver(struct sdioplatform_driver *drv)
9875 +{
9876 +    driver_unregister(&drv->drv);
9877 +}
9878 +
9879 +/*
9880 + * sdioplatform_add_controller - register a controller device
9881 + */
9882 +int sdioplatform_add_controller(char *name, struct sdioplatform_controller *dev)
9883 +{
9884 +    if (!dev) {
9885 +        return -EINVAL;
9886 +    }
9887 +    strncpy(dev->dev.bus_id, BUS_ID_SIZE, name);
9888 +    return device_register(&dev->dev);
9889 +}
9890 +
9891 +/*
9892 + * sdioplatform_remove_controller - unregister a controller device
9893 + */
9894 +int sdioplatform_remove_controller(char *name, struct sdioplatform_controller *dev)
9895 +{
9896 +    if (!dev) {
9897 +        return -EINVAL;
9898 +    }
9899 +    return device_unregister(&dev->dev);
9900 +}
9901 +
9902 +/* peripheral functions */
9903 +static int sdioplatform_drv_probe(struct device *dev)
9904 +{
9905 +    struct sdioplatform_driver *drv = driver_to_sdioplatform_driver(dev->driver);
9906 +    struct sdioplatform_peripheral *peripheral = device_to_sdioplatform_peripheral(dev);
9907 +
9908 +    return drv->probe(peripheral);
9909 +}
9910 +
9911 +static int sdioplatform_controllerdrv_remove(struct device *dev)
9912 +{
9913 +    struct sdioplatform_controller_driver *drv = driver_to_sdioplatform_controller_driver(dev->driver);
9914 +    struct sdioplatform_controller *controller = device_to_sdioplatform_controller(dev);
9915 +
9916 +    return drv->remove(controller);
9917 +}
9918 +
9919 +/*
9920 + * sdioplatform_register_driver - register a driver
9921 + */
9922 +int sdioplatform_register_driver(struct sdioplatform_driver *drv)
9923 +{
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);
9928 +}
9929 +
9930 +/*
9931 + *  sdioplatform_unregister_driver - unregister a driver
9932 + */
9933 +void sdioplatform_unregister_driver(struct sdioplatform_driver *drv)
9934 +{
9935 +    driver_unregister(&drv->drv);
9936 +}
9937 +
9938 +/*
9939 + * sdioplatform_add_peripheral - register a peripheral device
9940 + */
9941 +int sdioplatform_add_peripheral(char *name, struct sdioplatform_peripheral *dev)
9942 +{
9943 +    if (!dev) {
9944 +        return -EINVAL;
9945 +    }
9946 +    strncpy(dev->dev.bus_id, BUS_ID_SIZE, name);
9947 +    return device_register(&dev->dev);
9948 +}
9949 +
9950 +/*
9951 + * sdioplatform_remove_peripheral - unregister a peripheral device
9952 + */
9953 +int sdioplatform_remove_peripheral(char *name, struct sdioplatform_peripheral *dev)
9954 +{
9955 +    if (!dev) {
9956 +        return -EINVAL;
9957 +    }
9958 +    return device_unregister(&dev->dev);
9959 +}
9960 +
9961 +
9962 +
9963 +
9964 +
9965 +static int sdioplatform_bus_match(struct device *dev, struct device_driver *drv)
9966 +{
9967 +    /* probes handle the matching */
9968 +    return 1;
9969 +}
9970 +
9971 +static int sdioplatform_bus_suspend(struct device *dev, pm_message_t state)
9972 +{
9973 +    struct sdioplatform_driver *drv = driver_to_sdioplatform_driver(dev->driver);
9974 +    struct sdioplatform_peripheral *peripheral = device_to_sdioplatform_peripheral(dev);
9975 +    int ret = 0;
9976 +
9977 +    if (peripheral->driver && drv->suspend) {
9978 +        ret = drv->suspend(peripheral, state);
9979 +    }
9980 +    return ret;
9981 +}
9982 +
9983 +static int sdioplatform_bus_resume(struct device *dev)
9984 +{
9985 +    struct sdioplatform_driver *drv = driver_to_sdioplatform_driver(dev->driver);
9986 +    struct sdioplatform_peripheral *peripheral = device_to_sdioplatform_peripheral(dev);
9987 +    int ret = 0;
9988 +
9989 +    if (peripheral->driver && drv->resume) {
9990 +        ret = drv->resume(card);
9991 +    }
9992 +    return ret;
9993 +}
9994 +
9995 +/*
9996 + * module init
9997 +*/
9998 +static int __init sdio_platformdriver_init(void) {
9999 +    int ret = bus_register(&sdioplatform_bus_type);
10000 +    return ret;
10001 +}
10002 +
10003 +/*
10004 + * module cleanup
10005 +*/
10006 +static void __exit sdio_platformdriver_cleanup(void) {
10007 +    REL_PRINT(SDDBG_TRACE, ("SDIO unloaded\n"));
10008 +    _SDIO_BusDriverCleanup();
10009 +}
10010 +
10011 +MODULE_LICENSE("GPL");
10012 +MODULE_DESCRIPTION(DESCRIPTION);
10013 +MODULE_AUTHOR(AUTHOR);
10014 +
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);
10025 +
10026 +
10027 +
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
10031 --- /dev/null
10032 +++ b/include/linux/sdio/_sdio_defs.h
10033 @@ -0,0 +1,638 @@
10034 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10035 +@file: _sdio_defs.h
10036 +
10037 +@abstract: SD/SDIO definitions
10038 +
10039 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
10040 +
10041 +
10042 + *
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;
10046 + *
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.
10051 + *
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:
10054 + *
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.
10060 + *   Disclaimers:
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.
10069 + *
10070 + *
10071 + *  The initial developers of the original code are Seung Yi and Paul Lever
10072 + *
10073 + *  sdio@atheros.com
10074 + *
10075 + *
10076 +
10077 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
10078 +#ifndef ___SDIO_DEFS_H___
10079 +#define ___SDIO_DEFS_H___
10080 +
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 */
10088 +
10089 +/* commands */
10090 +#define CMD0    0
10091 +#define CMD1    1
10092 +#define CMD2    2
10093 +#define CMD3    3
10094 +#define CMD4    4
10095 +#define CMD5    5
10096 +#define CMD6    6
10097 +#define CMD7    7
10098 +#define CMD9    9
10099 +#define CMD10   10
10100 +#define CMD12   12
10101 +#define CMD13   13
10102 +#define CMD15   15
10103 +#define CMD16   16
10104 +#define CMD17   17
10105 +#define CMD18   18
10106 +#define CMD24   24
10107 +#define CMD25   25
10108 +#define CMD27   27
10109 +#define CMD28   28
10110 +#define CMD29   29
10111 +#define CMD30   30
10112 +#define CMD32   32
10113 +#define CMD33   33
10114 +#define CMD38   38
10115 +#define CMD42   42
10116 +#define CMD52   52
10117 +#define CMD53   53
10118 +#define CMD55   55
10119 +#define CMD56   56
10120 +#define CMD58   58
10121 +#define CMD59   59
10122 +#define ACMD6   6
10123 +#define ACMD13  13
10124 +#define ACMD22  22
10125 +#define ACMD23  23
10126 +#define ACMD41  41
10127 +#define ACMD42  42
10128 +#define ACMD51  51
10129 +
10130 +#define SD_ACMD6_BUS_WIDTH_1_BIT         0x00
10131 +#define SD_ACMD6_BUS_WIDTH_4_BIT         0x02
10132 +
10133 +#define SD_CMD59_CRC_OFF            0x00000000
10134 +#define SD_CMD59_CRC_ON             0x00000001
10135 +
10136 +/* SD/SPI max response size */
10137 +#define SD_MAX_CMD_RESPONSE_BYTES SD_R2_RESPONSE_BYTES
10138 +
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) \
10148 +{                                      \
10149 +    (pR)[1] = (UINT8)(status);         \
10150 +    (pR)[2] = (UINT8)((status) >> 8);  \
10151 +    (pR)[3] = (UINT8)((status) >> 16); \
10152 +    (pR)[4] = (UINT8)((status) >> 24); \
10153 +}
10154 +
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) \
10175 +{                               \
10176 +    (status) &= ~(0x0F << 9);   \
10177 +    (status) |= (state) << 9    \
10178 +}
10179 +
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   | \
10185 +                  SD_CS_WP_ERR            | \
10186 +                  SD_CS_ECC_FAILED        | \
10187 +                  SD_CS_CARD_INTERNAL_ERR | \
10188 +                  SD_CS_GENERAL_ERR )
10189 +
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)
10202 +
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]
10215 +
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)
10225 +
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)
10248 +
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
10259 +
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))
10264 +
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
10277 +
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)
10284 +
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)
10293 +
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)
10309 +
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
10314 +
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))
10319 +
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
10331 +
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)
10346 +
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]
10355 +
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]
10365 +
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)
10375 +
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)          | \
10385 +            (1 << 26)                    | \
10386 +            (((address) & 0x1FFFF) << 9) | \
10387 +            (1 << 8)                     | \
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)
10393 +
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)
10408 +
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
10415 +
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)
10418 +
10419 +
10420 +/* SDIO COMMON Registers */
10421 +
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
10436 +/* I/O Enable  */
10437 +#define SDIO_ENABLE_REG         0x02
10438 +/* I/O Ready */
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
10447 +/* I/O Abort */
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
10469 +/* Bus suspend */
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
10483 +
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
10488 +
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
10493 +
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;
10500 +    while (i) {
10501 +        offset += 0x100;
10502 +        i--;
10503 +    }
10504 +    return offset;
10505 +}
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
10543 +
10544 +
10545 +/* these structures must be packed */
10546 +
10547 +/* Manufacturer ID tuple */
10548 +struct SDIO_MANFID_TPL {
10549 +    UINT16  ManufacturerCode;   /* jedec code */
10550 +    UINT16  ManufacturerInfo;   /* manufacturer specific code */
10551 +}CT_PACK_STRUCT;
10552 +
10553 +/* Function ID Tuple */
10554 +struct SDIO_FUNC_ID_TPL {
10555 +    UINT8  DeviceCode;  /* device code */
10556 +    UINT8  InitMask;    /* system initialization mask (not used) */
10557 +}CT_PACK_STRUCT;
10558 +
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
10567 +}CT_PACK_STRUCT;
10568 +
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 */
10588 +}CT_PACK_STRUCT;
10589 +
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;
10599 +}CT_PACK_STRUCT;
10600 +
10601 +static INLINE SDIO_STATUS ConvertCMD52ResponseToSDIOStatus(UINT8 CMD52ResponseFlags) {
10602 +    if (!(CMD52ResponseFlags & SD_R5_ERRORS)) {
10603 +        return SDIO_STATUS_SUCCESS;
10604 +    }
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;
10611 +    } else {
10612 +        return SDIO_STATUS_DATA_ERROR_UNKNOWN;
10613 +    }
10614 +}
10615 +
10616 +/* CMD6 mode switch definitions */
10617 +
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
10627 +
10628 +#define SD_SWITCH_HIGH_SPEED_GROUP     SD_SWITCH_GRP_1
10629 +#define SD_SWITCH_HIGH_SPEED_FUNC_NO   1
10630 +
10631 +#define SD_SWITCH_MAKE_SHIFT(grp) ((grp) * 4)
10632 +
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)))                 \
10636 +
10637 +#define SD_SWITCH_FUNC_ARG_GROUP_CHECK(FuncGrp,FuncNo) \
10638 +    (SD_SWITCH_FUNC_CHECK | SD_SWITCH_MAKE_GRP_PATTERN(FuncGrp,FuncNo))
10639 +
10640 +#define SD_SWITCH_FUNC_ARG_GROUP_SET(FuncGrp,FuncNo)   \
10641 +    (SD_SWITCH_FUNC_SET | SD_SWITCH_MAKE_GRP_PATTERN(FuncGrp,FuncNo))
10642 +
10643 +#define SD_SWITCH_FUNC_STATUS_BLOCK_BYTES 64
10644 +
10645 +#define SD_SWITCH_FUNC_STATUS_GET_GRP_BIT_MASK(pBuffer,FuncGrp) \
10646 +    (USHORT)((pBuffer)[50 + ((FuncGrp)*2)] | ((pBuffer)[51 + ((FuncGrp)*2)] << 8))
10647 +
10648 +#define SD_SWITCH_FUNC_STATUS_GET_MAX_CURRENT(pBuffer) \
10649 +     (USHORT)((pBuffer)[62] | ((pBuffer)[63] << 8))
10650 +
10651 +static INLINE UINT8 SDSwitchGetSwitchResult(PUINT8 pBuffer, UINT8 FuncGrp)
10652 +{
10653 +    switch (FuncGrp) {
10654 +        case 0:
10655 +            return (pBuffer[47] & 0xF);
10656 +        case 1:
10657 +            return (pBuffer[47] >> 4);
10658 +        case 2:
10659 +            return (pBuffer[48] & 0xF);
10660 +        case 3:
10661 +            return (pBuffer[48] >> 4);
10662 +        case 4:
10663 +            return (pBuffer[49] & 0xF);
10664 +        case 5:
10665 +            return (pBuffer[49] >> 4);
10666 +        default:
10667 +            return 0xF;
10668 +    }
10669 +}
10670 +
10671 +#endif
10672 diff --git a/include/linux/sdio/ctsystem.h b/include/linux/sdio/ctsystem.h
10673 new file mode 100644
10674 index 0000000..4f72739
10675 --- /dev/null
10676 +++ b/include/linux/sdio/ctsystem.h
10677 @@ -0,0 +1,115 @@
10678 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10679 +@file: cpsystem.h
10680 +
10681 +@abstract: common system include file.
10682 +
10683 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
10684 +
10685 +
10686 + *
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;
10690 + *
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.
10695 + *
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:
10698 + *
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.
10704 + *   Disclaimers:
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.
10713 + *
10714 + *
10715 + *  The initial developers of the original code are Seung Yi and Paul Lever
10716 + *
10717 + *  sdio@atheros.com
10718 + *
10719 + *
10720 +
10721 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
10722 +#ifndef __CPSYSTEM_H___
10723 +#define __CPSYSTEM_H___
10724 +
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  */
10760 +
10761 +#include <linux/sdio/ctsystem_linux.h>
10762 +
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)))
10766 +
10767 +#define ZERO_OBJECT(obj) memset(&(obj),0,sizeof(obj))
10768 +#define ZERO_POBJECT(pObj) memset((pObj),0,sizeof(*(pObj)))
10769 +
10770 +
10771 +/* bit field support functions */
10772 +static INLINE void SetBit(PULONG pField, UINT position) {
10773 +    *pField |= 1 << position;
10774 +}
10775 +static INLINE void ClearBit(PULONG pField, UINT position) {
10776 +    *pField &= ~(1 << position);
10777 +}
10778 +static INLINE BOOL IsBitSet(PULONG pField, UINT position) {
10779 +    return (*pField & (1 << position));
10780 +}
10781 +static INLINE INT FirstClearBit(PULONG pField) {
10782 +    UINT ii;
10783 +    for(ii = 0; ii < sizeof(ULONG)*8; ii++) {
10784 +        if (!IsBitSet(pField, ii)) {
10785 +            return ii;
10786 +        }
10787 +    }
10788 +    /* no clear bits found */
10789 +    return -1;
10790 +}
10791 +
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
10796 --- /dev/null
10797 +++ b/include/linux/sdio/ctsystem_linux.h
10798 @@ -0,0 +1,983 @@
10799 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10800 +@file: ctsystem_linux.h
10801 +
10802 +@abstract: common system include file for Linux.
10803 +
10804 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
10805 +
10806 +
10807 + *
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;
10811 + *
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.
10816 + *
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:
10819 + *
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.
10825 + *   Disclaimers:
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.
10834 + *
10835 + *
10836 + *  The initial developers of the original code are Seung Yi and Paul Lever
10837 + *
10838 + *  sdio@atheros.com
10839 + *
10840 + *
10841 +
10842 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
10843 +#ifndef __CPSYSTEM_LINUX_H___
10844 +#define __CPSYSTEM_LINUX_H___
10845 +
10846 +/* #define DBG_TIMESTAMP 1 */
10847 +#define SD_TRACK_REQ 1
10848 +
10849 +/* LINUX support */
10850 +#include <linux/version.h>
10851 +
10852 +#ifndef KERNEL_VERSION
10853 +  #error KERNEL_VERSION macro not defined!
10854 +#endif
10855 +
10856 +#ifndef  LINUX_VERSION_CODE
10857 +  #error LINUX_VERSION_CODE macro not defined!
10858 +#endif
10859 +
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>
10866 +
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 */
10876 +#ifndef in_atomic
10877 +    /* released version of 2.6.9 */
10878 +#include <linux/hardirq.h>
10879 +#endif
10880 +#include <linux/delay.h>
10881 +#include <linux/device.h>
10882 +
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;
10892 +typedef    int              INT;
10893 +typedef    int*             PINT;
10894 +typedef    unsigned long    ULONG;
10895 +typedef    unsigned long*   PULONG;
10896 +typedef    u8               UINT8;
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;
10932 +#else
10933 +/* 2.4 */
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")
10945 +#endif
10946 +
10947 +typedef    int              CT_DEBUG_LEVEL;
10948 +
10949 +
10950 +#ifndef TRUE
10951 +#define TRUE 1
10952 +#endif
10953 +#ifndef FALSE
10954 +#define FALSE 0
10955 +#endif
10956 +#ifndef NULL
10957 +#define NULL ((PVOID)0)
10958 +#endif
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;
10970 +
10971 +#define INLINE  inline
10972 +#define CT_PACK_STRUCT __attribute__ ((packed))
10973 +
10974 +#define CT_DECLARE_MODULE_PARAM_INTEGER(p)  module_param(p, int, 0644);
10975 +
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
10983 +
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
10990 +
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
10997 +
10998 +#define DBG_GET_LEVEL(lvl) ((lvl) & 0xff)
10999 +#define DBG_GET_MASK(lvl) (((lvl) & 0xff00))
11000 +
11001 +#define DBG_SDIO_MASK (DBG_MASK_NONE | DBG_LEVEL_DEBUG)
11002 +
11003 +#define DEBUG 1
11004 +
11005 +#ifdef DEBUG
11006 +
11007 +#define DBG_ASSERT(test) \
11008 +{                         \
11009 +    if (!(test)) {          \
11010 +        DBG_PRINT(SDDBG_ERROR, ("Debug Assert Caught, File %s, Line: %d, Test:%s \n",__FILE__, __LINE__,#test)); \
11011 +    }                     \
11012 +}
11013 +#define DBG_ASSERT_WITH_MSG(test,s) \
11014 +{                                   \
11015 +    if (!(test)) {                  \
11016 +        DBG_PRINT(SDDBG_ERROR, ("Assert:%s File %s, Line: %d \n",(s),__FILE__, __LINE__)); \
11017 +    }                     \
11018 +}
11019 +
11020 +#define DBG_PRINT(lvl, args)\
11021 +    do {\
11022 +            if (DBG_GET_LEVEL(lvl) <= (DBG_SDIO_MASK & 0xff)) \
11023 +                printk(_DBG_PRINTX_ARG args); \
11024 +    } while(0);
11025 +
11026 +#else /* DEBUG */
11027 +
11028 +#define DBG_PRINT(lvl, str)
11029 +#define DBG_ASSERT(test)
11030 +#define DBG_ASSERT_WITH_MSG(test,s)
11031 +#endif /* DEBUG */
11032 +
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
11038 +
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
11043 +
11044 +  @output: none
11045 +
11046 +  @return:
11047 +
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
11051 +
11052 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11053 +#define REL_PRINT(lvl, args)\
11054 +    {if (lvl <= DBG_GET_DEBUG_LEVEL())\
11055 +        printk(SDDBG_KERNEL_PRINT_LEVEL _DBG_PRINTX_ARG args);\
11056 +    }
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
11062 +
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) \
11067 +{                                     \
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); \
11074 +  }                                   \
11075 +}
11076 +
11077 +#define call_spin_lock_irqsave(pCrit,isc) \
11078 +{                                     \
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); \
11085 +  }                                   \
11086 +}
11087 +
11088 +#else
11089 +#define call_spin_lock(s) spin_lock_bh(s)
11090 +#define call_spin_lock_irqsave(s,isc) spin_lock_irqsave(s,isc)
11091 +#endif
11092 +
11093 +#define call_spin_unlock(s) spin_unlock_bh((s))
11094 +#define call_spin_unlock_irqrestore(s,isc) spin_unlock_irqrestore(s,isc)
11095 +
11096 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
11097 +#define NonSchedulable() (in_atomic() || irqs_disabled())
11098 +#else
11099 +#define NonSchedulable() (irqs_disabled())
11100 +#endif
11101 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11102 +  @function: Initialize a critical section object.
11103 +
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
11108 +
11109 +  @return: SDIO_STATUS_SUCCESS on success.
11110 +
11111 +  @notes:  CriticalSectionDelete() must be called to cleanup any resources
11112 +           associated with the critical section.
11113 +
11114 +  @see also: CriticalSectionDelete, CriticalSectionAcquire, CriticalSectionRelease
11115 +  @example: To initialize a critical section:
11116 +        status = CriticalSectionInit(&pDevice->ListLock);
11117 +        if (!SDIO_SUCCESS(status)) {
11118 +                .. failed
11119 +            return status;
11120 +        }
11121 +
11122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11123 +static inline SDIO_STATUS CriticalSectionInit(POS_CRITICALSECTION pCrit) {
11124 +    spin_lock_init(pCrit);
11125 +    return SDIO_STATUS_SUCCESS;
11126 +}
11127 +
11128 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11129 +  @function: Acquire a critical section lock.
11130 +
11131 +  @function name: CriticalSectionAcquire
11132 +  @prototype: SDIO_STATUS CriticalSectionAcquire(POS_CRITICALSECTION pCrit)
11133 +  @category: Support_Reference
11134 +
11135 +  @input: pCrit - pointer to critical section that was initialized
11136 +
11137 +  @return: SDIO_STATUS_SUCCESS on success.
11138 +
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.
11142 +
11143 +  @see also: CriticalSectionRelease
11144 +
11145 +  @example: To acquire a critical section lock:
11146 +        status = CriticalSectionAcquire(&pDevice->ListLock);
11147 +        if (!SDIO_SUCCESS(status)) {
11148 +                .. failed
11149 +            return status;
11150 +        }
11151 +        ... access protected data
11152 +            // unlock
11153 +        status = CriticalSectionRelease(&pDevice->ListLock);
11154 +        if (!SDIO_SUCCESS(status)) {
11155 +                .. failed
11156 +            return status;
11157 +        }
11158 +
11159 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11160 +static inline SDIO_STATUS CriticalSectionAcquire(POS_CRITICALSECTION pCrit) {
11161 +    call_spin_lock(pCrit);
11162 +    return SDIO_STATUS_SUCCESS;
11163 +}
11164 +
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)
11170 +
11171 +#define CT_DECLARE_IRQ_SYNC_CONTEXT() unsigned long _ctSyncFlags
11172 +
11173 +#define CriticalSectionAcquireSyncIrq(pCrit) \
11174 +    SDIO_STATUS_SUCCESS; call_spin_lock_irqsave(pCrit,_ctSyncFlags)
11175 +
11176 +#define CriticalSectionReleaseSyncIrq(pCrit) \
11177 +    SDIO_STATUS_SUCCESS; call_spin_unlock_irqrestore(pCrit,_ctSyncFlags)
11178 +
11179 +
11180 +
11181 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11182 +  @function: Release a critical section lock.
11183 +
11184 +  @function name: CriticalSectionRelease
11185 +  @prototype: SDIO_STATUS CriticalSectionRelease(POS_CRITICALSECTION pCrit)
11186 +  @category: Support_Reference
11187 +
11188 +  @input: pCrit - pointer to critical section that was initialized
11189 +
11190 +  @return: SDIO_STATUS_SUCCESS on success.
11191 +
11192 +  @notes:  The critical section lock is released when this function returns
11193 +           SDIO_STATUS_SUCCESS.
11194 +
11195 +  @see also: CriticalSectionAcquire
11196 +
11197 +  @example: see CriticalSectionAcquire
11198 +
11199 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11200 +static inline SDIO_STATUS CriticalSectionRelease(POS_CRITICALSECTION pCrit) {
11201 +    call_spin_unlock(pCrit);
11202 +    return SDIO_STATUS_SUCCESS;
11203 +}
11204 +
11205 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11206 +  @function: Cleanup a critical section object
11207 +
11208 +  @function name: CriticalSectionDelete
11209 +  @prototype: void CriticalSectionDelete(POS_CRITICALSECTION pCrit)
11210 +  @category: Support_Reference
11211 +
11212 +  @input: pCrit - an initialized critical section object
11213 +
11214 +  @return: SDIO_STATUS_SUCCESS on success.
11215 +
11216 +  @notes:
11217 +
11218 +  @see also: CriticalSectionInit, CriticalSectionAcquire, CriticalSectionRelease
11219 +
11220 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11221 +static inline void CriticalSectionDelete(POS_CRITICALSECTION pCrit) {
11222 +    return;
11223 +}
11224 +
11225 +/* internal use */
11226 +static inline SDIO_STATUS SignalInitialize(POS_SIGNAL pSignal) {
11227 +    sema_init(pSignal, 0);
11228 +    return SDIO_STATUS_SUCCESS;
11229 +}
11230 +/* internal use */
11231 +static inline void SignalDelete(POS_SIGNAL pSignal) {
11232 +    return;
11233 +}
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;
11239 +    } else {
11240 +        return SDIO_STATUS_INTERRUPTED;
11241 +    }
11242 +}
11243 +/* internal use */
11244 +static inline SDIO_STATUS SignalWait(POS_SIGNAL pSignal) {
11245 +    DBG_ASSERT_WITH_MSG(!NonSchedulable(),"SignalWait not allowed\n");
11246 +    down(pSignal);
11247 +    return SDIO_STATUS_SUCCESS;
11248 +}
11249 +
11250 +/* internal use */
11251 +static inline SDIO_STATUS SignalSet(POS_SIGNAL pSignal) {
11252 +    up(pSignal);
11253 +    return SDIO_STATUS_SUCCESS;
11254 +}
11255 +
11256 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11257 +  @function: Initialize a semaphore object.
11258 +
11259 +  @function name: SemaphoreInitialize
11260 +  @prototype: SDIO_STATUS SemaphoreInitialize(POS_SEMAPHORE pSem, UINT value)
11261 +  @category: Support_Reference
11262 +
11263 +  @input:  value - initial value of the semaphore
11264 +
11265 +  @output: pSem - pointer to a semaphore object to initialize
11266 +
11267 +  @return: SDIO_STATUS_SUCCESS on success.
11268 +
11269 +  @notes:  SemaphoreDelete() must be called to cleanup any resources
11270 +           associated with the semaphore
11271 +
11272 +  @see also: SemaphoreDelete, SemaphorePend, SemaphorePendInterruptable
11273 +
11274 +  @example: To initialize a semaphore:
11275 +        status = SemaphoreInitialize(&pDevice->ResourceSem,1);
11276 +        if (!SDIO_SUCCESS(status)) {
11277 +                .. failed
11278 +            return status;
11279 +        }
11280 +
11281 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11282 +static inline SDIO_STATUS SemaphoreInitialize(POS_SEMAPHORE pSem, UINT value) {
11283 +    sema_init(pSem, value);
11284 +    return SDIO_STATUS_SUCCESS;
11285 +}
11286 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11287 +  @function: Cleanup a semaphore object.
11288 +
11289 +  @function name: SemaphoreDelete
11290 +  @prototype: void SemaphoreDelete(POS_SEMAPHORE pSem)
11291 +  @category: Support_Reference
11292 +
11293 +  @input: pSem - pointer to a semaphore object to cleanup
11294 +
11295 +  @return:
11296 +
11297 +  @notes:
11298 +
11299 +  @see also: SemaphoreInitialize
11300 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11301 +static inline void SemaphoreDelete(POS_SEMAPHORE pSem) {
11302 +    return;
11303 +}
11304 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11305 +  @function: Acquire the semaphore or pend if the resource is not available
11306 +
11307 +  @function name: SemaphorePend
11308 +  @prototype: SDIO_STATUS SemaphorePend(POS_SEMAPHORE pSem)
11309 +  @category: Support_Reference
11310 +
11311 +  @input: pSem - pointer to an initialized semaphore object
11312 +
11313 +  @return: SDIO_STATUS_SUCCESS on success.
11314 +
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.
11320 +
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)) {
11325 +                .. failed
11326 +            return status;
11327 +        }
11328 +        ... resource acquired
11329 +        SemaphorePost(&pDevice->ResourceSem);
11330 +
11331 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11332 +static inline SDIO_STATUS SemaphorePend(POS_SEMAPHORE pSem) {
11333 +    DBG_ASSERT_WITH_MSG(!NonSchedulable(),"SemaphorePend not allowed\n");
11334 +    down(pSem);
11335 +    return SDIO_STATUS_SUCCESS;
11336 +}
11337 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11338 +  @function: Acquire the semaphore or pend if the resource is not available
11339 +
11340 +  @function name: SemaphorePendInterruptable
11341 +  @prototype: SDIO_STATUS SemaphorePendInterruptable(POS_SEMAPHORE pSem)
11342 +  @category: Support_Reference
11343 +
11344 +  @input: pSem - pointer to an initialized semaphore object
11345 +
11346 +  @return: SDIO_STATUS_SUCCESS on success.
11347 +
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.
11352 +
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
11358 +            return status;
11359 +        }
11360 +        ... resource acquired
11361 +        SemaphorePost(&pDevice->ResourceSem);
11362 +
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;
11368 +    } else {
11369 +        return SDIO_STATUS_INTERRUPTED;
11370 +    }
11371 +}
11372 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11373 +  @function: Post a semaphore.
11374 +
11375 +  @function name: SemaphorePost
11376 +  @prototype: SDIO_STATUS SemaphorePost(POS_SEMAPHORE pSem)
11377 +  @category: Support_Reference
11378 +
11379 +  @input: pSem - pointer to an initialized semaphore object
11380 +
11381 +  @return: SDIO_STATUS_SUCCESS on success.
11382 +
11383 +  @notes: This function increments the semaphore count.
11384 +
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
11390 +            return status;
11391 +        }
11392 +        ... resource acquired
11393 +            // post the semaphore
11394 +        SemaphorePost(&pDevice->ResourceSem);
11395 +
11396 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11397 +static inline SDIO_STATUS SemaphorePost(POS_SEMAPHORE pSem) {
11398 +    DBG_ASSERT_WITH_MSG(!NonSchedulable(),"SemaphorePost not allowed\n");
11399 +    up(pSem);
11400 +    return SDIO_STATUS_SUCCESS;
11401 +}
11402 +
11403 +
11404 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11405 +  @function: Allocate a block of kernel accessible memory
11406 +
11407 +  @function name: KernelAlloc
11408 +  @prototype: PVOID KernelAlloc(UINT size)
11409 +  @category: Support_Reference
11410 +
11411 +  @input: size - size of memory block to allocate
11412 +
11413 +  @return: pointer to the allocated memory, NULL if allocation failed
11414 +
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.
11420 +
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;
11427 +        }
11428 +
11429 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11430 +static inline PVOID KernelAlloc(UINT size) {
11431 +    PVOID pMem = kmalloc(size, GFP_KERNEL);
11432 +    if (pMem != NULL) { memset(pMem,0,size); }
11433 +    return pMem;
11434 +}
11435 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11436 +  @function: Free a block of kernel accessible memory.
11437 +
11438 +  @function name: KernelFree
11439 +  @prototype: void KernelFree(PVOID ptr)
11440 +  @category: Support_Reference
11441 +
11442 +  @input: ptr - pointer to memory allocated with KernelAlloc()
11443 +
11444 +  @return:
11445 +
11446 +  @notes: Caller should only use KernelFree() to release memory that was allocated
11447 +          with KernelAlloc().
11448 +
11449 +  @see also: KernelAlloc
11450 +  @example: KernelFree(pBlock);
11451 +
11452 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11453 +static inline void KernelFree(PVOID ptr) {
11454 +    kfree(ptr);
11455 +}
11456 +
11457 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11458 +  @function: Allocate a block of kernel accessible memory in an IRQ-safe manner
11459 +
11460 +  @function name: KernelAllocIrqSafe
11461 +  @prototype: PVOID KernelAllocIrqSafe(UINT size)
11462 +  @category: Support_Reference
11463 +
11464 +  @input: size - size of memory block to allocate
11465 +
11466 +  @return: pointer to the allocated memory, NULL if allocation failed
11467 +
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.
11473 +
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;
11480 +        }
11481 +
11482 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11483 +static inline PVOID KernelAllocIrqSafe(UINT size) {
11484 +    return kmalloc(size, GFP_ATOMIC);
11485 +}
11486 +
11487 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11488 +  @function: Free a block of kernel accessible memory.
11489 +
11490 +  @function name: KernelFreeIrqSafe
11491 +  @prototype: void KernelFreeIrqSafe(PVOID ptr)
11492 +  @category: Support_Reference
11493 +
11494 +  @input: ptr - pointer to memory allocated with KernelAllocIrqSafe()
11495 +
11496 +  @return:
11497 +
11498 +  @notes: Caller should only use KernelFreeIrqSafe() to release memory that was allocated
11499 +          with KernelAllocIrqSafe().
11500 +
11501 +  @see also: KernelAllocIrqSafe
11502 +  @example: KernelFreeIrqSafe(pBlock);
11503 +
11504 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11505 +static inline void KernelFreeIrqSafe(PVOID ptr) {
11506 +    kfree(ptr);
11507 +}
11508 +
11509 +/* error status conversions */
11510 +static inline SYSTEM_STATUS SDIOErrorToOSError(SDIO_STATUS status) {
11511 +    switch (status) {
11512 +        case SDIO_STATUS_SUCCESS:
11513 +            return 0;
11514 +        case SDIO_STATUS_INVALID_PARAMETER:
11515 +            return -EINVAL;
11516 +        case SDIO_STATUS_PENDING:
11517 +            return -EAGAIN; /* try again */
11518 +        case SDIO_STATUS_DEVICE_NOT_FOUND:
11519 +            return -ENXIO;
11520 +        case SDIO_STATUS_DEVICE_ERROR:
11521 +            return -EIO;
11522 +        case SDIO_STATUS_INTERRUPTED:
11523 +            return -EINTR;
11524 +        case SDIO_STATUS_NO_RESOURCES:
11525 +            return -ENOMEM;
11526 +        case SDIO_STATUS_ERROR:
11527 +        default:
11528 +            return -EFAULT;
11529 +    }
11530 +}
11531 +static inline SDIO_STATUS OSErrorToSDIOError(SYSTEM_STATUS status) {
11532 +    if (status >=0) {
11533 +        return SDIO_STATUS_SUCCESS;
11534 +    }
11535 +    switch (status) {
11536 +        case -EINVAL:
11537 +            return SDIO_STATUS_INVALID_PARAMETER;
11538 +        case -ENXIO:
11539 +            return SDIO_STATUS_DEVICE_NOT_FOUND;
11540 +        case -EIO:
11541 +            return SDIO_STATUS_DEVICE_ERROR;
11542 +        case -EINTR:
11543 +            return SDIO_STATUS_INTERRUPTED;
11544 +        case -ENOMEM:
11545 +            return SDIO_STATUS_NO_RESOURCES;
11546 +        case -EFAULT:
11547 +            return SDIO_STATUS_ERROR;
11548 +        default:
11549 +            return SDIO_STATUS_ERROR;
11550 +    }
11551 +}
11552 +
11553 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11554 +  @function: Sleep or delay the execution context for a number of milliseconds.
11555 +
11556 +  @function name: OSSleep
11557 +  @prototype: SDIO_STATUS OSSleep(INT SleepInterval)
11558 +  @category: Support_Reference
11559 +
11560 +  @input: SleepInterval - time in milliseconds to put the execution context to sleep
11561 +
11562 +  @return: SDIO_STATUS_SUCCESS if sleep succeeded.
11563 +
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.
11566 +
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)){
11573 +            // failed..
11574 +        }
11575 +
11576 +
11577 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11578 +static inline SDIO_STATUS OSSleep(INT SleepInterval) {
11579 +    UINT32 delta;
11580 +
11581 +    DBG_ASSERT_WITH_MSG(!NonSchedulable(),"OSSleep not allowed\n");
11582 +        /* convert timeout to ticks */
11583 +    delta = (SleepInterval * HZ)/1000;
11584 +    if (delta == 0) {
11585 +        delta = 1;
11586 +    }
11587 +    set_current_state(TASK_INTERRUPTIBLE);
11588 +    if (schedule_timeout(delta) != 0) {
11589 +        return SDIO_STATUS_INTERRUPTED;
11590 +    }
11591 +    return SDIO_STATUS_SUCCESS;
11592 +}
11593 +
11594 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11595 +  @function: get the OSs device object
11596 +
11597 +  @function name: SD_GET_OS_DEVICE
11598 +  @prototype: POS_DEVICE SD_GET_OS_DEVICE(PSDDEVICE pDevice)
11599 +  @category: Support_Reference
11600 +
11601 +  @input: pDevice - the device on the HCD
11602 +
11603 +  @return: pointer to the OSs device
11604 +
11605 +  @see also:
11606 +  @example: obtain low level device
11607 +        pFunctionContext->GpsDevice.Port.dev = SD_GET_OS_DEVICE(pDevice);
11608 +
11609 +
11610 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11611 +#define SD_GET_OS_DEVICE(pDevice) &((pDevice)->Device.dev)
11612 +
11613 +
11614 +#ifdef __iomem
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))
11629 +#else
11630 +    /* I/O Access macros */
11631 +#define _READ_DWORD_REG(reg)  \
11632 +        readl((reg))
11633 +#define _READ_WORD_REG(reg)  \
11634 +        readw((reg))
11635 +#define _READ_BYTE_REG(reg)  \
11636 +        readb((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))
11643 +#endif
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);
11647 +}
11648 +static inline ATOMIC_FLAGS AtomicTest_Clear(volatile ATOMIC_FLAGS *pValue, INT BitNo) {
11649 +    return test_and_clear_bit(BitNo,(ATOMIC_FLAGS *)pValue);
11650 +}
11651 +
11652 +struct _OSKERNEL_HELPER;
11653 +
11654 +typedef THREAD_RETURN (*PHELPER_FUNCTION)(struct _OSKERNEL_HELPER *);
11655 +
11656 +typedef struct _OSKERNEL_HELPER {
11657 +    PKERNEL_TASK            pTask;
11658 +    BOOL                    ShutDown;
11659 +    OS_SIGNAL               WakeSignal;
11660 +    struct completion       Completion;
11661 +    PVOID                   pContext;
11662 +    PHELPER_FUNCTION        pHelperFunc;
11663 +}OSKERNEL_HELPER, *POSKERNEL_HELPER;
11664 +
11665 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11666 +  @function: Wake the helper thread
11667 +
11668 +  @function name: SD_WAKE_OS_HELPER
11669 +  @prototype: SD_WAKE_OS_HELPER(POSKERNEL_HELPER pOSHelper)
11670 +  @category: Support_Reference
11671 +
11672 +  @input: pOSHelper - the OS helper object
11673 +
11674 +  @return: SDIO_STATUS
11675 +
11676 +  @see also: SDLIB_OSCreateHelper
11677 +
11678 +  @example: Waking up a helper thread
11679 +        status = SD_WAKE_OS_HELPER(&pInstance->OSHelper);
11680 +
11681 +
11682 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11683 +#define SD_WAKE_OS_HELPER(p)        SignalSet(&(p)->WakeSignal)
11684 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11685 +  @function: Obtains the context for the helper function
11686 +
11687 +  @function name: SD_GET_OS_HELPER_CONTEXT
11688 +  @prototype: SD_GET_OS_HELPER_CONTEXT(POSKERNEL_HELPER pOSHelper)
11689 +  @category: Support_Reference
11690 +
11691 +  @input: pOSHelper - the OS helper object
11692 +
11693 +  @return: helper specific context
11694 +
11695 +  @notes: This macro should only be called by the function associated with
11696 +          the helper object.
11697 +
11698 +  @see also: SDLIB_OSCreateHelper
11699 +
11700 +  @example: Getting the helper specific context
11701 +        PMYCONTEXT pContext = (PMYCONTEXT)SD_GET_OS_HELPER_CONTEXT(pHelper);
11702 +
11703 +
11704 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11705 +#define SD_GET_OS_HELPER_CONTEXT(p)     (p)->pContext
11706 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11707 +  @function: Check helper function shut down flag.
11708 +
11709 +  @function name: SD_IS_HELPER_SHUTTING_DOWN
11710 +  @prototype: SD_IS_HELPER_SHUTTING_DOWN(POSKERNEL_HELPER pOSHelper)
11711 +  @category: Support_Reference
11712 +
11713 +  @input: pOSHelper - the OS helper object
11714 +
11715 +  @return: TRUE if shutting down, else FALSE
11716 +
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.
11721 +
11722 +  @see also: SDLIB_OSCreateHelper , SD_WAIT_FOR_WAKEUP
11723 +
11724 +  @example: Checking for shutdown
11725 +        while(1) {
11726 +              status = SD_WAIT_FOR_WAKEUP(pHelper);
11727 +              if (!SDIO_SUCCESS(status)) {
11728 +                  break;
11729 +              }
11730 +              if (SD_IS_HELPER_SHUTTING_DOWN(pHelper)) {
11731 +                  ... shutting down
11732 +                  break;
11733 +              }
11734 +        }
11735 +
11736 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11737 +#define SD_IS_HELPER_SHUTTING_DOWN(p)   (p)->ShutDown
11738 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11739 +  @function: Suspend and wait for wakeup signal
11740 +
11741 +  @function name: SD_WAIT_FOR_WAKEUP
11742 +  @prototype: SD_WAIT_FOR_WAKEUP(POSKERNEL_HELPER pOSHelper)
11743 +  @category: Support_Reference
11744 +
11745 +  @input: pOSHelper - the OS helper object
11746 +
11747 +  @return: SDIO_STATUS
11748 +
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.
11753 +
11754 +  @see also: SDLIB_OSCreateHelper , SD_IS_HELPER_SHUTTING_DOWN
11755 +
11756 +  @example: block on the wake signal
11757 +        while(1) {
11758 +              status = SD_WAIT_FOR_WAKEUP(pHelper);
11759 +              if (!SDIO_SUCCESS(status)) {
11760 +                  break;
11761 +              }
11762 +              if (SD_IS_HELPER_SHUTTING_DOWN(pHelper)) {
11763 +                  ... shutting down
11764 +                  break;
11765 +              }
11766 +        }
11767 +
11768 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11769 +#define SD_WAIT_FOR_WAKEUP(p)   SignalWait(&(p)->WakeSignal);
11770 +
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)
11775 +
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___ */
11781 +
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
11785 --- /dev/null
11786 +++ b/include/linux/sdio/mmc_defs.h
11787 @@ -0,0 +1,103 @@
11788 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11789 +@file: mmc_defs.h
11790 +
11791 +@abstract: MMC definitions not already defined in _sdio_defs.h
11792 +
11793 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
11794 +
11795 +
11796 + *
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;
11800 + *
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.
11805 + *
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:
11808 + *
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.
11814 + *   Disclaimers:
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.
11823 + *
11824 + *
11825 + *  The initial developers of the original code are Seung Yi and Paul Lever
11826 + *
11827 + *  sdio@atheros.com
11828 + *
11829 + *
11830 +
11831 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11832 +#ifndef ___MMC_DEFS_H___
11833 +#define ___MMC_DEFS_H___
11834 +
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 */
11837 +
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
11846 +
11847 +#define MMC_CMD_SWITCH    6
11848 +#define MMC_CMD8    8
11849 +
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))
11857 +
11858 +#define MMC_EXT_CSD_SIZE                     512
11859 +
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
11889 +
11890 +#endif
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
11894 --- /dev/null
11895 +++ b/include/linux/sdio/sdio_busdriver.h
11896 @@ -0,0 +1,1435 @@
11897 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11898 +@file: sdio_busdriver.h
11899 +
11900 +@abstract: include file for registration of SDIO function drivers
11901 +  and SDIO host controller bus drivers.
11902 +
11903 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
11904 +
11905 +
11906 + *
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;
11910 + *
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.
11915 + *
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:
11918 + *
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.
11924 + *   Disclaimers:
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.
11933 + *
11934 + *
11935 + *  The initial developers of the original code are Seung Yi and Paul Lever
11936 + *
11937 + *  sdio@atheros.com
11938 + *
11939 + *
11940 +
11941 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11942 +#ifndef __SDIO_BUSDRIVER_H___
11943 +#define __SDIO_BUSDRIVER_H___
11944 +
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"
11954 +
11955 +/* card flags */
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)
11967 +
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) \
11978 +{                       \
11979 +    (flags) &= ~SDCONFIG_BUS_WIDTH_MASK; \
11980 +    (flags) |= (width);                  \
11981 +}
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 */
11986 +
11987 +typedef UINT16 SD_SLOT_CURRENT;      /* slot current in mA */
11988 +
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
11996 +
11997 +#define MAX_CARD_RESPONSE_BYTES 17
11998 +
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;
12009 +
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))
12017 +
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;
12046 +
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
12072 +
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
12078 +
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
12091 +
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
12097 +
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
12115 +
12116 +struct _SDREQUEST;
12117 +struct _SDFUNCTION;
12118 +
12119 +typedef void (*PSDEQUEST_COMPLETION)(struct _SDREQUEST *);
12120 +
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 */
12141 +    PVOID   pBdRsv2;
12142 +    PVOID   pBdRsv3;
12143 +}SDREQUEST, *PSDREQUEST;
12144 +
12145 +    /* a request queue */
12146 +typedef struct _SDREQUESTQUEUE {
12147 +    SDLIST        Queue;           /* the queue of requests */
12148 +    BOOL          Busy;            /* busy flag */
12149 +}SDREQUESTQUEUE, *PSDREQUESTQUEUE;
12150 +
12151 +
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
12160 +/* both */
12161 +#define SDCONFIG_FLAGS_DATA_BOTH      (SDCONFIG_FLAGS_DATA_GET | SDCONFIG_FLAGS_DATA_PUT)
12162 +/* no data */
12163 +#define SDCONFIG_FLAGS_DATA_NONE      0x0000
12164 +
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)
12168 +
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)
12172 +
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)
12185 +
12186 +typedef UINT8  FUNC_ENABLE_DISABLE_FLAGS;
12187 +typedef UINT32 FUNC_ENABLE_TIMEOUT;
12188 +
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;
12198 +
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;
12203 +
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;
12210 +
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;
12217 +
12218 +#define SET_SDCONFIG_CMD_INFO(pHdr,cmd,pC,len) \
12219 +{           \
12220 +  (pHdr)->Cmd = (cmd);                     \
12221 +  (pHdr)->pData = (PVOID)(pC);             \
12222 +  (pHdr)->DataLength = (len);              \
12223 +}
12224 +
12225 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12226 +  @function: Get a pointer to the configuration command data.
12227 +
12228 +  @function name: GET_SDCONFIG_CMD
12229 +  @prototype: UNIT16 GET_SDCONFIG_CMD (PSDCONFIG pCommand)
12230 +  @category: HD_Reference
12231 +
12232 +  @input:  pCommand - config command structure.
12233 +
12234 +  @return: command code
12235 +
12236 +  @notes: Implemented as a macro. This macro returns the command code for this
12237 +          configuration request.
12238 +
12239 +  @example: getting the command code:
12240 +    cmd = GET_SDCONFIG_CMD(pConfig);
12241 +    switch (cmd) {
12242 +        case SDCONFIG_GET_WP:
12243 +             .. get write protect switch position
12244 +           break;
12245 +        ...
12246 +    }
12247 +
12248 +  @see also: GET_SDCONFIG_CMD_LEN, GET_SDCONFIG_CMD_DATA
12249 +
12250 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12251 +#define GET_SDCONFIG_CMD(pBuffer)     ((pBuffer)->Cmd)
12252 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12253 +  @function: Get a pointer to the configuration command data.
12254 +
12255 +  @function name: GET_SDCONFIG_CMD_LEN
12256 +  @prototype: INT GET_SDCONFIG_CMD_LEN (PSDCONFIG pCommand)
12257 +  @category: HD_Reference
12258 +
12259 +  @input:  pCommand - config command structure.
12260 +
12261 +  @return: length of config command data
12262 +
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.
12266 +
12267 +  @example: getting the data length:
12268 +    length = GET_SDCONFIG_CMD_LEN(pConfig);
12269 +    if (length < CUSTOM_COMMAND_XXX_SIZE) {
12270 +       ... invalid length
12271 +    }
12272 +
12273 +  @see also: GET_SDCONFIG_CMD, GET_SDCONFIG_CMD_DATA
12274 +
12275 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12276 +#define GET_SDCONFIG_CMD_LEN(pBuffer) ((pBuffer)->DataLength)
12277 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12278 +  @function: Get a pointer to the configuration command data.
12279 +
12280 +  @function name: GET_SDCONFIG_CMD_DATA
12281 +  @prototype: (casted ptr) GET_SDCONFIG_CMD_DATA (type, PSDCONFIG pCommand)
12282 +  @category: HD_Reference
12283 +
12284 +  @input:  type - pointer type to cast the returned pointer to.
12285 +           pCommand - config command structure.
12286 +
12287 +  @return: type-casted pointer to the command's data
12288 +
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.
12291 +
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
12297 +    }
12298 +
12299 +  @see also: GET_SDCONFIG_CMD, GET_SDCONFIG_CMD_LEN
12300 +
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)
12305 +
12306 +struct _SDDEVICE;
12307 +struct _SDHCD;
12308 +
12309 +typedef UINT8   SD_FUNCTION_FLAGS;
12310 +#define SDFUNCTION_FLAG_REMOVING       0x01
12311 +
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;
12333 +
12334 +typedef UINT8  HCD_EVENT;
12335 +
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;
12342 +
12343 +    /* device info for SD/MMC card functions */
12344 +typedef struct _SDMMC_INFO{
12345 +    UINT8  Unused;    /* reserved */
12346 +}SDMMC_INFO, *PSDMMC_INFO;
12347 +
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;
12353 +
12354 +
12355 +typedef UINT8   SD_DEVICE_FLAGS;
12356 +#define SDDEVICE_FLAG_REMOVING       0x01
12357 +
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;
12381 +
12382 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12383 +  @function: Get SDIO Bus Driver Version Major number
12384 +
12385 +  @function name: SDDEVICE_GET_VERSION_MAJOR
12386 +  @prototype: INT SDDEVICE_GET_VERSION_MAJOR(PSDDEVICE pDevice)
12387 +  @category: PD_Reference
12388 +
12389 +  @input:  pDevice   - the target device for this request
12390 +
12391 +  @output: none
12392 +
12393 +  @return: integer value for the major version
12394 +
12395 +  @notes: Implemented as a macro.
12396 +
12397 +  @see also: SDDEVICE_GET_VERSION_MINOR
12398 +
12399 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12400 +#define SDDEVICE_GET_VERSION_MAJOR(pDev) (GET_SDIO_STACK_VERSION_MAJOR(pDev))
12401 +
12402 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12403 +  @function: Get SDIO Bus Driver Version Minor number
12404 +
12405 +  @function name: SDDEVICE_GET_VERSION_MINOR
12406 +  @prototype: INT SDDEVICE_GET_VERSION_MINOR(PSDDEVICE pDevice)
12407 +  @category: PD_Reference
12408 +
12409 +  @input:  pDevice   - the target device for this request
12410 +
12411 +  @output: none
12412 +
12413 +  @return: integer value for the minor version
12414 +
12415 +  @notes: Implemented as a macro.
12416 +
12417 +  @see also: SDDEVICE_GET_VERSION_MAJOR
12418 +
12419 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12420 +#define SDDEVICE_GET_VERSION_MINOR(pDev) (GET_SDIO_STACK_VERSION_MINOR(pDev))
12421 +
12422 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12423 +  @function: Test the SDIO revision for greater than or equal to 1.10
12424 +
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
12428 +
12429 +  @input:  pDevice   - the target device for this request
12430 +
12431 +  @output: none
12432 +
12433 +  @return: TRUE if the revision is greater than or equal to 1.10
12434 +
12435 +  @notes: Implemented as a macro.
12436 +
12437 +  @see also: SDDEVICE_IS_SD_REV_GTEQ_1_10
12438 +  @see also: SDDEVICE_IS_MMC_REV_GTEQ_4_0
12439 +
12440 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12441 +#define SDDEVICE_IS_SDIO_REV_GTEQ_1_10(pDev) ((pDev)->pHcd->CardProperties.SDIORevision >= SDIO_REVISION_1_10)
12442 +
12443 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12444 +  @function: Test the SDIO revision for greater than or equal to 1.20
12445 +
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
12449 +
12450 +  @input:  pDevice   - the target device for this request
12451 +
12452 +  @output: none
12453 +
12454 +  @return: TRUE if the revision is greater than or equal to 1.20
12455 +
12456 +  @notes: Implemented as a macro.
12457 +
12458 +  @see also: SDDEVICE_IS_SD_REV_GTEQ_1_10
12459 +  @see also: SDDEVICE_IS_SDIO_REV_GTEQ_1_10
12460 +
12461 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12462 +#define SDDEVICE_IS_SDIO_REV_GTEQ_1_20(pDev) ((pDev)->pHcd->CardProperties.SDIORevision >= SDIO_REVISION_1_20)
12463 +
12464 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12465 +  @function: Test the SD revision for greater than or equal to 1.10
12466 +
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
12470 +
12471 +  @input:  pDevice   - the target device for this request
12472 +
12473 +  @output: none
12474 +
12475 +  @return: TRUE if the revision is greater than or equal to 1.10
12476 +
12477 +  @notes: Implemented as a macro.
12478 +
12479 +  @see also: SDDEVICE_IS_SDIO_REV_GTEQ_1_10
12480 +  @see also: SDDEVICE_IS_MMC_REV_GTEQ_4_0
12481 +
12482 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12483 +#define SDDEVICE_IS_SD_REV_GTEQ_1_10(pDev) ((pDev)->pHcd->CardProperties.SD_MMC_Revision >= SD_REVISION_1_10)
12484 +
12485 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12486 +  @function: Test the MMC revision for greater than or equal to 4.0
12487 +
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
12491 +
12492 +  @input:  pDevice   - the target device for this request
12493 +
12494 +  @output: none
12495 +
12496 +  @return: TRUE if the revision is greater than or equal to 4.0
12497 +
12498 +  @notes: Implemented as a macro.
12499 +
12500 +  @see also: SDDEVICE_IS_SDIO_REV_GTEQ_1_10
12501 +  @see also: SDDEVICE_IS_SD_REV_GTEQ_1_10
12502 +
12503 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12504 +#define SDDEVICE_IS_MMC_REV_GTEQ_4_0(pDev) ((pDev)->pHcd->CardProperties.SD_MMC_Revision >= MMC_REVISION_4_0)
12505 +
12506 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12507 +  @function: Test for write protect enabled
12508 +
12509 +  @function name: SDDEVICE_IS_CARD_WP_ON
12510 +  @prototype: BOOL SDDEVICE_IS_CARD_WP_ON(PSDDEVICE pDevice)
12511 +  @category: PD_Reference
12512 +
12513 +  @input:  pDevice   - the target device for this request
12514 +
12515 +  @output: none
12516 +
12517 +  @return: TRUE if device is write protected.
12518 +
12519 +  @notes: Implemented as a macro.
12520 +
12521 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12522 +#define SDDEVICE_IS_CARD_WP_ON(pDev)       ((pDev)->pHcd->CardProperties.Flags & CARD_SD_WP)
12523 +
12524 +
12525 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12526 +  @function: Get the device's manufacturer specific ID
12527 +
12528 +  @function name: SDDEVICE_GET_SDIO_MANFID
12529 +  @prototype: UINT16 SDDEVICE_GET_SDIO_MANFID(PSDDEVICE pDevice)
12530 +  @category: PD_Reference
12531 +
12532 +  @input:  pDevice   - the target device for this request
12533 +
12534 +  @output: none
12535 +
12536 +  @return: function number
12537 +
12538 +  @notes: Implemented as a macro.
12539 +
12540 +  @see also: SDDEVICE_GET_SDIO_MANFCODE
12541 +
12542 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12543 +#define SDDEVICE_GET_SDIO_MANFID(pDev)     (pDev)->pId[0].SDIO_ManufacturerID
12544 +
12545 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12546 +  @function: Get the device's manufacturer code
12547 +
12548 +  @function name: SDDEVICE_GET_SDIO_MANFCODE
12549 +  @prototype: UINT16 SDDEVICE_GET_SDIO_MANFCODE(PSDDEVICE pDevice)
12550 +  @category: PD_Reference
12551 +
12552 +  @input:  pDevice   - the target device for this request
12553 +
12554 +  @output: none
12555 +
12556 +  @return: function number
12557 +
12558 +  @notes: Implemented as a macro.
12559 +
12560 +  @see also: SDDEVICE_GET_SDIO_MANFID
12561 +
12562 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12563 +#define SDDEVICE_GET_SDIO_MANFCODE(pDev)     (pDev)->pId[0].SDIO_ManufacturerCode
12564 +
12565 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12566 +  @function: Get the device's function number
12567 +
12568 +  @function name: SDDEVICE_GET_SDIO_FUNCNO
12569 +  @prototype: UINT8 SDDEVICE_GET_SDIO_FUNCNO(PSDDEVICE pDevice)
12570 +  @category: PD_Reference
12571 +
12572 +  @input:  pDevice   - the target device for this request
12573 +
12574 +  @output: none
12575 +
12576 +  @return: function number
12577 +
12578 +  @notes: Implemented as a macro.
12579 +
12580 +  @see also: SDDEVICE_GET_SDIO_FUNC_CLASS
12581 +
12582 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12583 +#define SDDEVICE_GET_SDIO_FUNCNO(pDev)     (pDev)->pId[0].SDIO_FunctionNo
12584 +
12585 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12586 +  @function: Get the functions's class
12587 +
12588 +  @function name: SDDEVICE_GET_SDIO_FUNC_CLASS
12589 +  @prototype: UINT8 SDDEVICE_GET_SDIO_FUNC_CLASS(PSDDEVICE pDevice)
12590 +  @category: PD_Reference
12591 +
12592 +  @input:  pDevice   - the target device for this request
12593 +
12594 +  @output: none
12595 +
12596 +  @return: class number
12597 +
12598 +  @notes: Implemented as a macro.
12599 +
12600 +  @see also: SDDEVICE_GET_SDIO_FUNCNO
12601 +
12602 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12603 +#define SDDEVICE_GET_SDIO_FUNC_CLASS(pDev) (pDev)->pId[0].SDIO_FunctionClass
12604 +
12605 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12606 +  @function: Get the functions's Card Information Structure pointer
12607 +
12608 +  @function name: SDDEVICE_GET_SDIO_FUNC_CISPTR
12609 +  @prototype: UINT32 SDDEVICE_GET_SDIO_FUNC_CISPTR(PSDDEVICE pDevice)
12610 +  @category: PD_Reference
12611 +
12612 +  @input:  pDevice   - the target device for this request
12613 +
12614 +  @output: none
12615 +
12616 +  @return: CIS offset
12617 +
12618 +  @notes: Implemented as a macro.
12619 +
12620 +  @see also: SDDEVICE_GET_SDIO_FUNC_CSAPTR
12621 +  @see also: SDDEVICE_GET_SDIO_COMMON_CISPTR
12622 +
12623 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12624 +#define SDDEVICE_GET_SDIO_FUNC_CISPTR(pDev)(pDev)->DeviceInfo.AsSDIOInfo.FunctionCISPtr
12625 +
12626 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12627 +  @function: Get the functions's Code Stoarge Area pointer
12628 +
12629 +  @function name: SDDEVICE_GET_SDIO_FUNC_CSAPTR
12630 +  @prototype: UINT32 SDDEVICE_GET_SDIO_FUNC_CSAPTR(PSDDEVICE pDevice)
12631 +  @category: PD_Reference
12632 +
12633 +  @input:  pDevice   - the target device for this request
12634 +
12635 +  @output: none
12636 +
12637 +  @return: CSA offset
12638 +
12639 +  @notes: Implemented as a macro.
12640 +
12641 +  @see also: SDDEVICE_GET_SDIO_FUNC_CISPTR
12642 +
12643 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12644 +#define SDDEVICE_GET_SDIO_FUNC_CSAPTR(pDev)(pDev)->DeviceInfo.AsSDIOInfo.FunctionCSAPtr
12645 +
12646 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12647 +  @function: Get the functions's maximum reported block size
12648 +
12649 +  @function name: SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE
12650 +  @prototype: UINT16 SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(PSDDEVICE pDevice)
12651 +  @category: PD_Reference
12652 +
12653 +  @input:  pDevice   - the target device for this request
12654 +
12655 +  @output: none
12656 +
12657 +  @return: block size
12658 +
12659 +  @notes: Implemented as a macro.
12660 +
12661 +  @see also:
12662 +
12663 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12664 +#define SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(pDev) (pDev)->DeviceInfo.AsSDIOInfo.FunctionMaxBlockSize
12665 +
12666 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12667 +  @function: Get the common Card Information Structure pointer
12668 +
12669 +  @function name: SDDEVICE_GET_SDIO_COMMON_CISPTR
12670 +  @prototype: UINT32 SDDEVICE_GET_SDIO_COMMON_CISPTR(PSDDEVICE pDevice)
12671 +  @category: PD_Reference
12672 +
12673 +  @input:  pDevice   - the target device for this request
12674 +
12675 +  @output: none
12676 +
12677 +  @return: Common CIS Address (in SDIO address space)
12678 +
12679 +  @notes: Implemented as a macro.
12680 +
12681 +  @see also: SDDEVICE_GET_SDIO_FUNC_CSAPTR
12682 +
12683 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12684 +#define SDDEVICE_GET_SDIO_COMMON_CISPTR(pDev) (pDev)->pHcd->CardProperties.CommonCISPtr
12685 +
12686 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12687 +  @function: Get the card capabilities
12688 +
12689 +  @function name: SDDEVICE_GET_SDIO_CARD_CAPS
12690 +  @prototype: UINT8 SDDEVICE_GET_SDIO_CARD_CAPS(PSDDEVICE pDevice)
12691 +  @category: PD_Reference
12692 +
12693 +  @input:  pDevice   - the target device for this request
12694 +
12695 +  @output: none
12696 +
12697 +  @return: 8-bit card capabilities register
12698 +
12699 +  @notes: Implemented as a macro. Refer to SDIO spec for decoding.
12700 +
12701 +  @see also: SDDEVICE_GET_CARD_FLAGS
12702 +  @see also: SDDEVICE_GET_SDIOCARD_CAPS
12703 +
12704 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12705 +#define SDDEVICE_GET_SDIO_CARD_CAPS(pDev)     (pDev)->pHcd->CardProperties.SDIOCaps
12706 +
12707 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12708 +  @function: Get the card flags
12709 +
12710 +  @function name: SDDEVICE_GET_CARD_FLAGS
12711 +  @prototype: CARD_INFO_FLAGS SDDEVICE_GET_CARD_FLAGS(PSDDEVICE pDevice)
12712 +  @category: PD_Reference
12713 +
12714 +  @input:  pDevice   - the target device for this request
12715 +
12716 +  @output: none
12717 +
12718 +  @return: flags
12719 +
12720 +  @notes: Implemented as a macro.
12721 +
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
12727 +                ...
12728 +            case CARD_SD:  // SD-Memory present
12729 +                ...
12730 +            case CARD_SDIO: // SDIO card present
12731 +                ...
12732 +            case CARD_COMBO: //SDIO card with SD
12733 +                ...
12734 +        }
12735 +        if (flags & CARD_SD_WP) {
12736 +            ...SD write protect on
12737 +        }
12738 +
12739 +  @see also: SDDEVICE_GET_SDIO_CARD_CAPS
12740 +
12741 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12742 +#define SDDEVICE_GET_CARD_FLAGS(pDev)      (pDev)->pHcd->CardProperties.Flags
12743 +
12744 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12745 +  @function: Get the Relative Card Address register
12746 +
12747 +  @function name: SDDEVICE_GET_CARD_RCA
12748 +  @prototype: UINT16 SDDEVICE_GET_CARD_RCA(PSDDEVICE pDevice)
12749 +  @category: PD_Reference
12750 +
12751 +  @input:  pDevice   - the target device for this request
12752 +
12753 +  @output: none
12754 +
12755 +  @return: register address
12756 +
12757 +  @notes: Implemented as a macro. Refer to SDIO spec for decoding.
12758 +
12759 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12760 +#define SDDEVICE_GET_CARD_RCA(pDev)        (pDev)->pHcd->CardProperties.RCA
12761 +
12762 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12763 +  @function: Get operational bus clock
12764 +
12765 +  @function name: SDDEVICE_GET_OPER_CLOCK
12766 +  @prototype: SD_BUSCLOCK_RATE SDDEVICE_GET_OPER_CLOCK(PSDDEVICE pDevice)
12767 +  @category: PD_Reference
12768 +
12769 +  @input:  pDevice   - the target device for this request
12770 +
12771 +  @output: none
12772 +
12773 +  @return: clock rate
12774 +
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.
12778 +
12779 +  @see also: SDDEVICE_GET_MAX_CLOCK
12780 +
12781 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12782 +#define SDDEVICE_GET_OPER_CLOCK(pDev)      (pDev)->pHcd->CardProperties.OperBusClock
12783 +
12784 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12785 +  @function: Get maximum bus clock
12786 +
12787 +  @function name: SDDEVICE_GET_MAX_CLOCK
12788 +  @prototype: SD_BUSCLOCK_RATE SDDEVICE_GET_MAX_CLOCK(PSDDEVICE pDevice)
12789 +  @category: PD_Reference
12790 +
12791 +  @input:  pDevice   - the target device for this request
12792 +
12793 +  @output: none
12794 +
12795 +  @return: clock rate
12796 +
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().
12800 +
12801 +  @see also: SDDEVICE_GET_OPER_CLOCK
12802 +
12803 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12804 +#define SDDEVICE_GET_MAX_CLOCK(pDev)       (pDev)->pHcd->MaxClockRate
12805 +
12806 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12807 +  @function: Get operational maximum block length.
12808 +
12809 +  @function name: SDDEVICE_GET_OPER_BLOCK_LEN
12810 +  @prototype: UINT16 SDDEVICE_GET_OPER_BLOCK_LEN(PSDDEVICE pDevice)
12811 +  @category: PD_Reference
12812 +
12813 +  @input:  pDevice   - the target device for this request
12814 +
12815 +  @output: none
12816 +
12817 +  @return: block size in bytes
12818 +
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.
12822 +
12823 +  @see also: SDDEVICE_GET_MAX_BLOCK_LEN
12824 +
12825 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12826 +#define SDDEVICE_GET_OPER_BLOCK_LEN(pDev)  (pDev)->pHcd->CardProperties.OperBlockLenLimit
12827 +
12828 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12829 +  @function: Get maximum block length.
12830 +
12831 +  @function name: SDDEVICE_GET_MAX_BLOCK_LEN
12832 +  @prototype: UINT16 SDDEVICE_GET_MAX_BLOCK_LEN(PSDDEVICE pDevice)
12833 +  @category: PD_Reference
12834 +
12835 +  @input:  pDevice   - the target device for this request
12836 +
12837 +  @output: none
12838 +
12839 +  @return: block size in bytes
12840 +
12841 +  @notes: Implemented as a macro. Use SDDEVICE_GET_OPER_BLOCK_LEN to obtain
12842 +          the current block length.
12843 +
12844 +  @see also: SDDEVICE_GET_OPER_BLOCK_LEN
12845 +
12846 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12847 +#define SDDEVICE_GET_MAX_BLOCK_LEN(pDev)   (pDev)->pHcd->MaxBytesPerBlock
12848 +
12849 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12850 +  @function: Get operational maximum block count.
12851 +
12852 +  @function name: SDDEVICE_GET_OPER_BLOCKS
12853 +  @prototype: UINT16 SDDEVICE_GET_OPER_BLOCKS(PSDDEVICE pDevice)
12854 +  @category: PD_Reference
12855 +
12856 +  @input:  pDevice   - the target device for this request
12857 +
12858 +  @output: none
12859 +
12860 +  @return: maximum number of blocks per transaction.
12861 +
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.
12865 +
12866 +  @see also: SDDEVICE_GET_MAX_BLOCK_LEN
12867 +
12868 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12869 +#define SDDEVICE_GET_OPER_BLOCKS(pDev)     (pDev)->pHcd->CardProperties.OperBlockCountLimit
12870 +
12871 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12872 +  @function: Get maximum block count.
12873 +
12874 +  @function name: SDDEVICE_GET_MAX_BLOCKS
12875 +  @prototype: UINT16 SDDEVICE_GET_MAX_BLOCKS(PSDDEVICE pDevice)
12876 +  @category: PD_Reference
12877 +
12878 +  @input:  pDevice   - the target device for this request
12879 +
12880 +  @output: none
12881 +
12882 +  @return: maximum number of blocks per transaction.
12883 +
12884 +  @notes: Implemented as a macro. Use SDDEVICE_GET_OPER_BLOCKS to obtain
12885 +          the current block count.
12886 +
12887 +  @see also: SDDEVICE_GET_OPER_BLOCKS
12888 +
12889 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12890 +#define SDDEVICE_GET_MAX_BLOCKS(pDev)      (pDev)->pHcd->MaxBlocksPerTrans
12891 +
12892 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12893 +  @function: Get applied slot voltage
12894 +
12895 +  @function name: SDDEVICE_GET_SLOT_VOLTAGE_MASK
12896 +  @prototype: SLOT_VOLTAGE_MASK SDDEVICE_GET_SLOT_VOLTAGE_MASK(PSDDEVICE pDevice)
12897 +  @category: PD_Reference
12898 +
12899 +  @input:  pDevice   - the target device for this request
12900 +
12901 +  @output: none
12902 +
12903 +  @return: slot voltage mask
12904 +
12905 +  @notes: This function returns the applied voltage on the slot. The voltage value is a
12906 +          mask having the following values:
12907 +          SLOT_POWER_3_3V
12908 +          SLOT_POWER_3_0V
12909 +          SLOT_POWER_2_8V
12910 +          SLOT_POWER_2_0V
12911 +          SLOT_POWER_1_8V
12912 +          SLOT_POWER_1_6V
12913 +
12914 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12915 +#define SDDEVICE_GET_SLOT_VOLTAGE_MASK(pDev)   (pDev)->pHcd->CardProperties.CardVoltage
12916 +
12917 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12918 +  @function: Get the Card Specific Data Register.
12919 +
12920 +  @function name: SDDEVICE_GET_CARDCSD
12921 +  @prototype: PUINT8 SDDEVICE_GET_CARDCSD(PSDDEVICE pDevice)
12922 +  @category: PD_Reference
12923 +
12924 +  @input:  pDevice   - the target device for this request
12925 +
12926 +  @output: none
12927 +
12928 +  @return:  UINT8 CardCSD[MAX_CARD_RESPONSE_BYTES] array of CSD data.
12929 +
12930 +  @notes: Implemented as a macro.
12931 +
12932 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12933 +#define SDDEVICE_GET_CARDCSD(pDev)         (pDev)->pHcd->CardProperties.CardCSD
12934 +
12935 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12936 +  @function: Get the bus mode flags
12937 +
12938 +  @function name: SDDEVICE_GET_BUSMODE_FLAGS
12939 +  @prototype: SD_BUSMODE_FLAGS SDDEVICE_GET_BUSMODE_FLAGS(PSDDEVICE pDevice)
12940 +  @category: PD_Reference
12941 +
12942 +  @input:  pDevice   - the target device for this request
12943 +
12944 +  @output: none
12945 +
12946 +  @return:
12947 +
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.
12951 +
12952 +  @see also: SDDEVICE_GET_BUSWIDTH
12953 +  @see also: SDCONFIG_BUS_MODE_CTRL
12954 +
12955 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12956 +#define SDDEVICE_GET_BUSMODE_FLAGS(pDev)  (pDev)->pHcd->CardProperties.BusMode
12957 +
12958 +
12959 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12960 +  @function: Get the bus width.
12961 +
12962 +  @function name: SDDEVICE_GET_BUSWIDTH
12963 +  @prototype: UINT8 SDDEVICE_GET_BUSWIDTH(PSDDEVICE pDevice)
12964 +  @category: PD_Reference
12965 +
12966 +  @input:  pDevice   - the target device for this request
12967 +
12968 +  @output: none
12969 +
12970 +  @return:  bus width: SDCONFIG_BUS_WIDTH_SPI, SDCONFIG_BUS_WIDTH_1_BIT, SDCONFIG_BUS_WIDTH_4_BIT
12971 +
12972 +  @notes: Implemented as a macro.
12973 +
12974 +  @see also: SDDEVICE_IS_BUSMODE_SPI
12975 +
12976 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12977 +#define SDDEVICE_GET_BUSWIDTH(pDev)        SDCONFIG_GET_BUSWIDTH((pDev)->pHcd->CardProperties.BusMode)
12978 +
12979 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12980 +  @function: Is bus in SPI mode.
12981 +
12982 +  @function name: SDDEVICE_IS_BUSMODE_SPI
12983 +  @prototype: BOOL SDDEVICE_IS_BUSMODE_SPI(PSDDEVICE pDevice)
12984 +  @category: PD_Reference
12985 +
12986 +  @input:  pDevice   - the target device for this request
12987 +
12988 +  @output: none
12989 +
12990 +  @return:  TRUE, SPI mode.
12991 +
12992 +  @notes: Implemented as a macro.
12993 +
12994 +  @see also: SDDEVICE_GET_BUSWIDTH
12995 +
12996 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12997 +#define SDDEVICE_IS_BUSMODE_SPI(pDev) (SDDEVICE_GET_BUSWIDTH(pDev) == SDCONFIG_BUS_WIDTH_SPI)
12998 +
12999 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13000 +  @function: Send a request to a device.
13001 +
13002 +  @function name: SDDEVICE_CALL_REQUEST_FUNC
13003 +  @prototype: SDIO_STATUS SDDEVICE_CALL_REQUEST_FUNC(PSDDEVICE pDevice, PSDREQUEST pRequest)
13004 +  @category: PD_Reference
13005 +
13006 +  @input:  pDevice   - the target device for this request
13007 +  @input:  pRequest  - the request to be sent
13008 +
13009 +  @output: none
13010 +
13011 +  @return: SDIO_STATUS
13012 +
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.
13015 +
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;
13022 +    }
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)) {
13028 +        break;
13029 +    }
13030 +    //check the request response (based on the request type)
13031 +    if (SD_R5_GET_RESP_FLAGS(pReq->Response) & SD_R5_ERRORS) {
13032 +        ...
13033 +    }
13034 +    if (!Write) {
13035 +            // store the byte
13036 +        *pData =  SD_R5_GET_READ_DATA(pReq->Response);
13037 +    }
13038 +    //free the request
13039 +    SDDeviceFreeRequest(pDevice,pReq);
13040 +    ...
13041 +
13042 +  @see also: SDDeviceAllocRequest
13043 +  @see also: SDDEVICE_CALL_CONFIG_FUNC
13044 +
13045 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13046 +#define SDDEVICE_CALL_REQUEST_FUNC(pDev,pReq)  (pDev)->pRequest((pDev),(pReq))
13047 +
13048 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13049 +  @function: Send configuration to a device.
13050 +
13051 +  @function name: SDDEVICE_CALL_CONFIG_FUNC
13052 +  @prototype: SDIO_STATUS SDDEVICE_CALL_CONFIG_FUNC(PSDDEVICE pDevice, PSDCONFIG pConfigure)
13053 +  @category: PD_Reference
13054 +
13055 +  @input:  pDevice   - the target device for this request
13056 +  @input:  pConfigure - configuration request
13057 +
13058 +  @output: none
13059 +
13060 +  @return: SDIO_STATUS
13061 +
13062 +  @notes: Sends a configuration request to the specified device.
13063 +
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);
13071 +
13072 +  @see also: SDLIB_IssueConfig
13073 +
13074 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13075 +#define SDDEVICE_CALL_CONFIG_FUNC(pDev,pCfg)   (pDev)->pConfigure((pDev),(pCfg))
13076 +
13077 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13078 +  @function: Allocate a request structure.
13079 +
13080 +  @function name: SDDeviceAllocRequest
13081 +  @prototype: PSDREQUEST SDDeviceAllocRequest(PSDDEVICE pDevice)
13082 +  @category: PD_Reference
13083 +
13084 +  @input:  pDevice   - the target device for this request
13085 +
13086 +  @output: none
13087 +
13088 +  @return: request pointer or NULL if not available.
13089 +
13090 +  @notes:  This function must not be called in a non-schedulable (interrupts off) context.
13091 +           Allocating memory on some OSes may block.
13092 +
13093 +  @see also: SDDEVICE_CALL_REQUEST_FUNC
13094 +  @see also: SDDeviceFreeRequest
13095 +
13096 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13097 +#define SDDeviceAllocRequest(pDev)        (pDev)->AllocRequest((pDev))
13098 +
13099 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13100 +  @function: Free a request structure.
13101 +
13102 +  @function name: SDDeviceFreeRequest
13103 +  @prototype: void SDDeviceFreeRequest(PSDDEVICE pDevice, PSDREQUEST pRequest)
13104 +  @category: PD_Reference
13105 +
13106 +  @input:  pDevice   - the target device for this request
13107 +  @input:  pRequest  - request allocated by SDDeviceAllocRequest().
13108 +
13109 +  @output: none
13110 +
13111 +  @return: none
13112 +
13113 +  @notes: This function must not be called in a non-schedulable (interrupts off) context.
13114 +          Freeing memory on some OSes may block.
13115 +
13116 +  @see also: SDDEVICE_CALL_REQUEST_FUNC
13117 +  @see also: SDDeviceAllocRequest
13118 +
13119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13120 +#define SDDeviceFreeRequest(pDev,pReq)    (pDev)->FreeRequest((pDev),pReq)
13121 +
13122 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13123 +  @function: Register an interrupt handler for a device.
13124 +
13125 +  @function name: SDDEVICE_SET_IRQ_HANDLER
13126 +  @prototype: void SDDEVICE_SET_IRQ_HANDLER(PSDDEVICE pDevice,
13127 +                                            void (*pIrqFunction)(PVOID pContext),
13128 +                                            PVOID pContext)
13129 +  @category: PD_Reference
13130 +
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.
13134 +
13135 +  @output: none
13136 +
13137 +  @return: none
13138 +
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.
13144 +
13145 +  @see also: SDDEVICE_SET_ASYNC_IRQ_HANDLER
13146 +
13147 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13148 +#define SDDEVICE_SET_IRQ_HANDLER(pDev,pFn,pContext)  \
13149 +{                                                    \
13150 +    (pDev)->pIrqFunction = (pFn);                    \
13151 +    (pDev)->IrqContext = (PVOID)(pContext);          \
13152 +}
13153 +
13154 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13155 +  @function: Register an asynchronous interrupt handler for a device.
13156 +
13157 +  @function name: SDDEVICE_SET_ASYNC_IRQ_HANDLER
13158 +  @prototype: void SDDEVICE_SET_ASYNC_IRQ_HANDLER(PSDDEVICE pDevice,
13159 +                                            void (*pIrqAsyncFunction)(PVOID pContext),
13160 +                                            PVOID pContext)
13161 +  @category: PD_Reference
13162 +
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.
13166 +
13167 +  @output: none
13168 +
13169 +  @return: none
13170 +
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.
13178 +
13179 +  @see also: SDDEVICE_SET_IRQ_HANDLER
13180 +
13181 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13182 +#define SDDEVICE_SET_ASYNC_IRQ_HANDLER(pDev,pFn,pContext)  \
13183 +{                                                          \
13184 +    (pDev)->pIrqAsyncFunction = (pFn);                     \
13185 +    (pDev)->IrqAsyncContext = (PVOID)(pContext);           \
13186 +}
13187 +
13188 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13189 +  @function: Get the SDIO capabilities rgeister.
13190 +
13191 +  @function name: SDDEVICE_GET_SDIOCARD_CAPS
13192 +  @prototype: UINT8 SDDEVICE_GET_SDIOCARD_CAPS(PSDDEVICE pDevice)
13193 +  @category: PD_Reference
13194 +
13195 +  @input:  pDevice   - the target device for this request
13196 +
13197 +  @output: none
13198 +
13199 +  @return: SD capabilities
13200 +
13201 +  @notes: See SD specification for decoding of these capabilities.
13202 +
13203 +  @see also: SDDEVICE_GET_SDIO_CARD_CAPS
13204 +
13205 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13206 +#define SDDEVICE_GET_SDIOCARD_CAPS(pDev) (pDev)->pHcd->CardProperties.SDIOCaps
13207 +
13208 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13209 +  @function: Get HCD driver name
13210 +
13211 +  @function name: SDDEVICE_GET_HCDNAME
13212 +  @prototype: PTEXT SDDEVICE_GET_HCDNAME(PSDDEVICE pDevice)
13213 +  @category: PD_Reference
13214 +
13215 +  @input:  pDevice   - the target device for this request
13216 +
13217 +  @output: none
13218 +
13219 +  @return:  pointer to a string containing the name of the underlying HCD
13220 +
13221 +  @notes: Implemented as a macro.
13222 +
13223 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13224 +#define SDDEVICE_GET_HCDNAME(pDev)  (pDev)->pHcd->pName
13225 +
13226 +
13227 +#define SDDEVICE_CALL_IRQ_HANDLER(pDev)       (pDev)->pIrqFunction((pDev)->IrqContext)
13228 +#define SDDEVICE_CALL_IRQ_ASYNC_HANDLER(pDev) (pDev)->pIrqAsyncFunction((pDev)->IrqAsyncContext)
13229 +
13230 +
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)
13234 +
13235 +
13236 +typedef enum _SDHCD_IRQ_PROC_STATE {
13237 +    SDHCD_IDLE = 0,
13238 +    SDHCD_IRQ_PENDING = 1,
13239 +    SDHCD_IRQ_HELPER  = 2
13240 +}SDHCD_IRQ_PROC_STATE, *PSDHCD_IRQ_PROC_STATE;
13241 +
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 */
13281 +    PVOID              Reserved1;
13282 +    PVOID              Reserved2;
13283 +}SDHCD, *PSDHCD;
13284 +
13285 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13286 +  @function: Get a pointer to the HCD's DMA description
13287 +
13288 +  @function name: SDGET_DMA_DESCRIPTION
13289 +  @prototype: PSDDMA_DESCRIPTION SDGET_DMA_DESCRIPTION(PSDDEVICE pDevice)
13290 +  @category: PD_Reference
13291 +
13292 +  @input:  pDevice - device structure
13293 +
13294 +  @return: PSDDMA_DESCRIPTION or NULL if no DMA support
13295 +
13296 +  @notes: Implemented as a macro.
13297 +
13298 +  @example: getting the current request:
13299 +          PSDDMA_DESCRIPTION pDmaDescrp = SDGET_DMA_DESCRIPTION(pDevice);
13300 +
13301 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13302 +#define SDGET_DMA_DESCRIPTION(pDevice)     (pDevice)->pHcd->pDmaDescription
13303 +
13304 +
13305 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13306 +  @function: Get the logical slot number the device is assigned to.
13307 +
13308 +  @function name: SDDEVICE_GET_SLOT_NUMBER
13309 +  @prototype: UINT8 SDDEVICE_GET_SLOT_NUMBER(PSDDEVICE pDevice)
13310 +  @category: PD_Reference
13311 +
13312 +  @input:  pDevice - device structure
13313 +
13314 +  @return: unsigned number representing the slot number
13315 +
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
13318 +          slot number.
13319 +
13320 +  @example: getting the slot number:
13321 +          UINT8 thisSlot = SDDEVICE_GET_SLOT_NUMBER(pDevice);
13322 +
13323 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13324 +#define SDDEVICE_GET_SLOT_NUMBER(pDevice) (pDevice)->pHcd->SlotNumber
13325 +
13326 +/* for function use */
13327 +SDIO_STATUS SDIO_RegisterFunction(PSDFUNCTION pFunction);
13328 +SDIO_STATUS SDIO_UnregisterFunction(PSDFUNCTION pFunction);
13329 +
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
13335 --- /dev/null
13336 +++ b/include/linux/sdio/sdio_hcd_defs.h
13337 @@ -0,0 +1,219 @@
13338 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13339 +@file: sdio_hcd_defs.h
13340 +
13341 +@abstract: host controller driver definitions
13342 +
13343 +@notice: Copyright (c), 2005-2006 Atheros Communications, Inc.
13344 +
13345 +
13346 + *
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;
13350 + *
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.
13355 + *
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:
13358 + *
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.
13364 + *   Disclaimers:
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.
13373 + *
13374 + *
13375 + *  The initial developers of the original code are Seung Yi and Paul Lever
13376 + *
13377 + *  sdio@atheros.com
13378 + *
13379 + *
13380 +
13381 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13382 +#ifndef __SDIO_HCD_DEFS_H___
13383 +#define __SDIO_HCD_DEFS_H___
13384 +
13385 +    /* write protect switch position data */
13386 +typedef UINT8 SDCONFIG_WP_VALUE;
13387 +
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)
13395 +
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;
13400 +
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;
13406 +
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;
13418 +
13419 +/* card insert */
13420 +#define EVENT_HCD_ATTACH               1
13421 +/* card remove */
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
13429 +/* NOP */
13430 +#define EVENT_HCD_NOP                  0
13431 +
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 */
13450 +
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
13456 +
13457 +  @function name: GET_CURRENT_REQUEST
13458 +  @prototype: PSDREQUEST GET_CURRENT_REQUEST (PSDHCD pHcd)
13459 +  @category: HD_Reference
13460 +
13461 +  @input:  pHcd - host structure
13462 +
13463 +  @return: current SD/SDIO bus request being worked on
13464 +
13465 +  @notes: Implemented as a macro. This macro returns the current SD request that is
13466 +          being worked on.
13467 +
13468 +  @example: getting the current request:
13469 +          pReq = GET_CURRENT_REQUEST(&pHct->Hcd);
13470 +
13471 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13472 +#define GET_CURRENT_REQUEST(pHcd)     (pHcd)->pCurrentRequest
13473 +#define GET_CURRENT_BUS_WIDTH(pHcd) SDCONFIG_GET_BUSWIDTH((pHcd)->CardProperties.BusMode)
13474 +
13475 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13476 +  @function: Get host controller's current operational bus clock
13477 +
13478 +  @function name: SDHCD_GET_OPER_CLOCK
13479 +  @prototype: SD_BUSCLOCK_RATE SDHCD_GET_OPER_CLOCK(PSDHCD pHcd)
13480 +  @category: HD_Reference
13481 +
13482 +  @input:  pHcd   - the registered host structure
13483 +
13484 +  @output: none
13485 +
13486 +  @return: clock rate
13487 +
13488 +  @notes: Implemented as a macro. Returns the current bus clock rate.
13489 +
13490 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13491 +#define SDHCD_GET_OPER_CLOCK(pHcd)      (pHcd)->CardProperties.OperBusClock
13492 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13493 +  @function: Is host controller operating in SPI mode
13494 +
13495 +  @function name: IS_HCD_BUS_MODE_SPI
13496 +  @prototype: BOOL IS_HCD_BUS_MODE_SPI (PSDHCD pHcd)
13497 +  @category: HD_Reference
13498 +
13499 +  @input:  pHcd - host structure
13500 +
13501 +  @return: TRUE if in SPI mode
13502 +
13503 +  @notes: Implemented as a macro. Host controllers that operate in SPI mode
13504 +          dynamically can use this macro to check for SPI operation.
13505 +
13506 +  @example: testing for SPI mode:
13507 +          if (IS_HCD_BUS_MODE_SPI(&pHct->Hcd)) {
13508 +             .. in spi mode
13509 +          }
13510 +
13511 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13512 +#define IS_HCD_BUS_MODE_SPI(pHcd)   (GET_CURRENT_BUS_WIDTH(pHcd) == SDCONFIG_BUS_WIDTH_SPI)
13513 +
13514 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13515 +  @function: Is host controller using SPI in non-CRC mode
13516 +
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
13520 +
13521 +  @input:  pHcd - host structure
13522 +
13523 +  @return: TRUE if CRC mode is off
13524 +
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.
13530 +
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.
13534 +          }
13535 +
13536 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13537 +#define IS_HCD_BUS_MODE_SPI_NO_CRC(pHcd)   ((pHcd)->CardProperties.BusMode & \
13538 +                                                        SDCONFIG_BUS_MODE_SPI_NO_CRC)
13539 +
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
13546 +
13547 +/* prototypes */
13548 +/* for HCD use */
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);
13555 +
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
13560 --- /dev/null
13561 +++ b/include/linux/sdio/sdio_lib.h
13562 @@ -0,0 +1,270 @@
13563 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13564 +@file: sdio_lib.h
13565 +
13566 +@abstract: SDIO Library include
13567 +
13568 +#notes:
13569 +
13570 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
13571 +
13572 +
13573 + *
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;
13577 + *
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.
13582 + *
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:
13585 + *
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.
13591 + *   Disclaimers:
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.
13600 + *
13601 + *
13602 + *  The initial developers of the original code are Seung Yi and Paul Lever
13603 + *
13604 + *  sdio@atheros.com
13605 + *
13606 + *
13607 +
13608 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13609 +#ifndef __SDIO_LIB_H___
13610 +#define __SDIO_LIB_H___
13611 +
13612 +#ifdef UNDER_CE
13613 +#include "wince\sdio_lib_wince.h"
13614 +#endif /* WINCE */
13615 +
13616 +#define CMD52_DO_READ  FALSE
13617 +#define CMD52_DO_WRITE TRUE
13618 +
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)
13626 +
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))
13634 +
13635 +#define SDLIB_SetupCMD52RequestAsync(f,a,w,wd,pR)   \
13636 +{                                                   \
13637 +    SDLIB_SetupCMD52Request((f),(a),(w),(wd),(pR)); \
13638 +    (pR)->Flags |= SDREQ_FLAGS_TRANS_ASYNC;         \
13639 +}
13640 +
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;
13647 +
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;
13655 +
13656 +/* internal library prototypes that can be proxied */
13657 +SDIO_STATUS _SDLIB_IssueCMD52(PSDDEVICE     pDevice,
13658 +                        UINT8         FuncNo,
13659 +                        UINT32        Address,
13660 +                        PUINT8        pData,
13661 +                        INT           ByteCount,
13662 +                        BOOL          Write);
13663 +SDIO_STATUS _SDLIB_FindTuple(PSDDEVICE  pDevice,
13664 +                             UINT8      Tuple,
13665 +                             UINT32     *pTupleScanAddress,
13666 +                             PUINT8     pBuffer,
13667 +                             UINT8      *pLength);
13668 +SDIO_STATUS _SDLIB_IssueConfig(PSDDEVICE        pDevice,
13669 +                               SDCONFIG_COMMAND Command,
13670 +                               PVOID            pData,
13671 +                               INT              Length);
13672 +void _SDLIB_PrintBuffer(PUCHAR pBuffer, INT Length,PTEXT pDescription);
13673 +void _SDLIB_SetupCMD52Request(UINT8         FuncNo,
13674 +                              UINT32        Address,
13675 +                              BOOL          Write,
13676 +                              UINT8         WriteData,
13677 +                              PSDREQUEST    pRequest);
13678 +SDIO_STATUS _SDLIB_SetFunctionBlockSize(PSDDEVICE        pDevice,
13679 +                                        UINT16           BlockSize);
13680 +
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);
13687 +
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
13701 +#else
13702 +
13703 +/* proxied versions */
13704 +SDIO_STATUS SDLIB_IssueCMD52(PSDDEVICE     pDevice,
13705 +                             UINT8         FuncNo,
13706 +                             UINT32        Address,
13707 +                             PUINT8        pData,
13708 +                             INT           ByteCount,
13709 +                             BOOL          Write);
13710 +
13711 +void SDLIB_SetupCMD52Request(UINT8         FuncNo,
13712 +                             UINT32        Address,
13713 +                             BOOL          Write,
13714 +                             UINT8         WriteData,
13715 +                             PSDREQUEST    pRequest);
13716 +
13717 +SDIO_STATUS SDLIB_FindTuple(PSDDEVICE  pDevice,
13718 +                        UINT8      Tuple,
13719 +                        UINT32     *pTupleScanAddress,
13720 +                        PUINT8     pBuffer,
13721 +                        UINT8      *pLength);
13722 +
13723 +SDIO_STATUS SDLIB_IssueConfig(PSDDEVICE        pDevice,
13724 +                              SDCONFIG_COMMAND Command,
13725 +                              PVOID            pData,
13726 +                              INT              Length);
13727 +
13728 +SDIO_STATUS SDLIB_SetFunctionBlockSize(PSDDEVICE        pDevice,
13729 +                                       UINT16           BlockSize);
13730 +
13731 +void SDLIB_PrintBuffer(PUCHAR pBuffer, INT Length,PTEXT pDescription);
13732 +
13733 +SDIO_STATUS SDLIB_GetDefaultOpCurrent(PSDDEVICE  pDevice, SD_SLOT_CURRENT *pOpCurrent);
13734 +
13735 +PSDMESSAGE_QUEUE SDLIB_CreateMessageQueue(INT MaxMessages, INT MaxMessageLength);
13736 +
13737 +void SDLIB_DeleteMessageQueue(PSDMESSAGE_QUEUE pQueue);
13738 +
13739 +SDIO_STATUS SDLIB_PostMessage(PSDMESSAGE_QUEUE pQueue, PVOID pMessage, INT MessageLength);
13740 +
13741 +SDIO_STATUS SDLIB_GetMessage(PSDMESSAGE_QUEUE pQueue, PVOID pData, INT *pBufferLength);
13742 +#endif /* CTSYSTEM_NO_FUNCTION_PROXIES */
13743 +
13744 +
13745 +SDIO_STATUS SDLIB_OSCreateHelper(POSKERNEL_HELPER pHelper,
13746 +                           PHELPER_FUNCTION pFunction,
13747 +                           PVOID            pContext);
13748 +
13749 +void SDLIB_OSDeleteHelper(POSKERNEL_HELPER pHelper);
13750 +
13751 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13752 +  @function: Check message queue is empty
13753 +
13754 +  @function name: SDLIB_IsQueueEmpty
13755 +  @prototype: BOOL SDLIB_IsQueueEmpty(PSDMESSAGE_QUEUE pQueue)
13756 +  @category: Support_Reference
13757 +
13758 +  @input: pQueue - message queue to check
13759 +
13760 +  @return: TRUE if empty else false
13761 +
13762 +  @see also: SDLIB_CreateMessageQueue
13763 +
13764 +  @example: Check message queue :
13765 +              if (SDLIB_IsQueueEmpty(pInstance->pQueue)) {
13766 +                   .. message queue is empty
13767 +              }
13768 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13769 +static INLINE BOOL SDLIB_IsQueueEmpty(PSDMESSAGE_QUEUE pQueue) {
13770 +    return SDLIST_IS_EMPTY(&pQueue->MessageList);
13771 +}
13772 +
13773 +
13774 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13775 +  @function: Issue an I/O abort request
13776 +
13777 +  @function name: SDLIB_IssueIOAbort
13778 +  @prototype: SDIO_STATUS SDLIB_IssueIOAbort(PSDDEVICE pDevice)
13779 +  @category: PD_Reference
13780 +
13781 +  @input: pDevice - the device that is the target of this request
13782 +
13783 +  @return: SDIO_STATUS
13784 +
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.
13793 +
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);
13799 +              }
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);
13807 +
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);
13813 +}
13814 +
13815 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13816 +  @function: Setup an I/O abort request for async operation
13817 +
13818 +  @function name: SDLIB_SetupIOAbortAsync
13819 +  @prototype: SDLIB_SetupIOAbortAsync(PSDDEVICE pDevice, PSDREQUEST pRequest)
13820 +  @category: PD_Reference
13821 +
13822 +  @input: pDevice - the device that is the target of this request
13823 +          pRequest - the request to set up
13824 +
13825 +  @see also: SDLIB_IssueIOAbort
13826 +
13827 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13828 +#define SDLIB_SetupIOAbortAsync(pDevice, pReq) \
13829 +        SDLIB_SetupCMD52RequestAsync(0,0x06,TRUE,SDDEVICE_GET_SDIO_FUNCNO(pDevice),(pReq))
13830 +
13831 +
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
13836 --- /dev/null
13837 +++ b/include/linux/sdio/sdlist.h
13838 @@ -0,0 +1,141 @@
13839 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13840 +@file: sdlist.h
13841 +
13842 +@abstract: OS independent list functions
13843 +
13844 +@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.
13845 +
13846 +
13847 + *
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;
13851 + *
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.
13856 + *
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:
13859 + *
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.
13865 + *   Disclaimers:
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.
13874 + *
13875 + *
13876 + *  The initial developers of the original code are Seung Yi and Paul Lever
13877 + *
13878 + *  sdio@atheros.com
13879 + *
13880 + *
13881 +
13882 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
13883 +#ifndef __SDLIST_H___
13884 +#define __SDLIST_H___
13885 +
13886 +/* list functions */
13887 +/* pointers for the list */
13888 +typedef struct _SDLIST {
13889 +    struct _SDLIST *pPrev;
13890 +    struct _SDLIST *pNext;
13891 +}SDLIST, *PSDLIST;
13892 +/*
13893 + * SDLIST_INIT , circular list
13894 +*/
13895 +#define SDLIST_INIT(pList)\
13896 +    {(pList)->pPrev = pList; (pList)->pNext = pList;}
13897 +#define SDLIST_INIT_DECLARE(List)\
13898 +    SDLIST List =   {&List, &List}
13899 +
13900 +
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
13904 +/*
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
13907 + * iteration loop
13908 +*/
13909 +#define SDITERATE_OVER_LIST(pStart, pTemp) \
13910 +    for((pTemp) =(pStart)->pNext; pTemp != (pStart); (pTemp) = (pTemp)->pNext)
13911 +
13912 +
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
13915 + */
13916 +#define SDITERATE_OVER_LIST_ALLOW_REMOVE(pStart,pItem,st,offset)  \
13917 +{                                                       \
13918 +    PSDLIST  pTemp;                                     \
13919 +    pTemp = (pStart)->pNext;                            \
13920 +    while (pTemp != (pStart)) {                         \
13921 +        (pItem) = CONTAINING_STRUCT(pTemp,st,offset);   \
13922 +         pTemp = pTemp->pNext;                          \
13923 +
13924 +#define SDITERATE_END }}
13925 +
13926 +/*
13927 + * SDListInsertTail - insert pAdd to the end of the list
13928 +*/
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;
13937 +    return pAdd;
13938 +}
13939 +
13940 +/*
13941 + * SDListInsertHead - insert pAdd into the head of the list
13942 +*/
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;
13951 +    return pAdd;
13952 +}
13953 +
13954 +#define SDListAdd(pList,pItem) SDListInsertHead((pList),(pItem))
13955 +/*
13956 + * SDListRemove - remove pDel from list
13957 +*/
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;
13964 +    return pDel;
13965 +}
13966 +
13967 +/*
13968 + * SDListRemoveItemFromHead - get a list item from the head
13969 +*/
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);
13976 +    }
13977 +    return pItem;
13978 +}
13979 +#endif /* __SDLIST_H___ */
13980 -- 
13981 1.5.6.3
13982