客户端驱动的注册
SD卡客户端驱动没有和输出函数直接连接。相反的,这些函数调用去访问客户端驱动得通过客户端的注册过程。
在这个过程期间,客户驱动通过他自己的信息给总线驱动,并且接收信息需要去调用给外部函数。在注册之后,提供宏使能客户端驱动去访问那些API。这些宏只被客户端驱动使用。
去完成注册的过程,客户端驱动必须使用SDRegisterClient为SD设备发送它的本地设备信息,和一个友名给总线驱动。
卡信息结构
一个SDIO卡包含一个或多个卡信息结构(CIS)。一个SD客户端驱动将需要从这些结构中读出信息,以获得卡的性能和功能。
一个CIS被组成一个块的数据链,包含标准和特殊的应用信息。一个SDIO卡有一个所有卡的公共CIS区域,和每一个卡都有一个独自的CIS区域。客户端驱动可以从CIS区域读出它自己的功能,或从公共CIS区域,通过使用CommonCIS参数标志。
SDGetTuple函数允许客户端去访问一个指定的tuple。由于tuples经常不知道结构的大小,如果pBuffer为空的话,SDGetTuple函数通过pBufferSize返回一个tuple的长度。
一个tuple长度为0,tuple是不存在的。当tuple长度被确定,客户端驱动可以分配足够的存储和调用API再与一个非空的pBuffer值去读tuple 数据。
(注:
tuple
元组,数组
In a relational data base, a part of a relation that identifiers an entity and its attributes.
关系数据库中,标识一个实体及其属性的关系的一部分。 参阅relation。)
插槽事件回调
SD卡客户端驱动可以选择插槽事件回调。这个回调提供异步信息关于插槽状态的改变。下面的代码例子就是一类插槽事件回调。
VOID SlotEventCallBack(SD_DEVICE_HANDLE hDevice,
PVOID pContext,
SD_SLOT_EVENT_TYPE SlotEventType,
PVOID pData,
DWORD DataLength)
{
PSD_MY_DEVICE_INSTANCE pDevice = (PSD_MEMCARD_INFO)pContext;
switch (SlotEventType) {
case SDCardEjected :
// mark that the card is being ejected
pDevice->CardEjected = TRUE;
break;
}
}
客户端驱动使用注册信息结构去提供一个指向客户端函数的指针,下面例子是一类注册信息结构。
memset(&ClientInfo, 0, sizeof(ClientInfo));
// set client options and register as a client device
_tcscpy(ClientInfo.ClientName, TEXT("MyDriver"));
// set the callback, we want slot events
ClientInfo.pSlotEventCallBack = SlotEventCallBack;
// register the client
Status = SDRegisterClient(hClientHandle,
pDevice,
&ClientInfo);
插槽事件类型通过作为参数传给回调函数。回调函数可以被调用再任何线程空间。插槽事件类型可以限制,当回调函数被调用的时候要不要被触发。
当卡从插槽移开时SDCardEjected被调用。当事件类型显示出来,客户端驱动将不会在回调函数里面承交任何总线请求。
回调函数被调用,先前调用*_Deinit (Device Manager)的进入点为客户端驱动,这些会给客户端驱动一个机会去设置内部设备状态。例如,回调函数可以设置一个标志允许客户驱动去拒绝用户的应用程序IO请求。
客户端驱动的总线请求
SD客户端驱动使用总线请求发送命令和相应到SD卡,同时也是通过总线接收命令和相应。总线请求包含SD卡协议栈信息被使用在:
控制命令发送给SD卡
控制发送或响应任何的命令相关数据
SDBusRequest函数使客户端驱动可以异步发送总线请求给卡。这些参数在同步和异步功能的使用上是类似的。CommandCode参数是命令,在SD规格上定义。CommandArgument是32位任意的参数,在SD规格上定义。
所有的SD命令,除了CMD0,都需要卡反馈一个响应。一些命令可以使卡发送数据。一些命令使卡准备去接收数据。
SDBusRequest函数里面的TransferClass参数是存放当前类别的种类。下面表是现实当前的总类:
SD_COMMAND说明是一个命令或相应
SD_READ说明是一个命令、相应或数据读
SD_WRITE说明是一个命令、相应或数据写
ResponseType参数说明了希望从命令中得到SD响应类型。
数据可以通过块传输给SD卡。pBlockBuffer参数是指向一个缓冲区的指针,这缓冲区需要足够大去存储指定块的数量。
一些命令类型需要在总线上专用的操作。客户端驱动可以使用总线请求标志来实现。
同步和异步总线请求功能包含可选的Flags参数。这些Flags参数允许SD客户端在总线上提出一些特殊操作的请求,特殊的命令类型。如果总线驱动没有请求特殊操作,这个参数将被设置为0。
同步总线请求
从一些SD命令,比如SET_BLOCKLEN,这里没有强制执行异步传输。一般来说,提供同步总线请求。客户端驱动直到总线请求程序段完成。SDSynchronousBusRequest函数被使用在这些请求上面。
pResponse参数用来从SD卡获得相应。这相应将包含一些命令数据的错误状态。
异步总线请求。
通过使用异步总线请求,客户端驱动可以发出多总线请求,不需要等待先前的请求执行完成。总线请求队列在总线驱动内部,等待SD总线可用。
可以使用同步请求,客户端驱动可以最大使用可用的SD总线宽度。当SDIO网络适配器忙着传输包时,客户端驱动可以格式化下一个将要被发送的包。
当每一个请求完成,总线驱动调用回调程序给客户端驱动。回调程序可以通知主客户端驱动线程请求已经完成。
SDBusRequest
一个异步总线请求通过调用SDBusRequest函数。pCallback参数是一个指向回调函数的指针,当总线请求完成,它将被总线驱动的线程调用。RequestParam参数是可选的,它通过回调程序为总线请求。
ppRequest参数被使用去获得一个指向新创建的总线请求结构。通常,客户端驱动将保存这个指针去使能请求的取消和删除。这不是强制性的,指针是通过回调函数在请求完成之上。
SDFreeBusRequest
客户驱动为了去释放存储分配为新的总线请求。当请求完成的时候,它可以去调用SDFreeBusRequest函数。在请求成功,错误或取消的时候。
SDCancelBusRequest
客户端驱动可以去取消任何的总线请求,调用SDCancelBusRequest函数。如果总线请求还没被发送,它将从队列中移开。回调函数必须释放总线请求,SD_API_STATUS_CANCELED状态表示请求被取消。通常情况厦,客户端驱动将等待知道所有请求都完成。
单功能卡,多功能卡,和结合卡
SD卡可以分城下面3种类型:
单功能卡,在总线驱动内只有一种设备操作,只加载一种客户端驱动。
多功能卡,执行超过一种IO功能。
结合卡,执行一种或多种IO功能,包含SD存储功能。
单功能卡
单功能卡可以可以作为SD存储客户端驱动或单功能的SDIO设备。客户端驱动去加载要通过注册表查询。一个单功能的SDIO设备在总线驱动内只有一种设备操作,只加载一种客户端驱动。
SD存储客户端驱动
下面的注册表需要去加载一个SD存储客户端驱动的入口
[HKEY_LOCAL_MACHINE\Drivers\SDCARD\ClientDrivers\Class\SDMemory_Class]
下面注册表可以使用为加载一个自定义的客户端驱动的默认设置
[HKEY_LOCAL_MACHINE\Drivers\SDCARD\ClientDrivers\Custom\CID-M-AA-PPPPP]
M的值是厂商的ID,AA值是OEM使用的ID为两个字节。PPPPP值是产品名为5个字符。
SDIO Device
下面注册表是加载SDIO设备的入口
[HKEY_LOCAL_MACHINE\Drivers\SDCARD\ClientDrivers\Class\SDIO_Class\]
下面是加载自定义的SDIO设备的入口
[HKEY_LOCAL_MACHINE\Drivers\SDCARD\ClientDrivers\Custom\MANF--CARDID--FUNC-]
厂商ID和卡ID值将被存储在十六进制中。function可以被一个从1-7的值。