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.

1993 lines
62 KiB

  1. /*
  2. (C) Copyright 1999
  3. All rights reserved.
  4. Portions of this software are:
  5. (C) Copyright 1995 TriplePoint, Inc. -- http://www.TriplePoint.com
  6. License to use this software is granted under the same terms
  7. outlined in the Microsoft Windows Device Driver Development Kit.
  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.
  16. @comm
  17. This module isolates most the vendor specific hardware access interfaces.
  18. It will require signficant changes to accomodate your hardware device.
  19. You should try to isolate your changes to the <t CARD_OBJECT> rather then
  20. the <t MINIPORT_ADAPTER_OBJECT>. This will make it eaiser to reuse the
  21. upper portions of the driver should your hardware change in the future.
  22. @head3 Contents |
  23. @index class,mfunc,func,msg,mdata,struct,enum | Card_c
  24. @end
  25. */
  26. #define __FILEID__ CARD_OBJECT_TYPE
  27. // Unique file ID for error logging
  28. #include "Miniport.h" // Defines all the miniport objects
  29. #if defined(NDIS_LCODE)
  30. # pragma NDIS_LCODE // Windows 9x wants this code locked down!
  31. # pragma NDIS_LDATA
  32. #endif
  33. DBG_STATIC ULONG g_CardInstanceCounter // @globalv
  34. // Keeps track of how many <t CARD_OBJECT>s are created.
  35. = 0;
  36. /* @doc EXTERNAL INTERNAL Card Card_c g_CardParameters
  37. @topic 5.2 Card Parameters |
  38. This section describes the registry parameters read into the
  39. <t CARD_OBJECT>.
  40. @globalv PARAM_TABLE | g_CardParameters |
  41. This table defines the registry based parameters to be assigned to data
  42. members of the <t CARD_OBJECT>.
  43. <f Note>:
  44. If you add any registry based data members to <t CARD_OBJECT>
  45. you will need to modify <f CardReadParameters> and add the parameter
  46. definitions to the <f g_CardParameters> table.
  47. @flag <f BufferSize> (OPTIONAL) |
  48. This DWORD parameter allows you to control the maximum buffer size used
  49. to transmit and receive packets over the IDSN line. Typically, this is
  50. defined to be 1500 bytes for most Point to Point (PPP) connections.<nl>
  51. <tab><f Default Value:><tab><tab>1532<nl>
  52. <tab><f Valid Range N:><tab><tab>532 <lt>= N <lt>= 4032<nl>
  53. <f Note>: You must add 32 bytes to the maximum packet size you
  54. expect to send or receive. Therefore, if you have a maximum packet size
  55. of 1500 bytes, excluding media headers, you should set the <f BufferSize>
  56. value to 1532.<nl>
  57. @flag <f ReceiveBuffersPerLink> (OPTIONAL) |
  58. This DWORD parameter allows you to control the maximum number of incoming
  59. packets that can in progress at any one time. The Miniport will allocate
  60. this number of packets per BChannel and set them up for incoming packets.
  61. Typically, three or four should be sufficient to handle a few short bursts
  62. that may occur with small packets. If the Miniport is not able to service
  63. the incoming packets fast enough, new packets will be dropped and it is up
  64. to the NDIS WAN Wrapper to resynchronize with the remote station.<nl>
  65. <tab><f Default Value:><tab><tab>3<nl>
  66. <tab><f Valid Range N:><tab><tab>2 <lt>= N <lt>= 16<nl>
  67. @flag <f TransmitBuffersPerLink> (OPTIONAL) |
  68. This DWORD parameter allows you to control the maximum number of outgoing
  69. packets that can in progress at any one time. The Miniport will allow
  70. this number of packets per BChannel to be outstanding (i.e. in progress).
  71. Typically, two or three should be sufficient to keep the channel busy for
  72. normal sized packets. If there are alot of small packets being sent, the
  73. BChannel may become idle for brief periods while new packets are being
  74. queued. Windows does not normally work this way if it has large amounts
  75. of data to transfer, so the default value should be sufficient. <nl>
  76. <tab><f Default Value:><tab><tab>2<nl>
  77. <tab><f Valid Range N:><tab><tab>1 <lt>= N <lt>= 16<nl>
  78. @flag <f IsdnNumDChannels> (OPTIONAL) |
  79. This DWORD parameter allows you to control the number of ISDN D Channels
  80. allocated for the adapter. The driver assumes only one logical
  81. <t DCHANNEL_OBJECT>, but the card can have multiple physical D channels
  82. managed by the <t PORT_OBJECT>.
  83. <tab><f Default Value:><tab><tab>1<nl>
  84. <tab><f Valid Range N:><tab><tab>1 <lt>= N <lt>= 16<nl>
  85. */
  86. DBG_STATIC PARAM_TABLE g_CardParameters[] =
  87. {
  88. #if defined(PCI_BUS)
  89. PARAM_ENTRY(CARD_OBJECT,
  90. PciSlotNumber, PARAM_PciSlotNumber,
  91. TRUE, NdisParameterInteger, 0,
  92. 0, 0, 31),
  93. #endif // PCI_BUS
  94. PARAM_ENTRY(CARD_OBJECT,
  95. BufferSize, PARAM_BufferSize,
  96. FALSE, NdisParameterInteger, 0,
  97. CARD_DEFAULT_PACKET_SIZE, CARD_MIN_PACKET_SIZE, CARD_MAX_PACKET_SIZE),
  98. PARAM_ENTRY(CARD_OBJECT,
  99. ReceiveBuffersPerLink, PARAM_ReceiveBuffersPerLink,
  100. FALSE, NdisParameterInteger, 0,
  101. 2, 2, 16),
  102. PARAM_ENTRY(CARD_OBJECT,
  103. TransmitBuffersPerLink, PARAM_TransmitBuffersPerLink,
  104. FALSE, NdisParameterInteger, 0,
  105. 2, 1, 16),
  106. PARAM_ENTRY(CARD_OBJECT,
  107. NumDChannels, PARAM_NumDChannels,
  108. FALSE, NdisParameterInteger, 0,
  109. 1, 1, 4),
  110. /* The last entry must be an empty string! */
  111. { { 0 } }
  112. };
  113. /* @doc INTERNAL Card Card_c CardReadParameters
  114. @func
  115. <f CardReadParameters> reads the Card parameters from the registry
  116. and initializes the associated data members. This should only be called
  117. by <f CardCreate>.
  118. <f Note>:
  119. If you add any registry based data members to <t CARD_OBJECT>
  120. you will need to modify <f CardReadParameters> and add the parameter
  121. definitions to the <f g_CardParameters> table.
  122. @rdesc
  123. <f CardReadParameters> returns zero if it is successful.<nl>
  124. Otherwise, a non-zero return value indicates an error condition.
  125. */
  126. DBG_STATIC NDIS_STATUS CardReadParameters(
  127. IN PCARD_OBJECT pCard // @parm
  128. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  129. )
  130. {
  131. DBG_FUNC("CardReadParameters")
  132. NDIS_STATUS Status;
  133. // Status result returned from an NDIS function call.
  134. PMINIPORT_ADAPTER_OBJECT pAdapter;
  135. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  136. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  137. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  138. DBG_ENTER(pAdapter);
  139. /*
  140. // Parse the registry parameters.
  141. */
  142. Status = ParamParseRegistry(
  143. pAdapter->MiniportAdapterHandle,
  144. pAdapter->WrapperConfigurationContext,
  145. (PUCHAR)pCard,
  146. g_CardParameters
  147. );
  148. if (Status == NDIS_STATUS_SUCCESS)
  149. {
  150. /*
  151. // Make sure the parameters are valid.
  152. */
  153. if (pCard->BufferSize & 0x1F)
  154. {
  155. DBG_ERROR(pAdapter,("Invalid value 'BufferSize'=0x0x%X must be multiple of 32\n",
  156. pCard->BufferSize));
  157. NdisWriteErrorLogEntry(
  158. pAdapter->MiniportAdapterHandle,
  159. NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
  160. 3,
  161. pCard->BufferSize,
  162. __FILEID__,
  163. __LINE__
  164. );
  165. Status = NDIS_STATUS_FAILURE;
  166. }
  167. else
  168. {
  169. /*
  170. // Finish setting up data members based on registry settings.
  171. */
  172. }
  173. }
  174. DBG_RETURN(pAdapter, Status);
  175. return (Status);
  176. }
  177. /* @doc INTERNAL Card Card_c CardFindNIC
  178. @func
  179. <f CardFindNIC> locates the NIC associated with this NDIS device.
  180. @rdesc
  181. <f CardFindNIC> returns zero if it is successful.<nl>
  182. Otherwise, a non-zero return value indicates an error condition.
  183. */
  184. DBG_STATIC NDIS_STATUS CardFindNIC(
  185. IN PCARD_OBJECT pCard // @parm
  186. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  187. )
  188. {
  189. DBG_FUNC("CardFindNIC")
  190. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  191. // Holds the result code returned by this function.
  192. #if defined(PCI_BUS)
  193. ULONG Index;
  194. // Loop counter.
  195. PNDIS_RESOURCE_LIST pPciResourceList;
  196. PCM_PARTIAL_RESOURCE_DESCRIPTOR pPciResource;
  197. #endif // PCI_BUS
  198. PMINIPORT_ADAPTER_OBJECT pAdapter;
  199. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  200. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  201. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  202. DBG_ENTER(pAdapter);
  203. #if defined(PCI_BUS)
  204. /*
  205. // Read the PCI data and initialize the driver data structure
  206. // with the data returned.
  207. */
  208. pPciResourceList = NULL;
  209. Result = NdisMPciAssignResources(pAdapter->MiniportAdapterHandle,
  210. pCard->PciSlotNumber,
  211. &pPciResourceList);
  212. if (Result != NDIS_STATUS_SUCCESS)
  213. {
  214. DBG_ERROR(pAdapter,("NdisMPciAssignResources Result=0x%X\n",
  215. Result));
  216. NdisWriteErrorLogEntry(
  217. pAdapter->MiniportAdapterHandle,
  218. NDIS_ERROR_CODE_INVALID_VALUE_FROM_ADAPTER,
  219. 4,
  220. pCard->PciSlotNumber,
  221. Result,
  222. __FILEID__,
  223. __LINE__
  224. );
  225. }
  226. for (Index = 0; Result == NDIS_STATUS_SUCCESS &&
  227. Index < pPciResourceList->Count; ++Index)
  228. {
  229. ASSERT(pPciResourceList);
  230. pPciResource = &pPciResourceList->PartialDescriptors[Index];
  231. ASSERT(pPciResource);
  232. switch (pPciResource->Type)
  233. {
  234. case CmResourceTypePort:
  235. #if defined(CARD_MIN_IOPORT_SIZE)
  236. if (pPciResource->u.Port.Start.LowPart &&
  237. pPciResource->u.Port.Length >= CARD_MIN_IOPORT_SIZE)
  238. {
  239. DBG_NOTICE(pAdapter,("Port: Ptr=0x%X Len=%d<%d\n",
  240. pPciResource->u.Port.Start.LowPart,
  241. pPciResource->u.Port.Length,
  242. CARD_MIN_IOPORT_SIZE));
  243. pCard->ResourceInformation.IoPortPhysicalAddress =
  244. pPciResource->u.Port.Start;
  245. pCard->ResourceInformation.IoPortLength =
  246. pPciResource->u.Port.Length;
  247. }
  248. else
  249. {
  250. DBG_ERROR(pAdapter,("Invalid Port: Ptr=0x%X Len=%d<%d\n",
  251. pPciResource->u.Port.Start,
  252. pPciResource->u.Port.Length,
  253. CARD_MIN_IOPORT_SIZE));
  254. NdisWriteErrorLogEntry(
  255. pAdapter->MiniportAdapterHandle,
  256. NDIS_ERROR_CODE_INVALID_VALUE_FROM_ADAPTER,
  257. 4,
  258. pPciResource->u.Port.Length,
  259. CARD_MIN_IOPORT_SIZE,
  260. __FILEID__,
  261. __LINE__
  262. );
  263. Result = NDIS_STATUS_RESOURCE_CONFLICT;
  264. }
  265. #endif // CARD_MIN_IOPORT_SIZE
  266. break;
  267. case CmResourceTypeInterrupt:
  268. #if defined(CARD_REQUEST_ISR)
  269. if (pPciResource->u.Interrupt.Level)
  270. {
  271. DBG_NOTICE(pAdapter,("Interrupt: Lev=%d,Vec=%d\n",
  272. pPciResource->u.Interrupt.Level,
  273. pPciResource->u.Interrupt.Vector));
  274. pCard->ResourceInformation.InterruptLevel =
  275. pPciResource->u.Interrupt.Level;
  276. pCard->ResourceInformation.InterruptVector =
  277. pPciResource->u.Interrupt.Vector;
  278. pCard->ResourceInformation.InterruptShared = CARD_INTERRUPT_SHARED;
  279. pCard->ResourceInformation.InterruptMode = CARD_INTERRUPT_MODE;
  280. }
  281. else
  282. {
  283. DBG_ERROR(pAdapter,("Invalid Interrupt: Lev=%d,Vec=%d\n",
  284. pPciResource->u.Interrupt.Level,
  285. pPciResource->u.Interrupt.Vector));
  286. NdisWriteErrorLogEntry(
  287. pAdapter->MiniportAdapterHandle,
  288. NDIS_ERROR_CODE_INVALID_VALUE_FROM_ADAPTER,
  289. 4,
  290. pPciResource->u.Interrupt.Level,
  291. pPciResource->u.Interrupt.Vector,
  292. __FILEID__,
  293. __LINE__
  294. );
  295. Result = NDIS_STATUS_RESOURCE_CONFLICT;
  296. }
  297. #endif // defined(CARD_REQUEST_ISR)
  298. break;
  299. case CmResourceTypeMemory:
  300. #if defined(CARD_MIN_MEMORY_SIZE)
  301. if (pPciResource->u.Memory.Start.LowPart &&
  302. pPciResource->u.Memory.Length >= CARD_MIN_MEMORY_SIZE)
  303. {
  304. DBG_NOTICE(pAdapter,("Memory: Ptr=0x%X Len=%d<%d\n",
  305. pPciResource->u.Memory.Start.LowPart,
  306. pPciResource->u.Memory.Length,
  307. CARD_MIN_MEMORY_SIZE));
  308. pCard->ResourceInformation.MemoryPhysicalAddress =
  309. pPciResource->u.Memory.Start;
  310. pCard->ResourceInformation.MemoryLength =
  311. pPciResource->u.Memory.Length;
  312. }
  313. else
  314. {
  315. DBG_ERROR(pAdapter,("Invalid Memory: Ptr=0x%X Len=%d<%d\n",
  316. pPciResource->u.Memory.Start.LowPart,
  317. pPciResource->u.Memory.Length,
  318. CARD_MIN_MEMORY_SIZE));
  319. NdisWriteErrorLogEntry(
  320. pAdapter->MiniportAdapterHandle,
  321. NDIS_ERROR_CODE_INVALID_VALUE_FROM_ADAPTER,
  322. 4,
  323. pPciResource->u.Memory.Length,
  324. CARD_MIN_MEMORY_SIZE,
  325. __FILEID__,
  326. __LINE__
  327. );
  328. Result = NDIS_STATUS_RESOURCE_CONFLICT;
  329. }
  330. break;
  331. #endif // CARD_MIN_MEMORY_SIZE
  332. default:
  333. DBG_ERROR(pAdapter,("Unknown resource type=%d\n",
  334. pPciResource->Type));
  335. break;
  336. }
  337. }
  338. pCard->ResourceInformation.BusInterfaceType = NdisInterfacePci;
  339. #endif // PCI_BUS
  340. pCard->ResourceInformation.Master = CARD_IS_BUS_MASTER;
  341. #if (CARD_IS_BUS_MASTER)
  342. pCard->ResourceInformation.DmaChannel = 0;
  343. pCard->ResourceInformation.Dma32BitAddresses = TRUE,
  344. pCard->ResourceInformation.MaximumPhysicalMapping = pCard->BufferSize;
  345. pCard->ResourceInformation.PhysicalMapRegistersNeeded = CARD_MAP_REGISTERS_NEEDED;
  346. #endif // (CARD_IS_BUS_MASTER)
  347. DBG_RETURN(pAdapter, Result);
  348. return (Result);
  349. }
  350. /* @doc INTERNAL Card Card_c CardCreateInterface
  351. @func
  352. <f CardCreateInterface> allocates a shared memory pool and uses it to
  353. establish the message interface between the Miniport and the NIC.
  354. @rdesc
  355. <f CardCreateInterface> returns zero if it is successful.<nl>
  356. Otherwise, a non-zero return value indicates an error condition.
  357. */
  358. DBG_STATIC NDIS_STATUS CardCreateInterface(
  359. IN PCARD_OBJECT pCard // @parm
  360. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  361. )
  362. {
  363. DBG_FUNC("CardCreateObjects")
  364. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  365. // Holds the result code returned by this function.
  366. PMINIPORT_ADAPTER_OBJECT pAdapter;
  367. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  368. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  369. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  370. DBG_ENTER(pAdapter);
  371. DBG_RETURN(pAdapter, Result);
  372. return (Result);
  373. }
  374. /* @doc INTERNAL Card Card_c CardCreateObjects
  375. @func
  376. <f CardCreateObjects> calls the create routines for all the objects
  377. contained in <t CARD_OBJECT>. This should only be called
  378. by <f CardCreate>.
  379. <f Note>:
  380. If you add any new objects to <t CARD_OBJECT> you will need
  381. to modify <f CardCreateObjects> and <f CardDestroyObjects> so they
  382. will get created and destroyed properly.
  383. @rdesc
  384. <f CardCreateObjects> returns zero if it is successful.<nl>
  385. Otherwise, a non-zero return value indicates an error condition.
  386. */
  387. DBG_STATIC NDIS_STATUS CardCreateObjects(
  388. IN PCARD_OBJECT pCard // @parm
  389. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  390. )
  391. {
  392. DBG_FUNC("CardCreateObjects")
  393. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  394. // Holds the result code returned by this function.
  395. ULONG Index;
  396. // Loop counter.
  397. ULONG NumPorts;
  398. // The number of Ports supported by the NIC.
  399. PMINIPORT_ADAPTER_OBJECT pAdapter;
  400. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  401. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  402. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  403. DBG_ENTER(pAdapter);
  404. /*
  405. // Try to locate the NIC on the PCI bus.
  406. */
  407. Result = CardFindNIC(pCard);
  408. if (Result != NDIS_STATUS_SUCCESS)
  409. {
  410. goto ExceptionExit;
  411. }
  412. /*
  413. // Create the message interface to the NIC.
  414. */
  415. Result = CardCreateInterface(pCard);
  416. if (Result != NDIS_STATUS_SUCCESS)
  417. {
  418. goto ExceptionExit;
  419. }
  420. /*
  421. // Create the Port objects.
  422. */
  423. NumPorts = CardNumPorts(pCard);
  424. Result = ALLOCATE_MEMORY(pCard->pPortArray,
  425. sizeof(PVOID) * NumPorts,
  426. pAdapter->MiniportAdapterHandle);
  427. for (Index = 0; Result == NDIS_STATUS_SUCCESS &&
  428. Index < NumPorts; Index++)
  429. {
  430. Result = PortCreate(&pCard->pPortArray[Index], pCard);
  431. /*
  432. // Keep track of how many are created.
  433. */
  434. if (Result == NDIS_STATUS_SUCCESS)
  435. {
  436. pCard->NumPorts++;
  437. }
  438. }
  439. /*
  440. // We allocate (ReceiveBuffersPerLink * NumBChannels) buffers
  441. // to be used to receive incoming messages from the card.
  442. */
  443. pCard->NumMessageBuffers = (CardNumChannels(pCard) *
  444. pCard->ReceiveBuffersPerLink);
  445. Result = ALLOCATE_MEMORY(pCard->MessagesVirtualAddress,
  446. pCard->NumMessageBuffers * pCard->BufferSize,
  447. pAdapter->MiniportAdapterHandle);
  448. if (Result == NDIS_STATUS_SUCCESS)
  449. {
  450. PUCHAR MessageBuffer = pCard->MessagesVirtualAddress;
  451. ULONG Index;
  452. ASSERT(pCard->MessagesVirtualAddress);
  453. /*
  454. // Allocate the buffer list spin lock to use as a MUTEX.
  455. */
  456. NdisAllocateSpinLock(&pCard->MessageBufferLock);
  457. InitializeListHead(&pCard->MessageBufferList);
  458. for (Index = 0; Index < pCard->NumMessageBuffers; Index++)
  459. {
  460. InsertTailList(&pCard->MessageBufferList,
  461. (PLIST_ENTRY)MessageBuffer);
  462. MessageBuffer += pCard->BufferSize;
  463. }
  464. }
  465. /*
  466. // Allocate the message buffer pool.
  467. */
  468. if (Result == NDIS_STATUS_SUCCESS)
  469. {
  470. NdisAllocateBufferPool(&Result,
  471. &pCard->BufferPoolHandle,
  472. pCard->NumMessageBuffers
  473. );
  474. if (Result != NDIS_STATUS_SUCCESS)
  475. {
  476. pCard->BufferPoolHandle = NULL_BUFFER_POOL;
  477. DBG_ERROR(pAdapter,("NdisAllocateBufferPool: Result=0x%X\n",
  478. Result));
  479. NdisWriteErrorLogEntry(
  480. pCard->pAdapter->MiniportAdapterHandle,
  481. NDIS_ERROR_CODE_OUT_OF_RESOURCES,
  482. 3,
  483. Result,
  484. __FILEID__,
  485. __LINE__
  486. );
  487. }
  488. else
  489. {
  490. ASSERT(pCard->BufferPoolHandle != NULL_BUFFER_POOL);
  491. DBG_FILTER(pAdapter, DBG_BUFFER_ON,
  492. ("BufferPoolSize=%d\n",
  493. pCard->NumMessageBuffers
  494. ));
  495. }
  496. }
  497. /*
  498. // Allocate the message packet pool.
  499. */
  500. if (Result == NDIS_STATUS_SUCCESS)
  501. {
  502. NdisAllocatePacketPool(&Result,
  503. &pCard->PacketPoolHandle,
  504. pCard->NumMessageBuffers,
  505. 0
  506. );
  507. if (Result != NDIS_STATUS_SUCCESS)
  508. {
  509. DBG_ERROR(pAdapter,("NdisAllocatePacketPool: Result=0x%X\n",
  510. Result));
  511. NdisWriteErrorLogEntry(
  512. pCard->pAdapter->MiniportAdapterHandle,
  513. NDIS_ERROR_CODE_OUT_OF_RESOURCES,
  514. 3,
  515. Result,
  516. __FILEID__,
  517. __LINE__
  518. );
  519. }
  520. else
  521. {
  522. ASSERT(pCard->PacketPoolHandle);
  523. DBG_FILTER(pAdapter, DBG_PACKET_ON,
  524. ("PacketPoolSize=%d\n",
  525. pCard->NumMessageBuffers
  526. ));
  527. }
  528. }
  529. ExceptionExit:
  530. DBG_RETURN(pAdapter, Result);
  531. return (Result);
  532. }
  533. /* @doc INTERNAL Card Card_c CardCreate
  534. @func
  535. <f CardCreate> allocates memory for a <t CARD_OBJECT> and then
  536. initializes the data members to their starting state.
  537. If successful, <p ppCard> will be set to point to the newly created
  538. <t CARD_OBJECT>. Otherwise, <p ppCard> will be set to NULL.
  539. @comm
  540. This function should be called only once when the Miniport is loaded.
  541. Before the Miniport is unloaded, <f CardDestroy> must be called to
  542. release the <t CARD_OBJECT> created by this function.
  543. @rdesc
  544. <f CardCreate> returns zero if it is successful.<nl>
  545. Otherwise, a non-zero return value indicates an error condition.
  546. */
  547. NDIS_STATUS CardCreate(
  548. OUT PCARD_OBJECT * ppCard, // @parm
  549. // Points to a caller-defined memory location to which this function
  550. // writes the virtual address of the allocated <t CARD_OBJECT>.
  551. IN PMINIPORT_ADAPTER_OBJECT pAdapter // @parm
  552. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
  553. )
  554. {
  555. DBG_FUNC("CardCreate")
  556. PCARD_OBJECT pCard;
  557. // Pointer to our newly allocated object.
  558. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  559. // Holds the result code returned by this function.
  560. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  561. DBG_ENTER(pAdapter);
  562. /*
  563. // Make sure the caller's object pointer is NULL to begin with.
  564. // It will be set later only if everything is successful.
  565. */
  566. *ppCard = NULL;
  567. /*
  568. // Allocate memory for the object.
  569. */
  570. Result = ALLOCATE_OBJECT(pCard, pAdapter->MiniportAdapterHandle);
  571. if (Result == NDIS_STATUS_SUCCESS)
  572. {
  573. /*
  574. // Zero everything to begin with.
  575. // Then set the object type and assign a unique ID .
  576. */
  577. pCard->ObjectType = CARD_OBJECT_TYPE;
  578. pCard->ObjectID = ++g_CardInstanceCounter;
  579. /*
  580. // Initialize the member variables to their default settings.
  581. */
  582. pCard->pAdapter = pAdapter;
  583. // TODO - Add code here
  584. /*
  585. // Parse the registry parameters.
  586. */
  587. Result = CardReadParameters(pCard);
  588. /*
  589. // If all goes well, we are ready to create the sub-components.
  590. */
  591. if (Result == NDIS_STATUS_SUCCESS)
  592. {
  593. Result = CardCreateObjects(pCard);
  594. }
  595. if (Result == NDIS_STATUS_SUCCESS)
  596. {
  597. /*
  598. // All is well, so return the object pointer to the caller.
  599. */
  600. *ppCard = pCard;
  601. }
  602. else
  603. {
  604. /*
  605. // Something went wrong, so let's make sure everything is
  606. // cleaned up.
  607. */
  608. CardDestroy(pCard);
  609. }
  610. }
  611. DBG_RETURN(pAdapter, Result);
  612. return (Result);
  613. }
  614. /* @doc INTERNAL Card Card_c CardDestroyObjects
  615. @func
  616. <f CardDestroyObjects> calls the destroy routines for all the objects
  617. contained in <t CARD_OBJECT>. This should only be called by
  618. <f CardDestroy>.
  619. <f Note>:
  620. If you add any new objects to <t PCARD_OBJECT> you will need to
  621. modify <f CardCreateObjects> and <f CardDestroyObjects> so they
  622. will get created and destroyed properly.
  623. */
  624. DBG_STATIC void CardDestroyObjects(
  625. IN PCARD_OBJECT pCard // @parm
  626. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  627. )
  628. {
  629. DBG_FUNC("CardDestroyObjects")
  630. ULONG NumPorts;
  631. // The number of Ports supported by the NIC.
  632. PMINIPORT_ADAPTER_OBJECT pAdapter;
  633. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  634. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  635. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  636. DBG_ENTER(pAdapter);
  637. // TODO - Add code here
  638. /*
  639. // Release the packet, buffer, and message memory back to NDIS.
  640. */
  641. if (pCard->PacketPoolHandle)
  642. {
  643. NdisFreePacketPool(pCard->PacketPoolHandle);
  644. }
  645. if (pCard->BufferPoolHandle != NULL_BUFFER_POOL)
  646. {
  647. NdisFreeBufferPool(pCard->BufferPoolHandle);
  648. }
  649. if (pCard->MessagesVirtualAddress)
  650. {
  651. FREE_MEMORY(pCard->MessagesVirtualAddress,
  652. pCard->NumMessageBuffers * pCard->BufferSize);
  653. }
  654. if (pCard->MessageBufferLock.SpinLock)
  655. {
  656. NdisFreeSpinLock(&pCard->MessageBufferLock);
  657. }
  658. /*
  659. // Destory the Port objects.
  660. */
  661. NumPorts = pCard->NumPorts;
  662. while (NumPorts--)
  663. {
  664. PortDestroy(pCard->pPortArray[NumPorts]);
  665. }
  666. pCard->NumPorts = 0;
  667. /*
  668. // Free space for the Ports.
  669. */
  670. if (pCard->pPortArray)
  671. {
  672. NumPorts = CardNumPorts(pCard);
  673. FREE_MEMORY(pCard->pPortArray, sizeof(PVOID) * NumPorts);
  674. }
  675. /*
  676. // Release the system resources back to NDIS.
  677. */
  678. #if defined(CARD_REQUEST_ISR)
  679. if (pCard->Interrupt.InterruptObject)
  680. {
  681. NdisMDeregisterInterrupt(&pCard->Interrupt);
  682. pCard->Interrupt.InterruptObject = NULL;
  683. }
  684. #endif // defined(CARD_REQUEST_ISR)
  685. #if defined(CARD_MIN_IOPORT_SIZE)
  686. if (pCard->pIoPortVirtualAddress)
  687. {
  688. NdisMDeregisterIoPortRange(
  689. pAdapter->MiniportAdapterHandle,
  690. pCard->ResourceInformation.IoPortPhysicalAddress.LowPart,
  691. pCard->ResourceInformation.IoPortLength,
  692. pCard->pIoPortVirtualAddress);
  693. pCard->pIoPortVirtualAddress = NULL;
  694. }
  695. #endif // CARD_MIN_IOPORT_SIZE
  696. #if defined(CARD_MIN_MEMORY_SIZE)
  697. if (pCard->pMemoryVirtualAddress)
  698. {
  699. NdisMUnmapIoSpace(
  700. pAdapter->MiniportAdapterHandle,
  701. pCard->pMemoryVirtualAddress,
  702. pCard->ResourceInformation.MemoryLength
  703. );
  704. pCard->pMemoryVirtualAddress = NULL;
  705. }
  706. #endif // CARD_MIN_MEMORY_SIZE
  707. DBG_LEAVE(pAdapter);
  708. }
  709. /* @doc INTERNAL Card Card_c CardDestroy
  710. @func
  711. <f CardDestroy> frees the memory for this <t CARD_OBJECT>. All memory
  712. allocated by <f CardCreate> will be released back to the OS.
  713. */
  714. void CardDestroy(
  715. IN PCARD_OBJECT pCard // @parm
  716. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  717. )
  718. {
  719. DBG_FUNC("CardDestroy")
  720. PMINIPORT_ADAPTER_OBJECT pAdapter;
  721. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  722. if (pCard)
  723. {
  724. ASSERT(pCard->ObjectType == CARD_OBJECT_TYPE);
  725. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  726. DBG_ENTER(pAdapter);
  727. // TODO - Add code here
  728. /*
  729. // Release all objects allocated within this object.
  730. */
  731. CardDestroyObjects(pCard);
  732. /*
  733. // Make sure we fail the ASSERT if we see this object again.
  734. */
  735. pCard->ObjectType = 0;
  736. FREE_OBJECT(pCard);
  737. DBG_LEAVE(pAdapter);
  738. }
  739. }
  740. /* @doc INTERNAL Card Card_c CardNumPorts
  741. @func
  742. <f CardNumPorts> will return the total number of ports available on the
  743. NIC.
  744. @rdesc
  745. <f CardNumPorts> returns the total number of ports available.
  746. */
  747. ULONG CardNumPorts(
  748. IN PCARD_OBJECT pCard // @parm
  749. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  750. )
  751. {
  752. DBG_FUNC("CardNumPorts")
  753. // TODO - Get the actual number of ports from the card.
  754. return (pCard->NumDChannels);
  755. }
  756. /* @doc INTERNAL Card Card_c CardNumChannels
  757. @func
  758. <f CardNumChannels> will return the total number of channels capable
  759. of supporting data connections to a remote end-point.
  760. @rdesc
  761. <f CardNumChannels> returns the total number of data channels supported
  762. on all the NIC ports.
  763. */
  764. ULONG CardNumChannels(
  765. IN PCARD_OBJECT pCard // @parm
  766. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  767. )
  768. {
  769. DBG_FUNC("CardNumChannels")
  770. UINT PortIndex;
  771. // Loop index.
  772. if (pCard->NumChannels == 0)
  773. {
  774. // NumPorts should already be known.
  775. ASSERT(pCard->NumPorts);
  776. // Get the actual number of channels configured on all ports.
  777. for (PortIndex = 0; PortIndex < pCard->NumPorts; PortIndex++)
  778. {
  779. pCard->NumChannels += pCard->pPortArray[PortIndex]->NumChannels;
  780. }
  781. ASSERT(pCard->NumChannels);
  782. }
  783. return (pCard->NumChannels);
  784. }
  785. /* @doc INTERNAL Card Card_c CardInitialize
  786. @func
  787. <f CardInitialize> will attempt to initialize the NIC, but will not
  788. enable transmits or receives.
  789. @rdesc
  790. <f CardInitialize> returns zero if it is successful.<nl>
  791. Otherwise, a non-zero return value indicates an error condition.
  792. */
  793. NDIS_STATUS CardInitialize(
  794. IN PCARD_OBJECT pCard // @parm
  795. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  796. )
  797. {
  798. DBG_FUNC("CardInitialize")
  799. int num_dial_chan = 0;
  800. int num_sync_chan = 0;
  801. // The number of channels supported by card is based on InterfaceType.
  802. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  803. // Holds the result code returned by this function.
  804. PMINIPORT_ADAPTER_OBJECT pAdapter;
  805. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  806. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  807. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  808. DBG_ENTER(pAdapter);
  809. /*
  810. // Inform the wrapper of the physical attributes of this adapter.
  811. // This must be called before any NdisMRegister functions!
  812. // This call also associates the MiniportAdapterHandle with this pAdapter.
  813. */
  814. NdisMSetAttributes(pAdapter->MiniportAdapterHandle,
  815. (NDIS_HANDLE) pAdapter,
  816. pCard->ResourceInformation.Master,
  817. pCard->ResourceInformation.BusInterfaceType
  818. );
  819. #if (CARD_IS_BUS_MASTER)
  820. if (pCard->ResourceInformation.Master)
  821. {
  822. ASSERT(pCard->ResourceInformation.DmaChannel == 0 ||
  823. pCard->ResourceInformation.BusInterfaceType == NdisInterfaceIsa);
  824. Result = NdisMAllocateMapRegisters(
  825. pAdapter->MiniportAdapterHandle,
  826. pCard->ResourceInformation.DmaChannel,
  827. pCard->ResourceInformation.Dma32BitAddresses,
  828. pCard->ResourceInformation.PhysicalMapRegistersNeeded + 1,
  829. pCard->ResourceInformation.MaximumPhysicalMapping
  830. );
  831. if (Result != NDIS_STATUS_SUCCESS)
  832. {
  833. DBG_ERROR(pAdapter,("NdisMAllocateMapRegisters(%d,%d) Result=0x%X\n",
  834. pCard->ResourceInformation.PhysicalMapRegistersNeeded,
  835. pCard->ResourceInformation.MaximumPhysicalMapping,
  836. Result));
  837. NdisWriteErrorLogEntry(
  838. pAdapter->MiniportAdapterHandle,
  839. NDIS_ERROR_CODE_RESOURCE_CONFLICT,
  840. 5,
  841. pCard->ResourceInformation.PhysicalMapRegistersNeeded,
  842. pCard->ResourceInformation.MaximumPhysicalMapping,
  843. Result,
  844. __FILEID__,
  845. __LINE__
  846. );
  847. }
  848. }
  849. #endif // (CARD_IS_BUS_MASTER)
  850. #if defined(CARD_MIN_MEMORY_SIZE)
  851. if (Result == NDIS_STATUS_SUCCESS &&
  852. pCard->ResourceInformation.MemoryLength)
  853. {
  854. Result = NdisMMapIoSpace(
  855. &pCard->pMemoryVirtualAddress,
  856. pAdapter->MiniportAdapterHandle,
  857. pCard->ResourceInformation.MemoryPhysicalAddress,
  858. pCard->ResourceInformation.MemoryLength);
  859. if (Result != NDIS_STATUS_SUCCESS)
  860. {
  861. DBG_ERROR(pAdapter,("NdisMMapIoSpace(0x%X,0x%X) Result=0x%X\n",
  862. pCard->ResourceInformation.MemoryPhysicalAddress.LowPart,
  863. pCard->ResourceInformation.MemoryLength,
  864. Result));
  865. NdisWriteErrorLogEntry(
  866. pAdapter->MiniportAdapterHandle,
  867. NDIS_ERROR_CODE_RESOURCE_CONFLICT,
  868. 5,
  869. pCard->ResourceInformation.MemoryPhysicalAddress.LowPart,
  870. pCard->ResourceInformation.MemoryLength,
  871. Result,
  872. __FILEID__,
  873. __LINE__
  874. );
  875. }
  876. else
  877. {
  878. DBG_NOTICE(pAdapter,("NdisMMapIoSpace(0x%X,0x%X) VirtualAddress=0x%X\n",
  879. pCard->ResourceInformation.MemoryPhysicalAddress.LowPart,
  880. pCard->ResourceInformation.MemoryLength,
  881. pCard->pMemoryVirtualAddress));
  882. }
  883. }
  884. #endif // CARD_MIN_MEMORY_SIZE
  885. #if defined(CARD_MIN_IOPORT_SIZE)
  886. if (Result == NDIS_STATUS_SUCCESS &&
  887. pCard->ResourceInformation.IoPortLength)
  888. {
  889. Result = NdisMRegisterIoPortRange(
  890. &pCard->pIoPortVirtualAddress,
  891. pAdapter->MiniportAdapterHandle,
  892. pCard->ResourceInformation.IoPortPhysicalAddress.LowPart,
  893. pCard->ResourceInformation.IoPortLength);
  894. if (Result != NDIS_STATUS_SUCCESS)
  895. {
  896. DBG_ERROR(pAdapter,("NdisMRegisterIoPortRange(0x%X,0x%X) Result=0x%X\n",
  897. pCard->ResourceInformation.IoPortPhysicalAddress.LowPart,
  898. pCard->ResourceInformation.IoPortLength,
  899. Result));
  900. NdisWriteErrorLogEntry(
  901. pAdapter->MiniportAdapterHandle,
  902. NDIS_ERROR_CODE_RESOURCE_CONFLICT,
  903. 5,
  904. pCard->ResourceInformation.IoPortPhysicalAddress.LowPart,
  905. pCard->ResourceInformation.IoPortLength,
  906. Result,
  907. __FILEID__,
  908. __LINE__
  909. );
  910. }
  911. else
  912. {
  913. DBG_NOTICE(pAdapter,("NdisMRegisterIoPortRange(0x%X,0x%X) VirtualAddress=0x%X\n",
  914. pCard->ResourceInformation.IoPortPhysicalAddress.LowPart,
  915. pCard->ResourceInformation.IoPortLength,
  916. pCard->pIoPortVirtualAddress));
  917. }
  918. }
  919. #endif // CARD_MIN_IOPORT_SIZE
  920. #if defined(CARD_REQUEST_ISR)
  921. if (Result == NDIS_STATUS_SUCCESS &&
  922. pCard->ResourceInformation.InterruptVector)
  923. {
  924. ASSERT(pCard->ResourceInformation.InterruptShared == FALSE ||
  925. (pCard->ResourceInformation.InterruptMode == NdisInterruptLevelSensitive &&
  926. CARD_REQUEST_ISR == TRUE));
  927. Result = NdisMRegisterInterrupt(
  928. &pCard->Interrupt,
  929. pAdapter->MiniportAdapterHandle,
  930. pCard->ResourceInformation.InterruptVector,
  931. pCard->ResourceInformation.InterruptLevel,
  932. CARD_REQUEST_ISR,
  933. pCard->ResourceInformation.InterruptShared,
  934. pCard->ResourceInformation.InterruptMode
  935. );
  936. if (Result != NDIS_STATUS_SUCCESS)
  937. {
  938. DBG_ERROR(pAdapter,("NdisMRegisterInterrupt failed: Vec=%d, Lev=%d\n",
  939. (UINT)pCard->ResourceInformation.InterruptVector,
  940. (UINT)pCard->ResourceInformation.InterruptLevel));
  941. NdisWriteErrorLogEntry(
  942. pAdapter->MiniportAdapterHandle,
  943. NDIS_ERROR_CODE_RESOURCE_CONFLICT,
  944. 5,
  945. pCard->ResourceInformation.InterruptVector,
  946. pCard->ResourceInformation.InterruptLevel,
  947. Result,
  948. __FILEID__,
  949. __LINE__
  950. );
  951. }
  952. }
  953. #endif // defined(CARD_REQUEST_ISR)
  954. // TODO - Add your card initialization here.
  955. if (Result == NDIS_STATUS_SUCCESS)
  956. {
  957. }
  958. DBG_RETURN(pAdapter, Result);
  959. return (Result);
  960. }
  961. /* @doc INTERNAL Card Card_c CardTransmitPacket
  962. @func
  963. <f CardTransmitPacket> will start sending the current packet out.
  964. @rdesc
  965. <f CardTransmitPacket> returns TRUE if the packet is being transmitted,
  966. otherwise FALSE is returned.
  967. */
  968. BOOLEAN CardTransmitPacket(
  969. IN PCARD_OBJECT pCard, // @parm
  970. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  971. IN PBCHANNEL_OBJECT pBChannel, // @parm
  972. // A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
  973. IN PNDIS_PACKET pNdisPacket // @parm
  974. // A pointer to the associated NDIS packet structure <t NDIS_PACKET>.
  975. )
  976. {
  977. DBG_FUNC("CardTransmitPacket")
  978. BOOLEAN bResult = FALSE;
  979. // Holds the result code returned by this function.
  980. PMINIPORT_ADAPTER_OBJECT pAdapter;
  981. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  982. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  983. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  984. DBG_ENTER(pAdapter);
  985. #if defined(SAMPLE_DRIVER)
  986. {
  987. PBCHANNEL_OBJECT pPeerBChannel;
  988. // A pointer to the peer <t BCHANNEL_OBJECT>.
  989. PCARD_EVENT_OBJECT pEvent;
  990. // A pointer to the <t CARD_EVENT_OBJECT> associated with this event.
  991. // If you can transmit the packet on pBChannel, do it now.
  992. pPeerBChannel = pBChannel->pPeerBChannel;
  993. if (pPeerBChannel)
  994. {
  995. pEvent = CardEventAllocate(pPeerBChannel->pAdapter->pCard);
  996. if (pEvent)
  997. {
  998. /*
  999. // Append the packet onto TransmitBusyList while it is being sent.
  1000. // Then move it to the TransmitCompleteList in CardInterruptHandler
  1001. // after the card is done with it.
  1002. */
  1003. NdisAcquireSpinLock(&pAdapter->TransmitLock);
  1004. InsertTailList(&pBChannel->TransmitBusyList,
  1005. GET_QUEUE_FROM_PACKET(pNdisPacket));
  1006. NdisReleaseSpinLock(&pAdapter->TransmitLock);
  1007. pEvent->ulEventCode = CARD_EVENT_RECEIVE;
  1008. pEvent->pSendingObject = pBChannel;
  1009. pEvent->pReceivingObject = pPeerBChannel;
  1010. pEvent->pNdisPacket = pNdisPacket;
  1011. CardNotifyEvent(pPeerBChannel->pAdapter->pCard, pEvent);
  1012. bResult = TRUE;
  1013. }
  1014. }
  1015. else
  1016. {
  1017. DBG_ERROR(pAdapter,("pPeerBChannel == NULL\n"));
  1018. }
  1019. }
  1020. #else // SAMPLE_DRIVER
  1021. // TODO - Add code here to transmit the packet.
  1022. DBG_TX(pAdapter, pBChannel->ObjectID,
  1023. BytesToSend, pNdisPacket->CurrentBuffer);
  1024. #endif // SAMPLE_DRIVER
  1025. DBG_RETURN(pAdapter, bResult);
  1026. return (bResult);
  1027. }
  1028. /* @doc EXTERNAL Card Card_c TpiCopyFromPacketToBuffer
  1029. @func
  1030. <f TpiCopyFromPacketToBuffer> copies from an NDIS packet into a memory
  1031. buffer.
  1032. */
  1033. DBG_STATIC VOID TpiCopyFromPacketToBuffer(
  1034. IN PNDIS_PACKET Packet, // @parm
  1035. // The packet to copy from.
  1036. IN UINT Offset, // @parm
  1037. // The offset from which to start the copy.
  1038. IN UINT BytesToCopy, // @parm
  1039. // The number of bytes to copy from the packet.
  1040. IN PUCHAR Buffer, // @parm
  1041. // The destination of the copy.
  1042. OUT PUINT BytesCopied // @parm
  1043. // The number of bytes actually copied. Can be less then
  1044. // BytesToCopy if the packet is shorter than BytesToCopy.
  1045. )
  1046. {
  1047. UINT NdisBufferCount;
  1048. PNDIS_BUFFER CurrentBuffer;
  1049. PVOID VirtualAddress;
  1050. UINT CurrentLength;
  1051. UINT LocalBytesCopied = 0;
  1052. UINT AmountToMove;
  1053. *BytesCopied = 0;
  1054. if (!BytesToCopy)
  1055. {
  1056. return;
  1057. }
  1058. //
  1059. // Get the first buffer.
  1060. //
  1061. NdisQueryPacket(
  1062. Packet,
  1063. NULL,
  1064. &NdisBufferCount,
  1065. &CurrentBuffer,
  1066. NULL
  1067. );
  1068. //
  1069. // Could have a null packet.
  1070. //
  1071. if (!NdisBufferCount)
  1072. {
  1073. return;
  1074. }
  1075. NdisQueryBuffer(
  1076. CurrentBuffer,
  1077. &VirtualAddress,
  1078. &CurrentLength
  1079. );
  1080. while (LocalBytesCopied < BytesToCopy)
  1081. {
  1082. if (!CurrentLength)
  1083. {
  1084. NdisGetNextBuffer(
  1085. CurrentBuffer,
  1086. &CurrentBuffer
  1087. );
  1088. //
  1089. // We've reached the end of the packet. We return
  1090. // with what we've done so far. (Which must be shorter
  1091. // than requested.
  1092. //
  1093. if (!CurrentBuffer)
  1094. {
  1095. break;
  1096. }
  1097. NdisQueryBuffer(
  1098. CurrentBuffer,
  1099. &VirtualAddress,
  1100. &CurrentLength
  1101. );
  1102. continue;
  1103. }
  1104. //
  1105. // Try to get us up to the point to start the copy.
  1106. //
  1107. if (Offset)
  1108. {
  1109. if (Offset > CurrentLength)
  1110. {
  1111. //
  1112. // What we want isn't in this buffer.
  1113. //
  1114. Offset -= CurrentLength;
  1115. CurrentLength = 0;
  1116. continue;
  1117. }
  1118. else
  1119. {
  1120. VirtualAddress = (PCHAR)VirtualAddress + Offset;
  1121. CurrentLength -= Offset;
  1122. Offset = 0;
  1123. }
  1124. }
  1125. //
  1126. // Copy the data.
  1127. //
  1128. AmountToMove =
  1129. ((CurrentLength <= (BytesToCopy - LocalBytesCopied)) ?
  1130. (CurrentLength):(BytesToCopy - LocalBytesCopied));
  1131. NdisMoveMemory(Buffer,VirtualAddress,AmountToMove);
  1132. Buffer = (PUCHAR)Buffer + AmountToMove;
  1133. VirtualAddress = (PCHAR)VirtualAddress + AmountToMove;
  1134. LocalBytesCopied += AmountToMove;
  1135. CurrentLength -= AmountToMove;
  1136. }
  1137. *BytesCopied = LocalBytesCopied;
  1138. }
  1139. /* @doc INTERNAL Card Card_c CardInterruptHandler
  1140. @func
  1141. <f CardInterruptHandler> dequeues an event from the asynchronous event
  1142. callback queue <t CARD_EVENT_OBJECT>, and processes it according to
  1143. whether it is a BChannel event, Card event, or B-Advise event.
  1144. The associated callback routines are responsible for processing the
  1145. event.
  1146. @comm
  1147. <f NdisAcquireSpinLock> and <f NdisReleaseSpinLock> are used to provide
  1148. protection around the dequeueing code and keep it from being re-entered
  1149. as a result of another asynchronous callback event.
  1150. */
  1151. VOID CardInterruptHandler(
  1152. IN PCARD_OBJECT pCard // @parm
  1153. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  1154. )
  1155. {
  1156. DBG_FUNC("CardInterruptHandler")
  1157. PMINIPORT_ADAPTER_OBJECT pAdapter;
  1158. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  1159. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  1160. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  1161. // DBG_ENTER(pAdapter);
  1162. #if defined(SAMPLE_DRIVER)
  1163. {
  1164. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1165. PNDIS_BUFFER pDstNdisBuffer;
  1166. // A pointer to the NDIS buffer we use to indicate the receive.
  1167. PUCHAR pMemory;
  1168. // A pointer to a memory area we use to create a copy of the incoming
  1169. // packet.
  1170. ULONG ByteCount = 0;
  1171. ULONG BytesCopied = 0;
  1172. PLIST_ENTRY pList;
  1173. PCARD_EVENT_OBJECT pEvent;
  1174. PCARD_EVENT_OBJECT pNewEvent;
  1175. // A pointer to the <t CARD_EVENT_OBJECT> associated with this event.
  1176. PBCHANNEL_OBJECT pBChannel;
  1177. PBCHANNEL_OBJECT pPeerBChannel;
  1178. // A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
  1179. /*
  1180. // Clear out all packets in the receive buffer.
  1181. */
  1182. NdisDprAcquireSpinLock(&pAdapter->EventLock);
  1183. while (!IsListEmpty(&pAdapter->EventList))
  1184. {
  1185. pEvent = (PCARD_EVENT_OBJECT)RemoveHeadList(&pAdapter->EventList);
  1186. NdisDprReleaseSpinLock(&pAdapter->EventLock);
  1187. ASSERT(pEvent->pReceivingObject);
  1188. switch (pEvent->ulEventCode)
  1189. {
  1190. case CARD_EVENT_RING:
  1191. // The caller has already removed the BChannel from the available
  1192. // list, so we just pass it up to SetupIncomingCall so it can
  1193. // get the same one from ProtocolCoCreateVc.
  1194. pBChannel = pEvent->pReceivingObject;
  1195. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1196. pPeerBChannel = pEvent->pSendingObject;
  1197. ASSERT(pPeerBChannel && pPeerBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1198. pBChannel->pPeerBChannel = pPeerBChannel;
  1199. DBG_FILTER(pAdapter,DBG_TAPICALL_ON,
  1200. ("#%d CallState=0x%X CARD_EVENT_RING from #%d\n",
  1201. pBChannel->ObjectID, pBChannel->CallState,
  1202. (pBChannel->pPeerBChannel == NULL) ? -1 :
  1203. pBChannel->pPeerBChannel->ObjectID));
  1204. Status = SetupIncomingCall(pAdapter, &pBChannel);
  1205. if (Status == NDIS_STATUS_SUCCESS)
  1206. {
  1207. ASSERT(pBChannel == pEvent->pReceivingObject);
  1208. }
  1209. else if (Status != NDIS_STATUS_PENDING)
  1210. {
  1211. DChannelRejectCall(pAdapter->pDChannel, pBChannel);
  1212. }
  1213. else
  1214. {
  1215. ASSERT(pBChannel == pEvent->pReceivingObject);
  1216. }
  1217. break;
  1218. case CARD_EVENT_CONNECT:
  1219. // The other side answered the call.
  1220. pBChannel = pEvent->pReceivingObject;
  1221. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1222. pBChannel->pPeerBChannel = pEvent->pSendingObject;
  1223. DBG_FILTER(pAdapter,DBG_TAPICALL_ON,
  1224. ("#%d CallState=0x%X CARD_EVENT_CONNECT from #%d\n",
  1225. pBChannel->ObjectID, pBChannel->CallState,
  1226. (pBChannel->pPeerBChannel == NULL) ? -1 :
  1227. pBChannel->pPeerBChannel->ObjectID));
  1228. if (pBChannel->Flags & VCF_OUTGOING_CALL)
  1229. {
  1230. // The other side answered the call.
  1231. CompleteCmMakeCall(pBChannel, NDIS_STATUS_SUCCESS);
  1232. }
  1233. break;
  1234. case CARD_EVENT_DISCONNECT:
  1235. // The other side has closed the call.
  1236. pBChannel = pEvent->pReceivingObject;
  1237. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1238. DBG_FILTER(pAdapter,DBG_TAPICALL_ON,
  1239. ("#%d CallState=0x%X CARD_EVENT_DISCONNECT from #%d\n",
  1240. pBChannel->ObjectID, pBChannel->CallState,
  1241. (pBChannel->pPeerBChannel == NULL) ? -1 :
  1242. pBChannel->pPeerBChannel->ObjectID));
  1243. pBChannel->pPeerBChannel = NULL;
  1244. if (pBChannel->Flags & VCF_OUTGOING_CALL)
  1245. {
  1246. if (pBChannel->CallState != LINECALLSTATE_CONNECTED)
  1247. {
  1248. // Call never made it to the connected state.
  1249. CompleteCmMakeCall(pBChannel, NDIS_STATUS_FAILURE);
  1250. }
  1251. else
  1252. {
  1253. // Call was disconnected by remote endpoint.
  1254. InitiateCallTeardown(pAdapter, pBChannel);
  1255. }
  1256. }
  1257. else if (pBChannel->Flags & VCF_INCOMING_CALL)
  1258. {
  1259. InitiateCallTeardown(pAdapter, pBChannel);
  1260. }
  1261. break;
  1262. case CARD_EVENT_RECEIVE:
  1263. pBChannel = pEvent->pReceivingObject;
  1264. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1265. DBG_FILTER(pAdapter,DBG_TXRX_VERBOSE_ON,
  1266. ("#%d CallState=0x%X CARD_EVENT_RECEIVE from #%d\n",
  1267. pBChannel->ObjectID, pBChannel->CallState,
  1268. (pBChannel->pPeerBChannel == NULL) ? -1 :
  1269. pBChannel->pPeerBChannel->ObjectID));
  1270. if (pBChannel->CallState == LINECALLSTATE_CONNECTED)
  1271. {
  1272. // Find out how big the packet is.
  1273. NdisQueryPacket(pEvent->pNdisPacket, NULL, NULL, NULL,
  1274. &ByteCount);
  1275. // Allocate memory for a copy of the data.
  1276. Status = ALLOCATE_MEMORY(pMemory, ByteCount,
  1277. pAdapter->MiniportAdapterHandle);
  1278. if (Status == NDIS_STATUS_SUCCESS)
  1279. {
  1280. NdisAllocateBuffer(&Status, &pDstNdisBuffer,
  1281. pAdapter->pCard->BufferPoolHandle,
  1282. pMemory, ByteCount);
  1283. if (Status == NDIS_STATUS_SUCCESS)
  1284. {
  1285. TpiCopyFromPacketToBuffer(pEvent->pNdisPacket, 0,
  1286. ByteCount, pMemory,
  1287. &BytesCopied);
  1288. ASSERT(BytesCopied == ByteCount);
  1289. ReceivePacketHandler(pBChannel, pDstNdisBuffer,
  1290. ByteCount);
  1291. }
  1292. else
  1293. {
  1294. FREE_MEMORY(pMemory, ByteCount);
  1295. DBG_ERROR(pAdapter,("NdisAllocateBuffer Error=0x%X\n",
  1296. Status));
  1297. }
  1298. }
  1299. }
  1300. pPeerBChannel = pBChannel->pPeerBChannel;
  1301. if (pPeerBChannel)
  1302. {
  1303. pNewEvent = CardEventAllocate(pPeerBChannel->pAdapter->pCard);
  1304. if (pNewEvent)
  1305. {
  1306. pNewEvent->ulEventCode = CARD_EVENT_TRANSMIT_COMPLETE;
  1307. pNewEvent->pSendingObject = pBChannel;
  1308. pNewEvent->pReceivingObject = pPeerBChannel;
  1309. CardNotifyEvent(pPeerBChannel->pAdapter->pCard, pNewEvent);
  1310. }
  1311. }
  1312. else
  1313. {
  1314. DBG_WARNING(pAdapter,("pPeerBChannel == NULL\n"));
  1315. }
  1316. break;
  1317. case CARD_EVENT_TRANSMIT_COMPLETE:
  1318. pBChannel = pEvent->pReceivingObject;
  1319. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1320. DBG_FILTER(pAdapter,DBG_TXRX_VERBOSE_ON,
  1321. ("#%d CallState=0x%X CARD_EVENT_TRANSMIT_COMPLETE from #%d\n",
  1322. pBChannel->ObjectID, pBChannel->CallState,
  1323. (pBChannel->pPeerBChannel == NULL) ? -1 :
  1324. pBChannel->pPeerBChannel->ObjectID));
  1325. /*
  1326. // Remove the packet from the BChannel's TransmitBusyList and
  1327. // place it on the adapter's TransmitCompleteList now that the
  1328. // card has completed the transmit.
  1329. */
  1330. NdisAcquireSpinLock(&pAdapter->TransmitLock);
  1331. if (!IsListEmpty(&pBChannel->TransmitBusyList))
  1332. {
  1333. pList = RemoveHeadList(&pBChannel->TransmitBusyList);
  1334. InsertTailList(&pBChannel->pAdapter->TransmitCompleteList, pList);
  1335. }
  1336. NdisReleaseSpinLock(&pAdapter->TransmitLock);
  1337. TransmitCompleteHandler(pAdapter);
  1338. break;
  1339. default:
  1340. DBG_ERROR(pAdapter,("Unknown event code=%d\n",
  1341. pEvent->ulEventCode));
  1342. break;
  1343. }
  1344. CardEventRelease(pCard, pEvent);
  1345. NdisDprAcquireSpinLock(&pAdapter->EventLock);
  1346. }
  1347. NdisDprReleaseSpinLock(&pAdapter->EventLock);
  1348. }
  1349. #else // SAMPLE_DRIVER
  1350. // TODO - Add interrupt handler code here
  1351. #endif // SAMPLE_DRIVER
  1352. // DBG_LEAVE(pAdapter);
  1353. }
  1354. /* @doc INTERNAL Card Card_c CardCleanPhoneNumber
  1355. @func
  1356. <f CardCleanPhoneNumber> copies the phone number from the input string
  1357. to the output string, deleting any non-phone number characters (i.e.
  1358. dashes, parens, modem keywords, etc.).
  1359. @rdesc
  1360. <f CardCleanPhoneNumber> returns the length of the output string in bytes.
  1361. */
  1362. USHORT CardCleanPhoneNumber(
  1363. OUT PUCHAR Dst, // @parm
  1364. // A pointer to the output string.
  1365. IN PUSHORT Src, // @parm
  1366. // A pointer to the input string.
  1367. IN USHORT Length // @parm
  1368. // The length of the input string in bytes.
  1369. )
  1370. {
  1371. DBG_FUNC("CardCleanPhoneNumber")
  1372. USHORT NumDigits;
  1373. /*
  1374. // Strip out any character which are not digits or # or *.
  1375. */
  1376. for (NumDigits = 0; Length > 0; --Length)
  1377. {
  1378. if ((*Src >= '0' && *Src <= '9') ||
  1379. (*Src == '#' || *Src == '*'))
  1380. {
  1381. /*
  1382. // Make sure dial string is within the limit of the adapter.
  1383. */
  1384. if (NumDigits < CARD_MAX_DIAL_DIGITS)
  1385. {
  1386. ++NumDigits;
  1387. *Dst++ = (UCHAR) *Src;
  1388. }
  1389. else
  1390. {
  1391. break;
  1392. }
  1393. }
  1394. Src++;
  1395. }
  1396. *Dst++ = 0;
  1397. return (NumDigits);
  1398. }
  1399. /* @doc INTERNAL Card Card_c CardReset
  1400. @func
  1401. <f CardReset> issues a hard reset to the NIC. Same as power up.
  1402. @rdesc
  1403. <f CardReset> returns zero if it is successful.<nl>
  1404. Otherwise, a non-zero return value indicates an error condition.
  1405. */
  1406. NDIS_STATUS CardReset(
  1407. IN PCARD_OBJECT pCard // @parm
  1408. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  1409. )
  1410. {
  1411. DBG_FUNC("CardReset")
  1412. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  1413. // Holds the result code returned by this function.
  1414. PMINIPORT_ADAPTER_OBJECT pAdapter;
  1415. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  1416. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  1417. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  1418. DBG_ENTER(pAdapter);
  1419. DBG_BREAK(pAdapter);
  1420. // TODO - Add code here to reset your hardware to its initial state.
  1421. DBG_RETURN(pAdapter, Result);
  1422. return (Result);
  1423. }
  1424. #if defined(SAMPLE_DRIVER)
  1425. /* @doc INTERNAL Card Card_c GET_BCHANNEL_FROM_PHONE_NUMBER
  1426. @func
  1427. <f GET_BCHANNEL_FROM_PHONE_NUMBER> assumes the phone number is a BChannel
  1428. index, and uses it to lookup the associated BChannel on one of our
  1429. adapters. Zero means use the first availble BChannel on another adapter.
  1430. @rdesc
  1431. <f GET_BCHANNEL_FROM_PHONE_NUMBER> returns a pointer to the associated
  1432. <t BCHANNEL_OBJECT> if successful. Otherwise, NULL is returned.
  1433. */
  1434. PBCHANNEL_OBJECT GET_BCHANNEL_FROM_PHONE_NUMBER(
  1435. IN PUCHAR pDialString // @parm
  1436. // A pointer to the dial string.
  1437. )
  1438. {
  1439. DBG_FUNC("GET_BCHANNEL_FROM_PHONE_NUMBER")
  1440. ULONG ulCalledID = 0;
  1441. // Phone number converted to BChannel ObjectID (spans all adapters).
  1442. ULONG ulAdapterIndex;
  1443. // Loop index.
  1444. /*
  1445. // Strip out any character which are not digits or # or *.
  1446. */
  1447. while (*pDialString)
  1448. {
  1449. if (*pDialString >= '0' && *pDialString <= '9')
  1450. {
  1451. ulCalledID *= 10;
  1452. ulCalledID += *pDialString - '0';
  1453. }
  1454. else
  1455. {
  1456. break;
  1457. }
  1458. pDialString++;
  1459. }
  1460. if (*pDialString)
  1461. {
  1462. DBG_ERROR(DbgInfo,("Invalid dial string '%s'\n", pDialString));
  1463. }
  1464. else
  1465. {
  1466. PMINIPORT_ADAPTER_OBJECT pAdapter;
  1467. for (ulAdapterIndex = 0; ulAdapterIndex < MAX_ADAPTERS; ++ulAdapterIndex)
  1468. {
  1469. // Does call want to look on specific adapter, or any?
  1470. if (ulCalledID == 0 || ulCalledID == ulAdapterIndex+1)
  1471. {
  1472. pAdapter = g_Adapters[ulAdapterIndex];
  1473. if (pAdapter)
  1474. {
  1475. // Find first available channel.
  1476. NdisAcquireSpinLock(&pAdapter->EventLock);
  1477. if (!IsListEmpty(&pAdapter->BChannelAvailableList))
  1478. {
  1479. PBCHANNEL_OBJECT pBChannel;
  1480. pBChannel = (PBCHANNEL_OBJECT) pAdapter->BChannelAvailableList.Blink;
  1481. if (pBChannel->NdisSapHandle &&
  1482. pBChannel->NdisVcHandle == NULL)
  1483. {
  1484. // Find first available listening channel.
  1485. pBChannel = (PBCHANNEL_OBJECT) RemoveTailList(
  1486. &pAdapter->BChannelAvailableList);
  1487. // Reset the link info so we can tell that it's
  1488. // not on the list.
  1489. InitializeListHead(&pBChannel->LinkList);
  1490. NdisReleaseSpinLock(&pAdapter->EventLock);
  1491. return (pBChannel);
  1492. }
  1493. }
  1494. NdisReleaseSpinLock(&pAdapter->EventLock);
  1495. }
  1496. }
  1497. }
  1498. }
  1499. return (NULL);
  1500. }
  1501. /* @doc INTERNAL Card Card_c CardNotifyEvent
  1502. @func
  1503. <f CardNotifyEvent> queues an IMS event to be processed by the DPC
  1504. handler when things quiet down.
  1505. @comm
  1506. We have to queue the event to be processed in DPC context. We have
  1507. to make sure that the queue is protected by a mutual exclusion
  1508. primative which cannot be violated by the callback.
  1509. */
  1510. VOID CardNotifyEvent(
  1511. IN PCARD_OBJECT pCard, // @parm
  1512. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  1513. IN PCARD_EVENT_OBJECT pEvent // @parm
  1514. // A pointer to the <t CARD_EVENT_OBJECT> associated with this event.
  1515. )
  1516. {
  1517. DBG_FUNC("CardNotifyEvent")
  1518. PMINIPORT_ADAPTER_OBJECT pAdapter;
  1519. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  1520. ASSERT(pCard && pCard->ObjectType == CARD_OBJECT_TYPE);
  1521. pAdapter = GET_ADAPTER_FROM_CARD(pCard);
  1522. // DBG_ENTER(pAdapter);
  1523. /*
  1524. // Schedule the event handler to run as soon as possible.
  1525. // We must schedule the event to go through the NDIS wrapper
  1526. // so the proper spin locks will be held.
  1527. // Don't schedule another event if processing is already in progress.
  1528. */
  1529. NdisAcquireSpinLock(&pAdapter->EventLock);
  1530. InsertTailList(&pAdapter->EventList, &pEvent->Queue);
  1531. NdisReleaseSpinLock(&pAdapter->EventLock);
  1532. if (pEvent->ulEventCode == CARD_EVENT_RING ||
  1533. pEvent->ulEventCode == CARD_EVENT_CONNECT ||
  1534. pEvent->ulEventCode == CARD_EVENT_DISCONNECT)
  1535. {
  1536. NdisMSetTimer(&pAdapter->EventTimer, 100);
  1537. }
  1538. else
  1539. {
  1540. NdisMSetTimer(&pAdapter->EventTimer, 0);
  1541. }
  1542. // DBG_LEAVE(pAdapter);
  1543. }
  1544. /* @doc INTERNAL Card Card_c CardEventAllocate
  1545. @func
  1546. <f CardEventAllocate> allocates an <t CARD_EVENT_OBJECT> from the
  1547. <p pCard>'s EventList.
  1548. @rdesc
  1549. <f CardEventAllocate> returns a pointer to a <t CARD_EVENT_OBJECT>
  1550. if it is successful.<nl>
  1551. Otherwise, a NULL return value indicates an error condition.
  1552. */
  1553. PCARD_EVENT_OBJECT CardEventAllocate(
  1554. IN PCARD_OBJECT pCard // @parm
  1555. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  1556. )
  1557. {
  1558. PCARD_EVENT_OBJECT pEvent;
  1559. // A pointer to the <t CARD_EVENT_OBJECT> associated with this event.
  1560. pEvent = &pCard->EventArray[pCard->NextEvent++];
  1561. ASSERT(pEvent->pReceivingObject == NULL);
  1562. if (pCard->NextEvent >= MAX_EVENTS)
  1563. {
  1564. pCard->NextEvent = 0;
  1565. }
  1566. return (pEvent);
  1567. }
  1568. /* @doc INTERNAL Card Card_c CardEventRelease
  1569. @func
  1570. <f CardEventRelease> returns a previously allocate <t CARD_EVENT_OBJECT>
  1571. to the <p pCard>'s EventList.
  1572. */
  1573. VOID CardEventRelease(
  1574. IN PCARD_OBJECT pCard, // @parm
  1575. // A pointer to the <t CARD_OBJECT> returned by <f CardCreate>.
  1576. IN PCARD_EVENT_OBJECT pEvent // @parm
  1577. // A pointer to the <t CARD_EVENT_OBJECT> associated with this event.
  1578. )
  1579. {
  1580. pEvent->pReceivingObject = NULL;
  1581. }
  1582. #endif // SAMPLE_DRIVER