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.

620 lines
18 KiB

  1. /*****************************************************************************
  2. ** **
  3. ** COPYRIGHT (C) 2000, 2001 MKNET CORPORATION **
  4. ** DEVELOPED FOR THE MK7100-BASED VFIR PCI CONTROLLER. **
  5. ** **
  6. *****************************************************************************/
  7. /*****************************************************************************
  8. Module Name:
  9. MKMINI.C
  10. Routines:
  11. MKMiniportReturnPackets
  12. MKMiniportCheckForHang
  13. MKMiniportHalt
  14. MKMiniportShutdownHandler
  15. MKMiniportInitialize
  16. MKMiniportReset
  17. (MK7EnableInterrupt & Disable in MK7COMM.C.)
  18. DriverEntry
  19. Comments:
  20. Contains most NDIS API routines supplied to Windows by the miniport.
  21. *****************************************************************************/
  22. #include "precomp.h"
  23. #pragma hdrstop
  24. #include "protot.h"
  25. // Globals to help debug/test
  26. PMK7_ADAPTER GAdapter;
  27. //-----------------------------------------------------------------------------
  28. // Procedure: [MKMiniportReturnPackets]
  29. //
  30. // Description: NDIS returns a previously indicated pkt by calling this routine.
  31. //
  32. // Arguments:
  33. // IN NDIS_HANDLE MiniportAdapterContext
  34. // - a context version of our Adapter pointer
  35. // IN NDIS_PACKET Packet
  36. // - the packet that is being freed
  37. //
  38. // Returns: (none)
  39. //
  40. //-----------------------------------------------------------------------------
  41. VOID MKMiniportReturnPackets( NDIS_HANDLE MiniportAdapterContext,
  42. PNDIS_PACKET Packet)
  43. {
  44. PMK7_ADAPTER Adapter;
  45. PRPD rpd;
  46. PRCB rcb;
  47. //****************************************
  48. // - SpinLock brackets the FreeList resource.
  49. // - Recover the RPD from the returned pkt, then return
  50. // the RPD to the FreeList.
  51. //****************************************
  52. Adapter = PMK7_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
  53. NdisAcquireSpinLock(&Adapter->Lock);
  54. ASSERT(Packet);
  55. #if DBG
  56. GDbgStat.rxPktsRtn++;
  57. #endif
  58. rpd = *(PRPD *)(Packet->MiniportReserved);
  59. ASSERT(rpd);
  60. ProcReturnedRpd(Adapter, rpd);
  61. // 4.0.1 BOC
  62. Adapter->UsedRpdCount--;
  63. // 4.0.1 EOC
  64. NdisReleaseSpinLock(&Adapter->Lock);
  65. }
  66. //-----------------------------------------------------------------------------
  67. // Procedure: [MKMiniportCheckForHang]
  68. //
  69. // Description: This procedure does not do much for now.
  70. //
  71. // Arguments:
  72. // MiniportAdapterContext (both) - pointer to the adapter object data area
  73. //
  74. // Returns:
  75. // FALSE or TRUE
  76. //-----------------------------------------------------------------------------
  77. BOOLEAN MKMiniportCheckForHang(NDIS_HANDLE MiniportAdapterContext)
  78. {
  79. PMK7_ADAPTER Adapter;
  80. Adapter = PMK7_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
  81. NdisAcquireSpinLock(&Adapter->Lock);
  82. // DbgPrint(" ==> Hang Check\n\r");
  83. if (Adapter->IOMode == TX_MODE) {
  84. Adapter->HangCheck++;
  85. if (Adapter->HangCheck >= 3) {
  86. NdisReleaseSpinLock(&Adapter->Lock);
  87. return(TRUE);
  88. }
  89. }
  90. NdisReleaseSpinLock(&Adapter->Lock);
  91. return(FALSE);
  92. }
  93. //-----------------------------------------------------------------------------
  94. // Procedure: [MKMiniportHalt]
  95. //
  96. // Description: Halts our hardware. We disable interrupts as well as the hw
  97. // itself. We release other Windows resources such as allocated
  98. // memory and timers.
  99. //
  100. // Arguments:
  101. // MiniportAdapterContext - pointer to the adapter object data area.
  102. //
  103. // Returns: (none)
  104. //-----------------------------------------------------------------------------
  105. VOID MKMiniportHalt(NDIS_HANDLE MiniportAdapterContext)
  106. {
  107. PMK7_ADAPTER Adapter;
  108. BOOLEAN Cancelled;
  109. DBGFUNC(" MKMiniportHalt");
  110. Adapter = PMK7_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
  111. MK7DisableInterrupt(Adapter);
  112. MK7DisableIr(Adapter);
  113. Adapter->hardwareStatus = NdisHardwareStatusClosing;
  114. // check to make sure there are no outstanding transmits
  115. while(Adapter->FirstTxQueue) {
  116. PNDIS_PACKET QueuePacket = Adapter->FirstTxQueue;
  117. Adapter->NumPacketsQueued--;
  118. DequeuePacket(Adapter->FirstTxQueue, Adapter->LastTxQueue);
  119. NDIS_SET_PACKET_STATUS(QueuePacket, NDIS_STATUS_FAILURE);
  120. NdisMSendComplete(
  121. Adapter->MK7AdapterHandle,
  122. QueuePacket,
  123. NDIS_STATUS_FAILURE);
  124. }
  125. // deregister shutdown handler
  126. NdisMDeregisterAdapterShutdownHandler(Adapter->MK7AdapterHandle);
  127. // Free the interrupt object
  128. NdisMDeregisterInterrupt(&Adapter->Interrupt);
  129. NdisMCancelTimer(&Adapter->MinTurnaroundTxTimer, &Cancelled);
  130. NdisFreeSpinLock(&Adapter->Lock);
  131. // Free the entire adapter object, including the shared memory structures.
  132. FreeAdapterObject(Adapter);
  133. }
  134. //-----------------------------------------------------------------------------
  135. // Procedure: [MKMiniportShutdownHandler]
  136. //
  137. // Description: Removes an adapter instance that was previously initialized.
  138. // To Shutdown simply Disable interrupts. Since the system is shutting
  139. // down there is no need to release resources (memory, i/o space, etc.)
  140. // that the adapter instance was using.
  141. //
  142. // Arguments:
  143. // MiniportAdapterContext - pointer to the adapter object data area.
  144. //
  145. // Returns: (none)
  146. //-----------------------------------------------------------------------------
  147. VOID MKMiniportShutdownHandler(NDIS_HANDLE MiniportAdapterContext)
  148. {
  149. PMK7_ADAPTER Adapter;
  150. Adapter = PMK7_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
  151. MK7DisableInterrupt(Adapter);
  152. }
  153. //-----------------------------------------------------------------------------
  154. // Procedure: [MKMiniportInitialize] (only single adapter support for now)
  155. //
  156. // Description: This routine is called once per supported adapter card in the
  157. // system. This routine is responsible for initializing each adapter.
  158. // This includes parsing all of the necessary parameters from the registry,
  159. // allocating and initializing shared memory structures, configuring the
  160. // MK7100 chip, registering the interrupt, etc.
  161. //
  162. // Arguments:
  163. // OpenErrorStatus (mini) - Returns more info about any failure
  164. // SelectedMediumIndex (mini) - Returns the index in MediumArray of the
  165. // medium that the miniport is using
  166. // MediumArraySize (mini) - An array of medium types that the driver
  167. // supports
  168. // MiniportAdapterHandle (mini) - pointer to the adapter object data area.
  169. //
  170. // WrapperConfigurationContext (both) - A value that we will pass to
  171. // NdisOpenConfiguration.
  172. //
  173. //
  174. // Returns:
  175. // NDIS_STATUS_SUCCESS - If the adapter was initialized successfully.
  176. // <not NDIS_STATUS_SUCCESS> - If for some reason the adapter didn't
  177. // initialize
  178. //-----------------------------------------------------------------------------
  179. NDIS_STATUS
  180. MKMiniportInitialize(PNDIS_STATUS OpenErrorStatus,
  181. PUINT SelectedMediumIndex,
  182. PNDIS_MEDIUM MediumArray,
  183. UINT MediumArraySize,
  184. NDIS_HANDLE MiniportAdapterHandle,
  185. NDIS_HANDLE WrapperConfigurationContext)
  186. {
  187. ULONG i;
  188. NDIS_STATUS Status;
  189. PMK7_ADAPTER Adapter;
  190. NDIS_HANDLE ConfigHandle;
  191. NDIS_INTERFACE_TYPE IfType;
  192. PVOID OverrideNetAddress;
  193. MK7REG mk7reg;
  194. DBGFUNC(" MKMiniportInitialize");
  195. //****************************************
  196. // We're an IrDA device. Exit w/ error if type not passed in.
  197. //****************************************
  198. for (i = 0; i < MediumArraySize; i++) {
  199. if (MediumArray[i] == NdisMediumIrda)
  200. break;
  201. }
  202. if (i == MediumArraySize) {
  203. DBGSTR(("ERROR: IrDA Media type not found.\n"));
  204. DBGLOG("=> MKMiniportInitialize (ERR): IrDA not found", 0);
  205. return (NDIS_STATUS_UNSUPPORTED_MEDIA);
  206. }
  207. *SelectedMediumIndex = i;
  208. //****************************************
  209. // Allocate the Adapter Object, exit if error.
  210. // (Cacheable, non-paged system memory)
  211. //****************************************
  212. Status = ALLOC_SYS_MEM(&Adapter, sizeof(MK7_ADAPTER));
  213. if (Status != NDIS_STATUS_SUCCESS) {
  214. DBGSTR(("ERROR: ADAPTER Allocate Memory failed (Status = 0x%x)\n", Status));
  215. DBGLOG("<= MKMiniportInitialize: (ERR - 1)", 0);
  216. return (Status);
  217. }
  218. NdisZeroMemory(Adapter, sizeof(MK7_ADAPTER));
  219. Adapter->MK7AdapterHandle = MiniportAdapterHandle;
  220. GAdapter = Adapter;
  221. Adapter->hardwareStatus = NdisHardwareStatusInitializing;
  222. //****************************************
  223. // Process the Registry -- Get config settings, etc.
  224. //****************************************
  225. Status = ProcessRegistry(Adapter, WrapperConfigurationContext);
  226. if (Status != NDIS_STATUS_SUCCESS) {
  227. FreeAdapterObject(Adapter);
  228. DBGSTR(("ERROR: ProcessRegistry() \n"));
  229. DBGLOG("<= MKMiniportInitialize: (ERR - 2)", 0);
  230. return (NDIS_STATUS_FAILURE);
  231. }
  232. //****************************************
  233. // Let NDIS know kind of driver and features we support
  234. //****************************************
  235. IfType = NdisInterfacePci;
  236. NdisMSetAttributesEx(
  237. Adapter->MK7AdapterHandle,
  238. (NDIS_HANDLE) Adapter,
  239. 0,
  240. (ULONG) NDIS_ATTRIBUTE_DESERIALIZE | NDIS_ATTRIBUTE_BUS_MASTER,
  241. IfType );
  242. //****************************************
  243. // Claim the physical Adapter for this Adapter object. We call on
  244. // NdisMPciAssignResources to find our assigned resources.
  245. //****************************************
  246. if (ClaimAdapter(Adapter, WrapperConfigurationContext) != NDIS_STATUS_SUCCESS) {
  247. FreeAdapterObject(Adapter);
  248. DBGSTR(("ERROR: No adapter detected\n"));
  249. DBGLOG("<= MKMiniportInitialize: (ERR - 3)", 0);
  250. return (NDIS_STATUS_FAILURE);
  251. }
  252. //****************************************
  253. // Set up the MK7 register I/O mapping w/ NDIS, interrupt mode, etc.
  254. //****************************************
  255. Status = SetupAdapterInfo(Adapter);
  256. if (Status != NDIS_STATUS_SUCCESS) {
  257. FreeAdapterObject(Adapter);
  258. DBGSTR(("ERROR: I/O Space allocation failed (Status = 0x%X)\n",Status));
  259. DBGLOG("<= MKMiniportInitialize: (ERR - 4)", 0);
  260. return(NDIS_STATUS_FAILURE);
  261. }
  262. //****************************************
  263. // Allocate & initialize memory/buffer needs.
  264. //****************************************
  265. Status = AllocAdapterMemory(Adapter);
  266. if (Status != NDIS_STATUS_SUCCESS) {
  267. FreeAdapterObject(Adapter);
  268. MKLogError(Adapter, EVENT_10, NDIS_ERROR_CODE_OUT_OF_RESOURCES, 0);
  269. DBGSTR(("ERROR: Shared Memory Allocation failed (Status = 0x%x)\n", Status));
  270. DBGLOG("<= MKMiniportInitialize: (ERR - 5)", 0);
  271. return (NDIS_STATUS_FAILURE);
  272. }
  273. // 4.1.0 Check hw version.
  274. MK7Reg_Read(Adapter, R_CFG3, &mk7reg);
  275. if ((mk7reg & 0x1000) != 0){
  276. mk7reg &= 0xEFFF;
  277. MK7Reg_Write(Adapter, R_CFG3, mk7reg);
  278. mk7reg |= 0x1000;
  279. MK7Reg_Write(Adapter, R_CFG3, mk7reg);
  280. MK7Reg_Read(Adapter, R_CFG3, &mk7reg);
  281. if ((mk7reg & 0x1000) != 0)
  282. Adapter->HwVersion = HW_VER_1;
  283. else
  284. Adapter->HwVersion = HW_VER_2;
  285. }
  286. else{
  287. Adapter->HwVersion = HW_VER_2;
  288. }
  289. //****************************************
  290. // Disable interrupts while we finish with the initialization
  291. // Must AllocAdapterMemory() before you can do this.
  292. //****************************************
  293. MK7DisableInterrupt(Adapter);
  294. //****************************************
  295. // Register our interrupt with the NDIS wrapper, hook our interrupt
  296. // vector, & use shared interrupts for our PCI adapters
  297. //****************************************
  298. Status = NdisMRegisterInterrupt(&Adapter->Interrupt,
  299. Adapter->MK7AdapterHandle,
  300. Adapter->MKInterrupt,
  301. Adapter->MKInterrupt,
  302. TRUE, // call ISR each time NIC interrupts
  303. TRUE, // shared irq
  304. Adapter->InterruptMode); // NdisInterruptLatched, NdisInterruptLevelSensitive
  305. if (Status != NDIS_STATUS_SUCCESS) {
  306. FreeAdapterObject(Adapter);
  307. MKLogError(Adapter,
  308. EVENT_0,
  309. NDIS_ERROR_CODE_INTERRUPT_CONNECT,
  310. (ULONG) Adapter->MKInterrupt);
  311. DBGLOG("<= MKMiniportInitialize: (ERR - 6)", 0);
  312. return (NDIS_STATUS_FAILURE);
  313. }
  314. #if DBG
  315. DbgTestInit(Adapter);
  316. #endif
  317. //****************************************
  318. // allocate a spin lock
  319. //****************************************
  320. NdisAllocateSpinLock(&Adapter->Lock);
  321. Adapter->HangCheck = 0;
  322. Adapter->nowReceiving=FALSE; // 4.1.0
  323. //****************************************
  324. // Setup and initialize the transmit and receive structures then
  325. // init the adapter
  326. //****************************************
  327. SetupTransmitQueues(Adapter, TRUE);
  328. SetupReceiveQueues(Adapter);
  329. if (!InitializeAdapter(Adapter)) {
  330. FreeAdapterObject(Adapter);
  331. NdisMDeregisterInterrupt(&Adapter->Interrupt);
  332. DBGSTR(("ERROR: InitializeAdapter Failed.\n"));
  333. DBGLOG("<= MKMiniportInitialize: (ERR - 7)", 0);
  334. return (NDIS_STATUS_FAILURE);
  335. }
  336. //****************************************
  337. // Register a shutdown handler
  338. //****************************************
  339. NdisMRegisterAdapterShutdownHandler(Adapter->MK7AdapterHandle,
  340. (PVOID) Adapter,
  341. (ADAPTER_SHUTDOWN_HANDLER) MKMiniportShutdownHandler);
  342. StartAdapter(Adapter);
  343. MK7EnableInterrupt(Adapter);
  344. Adapter->hardwareStatus = NdisHardwareStatusReady;
  345. DBGSTR(("MKMiniportInitialize: Completed Init Successfully\n"));
  346. DBGLOG("<= MKMiniportInitialize", 0);
  347. return (NDIS_STATUS_SUCCESS);
  348. }
  349. //-----------------------------------------------------------------------------
  350. // RYM-5++
  351. // Procedure: [MKMiniportReset]
  352. //
  353. // Description: Instructs the Miniport to issue a hardware reset to the
  354. // network adapter. The driver also resets its software state. this
  355. // function also resets the transmit queues.
  356. //
  357. // Arguments:
  358. // AddressingReset - TRUE if the wrapper needs to call
  359. // MiniportSetInformation to restore the addressing
  360. // information to the current values
  361. // MiniportAdapterContext - pointer to the adapter object data area.
  362. //
  363. // Returns:
  364. // NDIS_STATUS_PENDING - This function sets a timer to complete, so
  365. // pending is always returned
  366. //
  367. // (NOTE: The timer-based completion scheme has been disable by now starting
  368. // the timer. We may now want to return Success instead of Pending.)
  369. //-----------------------------------------------------------------------------
  370. NDIS_STATUS
  371. MKMiniportReset(PBOOLEAN AddressingReset,
  372. NDIS_HANDLE MiniportAdapterContext)
  373. {
  374. PMK7_ADAPTER Adapter;
  375. MK7REG mk7reg;
  376. DBGFUNC("MKMiniportReset");
  377. Adapter = PMK7_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
  378. NdisAcquireSpinLock(&Adapter->Lock);
  379. Adapter->hardwareStatus = NdisHardwareStatusReset;
  380. *AddressingReset = TRUE;
  381. // *** possible temporary code
  382. // *** NDIS may actually handle this
  383. Adapter->ResetInProgress = TRUE;
  384. // Disable interrupts while we re-init the transmit structures
  385. MK7DisableInterrupt(Adapter);
  386. MK7DisableIr(Adapter);
  387. // The NDIS 5 support for deserialized miniports requires that
  388. // when reset is called, the driver de-queue and fail all uncompleted
  389. // sends, and complete any uncompleted sends. Essentially we must have
  390. // no pending send requests left when we leave this routine.
  391. // we will fail all sends that we have left right now.
  392. while(Adapter->FirstTxQueue) {
  393. PNDIS_PACKET QueuePacket = Adapter->FirstTxQueue;
  394. Adapter->NumPacketsQueued--;
  395. DequeuePacket(Adapter->FirstTxQueue, Adapter->LastTxQueue);
  396. // we must release the lock here before returning control to ndis
  397. // (even temporarily like this)
  398. NdisReleaseSpinLock(&Adapter->Lock);
  399. NDIS_SET_PACKET_STATUS(QueuePacket, NDIS_STATUS_FAILURE);
  400. NdisMSendComplete(
  401. Adapter->MK7AdapterHandle,
  402. QueuePacket,
  403. NDIS_STATUS_FAILURE);
  404. NdisAcquireSpinLock(&Adapter->Lock);
  405. }
  406. // clean up all the packets we have successfully TX'd
  407. // ProcessTXInterrupt(Adapter);
  408. // Clear out our software transmit structures
  409. NdisZeroMemory((PVOID) Adapter->XmitCached, Adapter->XmitCachedSize);
  410. // Re-initialize the transmit structures
  411. ResetTransmitQueues(Adapter, FALSE);
  412. ResetReceiveQueues(Adapter);
  413. Adapter->tcbUsed = 0;
  414. NdisMSetTimer(&Adapter->MK7AsyncResetTimer, 500);
  415. // Adapter->hardwareStatus = NdisHardwareStatusReady;
  416. // Adapter->ResetInProgress = FALSE;
  417. // MK7EnableInterrupt(Adapter);
  418. // MK7EnableIr(Adapter);
  419. NdisReleaseSpinLock(&Adapter->Lock);
  420. return(NDIS_STATUS_PENDING);
  421. }
  422. //-----------------------------------------------------------------------------
  423. // Procedure: [DriverEntry]
  424. //
  425. // Description: This is the primary initialization routine for the MK7 driver.
  426. // It is simply responsible for the intializing the wrapper and registering
  427. // the adapter driver. The routine gets called once per driver, but
  428. // MKMiniportInitialize(miniport) will get called multiple times if there are
  429. // multiple adapters.
  430. //
  431. // Arguments:
  432. // DriverObject - Pointer to driver object created by the system.
  433. // RegistryPath - The registry path of this driver
  434. //
  435. // Returns:
  436. // The status of the operation, normally this will be NDIS_STATUS_SUCCESS
  437. //-----------------------------------------------------------------------------
  438. NTSTATUS
  439. DriverEntry(PDRIVER_OBJECT DriverObject,
  440. PUNICODE_STRING RegistryPath)
  441. {
  442. NDIS_STATUS Status;
  443. NDIS_HANDLE NdisWrapperHandle;
  444. NDIS_MINIPORT_CHARACTERISTICS MKMiniportChar;
  445. DBGFUNC("MK7-DriverEntry");
  446. DBGLOG("=> DriverEntry", 0);
  447. //****************************************
  448. // Now we must initialize the wrapper, and then register the Miniport
  449. //****************************************
  450. NdisMInitializeWrapper( &NdisWrapperHandle,
  451. DriverObject,
  452. RegistryPath,
  453. NULL );
  454. NdisZeroMemory(&MKMiniportChar, sizeof(MKMiniportChar));
  455. // Initialize the Miniport characteristics for the call to
  456. // NdisMRegisterMiniport.
  457. MKMiniportChar.MajorNdisVersion = MK7_NDIS_MAJOR_VERSION;
  458. MKMiniportChar.MinorNdisVersion = MK7_NDIS_MINOR_VERSION;
  459. MKMiniportChar.CheckForHangHandler = MKMiniportCheckForHang;
  460. MKMiniportChar.DisableInterruptHandler = MK7DisableInterrupt;
  461. MKMiniportChar.EnableInterruptHandler = MK7EnableInterrupt;
  462. MKMiniportChar.HaltHandler = MKMiniportHalt;
  463. MKMiniportChar.HandleInterruptHandler = MKMiniportHandleInterrupt;
  464. MKMiniportChar.InitializeHandler = MKMiniportInitialize;
  465. MKMiniportChar.ISRHandler = MKMiniportIsr;
  466. MKMiniportChar.QueryInformationHandler = MKMiniportQueryInformation;
  467. MKMiniportChar.ReconfigureHandler = NULL;
  468. MKMiniportChar.ResetHandler = MKMiniportReset;
  469. MKMiniportChar.SetInformationHandler = MKMiniportSetInformation;
  470. MKMiniportChar.SendHandler = NULL;
  471. MKMiniportChar.SendPacketsHandler = MKMiniportMultiSend;
  472. MKMiniportChar.ReturnPacketHandler = MKMiniportReturnPackets;
  473. MKMiniportChar.TransferDataHandler = NULL;
  474. // MKMiniportChar.AllocateCompleteHandler = D100AllocateComplete;
  475. //****************************************
  476. // Register this driver with the NDIS wrapper
  477. // This will cause MKMiniportInitialize to be called before returning
  478. // (is this really true? -- SoftIce shows this returning before
  479. // MKMiniportInitialize() is called(?))
  480. //****************************************
  481. Status = NdisMRegisterMiniport( NdisWrapperHandle,
  482. &MKMiniportChar,
  483. sizeof(NDIS_MINIPORT_CHARACTERISTICS));
  484. if (Status == NDIS_STATUS_SUCCESS) {
  485. DBGLOG("<= DriverEntry", 0);
  486. return (STATUS_SUCCESS);
  487. }
  488. DBGLOG("<= DriverEntry: Failed!", 0);
  489. return (Status);
  490. }