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.

1036 lines
31 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. intrface.c
  5. Abstract:
  6. This module contains the external interfaces of the
  7. pcmcia driver
  8. Author:
  9. Neil Sandlin (neilsa) 3-Mar-1999
  10. Environment:
  11. Kernel mode
  12. Revision History :
  13. --*/
  14. #include "pch.h"
  15. //
  16. // Internal References
  17. //
  18. ULONG
  19. PcmciaReadCardMemory(
  20. IN PDEVICE_OBJECT Pdo,
  21. IN ULONG WhichSpace,
  22. OUT PUCHAR Buffer,
  23. IN ULONG Offset,
  24. IN ULONG Length
  25. );
  26. ULONG
  27. PcmciaWriteCardMemory(
  28. IN PDEVICE_OBJECT Pdo,
  29. IN ULONG WhichSpace,
  30. IN PUCHAR Buffer,
  31. IN ULONG Offset,
  32. IN ULONG Length
  33. );
  34. NTSTATUS
  35. PcmciaMfEnumerateChild(
  36. IN PPDO_EXTENSION PdoExtension,
  37. IN ULONG Index,
  38. OUT PMF_DEVICE_INFO ChildInfo
  39. );
  40. BOOLEAN
  41. PcmciaModifyMemoryWindow(
  42. IN PDEVICE_OBJECT Pdo,
  43. IN ULONGLONG HostBase,
  44. IN ULONGLONG CardBase,
  45. IN BOOLEAN Enable,
  46. IN ULONG WindowSize OPTIONAL,
  47. IN UCHAR AccessSpeed OPTIONAL,
  48. IN UCHAR BusWidth OPTIONAL,
  49. IN BOOLEAN IsAttributeMemory OPTIONAL
  50. );
  51. BOOLEAN
  52. PcmciaSetVpp(
  53. IN PDEVICE_OBJECT Pdo,
  54. IN UCHAR VppLevel
  55. );
  56. BOOLEAN
  57. PcmciaIsWriteProtected(
  58. IN PDEVICE_OBJECT Pdo
  59. );
  60. BOOLEAN
  61. PcmciaTranslateBusAddress(
  62. IN PVOID Context,
  63. IN PHYSICAL_ADDRESS BusAddress,
  64. IN ULONG Length,
  65. IN OUT PULONG AddressSpace,
  66. OUT PPHYSICAL_ADDRESS TranslatedAddress
  67. );
  68. PDMA_ADAPTER
  69. PcmciaGetDmaAdapter(
  70. IN PVOID Context,
  71. IN struct _DEVICE_DESCRIPTION *DeviceDescriptor,
  72. OUT PULONG NumberOfMapRegisters
  73. );
  74. VOID
  75. PcmciaNop(
  76. IN PVOID Context
  77. );
  78. #ifdef ALLOC_PRAGMA
  79. #pragma alloc_text(PAGE, PcmciaPdoQueryInterface)
  80. #pragma alloc_text(PAGE, PcmciaMfEnumerateChild)
  81. #pragma alloc_text(PAGE, PcmciaNop)
  82. #pragma alloc_text(PAGE, PcmciaGetInterface)
  83. #pragma alloc_text(PAGE, PcmciaUpdateInterruptLine)
  84. #endif
  85. NTSTATUS
  86. PcmciaPdoQueryInterface(
  87. IN PDEVICE_OBJECT Pdo,
  88. IN OUT PIRP Irp
  89. )
  90. /*++
  91. Routine Description:
  92. Fills in the interface requested
  93. Interfaces supported are:
  94. GUID_PCMCIA_INTERFACE_STANDARD:
  95. This returns a pointer to a PCMCIA_INTERFACE_STANDARD structure.
  96. These interfaces are exported solely for flash memory card support as
  97. a means for flash memory card drivers to slide memory windows,
  98. set Vpp levels etc.
  99. GUID_TRANSLATOR_INTERFACE_STANDARD:
  100. This returns an interrupt translator for 16-bit pc-cards which is used
  101. by PnP for translating raw IRQs. We simply return the Hal implemented
  102. translator, since PCMCIA does not need any specific translation. We do not
  103. return a translator if this is for a cardbus card
  104. GUID_PCMCIA_BUS_INTERFACE_STANDARD:
  105. This returns a pointer to a PCMCIA_BUS_INTERFACE_STANDARD structure.
  106. This contains entry points to set/get PCMCIA config data for the pc-card
  107. GUID_MF_ENUMERATION_INTERFACE
  108. For 16-bit multifunction pc-cards returns a pointer to MF_ENUMERATION_INTERFACE
  109. structure which contains entry points to enumerate multifunction children of
  110. the pc-card
  111. Completes the Passed in IRP before returning
  112. Arguments
  113. Pdo - Pointer to the device object
  114. Irp - Pointer to the io request packet
  115. Return Value
  116. STATUS_SUCCESS
  117. STATUS_INSUFFICIENT_RESOURCES - if supplied interface size is
  118. not big enough to accomodate the interface
  119. STATUS_INVALID_PARAMETER_1 - if the requested interface is not supported
  120. by this driver
  121. --*/
  122. {
  123. PIO_STACK_LOCATION irpStack;
  124. PPCMCIA_INTERFACE_STANDARD pcmciaInterfaceStandard;
  125. GUID *interfaceType;
  126. PPDO_EXTENSION pdoExtension;
  127. PFDO_EXTENSION fdoExtension;
  128. NTSTATUS status = STATUS_NOT_SUPPORTED;
  129. PAGED_CODE();
  130. irpStack = IoGetCurrentIrpStackLocation(Irp);
  131. interfaceType = (GUID *) irpStack->Parameters.QueryInterface.InterfaceType;
  132. pdoExtension = Pdo->DeviceExtension;
  133. fdoExtension = pdoExtension->Socket->DeviceExtension;
  134. try{
  135. if (Is16BitCard(pdoExtension) && CompareGuid(interfaceType, (PVOID) &GUID_PCMCIA_INTERFACE_STANDARD)) {
  136. if (irpStack->Parameters.QueryInterface.Size < sizeof(PCMCIA_INTERFACE_STANDARD)) {
  137. status = STATUS_INVALID_PARAMETER;
  138. leave;
  139. }
  140. //
  141. // Ignore the version for the present
  142. //
  143. pcmciaInterfaceStandard = (PPCMCIA_INTERFACE_STANDARD) irpStack->Parameters.QueryInterface.Interface;
  144. RtlZeroMemory(pcmciaInterfaceStandard, sizeof (PCMCIA_INTERFACE_STANDARD));
  145. pcmciaInterfaceStandard->Size = sizeof(PCMCIA_INTERFACE_STANDARD);
  146. pcmciaInterfaceStandard->Version = 1;
  147. pcmciaInterfaceStandard->Context = Pdo;
  148. //
  149. // Fill in the exported functions
  150. //
  151. pcmciaInterfaceStandard->InterfaceReference = (PINTERFACE_REFERENCE) PcmciaNop;
  152. pcmciaInterfaceStandard->InterfaceDereference = (PINTERFACE_DEREFERENCE) PcmciaNop;
  153. pcmciaInterfaceStandard->ModifyMemoryWindow = PcmciaModifyMemoryWindow;
  154. pcmciaInterfaceStandard->SetVpp = PcmciaSetVpp;
  155. pcmciaInterfaceStandard->IsWriteProtected = PcmciaIsWriteProtected;
  156. DebugPrint((PCMCIA_DEBUG_INTERFACE, "pdo %08x returning PCMCIA_INTERFACE_STANDARD\n", Pdo));
  157. status = STATUS_SUCCESS;
  158. } else if (CompareGuid(interfaceType, (PVOID) &GUID_TRANSLATOR_INTERFACE_STANDARD)
  159. && ((ULONG_PTR)irpStack->Parameters.QueryInterface.InterfaceSpecificData ==
  160. CmResourceTypeInterrupt)) {
  161. if ((Is16BitCard(pdoExtension) && !IsSocketFlagSet(pdoExtension->Socket, SOCKET_CB_ROUTE_R2_TO_PCI)) &&
  162. //
  163. // Eject a translator only if the controller is PCI enumerated
  164. // (i.e. we are enumerated by PCI - so we eject a PCI-Isa translator)
  165. //
  166. (CardBusExtension(fdoExtension) || PciPcmciaBridgeExtension(fdoExtension))) {
  167. PTRANSLATOR_INTERFACE translator;
  168. ULONG busNumber;
  169. //
  170. // We need a translator for this PDO (16-bit pc-card) which uses
  171. // ISA resources.
  172. //
  173. status = HalGetInterruptTranslator(
  174. PCIBus,
  175. 0,
  176. Isa,
  177. irpStack->Parameters.QueryInterface.Size,
  178. irpStack->Parameters.QueryInterface.Version,
  179. (PTRANSLATOR_INTERFACE) irpStack->Parameters.QueryInterface.Interface,
  180. &busNumber
  181. );
  182. }
  183. } else if (IsDeviceMultifunction(pdoExtension) && CompareGuid(interfaceType, (PVOID)&GUID_MF_ENUMERATION_INTERFACE)) {
  184. //
  185. // Multifunction enumeration interface
  186. //
  187. PMF_ENUMERATION_INTERFACE mfEnum;
  188. if (irpStack->Parameters.QueryInterface.Size < sizeof(MF_ENUMERATION_INTERFACE)) {
  189. status = STATUS_INVALID_PARAMETER;
  190. leave;
  191. }
  192. mfEnum = (PMF_ENUMERATION_INTERFACE) irpStack->Parameters.QueryInterface.Interface;
  193. mfEnum->Context = pdoExtension;
  194. mfEnum->InterfaceReference = PcmciaNop;
  195. mfEnum->InterfaceDereference = PcmciaNop;
  196. mfEnum->EnumerateChild = (PMF_ENUMERATE_CHILD) PcmciaMfEnumerateChild;
  197. DebugPrint((PCMCIA_DEBUG_INTERFACE, "pdo %08x returning MF_ENUMERATION_INTERFACE\n", Pdo));
  198. status = STATUS_SUCCESS;
  199. } else if (CompareGuid(interfaceType, (PVOID)&GUID_PCMCIA_BUS_INTERFACE_STANDARD)) {
  200. PPCMCIA_BUS_INTERFACE_STANDARD busInterface;
  201. if (irpStack->Parameters.QueryInterface.Size < sizeof(PCMCIA_BUS_INTERFACE_STANDARD)) {
  202. status = STATUS_INVALID_PARAMETER;
  203. leave;
  204. }
  205. busInterface = (PPCMCIA_BUS_INTERFACE_STANDARD) irpStack->Parameters.QueryInterface.Interface;
  206. busInterface->Context = Pdo;
  207. busInterface->InterfaceReference = PcmciaNop;
  208. busInterface->InterfaceDereference = PcmciaNop;
  209. busInterface->ReadConfig = PcmciaReadCardMemory;
  210. busInterface->WriteConfig = PcmciaWriteCardMemory;
  211. DebugPrint((PCMCIA_DEBUG_INTERFACE, "pdo %08x returning PCMCIA_BUS_INTERFACE_STANDARD\n", Pdo));
  212. status = STATUS_SUCCESS;
  213. } else if (Is16BitCard(pdoExtension) && CompareGuid(interfaceType, (PVOID) &GUID_BUS_INTERFACE_STANDARD)) {
  214. PBUS_INTERFACE_STANDARD busInterface = (PBUS_INTERFACE_STANDARD)irpStack->Parameters.QueryInterface.Interface;
  215. if (irpStack->Parameters.QueryInterface.Size < sizeof(BUS_INTERFACE_STANDARD)) {
  216. status = STATUS_INVALID_PARAMETER;
  217. leave;
  218. }
  219. busInterface->Size = sizeof( BUS_INTERFACE_STANDARD );
  220. busInterface->Version = 1;
  221. busInterface->Context = Pdo;
  222. busInterface->InterfaceReference = PcmciaNop;
  223. busInterface->InterfaceDereference = PcmciaNop;
  224. busInterface->TranslateBusAddress = PcmciaTranslateBusAddress;
  225. busInterface->GetDmaAdapter = PcmciaGetDmaAdapter;
  226. busInterface->GetBusData = PcmciaReadCardMemory;
  227. busInterface->SetBusData = PcmciaWriteCardMemory;
  228. DebugPrint((PCMCIA_DEBUG_INTERFACE, "pdo %08x returning BUS_INTERFACE_STANDARD\n", Pdo));
  229. status = STATUS_SUCCESS;
  230. }
  231. } finally {
  232. if (status == STATUS_NOT_SUPPORTED) {
  233. //
  234. // Query Interface type not supported
  235. //
  236. if (pdoExtension->LowerDevice != NULL) {
  237. PcmciaSkipCallLowerDriver(status, pdoExtension->LowerDevice, Irp);
  238. } else {
  239. status = Irp->IoStatus.Status;
  240. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  241. }
  242. } else {
  243. Irp->IoStatus.Status = status;
  244. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  245. }
  246. }
  247. return status;
  248. }
  249. ULONG
  250. PcmciaReadCardMemory(
  251. IN PDEVICE_OBJECT Pdo,
  252. IN ULONG WhichSpace,
  253. OUT PUCHAR Buffer,
  254. IN ULONG Offset,
  255. IN ULONG Length
  256. )
  257. /*++
  258. Routine Description:
  259. Stub for reading card memory which is exported via
  260. PCMCIA_BUS_INTERFACE_STANDARD. This just calls the
  261. PcmciaReadWriteCardMemory which does the real work
  262. Note: this has to be non-paged since it can be called by
  263. clients at DISPATCH_LEVEL
  264. Arguments:
  265. Pdo - Device object representing the PC-CARD whose config memory needs to be read
  266. WhichSpace - Indicates which memory space needs to be mapped: one of
  267. PCCARD_COMMON_MEMORY_SPACE
  268. PCCARD_ATTRIBUTE_MEMORY_SPACE
  269. PCCARD_PCI_CONFIGURATION_MEMORY_SPACE (only for cardbus cards)
  270. Buffer - Caller supplied buffer into which the memory contents are copied
  271. Offset - Offset of the attribute memory at which we copy
  272. Length - Number of bytes of attribute memory to be copied
  273. Return value:
  274. Count of bytes read
  275. --*/
  276. {
  277. DebugPrint((PCMCIA_DEBUG_INTERFACE, "pdo %08x read card memory\n", Pdo));
  278. return NT_SUCCESS(PcmciaReadWriteCardMemory(Pdo, WhichSpace, Buffer, Offset, Length, TRUE)) ?
  279. Length : 0;
  280. }
  281. ULONG
  282. PcmciaWriteCardMemory(
  283. IN PDEVICE_OBJECT Pdo,
  284. IN ULONG WhichSpace,
  285. IN PUCHAR Buffer,
  286. IN ULONG Offset,
  287. IN ULONG Length
  288. )
  289. /*++
  290. Routine Description:
  291. Stub for writing to card memory which is exported via
  292. PCMCIA_BUS_INTERFACE_STANDARD. This just calls
  293. PcmciaReadWriteCardMemory which does the real work
  294. Note: this has to be non-paged since it can be called by
  295. clients at DISPATCH_LEVEL
  296. Arguments:
  297. Pdo - Device object representing the PC-CARD whose config memory needs to be written to
  298. WhichSpace - Indicates which memory space needs to be mapped: one of
  299. PCCARD_COMMON_MEMORY_SPACE
  300. PCCARD_ATTRIBUTE_MEMORY_SPACE
  301. PCCARD_PCI_CONFIGURATION_MEMORY_SPACE (only for cardbus cards)
  302. Buffer - Caller supplied buffer out of which the memory contents are copied
  303. Offset - Offset of the attribute memory at which we copy
  304. Length - Number of bytes of buffer to be copied
  305. Return value:
  306. Count of bytes written
  307. --*/
  308. {
  309. DebugPrint((PCMCIA_DEBUG_INTERFACE, "pdo %08x write card memory\n", Pdo));
  310. return NT_SUCCESS(PcmciaReadWriteCardMemory(Pdo, WhichSpace, Buffer, Offset, Length, FALSE)) ?
  311. Length : 0;
  312. }
  313. BOOLEAN
  314. PcmciaModifyMemoryWindow(
  315. IN PDEVICE_OBJECT Pdo,
  316. IN ULONGLONG HostBase,
  317. IN ULONGLONG CardBase,
  318. IN BOOLEAN Enable,
  319. IN ULONG WindowSize OPTIONAL,
  320. IN UCHAR AccessSpeed OPTIONAL,
  321. IN UCHAR BusWidth OPTIONAL,
  322. IN BOOLEAN IsAttributeMemory OPTIONAL
  323. )
  324. /*++
  325. Routine Description:
  326. Part of the interfaces originally developed to
  327. support flash memory cards.
  328. This routine enables the caller to 'slide' the supplied
  329. host memory window across the given (16-bit)pc-card's card memory.
  330. i.e. the host memory window will be modified to map
  331. the pc-card at a new card memory offset
  332. Arguments:
  333. Pdo - Pointer to the device object for the PC-Card
  334. HostBase - Host memory window base to be mapped
  335. CardBase - Mandatory if Enable is TRUE
  336. New card memory offset to map the host memory window
  337. to
  338. Enable - If this is FALSE - all the remaining arguments
  339. are ignored and the host window will simply be
  340. disabled
  341. WindowSize - Specifies the size of the host memory window to
  342. be mapped. Note this must be at the proper alignment
  343. and must be less than or equal to the originally
  344. allocated window size for the host base.
  345. If this is zero, the originally allocated window
  346. size will be used.
  347. AccessSpeed - Mandatory if Enable is TRUE
  348. Specifies the new access speed for the pc-card.
  349. (AccessSpeed should be encoded as per the pc-card
  350. standard, card/socket services spec)
  351. BusWidth - Mandatory if Enable is TRUE
  352. One of PCMCIA_MEMORY_8BIT_ACCESS
  353. or PCMCIA_MEMORY_16BIT_ACCESS
  354. IsAttributeMemory - Mandatory if Enable is TRUE
  355. Specifies if the window should be mapped
  356. to the pc-card's attribute or common memory
  357. Return Value:
  358. TRUE - Memory window was enabled/disabled as requested
  359. FALSE - If not
  360. --*/
  361. {
  362. PPDO_EXTENSION pdoExtension;
  363. PSOCKET socket;
  364. pdoExtension = Pdo->DeviceExtension;
  365. socket = pdoExtension->Socket;
  366. DebugPrint((PCMCIA_DEBUG_INTERFACE, "pdo %08x modify memory window\n", Pdo));
  367. if (socket->SocketFnPtr->PCBModifyMemoryWindow == NULL) {
  368. return FALSE;
  369. } else {
  370. return (*(socket->SocketFnPtr->PCBModifyMemoryWindow))(Pdo, HostBase, CardBase, Enable,
  371. WindowSize, AccessSpeed, BusWidth,
  372. IsAttributeMemory);
  373. }
  374. }
  375. BOOLEAN
  376. PcmciaSetVpp(
  377. IN PDEVICE_OBJECT Pdo,
  378. IN UCHAR VppLevel
  379. )
  380. /*++
  381. Routine Description
  382. Part of the interfaces originally developed to
  383. support flash memory cards.
  384. Sets VPP1 to the required setting
  385. Arguments
  386. Pdo - Pointer to device object for the PC-Card
  387. Vpp - Desired Vpp setting. This is currently one of
  388. PCMCIA_VPP_12V (12 volts)
  389. PCMCIA_VPP_0V (disable VPP)
  390. PCMCIA_VPP_IS_VCC (route VCC to VPP)
  391. Return
  392. TRUE - if successful
  393. FALSE - if not. This will be returned if the
  394. PC-Card is not already powered up
  395. --*/
  396. {
  397. PPDO_EXTENSION pdoExtension;
  398. PSOCKET socket;
  399. pdoExtension = Pdo->DeviceExtension;
  400. socket = pdoExtension->Socket;
  401. DebugPrint((PCMCIA_DEBUG_INTERFACE, "pdo %08x set vpp\n", Pdo));
  402. if (socket->SocketFnPtr->PCBSetVpp == NULL) {
  403. return FALSE;
  404. } else {
  405. return (*(socket->SocketFnPtr->PCBSetVpp))(Pdo, VppLevel);
  406. }
  407. }
  408. BOOLEAN
  409. PcmciaIsWriteProtected(
  410. IN PDEVICE_OBJECT Pdo
  411. )
  412. /*++
  413. Routine Description:
  414. Part of the interfaces originally developed to
  415. support flash memory cards.
  416. Returns the status of the write protected pin
  417. for the given PC-Card
  418. Arguments:
  419. Pdo - Pointer to the device object for the PC-Card
  420. Return Value:
  421. TRUE - if the PC-Card is write-protected
  422. FALSE - if not
  423. --*/
  424. {
  425. PPDO_EXTENSION pdoExtension;
  426. PSOCKET socket;
  427. pdoExtension = Pdo->DeviceExtension;
  428. socket = pdoExtension->Socket;
  429. DebugPrint((PCMCIA_DEBUG_INTERFACE, "pdo %08x is write protected \n", Pdo));
  430. if (socket->SocketFnPtr->PCBIsWriteProtected == NULL) {
  431. return FALSE;
  432. } else {
  433. return (*(socket->SocketFnPtr->PCBIsWriteProtected))(Pdo);
  434. }
  435. }
  436. BOOLEAN
  437. PcmciaTranslateBusAddress(
  438. IN PVOID Context,
  439. IN PHYSICAL_ADDRESS BusAddress,
  440. IN ULONG Length,
  441. IN OUT PULONG AddressSpace,
  442. OUT PPHYSICAL_ADDRESS TranslatedAddress
  443. )
  444. /*++
  445. Routine Description
  446. This function is used to translate bus addresses from legacy drivers.
  447. Arguments
  448. Context - Supplies a pointer to the interface context. This is actually
  449. the PDO for the root bus.
  450. BusAddress - Supplies the orginal address to be translated.
  451. Length - Supplies the length of the range to be translated.
  452. AddressSpace - Points to the location of of the address space type such as
  453. memory or I/O port. This value is updated by the translation.
  454. TranslatedAddress - Returns the translated address.
  455. Return Value
  456. Returns a boolean indicating if the operations was a success.
  457. --*/
  458. {
  459. return HalTranslateBusAddress(Isa,
  460. 0,
  461. BusAddress,
  462. AddressSpace,
  463. TranslatedAddress);
  464. }
  465. PDMA_ADAPTER
  466. PcmciaGetDmaAdapter(
  467. IN PVOID Context,
  468. IN struct _DEVICE_DESCRIPTION *DeviceDescriptor,
  469. OUT PULONG NumberOfMapRegisters
  470. )
  471. /*++
  472. Routine Description
  473. Passes IoGetDmaAdapter calls to the parent.
  474. Arguments
  475. Context - Supplies a pointer to the interface context. This is actually the PDO.
  476. DeviceDescriptor - Supplies the device descriptor used to allocate the dma
  477. adapter object.
  478. NubmerOfMapRegisters - Returns the maximum number of map registers a device
  479. can allocate at one time.
  480. Return Value
  481. Returns a DMA adapter or NULL.
  482. --*/
  483. {
  484. PDEVICE_OBJECT Pdo = Context;
  485. PPDO_EXTENSION pdoExtension;
  486. PFDO_EXTENSION fdoExtension;
  487. pdoExtension = Pdo->DeviceExtension;
  488. if (!pdoExtension || !pdoExtension->Socket || !pdoExtension->Socket->DeviceExtension) {
  489. return NULL;
  490. }
  491. //
  492. // Get the parent FDO extension
  493. //
  494. fdoExtension = pdoExtension->Socket->DeviceExtension;
  495. //
  496. // Pass the call on to the parent
  497. //
  498. return IoGetDmaAdapter(fdoExtension->Pdo,
  499. DeviceDescriptor,
  500. NumberOfMapRegisters);
  501. }
  502. VOID
  503. PcmciaNop(
  504. IN PVOID Context
  505. )
  506. /*++
  507. Routine Description
  508. Does nothing
  509. Arguments
  510. none
  511. Return Value
  512. none
  513. --*/
  514. {
  515. PAGED_CODE();
  516. UNREFERENCED_PARAMETER(Context);
  517. }
  518. NTSTATUS
  519. PcmciaMfEnumerateChild(
  520. IN PPDO_EXTENSION PdoExtension,
  521. IN ULONG Index,
  522. OUT PMF_DEVICE_INFO ChildInfo
  523. )
  524. /*++
  525. Routine Description
  526. Returns required enumeration information for the multifunction children
  527. of the given pc-card. This fills in the required info. for the child
  528. indicated, returing STATUS_NO_MORE_ENTRIES when there are no more
  529. children to be enumerated
  530. Arguments
  531. PdoExtension - Pointer to the device extension for the multifunction parent pc-card
  532. Index - Zero based index for the child to be enumerated
  533. ChildInfo - Caller allocated buffer in which the info about the child is returned.
  534. We may allocate additional buffers for each field in the supplied
  535. structure. This will be freed by the caller when no longer needed
  536. Return value
  537. STATUS_SUCCESS - supplied child info filled in & returned
  538. STATUS_NO_MORE_ENTRIES - No child of the given index exists. Caller is
  539. assumed to iteratively call this routine with index incremented
  540. from 0 upwards till this status value is returned
  541. STATUS_NO_SUCH_DEVICE - if the pc-card no longer exists
  542. --*/
  543. {
  544. PSOCKET socket;
  545. PSOCKET_DATA socketData;
  546. PCONFIG_ENTRY configEntry, mfConfigEntry;
  547. ULONG i, currentIndex, count;
  548. NTSTATUS status;
  549. UCHAR iRes;
  550. PUCHAR idString;
  551. ANSI_STRING ansiString;
  552. PAGED_CODE();
  553. DebugPrint((PCMCIA_DEBUG_INTERFACE,
  554. "PcmciaMfEnumerateChild: parent ext %x child index %x\n",
  555. PdoExtension,
  556. Index
  557. ));
  558. try {
  559. if (IsDeviceDeleted(PdoExtension) ||
  560. IsDeviceLogicallyRemoved(PdoExtension)) {
  561. //
  562. // This pdo is deleted or marked to be deleted
  563. //
  564. status = STATUS_NO_SUCH_DEVICE;
  565. leave;
  566. }
  567. socket = PdoExtension->Socket;
  568. ASSERT (socket != NULL);
  569. RtlZeroMemory(ChildInfo, sizeof(MF_DEVICE_INFO));
  570. if (Index >= socket->NumberOfFunctions) {
  571. //
  572. // info requested for a child which doesn't exist
  573. //
  574. status = STATUS_NO_MORE_ENTRIES;
  575. leave;
  576. }
  577. //
  578. // Fill in the name field
  579. // This is of the form ChildXX
  580. // where XX is the number of the function
  581. // Examples: Child00, Child01 etc.
  582. //
  583. idString = (PUCHAR) ExAllocatePool(PagedPool, PCMCIA_MAXIMUM_DEVICE_ID_LENGTH);
  584. if (!idString) {
  585. status = STATUS_INSUFFICIENT_RESOURCES;
  586. leave;
  587. }
  588. sprintf(idString, "Child%02x", Index);
  589. RtlInitAnsiString(&ansiString, idString);
  590. status = RtlAnsiStringToUnicodeString(&ChildInfo->Name,
  591. &ansiString,
  592. TRUE);
  593. ExFreePool(idString);
  594. if (!NT_SUCCESS(status)) {
  595. leave;
  596. }
  597. //
  598. // Get compatible ids
  599. //
  600. status = PcmciaGetCompatibleIds(PdoExtension->DeviceObject,
  601. Index,
  602. &ChildInfo->CompatibleID);
  603. if (!NT_SUCCESS(status)) {
  604. leave;
  605. }
  606. //
  607. // Get hardware ids
  608. //
  609. status = PcmciaGetHardwareIds(PdoExtension->DeviceObject,
  610. Index,
  611. &ChildInfo->HardwareID);
  612. if (!NT_SUCCESS(status)) {
  613. leave;
  614. }
  615. //
  616. // Fill in the resource map stuff
  617. //
  618. // Locate the socket data structure corresponding to this function
  619. for (socketData = PdoExtension->SocketData, i=0; (socketData != NULL) && (i != Index); socketData=socketData->Next, i++);
  620. if (!socketData) {
  621. //
  622. // this condition should never be encountered
  623. //
  624. ASSERT (FALSE);
  625. status = STATUS_NO_MORE_ENTRIES;
  626. leave;
  627. }
  628. if (!(socketData->NumberOfConfigEntries > 0)) {
  629. //
  630. // No resource map required
  631. //
  632. status = STATUS_SUCCESS;
  633. leave;
  634. }
  635. count = (socketData->MfNeedsIrq ? 1 : 0) + socketData->MfIoPortCount + socketData->MfMemoryCount;
  636. if (count == 0) {
  637. ASSERT(FALSE);
  638. //
  639. // No resource map required
  640. //
  641. status = STATUS_SUCCESS;
  642. leave;
  643. }
  644. //
  645. // Allocate resource map
  646. //
  647. ChildInfo->ResourceMap = ExAllocatePool(PagedPool,
  648. sizeof(MF_RESOURCE_MAP) + (count-1) * sizeof(UCHAR));
  649. if (!ChildInfo->ResourceMap) {
  650. status = STATUS_INSUFFICIENT_RESOURCES;
  651. leave;
  652. }
  653. ChildInfo->ResourceMap->Count = count;
  654. //
  655. // Compute the resource map indices
  656. // The config entry *already* contains fields (MfIrqResourceMapIndex, MfIoPortResourceMapIndex etc.)
  657. // which indicate the relative index of the resource requested for this function within the resource type.
  658. // We calculate the absolute index by adding up the number of instances of each resource type requested,
  659. // preceding the current resource type, to this relative index.
  660. //
  661. currentIndex = 0;
  662. //
  663. // Fill the irq map if there's one
  664. //
  665. if (socketData->MfNeedsIrq) {
  666. ChildInfo->ResourceMap->Resources[currentIndex++] = socketData->MfIrqResourceMapIndex;
  667. }
  668. //
  669. // Fill the i/o port map if there's one
  670. //
  671. if (socketData->MfIoPortCount) {
  672. for (iRes=0; iRes<socketData->MfIoPortCount; iRes++) {
  673. ChildInfo->ResourceMap->Resources[currentIndex++] = socketData->MfIoPortResourceMapIndex + iRes;
  674. }
  675. }
  676. //
  677. // Fill the memory request map if there's one
  678. //
  679. if (socketData->MfMemoryCount) {
  680. for (iRes=0; iRes<socketData->MfMemoryCount; iRes++) {
  681. ChildInfo->ResourceMap->Resources[currentIndex++] = socketData->MfMemoryResourceMapIndex + iRes;
  682. }
  683. }
  684. status = STATUS_SUCCESS;
  685. } finally {
  686. if (!NT_SUCCESS(status)) {
  687. //
  688. // Free up all the allocated buffers
  689. //
  690. if (ChildInfo->Name.Buffer) {
  691. ExFreePool(ChildInfo->Name.Buffer);
  692. }
  693. if (ChildInfo->CompatibleID.Buffer) {
  694. ExFreePool(ChildInfo->CompatibleID.Buffer);
  695. }
  696. if (ChildInfo->HardwareID.Buffer) {
  697. ExFreePool(ChildInfo->HardwareID.Buffer);
  698. }
  699. if (ChildInfo->ResourceMap) {
  700. ExFreePool(ChildInfo->ResourceMap);
  701. }
  702. if (ChildInfo->VaryingResourceMap) {
  703. ExFreePool(ChildInfo->ResourceMap);
  704. }
  705. }
  706. }
  707. return status;
  708. }
  709. NTSTATUS
  710. PcmciaGetInterface(
  711. IN PDEVICE_OBJECT DeviceObject,
  712. IN CONST GUID *pGuid,
  713. IN USHORT sizeofInterface,
  714. OUT PINTERFACE pInterface
  715. )
  716. /*
  717. Routine Description
  718. Gets the interface exported by PCI for enumerating 32-bit cardbus cards, which
  719. appear as regular PCI devices. This interface will be used to respond during
  720. subsequent enumeration requests from PnP to invoke PCI to enumerate the cards.
  721. Arguments
  722. Pdo - Pointer to physical device object for the cardbus controller
  723. PciCardBusInterface - Pointer to the PCI-Cardbus interface will be returned
  724. in this variable
  725. Return Value
  726. Status
  727. */
  728. {
  729. KEVENT event;
  730. PIRP irp;
  731. NTSTATUS status;
  732. IO_STATUS_BLOCK statusBlock;
  733. PIO_STACK_LOCATION irpSp;
  734. PAGED_CODE();
  735. KeInitializeEvent (&event, NotificationEvent, FALSE);
  736. irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
  737. DeviceObject,
  738. NULL,
  739. 0,
  740. 0,
  741. &event,
  742. &statusBlock
  743. );
  744. irp->IoStatus.Status = STATUS_NOT_SUPPORTED ;
  745. irp->IoStatus.Information = 0;
  746. irpSp = IoGetNextIrpStackLocation(irp);
  747. irpSp->MinorFunction = IRP_MN_QUERY_INTERFACE;
  748. irpSp->Parameters.QueryInterface.InterfaceType= pGuid;
  749. irpSp->Parameters.QueryInterface.Size = sizeofInterface;
  750. irpSp->Parameters.QueryInterface.Version = 1;
  751. irpSp->Parameters.QueryInterface.Interface = pInterface;
  752. status = IoCallDriver(DeviceObject, irp);
  753. if (status == STATUS_PENDING) {
  754. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  755. status = statusBlock.Status;
  756. }
  757. if (!NT_SUCCESS(status)) {
  758. DebugPrint((PCMCIA_DEBUG_INFO, "GetInterface failed with status %x\n", status));
  759. }
  760. return status;
  761. }
  762. NTSTATUS
  763. PcmciaUpdateInterruptLine(
  764. IN PPDO_EXTENSION PdoExtension,
  765. IN PFDO_EXTENSION FdoExtension
  766. )
  767. /*
  768. Routine Description
  769. This routine uses the PCI Irq Routing interface to update the raw interrupt
  770. line of a cardbus card. This is done in order to allow cardbus cards to run
  771. on non-acpi machines without pci irq routing, as long as the bios supplies
  772. the interrupt for the cardbus controller.
  773. Arguments
  774. PdoExtension - Pointer to the extension for the cardbus card
  775. FdoExtension - Pointer to the extension for the cardbus controller
  776. Return Value
  777. Status
  778. */
  779. {
  780. PAGED_CODE();
  781. if (!IsDeviceFlagSet(FdoExtension, PCMCIA_INT_ROUTE_INTERFACE)) {
  782. return STATUS_UNSUCCESSFUL;
  783. }
  784. if (FdoExtension->Configuration.Interrupt.u.Interrupt.Vector == 0) {
  785. return STATUS_UNSUCCESSFUL;
  786. }
  787. (FdoExtension->PciIntRouteInterface.UpdateInterruptLine)(PdoExtension->PciPdo,
  788. (UCHAR) FdoExtension->Configuration.Interrupt.u.Interrupt.Vector);
  789. return STATUS_SUCCESS;
  790. }