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.

1178 lines
34 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. //////////////////////////////////////////////////////////////////////
  8. // SEND code
  9. //////////////////////////////////////////////////////////////////////
  10. ULONG numberOfResources = 0;
  11. NDIS_STATUS EProSend(IN NDIS_HANDLE miniportAdapterContext,
  12. IN PNDIS_PACKET packet,
  13. IN UINT flags)
  14. /*++
  15. Routine Description:
  16. The MiniportSend handler for the EPro. About 18 million different
  17. things happen here:
  18. 1) We need to see if there are free transmit buffer pointer for
  19. this packet.
  20. 2) Once we've got a tx buffer pointer, we then see if we have enough
  21. physical memory space for this transmit. If we don't, then
  22. we resources out
  23. 3) We need to copy the 82595 frame header, then the packet to the card
  24. 4) We need to start the transmit if none are in progress
  25. 5) We need to update some structures to keep track of the transmit
  26. Arguments:
  27. miniportAdapterContext - Really a pointer to our EPRO_ADAPTER structure
  28. packet - the packet to send
  29. flags - an optional FLAGS field - not used currently in NDIS
  30. Return Value:
  31. NDIS_STATUS_RESOURCES - no free transmit buffers. Please hang up and then
  32. dial again. If you need help, please dial your operator
  33. NDIS_STATUS_PENDING - The packet is on the card and is being sent.
  34. --*/
  35. {
  36. PEPRO_ADAPTER adapter = (EPRO_ADAPTER *)miniportAdapterContext;
  37. // This is the adapter's current transmit buffer...
  38. PEPRO_TRANSMIT_BUFFER curTBuf = adapter->CurrentTXBuf;
  39. USHORT freeSpace;
  40. UINT totalPacketLength;
  41. USHORT result;
  42. // If we're currently executing an MC_SETUP command, we can't
  43. // handle any transmits. The reason is that the MC_SETUP uses
  44. // a transmit buffer, and we will have problems trying to complete
  45. // transfers if we do both at the same time. There are a few ways
  46. // we could get around this, but they'd make things more complicated,
  47. // and don't gain us much if we go by the assumption that in "normal"
  48. // use we won't get that many MC-setups...
  49. if (adapter->IntPending == EPRO_INT_MC_SET_PENDING) {
  50. return(NDIS_STATUS_RESOURCES);
  51. }
  52. // Check for free buffer. If can't find one, then return
  53. // NDIS_STATUS_RESOURCES.
  54. // is the current buffer free?
  55. if (!curTBuf->fEmpty) {
  56. // nope. can we free it?
  57. if (!EProCheckTransmitCompletion(adapter, curTBuf)) {
  58. numberOfResources++;
  59. return(NDIS_STATUS_RESOURCES);
  60. }
  61. }
  62. // Get the total length of this packet so we can see if we have
  63. // room for it.
  64. NdisQueryPacket(packet, NULL, NULL, NULL, &totalPacketLength);
  65. curTBuf->TXSize = totalPacketLength;
  66. // Add in the 82595's tx memory structure plus 2 bytes padding
  67. // between frames
  68. totalPacketLength+=(I82595_TX_FRM_HDR_SIZE + 2);
  69. // is there a transmit in progress?
  70. if (adapter->TXChainStart == NULL) {
  71. curTBuf->TXBaseAddr = EPRO_TX_LOWER_LIMIT_SHORT;
  72. curTBuf->NextBuf->TXBaseAddr = totalPacketLength;
  73. } else {
  74. // Do we have free space for this packet?
  75. EPRO_ASSERT(adapter->TXChainStart != curTBuf);
  76. EPRO_ASSERT(curTBuf->TXBaseAddr >= EPRO_TX_LOWER_LIMIT_SHORT);
  77. // Although TxBaseAddr == upper limit is NOT LEGAL, we allow it in
  78. // this assert because it will fall through the next if statement
  79. // and be dealt with properly. (freespace will = 0 and then we will wrap)
  80. EPRO_ASSERT(curTBuf->TXBaseAddr <= EPRO_TX_UPPER_LIMIT_SHORT);
  81. // Now we need to know if the current buffer position is above or
  82. // below the space in use.
  83. if (adapter->TXChainStart->TXBaseAddr >= curTBuf->TXBaseAddr) {
  84. // We're BELOW the in-use space
  85. freeSpace = adapter->TXChainStart->TXBaseAddr -
  86. curTBuf->TXBaseAddr;
  87. } else {
  88. freeSpace = EPRO_TX_UPPER_LIMIT_SHORT -
  89. curTBuf->TXBaseAddr;
  90. freeSpace += (adapter->TXChainStart->TXBaseAddr -
  91. EPRO_TX_LOWER_LIMIT_SHORT);
  92. }
  93. if (freeSpace < totalPacketLength) {
  94. return(NDIS_STATUS_RESOURCES);
  95. }
  96. }
  97. // Now, the set the next buffer's address:
  98. curTBuf->NextBuf->TXBaseAddr = curTBuf->TXBaseAddr +
  99. totalPacketLength;
  100. if (curTBuf->NextBuf->TXBaseAddr >= EPRO_TX_UPPER_LIMIT_SHORT)
  101. curTBuf->NextBuf->TXBaseAddr -= EPRO_TX_UPPER_LIMIT_SHORT;
  102. // Okay, when we've gotten to this point, it's because we've determined
  103. // that there is enough space on the card for the packet. So, now we
  104. // set the current transmit buffer to be empty.
  105. curTBuf->fEmpty = FALSE;
  106. // move the current buffer pointer forward
  107. adapter->CurrentTXBuf = curTBuf->NextBuf;
  108. // bank 0
  109. EPRO_ASSERT_BANK_0(adapter);
  110. // set our packet pointer so we can ethindicatereceive later.
  111. curTBuf->TXPacket = packet;
  112. // This is a double-check that the txbuffer structure was freed
  113. // correctly -- this is set in checktransmitcompletion
  114. EPRO_ASSERT(curTBuf->TXSendAddr == 0xffff);
  115. // We make a backup copy of the TXBaseAddr, in case we use up all
  116. // of our buffer pointer strucutres and wrap around and overwrite the
  117. // TXBaseAddr of this buffer....
  118. curTBuf->TXSendAddr = curTBuf->TXBaseAddr;
  119. // Set the address on the card to copy to
  120. EPRO_SET_HOST_ADDR(adapter, curTBuf->TXBaseAddr);
  121. EProCopyPacketToCard(adapter, packet);
  122. // Is there a transmit already going?
  123. if (!adapter->TXChainStart) {
  124. // Nope - queue this one up and let it rip..
  125. {
  126. UINT i;
  127. UCHAR result;
  128. for (i=0;i<I82595_SPIN_TIMEOUT;i++) {
  129. EPRO_RD_PORT_UCHAR(adapter, I82595_STATUS_REG, &result);
  130. if (!(result &I82595_EXEC_STATE)) {
  131. if (result & I82595_EXEC_INT_RCVD) {
  132. EPRO_WR_PORT_UCHAR(adapter, I82595_STATUS_REG,
  133. I82595_EXEC_INT_RCVD);
  134. }
  135. break;
  136. }
  137. }
  138. }
  139. // Set up and start the transmit
  140. EPRO_WR_PORT_USHORT(adapter, I82595_TX_BAR_REG, curTBuf->TXBaseAddr);
  141. EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_XMT);
  142. adapter->TXChainStart = curTBuf;
  143. } else {
  144. // If chainstart != NULL (ie is pointing to a buffer) and there is no tx
  145. // in progress - we're hosed....
  146. // if (curTBuf->LastBuf->TXSendAddr + 4 >= EPRO_TX_UPPER_LIMIT_SHORT) {
  147. // EPRO_SET_HOST_ADDR(adapter, ((curTBuf->LastBuf->TXSendAddr + 4) -
  148. // EPRO_TX_UPPER_LIMIT_SHORT));
  149. // } else {
  150. // EPRO_SET_HOST_ADDR(adapter, (curTBuf->LastBuf->TXSendAddr + 4));
  151. // }
  152. // EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG,
  153. // curTBuf->TXSendAddr);
  154. // EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG,
  155. // curTBuf->LastBuf->TXSize | 8000);
  156. //
  157. // EPRO_RD_PORT_USHORT(adapter, I82595_MEM_IO_REG, &result);
  158. //
  159. // EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_XMT_RESUME);
  160. }
  161. // okay, we're PENDING...
  162. return(NDIS_STATUS_PENDING);
  163. }
  164. VOID EProCopyPacketToCard(PEPRO_ADAPTER adapter,
  165. PNDIS_PACKET packet)
  166. /*++
  167. Routine Description:
  168. This routine copies a packet down to the card. We assume the card's IO port
  169. has been set to the correct address at function entry.
  170. Parameters:
  171. adapter - Pointer to our EPRO_ADAPTER structure
  172. packet - pointer to the NDIS_PACKET we are copying down.
  173. Return Values:
  174. none
  175. --*/
  176. {
  177. // frame header....
  178. EPRO_TX_FRAME_HEADER txFrameHeader;
  179. // This is a hack to transfer buffers of odd lengths
  180. BOOLEAN fForward = FALSE;
  181. // this is the
  182. USHORT forwardedShort;
  183. // The physical address of the buffer to copy out of...
  184. PVOID bufferAddr;
  185. // packet information
  186. UINT bufferCount, totalPacketLength, bufferLen, currentOffset;
  187. // This is the current buffer of the packet that is passed in...
  188. PNDIS_BUFFER curBuffer;
  189. // Get the first buffer out of the packet.
  190. NdisQueryPacket(packet, NULL, &bufferCount,
  191. &curBuffer, &totalPacketLength);
  192. // Copy the TX header down to the card.
  193. EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG, I82595_XMT_SHORT);
  194. EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG, 0);
  195. EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG, 0);
  196. EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG, totalPacketLength);
  197. /////////////////////////////////////////////////////
  198. // LOOP on all the buffers in the packet...
  199. /////////////////////////////////////////////////////
  200. do {
  201. NdisQueryBuffer(curBuffer, &bufferAddr, &bufferLen);
  202. // skip over zero-length buffers.
  203. if (bufferLen == 0) {
  204. NdisGetNextBuffer(curBuffer, &curBuffer);
  205. continue;
  206. }
  207. // BEGIN fix for odd-length buffers
  208. if (fForward) {
  209. fForward = FALSE;
  210. forwardedShort |= ((*((UCHAR *)bufferAddr)) << 8);
  211. ((UCHAR *)bufferAddr)++;
  212. bufferLen--;
  213. EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG, forwardedShort);
  214. }
  215. if (bufferLen & 1) {
  216. fForward = TRUE;
  217. forwardedShort =*(UCHAR *)( ((UCHAR *)bufferAddr) + (bufferLen-1) );
  218. }
  219. // END fix for odd-length buffers...
  220. #ifndef EPRO_USE_32_BIT_IO
  221. EPRO_COPY_BUFFER_TO_NIC_USHORT(adapter,
  222. ((UNALIGNED USHORT *)bufferAddr),
  223. ((ULONG)bufferLen>>1));
  224. #else
  225. // using 32-bit
  226. if (adapter->EProUse32BitIO) {
  227. if (bufferLen & 2) {
  228. EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG,
  229. *((UNALIGNED USHORT *)bufferAddr));
  230. (UCHAR *)bufferAddr += 2;
  231. EPRO_COPY_BUFFER_TO_NIC_ULONG(adapter, ((UNALIGNED ULONG *)bufferAddr),
  232. ((ULONG)bufferLen >> 2));
  233. } else {
  234. EPRO_COPY_BUFFER_TO_NIC_ULONG(adapter, ((UNALIGNED ULONG *)bufferAddr),
  235. ((ULONG)bufferLen >> 2));
  236. }
  237. } else {
  238. // This is an older version of the 82595 - we need to use 16-bit anyway
  239. EPRO_COPY_BUFFER_TO_NIC_USHORT(adapter,
  240. (USHORT *)bufferAddr,
  241. ((ULONG)bufferLen>>1));
  242. }
  243. #endif
  244. NdisGetNextBuffer(curBuffer, &curBuffer);
  245. } while (curBuffer);
  246. ////////////////////////////////////////////////////////
  247. // END of loop for all buffers in packet
  248. ////////////////////////////////////////////////////////
  249. // copy down a trailing byte
  250. if (fForward) {
  251. EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG, forwardedShort);
  252. }
  253. }
  254. BOOLEAN EProCheckTransmitCompletion(PEPRO_ADAPTER adapter,
  255. PEPRO_TRANSMIT_BUFFER txBuf)
  256. /*++
  257. Routine Description:
  258. This routine takes the transmit buffer pointed to by txBuf and tries to
  259. free it. This can be called from two places. On an adapter that is very
  260. very busy transmitting, it can get called from our send handler if the send
  261. handler is called and all the transmit buffers on the card are full. This
  262. routine is called directly from the send handler to minimize the latency of
  263. the returning NDIS_STATUS_RESOURCES----free buffer in interrupt handler dpc---
  264. ---ndis calls back down in it's send handler. There is the possibility here
  265. that packets will be sent out of order in this, but it doesn't matter, let the
  266. protocols figure that out.
  267. This routine is also called by our handleinterrupt handler where it does the
  268. exact same thing, except in response to a transmit interrupt.
  269. Arguments:
  270. adapter - a pointer to our EPRO_ADAPTER structure
  271. txBuf - this is a pointer to the transmit buffer we are checking
  272. Return Value:
  273. TRUE if the buffer is already free or has been indicated and now is free.
  274. FALSE if the buffer is not finished being transmitted.
  275. --*/
  276. {
  277. UCHAR result;
  278. USHORT status;
  279. // NDIS_STATUS returnStatus = NDIS_STATUS_FAILURE;
  280. if (!txBuf) {
  281. return(FALSE);
  282. }
  283. if (txBuf->fEmpty) {
  284. return(TRUE);
  285. }
  286. // if we got through the first if, then there must be a non-empty
  287. // buffer. Therefore, we have to assume that there is a transmit in
  288. // progress (txchainstart is set to the tx in progress) - if there
  289. // is not one in progress, then something is screwed.
  290. EPRO_ASSERT(adapter->TXChainStart != NULL);
  291. // bank0
  292. EPRO_ASSERT_BANK_0(adapter);
  293. // Check and see if this transmit has completed...
  294. EPRO_SET_HOST_ADDR(adapter, txBuf->TXSendAddr);
  295. // check DN (tx done) flag...
  296. EPRO_RD_PORT_USHORT(adapter, I82595_MEM_IO_REG, &status);
  297. // See if the TX_DONE bit is set...
  298. if (!(status & I82595_TX_DN_BYTE_MASK)) {
  299. return(FALSE);
  300. }
  301. // Check the status of the transmition
  302. EPRO_RD_PORT_USHORT(adapter, I82595_MEM_IO_REG, &status);
  303. if (status & I82595_TX_OK_SHORT_MASK) {
  304. // returnStatus = NDIS_STATUS_SUCCESS;
  305. adapter->FramesXmitOK++;
  306. if ((status & I82595_NO_COLLISIONS_MASK) > 0) {
  307. adapter->FramesXmitOneCollision++;
  308. if ((status & I82595_NO_COLLISIONS_MASK) > 1) {
  309. adapter->FramesXmitManyCollisions++;
  310. }
  311. }
  312. } else {
  313. adapter->FramesXmitErr++;
  314. // D---it, the frame errored out...
  315. // Just re-send it.
  316. EPRO_SET_HOST_ADDR(adapter, adapter->TXChainStart->TXSendAddr);
  317. EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG, I82595_XMT);
  318. EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG, 0);
  319. if (!EProWaitForExeDma(adapter)) {
  320. adapter->fHung = TRUE;
  321. // EPRO_ASSERT(FALSE);
  322. }
  323. EPRO_WR_PORT_USHORT(adapter, I82595_TX_BAR_REG,
  324. adapter->TXChainStart->TXSendAddr);
  325. EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_XMT);
  326. return(FALSE);
  327. }
  328. // move the chain forward b/c this buffer has been freed....
  329. #if DBG
  330. adapter->TXChainStart->TXSendAddr = 0xffff;
  331. #endif
  332. adapter->TXChainStart = adapter->TXChainStart->NextBuf;
  333. if (adapter->TXChainStart == adapter->CurrentTXBuf) {
  334. // since we just moved the chain FORWARD one, if these
  335. // two pointers are equal it means the buffer is EMPTY, not full...
  336. adapter->TXChainStart = NULL;
  337. } else {
  338. // Make sure the card is idle
  339. // EProWaitForExeDma(adapter);
  340. {
  341. UINT i;
  342. for (i=0;i<I82595_SPIN_TIMEOUT;i++) {
  343. EPRO_RD_PORT_UCHAR(adapter, I82595_STATUS_REG, &result);
  344. if (!(result &I82595_EXEC_STATE)) {
  345. if (result & I82595_EXEC_INT_RCVD) {
  346. EPRO_WR_PORT_UCHAR(adapter, I82595_STATUS_REG,
  347. I82595_EXEC_INT_RCVD);
  348. }
  349. break;
  350. }
  351. }
  352. }
  353. // Get the next TX going....
  354. EPRO_WR_PORT_USHORT(adapter, I82595_TX_BAR_REG,
  355. adapter->TXChainStart->TXSendAddr);
  356. EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_XMT);
  357. }
  358. // this buffer is empty now.
  359. txBuf->fEmpty = TRUE;
  360. // Yes, here's the deep and dark secret: either we succeed a packet,
  361. // or we re-send it, so whenever packets complete, they ALWAYS
  362. // succeed :)
  363. NdisMSendComplete(adapter->MiniportAdapterHandle,
  364. txBuf->TXPacket, NDIS_STATUS_SUCCESS);
  365. return(TRUE);
  366. }
  367. //////////////////////////////////////////////////////////////////////
  368. //////////////////////////////////////////////////////////////////////
  369. // RECEIVE code...
  370. //////////////////////////////////////////////////////////////////////
  371. //////////////////////////////////////////////////////////////////////
  372. UINT EProHandleReceive(PEPRO_ADAPTER adapter)
  373. /*++
  374. Routine Description:
  375. This is the dpc-level code that really handles a receive interrupt.
  376. Arguments:
  377. adapter - pointer to the adapter structure.
  378. Return Value:
  379. the number of packets received
  380. --*/
  381. {
  382. // The 82595s RCV header
  383. EPRO_RCV_HEADER header;
  384. // the Ethernet header to indicate up
  385. EPRO_ETH_HEADER ethHeader;
  386. // temp variable to figure out how much to copy up
  387. USHORT bytesToCopy;
  388. // Our context to pass in NdisMEthIndicateReceive...
  389. EPRO_RCV_CONTEXT context;
  390. // Use this to loop and handle multiple receives in one int...
  391. //
  392. UCHAR tempCopy;
  393. UINT numRcvd = 0;
  394. // bank0
  395. // EPRO_SWITCH_BANK_0(adapter);
  396. //
  397. EPRO_ASSERT_BANK_0(adapter);
  398. if ((adapter->RXCurrentAddress < EPRO_RX_LOWER_LIMIT_SHORT) ||
  399. (adapter->RXCurrentAddress > EPRO_RX_UPPER_LIMIT_SHORT))
  400. {
  401. adapter->fHung = TRUE;
  402. #if DBG
  403. DbgPrint("the RxCurrentAddress is not within acceptable limits: 0x%x\n", adapter->RXCurrentAddress);
  404. // EPRO_ASSERT(FALSE);
  405. #endif
  406. return(0);
  407. }
  408. // Read the header...
  409. EPRO_SET_HOST_ADDR(adapter, adapter->RXCurrentAddress);
  410. EPRO_READ_BUFFER_FROM_NIC_USHORT(
  411. adapter,
  412. (USHORT *)&header,
  413. ((ULONG)sizeof(EPRO_RCV_HEADER) >> 1));
  414. // Process one or more received frames...
  415. while ((header.Event == I82595_RX_EOF) && !adapter->fHung)
  416. {
  417. // Was the transmit OK?
  418. if (!header.Status1 & I82595_RX_OK)
  419. {
  420. adapter->FramesRcvErr++;
  421. // Since we configure the 82595 to discard bad frames, we know we've reached the
  422. // latest received frame when we hit a bad one -- since the card will "reclaim"
  423. // the space filled by the bad frame as soon as it gets another one.
  424. break;
  425. }
  426. else
  427. {
  428. numRcvd++;
  429. // Fill in our receive context - to be passed in to TransferData
  430. context.RXFrameSize = (USHORT)((USHORT)header.ByteCountLo) | (((USHORT)header.ByteCountHi) << 8);
  431. // Figure out how many bytes to indicate up. Either the size of the current lookahead
  432. // or the entire frame - whichever is smaller.
  433. bytesToCopy = ((context.RXFrameSize-sizeof(EPRO_ETH_HEADER)) > adapter->RXLookAheadSize) ?
  434. adapter->RXLookAheadSize :
  435. (context.RXFrameSize - sizeof(EPRO_ETH_HEADER));
  436. EPRO_READ_BUFFER_FROM_NIC_USHORT(
  437. adapter,
  438. (USHORT *)(&ethHeader),
  439. sizeof(EPRO_ETH_HEADER) >> 1);
  440. #ifndef EPRO_USE_32_BIT_IO
  441. EPRO_READ_BUFFER_FROM_NIC_USHORT(adapter, &adapter->RXLookAhead, bytesToCopy >> 1);
  442. #else
  443. if (adapter->EProUse32BitIO)
  444. {
  445. if (bytesToCopy & 2)
  446. {
  447. EPRO_RD_PORT_USHORT(
  448. adapter,
  449. I82595_MEM_IO_REG,
  450. (UNALIGNED USHORT *)(&adapter->RXLookAhead));
  451. EPRO_READ_BUFFER_FROM_NIC_ULONG(
  452. adapter,
  453. (UNALIGNED ULONG *)(((UCHAR *)&(adapter->RXLookAhead)) + 2),
  454. bytesToCopy >> 2);
  455. }
  456. else
  457. {
  458. EPRO_READ_BUFFER_FROM_NIC_ULONG(
  459. adapter,
  460. (UNALIGNED ULONG *)(&(adapter->RXLookAhead)),
  461. bytesToCopy >> 2);
  462. }
  463. }
  464. else
  465. {
  466. // This is an old version of the 82595 - we have to use 16-bit IO
  467. EPRO_READ_BUFFER_FROM_NIC_USHORT(
  468. adapter,
  469. (USHORT *)&adapter->RXLookAhead,
  470. bytesToCopy>>1);
  471. }
  472. #endif
  473. if (bytesToCopy & 1)
  474. {
  475. // just read the low-order byte here....
  476. EPRO_RD_PORT_UCHAR(adapter, I82595_MEM_IO_REG, &tempCopy);
  477. adapter->RXLookAhead[bytesToCopy-1] = tempCopy;
  478. }
  479. context.RXCurrentAddress = adapter->RXCurrentAddress;
  480. context.LookAheadSize = bytesToCopy;
  481. // indicate packet
  482. NdisMEthIndicateReceive(adapter->MiniportAdapterHandle,
  483. (NDIS_HANDLE)&context,
  484. (PCHAR)&ethHeader,
  485. sizeof(EPRO_ETH_HEADER),
  486. &adapter->RXLookAhead,
  487. bytesToCopy,
  488. context.RXFrameSize - sizeof(EPRO_ETH_HEADER));
  489. // verify bank0
  490. EPRO_ASSERT_BANK_0(adapter);
  491. }
  492. {
  493. USHORT temp = (USHORT)header.NextFrmLo | (((USHORT)header.NextFrmHi) << 8);
  494. if ((temp < EPRO_RX_LOWER_LIMIT_SHORT) ||
  495. (temp > EPRO_RX_UPPER_LIMIT_SHORT))
  496. {
  497. adapter->fHung = TRUE;
  498. #if DBG
  499. DbgPrint("The receive header has an invalid next frame pointer!\n");
  500. DbgPrint("current rx: %lx, rx: %lx, hi: %x, lo: %x hdr: %lx\n",
  501. adapter->RXCurrentAddress,
  502. temp,
  503. header.NextFrmHi,
  504. header.NextFrmLo,
  505. &header);
  506. // EPRO_ASSERT(FALSE);
  507. #endif
  508. break;
  509. }
  510. }
  511. adapter->RXCurrentAddress = (USHORT)header.NextFrmLo | (((USHORT)header.NextFrmHi) << 8);
  512. // Seek to the next frame
  513. EPRO_SET_HOST_ADDR(adapter, adapter->RXCurrentAddress);
  514. // Read the header...
  515. EPRO_READ_BUFFER_FROM_NIC_USHORT(
  516. adapter,
  517. (USHORT *)(&header),
  518. sizeof(EPRO_RCV_HEADER) >> 1);
  519. }
  520. // now, update the stop reg to = the bottom of the received frame....
  521. if (numRcvd > 0)
  522. {
  523. USHORT value;
  524. value = context.RXCurrentAddress + context.RXFrameSize;
  525. // wrap around...
  526. if (value >= EPRO_RX_UPPER_LIMIT_SHORT)
  527. {
  528. value -= (EPRO_RX_UPPER_LIMIT_SHORT - EPRO_RX_LOWER_LIMIT_SHORT);
  529. }
  530. if (!((value <= EPRO_RX_UPPER_LIMIT_SHORT) &&
  531. (value >= EPRO_RX_LOWER_LIMIT_SHORT)))
  532. {
  533. adapter->fHung = TRUE;
  534. #if DBG
  535. DbgPrint("ca: %lx, fs: %lx, val: %lx",
  536. context.RXCurrentAddress,
  537. context.RXFrameSize,
  538. value);
  539. // EPRO_ASSERT(FALSE);
  540. #endif
  541. }
  542. EPRO_WR_PORT_USHORT(adapter, I82595_RX_STOP_REG, value);
  543. }
  544. adapter->FramesRcvOK += numRcvd;
  545. return(numRcvd);
  546. }
  547. #if 0
  548. // You know. This code PASSES all the stress tests. Passes everything the
  549. // tester can throw out, but still is broken when I try to make it work
  550. // in real life. <sigh>. Look at this later.
  551. NDIS_STATUS EProTransferData(OUT PNDIS_PACKET packet,
  552. OUT PUINT bytesTransferred,
  553. IN NDIS_HANDLE miniportAdapterContext,
  554. IN NDIS_HANDLE miniportReceivedContext,
  555. IN UINT byteOffset,
  556. IN UINT bytesToTransfer)
  557. /*++
  558. Routine Description:
  559. The transferdata handler for the EPro.
  560. Arguments:
  561. packet - The packet to transfer the data into
  562. bytesTransferred - The number of bytes actually copied into packet.
  563. miniportAdapterContext - Reallly a pointer to our EPRO_ADAPTER structure
  564. miniportReceivedContext - This is our EPRO_RCV_CONTEXT, which basically just
  565. has the packet length and pointer to where it lies
  566. in the card's address space.
  567. byteOffset - where in the frame to begin trasferring from
  568. bytesToTransfer - how many bytes to transfer.
  569. Return Value:
  570. NDIS_STATUS_SUCCESS - data transfered OK
  571. NDIS_STATUS_FAILURE - tried to transfer off end of frame
  572. --*/
  573. {
  574. PEPRO_ADAPTER adapter = (PEPRO_ADAPTER)miniportAdapterContext;
  575. // The 82595's on-card RCV memory structure
  576. EPRO_RCV_HEADER header;
  577. // An 802.3 ethernet header.
  578. EPRO_ETH_HEADER ethHeader;
  579. // How many bytes have we copied, how many are left to copy
  580. USHORT byteCount, bytesToCopy;
  581. PEPRO_RCV_CONTEXT pcontext = (PEPRO_RCV_CONTEXT)miniportReceivedContext;
  582. // The current buffer we are copying into.
  583. PNDIS_BUFFER curDestBuf;
  584. // The physical address of the buffer we are currently copying into
  585. PVOID curDestBufAddr;
  586. // The length of that buffer
  587. UINT curDestBufLen;
  588. // Two bytes used when we have to transfer in to odd-length buffers (since
  589. // accesses to the EPro's memory are only by-word.
  590. UCHAR tempCopy[2];
  591. // This is TRUE if we are "forwarding" a single byte from an odd-length transfer
  592. BOOLEAN fForward = FALSE;
  593. // the address to read from on the card
  594. USHORT cardAddress;
  595. UINT bytesWriteThisPacket;
  596. // TODO - copy first lookahead size bytes out of lookahead buffer.
  597. *bytesTransferred = 0;
  598. // switch to bank0 for mem io
  599. EPRO_ASSERT_BANK_0(adapter);
  600. // Make sure they're not seeking past the end of the frame
  601. if (byteOffset > pcontext->RXFrameSize) {
  602. return(NDIS_STATUS_FAILURE);
  603. }
  604. // get the first buffer
  605. NdisQueryPacket(packet, NULL, NULL, &curDestBuf, NULL);
  606. // copy the amount requested, or the entire packet - whichever is smaller
  607. if ((bytesToTransfer + byteOffset) <= pcontext->RXFrameSize) {
  608. bytesToCopy = bytesToTransfer;
  609. } else {
  610. bytesToCopy = (pcontext->RXFrameSize - byteOffset);
  611. }
  612. // first loop -- copy up to the end of the lookahead buffer's worth:
  613. if (byteOffset < adapter->RXLookAheadSize) {
  614. UINT laOffset = byteOffset;
  615. UINT laToCopy = adapter->RXLookAheadSize - laOffset;
  616. if (laToCopy > bytesToCopy) {
  617. laToCopy = bytesToCopy;
  618. }
  619. *bytesTransferred+=laToCopy;
  620. bytesToCopy-=laToCopy;
  621. while (laToCopy > 0) {
  622. NdisQueryBuffer(curDestBuf, &curDestBufAddr, &curDestBufLen);
  623. if (curDestBufLen == 0) {
  624. continue;
  625. }
  626. // We either write the entire buffer size bytes or the number of bytes
  627. // remaining to copy - whichever is smaller.
  628. bytesWriteThisPacket = (laToCopy > curDestBufLen) ?
  629. curDestBufLen : laToCopy;
  630. EPRO_ASSERT(bytesWriteThisPacket <= laToCopy);
  631. NdisMoveMemory(curDestBufAddr, &adapter->RXLookAhead[laOffset],
  632. bytesWriteThisPacket);
  633. laToCopy-=bytesWriteThisPacket;
  634. laOffset+=bytesWriteThisPacket;
  635. }
  636. byteOffset = adapter->RXLookAheadSize;
  637. EPRO_ASSERT(bytesToCopy >= laToCopy);
  638. if (bytesToCopy == 0) {
  639. EProLogStr(" 1BytesTo:");
  640. EProLogLong(bytesToTransfer);
  641. EProLogStr("BytesTransf:");
  642. EProLogLong(*bytesTransferred);
  643. return(NDIS_STATUS_SUCCESS);
  644. }
  645. if (curDestBufLen > bytesWriteThisPacket) {
  646. (UCHAR *)curDestBufAddr += bytesWriteThisPacket;
  647. } else {
  648. curDestBufLen = 0;
  649. while (curDestBufLen == 0) {
  650. NdisGetNextBuffer(curDestBuf, &curDestBuf);
  651. if (!curDestBuf) {
  652. EProLogStr(" 2BytesTo:");
  653. EProLogLong(bytesToTransfer);
  654. EProLogStr("BytesTransf:");
  655. EProLogLong(*bytesTransferred);
  656. return(NDIS_STATUS_SUCCESS);
  657. }
  658. NdisQueryBuffer(curDestBuf, &curDestBufAddr, &curDestBufLen);
  659. }
  660. }
  661. } else {
  662. NdisQueryBuffer(curDestBuf, &curDestBufAddr, &curDestBufLen);
  663. }
  664. // set our memory address on the card...
  665. cardAddress = (pcontext->RXCurrentAddress + sizeof(EPRO_RCV_HEADER) +
  666. sizeof(EPRO_ETH_HEADER) + byteOffset);
  667. // Set the address on the card. Note that you can do sequential reads
  668. // from the IO port which WRAP around the memory boundry, but if you
  669. // manually set the address, you have to wrap manually.
  670. if (cardAddress >= EPRO_RX_UPPER_LIMIT_SHORT) {
  671. cardAddress -= (EPRO_RX_UPPER_LIMIT_SHORT - EPRO_RX_LOWER_LIMIT_SHORT);
  672. }
  673. // Are we starting of reading from an odd address?
  674. if (cardAddress & 1) {
  675. // yes; odd offset -- forward a byte in...
  676. fForward = TRUE;
  677. cardAddress--;
  678. }
  679. // Okay, now seek to the right address on the card
  680. EPRO_SET_HOST_ADDR(adapter, cardAddress);
  681. // Are we forwarding a byte in? If so, fetch it now....
  682. if (fForward == TRUE) {
  683. EPRO_RD_PORT_USHORT(adapter, I82595_MEM_IO_REG, (USHORT *)(&tempCopy));
  684. }
  685. // continue until we either run out of buffers, or out of bytes....
  686. while((bytesToCopy > 0) && (curDestBuf!=NULL)) {
  687. // We either write the entire buffer size bytes or the number of bytes
  688. // remaining to copy - whichever is smaller.
  689. bytesWriteThisPacket = (bytesToCopy > curDestBufLen) ?
  690. curDestBufLen : bytesToCopy;
  691. bytesToCopy-=bytesWriteThisPacket;
  692. // Ooh, we're going to transfer some bytes...
  693. *bytesTransferred+=bytesWriteThisPacket;
  694. // Okay. Did we have to forward a byte in? Copy it to the buffer NOW..
  695. if (fForward == TRUE) {
  696. *(UCHAR *)curDestBufAddr = tempCopy[1];
  697. fForward = FALSE;
  698. ((UCHAR *)curDestBufAddr)++;
  699. bytesWriteThisPacket--;
  700. }
  701. // Copy the bulk of the data...
  702. #ifndef EPRO_USE_32_BIT_IO
  703. EPRO_READ_BUFFER_FROM_NIC_USHORT(adapter, curDestBufAddr,
  704. bytesWriteThisPacket>>1);
  705. #else
  706. if (adapter->EProUse32BitIO) {
  707. if (bytesWriteThisPacket & 2) {
  708. EPRO_RD_PORT_USHORT(adapter, I82595_MEM_IO_REG, (USHORT *)curDestBufAddr);
  709. EPRO_READ_BUFFER_FROM_NIC_ULONG(adapter,
  710. (UNALIGNED ULONG *)((UCHAR *)curDestBufAddr +2),
  711. bytesWriteThisPacket >> 2);
  712. } else {
  713. EPRO_READ_BUFFER_FROM_NIC_ULONG(adapter,
  714. (UNALIGNED ULONG *)curDestBufAddr,
  715. bytesWriteThisPacket >> 2);
  716. }
  717. } else {
  718. EPRO_READ_BUFFER_FROM_NIC_USHORT(adapter, curDestBufAddr,
  719. bytesWriteThisPacket>>1);
  720. }
  721. #endif
  722. // Okay, the rshift in the last call will lose the odd byte. If there is one, we need
  723. // to read it and possibly forward the second byte....
  724. if (bytesWriteThisPacket & 1) {
  725. fForward = TRUE;
  726. // Read the LOW order byte.
  727. EPRO_RD_PORT_USHORT(adapter, I82595_MEM_IO_REG, (USHORT *)(&tempCopy));
  728. ((UCHAR *)curDestBufAddr)[bytesWriteThisPacket-1] = tempCopy[0];
  729. }
  730. NdisGetNextBuffer(curDestBuf, &curDestBuf);
  731. if (curDestBuf != NULL) {
  732. NdisQueryBuffer(curDestBuf, &curDestBufAddr, &curDestBufLen);
  733. }
  734. }
  735. EProLogStr(" 3BytesTo:");
  736. EProLogLong(bytesToTransfer);
  737. EProLogStr("BytesTransf:");
  738. EProLogLong(*bytesTransferred);
  739. return(NDIS_STATUS_SUCCESS);
  740. }
  741. #else
  742. NDIS_STATUS EProTransferData(OUT PNDIS_PACKET packet,
  743. OUT PUINT bytesTransferred,
  744. IN NDIS_HANDLE miniportAdapterContext,
  745. IN NDIS_HANDLE miniportReceivedContext,
  746. IN UINT byteOffset,
  747. IN UINT bytesToTransfer)
  748. /*++
  749. Routine Description:
  750. The transferdata handler for the EPro.
  751. Arguments:
  752. packet - The packet to transfer the data into
  753. bytesTransferred - The number of bytes actually copied into packet.
  754. miniportAdapterContext - Reallly a pointer to our EPRO_ADAPTER structure
  755. miniportReceivedContext - This is our EPRO_RCV_CONTEXT, which basically just
  756. has the packet length and pointer to where it lies
  757. in the card's address space.
  758. byteOffset - where in the frame to begin trasferring from
  759. bytesToTransfer - how many bytes to transfer.
  760. Return Value:
  761. NDIS_STATUS_SUCCESS - data transfered OK
  762. NDIS_STATUS_FAILURE - tried to transfer off end of frame
  763. --*/
  764. {
  765. PEPRO_ADAPTER adapter = (PEPRO_ADAPTER)miniportAdapterContext;
  766. // The 82595's on-card RCV memory structure
  767. EPRO_RCV_HEADER header;
  768. // An 802.3 ethernet header.
  769. EPRO_ETH_HEADER ethHeader;
  770. // How many bytes have we copied, how many are left to copy
  771. USHORT byteCount, bytesToCopy;
  772. PEPRO_RCV_CONTEXT pcontext = (PEPRO_RCV_CONTEXT)miniportReceivedContext;
  773. // The current buffer we are copying into.
  774. PNDIS_BUFFER curDestBuf;
  775. // The physical address of the buffer we are currently copying into
  776. PVOID curDestBufAddr;
  777. // The length of that buffer
  778. UINT curDestBufLen;
  779. // Two bytes used when we have to transfer in to odd-length buffers (since
  780. // accesses to the EPro's memory are only by-word.
  781. UCHAR tempCopy[2];
  782. // This is TRUE if we are "forwarding" a single byte from an odd-length transfer
  783. BOOLEAN fForward = FALSE;
  784. // the address to read from on the card
  785. USHORT cardAddress;
  786. // TODO - copy first lookahead size bytes out of lookahead buffer.
  787. *bytesTransferred = 0;
  788. // switch to bank0 for mem io
  789. // EPRO_SWITCH_BANK_0(adapter);
  790. EPRO_ASSERT_BANK_0(adapter);
  791. // Make sure they're not asking for too much.
  792. // if (bytesToTransfer + byteOffset > pcontext->RXFrameSize)
  793. // {
  794. // return(NDIS_STATUS_FAILURE);
  795. // }
  796. // Make sure they're not seeking past the end of the frame
  797. if (byteOffset > pcontext->RXFrameSize)
  798. {
  799. return(NDIS_STATUS_FAILURE);
  800. }
  801. // copy the amount requested, or the entire packet - whichever is smaller
  802. if ((bytesToTransfer + byteOffset) <= pcontext->RXFrameSize)
  803. {
  804. bytesToCopy = bytesToTransfer;
  805. }
  806. else
  807. {
  808. bytesToCopy = (pcontext->RXFrameSize - byteOffset);
  809. }
  810. // set our memory address on the card...
  811. cardAddress = (pcontext->RXCurrentAddress +
  812. sizeof(EPRO_RCV_HEADER) +
  813. sizeof(EPRO_ETH_HEADER) +
  814. byteOffset);
  815. if (cardAddress >= EPRO_RX_UPPER_LIMIT_SHORT)
  816. {
  817. // cardAddress = EPRO_RX_LOWER_LIMIT_SHORT + (cardAddress - EPRO_RX_UPPER_LIMIT_SHORT);
  818. // Go algebraic simplification:
  819. cardAddress -= (EPRO_RX_UPPER_LIMIT_SHORT - EPRO_RX_LOWER_LIMIT_SHORT);
  820. }
  821. // Are we starting of reading from an odd address?
  822. if (cardAddress & 1)
  823. {
  824. // yes; odd offset -- forward a byte in...
  825. fForward = TRUE;
  826. cardAddress--;
  827. }
  828. // Okay, now seek to the right address on the card
  829. EPRO_SET_HOST_ADDR(adapter, cardAddress);
  830. // Are we forwarding a byte in? If so, fetch it now....
  831. if (fForward == TRUE)
  832. {
  833. EPRO_RD_PORT_USHORT(adapter, I82595_MEM_IO_REG, (USHORT *)(&tempCopy));
  834. }
  835. // get the first buffer
  836. NdisQueryPacket(packet, NULL, NULL, &curDestBuf, NULL);
  837. // continue until we either run out of buffers, or out of bytes....
  838. while((bytesToCopy > 0) && (curDestBuf!=NULL))
  839. {
  840. UINT bytesWriteThisPacket;
  841. NdisQueryBuffer(curDestBuf, &curDestBufAddr, &curDestBufLen);
  842. // We either write the entire buffer size bytes or the number of bytes
  843. // remaining to copy - whichever is smaller.
  844. bytesWriteThisPacket =
  845. (bytesToCopy > curDestBufLen) ? curDestBufLen : bytesToCopy;
  846. // Ooh, we're going to transfer some bytes...
  847. *bytesTransferred+=bytesWriteThisPacket;
  848. // Okay. Did we have to forward a byte in? Copy it to the buffer NOW..
  849. if (fForward == TRUE)
  850. {
  851. *(UCHAR *)curDestBufAddr = tempCopy[1];
  852. fForward = FALSE;
  853. ((UCHAR *)curDestBufAddr)++;
  854. bytesWriteThisPacket--;
  855. }
  856. // Copy the bulk of the data...
  857. #ifndef EPRO_USE_32_BIT_IO
  858. EPRO_READ_BUFFER_FROM_NIC_USHORT(adapter, curDestBufAddr, bytesWriteThisPacket>>1);
  859. #else
  860. if (adapter->EProUse32BitIO)
  861. {
  862. if (bytesWriteThisPacket & 2)
  863. {
  864. EPRO_RD_PORT_USHORT(
  865. adapter,
  866. I82595_MEM_IO_REG,
  867. (UNALIGNED USHORT *)curDestBufAddr);
  868. EPRO_READ_BUFFER_FROM_NIC_ULONG(
  869. adapter,
  870. ((UCHAR *)curDestBufAddr +2),
  871. bytesWriteThisPacket >> 2);
  872. }
  873. else
  874. {
  875. EPRO_READ_BUFFER_FROM_NIC_ULONG(
  876. adapter,
  877. curDestBufAddr,
  878. bytesWriteThisPacket >> 2);
  879. }
  880. }
  881. else
  882. {
  883. EPRO_READ_BUFFER_FROM_NIC_USHORT(
  884. adapter,
  885. curDestBufAddr,
  886. bytesWriteThisPacket >> 1);
  887. }
  888. #endif
  889. // Okay, the rshift in the last call will lose the odd byte. If there is one, we need
  890. // to read it and possibly forward the second byte....
  891. if (bytesWriteThisPacket & 1)
  892. {
  893. fForward = TRUE;
  894. // Read the LOW order byte.
  895. EPRO_RD_PORT_USHORT(
  896. adapter,
  897. I82595_MEM_IO_REG,
  898. (USHORT *)(&tempCopy));
  899. ((UCHAR *)curDestBufAddr)[bytesWriteThisPacket-1] = tempCopy[0];
  900. }
  901. NdisGetNextBuffer(curDestBuf, &curDestBuf);
  902. bytesToCopy -= curDestBufLen;
  903. }
  904. return(NDIS_STATUS_SUCCESS);
  905. }
  906. #endif
  907. BOOLEAN EProSyncCopyBufferToNicUlong(PVOID context)
  908. {
  909. UCHAR result;
  910. PEPRO_ADAPTER adapter = ((PEPRO_COPYBUF_CONTEXT)context)->Adapter;
  911. // PVOID buffer = ((PEPRO_COPYBUF_CONTEXT)context)->Buffer;
  912. // UINT len = ((PEPRO_COPYBUF_CONTEXT)context)->Len;
  913. EPRO_RD_PORT_UCHAR(adapter, I82595_32IOSEL_REG, &result);
  914. // result |= I82595_32IOSEL;
  915. EPRO_WR_PORT_UCHAR(adapter, I82595_32IOSEL_REG, (result | I82595_32IOSEL));
  916. NdisRawWritePortBufferUlong(adapter->IoPAddr + I82595_32MEM_IO_REG,
  917. ((PEPRO_COPYBUF_CONTEXT)context)->Buffer,
  918. ((PEPRO_COPYBUF_CONTEXT)context)->Len);
  919. // result &= ~I82595_32IOSEL;
  920. EPRO_WR_PORT_UCHAR(adapter, I82595_32IOSEL_REG, result);
  921. return(TRUE);
  922. }
  923. BOOLEAN EProSyncReadBufferFromNicUlong(PVOID context)
  924. {
  925. UCHAR result;
  926. PEPRO_ADAPTER adapter = ((PEPRO_COPYBUF_CONTEXT)context)->Adapter;
  927. // PVOID buffer = ((PEPRO_COPYBUF_CONTEXT)context)->Buffer;
  928. // UINT len = ((PEPRO_COPYBUF_CONTEXT)context)->Len;
  929. EPRO_RD_PORT_UCHAR(adapter, I82595_32IOSEL_REG, &result);
  930. // result |= I82595_32IOSEL;
  931. EPRO_WR_PORT_UCHAR(adapter, I82595_32IOSEL_REG, (result | I82595_32IOSEL));
  932. NdisRawReadPortBufferUlong(adapter->IoPAddr + I82595_32MEM_IO_REG,
  933. ((PEPRO_COPYBUF_CONTEXT)context)->Buffer,
  934. ((PEPRO_COPYBUF_CONTEXT)context)->Len);
  935. // result &= ~I82595_32IOSEL;
  936. EPRO_WR_PORT_UCHAR(adapter, I82595_32IOSEL_REG, result);
  937. return(TRUE);
  938. }