Windows NT 4.0 source code leak
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.

512 lines
11 KiB

4 years ago
  1. #include <ndis.h>
  2. #include "82595.h"
  3. #include "eprohw.h"
  4. #include "eprosw.h"
  5. #include "epro.h"
  6. #include "eprodbg.h"
  7. // Global data
  8. NDIS_MINIPORT_CHARACTERISTICS EPro_Miniport_Char;
  9. EPRO_DRIVER EProMiniportDriver={0};
  10. NDIS_STATUS EProSelReset(PEPRO_ADAPTER adapter)
  11. /*++
  12. Routine Description:
  13. This does a SEL-RESET of the i82595 chip. Read the 82595 docs
  14. for more info on what this does.
  15. Arguments:
  16. adapter - pointer to our adapter structure
  17. Return Values:
  18. always returns NDIS_STATUS_SUCCESS
  19. --*/
  20. {
  21. EPRO_ASSERT_BANK_0(adapter);
  22. EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_SEL_RESET);
  23. // according to 82595 prelim doc: wait 2 us after sel reset before
  24. // accessing the 82595
  25. NdisStallExecution(2);
  26. EProEnableInterrupts((NDIS_HANDLE)adapter);
  27. adapter->fHung = FALSE;
  28. return(NDIS_STATUS_SUCCESS);
  29. }
  30. VOID
  31. EProInitializeAdapterData(
  32. IN PEPRO_ADAPTER adapter
  33. )
  34. /*++
  35. Routine Description:
  36. This routine initializes our adapter structure - setting default
  37. values, zeroing fields, etc. This is called on adapter initialization
  38. and adapter reset.
  39. Arguments:
  40. A pointer to the adapter structure to clear.
  41. Return Values:
  42. none
  43. --*/
  44. {
  45. UINT i;
  46. adapter->CurrentHardwareStatus = NdisHardwareStatusReady;
  47. adapter->vendorID[0] = EPRO_VENDOR_ID_L;
  48. adapter->vendorID[1] = EPRO_VENDOR_ID_M;
  49. adapter->vendorID[2] = EPRO_VENDOR_ID_H;
  50. adapter->CurrentPacketFilter = 0;
  51. // hack to get around wrapper bug:
  52. // adapter->RXLookAheadSize = 0;
  53. //
  54. adapter->RXLookAheadSize = 256;
  55. adapter->FramesXmitOK = 0;
  56. adapter->FramesRcvOK = 0;
  57. adapter->FramesXmitErr = 0;
  58. adapter->FramesRcvErr = 0;
  59. adapter->FramesMissed = 0;
  60. adapter->FrameAlignmentErrors = 0;
  61. adapter->FramesXmitOneCollision = 0;
  62. adapter->FramesXmitManyCollisions = 0;
  63. adapter->CurrentTXBuf = &adapter->TXBuf[0];
  64. adapter->TXChainStart = NULL;
  65. // Packet filter settings...
  66. //
  67. adapter->fPromiscuousEnable = FALSE;
  68. adapter->fBroadcastEnable = FALSE;
  69. adapter->fMulticastEnable = FALSE;
  70. adapter->fReceiveEnabled = FALSE;
  71. adapter->NumMCAddresses = 0;
  72. // Don't force 8-bit operation
  73. //
  74. adapter->Use8Bit = FALSE;
  75. adapter->IntPending = EPRO_INT_NONE_PENDING;
  76. adapter->fHung = FALSE;
  77. // adapter->fTransmitInProgress = FALSE;
  78. // Set up the TX buffers...
  79. //
  80. for (i = 0;i < EPRO_NUM_TX_BUFFERS; i++)
  81. {
  82. if (0 == i)
  83. {
  84. adapter->TXBuf[0].LastBuf = &adapter->TXBuf[EPRO_NUM_TX_BUFFERS - 1];
  85. }
  86. else
  87. {
  88. adapter->TXBuf[i].LastBuf = &adapter->TXBuf[i-1];
  89. }
  90. if ((EPRO_NUM_TX_BUFFERS - 1) == i)
  91. {
  92. adapter->TXBuf[i].NextBuf = &adapter->TXBuf[0];
  93. }
  94. else
  95. {
  96. adapter->TXBuf[i].NextBuf = &adapter->TXBuf[i + 1];
  97. }
  98. adapter->TXBuf[i].fEmpty = TRUE;
  99. adapter->TXBuf[i].TXBaseAddr = 0;
  100. adapter->TXBuf[i].TXSendAddr = 0xffff;
  101. }
  102. }
  103. VOID EProEnableInterrupts(IN NDIS_HANDLE miniportAdapterContext)
  104. /*++
  105. Routine Description:
  106. The MiniportEnableInterrupt Handler for the card.
  107. Arguments:
  108. miniportAdapterContext - really a PEPRO_ADAPTER to our adapter structure
  109. Return Value: none
  110. --*/
  111. {
  112. PEPRO_ADAPTER adapter = (PEPRO_ADAPTER)miniportAdapterContext;
  113. // If this isn't true, then NdisMSyncronizeWithInterrupt is broken
  114. // or we've called a function which switches banks without syncronizing
  115. // it...
  116. EPRO_ASSERT_BANK_0(adapter);
  117. EPRO_WR_PORT_UCHAR(adapter, I82595_INTMASK_REG,
  118. adapter->CurrentInterruptMask);
  119. }
  120. VOID EProDisableInterrupts(IN NDIS_HANDLE miniportAdapterContext)
  121. /*++
  122. Routine Description:
  123. The MiniportDisableInterrupts handler for the driver
  124. Arguments:
  125. miniportAdapterContext - really a pointer to our adapter structure
  126. Return Values: none
  127. --*/
  128. {
  129. PEPRO_ADAPTER adapter = (PEPRO_ADAPTER)miniportAdapterContext;
  130. // If this isn't true, then NdisMSyncronizeWithInterrupt is broken
  131. // or we've called a function which switches banks without syncronizing
  132. // it...
  133. EPRO_ASSERT_BANK_0(adapter);
  134. // mask all int's
  135. EPRO_WR_PORT_UCHAR(adapter, I82595_INTMASK_REG,
  136. (adapter->CurrentInterruptMask | 0x0f));
  137. }
  138. VOID EProHalt(IN NDIS_HANDLE miniportAdapterContext)
  139. /*++
  140. Routine Description:
  141. This is the function which halts the 82595 chip and disables the
  142. adapter - frees hardware resources, etc.
  143. Arguments:
  144. miniportAdapterContext - pointer to our adapter structure
  145. Returns: nothing
  146. --*/
  147. {
  148. PEPRO_ADAPTER adapter = (EPRO_ADAPTER *)miniportAdapterContext;
  149. // Shut down the card - disable receives.
  150. EProReceiveDisable(adapter);
  151. // There won't be any more interrupts
  152. NdisMDeregisterInterrupt(&adapter->Interrupt);
  153. // Pause, wait for pending DPC stuff to clear... Random number stolen
  154. // from the NE2000 driver...
  155. NdisStallExecution(250000);
  156. // Unmap our IO ports
  157. NdisMDeregisterIoPortRange(adapter->MiniportAdapterHandle,
  158. (ULONG)adapter->IoBaseAddr,
  159. 0x10,
  160. (PVOID)adapter->IoPAddr);
  161. // Free up our adapter structure...
  162. NdisFreeMemory(adapter, sizeof(EPRO_ADAPTER), 0);
  163. }
  164. NDIS_STATUS EProReset(OUT PBOOLEAN fAddressingReset,
  165. IN NDIS_HANDLE miniportAdapterContext)
  166. /*++
  167. Routine Description:
  168. This is the MiniportReset handler for the EPro driver
  169. Arguments:
  170. fAddressingReset - Do we need to be re-told our MC address list?
  171. currently we say yes, although probably we don't
  172. have to be told this (the driver saves it)
  173. Return Values:
  174. the return from EProSelReset (always NDIS_STATUS_SUCCESS)
  175. --*/
  176. {
  177. PEPRO_ADAPTER adapter = (EPRO_ADAPTER *)miniportAdapterContext;
  178. // Okay, we don't want to get any interrupts anymore.
  179. EProDisableInterrupts(adapter);
  180. EProReceiveDisable(adapter);
  181. // clear out TX structures...
  182. EProInitializeAdapterData(adapter);
  183. // We probably can set this to false -- TODO
  184. *fAddressingReset = TRUE;
  185. return(EProSelReset(adapter));
  186. }
  187. BOOLEAN EProCheckForHang(IN NDIS_HANDLE miniportAdapterContext)
  188. /*++
  189. Routine Description:
  190. This is the MiniportCheckForHang handler for the driver.
  191. It does absolutely nothing right now.
  192. Arguments:
  193. miniportAdapterContext - right now a pointer to our adapter structure
  194. Return Value:
  195. --*/
  196. {
  197. PEPRO_ADAPTER adapter = (PEPRO_ADAPTER)miniportAdapterContext;
  198. if (adapter->fHung)
  199. {
  200. return(TRUE);
  201. }
  202. return(FALSE);
  203. }
  204. VOID EProHandleInterrupt(
  205. IN NDIS_HANDLE miniportAdapterContext)
  206. /*++
  207. Routine Description:
  208. This is the function that gets called at DPC level in response
  209. to a hardware interrupt. It is queued by the wrapper's ISR routines.
  210. Interrupts have been disabled when this routine is called.
  211. Arguments:
  212. miniportAdapterContext - really a pointer to our adapter structure
  213. Return Value:
  214. none
  215. --*/
  216. {
  217. PEPRO_ADAPTER adapter = (EPRO_ADAPTER *)miniportAdapterContext;
  218. UCHAR whichInt;
  219. BOOLEAN fFoundInts, fFoundRX = FALSE;
  220. // verify bank 0
  221. EPRO_ASSERT_BANK_0(adapter);
  222. do
  223. {
  224. fFoundInts = FALSE;
  225. // Read in the int mask
  226. //
  227. EPRO_RD_PORT_UCHAR(adapter, I82595_STATUS_REG, &whichInt);
  228. // quick out if there are no ints pending...
  229. if (!(whichInt & 0x0f))
  230. {
  231. break;
  232. }
  233. // acknowlege interrupts - writing a 1 over the int flag clears it
  234. EPRO_WR_PORT_UCHAR(adapter, I82595_STATUS_REG, whichInt);
  235. if (whichInt & I82595_TX_INT_RCVD)
  236. {
  237. fFoundInts = TRUE;
  238. if (adapter->TXChainStart != NULL)
  239. {
  240. EProCheckTransmitCompletion(adapter, adapter->TXChainStart);
  241. }
  242. }
  243. // if (whichInt & I82595_TX_INT_RCVD)
  244. // {
  245. // fFoundInts = TRUE;
  246. // if (adapter->TXChainStart != NULL)
  247. // {
  248. // while (EProCheckTransmitCompletion(adapter, adapter->TXChainStart))
  249. // ;
  250. // }
  251. // }
  252. if (whichInt & I82595_RX_INT_RCVD)
  253. {
  254. fFoundInts = TRUE;
  255. if (EProHandleReceive(adapter) > 0)
  256. {
  257. fFoundRX = TRUE;
  258. }
  259. }
  260. if (whichInt & I82595_EXEC_INT_RCVD)
  261. {
  262. fFoundInts = TRUE;
  263. EProSetInterruptMask(adapter, EPRO_DEFAULT_INTERRUPTS);
  264. switch(adapter->IntPending)
  265. {
  266. case EPRO_INT_MC_SET_PENDING:
  267. ((PEPRO_TRANSMIT_BUFFER)adapter->IntContext)->fEmpty = TRUE;
  268. EPRO_DPRINTF_INTERRUPT(("Set COMPLETED!"));
  269. NdisMSetInformationComplete(
  270. adapter->MiniportAdapterHandle,
  271. NDIS_STATUS_SUCCESS);
  272. break;
  273. // default:
  274. // EPRO_ASSERT(FALSE); // we shouldn't hit this...
  275. }
  276. // clear the pending interrupt...
  277. //
  278. adapter->IntPending = 0;
  279. adapter->IntContext = NULL;
  280. }
  281. } while ((fFoundInts == TRUE) && !adapter->fHung);
  282. if (fFoundRX)
  283. {
  284. NdisMEthIndicateReceiveComplete(adapter->MiniportAdapterHandle);
  285. }
  286. }
  287. void
  288. EProISR(
  289. OUT PBOOLEAN interruptRecognized,
  290. OUT PBOOLEAN queueMiniportHandleInterrupt,
  291. IN NDIS_HANDLE miniportAdapterContext)
  292. {
  293. EPRO_DPRINTF_INTERRUPT(("ISR"));
  294. *interruptRecognized = TRUE;
  295. *queueMiniportHandleInterrupt = FALSE;
  296. }
  297. BOOLEAN EProSyncSetInterruptMask(PVOID context)
  298. {
  299. PEPRO_ADAPTER adapter = ((PEPRO_SETINTERRUPT_CONTEXT)context)->Adapter;
  300. UCHAR newMask = ((PEPRO_SETINTERRUPT_CONTEXT)context)->NewMask;
  301. // unmask everyone...
  302. adapter->CurrentInterruptMask &= 0xf0;
  303. // now mask the ones we don't want
  304. adapter->CurrentInterruptMask |= newMask;
  305. EPRO_ASSERT_BANK_0(adapter);
  306. EPRO_WR_PORT_UCHAR(adapter, I82595_INTMASK_REG,
  307. adapter->CurrentInterruptMask);
  308. return(TRUE);
  309. }
  310. // Poll the exec-states reg (0,1), waiting for any execution to finish...
  311. BOOLEAN EProWaitForExeDma(PEPRO_ADAPTER adapter)
  312. {
  313. UINT i;
  314. UCHAR result;
  315. // status reg is in bank 0
  316. EPRO_ASSERT_BANK_0(adapter);
  317. for (i=0;i<I82595_SPIN_TIMEOUT;i++) {
  318. // make sure the dma is idle
  319. EPRO_RD_PORT_UCHAR(adapter, I82595_STATUS_REG, &result);
  320. if (!(result&I82595_EXEC_STATE)) {
  321. if (result & I82595_EXEC_INT_RCVD) {
  322. // clear the exec int if it's high...
  323. EPRO_WR_PORT_UCHAR(adapter, I82595_STATUS_REG,
  324. I82595_EXEC_INT_RCVD);
  325. }
  326. return(TRUE);
  327. }
  328. NdisStallExecution(1);
  329. }
  330. return(FALSE);
  331. }
  332. BOOLEAN EProReceiveEnable(PEPRO_ADAPTER adapter)
  333. {
  334. UINT i = 0;
  335. UCHAR result;
  336. adapter->RXCurrentAddress = 0 | (((USHORT)EPRO_RX_LOWER_LIMIT) << 8);
  337. // EPRO_ASSERT(!adapter->fReceiveEnabled);
  338. // don't enable if we're already enabled.
  339. if (adapter->fReceiveEnabled)
  340. {
  341. return(TRUE);
  342. }
  343. // bank0
  344. // EPRO_SWITCH_BANK_0(adapter);
  345. //
  346. EPRO_ASSERT_BANK_0(adapter);
  347. EPRO_WR_PORT_USHORT(adapter, I82595_RX_STOP_REG, 0 | (((USHORT)EPRO_RX_UPPER_LIMIT) << 8));
  348. EPRO_WR_PORT_USHORT(adapter, I82595_RX_BAR_REG, 0 | (((USHORT)EPRO_RX_LOWER_LIMIT) << 8));
  349. //
  350. // validate registers...
  351. //
  352. EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_RCV_ENABLE);
  353. adapter->fReceiveEnabled = TRUE;
  354. return(TRUE);
  355. }
  356. BOOLEAN EProReceiveDisable(PEPRO_ADAPTER adapter)
  357. {
  358. UINT i = 0;
  359. UCHAR result;
  360. // bank0
  361. // EPRO_SWITCH_BANK_0(adapter);
  362. EPRO_ASSERT_BANK_0(adapter);
  363. EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_STOP_RCV);
  364. adapter->fReceiveEnabled = FALSE;
  365. return(TRUE);
  366. }
  367. //VOID EProTimerFunc(IN PVOID foo1, IN PVOID context, IN PVOID foo2, IN PVOID foo3)
  368. //{
  369. // EProHandleInterrupt((NDIS_HANDLE)context);
  370. //
  371. // queue another timer...
  372. // NdisMSetTimer(&(((PEPRO_ADAPTER)context)->MiniportTimer), 10);
  373. //}