Source code of Windows XP (NT5)
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.

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