Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

563 lines
16 KiB

  1. /*++
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. card.c
  5. Abstract:
  6. This module contains code to handle SD card operations like identification
  7. and configuration.
  8. Authors:
  9. Neil Sandlin (neilsa) 1-Jan-2002
  10. Environment:
  11. Kernel mode only
  12. Notes:
  13. Revision History:
  14. --*/
  15. #include "pch.h"
  16. //
  17. // Internal References
  18. //
  19. VOID
  20. SdbusReadCommonCIS(
  21. IN PFDO_EXTENSION FdoExtension,
  22. IN PSD_CARD_DATA CardData
  23. );
  24. VOID
  25. SdbusReadFunctionCIS(
  26. IN PFDO_EXTENSION FdoExtension,
  27. IN PSD_FUNCTION_DATA FunctionData
  28. );
  29. NTSTATUS
  30. SdbusGetCardConfigData(
  31. IN PFDO_EXTENSION FdoExtension,
  32. OUT PSD_CARD_DATA *pCardData
  33. )
  34. /*++
  35. Routine Description:
  36. This enumerates the IO card present in the given SDBUS controller,
  37. and updates the internal structures to reflect the new card state.
  38. Arguments
  39. Return value
  40. Status
  41. --*/
  42. {
  43. NTSTATUS status = STATUS_UNSUCCESSFUL;
  44. ULONG i;
  45. ULONG relativeAddr = FdoExtension->RelativeAddr;
  46. PSD_CARD_DATA cardData = NULL;
  47. ULONG responseBuffer[4];
  48. try{
  49. if ((FdoExtension->numFunctions!=0) || FdoExtension->memFunction) {
  50. PSD_FUNCTION_DATA functionData;
  51. DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x IO functions found=%d, memFunction=%s\n",
  52. FdoExtension->DeviceObject, FdoExtension->numFunctions,
  53. (FdoExtension->memFunction ? "TRUE" : "FALSE")));
  54. //
  55. // At this point, it would be good to verify if the previous enumeration matches
  56. // the present one. This hokey mechanism is just to get something working.
  57. // ISSUE: NEED TO IMPLEMENT: swapping SD cards while hibernated
  58. //
  59. cardData = ExAllocatePool(NonPagedPool, sizeof(SD_CARD_DATA));
  60. if (cardData == NULL) {
  61. status = STATUS_INSUFFICIENT_RESOURCES;
  62. leave;
  63. }
  64. RtlZeroMemory(cardData, sizeof(SD_CARD_DATA));
  65. if (FdoExtension->memFunction) {
  66. PUCHAR pResponse, pTarget;
  67. UCHAR j;
  68. cardData->SdCid = FdoExtension->SdCid;
  69. cardData->SdCsd = FdoExtension->SdCsd;
  70. for (j=0; j<5; j++) {
  71. UCHAR data = cardData->SdCid.ProductName[4-j];
  72. if ((data <= ' ') || data > 0x7F) {
  73. break;
  74. }
  75. cardData->ProductName[j] = data;
  76. }
  77. }
  78. if (FdoExtension->memFunction) {
  79. //
  80. // Read the SCR register
  81. //
  82. SdbusSendCmdSynchronous(FdoExtension, SDCMD_APP_CMD, SDCMD_RESP_1, relativeAddr, 0, NULL, 0);
  83. //ISSUE: How do I get the data?
  84. SdbusSendCmdSynchronous(FdoExtension, SDCMD_SEND_SCR, SDCMD_RESP_1, 0, SDCMDF_ACMD, NULL, 0);
  85. }
  86. if (FdoExtension->numFunctions) {
  87. UCHAR function;
  88. (*(FdoExtension->FunctionBlock->SetFunctionType))(FdoExtension, SDBUS_FUNCTION_TYPE_IO);
  89. // This command seems to be needed to start reading tuples, but breaks memory
  90. // enumeration (gets bad Cid, Csd)... need to figure that out later, since that
  91. // would imply that a combo card wouldn't work.
  92. SdbusReadCommonCIS(FdoExtension, cardData);
  93. for (function=1; function<=FdoExtension->numFunctions; function++) {
  94. functionData = ExAllocatePool(NonPagedPool, sizeof(SD_FUNCTION_DATA));
  95. if (functionData == NULL) {
  96. status = STATUS_INSUFFICIENT_RESOURCES;
  97. leave;
  98. }
  99. RtlZeroMemory(functionData, sizeof(SD_FUNCTION_DATA));
  100. functionData->Function = function;
  101. SdbusReadFunctionCIS(FdoExtension, functionData);
  102. functionData->Next = cardData->FunctionData;
  103. cardData->FunctionData = functionData;
  104. }
  105. }
  106. status = STATUS_SUCCESS;
  107. }
  108. } finally {
  109. if (!NT_SUCCESS(status)) {
  110. SdbusCleanupCardData(cardData);
  111. } else {
  112. *pCardData = cardData;
  113. }
  114. }
  115. return status;
  116. }
  117. VOID
  118. SdbusCleanupCardData(
  119. IN PSD_CARD_DATA CardData
  120. )
  121. {
  122. PSD_FUNCTION_DATA functionData;
  123. PSD_FUNCTION_DATA nextFunctionData;
  124. if (CardData != NULL) {
  125. for (functionData = CardData->FunctionData; functionData != NULL; functionData = nextFunctionData) {
  126. nextFunctionData = functionData->Next;
  127. ExFreePool(functionData);
  128. }
  129. ExFreePool(CardData);
  130. }
  131. }
  132. UCHAR
  133. SdbusReadCIAChar(
  134. IN PFDO_EXTENSION FdoExtension,
  135. IN ULONG ciaPtr
  136. )
  137. {
  138. SD_RW_DIRECT_ARGUMENT argument;
  139. UCHAR response;
  140. argument.u.AsULONG = 0;
  141. argument.u.bits.Address = ciaPtr;
  142. SdbusSendCmdSynchronous(FdoExtension,
  143. SDCMD_IO_RW_DIRECT,
  144. SDCMD_RESP_5,
  145. argument.u.AsULONG,
  146. 0,
  147. &response,
  148. sizeof(UCHAR));
  149. return response;
  150. }
  151. VOID
  152. SdbusWriteCIAChar(
  153. IN PFDO_EXTENSION FdoExtension,
  154. IN ULONG ciaPtr,
  155. IN UCHAR data
  156. )
  157. {
  158. SD_RW_DIRECT_ARGUMENT argument;
  159. ULONG responseBuffer[4];
  160. argument.u.AsULONG = 0;
  161. argument.u.bits.Address = ciaPtr;
  162. argument.u.bits.Data = data;
  163. argument.u.bits.WriteToDevice = 1;
  164. SdbusSendCmdSynchronous(FdoExtension,
  165. SDCMD_IO_RW_DIRECT,
  166. SDCMD_RESP_5,
  167. argument.u.AsULONG,
  168. 0,
  169. NULL,
  170. 0);
  171. }
  172. USHORT
  173. SdbusReadCIAWord(
  174. IN PFDO_EXTENSION FdoExtension,
  175. IN ULONG ciaPtr
  176. )
  177. {
  178. USHORT data;
  179. data = (USHORT) SdbusReadCIAChar(FdoExtension, ciaPtr+1) << 8;
  180. data |= (USHORT) SdbusReadCIAChar(FdoExtension, ciaPtr);
  181. return data;
  182. }
  183. ULONG
  184. SdbusReadCIADword(
  185. IN PFDO_EXTENSION FdoExtension,
  186. IN ULONG ciaPtr
  187. )
  188. {
  189. ULONG data;
  190. data = (ULONG) SdbusReadCIAChar(FdoExtension, ciaPtr+3) << 24;
  191. data |= (ULONG) SdbusReadCIAChar(FdoExtension, ciaPtr+2) << 16;
  192. data |= (ULONG) SdbusReadCIAChar(FdoExtension, ciaPtr+1) << 8;
  193. data |= (ULONG) SdbusReadCIAChar(FdoExtension, ciaPtr);
  194. return data;
  195. }
  196. VOID
  197. SdbusReadCommonCIS(
  198. IN PFDO_EXTENSION FdoExtension,
  199. IN PSD_CARD_DATA CardData
  200. )
  201. {
  202. UCHAR cmd, link;
  203. UCHAR i;
  204. ULONG tupleCount = 0;
  205. USHORT manfCode, manfInf;
  206. UCHAR funcId;
  207. UCHAR funcEType;
  208. ULONG cisPtr;
  209. ULONG index;
  210. ULONG endStr;
  211. UCHAR data;
  212. CardData->CardCapabilities = SdbusReadCIAChar(FdoExtension,8);
  213. //
  214. // Get the common cisptr from the CCCR
  215. //
  216. cisPtr = ((SdbusReadCIAChar(FdoExtension, SD_CCCR_CIS_POINTER+2) << 16) +
  217. (SdbusReadCIAChar(FdoExtension, SD_CCCR_CIS_POINTER+1) << 8) +
  218. SdbusReadCIAChar(FdoExtension, SD_CCCR_CIS_POINTER));
  219. DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x cisPtr=%.06x\n",
  220. FdoExtension->DeviceObject, cisPtr));
  221. cmd = SdbusReadCIAChar(FdoExtension, cisPtr);
  222. link = SdbusReadCIAChar(FdoExtension, cisPtr+1);
  223. while((cmd != CISTPL_END) && (cmd != CISTPL_NULL)) {
  224. tupleCount++;
  225. DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x CIS %.06x cmd=%.02x link=%.02x\n",
  226. FdoExtension->DeviceObject, cisPtr, cmd, link));
  227. switch(cmd) {
  228. case CISTPL_MANFID:
  229. if (link < 4) {
  230. DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_MANFID invalid link %x\n",
  231. FdoExtension->DeviceObject, link));
  232. return;
  233. }
  234. CardData->MfgId = SdbusReadCIAWord(FdoExtension, cisPtr+2);
  235. CardData->MfgInfo = SdbusReadCIAWord(FdoExtension, cisPtr+4);
  236. DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x CISTPL_MANFID code=%x, inf=%x\n",
  237. FdoExtension->DeviceObject, CardData->MfgId, CardData->MfgInfo));
  238. break;
  239. case CISTPL_VERS_1:
  240. index = cisPtr+4;
  241. endStr = index + (link - 2);
  242. i = 0;
  243. data = SdbusReadCIAChar(FdoExtension, index++);
  244. while (data) {
  245. if (index > endStr) {
  246. DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_VERS_1 parse error\n",
  247. FdoExtension->DeviceObject));
  248. return;
  249. }
  250. if (data >= ' ' && data < 0x7F) {
  251. CardData->MfgText[i++] = data;
  252. }
  253. data = SdbusReadCIAChar(FdoExtension, index++);
  254. }
  255. CardData->MfgText[i] = 0;
  256. i = 0;
  257. data = SdbusReadCIAChar(FdoExtension, index++);
  258. while (data) {
  259. if (index > endStr) {
  260. DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_VERS_1 parse error\n",
  261. FdoExtension->DeviceObject));
  262. return;
  263. }
  264. if (data >= ' ' && data < 0x7F) {
  265. CardData->ProductText[i++] = data;
  266. }
  267. data = SdbusReadCIAChar(FdoExtension, index++);
  268. }
  269. CardData->ProductText[i] = 0;
  270. DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x CISTPL_VERS_1 %s %s\n",
  271. FdoExtension->DeviceObject, CardData->MfgText, CardData->ProductText));
  272. break;
  273. case CISTPL_FUNCID:
  274. if (link != 2) {
  275. DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_FUNCID invalid link %x\n",
  276. FdoExtension->DeviceObject, link));
  277. return;
  278. }
  279. funcId = SdbusReadCIAChar(FdoExtension, cisPtr+2);
  280. if (funcId != 12) {
  281. DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_FUNCID invalid id %x\n",
  282. FdoExtension->DeviceObject, funcId));
  283. return;
  284. }
  285. break;
  286. case CISTPL_FUNCE:
  287. funcEType = SdbusReadCIAChar(FdoExtension, cisPtr+2);
  288. if (funcEType == 0) {
  289. USHORT blkSize;
  290. UCHAR tranSpeed;
  291. if (link != 4) {
  292. DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_FUNCE invalid type0 link %x\n",
  293. FdoExtension->DeviceObject, link));
  294. return;
  295. }
  296. blkSize = SdbusReadCIAWord(FdoExtension, cisPtr+3);
  297. tranSpeed = SdbusReadCIAChar(FdoExtension, cisPtr+5);
  298. DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x CISTPL_FUNCE 0 blksize %04x transpeed %02x\n",
  299. FdoExtension->DeviceObject, blkSize, tranSpeed));
  300. } else {
  301. DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_FUNCE invalid funce type %x\n",
  302. FdoExtension->DeviceObject, funcEType));
  303. return;
  304. }
  305. break;
  306. }
  307. cisPtr += link+2;
  308. cmd = SdbusReadCIAChar(FdoExtension, cisPtr);
  309. link = SdbusReadCIAChar(FdoExtension, cisPtr+1);
  310. }
  311. DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x CIS %.06x cmd=%.02x link=%.02x EXITING %d tuples read\n",
  312. FdoExtension->DeviceObject, cisPtr, cmd, link, tupleCount));
  313. }
  314. VOID
  315. SdbusReadFunctionCIS(
  316. IN PFDO_EXTENSION FdoExtension,
  317. IN PSD_FUNCTION_DATA FunctionData
  318. )
  319. {
  320. UCHAR cmd, link;
  321. UCHAR i;
  322. ULONG tupleCount = 0;
  323. UCHAR funcId;
  324. UCHAR funcEType;
  325. ULONG fbrPtr = FunctionData->Function*0x100;
  326. ULONG cisPtr;
  327. BOOLEAN hasCsa;
  328. UCHAR data;
  329. data = SdbusReadCIAChar(FdoExtension, fbrPtr);
  330. FunctionData->IoDeviceInterface = data & 0xf;
  331. hasCsa = ((data & 0x40) != 0);
  332. cisPtr = ((SdbusReadCIAChar(FdoExtension, fbrPtr + SD_CCCR_CIS_POINTER + 2) << 16) +
  333. (SdbusReadCIAChar(FdoExtension, fbrPtr + SD_CCCR_CIS_POINTER + 1) << 8) +
  334. SdbusReadCIAChar(FdoExtension, fbrPtr + SD_CCCR_CIS_POINTER));
  335. DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x function %d cisPtr=%.06x interfaceCode=%d hasCsa=%s\n",
  336. FdoExtension->DeviceObject, FunctionData->Function, cisPtr, FunctionData->IoDeviceInterface,
  337. hasCsa ? "TRUE" : "FALSE"));
  338. if (!cisPtr || (cisPtr == 0xFFFFFF)) {
  339. return;
  340. }
  341. cmd = SdbusReadCIAChar(FdoExtension, cisPtr);
  342. link = SdbusReadCIAChar(FdoExtension, cisPtr+1);
  343. while((cmd != CISTPL_END) && (cmd != CISTPL_NULL)) {
  344. tupleCount++;
  345. DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x CIS %.06x cmd=%.02x link=%.02x\n",
  346. FdoExtension->DeviceObject, cisPtr, cmd, link));
  347. switch(cmd) {
  348. case CISTPL_FUNCID:
  349. if (link != 2) {
  350. DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_FUNCID invalid link %x\n",
  351. FdoExtension->DeviceObject, link));
  352. return;
  353. }
  354. funcId = SdbusReadCIAChar(FdoExtension, cisPtr+2);
  355. if (funcId != 12) {
  356. DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_FUNCID invalid id %x\n",
  357. FdoExtension->DeviceObject, funcId));
  358. return;
  359. }
  360. break;
  361. case CISTPL_FUNCE:
  362. funcEType = SdbusReadCIAChar(FdoExtension, cisPtr+2);
  363. if (funcEType == 1) {
  364. UCHAR fInfo, ioRev, csaProp, opMin, opAvg, opMax, sbMin, sbAvg, sbMax;
  365. USHORT blkSize, minBw, optBw;
  366. ULONG cardPsn, csaSize, ocr;
  367. if (link != 0x1C) {
  368. DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_FUNCE invalid type1 link %x\n",
  369. FdoExtension->DeviceObject, link));
  370. return;
  371. }
  372. fInfo = SdbusReadCIAChar(FdoExtension, cisPtr+3);
  373. ioRev = SdbusReadCIAChar(FdoExtension, cisPtr+4);
  374. cardPsn = SdbusReadCIADword(FdoExtension, cisPtr+5);
  375. csaSize = SdbusReadCIADword(FdoExtension, cisPtr+9);
  376. csaProp = SdbusReadCIAChar(FdoExtension, cisPtr+13);
  377. blkSize = SdbusReadCIAWord(FdoExtension, cisPtr+14);
  378. ocr = SdbusReadCIADword(FdoExtension, cisPtr+16);
  379. opMin = SdbusReadCIAChar(FdoExtension, cisPtr+20);
  380. opAvg = SdbusReadCIAChar(FdoExtension, cisPtr+21);
  381. opMax = SdbusReadCIAChar(FdoExtension, cisPtr+22);
  382. sbMin = SdbusReadCIAChar(FdoExtension, cisPtr+23);
  383. sbAvg = SdbusReadCIAChar(FdoExtension, cisPtr+24);
  384. sbMax = SdbusReadCIAChar(FdoExtension, cisPtr+25);
  385. minBw = SdbusReadCIAWord(FdoExtension, cisPtr+26);
  386. optBw = SdbusReadCIAWord(FdoExtension, cisPtr+28);
  387. DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x CISTPL_FUNCE 1\n",
  388. FdoExtension->DeviceObject));
  389. } else {
  390. DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_FUNCE invalid funce type %x\n",
  391. FdoExtension->DeviceObject, funcEType));
  392. return;
  393. }
  394. break;
  395. }
  396. cisPtr += link+2;
  397. cmd = SdbusReadCIAChar(FdoExtension, cisPtr);
  398. link = SdbusReadCIAChar(FdoExtension, cisPtr+1);
  399. }
  400. DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x CIS %.06x cmd=%.02x link=%.02x EXITING %d tuples read\n",
  401. FdoExtension->DeviceObject, cisPtr, cmd, link, tupleCount));
  402. }