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.

685 lines
17 KiB

  1. /*++
  2. Copyright (c) 1991-1998 Microsoft Corporation
  3. Module Name:
  4. pccard.c
  5. Abstract:
  6. Author:
  7. Neil Sandlin (neilsa) 1-Jan-01
  8. Environment:
  9. Kernel mode only.
  10. --*/
  11. #include "pch.h"
  12. NTSTATUS
  13. PcCardReadWrite(
  14. IN PSFFDISK_EXTENSION sffdiskExtension,
  15. IN ULONG startOffset,
  16. IN PVOID UserBuffer,
  17. IN ULONG lengthToCopy,
  18. IN BOOLEAN writeOperation
  19. );
  20. NTSTATUS
  21. PcCardRead(
  22. IN PSFFDISK_EXTENSION sffdiskExtension,
  23. IN PIRP Irp
  24. );
  25. NTSTATUS
  26. PcCardWrite(
  27. IN PSFFDISK_EXTENSION sffdiskExtension,
  28. IN PIRP Irp
  29. );
  30. NTSTATUS
  31. PcCardInitialize(
  32. IN PSFFDISK_EXTENSION sffdiskExtension
  33. );
  34. NTSTATUS
  35. PcCardDeleteDevice(
  36. IN PSFFDISK_EXTENSION sffdiskExtension
  37. );
  38. NTSTATUS
  39. PcCardGetDiskParameters(
  40. IN PSFFDISK_EXTENSION sffdiskExtension
  41. );
  42. BOOLEAN
  43. PcCardIsWriteProtected(
  44. IN PSFFDISK_EXTENSION sffdiskExtension
  45. );
  46. ULONG
  47. PcCardGetCapacityFromCIS(
  48. IN PSFFDISK_EXTENSION sffdiskExtension
  49. );
  50. ULONG
  51. PcCardGetCapacityFromBootSector(
  52. IN PSFFDISK_EXTENSION sffdiskExtension
  53. );
  54. ULONG
  55. PcCardProbeForCapacity(
  56. IN PSFFDISK_EXTENSION sffdiskExtension
  57. );
  58. #ifdef ALLOC_PRAGMA
  59. #pragma alloc_text(PAGE,PcCardRead)
  60. #pragma alloc_text(PAGE,PcCardWrite)
  61. #pragma alloc_text(PAGE,PcCardInitialize)
  62. #pragma alloc_text(PAGE,PcCardDeleteDevice)
  63. #pragma alloc_text(PAGE,PcCardGetDiskParameters)
  64. #pragma alloc_text(PAGE,PcCardIsWriteProtected)
  65. #pragma alloc_text(PAGE,PcCardGetCapacityFromCIS)
  66. #pragma alloc_text(PAGE,PcCardGetCapacityFromBootSector)
  67. #pragma alloc_text(PAGE,PcCardProbeForCapacity)
  68. #endif
  69. SFFDISK_FUNCTION_BLOCK PcCardSupportFns = {
  70. PcCardInitialize,
  71. PcCardDeleteDevice,
  72. PcCardGetDiskParameters,
  73. PcCardIsWriteProtected,
  74. PcCardRead,
  75. PcCardWrite
  76. };
  77. //
  78. // macros for ReadWriteMemory
  79. //
  80. #define SFFDISK_READ(Extension, Offset, Buffer, Size) \
  81. PcCardReadWrite(Extension, Offset, Buffer, Size, FALSE)
  82. #define SFFDISK_WRITE(Extension, Offset, Buffer, Size) \
  83. PcCardReadWrite(Extension, Offset, Buffer, Size, TRUE)
  84. NTSTATUS
  85. PcCardInitialize(
  86. IN PSFFDISK_EXTENSION sffdiskExtension
  87. )
  88. /*++
  89. Routine Description:
  90. Arguments:
  91. Return Value:
  92. --*/
  93. {
  94. NTSTATUS status = STATUS_SUCCESS;
  95. KEVENT event;
  96. IO_STATUS_BLOCK statusBlock;
  97. PIRP irp;
  98. PIO_STACK_LOCATION irpSp;
  99. //
  100. // Get pcmcia interfaces
  101. //
  102. KeInitializeEvent(&event, NotificationEvent, FALSE);
  103. irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, sffdiskExtension->UnderlyingPDO,
  104. NULL, 0, 0, &event, &statusBlock);
  105. if (!irp) {
  106. return STATUS_INSUFFICIENT_RESOURCES;
  107. }
  108. irp->IoStatus.Status = STATUS_NOT_SUPPORTED ;
  109. irp->IoStatus.Information = 0;
  110. irpSp = IoGetNextIrpStackLocation(irp);
  111. irpSp->MinorFunction = IRP_MN_QUERY_INTERFACE;
  112. irpSp->Parameters.QueryInterface.InterfaceType= &GUID_PCMCIA_INTERFACE_STANDARD;
  113. irpSp->Parameters.QueryInterface.Size = sizeof(PCMCIA_INTERFACE_STANDARD);
  114. irpSp->Parameters.QueryInterface.Version = 1;
  115. irpSp->Parameters.QueryInterface.Interface = (PINTERFACE) &sffdiskExtension->PcmciaInterface;
  116. status = IoCallDriver(sffdiskExtension->UnderlyingPDO, irp);
  117. if (status == STATUS_PENDING) {
  118. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  119. status = statusBlock.Status;
  120. }
  121. if (!NT_SUCCESS(status)) {
  122. return status;
  123. }
  124. KeInitializeEvent(&event, NotificationEvent, FALSE);
  125. irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, sffdiskExtension->UnderlyingPDO,
  126. NULL, 0, 0, &event, &statusBlock);
  127. if (!irp) {
  128. return STATUS_INSUFFICIENT_RESOURCES;
  129. }
  130. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  131. irp->IoStatus.Information = 0;
  132. irpSp = IoGetNextIrpStackLocation(irp);
  133. irpSp->MinorFunction = IRP_MN_QUERY_INTERFACE;
  134. // irpSp->Parameters.QueryInterface.InterfaceType= &GUID_PCMCIA_BUS_INTERFACE_STANDARD;
  135. irpSp->Parameters.QueryInterface.InterfaceType= &GUID_BUS_INTERFACE_STANDARD;
  136. // irpSp->Parameters.QueryInterface.Size = sizeof(PCMCIA_BUS_INTERFACE_STANDARD);
  137. irpSp->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
  138. irpSp->Parameters.QueryInterface.Version = 1;
  139. irpSp->Parameters.QueryInterface.Interface = (PINTERFACE) &sffdiskExtension->PcmciaBusInterface;
  140. status = IoCallDriver(sffdiskExtension->UnderlyingPDO, irp);
  141. if (status == STATUS_PENDING) {
  142. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  143. status = statusBlock.Status;
  144. }
  145. return status;
  146. }
  147. NTSTATUS
  148. PcCardDeleteDevice(
  149. IN PSFFDISK_EXTENSION sffdiskExtension
  150. )
  151. {
  152. return STATUS_SUCCESS;
  153. }
  154. BOOLEAN
  155. PcCardIsWriteProtected(
  156. IN PSFFDISK_EXTENSION sffdiskExtension
  157. )
  158. /*++
  159. Routine Description:
  160. Arguments:
  161. Return Value:
  162. --*/
  163. {
  164. return((sffdiskExtension->PcmciaInterface.IsWriteProtected)(sffdiskExtension->UnderlyingPDO));
  165. }
  166. NTSTATUS
  167. PcCardRead(
  168. IN PSFFDISK_EXTENSION sffdiskExtension,
  169. IN PIRP Irp
  170. )
  171. /*++
  172. Routine Description:
  173. This routine is called to read/write data to/from the memory card.
  174. It breaks the request into pieces based on the size of our memory
  175. window.
  176. Arguments:
  177. DeviceObject - a pointer to the object that represents the device
  178. that I/O is to be done on.
  179. Irp - a pointer to the I/O Request Packet for this request.
  180. Return Value:
  181. STATUS_SUCCESS if the packet was successfully read or written; the
  182. appropriate error is propogated otherwise.
  183. --*/
  184. {
  185. NTSTATUS status = STATUS_SUCCESS;
  186. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
  187. status = SFFDISK_READ(sffdiskExtension,
  188. irpSp->Parameters.Read.ByteOffset.LowPart,
  189. MmGetSystemAddressForMdl(Irp->MdlAddress),
  190. irpSp->Parameters.Read.Length);
  191. return status;
  192. }
  193. NTSTATUS
  194. PcCardWrite(
  195. IN PSFFDISK_EXTENSION sffdiskExtension,
  196. IN PIRP Irp
  197. )
  198. /*++
  199. Routine Description:
  200. This routine is called to read/write data to/from the memory card.
  201. It breaks the request into pieces based on the size of our memory
  202. window.
  203. Arguments:
  204. DeviceObject - a pointer to the object that represents the device
  205. that I/O is to be done on.
  206. Irp - a pointer to the I/O Request Packet for this request.
  207. Return Value:
  208. STATUS_SUCCESS if the packet was successfully read or written; the
  209. appropriate error is propogated otherwise.
  210. --*/
  211. {
  212. NTSTATUS status = STATUS_SUCCESS;
  213. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
  214. status = SFFDISK_WRITE(sffdiskExtension,
  215. irpSp->Parameters.Write.ByteOffset.LowPart,
  216. MmGetSystemAddressForMdl(Irp->MdlAddress),
  217. irpSp->Parameters.Write.Length);
  218. return status;
  219. }
  220. NTSTATUS
  221. PcCardReadWrite(
  222. IN PSFFDISK_EXTENSION sffdiskExtension,
  223. IN ULONG startOffset,
  224. IN PVOID UserBuffer,
  225. IN ULONG lengthToCopy,
  226. IN BOOLEAN writeOperation
  227. )
  228. /*++
  229. Routine Description:
  230. This routine is called to read/write data to/from the memory card.
  231. It breaks the request into pieces based on the size of our memory
  232. window.
  233. Arguments:
  234. DeviceObject - a pointer to the object that represents the device
  235. that I/O is to be done on.
  236. Irp - a pointer to the I/O Request Packet for this request.
  237. Return Value:
  238. STATUS_SUCCESS if the packet was successfully read or written; the
  239. appropriate error is propogated otherwise.
  240. --*/
  241. {
  242. NTSTATUS status = STATUS_SUCCESS;
  243. PCHAR userBuffer = UserBuffer;
  244. ULONG windowOffset;
  245. ULONG singleCopyLength;
  246. BOOLEAN bSuccess;
  247. ULONGLONG CardBase;
  248. if (writeOperation && PcCardIsWriteProtected(sffdiskExtension)) {
  249. return STATUS_MEDIA_WRITE_PROTECTED;
  250. }
  251. // pcmcia controller is 4k page granular
  252. windowOffset = startOffset % 4096;
  253. CardBase = startOffset - windowOffset;
  254. while(lengthToCopy) {
  255. bSuccess = (sffdiskExtension->PcmciaInterface.ModifyMemoryWindow) (
  256. sffdiskExtension->UnderlyingPDO,
  257. sffdiskExtension->HostBase,
  258. CardBase,
  259. TRUE,
  260. sffdiskExtension->MemoryWindowSize,
  261. 0, 0, FALSE);
  262. if (!bSuccess) {
  263. status = STATUS_DEVICE_NOT_READY;
  264. break;
  265. }
  266. singleCopyLength = (lengthToCopy <= (sffdiskExtension->MemoryWindowSize - windowOffset)) ?
  267. lengthToCopy :
  268. (sffdiskExtension->MemoryWindowSize - windowOffset);
  269. SffDiskDump(SFFDISKRW,("SffDisk: COPY %.8x (devbase %.8x) %s buffer %.8x, len %x\n",
  270. sffdiskExtension->MemoryWindowBase+windowOffset,
  271. (ULONG)(CardBase+windowOffset),
  272. (writeOperation ? "<=" : "=>"),
  273. userBuffer,
  274. singleCopyLength));
  275. if (writeOperation) {
  276. RtlCopyMemory(sffdiskExtension->MemoryWindowBase+windowOffset,
  277. userBuffer,
  278. singleCopyLength);
  279. } else {
  280. RtlCopyMemory(userBuffer,
  281. sffdiskExtension->MemoryWindowBase+windowOffset,
  282. singleCopyLength);
  283. }
  284. lengthToCopy -= singleCopyLength;
  285. userBuffer += singleCopyLength;
  286. CardBase += sffdiskExtension->MemoryWindowSize;
  287. windowOffset = 0;
  288. }
  289. return status;
  290. }
  291. NTSTATUS
  292. PcCardGetDiskParameters(
  293. IN PSFFDISK_EXTENSION sffdiskExtension
  294. )
  295. /*++
  296. Routine Description:
  297. Arguments:
  298. device extension for the card
  299. Return Value:
  300. --*/
  301. {
  302. ULONG capacity;
  303. capacity = PcCardGetCapacityFromCIS(sffdiskExtension);
  304. if (!capacity) {
  305. capacity = PcCardGetCapacityFromBootSector(sffdiskExtension);
  306. if (!capacity) {
  307. capacity = PcCardProbeForCapacity(sffdiskExtension);
  308. }
  309. }
  310. if (!capacity) {
  311. return STATUS_UNRECOGNIZED_MEDIA;
  312. }
  313. sffdiskExtension->ByteCapacity = capacity;
  314. sffdiskExtension->Cylinders = sffdiskExtension->ByteCapacity / (8 * 2 * 512);
  315. sffdiskExtension->TracksPerCylinder = 2;
  316. sffdiskExtension->SectorsPerTrack = 8;
  317. sffdiskExtension->BytesPerSector = 512;
  318. return STATUS_SUCCESS;
  319. }
  320. ULONG
  321. PcCardGetCapacityFromBootSector(
  322. IN PSFFDISK_EXTENSION sffdiskExtension
  323. )
  324. /*++
  325. Routine Description:
  326. Arguments:
  327. device extension for the card
  328. Return Value:
  329. --*/
  330. {
  331. NTSTATUS status;
  332. BOOT_SECTOR_INFO BootSector;
  333. ULONG capacity = 0;
  334. status = SFFDISK_READ(sffdiskExtension, 0, &BootSector, sizeof(BootSector));
  335. if (NT_SUCCESS(status)) {
  336. #define BYTES_PER_SECTOR 512
  337. //
  338. // see if this really looks like a boot sector
  339. // These are the same tests done in the win9x sram support
  340. //
  341. if ((BootSector.JumpByte == 0xE9 || BootSector.JumpByte == 0xEB) &&
  342. BootSector.BytesPerSector == BYTES_PER_SECTOR &&
  343. BootSector.SectorsPerCluster != 0 &&
  344. BootSector.ReservedSectors == 1 &&
  345. (BootSector.NumberOfFATs == 1 || BootSector.NumberOfFATs == 2) &&
  346. BootSector.RootEntries != 0 && (BootSector.RootEntries & 15) == 0 &&
  347. (BootSector.TotalSectors != 0 || BootSector.BigTotalSectors != 0) &&
  348. BootSector.SectorsPerFAT != 0 &&
  349. BootSector.SectorsPerTrack != 0 &&
  350. BootSector.Heads != 0 &&
  351. BootSector.MediaDescriptor >= 0xF0) {
  352. //
  353. // Finally it appears valid, return total size of region.
  354. //
  355. capacity = BootSector.TotalSectors * BYTES_PER_SECTOR;
  356. }
  357. }
  358. return capacity;
  359. }
  360. ULONG
  361. PcCardGetCapacityFromCIS(
  362. IN PSFFDISK_EXTENSION sffdiskExtension
  363. )
  364. /*++
  365. Routine Description:
  366. This is a quick and dirty routine to read the tuples of the card, if they
  367. exist, to get the capacity.
  368. Arguments:
  369. device extension for the card
  370. Return Value:
  371. The # of bytes of memory on the device
  372. --*/
  373. {
  374. UCHAR tupleData[16];
  375. ULONG bytesRead;
  376. ULONG dataCount;
  377. ULONG unitSize;
  378. ULONG unitCount;
  379. ULONG i;
  380. //
  381. // get device capacity
  382. // all this stuff should really be in the bus driver
  383. //
  384. bytesRead = (sffdiskExtension->PcmciaBusInterface.GetBusData)(sffdiskExtension->UnderlyingPDO,
  385. PCCARD_ATTRIBUTE_MEMORY,
  386. tupleData,
  387. 0,
  388. 16);
  389. if ((bytesRead != 16) || (tupleData[0] != 1)){
  390. return 0;
  391. }
  392. dataCount = (ULONG)tupleData[1];
  393. if ((dataCount < 2) || (dataCount>14)){
  394. return 0;
  395. }
  396. i = 3;
  397. if ((tupleData[2] & 7) == 7) {
  398. while(tupleData[i] & 0x80) {
  399. if ((i-2) > dataCount) {
  400. return 0;
  401. }
  402. i++;
  403. }
  404. }
  405. if ((tupleData[i]&7) == 7) {
  406. return 0;
  407. }
  408. unitSize = 512 << ((tupleData[i]&7)*2);
  409. unitCount = (tupleData[i]>>3)+1;
  410. return(unitCount * unitSize);
  411. }
  412. ULONG
  413. PcCardProbeForCapacity(
  414. IN PSFFDISK_EXTENSION sffdiskExtension
  415. )
  416. /*++
  417. Routine Description:
  418. Since we were unable to determine the card capacity through other means,
  419. here we actually write stuff out on the card to check how big it is.
  420. This algorithm for testing the card capacity was ported from win9x.
  421. Arguments:
  422. device extension for the card
  423. Return Value:
  424. byte capacity of device
  425. --*/
  426. {
  427. NTSTATUS status;
  428. ULONG capacity = 0;
  429. USHORT origValue, ChkValue, StartValue;
  430. USHORT mcSig = 'Mc';
  431. USHORT zeroes = 0;
  432. #define SRAM_BLK_SIZE (16*1024)
  433. ULONG CardOff = SRAM_BLK_SIZE;
  434. USHORT CurValue;
  435. if ((sffdiskExtension->PcmciaInterface.IsWriteProtected)(sffdiskExtension->UnderlyingPDO)) {
  436. return 0;
  437. }
  438. //
  439. //
  440. if (!NT_SUCCESS(SFFDISK_READ (sffdiskExtension, 0, &origValue, sizeof(origValue))) ||
  441. !NT_SUCCESS(SFFDISK_WRITE(sffdiskExtension, 0, &mcSig, sizeof(mcSig))) ||
  442. !NT_SUCCESS(SFFDISK_READ (sffdiskExtension, 0, &ChkValue, sizeof(ChkValue)))) {
  443. return 0;
  444. }
  445. if (ChkValue != mcSig) {
  446. //
  447. // not sram
  448. //
  449. return 0;
  450. }
  451. for (;;) {
  452. if (!NT_SUCCESS(SFFDISK_READ (sffdiskExtension, CardOff, &CurValue, sizeof(CurValue))) ||
  453. !NT_SUCCESS(SFFDISK_WRITE(sffdiskExtension, CardOff, &zeroes, sizeof(zeroes))) ||
  454. !NT_SUCCESS(SFFDISK_READ (sffdiskExtension, CardOff, &ChkValue, sizeof(ChkValue))) ||
  455. !NT_SUCCESS(SFFDISK_READ (sffdiskExtension, 0, &StartValue, sizeof(StartValue)))) {
  456. break;
  457. }
  458. // We stop when either we can't write 0 anymore or the 0
  459. // has wrapped over the 0x9090 at card offset 0
  460. if (ChkValue != zeroes || StartValue == zeroes) {
  461. capacity = CardOff;
  462. break;
  463. }
  464. // Restore the saved value from the start of the block.
  465. if (!NT_SUCCESS(SFFDISK_WRITE(sffdiskExtension, CardOff, &CurValue, sizeof(CurValue)))) {
  466. break;
  467. }
  468. CardOff += SRAM_BLK_SIZE; // increment to the next block
  469. }
  470. //
  471. // try to restore original value
  472. //
  473. SFFDISK_WRITE(sffdiskExtension, 0, &origValue, sizeof(origValue));
  474. return capacity;
  475. }