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.

1738 lines
55 KiB

  1. /*
  2. (C) Copyright 1998
  3. All rights reserved.
  4. Portions of this software are:
  5. (C) Copyright 1995, 1999 TriplePoint, Inc. -- http://www.TriplePoint.com
  6. License to use this software is granted under the terms outlined in
  7. the TriplePoint Software Services Agreement.
  8. (C) Copyright 1992 Microsoft Corp. -- http://www.Microsoft.com
  9. License to use this software is granted under the terms outlined in
  10. the Microsoft Windows Device Driver Development Kit.
  11. @doc INTERNAL Card Card_c
  12. @module Card.c |
  13. This module implements the interface to the <t CARD_OBJECT>.
  14. Supports the low-level hardware control functions used by the NDIS WAN
  15. Minport driver. This module isolates most the vendor specific hardware
  16. access interfaces. It will require signficant changes to accomodate
  17. your hardware device.
  18. @head3 Contents |
  19. @index class,mfunc,func,msg,mdata,struct,enum | Card_c
  20. @end
  21. */
  22. #define __FILEID__ CARD_OBJECT_TYPE
  23. // Unique file ID for error logging
  24. #include "Miniport.h" // Defines all the miniport objects
  25. #if defined(NDIS_LCODE)
  26. # pragma NDIS_LCODE // Windows 95 wants this code locked down!
  27. # pragma NDIS_LDATA
  28. #endif
  29. DBG_STATIC ULONG g_CardInstanceCounter // @globalv
  30. // Keeps track of how many <t CARD_OBJECT>s are created.
  31. = 0;
  32. /* @doc EXTERNAL INTERNAL Card Card_c g_CardParameters
  33. @topic 5.3 Card Parameters |
  34. This section describes the registry parameters read into the
  35. <t CARD_OBJECT>.
  36. @globalv PARAM_TABLE | g_CardParameters |
  37. This table defines the registry based parameters to be assigned to data
  38. members of the <t CARD_OBJECT>.
  39. <f Note>:
  40. If you add any registry based data members to <t CARD_OBJECT>
  41. you will need to modify <f CardReadParameters> and add the parameter
  42. definitions to the <f g_CardParameters> table.
  43. */
  44. DBG_STATIC PARAM_TABLE g_CardParameters[] =
  45. {
  46. #if defined(PCI_BUS)
  47. PARAM_ENTRY(CARD_OBJECT,
  48. PciSlotNumber, PARAM_PciSlotNumber,
  49. TRUE, NdisParameterInteger, 0,
  50. 0, 0, 31),
  51. #endif // PCI_BUS
  52. PARAM_ENTRY(CARD_OBJECT,
  53. BufferSize, PARAM_BufferSize,
  54. FALSE, NdisParameterInteger, 0,
  55. CARD_DEFAULT_PACKET_SIZE, CARD_MIN_PACKET_SIZE, CARD_MAX_PACKET_SIZE),
  56. PARAM_ENTRY(CARD_OBJECT,
  57. ReceiveBuffersPerLink, PARAM_ReceiveBuffersPerLink,
  58. FALSE, NdisParameterInteger, 0,
  59. 2, 2, 16),
  60. PARAM_ENTRY(CARD_OBJECT,
  61. TransmitBuffersPerLink, PARAM_TransmitBuffersPerLink,
  62. FALSE, NdisParameterInteger, 0,
  63. 2, 1, 16),
  64. PARAM_ENTRY(CARD_OBJECT,
  65. NumDChannels, PARAM_NumDChannels,
  66. FALSE, NdisParameterInteger, 0,
  67. 1, 1, 4),
  68. /* The last entry must be an empty string! */
  69. { { 0 } }
  70. };
  71. /* @doc INTERNAL Card Card_c CardReadParameters
  72. @func
  73. <f CardReadParameters> reads the Card parameters from the registry
  74. and initializes the associated data members. This should only be called
  75. by <f CardCreate>.
  76. <f Note>:
  77. If you add any registry based data members to <t CARD_OBJECT>
  78. you will need to modify <f CardReadParameters> and add the parameter
  79. definitions to the <f g_CardParameters> table.
  80. @rdesc
  81. <f CardReadParameters> returns zero if it is successful.<nl>
  82. Otherwise, a non-zero return value indicates an error condition.
  83. */
  84. DBG_STATIC NDIS_STATUS CardReadParameters(
  85. IN PCARD_OBJECT pCard // @parm
  86. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  87. )
  88. {
  89. DBG_FUNC("CardReadParameters")
  90. NDIS_STATUS Status;
  91. // Status result returned from an NDIS function call.
  92. PMINIPORT_ADAPTER_OBJECT pAdapter;
  93. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  94. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  95. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  96. DBG_ENTER(pAdapter);
  97. /*
  98. // Parse the registry parameters.
  99. */
  100. Status = ParamParseRegistry(
  101. pAdapter->MiniportAdapterHandle,
  102. pAdapter->WrapperConfigurationContext,
  103. (PUCHAR)pCard,
  104. g_CardParameters
  105. );
  106. if (Status == NDIS_STATUS_SUCCESS)
  107. {
  108. /*
  109. // Make sure the parameters are valid.
  110. */
  111. if (pCard->BufferSize & 0x1F)
  112. {
  113. DBG_ERROR(pAdapter,("Invalid value 'BufferSize'=0x0x%X must be multiple of 32\n",
  114. pCard->BufferSize));
  115. NdisWriteErrorLogEntry(
  116. pAdapter->MiniportAdapterHandle,
  117. NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
  118. 3,
  119. pCard->BufferSize,
  120. __FILEID__,
  121. __LINE__
  122. );
  123. Status = NDIS_STATUS_FAILURE;
  124. }
  125. else
  126. {
  127. /*
  128. // Finish setting up data members based on registry settings.
  129. */
  130. }
  131. }
  132. DBG_RETURN(pAdapter, Status);
  133. return (Status);
  134. }
  135. /* @doc INTERNAL Card Card_c CardFindNIC
  136. @func
  137. <f CardFindNIC> locates the NIC associated with this NDIS device.
  138. @rdesc
  139. <f CardFindNIC> returns zero if it is successful.<nl>
  140. Otherwise, a non-zero return value indicates an error condition.
  141. */
  142. DBG_STATIC NDIS_STATUS CardFindNIC(
  143. IN PCARD_OBJECT pCard // @parm
  144. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  145. )
  146. {
  147. DBG_FUNC("CardFindNIC")
  148. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  149. // Holds the result code returned by this function.
  150. #if defined(PCI_BUS)
  151. ULONG Index;
  152. // Loop counter.
  153. PNDIS_RESOURCE_LIST pPciResourceList;
  154. PCM_PARTIAL_RESOURCE_DESCRIPTOR pPciResource;
  155. #endif // PCI_BUS
  156. PMINIPORT_ADAPTER_OBJECT pAdapter;
  157. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  158. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  159. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  160. DBG_ENTER(pAdapter);
  161. #if defined(PCI_BUS)
  162. /*
  163. // Read the PCI data and initialize the driver data structure
  164. // with the data returned.
  165. */
  166. pPciResourceList = NULL;
  167. Result = NdisMPciAssignResources(pAdapter->MiniportAdapterHandle,
  168. pCard->PciSlotNumber,
  169. &pPciResourceList);
  170. if (Result != NDIS_STATUS_SUCCESS)
  171. {
  172. DBG_ERROR(pAdapter,("NdisMPciAssignResources Result=0x%X\n",
  173. Result));
  174. NdisWriteErrorLogEntry(
  175. pAdapter->MiniportAdapterHandle,
  176. NDIS_ERROR_CODE_INVALID_VALUE_FROM_ADAPTER,
  177. 4,
  178. pCard->PciSlotNumber,
  179. Result,
  180. __FILEID__,
  181. __LINE__
  182. );
  183. }
  184. for (Index = 0; Result == NDIS_STATUS_SUCCESS &&
  185. Index < pPciResourceList->Count; ++Index)
  186. {
  187. ASSERT(pPciResourceList);
  188. pPciResource = &pPciResourceList->PartialDescriptors[Index];
  189. ASSERT(pPciResource);
  190. switch (pPciResource->Type)
  191. {
  192. case CmResourceTypePort:
  193. #if defined(CARD_MIN_IOPORT_SIZE)
  194. if (pPciResource->u.Port.Start.LowPart &&
  195. pPciResource->u.Port.Length >= CARD_MIN_IOPORT_SIZE)
  196. {
  197. DBG_NOTICE(pAdapter,("Port: Ptr=0x%X Len=%d<%d\n",
  198. pPciResource->u.Port.Start.LowPart,
  199. pPciResource->u.Port.Length,
  200. CARD_MIN_IOPORT_SIZE));
  201. pCard->ResourceInformation.IoPortPhysicalAddress =
  202. pPciResource->u.Port.Start;
  203. pCard->ResourceInformation.IoPortLength =
  204. pPciResource->u.Port.Length;
  205. }
  206. else
  207. {
  208. DBG_ERROR(pAdapter,("Invalid Port: Ptr=0x%X Len=%d<%d\n",
  209. pPciResource->u.Port.Start,
  210. pPciResource->u.Port.Length,
  211. CARD_MIN_IOPORT_SIZE));
  212. NdisWriteErrorLogEntry(
  213. pAdapter->MiniportAdapterHandle,
  214. NDIS_ERROR_CODE_INVALID_VALUE_FROM_ADAPTER,
  215. 4,
  216. pPciResource->u.Port.Length,
  217. CARD_MIN_IOPORT_SIZE,
  218. __FILEID__,
  219. __LINE__
  220. );
  221. Result = NDIS_STATUS_RESOURCE_CONFLICT;
  222. }
  223. #endif // CARD_MIN_IOPORT_SIZE
  224. break;
  225. case CmResourceTypeInterrupt:
  226. #if defined(CARD_REQUEST_ISR)
  227. if (pPciResource->u.Interrupt.Level)
  228. {
  229. DBG_NOTICE(pAdapter,("Interrupt: Lev=%d,Vec=%d\n",
  230. pPciResource->u.Interrupt.Level,
  231. pPciResource->u.Interrupt.Vector));
  232. pCard->ResourceInformation.InterruptLevel =
  233. pPciResource->u.Interrupt.Level;
  234. pCard->ResourceInformation.InterruptVector =
  235. pPciResource->u.Interrupt.Vector;
  236. pCard->ResourceInformation.InterruptShared = CARD_INTERRUPT_SHARED;
  237. pCard->ResourceInformation.InterruptMode = CARD_INTERRUPT_MODE;
  238. }
  239. else
  240. {
  241. DBG_ERROR(pAdapter,("Invalid Interrupt: Lev=%d,Vec=%d\n",
  242. pPciResource->u.Interrupt.Level,
  243. pPciResource->u.Interrupt.Vector));
  244. NdisWriteErrorLogEntry(
  245. pAdapter->MiniportAdapterHandle,
  246. NDIS_ERROR_CODE_INVALID_VALUE_FROM_ADAPTER,
  247. 4,
  248. pPciResource->u.Interrupt.Level,
  249. pPciResource->u.Interrupt.Vector,
  250. __FILEID__,
  251. __LINE__
  252. );
  253. Result = NDIS_STATUS_RESOURCE_CONFLICT;
  254. }
  255. #endif // defined(CARD_REQUEST_ISR)
  256. break;
  257. case CmResourceTypeMemory:
  258. #if defined(CARD_MIN_MEMORY_SIZE)
  259. if (pPciResource->u.Memory.Start.LowPart &&
  260. pPciResource->u.Memory.Length >= CARD_MIN_MEMORY_SIZE)
  261. {
  262. DBG_NOTICE(pAdapter,("Memory: Ptr=0x%X Len=%d<%d\n",
  263. pPciResource->u.Memory.Start.LowPart,
  264. pPciResource->u.Memory.Length,
  265. CARD_MIN_MEMORY_SIZE));
  266. pCard->ResourceInformation.MemoryPhysicalAddress =
  267. pPciResource->u.Memory.Start;
  268. pCard->ResourceInformation.MemoryLength =
  269. pPciResource->u.Memory.Length;
  270. }
  271. else
  272. {
  273. DBG_ERROR(pAdapter,("Invalid Memory: Ptr=0x%X Len=%d<%d\n",
  274. pPciResource->u.Memory.Start.LowPart,
  275. pPciResource->u.Memory.Length,
  276. CARD_MIN_MEMORY_SIZE));
  277. NdisWriteErrorLogEntry(
  278. pAdapter->MiniportAdapterHandle,
  279. NDIS_ERROR_CODE_INVALID_VALUE_FROM_ADAPTER,
  280. 4,
  281. pPciResource->u.Memory.Length,
  282. CARD_MIN_MEMORY_SIZE,
  283. __FILEID__,
  284. __LINE__
  285. );
  286. Result = NDIS_STATUS_RESOURCE_CONFLICT;
  287. }
  288. break;
  289. #endif // CARD_MIN_MEMORY_SIZE
  290. default:
  291. DBG_ERROR(pAdapter,("Unknown resource type=%d\n",
  292. pPciResource->Type));
  293. break;
  294. }
  295. }
  296. pCard->ResourceInformation.BusInterfaceType = NdisInterfacePci;
  297. #endif // PCI_BUS
  298. pCard->ResourceInformation.Master = CARD_IS_BUS_MASTER;
  299. #if (CARD_IS_BUS_MASTER)
  300. pCard->ResourceInformation.DmaChannel = 0;
  301. pCard->ResourceInformation.Dma32BitAddresses = TRUE,
  302. pCard->ResourceInformation.MaximumPhysicalMapping = pCard->BufferSize;
  303. pCard->ResourceInformation.PhysicalMapRegistersNeeded = CARD_MAP_REGISTERS_NEEDED;
  304. #endif // (CARD_IS_BUS_MASTER)
  305. DBG_RETURN(pAdapter, Result);
  306. return (Result);
  307. }
  308. /* @doc INTERNAL Card Card_c CardCreateInterface
  309. @func
  310. <f CardCreateInterface> allocates a shared memory pool and uses it to
  311. establish the message interface between the Miniport and the NIC.
  312. @rdesc
  313. <f CardCreateInterface> returns zero if it is successful.<nl>
  314. Otherwise, a non-zero return value indicates an error condition.
  315. */
  316. DBG_STATIC NDIS_STATUS CardCreateInterface(
  317. IN PCARD_OBJECT pCard // @parm
  318. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  319. )
  320. {
  321. DBG_FUNC("CardCreateObjects")
  322. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  323. // Holds the result code returned by this function.
  324. PMINIPORT_ADAPTER_OBJECT pAdapter;
  325. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  326. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  327. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  328. DBG_ENTER(pAdapter);
  329. DBG_RETURN(pAdapter, Result);
  330. return (Result);
  331. }
  332. /* @doc INTERNAL Card Card_c CardCreateObjects
  333. @func
  334. <f CardCreateObjects> calls the create routines for all the objects
  335. contained in <t CARD_OBJECT>. This should only be called
  336. by <f CardCreate>.
  337. <f Note>:
  338. If you add any new objects to <t CARD_OBJECT> you will need
  339. to modify <f CardCreateObjects> and <f CardDestroyObjects> so they
  340. will get created and destroyed properly.
  341. @rdesc
  342. <f CardCreateObjects> returns zero if it is successful.<nl>
  343. Otherwise, a non-zero return value indicates an error condition.
  344. */
  345. DBG_STATIC NDIS_STATUS CardCreateObjects(
  346. IN PCARD_OBJECT pCard // @parm
  347. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  348. )
  349. {
  350. DBG_FUNC("CardCreateObjects")
  351. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  352. // Holds the result code returned by this function.
  353. ULONG Index;
  354. // Loop counter.
  355. ULONG NumPorts;
  356. // The number of Ports supported by the NIC.
  357. PMINIPORT_ADAPTER_OBJECT pAdapter;
  358. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  359. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  360. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  361. DBG_ENTER(pAdapter);
  362. /*
  363. // Try to locate the NIC on the PCI bus.
  364. */
  365. Result = CardFindNIC(pCard);
  366. if (Result != NDIS_STATUS_SUCCESS)
  367. {
  368. goto ExceptionExit;
  369. }
  370. /*
  371. // Create the message interface to the NIC.
  372. */
  373. Result = CardCreateInterface(pCard);
  374. if (Result != NDIS_STATUS_SUCCESS)
  375. {
  376. goto ExceptionExit;
  377. }
  378. /*
  379. // Create the Port objects.
  380. */
  381. NumPorts = CardNumPorts(pCard);
  382. Result = ALLOCATE_MEMORY(pCard->pPortArray,
  383. sizeof(PVOID) * NumPorts,
  384. pAdapter->MiniportAdapterHandle);
  385. for (Index = 0; Result == NDIS_STATUS_SUCCESS &&
  386. Index < NumPorts; Index++)
  387. {
  388. Result = PortCreate(&pCard->pPortArray[Index], pCard);
  389. /*
  390. // Keep track of how many are created.
  391. */
  392. if (Result == NDIS_STATUS_SUCCESS)
  393. {
  394. pCard->NumPorts++;
  395. }
  396. }
  397. ExceptionExit:
  398. DBG_RETURN(pAdapter, Result);
  399. return (Result);
  400. }
  401. /* @doc INTERNAL Card Card_c CardCreate
  402. @func
  403. <f CardCreate> allocates memory for a <t CARD_OBJECT> and then
  404. initializes the data members to their starting state.
  405. If successful, <p ppCard> will be set to point to the newly created
  406. <t CARD_OBJECT>. Otherwise, <p ppCard> will be set to NULL.
  407. @comm
  408. This function should be called only once when the Miniport is loaded.
  409. Before the Miniport is unloaded, <f CardDestroy> must be called to
  410. release the <t CARD_OBJECT> created by this function.
  411. @rdesc
  412. <f CardCreate> returns zero if it is successful.<nl>
  413. Otherwise, a non-zero return value indicates an error condition.
  414. */
  415. NDIS_STATUS CardCreate(
  416. OUT PCARD_OBJECT * ppCard, // @parm
  417. // Points to a caller-defined memory location to which this function
  418. // writes the virtual address of the allocated <t CARD_OBJECT>.
  419. IN PMINIPORT_ADAPTER_OBJECT pAdapter // @parm
  420. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
  421. )
  422. {
  423. DBG_FUNC("CardCreate")
  424. PCARD_OBJECT pCard;
  425. // Pointer to our newly allocated object.
  426. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  427. // Holds the result code returned by this function.
  428. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  429. DBG_ENTER(pAdapter);
  430. /*
  431. // Make sure the caller's object pointer is NULL to begin with.
  432. // It will be set later only if everything is successful.
  433. */
  434. *ppCard = NULL;
  435. /*
  436. // Allocate memory for the object.
  437. */
  438. Result = ALLOCATE_OBJECT(pCard, pAdapter->MiniportAdapterHandle);
  439. if (Result == NDIS_STATUS_SUCCESS)
  440. {
  441. /*
  442. // Zero everything to begin with.
  443. // Then set the object type and assign a unique ID .
  444. */
  445. pCard->ObjectType = CARD_OBJECT_TYPE;
  446. pCard->ObjectID = ++g_CardInstanceCounter;
  447. /*
  448. // Initialize the member variables to their default settings.
  449. */
  450. pCard->pAdapter = pAdapter;
  451. // TODO - Add code here
  452. /*
  453. // Parse the registry parameters.
  454. */
  455. Result = CardReadParameters(pCard);
  456. /*
  457. // If all goes well, we are ready to create the sub-components.
  458. */
  459. if (Result == NDIS_STATUS_SUCCESS)
  460. {
  461. Result = CardCreateObjects(pCard);
  462. }
  463. if (Result == NDIS_STATUS_SUCCESS)
  464. {
  465. /*
  466. // All is well, so return the object pointer to the caller.
  467. */
  468. *ppCard = pCard;
  469. }
  470. else
  471. {
  472. /*
  473. // Something went wrong, so let's make sure everything is
  474. // cleaned up.
  475. */
  476. CardDestroy(pCard);
  477. }
  478. }
  479. DBG_RETURN(pAdapter, Result);
  480. return (Result);
  481. }
  482. /* @doc INTERNAL Card Card_c CardDestroyObjects
  483. @func
  484. <f CardDestroyObjects> calls the destroy routines for all the objects
  485. contained in <t CARD_OBJECT>. This should only be called by
  486. <f CardDestroy>.
  487. <f Note>:
  488. If you add any new objects to <t PCARD_OBJECT> you will need to
  489. modify <f CardCreateObjects> and <f CardDestroyObjects> so they
  490. will get created and destroyed properly.
  491. */
  492. DBG_STATIC void CardDestroyObjects(
  493. IN PCARD_OBJECT pCard // @parm
  494. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  495. )
  496. {
  497. DBG_FUNC("CardDestroyObjects")
  498. ULONG NumPorts;
  499. // The number of Ports supported by the NIC.
  500. PMINIPORT_ADAPTER_OBJECT pAdapter;
  501. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  502. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  503. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  504. DBG_ENTER(pAdapter);
  505. // TODO - Add code here
  506. /*
  507. // Destory the Port objects.
  508. */
  509. NumPorts = pCard->NumPorts;
  510. while (NumPorts--)
  511. {
  512. PortDestroy(pCard->pPortArray[NumPorts]);
  513. }
  514. pCard->NumPorts = 0;
  515. /*
  516. // Free space for the Ports.
  517. */
  518. if (pCard->pPortArray)
  519. {
  520. NumPorts = CardNumPorts(pCard);
  521. FREE_MEMORY(pCard->pPortArray, sizeof(PVOID) * NumPorts);
  522. }
  523. /*
  524. // Release the system resources back to NDIS.
  525. */
  526. #if defined(CARD_REQUEST_ISR)
  527. if (pCard->Interrupt.InterruptObject)
  528. {
  529. NdisMDeregisterInterrupt(&pCard->Interrupt);
  530. pCard->Interrupt.InterruptObject = NULL;
  531. }
  532. #endif // defined(CARD_REQUEST_ISR)
  533. #if defined(CARD_MIN_IOPORT_SIZE)
  534. if (pCard->pIoPortVirtualAddress)
  535. {
  536. NdisMDeregisterIoPortRange(
  537. pAdapter->MiniportAdapterHandle,
  538. pCard->ResourceInformation.IoPortPhysicalAddress.LowPart,
  539. pCard->ResourceInformation.IoPortLength,
  540. pCard->pIoPortVirtualAddress);
  541. pCard->pIoPortVirtualAddress = NULL;
  542. }
  543. #endif // CARD_MIN_IOPORT_SIZE
  544. #if defined(CARD_MIN_MEMORY_SIZE)
  545. if (pCard->pMemoryVirtualAddress)
  546. {
  547. NdisMUnmapIoSpace(
  548. pAdapter->MiniportAdapterHandle,
  549. pCard->pMemoryVirtualAddress,
  550. pCard->ResourceInformation.MemoryLength
  551. );
  552. pCard->pMemoryVirtualAddress = NULL;
  553. }
  554. #endif // CARD_MIN_MEMORY_SIZE
  555. DBG_LEAVE(pAdapter);
  556. }
  557. /* @doc INTERNAL Card Card_c CardDestroy
  558. @func
  559. <f CardDestroy> frees the memory for this <t CARD_OBJECT>. All memory
  560. allocated by <f CardCreate> will be released back to the OS.
  561. */
  562. void CardDestroy(
  563. IN PCARD_OBJECT pCard // @parm
  564. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  565. )
  566. {
  567. DBG_FUNC("CardDestroy")
  568. PMINIPORT_ADAPTER_OBJECT pAdapter;
  569. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  570. if (pCard)
  571. {
  572. ASSERT(pCard->ObjectType == CARD_OBJECT_TYPE);
  573. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  574. DBG_ENTER(pAdapter);
  575. // TODO - Add code here
  576. /*
  577. // Release all objects allocated within this object.
  578. */
  579. CardDestroyObjects(pCard);
  580. /*
  581. // Make sure we fail the ASSERT if we see this object again.
  582. */
  583. pCard->ObjectType = 0;
  584. FREE_OBJECT(pCard);
  585. DBG_LEAVE(pAdapter);
  586. }
  587. }
  588. /* @doc INTERNAL Card Card_c CardNumPorts
  589. @func
  590. <f CardNumPorts> will return the total number of ports available on the
  591. NIC.
  592. @rdesc
  593. <f CardNumPorts> returns the total number of ports available.
  594. */
  595. ULONG CardNumPorts(
  596. IN PCARD_OBJECT pCard // @parm
  597. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  598. )
  599. {
  600. DBG_FUNC("CardNumPorts")
  601. // TODO - Get the actual number of ports from the card.
  602. return (pCard->NumDChannels);
  603. }
  604. /* @doc INTERNAL Card Card_c CardNumChannels
  605. @func
  606. <f CardNumChannels> will return the total number of channels capable
  607. of supporting data connections to a remote end-point.
  608. @rdesc
  609. <f CardNumChannels> returns the total number of data channels supported
  610. on all the NIC ports.
  611. */
  612. ULONG CardNumChannels(
  613. IN PCARD_OBJECT pCard // @parm
  614. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  615. )
  616. {
  617. DBG_FUNC("CardNumChannels")
  618. UINT PortIndex;
  619. // Loop index.
  620. if (pCard->NumChannels == 0)
  621. {
  622. // NumPorts should already be known.
  623. ASSERT(pCard->NumPorts);
  624. // Get the actual number of channels configured on all ports.
  625. for (PortIndex = 0; PortIndex < pCard->NumPorts; PortIndex++)
  626. {
  627. pCard->NumChannels += pCard->pPortArray[PortIndex]->NumChannels;
  628. }
  629. ASSERT(pCard->NumChannels);
  630. }
  631. return (pCard->NumChannels);
  632. }
  633. /* @doc INTERNAL Card Card_c CardInitialize
  634. @func
  635. <f CardInitialize> will attempt to initialize the NIC, but will not
  636. enable transmits or receives.
  637. @rdesc
  638. <f CardInitialize> returns zero if it is successful.<nl>
  639. Otherwise, a non-zero return value indicates an error condition.
  640. */
  641. NDIS_STATUS CardInitialize(
  642. IN PCARD_OBJECT pCard // @parm
  643. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  644. )
  645. {
  646. DBG_FUNC("CardInitialize")
  647. int num_dial_chan = 0;
  648. int num_sync_chan = 0;
  649. // The number of channels supported by card is based on InterfaceType.
  650. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  651. // Holds the result code returned by this function.
  652. PMINIPORT_ADAPTER_OBJECT pAdapter;
  653. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  654. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  655. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  656. DBG_ENTER(pAdapter);
  657. /*
  658. // Inform the wrapper of the physical attributes of this adapter.
  659. // This must be called before any NdisMRegister functions!
  660. // This call also associates the MiniportAdapterHandle with this pAdapter.
  661. */
  662. NdisMSetAttributes(pAdapter->MiniportAdapterHandle,
  663. (NDIS_HANDLE) pAdapter,
  664. pCard->ResourceInformation.Master,
  665. pCard->ResourceInformation.BusInterfaceType
  666. );
  667. #if (CARD_IS_BUS_MASTER)
  668. if (pCard->ResourceInformation.Master)
  669. {
  670. ASSERT(pCard->ResourceInformation.DmaChannel == 0 ||
  671. pCard->ResourceInformation.BusInterfaceType == NdisInterfaceIsa);
  672. Result = NdisMAllocateMapRegisters(
  673. pAdapter->MiniportAdapterHandle,
  674. pCard->ResourceInformation.DmaChannel,
  675. pCard->ResourceInformation.Dma32BitAddresses,
  676. pCard->ResourceInformation.PhysicalMapRegistersNeeded + 1,
  677. pCard->ResourceInformation.MaximumPhysicalMapping
  678. );
  679. if (Result != NDIS_STATUS_SUCCESS)
  680. {
  681. DBG_ERROR(pAdapter,("NdisMAllocateMapRegisters(%d,%d) Result=0x%X\n",
  682. pCard->ResourceInformation.PhysicalMapRegistersNeeded,
  683. pCard->ResourceInformation.MaximumPhysicalMapping,
  684. Result));
  685. NdisWriteErrorLogEntry(
  686. pAdapter->MiniportAdapterHandle,
  687. NDIS_ERROR_CODE_RESOURCE_CONFLICT,
  688. 5,
  689. pCard->ResourceInformation.PhysicalMapRegistersNeeded,
  690. pCard->ResourceInformation.MaximumPhysicalMapping,
  691. Result,
  692. __FILEID__,
  693. __LINE__
  694. );
  695. }
  696. }
  697. #endif // (CARD_IS_BUS_MASTER)
  698. #if defined(CARD_MIN_MEMORY_SIZE)
  699. if (Result == NDIS_STATUS_SUCCESS &&
  700. pCard->ResourceInformation.MemoryLength)
  701. {
  702. Result = NdisMMapIoSpace(
  703. &pCard->pMemoryVirtualAddress,
  704. pAdapter->MiniportAdapterHandle,
  705. pCard->ResourceInformation.MemoryPhysicalAddress,
  706. pCard->ResourceInformation.MemoryLength);
  707. if (Result != NDIS_STATUS_SUCCESS)
  708. {
  709. DBG_ERROR(pAdapter,("NdisMMapIoSpace(0x%X,0x%X) Result=0x%X\n",
  710. pCard->ResourceInformation.MemoryPhysicalAddress.LowPart,
  711. pCard->ResourceInformation.MemoryLength,
  712. Result));
  713. NdisWriteErrorLogEntry(
  714. pAdapter->MiniportAdapterHandle,
  715. NDIS_ERROR_CODE_RESOURCE_CONFLICT,
  716. 5,
  717. pCard->ResourceInformation.MemoryPhysicalAddress.LowPart,
  718. pCard->ResourceInformation.MemoryLength,
  719. Result,
  720. __FILEID__,
  721. __LINE__
  722. );
  723. }
  724. else
  725. {
  726. DBG_NOTICE(pAdapter,("NdisMMapIoSpace(0x%X,0x%X) VirtualAddress=0x%X\n",
  727. pCard->ResourceInformation.MemoryPhysicalAddress.LowPart,
  728. pCard->ResourceInformation.MemoryLength,
  729. pCard->pMemoryVirtualAddress));
  730. }
  731. }
  732. #endif // CARD_MIN_MEMORY_SIZE
  733. #if defined(CARD_MIN_IOPORT_SIZE)
  734. if (Result == NDIS_STATUS_SUCCESS &&
  735. pCard->ResourceInformation.IoPortLength)
  736. {
  737. Result = NdisMRegisterIoPortRange(
  738. &pCard->pIoPortVirtualAddress,
  739. pAdapter->MiniportAdapterHandle,
  740. pCard->ResourceInformation.IoPortPhysicalAddress.LowPart,
  741. pCard->ResourceInformation.IoPortLength);
  742. if (Result != NDIS_STATUS_SUCCESS)
  743. {
  744. DBG_ERROR(pAdapter,("NdisMRegisterIoPortRange(0x%X,0x%X) Result=0x%X\n",
  745. pCard->ResourceInformation.IoPortPhysicalAddress.LowPart,
  746. pCard->ResourceInformation.IoPortLength,
  747. Result));
  748. NdisWriteErrorLogEntry(
  749. pAdapter->MiniportAdapterHandle,
  750. NDIS_ERROR_CODE_RESOURCE_CONFLICT,
  751. 5,
  752. pCard->ResourceInformation.IoPortPhysicalAddress.LowPart,
  753. pCard->ResourceInformation.IoPortLength,
  754. Result,
  755. __FILEID__,
  756. __LINE__
  757. );
  758. }
  759. else
  760. {
  761. DBG_NOTICE(pAdapter,("NdisMRegisterIoPortRange(0x%X,0x%X) VirtualAddress=0x%X\n",
  762. pCard->ResourceInformation.IoPortPhysicalAddress.LowPart,
  763. pCard->ResourceInformation.IoPortLength,
  764. pCard->pIoPortVirtualAddress));
  765. }
  766. }
  767. #endif // CARD_MIN_IOPORT_SIZE
  768. #if defined(CARD_REQUEST_ISR)
  769. if (Result == NDIS_STATUS_SUCCESS &&
  770. pCard->ResourceInformation.InterruptVector)
  771. {
  772. ASSERT(pCard->ResourceInformation.InterruptShared == FALSE ||
  773. (pCard->ResourceInformation.InterruptMode == NdisInterruptLevelSensitive &&
  774. CARD_REQUEST_ISR == TRUE));
  775. Result = NdisMRegisterInterrupt(
  776. &pCard->Interrupt,
  777. pAdapter->MiniportAdapterHandle,
  778. pCard->ResourceInformation.InterruptVector,
  779. pCard->ResourceInformation.InterruptLevel,
  780. CARD_REQUEST_ISR,
  781. pCard->ResourceInformation.InterruptShared,
  782. pCard->ResourceInformation.InterruptMode
  783. );
  784. if (Result != NDIS_STATUS_SUCCESS)
  785. {
  786. DBG_ERROR(pAdapter,("NdisMRegisterInterrupt failed: Vec=%d, Lev=%d\n",
  787. (UINT)pCard->ResourceInformation.InterruptVector,
  788. (UINT)pCard->ResourceInformation.InterruptLevel));
  789. NdisWriteErrorLogEntry(
  790. pAdapter->MiniportAdapterHandle,
  791. NDIS_ERROR_CODE_RESOURCE_CONFLICT,
  792. 5,
  793. pCard->ResourceInformation.InterruptVector,
  794. pCard->ResourceInformation.InterruptLevel,
  795. Result,
  796. __FILEID__,
  797. __LINE__
  798. );
  799. }
  800. }
  801. #endif // defined(CARD_REQUEST_ISR)
  802. // TODO - Add your card initialization here.
  803. if (Result == NDIS_STATUS_SUCCESS)
  804. {
  805. }
  806. DBG_RETURN(pAdapter, Result);
  807. return (Result);
  808. }
  809. /* @doc INTERNAL Card Card_c CardLineConnect
  810. @func
  811. <f CardLineConnect> will connect a call to the selected line.
  812. @rdesc
  813. <f CardLineConnect> returns zero if it is successful.<nl>
  814. Otherwise, a non-zero return value indicates an error condition.
  815. */
  816. NDIS_STATUS CardLineConnect(
  817. IN PCARD_OBJECT pCard, // @parm
  818. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  819. IN PBCHANNEL_OBJECT pBChannel // @parm
  820. // A pointer to the <t NDIS_LINK_OBJECT> returned by <f NdisLinkCreate>.
  821. )
  822. {
  823. DBG_FUNC("CardLineConnect")
  824. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  825. // Holds the result code returned by this function.
  826. PMINIPORT_ADAPTER_OBJECT pAdapter;
  827. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  828. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  829. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  830. DBG_ENTER(pAdapter);
  831. // TODO - Add code here
  832. DBG_RETURN(pAdapter, Result);
  833. return (Result);
  834. }
  835. /* @doc INTERNAL Card Card_c CardLineDisconnect
  836. @func
  837. <f CardLineDisconnect> will disconnect any call currently on the line.
  838. */
  839. void CardLineDisconnect(
  840. IN PCARD_OBJECT pCard, // @parm
  841. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  842. IN PBCHANNEL_OBJECT pBChannel // @parm
  843. // A pointer to the <t NDIS_LINK_OBJECT> returned by <f NdisLinkCreate>.
  844. )
  845. {
  846. DBG_FUNC("CardLineDisconnect")
  847. PMINIPORT_ADAPTER_OBJECT pAdapter;
  848. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  849. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  850. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  851. DBG_ENTER(pAdapter);
  852. // TODO - Add code here
  853. DBG_LEAVE(pAdapter);
  854. }
  855. /* @doc INTERNAL Card Card_c CardTransmitPacket
  856. @func
  857. <f CardTransmitPacket> will start sending the current packet out.
  858. @rdesc
  859. <f CardTransmitPacket> returns TRUE if the packet is being transmitted,
  860. otherwise FALSE is returned.
  861. */
  862. BOOLEAN CardTransmitPacket(
  863. IN PCARD_OBJECT pCard, // @parm
  864. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  865. IN PBCHANNEL_OBJECT pBChannel, // @parm
  866. // A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
  867. IN PNDIS_WAN_PACKET pWanPacket // @parm
  868. // A pointer to the associated NDIS packet structure <t NDIS_WAN_PACKET>.
  869. )
  870. {
  871. DBG_FUNC("CardTransmitPacket")
  872. BOOLEAN bResult = FALSE;
  873. // Holds the result code returned by this function.
  874. PMINIPORT_ADAPTER_OBJECT pAdapter;
  875. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  876. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  877. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  878. DBG_ENTER(pAdapter);
  879. #if defined(SAMPLE_DRIVER)
  880. {
  881. PBCHANNEL_OBJECT pPeerBChannel;
  882. // A pointer to the peer <t BCHANNEL_OBJECT>.
  883. PCARD_EVENT_OBJECT pEvent;
  884. // A pointer to the <t CARD_EVENT_OBJECT> associated with this event.
  885. // If you can transmit the packet on pBChannel, do it now.
  886. pPeerBChannel = pBChannel->pPeerBChannel;
  887. if (pPeerBChannel)
  888. {
  889. pEvent = CardEventAllocate(pPeerBChannel->pAdapter->pCard);
  890. if (pEvent)
  891. {
  892. /*
  893. // Append the packet onto TransmitBusyList while it is being sent.
  894. // Then move it to the TransmitCompleteList in CardInterruptHandler
  895. // after the card is done with it.
  896. */
  897. NdisAcquireSpinLock(&pAdapter->TransmitLock);
  898. InsertTailList(&pBChannel->TransmitBusyList,
  899. &pWanPacket->WanPacketQueue);
  900. NdisReleaseSpinLock(&pAdapter->TransmitLock);
  901. pEvent->ulEventCode = CARD_EVENT_RECEIVE;
  902. pEvent->pSendingObject = pBChannel;
  903. pEvent->pReceivingObject = pPeerBChannel;
  904. pEvent->pWanPacket = pWanPacket;
  905. CardNotifyEvent(pPeerBChannel->pAdapter->pCard, pEvent);
  906. bResult = TRUE;
  907. }
  908. }
  909. else
  910. {
  911. DBG_ERROR(pAdapter,("pPeerBChannel == NULL\n"));
  912. }
  913. }
  914. #else // SAMPLE_DRIVER
  915. // TODO - Add code here to transmit the packet.
  916. #endif // SAMPLE_DRIVER
  917. DBG_RETURN(pAdapter, bResult);
  918. return (bResult);
  919. }
  920. /* @doc INTERNAL Card Card_c CardGetReceiveInfo
  921. @func
  922. <f CardGetReceiveInfo> will retrieve the packet header information from
  923. the receive buffer. This assumes that the controller has notified the
  924. driver that a packet has been received.
  925. @rdesc
  926. <f CardGetReceiveInfo> returns a pointer to the receive buffer if there
  927. is a packet available, otherwise NULL is returned.
  928. */
  929. PUCHAR CardGetReceiveInfo(
  930. IN PCARD_OBJECT pCard, // @parm
  931. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  932. OUT PBCHANNEL_OBJECT * ppBChannel, // @parm
  933. // Points to a caller-defined memory location to which this function
  934. // writes the virtual address of the allocated <t BCHANNEL_OBJECT>.
  935. OUT PULONG pBytesReceived // @parm
  936. // Points to a caller-defined memory location to which this function
  937. // writes the number of bytes received on this BChannel.
  938. )
  939. {
  940. DBG_FUNC("CardGetReceiveInfo")
  941. PUCHAR pBuffer = NULL;
  942. PMINIPORT_ADAPTER_OBJECT pAdapter;
  943. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  944. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  945. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  946. DBG_ENTER(pAdapter);
  947. /*
  948. // The length field tells us how many bytes are in the packet.
  949. // Make sure it isn't bigger than we expect!
  950. */
  951. *pBytesReceived = 0;
  952. *ppBChannel = NULL;
  953. DBG_RETURN(pAdapter, pBuffer);
  954. return (pBuffer);
  955. }
  956. /* @doc INTERNAL Card Card_c CardReceiveComplete
  957. @func
  958. <f CardReceiveComplete> will return the last receive buffer to the
  959. B-channel queue so it can be used for another incoming packet.
  960. */
  961. VOID CardReceiveComplete(
  962. IN PCARD_OBJECT pCard, // @parm
  963. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  964. IN PBCHANNEL_OBJECT pBChannel // @parm
  965. // A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
  966. )
  967. {
  968. DBG_FUNC("CardReceiveComplete")
  969. PMINIPORT_ADAPTER_OBJECT pAdapter;
  970. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  971. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  972. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  973. DBG_ENTER(pAdapter);
  974. // TODO - Add code here
  975. DBG_LEAVE(pAdapter);
  976. }
  977. /* @doc INTERNAL Card Card_c CardInterruptHandler
  978. @func
  979. <f CardInterruptHandler> dequeues an event from the asynchronous event
  980. callback queue <t CARD_EVENT_OBJECT>, and processes it according to
  981. whether it is a BChannel event, Card event, or B-Advise event.
  982. The associated callback routines are responsible for processing the
  983. event.
  984. @comm
  985. <f NdisAcquireSpinLock> and <f NdisReleaseSpinLock> are used to provide
  986. protection around the dequeueing code and keep it from being re-entered
  987. as a result of another asynchronous callback event.
  988. */
  989. VOID CardInterruptHandler(
  990. IN PCARD_OBJECT pCard // @parm
  991. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  992. )
  993. {
  994. DBG_FUNC("CardInterruptHandler")
  995. PMINIPORT_ADAPTER_OBJECT pAdapter;
  996. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  997. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  998. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  999. DBG_ENTER(pAdapter);
  1000. #if defined(SAMPLE_DRIVER)
  1001. {
  1002. PCARD_EVENT_OBJECT pEvent;
  1003. PCARD_EVENT_OBJECT pNewEvent;
  1004. // A pointer to the <t CARD_EVENT_OBJECT> associated with this event.
  1005. PBCHANNEL_OBJECT pBChannel;
  1006. PBCHANNEL_OBJECT pPeerBChannel;
  1007. // A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
  1008. PNDIS_WAN_PACKET pWanPacket;
  1009. // A pointer to the associated NDIS packet structure <t NDIS_WAN_PACKET>.
  1010. /*
  1011. // Clear out all packets in the receive buffer.
  1012. */
  1013. NdisDprAcquireSpinLock(&pAdapter->EventLock);
  1014. while (!IsListEmpty(&pAdapter->EventList))
  1015. {
  1016. pEvent = (PCARD_EVENT_OBJECT)RemoveHeadList(&pAdapter->EventList);
  1017. NdisDprReleaseSpinLock(&pAdapter->EventLock);
  1018. ASSERT(pEvent->pReceivingObject);
  1019. switch (pEvent->ulEventCode)
  1020. {
  1021. case CARD_EVENT_RING:
  1022. pBChannel = pEvent->pReceivingObject;
  1023. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1024. DBG_NOTICE(pAdapter,("#%d CallState=0x%X CARD_EVENT_RING\n",
  1025. pBChannel->BChannelIndex, pBChannel->CallState));
  1026. pBChannel->pPeerBChannel = pEvent->pSendingObject;
  1027. ASSERT(pBChannel->pPeerBChannel &&
  1028. pBChannel->pPeerBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1029. // We only have to spoof digital data for this sample.
  1030. pBChannel->MediaMode = LINEMEDIAMODE_DIGITALDATA;
  1031. pBChannel->BearerMode = LINEBEARERMODE_DATA;
  1032. pBChannel->LinkSpeed = _64KBPS;
  1033. TspiLineDevStateHandler(pAdapter, pBChannel,
  1034. LINEDEVSTATE_RINGING);
  1035. break;
  1036. case CARD_EVENT_CONNECT:
  1037. pBChannel = pEvent->pReceivingObject;
  1038. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1039. DBG_NOTICE(pAdapter,("#%d CallState=0x%X CARD_EVENT_CONNECT\n",
  1040. pBChannel->BChannelIndex, pBChannel->CallState));
  1041. TspiCallStateHandler(pAdapter, pBChannel,
  1042. LINECALLSTATE_CONNECTED,
  1043. 0);
  1044. break;
  1045. case CARD_EVENT_DISCONNECT:
  1046. pBChannel = pEvent->pReceivingObject;
  1047. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1048. DBG_NOTICE(pAdapter,("#%d CallState=0x%X CARD_EVENT_DISCONNECT\n",
  1049. pBChannel->BChannelIndex, pBChannel->CallState));
  1050. pBChannel->pPeerBChannel = NULL;
  1051. TspiCallStateHandler(pAdapter, pBChannel,
  1052. LINECALLSTATE_DISCONNECTED,
  1053. LINEDISCONNECTMODE_NORMAL);
  1054. break;
  1055. case CARD_EVENT_RECEIVE:
  1056. pBChannel = pEvent->pReceivingObject;
  1057. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1058. DBG_NOTICE(pAdapter,("#%d CallState=0x%X CARD_EVENT_RECEIVE\n",
  1059. pBChannel->BChannelIndex, pBChannel->CallState));
  1060. ReceivePacketHandler(pBChannel, pEvent->pWanPacket->CurrentBuffer,
  1061. pEvent->pWanPacket->CurrentLength);
  1062. pPeerBChannel = pBChannel->pPeerBChannel;
  1063. if (pPeerBChannel)
  1064. {
  1065. pNewEvent = CardEventAllocate(pPeerBChannel->pAdapter->pCard);
  1066. if (pNewEvent)
  1067. {
  1068. pNewEvent->ulEventCode = CARD_EVENT_TRANSMIT_COMPLETE;
  1069. pNewEvent->pSendingObject = pBChannel;
  1070. pNewEvent->pReceivingObject = pPeerBChannel;
  1071. CardNotifyEvent(pPeerBChannel->pAdapter->pCard, pNewEvent);
  1072. }
  1073. }
  1074. else
  1075. {
  1076. DBG_ERROR(pAdapter,("pPeerBChannel == NULL\n"));
  1077. }
  1078. break;
  1079. case CARD_EVENT_TRANSMIT_COMPLETE:
  1080. pBChannel = pEvent->pReceivingObject;
  1081. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1082. DBG_NOTICE(pAdapter,("#%d CallState=0x%X CARD_EVENT_TRANSMIT_COMPLETE\n",
  1083. pBChannel->BChannelIndex, pBChannel->CallState));
  1084. /*
  1085. // Remove the packet from the BChannel's TransmitBusyList and
  1086. // place it on the adapter's TransmitCompleteList now that the
  1087. // card has completed the transmit.
  1088. */
  1089. NdisAcquireSpinLock(&pAdapter->TransmitLock);
  1090. pWanPacket = (PNDIS_WAN_PACKET)RemoveHeadList(
  1091. &pBChannel->TransmitBusyList);
  1092. InsertTailList(&pBChannel->pAdapter->TransmitCompleteList,
  1093. &pWanPacket->WanPacketQueue);
  1094. NdisReleaseSpinLock(&pAdapter->TransmitLock);
  1095. TransmitCompleteHandler(pAdapter);
  1096. break;
  1097. default:
  1098. DBG_ERROR(pAdapter,("Unknown event code=%d\n",
  1099. pEvent->ulEventCode));
  1100. break;
  1101. }
  1102. CardEventRelease(pCard, pEvent);
  1103. NdisDprAcquireSpinLock(&pAdapter->EventLock);
  1104. }
  1105. NdisDprReleaseSpinLock(&pAdapter->EventLock);
  1106. }
  1107. #else // SAMPLE_DRIVER
  1108. // TODO - Add interrupt handler code here
  1109. #endif // SAMPLE_DRIVER
  1110. DBG_LEAVE(pAdapter);
  1111. }
  1112. /* @doc INTERNAL Card Card_c CardCleanPhoneNumber
  1113. @func
  1114. <f CardCleanPhoneNumber> copies the phone number from the input string
  1115. to the output string, deleting any non-phone number characters (i.e.
  1116. dashes, parens, modem keywords, etc.).
  1117. @rdesc
  1118. <f CardCleanPhoneNumber> returns the length of the output string in bytes.
  1119. */
  1120. USHORT CardCleanPhoneNumber(
  1121. OUT PUCHAR Dst, // @parm
  1122. // A pointer to the output string.
  1123. IN PUCHAR Src, // @parm
  1124. // A pointer to the input string.
  1125. IN USHORT Length // @parm
  1126. // The length of the input string in bytes.
  1127. )
  1128. {
  1129. DBG_FUNC("CardCleanPhoneNumber")
  1130. USHORT NumDigits;
  1131. /*
  1132. // Strip out any character which are not digits or # or *.
  1133. */
  1134. for (NumDigits = 0; Length > 0; --Length)
  1135. {
  1136. if ((*Src >= '0' && *Src <= '9') ||
  1137. (*Src == '#' || *Src == '*'))
  1138. {
  1139. /*
  1140. // Make sure dial string is within the limit of the adapter.
  1141. */
  1142. if (NumDigits < CARD_MAX_DIAL_DIGITS)
  1143. {
  1144. ++NumDigits;
  1145. *Dst++ = *Src;
  1146. }
  1147. else
  1148. {
  1149. break;
  1150. }
  1151. }
  1152. Src++;
  1153. }
  1154. *Dst++ = 0;
  1155. return (NumDigits);
  1156. }
  1157. /* @doc INTERNAL Card Card_c CardReset
  1158. @func
  1159. <f CardReset> issues a hard reset to the NIC. Same as power up.
  1160. @rdesc
  1161. <f CardReset> returns zero if it is successful.<nl>
  1162. Otherwise, a non-zero return value indicates an error condition.
  1163. */
  1164. NDIS_STATUS CardReset(
  1165. IN PCARD_OBJECT pCard // @parm
  1166. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  1167. )
  1168. {
  1169. DBG_FUNC("CardReset")
  1170. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  1171. // Holds the result code returned by this function.
  1172. PMINIPORT_ADAPTER_OBJECT pAdapter;
  1173. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  1174. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  1175. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  1176. DBG_ENTER(pAdapter);
  1177. DBG_BREAK(pAdapter);
  1178. // TODO - Add code here to reset your hardware to its initial state.
  1179. DBG_RETURN(pAdapter, Result);
  1180. return (Result);
  1181. }
  1182. #if defined(SAMPLE_DRIVER)
  1183. /* @doc INTERNAL Card Card_c GET_BCHANNEL_FROM_PHONE_NUMBER
  1184. @func
  1185. <f GET_BCHANNEL_FROM_PHONE_NUMBER> assumes the phone number is a tapi
  1186. DeviceID, and uses it to lookup the associated BChannel on one of our
  1187. adapters.
  1188. @rdesc
  1189. <f GET_BCHANNEL_FROM_PHONE_NUMBER> returns a pointer to the associated
  1190. <t BCHANNEL_OBJECT> if successful. Otherwise, NULL is returned.
  1191. */
  1192. PBCHANNEL_OBJECT GET_BCHANNEL_FROM_PHONE_NUMBER(
  1193. IN PUCHAR pDialString // @parm
  1194. // A pointer to the dial string.
  1195. )
  1196. {
  1197. DBG_FUNC("GET_BCHANNEL_FROM_PHONE_NUMBER")
  1198. ULONG ulCalledID = 0;
  1199. // Phone number converted to BChannel ObjectID (spans all adapters).
  1200. ULONG ulAdapterIndex;
  1201. ULONG ulBChannelIndex;
  1202. // Loop index.
  1203. /*
  1204. // Strip out any character which are not digits or # or *.
  1205. */
  1206. while (*pDialString)
  1207. {
  1208. if (*pDialString >= '0' && *pDialString <= '9')
  1209. {
  1210. ulCalledID *= 10;
  1211. ulCalledID += *pDialString - '0';
  1212. }
  1213. else
  1214. {
  1215. break;
  1216. }
  1217. pDialString++;
  1218. }
  1219. if (*pDialString)
  1220. {
  1221. DBG_ERROR(DbgInfo,("Invalid dial string '%s'\n", pDialString));
  1222. }
  1223. else
  1224. {
  1225. PMINIPORT_ADAPTER_OBJECT pAdapter;
  1226. for (ulAdapterIndex = 0; ulAdapterIndex < MAX_ADAPTERS; ++ulAdapterIndex)
  1227. {
  1228. pAdapter = g_Adapters[ulAdapterIndex];
  1229. if (pAdapter)
  1230. {
  1231. PBCHANNEL_OBJECT pBChannel;
  1232. for (ulBChannelIndex = 0;
  1233. ulBChannelIndex < pAdapter->NumBChannels;
  1234. ulBChannelIndex++)
  1235. {
  1236. pBChannel = GET_BCHANNEL_FROM_INDEX(pAdapter, ulBChannelIndex);
  1237. if (pBChannel->htCall == (HTAPI_CALL)0 &&
  1238. pBChannel->MediaModesMask != 0)
  1239. {
  1240. if (ulCalledID == 0)
  1241. {
  1242. // Find first available channel.
  1243. return (pBChannel);
  1244. }
  1245. else if (ulCalledID == pBChannel->ObjectID)
  1246. {
  1247. // Find selected channel.
  1248. return (pBChannel);
  1249. }
  1250. }
  1251. }
  1252. }
  1253. }
  1254. }
  1255. return (NULL);
  1256. }
  1257. /* @doc INTERNAL Card Card_c CardNotifyEvent
  1258. @func
  1259. <f CardNotifyEvent> queues an IMS event to be processed by the DPC
  1260. handler when things quiet down.
  1261. @comm
  1262. We have to queue the event to be processed in DPC context. We have
  1263. to make sure that the queue is protected by a mutual exclusion
  1264. primative which cannot be violated by the callback.
  1265. */
  1266. VOID CardNotifyEvent(
  1267. IN PCARD_OBJECT pCard, // @parm
  1268. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  1269. IN PCARD_EVENT_OBJECT pEvent // @parm
  1270. // A pointer to the <t CARD_EVENT_OBJECT> associated with this event.
  1271. )
  1272. {
  1273. DBG_FUNC("CardNotifyEvent")
  1274. PMINIPORT_ADAPTER_OBJECT pAdapter;
  1275. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  1276. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  1277. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  1278. DBG_ENTER(pAdapter);
  1279. DBG_NOTICE(pAdapter,("pEvent=%X\n",pEvent));
  1280. /*
  1281. // Schedule the event handler to run as soon as possible.
  1282. // We must schedule the event to go through the NDIS wrapper
  1283. // so the proper spin locks will be held.
  1284. // Don't schedule another event if processing is already in progress.
  1285. */
  1286. NdisAcquireSpinLock(&pAdapter->EventLock);
  1287. InsertTailList(&pAdapter->EventList, &pEvent->Queue);
  1288. NdisReleaseSpinLock(&pAdapter->EventLock);
  1289. NdisMSetTimer(&pAdapter->EventTimer, 0);
  1290. DBG_LEAVE(pAdapter);
  1291. }
  1292. /* @doc INTERNAL Card Card_c CardEventAllocate
  1293. @func
  1294. <f CardEventAllocate> allocates an <t CARD_EVENT_OBJECT> from the
  1295. <p pCard>'s EventList.
  1296. @rdesc
  1297. <f CardEventAllocate> returns a pointer to a <t CARD_EVENT_OBJECT>
  1298. if it is successful.<nl>
  1299. Otherwise, a NULL return value indicates an error condition.
  1300. */
  1301. PCARD_EVENT_OBJECT CardEventAllocate(
  1302. IN PCARD_OBJECT pCard // @parm
  1303. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  1304. )
  1305. {
  1306. PCARD_EVENT_OBJECT pEvent;
  1307. // A pointer to the <t CARD_EVENT_OBJECT> associated with this event.
  1308. pEvent = &pCard->EventArray[pCard->NextEvent++];
  1309. ASSERT(pEvent->pReceivingObject == NULL);
  1310. if (pCard->NextEvent >= MAX_EVENTS)
  1311. {
  1312. pCard->NextEvent = 0;
  1313. }
  1314. return (pEvent);
  1315. }
  1316. /* @doc INTERNAL Card Card_c CardEventRelease
  1317. @func
  1318. <f CardEventRelease> returns a previously allocate <t CARD_EVENT_OBJECT>
  1319. to the <p pCard>'s EventList.
  1320. */
  1321. VOID CardEventRelease(
  1322. IN PCARD_OBJECT pCard, // @parm
  1323. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  1324. IN PCARD_EVENT_OBJECT pEvent // @parm
  1325. // A pointer to the <t CARD_EVENT_OBJECT> associated with this event.
  1326. )
  1327. {
  1328. pEvent->pReceivingObject = NULL;
  1329. }
  1330. #endif // SAMPLE_DRIVER