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.

2780 lines
58 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. card.c
  5. Abstract:
  6. Card-specific functions for the NDIS 3.0 Etherlink II driver.
  7. Author:
  8. Adam Barr (adamba) 30-Jul-1990
  9. Environment:
  10. Kernel mode, FSD
  11. Revision History:
  12. Adam Barr (adamba) 28-Aug-1990
  13. - moved the SyncXXX() functions to sync.c
  14. --*/
  15. #include <ndis.h>
  16. #include <efilter.h>
  17. #include "elnkhrd.h"
  18. #include "elnksft.h"
  19. //
  20. // The amount of data to transfer in one programmed I/O burst
  21. // (should be 8 or 16).
  22. //
  23. #define DMA_BURST_SIZE 16
  24. #if DBG
  25. UCHAR PrevBurstSize = 0;
  26. UCHAR PrevPrevBurstSize = 0;
  27. #endif
  28. //
  29. // Array to hold multicast address list.
  30. //
  31. CHAR Addresses[DEFAULT_MULTICASTLISTMAX][ETH_LENGTH_OF_ADDRESS] = {0};
  32. #pragma NDIS_INIT_FUNCTION(CardGetMemBaseAddr)
  33. PUCHAR
  34. CardGetMemBaseAddr(
  35. IN PELNKII_ADAPTER AdaptP,
  36. OUT PBOOLEAN CardPresent,
  37. OUT PBOOLEAN IoBaseCorrect
  38. )
  39. /*++
  40. Routine Description:
  41. Checks that the I/O base address is correct and returns
  42. the memory base address. For cards that are not set up
  43. for memory mapped mode, it will only check the I/O base
  44. address, and return NULL if it is not correct.
  45. Arguments:
  46. AdaptP - pointer to the adapter block.
  47. CardPresent - Returns FALSE if the card does not appear
  48. to be present in the machine.
  49. IoBaseCorrect - Returns TRUE if the jumper matches the
  50. configured I/O base address.
  51. Return Value:
  52. The memory base address for memory mapped systems.
  53. --*/
  54. {
  55. static PVOID IoBases[] = { (PVOID)0x2e0, (PVOID)0x2a0,
  56. (PVOID)0x280, (PVOID)0x250,
  57. (PVOID)0x350, (PVOID)0x330,
  58. (PVOID)0x310, (PVOID)0x300 };
  59. static PVOID MemBases[] = { (PVOID)0xc8000, (PVOID)0xcc000,
  60. (PVOID)0xd8000, (PVOID)0xdc000 };
  61. UCHAR BaseConfig, Tmp, MemConfig;
  62. //
  63. // Read in the Base Configuration Register.
  64. //
  65. NdisRawReadPortUchar(AdaptP->MappedGaBaseAddr+GA_IO_BASE, &Tmp);
  66. //
  67. // Make sure that only one bit in Tmp is on.
  68. //
  69. if ((Tmp != 0) && ((Tmp & (Tmp-1)) == 0)) {
  70. *CardPresent = TRUE;
  71. } else {
  72. *CardPresent = FALSE;
  73. return NULL;
  74. }
  75. //
  76. // Make sure the correct bit is on for AdaptP->IoBaseAddr.
  77. //
  78. BaseConfig = 0;
  79. while (!(Tmp & 1)) {
  80. Tmp >>= 1;
  81. ++BaseConfig;
  82. if (BaseConfig == 8) {
  83. return NULL;
  84. }
  85. }
  86. if (IoBases[BaseConfig] != AdaptP->IoBaseAddr) {
  87. //
  88. // Probably the jumper is wrong.
  89. //
  90. *IoBaseCorrect = FALSE;
  91. return NULL;
  92. } else {
  93. *IoBaseCorrect = TRUE;
  94. }
  95. //
  96. // For non-memory-mapped cards, there is nothing else to check.
  97. //
  98. if (!AdaptP->MemMapped) {
  99. return NULL;
  100. }
  101. //
  102. // Now read in the PROM configuration register.
  103. //
  104. NdisRawReadPortUchar(AdaptP->MappedGaBaseAddr+GA_MEM_BASE, &Tmp);
  105. //
  106. // See which bit is on, minus 4.
  107. //
  108. MemConfig = 0;
  109. while (!(Tmp & 0x10)) {
  110. Tmp >>= 1;
  111. ++MemConfig;
  112. if (MemConfig == 4) {
  113. return NULL;
  114. }
  115. }
  116. //
  117. // Based on the bit, look up MemBaseAddr in the table.
  118. //
  119. AdaptP->MemMapped = TRUE;
  120. return MemBases[MemConfig];
  121. }
  122. #pragma NDIS_INIT_FUNCTION(CardReadEthernetAddress)
  123. VOID
  124. CardReadEthernetAddress(
  125. IN PELNKII_ADAPTER AdaptP
  126. )
  127. /*++
  128. Routine Description:
  129. Reads in the Ethernet address from the Etherlink II PROM.
  130. Arguments:
  131. AdaptP - pointer to the adapter block.
  132. Return Value:
  133. The address is stored in AdaptP->PermanentAddress, and StationAddress if it
  134. is currently zero.
  135. --*/
  136. {
  137. UINT i;
  138. //
  139. // Window the PROM into the NIC ports.
  140. //
  141. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_CONTROL, CTRL_PROM_SEL | CTRL_BNC);
  142. //
  143. // Read in the station address.
  144. //
  145. for (i=0; i<ETH_LENGTH_OF_ADDRESS; i++) {
  146. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+i, &AdaptP->PermanentAddress[i]);
  147. }
  148. IF_LOUD( DbgPrint(" [ %x-%x-%x-%x-%x-%x ]\n",
  149. AdaptP->PermanentAddress[0],
  150. AdaptP->PermanentAddress[1],
  151. AdaptP->PermanentAddress[2],
  152. AdaptP->PermanentAddress[3],
  153. AdaptP->PermanentAddress[4],
  154. AdaptP->PermanentAddress[5]);)
  155. //
  156. // Window the NIC registers into the NIC ports.
  157. //
  158. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_CONTROL, CTRL_GA_SEL | CTRL_BNC);
  159. if ((AdaptP->StationAddress[0] == 0x00) &&
  160. (AdaptP->StationAddress[1] == 0x00) &&
  161. (AdaptP->StationAddress[2] == 0x00) &&
  162. (AdaptP->StationAddress[3] == 0x00) &&
  163. (AdaptP->StationAddress[4] == 0x00) &&
  164. (AdaptP->StationAddress[5] == 0x00)) {
  165. AdaptP->StationAddress[0] = AdaptP->PermanentAddress[0];
  166. AdaptP->StationAddress[1] = AdaptP->PermanentAddress[1];
  167. AdaptP->StationAddress[2] = AdaptP->PermanentAddress[2];
  168. AdaptP->StationAddress[3] = AdaptP->PermanentAddress[3];
  169. AdaptP->StationAddress[4] = AdaptP->PermanentAddress[4];
  170. AdaptP->StationAddress[5] = AdaptP->PermanentAddress[5];
  171. }
  172. }
  173. BOOLEAN
  174. CardSetup(
  175. IN PELNKII_ADAPTER AdaptP
  176. )
  177. /*++
  178. Routine Description:
  179. Sets up the card, using the sequence given in the Etherlink II
  180. technical reference.
  181. Arguments:
  182. AdaptP - pointer to the adapter block, which must be initialized.
  183. Return Value:
  184. TRUE if successful.
  185. --*/
  186. {
  187. UINT i;
  188. UINT Filter;
  189. UCHAR IntConfig;
  190. UCHAR Tmp;
  191. //
  192. // First set up the Gate Array.
  193. //
  194. //
  195. // Toggle the reset bit.
  196. //
  197. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_CONTROL, CTRL_RESET | CTRL_BNC);
  198. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_CONTROL, 0x00);
  199. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_CONTROL, CTRL_BNC);
  200. //
  201. // Set up the bits in the Control Register that don't change.
  202. //
  203. AdaptP->GaControlBits = AdaptP->ExternalTransceiver ? CTRL_DIX : CTRL_BNC;
  204. if (DMA_BURST_SIZE == 16) {
  205. AdaptP->GaControlBits |= CTRL_DB_SEL;
  206. }
  207. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_CONTROL, AdaptP->GaControlBits);
  208. //
  209. // Set Page Start and Page Stop to match the NIC registers.
  210. //
  211. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_PAGE_START, AdaptP->NicPageStart);
  212. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_PAGE_STOP, AdaptP->NicPageStop);
  213. //
  214. // Select which interrupt to use.
  215. //
  216. IntConfig = 0x04; // set bit in position 2
  217. IntConfig <<= AdaptP->InterruptNumber; // move it to 4 through 7
  218. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_INT_DMA_CONFIG, IntConfig);
  219. //
  220. // Choose between 8- and 16-byte programmed I/O bursts.
  221. //
  222. if (DMA_BURST_SIZE == 8) {
  223. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_DRQ_TIMER, DQTR_8_BYTE);
  224. } else {
  225. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_DRQ_TIMER, DQTR_16_BYTE);
  226. }
  227. //
  228. // Initialize these to a correct value for an 8K card.
  229. //
  230. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_DMA_ADDR_MSB, 0x20);
  231. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_DMA_ADDR_LSB, 0x00);
  232. //
  233. // Set up the Configuration register.
  234. //
  235. if (AdaptP->MemMapped) {
  236. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_CONFIG,
  237. GACFR_TC_MASK | GACFR_RAM_SEL | GACFR_MEM_BANK1);
  238. } else {
  239. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_CONFIG, GACFR_TC_MASK);
  240. }
  241. //
  242. // Now set up NIC registers.
  243. //
  244. //
  245. // Write to and read from CR to make sure it is there.
  246. //
  247. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND, CR_STOP | CR_NO_DMA | CR_PAGE0);
  248. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND, &Tmp);
  249. if (Tmp != (CR_STOP | CR_NO_DMA | CR_PAGE0)) {
  250. return FALSE;
  251. }
  252. //
  253. // Set up the registers in the correct sequence.
  254. //
  255. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_DATA_CONFIG,
  256. DCR_BYTE_WIDE | DCR_NORMAL | DCR_FIFO_8_BYTE);
  257. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_RMT_COUNT_MSB, 0);
  258. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_RMT_COUNT_LSB, 0);
  259. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_RCV_CONFIG, AdaptP->NicReceiveConfig);
  260. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_CONFIG, TCR_LOOPBACK);
  261. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_BOUNDARY, AdaptP->NicPageStart);
  262. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_PAGE_START, AdaptP->NicPageStart);
  263. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_PAGE_STOP, AdaptP->NicPageStop);
  264. AdaptP->Current = AdaptP->NicPageStart + (UCHAR)1;
  265. AdaptP->NicNextPacket = AdaptP->NicPageStart + (UCHAR)1;
  266. AdaptP->BufferOverflow = FALSE;
  267. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_INTR_STATUS, 0xff); // clear all
  268. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_INTR_MASK, AdaptP->NicInterruptMask);
  269. //
  270. // Move to page 1 to write the station address and
  271. // multicast registers.
  272. //
  273. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  274. CR_STOP | CR_NO_DMA | CR_PAGE1);
  275. for (i=0; i<ETH_LENGTH_OF_ADDRESS; i++) {
  276. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+(NIC_PHYS_ADDR+i),
  277. AdaptP->StationAddress[i]);
  278. }
  279. Filter = ETH_QUERY_FILTER_CLASSES(AdaptP->FilterDB);
  280. for (i=0; i<8; i++) {
  281. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+(NIC_MC_ADDR+i),
  282. (UCHAR)((Filter & NDIS_PACKET_TYPE_ALL_MULTICAST)
  283. ? 0xff : AdaptP->NicMulticastRegs[i]));
  284. }
  285. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_CURRENT, AdaptP->Current);
  286. //
  287. // move back to page 0 and start the card...
  288. //
  289. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  290. CR_STOP | CR_NO_DMA | CR_PAGE0);
  291. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  292. CR_START | CR_NO_DMA | CR_PAGE0);
  293. //
  294. // ... but it is still in loopback mode.
  295. //
  296. return TRUE;
  297. }
  298. VOID
  299. CardStop(
  300. IN PELNKII_ADAPTER AdaptP
  301. )
  302. /*++
  303. Routine Description:
  304. Stops the card.
  305. Arguments:
  306. AdaptP - pointer to the adapter block
  307. Return Value:
  308. None.
  309. --*/
  310. {
  311. UINT i;
  312. UCHAR Tmp;
  313. //
  314. // Turn on the STOP bit in the Command register.
  315. //
  316. NdisSynchronizeWithInterrupt(
  317. &(AdaptP)->NdisInterrupt,
  318. (PVOID)SyncCardStop,
  319. (PVOID)AdaptP
  320. );
  321. //
  322. // Clear the Remote Byte Count register so that ISR_RESET
  323. // will come on.
  324. //
  325. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_RMT_COUNT_MSB, 0);
  326. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_RMT_COUNT_LSB, 0);
  327. //
  328. // Wait for ISR_RESET, but only for 1.6 milliseconds (as
  329. // described in the March 1991 8390 addendum), since that
  330. // is the maximum time for a software reset to occur.
  331. //
  332. //
  333. for (i=0; i<4; i++) {
  334. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+NIC_INTR_STATUS, &Tmp);
  335. if (Tmp & ISR_RESET) {
  336. break;
  337. }
  338. NdisStallExecution(500);
  339. }
  340. if (i == 4) {
  341. IF_LOUD( DbgPrint("RESET\n");)
  342. IF_LOG( ElnkiiLog('R');)
  343. }
  344. //
  345. // Put the card in loopback mode, then start it.
  346. //
  347. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_CONFIG, TCR_LOOPBACK);
  348. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND, CR_START | CR_NO_DMA);
  349. //
  350. // At this point the card is still in loopback mode.
  351. //
  352. }
  353. VOID DelayComplete(
  354. IN PVOID SystemSpecific1,
  355. IN PVOID TimerExpired,
  356. IN PVOID SystemSpecific2,
  357. IN PVOID SystemSpecific3
  358. )
  359. {
  360. UNREFERENCED_PARAMETER(SystemSpecific1);
  361. UNREFERENCED_PARAMETER(SystemSpecific2);
  362. UNREFERENCED_PARAMETER(SystemSpecific3);
  363. *((BOOLEAN *)TimerExpired)=TRUE;
  364. }
  365. #pragma NDIS_INIT_FUNCTION(CardTest)
  366. BOOLEAN
  367. CardTest(
  368. IN PELNKII_ADAPTER AdaptP
  369. )
  370. /*++
  371. Routine Description:
  372. Tests the card. Follows the tests described in section 12 of
  373. the 8390 Data Sheet.
  374. Arguments:
  375. AdaptP - pointer to the adapter block, which must be initialized
  376. and set up.
  377. Return Value:
  378. TRUE if everything is OK.
  379. --*/
  380. {
  381. #define TEST_LEN 60
  382. #define MAGIC_NUM 0x92
  383. UINT FirstTest, SecondTest, i;
  384. UCHAR TSRResult, RSRResult;
  385. UCHAR CrcBuf[4];
  386. BOOLEAN FinalResult = TRUE;
  387. UCHAR TestSrcBuf[256], TestDestBuf[256];
  388. PUCHAR CurTestLoc;
  389. UCHAR Tmp;
  390. static NDIS_TIMER Timer = {0};
  391. BOOLEAN TimerExpired=FALSE;
  392. BOOLEAN dummy; //for return from NdisCancelTimer
  393. //
  394. // These arrays are indexed by FirstTest.
  395. //
  396. static UCHAR TCRValues[3] = { TCR_NIC_LBK, TCR_SNI_LBK, TCR_COAX_LBK };
  397. static UCHAR TSRCDHWanted[3] = { TSR_NO_CDH, TSR_NO_CDH, 0x00 };
  398. static UCHAR TSRCRSWanted[3] = { TSR_NO_CARRIER, 0x00, 0x00 };
  399. static UCHAR FIFOWanted[4] = { LSB(TEST_LEN+4), MSB(TEST_LEN+4),
  400. MSB(TEST_LEN+4), MAGIC_NUM };
  401. //
  402. // These arrays are indexed by SecondTest.
  403. //
  404. static BOOLEAN GoodCrc[3] = { TRUE, FALSE, FALSE };
  405. static BOOLEAN GoodAddress[3] = { TRUE, TRUE, FALSE };
  406. static UCHAR RSRWanted[3] = { RSR_PACKET_OK, RSR_CRC_ERROR, RSR_PACKET_OK };
  407. static UCHAR TestPacket[TEST_LEN] = {0}; // a dummy packet.
  408. static UCHAR NullAddress[ETH_LENGTH_OF_ADDRESS] = { 0x00, 0x00, 0x00,
  409. 0x00, 0x00, 0x00 };
  410. //
  411. // First construct TestPacket.
  412. //
  413. ELNKII_MOVE_MEM(TestPacket, AdaptP->StationAddress, ETH_LENGTH_OF_ADDRESS);
  414. ELNKII_MOVE_MEM(TestPacket+ETH_LENGTH_OF_ADDRESS, AdaptP->StationAddress, ETH_LENGTH_OF_ADDRESS);
  415. TestPacket[2*ETH_LENGTH_OF_ADDRESS] = 0x00;
  416. TestPacket[2*ETH_LENGTH_OF_ADDRESS+1] = 0x00;
  417. TestPacket[TEST_LEN-1] = MAGIC_NUM;
  418. //
  419. // Set up the DCR for loopback operation.
  420. //
  421. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_DATA_CONFIG,
  422. DCR_BYTE_WIDE | DCR_LOOPBACK | DCR_FIFO_8_BYTE);
  423. //
  424. // Set the RCR to reject all packets.
  425. //
  426. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_RCV_CONFIG, 0x00);
  427. //
  428. // First round of tests -- different loopback modes
  429. //
  430. for (FirstTest = 0; FirstTest < 2; ++FirstTest) {
  431. //
  432. // Stop the card.
  433. //
  434. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  435. CR_STOP | CR_NO_DMA | CR_PAGE0);
  436. //
  437. // Set up the TCR for the appropriate loopback mode.
  438. //
  439. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_CONFIG, 0x00);
  440. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_CONFIG, TCRValues[FirstTest]);
  441. //
  442. // Restart the card.
  443. //
  444. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  445. CR_START | CR_NO_DMA | CR_PAGE0);
  446. //
  447. // Now copy down TestPacket and start the transmission.
  448. //
  449. CardCopyDownBuffer(AdaptP, TestPacket, 0, 0, TEST_LEN);
  450. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_START, AdaptP->NicXmitStart);
  451. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_COUNT_MSB, MSB(TEST_LEN));
  452. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_COUNT_LSB, LSB(TEST_LEN));
  453. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  454. CR_START | CR_XMIT | CR_NO_DMA);
  455. //
  456. // Wait for the transmission to complete, for about a second.
  457. //
  458. {
  459. UINT i;
  460. i=0;
  461. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+NIC_INTR_STATUS, &Tmp);
  462. while (!(Tmp & (ISR_XMIT | ISR_XMIT_ERR))) {
  463. if (++i > 100) {
  464. IF_TEST( DbgPrint("F%d: TEST reset timed out\n", FirstTest);)
  465. FinalResult = FALSE;
  466. goto FinishTest;
  467. }
  468. NdisStallExecution(11000);
  469. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+NIC_INTR_STATUS, &Tmp);
  470. }
  471. }
  472. //
  473. // WAIT FOR CHIP TO STABILIZE
  474. // Write to and read from CR to make sure it is there.
  475. // Bug#4267 - WFW
  476. //
  477. {
  478. UINT i;
  479. for (i = 0; i < 2000; ++i) {
  480. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND, CR_STOP | CR_NO_DMA | CR_PAGE0);
  481. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND, &Tmp);
  482. if (Tmp != (CR_STOP | CR_NO_DMA | CR_PAGE0)) {
  483. NdisStallExecution(1000);
  484. } else {
  485. break;
  486. }
  487. }
  488. }
  489. //
  490. // Acknowledge the interrupt.
  491. //
  492. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_INTR_STATUS,
  493. ISR_XMIT | ISR_XMIT_ERR);
  494. //
  495. // Check that the CRS and CDH bits are set correctly.
  496. //
  497. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_STATUS, &TSRResult);
  498. if ((TSRResult & TSR_NO_CARRIER) != TSRCRSWanted[FirstTest]) {
  499. IF_TEST(DbgPrint("F%d: Incorrect CRS value: %x\n", FirstTest, TSRResult);)
  500. FinalResult = FALSE;
  501. goto FinishTest;
  502. }
  503. if ((TSRResult & TSR_NO_CDH) != TSRCDHWanted[FirstTest]) {
  504. //
  505. // the spec says CDH won't go on for TCR_COAX_LBK, but it does
  506. //
  507. if (TCRValues[FirstTest] != TCR_COAX_LBK) {
  508. IF_TEST( DbgPrint("F%d: Incorrect CDH value: %x\n", FirstTest,TSRResult);)
  509. FinalResult = FALSE;
  510. goto FinishTest;
  511. }
  512. }
  513. //
  514. // For the Loopback to Coax test the RSR and FIFO
  515. // can't be trusted, so skip them.
  516. //
  517. if (TCRValues[FirstTest] == TCR_COAX_LBK) {
  518. continue;
  519. }
  520. //
  521. // Check that the CRC error happened (it should).
  522. //
  523. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+NIC_RCV_STATUS, &RSRResult);
  524. if (!(RSRResult & RSR_CRC_ERROR)) {
  525. IF_TEST( DbgPrint("F%d: No CRC error: %x\n", FirstTest, RSRResult);)
  526. FinalResult = FALSE;
  527. goto FinishTest;
  528. }
  529. //
  530. // Check that the right values are in the FIFO.
  531. //
  532. for (i=0; i<4; i++) {
  533. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+NIC_FIFO, &Tmp);
  534. if (Tmp != FIFOWanted[i]) {
  535. IF_TEST( DbgPrint("F%d: Bad FIFO value: %d\n", FirstTest, i);)
  536. FinalResult = FALSE;
  537. goto FinishTest;
  538. }
  539. }
  540. //
  541. // Flush the rest of the FIFO.
  542. //
  543. for (i=0; i<4; i++) {
  544. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+NIC_FIFO, &Tmp);
  545. }
  546. }
  547. //
  548. // Stop the card.
  549. //
  550. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  551. CR_STOP | CR_NO_DMA | CR_PAGE0);
  552. //
  553. // Set the TCR for internal loopback.
  554. //
  555. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_CONFIG, 0x00);
  556. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_CONFIG,
  557. TCR_INHIBIT_CRC | TCR_NIC_LBK);
  558. //
  559. // Restart the card.
  560. //
  561. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  562. CR_START | CR_NO_DMA | CR_PAGE0);
  563. //
  564. // Second round of tests -- CRC and Address recognition logic
  565. //
  566. for (SecondTest = 0; SecondTest < 3; ++SecondTest) {
  567. //
  568. // See if the destination address should be valid.
  569. //
  570. if (GoodAddress[SecondTest]) {
  571. ELNKII_MOVE_MEM(TestPacket, AdaptP->StationAddress, ETH_LENGTH_OF_ADDRESS);
  572. } else {
  573. ELNKII_MOVE_MEM(TestPacket, NullAddress, ETH_LENGTH_OF_ADDRESS);
  574. }
  575. //
  576. // Copy down TestPacket.
  577. //
  578. CardCopyDownBuffer(AdaptP, TestPacket, 0, 0, TEST_LEN);
  579. //
  580. // Copy down a good or bad CRC, as needed.
  581. //
  582. CardGetPacketCrc(TestPacket, TEST_LEN, CrcBuf);
  583. if (!GoodCrc[SecondTest]) {
  584. CrcBuf[0] = (UCHAR)(CrcBuf[0] ^ 0xff); // intentionally make it bad
  585. }
  586. CardCopyDownBuffer(AdaptP, CrcBuf, 0, TEST_LEN, 4);
  587. //
  588. // Start the transmission.
  589. //
  590. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_START, AdaptP->NicXmitStart);
  591. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_COUNT_MSB, MSB(TEST_LEN+4));
  592. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_COUNT_LSB, LSB(TEST_LEN+4));
  593. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  594. CR_START | CR_XMIT | CR_NO_DMA);
  595. //
  596. // Wait for the transmission to complete, for about a second.
  597. //
  598. TimerExpired=FALSE;
  599. NdisInitializeTimer(&Timer, DelayComplete, &TimerExpired);
  600. NdisSetTimer(&Timer, 1000);
  601. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+NIC_INTR_STATUS, &Tmp);
  602. while (!(Tmp & (ISR_XMIT | ISR_XMIT_ERR))) {
  603. if (TimerExpired) {
  604. IF_TEST( DbgPrint("F%d: TEST reset timed out\n", FirstTest);)
  605. FinalResult = FALSE;
  606. goto FinishTest;
  607. }
  608. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+NIC_INTR_STATUS, &Tmp);
  609. }
  610. //
  611. //MUST Cancel the unexpired timer
  612. //
  613. NdisCancelTimer(&Timer,&dummy);
  614. //
  615. // Acknowledge the interrupt.
  616. //
  617. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_INTR_STATUS,
  618. ISR_XMIT | ISR_XMIT_ERR);
  619. //
  620. // Check that RSR is as expected.
  621. //
  622. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+NIC_RCV_STATUS, &RSRResult);
  623. if ((UCHAR)(RSRResult & (RSR_PACKET_OK | RSR_CRC_ERROR)) !=
  624. RSRWanted[SecondTest]) {
  625. IF_TEST( DbgPrint("S%d: Bad RSR: wanted %x got %x\n", SecondTest,
  626. RSRWanted[SecondTest], RSRResult);)
  627. FinalResult = FALSE;
  628. goto FinishTest;
  629. }
  630. }
  631. //
  632. // Third round of tests - copying data to and from the card.
  633. //
  634. //
  635. // First put data in the buffer.
  636. //
  637. for (i=0; i<256; i++) {
  638. TestSrcBuf[i] = (UCHAR)(256-i);
  639. }
  640. //
  641. // Loop through all the card memory in 256-byte pieces.
  642. //
  643. for (CurTestLoc = 0; CurTestLoc < (PUCHAR)0x2000; CurTestLoc += 256) {
  644. //
  645. // Copy the data down (have to play around with buffer
  646. // numbers and offsets to put it in the right place).
  647. //
  648. CardCopyDownBuffer(AdaptP, TestSrcBuf,
  649. (XMIT_BUF)((ULONG)CurTestLoc / TX_BUF_SIZE),
  650. (ULONG)CurTestLoc % TX_BUF_SIZE, 256);
  651. //
  652. // Clear the destination buffer and read it back.
  653. //
  654. for (i=0; i<256; i++) {
  655. TestDestBuf[i] = 77;
  656. }
  657. CardCopyUp(AdaptP, TestDestBuf,
  658. AdaptP->XmitStart + (ULONG)CurTestLoc, 256);
  659. //
  660. // Make sure that the data matches.
  661. //
  662. for (i=0; i<256; i++) {
  663. if (TestSrcBuf[i] != TestDestBuf[i]) {
  664. IF_TEST( DbgPrint("T: Bad data at %lx\n", (ULONG)(CurTestLoc+i));)
  665. FinalResult = FALSE;
  666. goto FinishTest;
  667. }
  668. }
  669. }
  670. //
  671. // FinishTest: jump here to exit the tests cleanly.
  672. //
  673. FinishTest:
  674. //
  675. // Stop the card.
  676. //
  677. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  678. CR_STOP | CR_NO_DMA | CR_PAGE0);
  679. //
  680. // Restore DCR, RCR, and TCR.
  681. //
  682. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_DATA_CONFIG,
  683. DCR_BYTE_WIDE | DCR_NORMAL | DCR_FIFO_8_BYTE);
  684. //
  685. // (clear these two to be safe)
  686. //
  687. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_RMT_COUNT_MSB, 0);
  688. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_RMT_COUNT_LSB, 0);
  689. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_RCV_CONFIG, AdaptP->NicReceiveConfig);
  690. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_CONFIG, TCR_LOOPBACK);
  691. //
  692. // The reconfiguring of the config registers can cause the xmit to complete
  693. // if the test was a failure. Therefore, we pause here to allow the xmit
  694. // to complete so that we can ACK it below - leaving the card in a valid state.
  695. //
  696. NdisStallExecution(50000);
  697. //
  698. // Acknowledge any interrupts that are floating around.
  699. //
  700. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_INTR_STATUS, 0xff);
  701. //
  702. // Start the card, but stay in loopback mode.
  703. //
  704. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  705. CR_START | CR_NO_DMA | CR_PAGE0);
  706. return FinalResult;
  707. }
  708. BOOLEAN
  709. CardReset(
  710. IN PELNKII_ADAPTER AdaptP
  711. )
  712. /*++
  713. Routine Description:
  714. Resets the card.
  715. Arguments:
  716. AdaptP - pointer to the adapter block
  717. Return Value:
  718. TRUE if everything is OK.
  719. --*/
  720. {
  721. CardStop(AdaptP);
  722. //
  723. // CardSetup() does a software reset.
  724. //
  725. if (!CardSetup(AdaptP)) {
  726. NdisWriteErrorLogEntry(
  727. AdaptP->NdisAdapterHandle,
  728. NDIS_ERROR_CODE_HARDWARE_FAILURE,
  729. 2,
  730. cardReset,
  731. ELNKII_ERRMSG_CARD_SETUP
  732. );
  733. return FALSE;
  734. }
  735. CardStart(AdaptP);
  736. return TRUE;
  737. }
  738. BOOLEAN
  739. CardCopyDownPacket(
  740. IN PELNKII_ADAPTER AdaptP,
  741. IN PNDIS_PACKET Packet,
  742. IN XMIT_BUF XmitBufferNum,
  743. OUT UINT * Length
  744. )
  745. /*++
  746. Routine Description:
  747. Copies the packet Packet down starting at the beginning of
  748. transmit buffer XmitBufferNum, fills in Length to be the
  749. length of the packet. It uses memory mapping or programmed
  750. I/O as appropriate.
  751. Arguments:
  752. AdaptP - pointer to the adapter block
  753. Packet - the packet to copy down
  754. XmitBufferNum - the transmit buffer number
  755. Return Value:
  756. Length - the length of the data in the packet in bytes.
  757. TRUE if the transfer completed with no problems.
  758. --*/
  759. {
  760. PUCHAR CurAddress, BufAddress;
  761. UINT CurLength, Len;
  762. PNDIS_BUFFER CurBuffer;
  763. UINT TmpLen, BurstSize;
  764. UCHAR GaStatus;
  765. if (AdaptP->MemMapped) {
  766. //
  767. // Memory mapped, just copy each buffer over.
  768. //
  769. NdisQueryPacket(Packet, NULL, NULL, &CurBuffer, NULL);
  770. CurAddress = AdaptP->XmitStart + XmitBufferNum*TX_BUF_SIZE;
  771. CurLength = 0;
  772. while (CurBuffer) {
  773. NdisQueryBuffer(CurBuffer, (PVOID *)&BufAddress, &Len);
  774. ELNKII_MOVE_MEM_TO_SHARED_RAM(CurAddress, BufAddress, Len);
  775. CurAddress += Len;
  776. CurLength += Len;
  777. NdisGetNextBuffer(CurBuffer, &CurBuffer);
  778. }
  779. *Length = CurLength;
  780. } else {
  781. //
  782. // Programmed I/O, have to transfer the data.
  783. //
  784. NdisQueryPacket(Packet, NULL, NULL, &CurBuffer, NULL);
  785. CurAddress = (PUCHAR)0x2000 + XmitBufferNum*TX_BUF_SIZE;
  786. CurLength = 0;
  787. NdisAcquireSpinLock(&AdaptP->Lock);
  788. while (CurBuffer) {
  789. NdisQueryBuffer(CurBuffer, (PVOID *)&BufAddress, &Len);
  790. if (Len == 0) {
  791. NdisGetNextBuffer(CurBuffer, &CurBuffer);
  792. continue;
  793. }
  794. //
  795. // Set up the Gate Array for programmed I/O transfer.
  796. //
  797. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_DMA_ADDR_MSB,
  798. MSB((ULONG)CurAddress));
  799. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_DMA_ADDR_LSB,
  800. LSB((ULONG)CurAddress));
  801. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_CONTROL,
  802. (UCHAR)((CTRL_START | CTRL_DIR_DOWN) | AdaptP->GaControlBits));
  803. //
  804. // First transfer multiples of DMA_BURST_SIZE.
  805. //
  806. TmpLen = Len;
  807. BurstSize = DMA_BURST_SIZE;
  808. while (TmpLen >= BurstSize) {
  809. if ((ULONG)BufAddress & 0x01) {
  810. NdisRawWritePortBufferUchar(
  811. AdaptP->MappedGaBaseAddr+GA_REG_FILE_MSB,
  812. (PUCHAR)BufAddress,
  813. BurstSize
  814. );
  815. } else {
  816. NdisRawWritePortBufferUshort(
  817. AdaptP->MappedGaBaseAddr+GA_REG_FILE_MSB,
  818. (PUSHORT)BufAddress,
  819. BurstSize/2
  820. );
  821. }
  822. TmpLen -= BurstSize;
  823. BufAddress += BurstSize;
  824. //
  825. // Wait for the Gate Array FIFO to be ready.
  826. //
  827. do {
  828. NdisRawReadPortUchar(AdaptP->MappedGaBaseAddr+GA_STATUS, &GaStatus);
  829. if (GaStatus & (STREG_UNDERFLOW | STREG_OVERFLOW)) {
  830. #if DBG
  831. DbgPrint("DATA PORT READY ERROR IN ELNKII - CCDP\n");
  832. DbgPrint("\tStatus = 0x%x, BurstSize = 0x%x, PrevBurstSize = 0x%x\n",
  833. GaStatus, BurstSize, PrevBurstSize);
  834. #endif
  835. NdisWriteErrorLogEntry(
  836. AdaptP->NdisAdapterHandle,
  837. NDIS_ERROR_CODE_DRIVER_FAILURE,
  838. 2,
  839. cardCopyDownPacket,
  840. ELNKII_ERRMSG_DATA_PORT_READY
  841. );
  842. NdisReleaseSpinLock(&AdaptP->Lock);
  843. return FALSE;
  844. }
  845. } while (!(GaStatus & STREG_DP_READY));
  846. #if DBG
  847. PrevBurstSize = (UCHAR)BurstSize;
  848. #endif
  849. }
  850. //
  851. // Now copy the last bit as UCHARs.
  852. //
  853. NdisRawWritePortBufferUchar(
  854. AdaptP->MappedGaBaseAddr+GA_REG_FILE_MSB,
  855. BufAddress, TmpLen);
  856. do {
  857. NdisRawReadPortUchar(AdaptP->MappedGaBaseAddr+GA_STATUS, &GaStatus);
  858. if (GaStatus & (STREG_UNDERFLOW | STREG_OVERFLOW)) {
  859. #if DBG
  860. DbgPrint("DATA PORT READY ERROR IN ELNKII - CCDPII\n");
  861. DbgPrint("\tStatus = 0x%x, BurstSize = 0x%x, PrevBurstSize = 0x%x\n",
  862. GaStatus, BurstSize, PrevBurstSize);
  863. #endif
  864. NdisWriteErrorLogEntry(
  865. AdaptP->NdisAdapterHandle,
  866. NDIS_ERROR_CODE_DRIVER_FAILURE,
  867. 2,
  868. cardCopyDownPacket,
  869. ELNKII_ERRMSG_DATA_PORT_READY
  870. );
  871. NdisReleaseSpinLock(&AdaptP->Lock);
  872. return FALSE;
  873. }
  874. } while (!(GaStatus & STREG_DP_READY));
  875. #if DBG
  876. PrevBurstSize = (UCHAR)TmpLen;
  877. #endif
  878. //
  879. // Done, turn off the start bit...
  880. //
  881. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_CONTROL,
  882. (UCHAR)(CTRL_STOP | AdaptP->GaControlBits));
  883. //
  884. // ... and wait for DMA_IN_PROGRESS to go off,
  885. // indicating end of flush.
  886. //
  887. do {
  888. NdisRawReadPortUchar(AdaptP->MappedGaBaseAddr+GA_STATUS, &GaStatus);
  889. } while (GaStatus & STREG_IN_PROG);
  890. CurAddress += Len;
  891. CurLength += Len;
  892. NdisGetNextBuffer(CurBuffer, &CurBuffer);
  893. }
  894. NdisReleaseSpinLock(&AdaptP->Lock);
  895. *Length = CurLength;
  896. }
  897. return TRUE;
  898. }
  899. BOOLEAN
  900. CardCopyDownBuffer(
  901. IN PELNKII_ADAPTER AdaptP,
  902. IN PUCHAR SourceBuffer,
  903. IN XMIT_BUF XmitBufferNum,
  904. IN UINT Offset,
  905. IN UINT Length
  906. )
  907. /*++
  908. Routine Description:
  909. Copies down one character buffer (rather than an
  910. entire packet), starting at offset Offset, for Length
  911. bytes. It uses memory mapping or programmed I/O as
  912. appropriate. This function is used for blanking the padding
  913. at the end of short packets and also for loopback testing.
  914. Arguments:
  915. AdaptP - pointer to the adapter block
  916. SourceBuffer - the source data to be copied down
  917. XmitBufferNum - the transmit buffer number
  918. Offset - the offset from the start of the transmit buffer
  919. Length - the number of bytes to blank out
  920. Return Value:
  921. Length - the length of the data in the packet in bytes.
  922. TRUE if the transfer completed with no problems.
  923. --*/
  924. {
  925. PUCHAR CurAddress;
  926. UINT TmpLen, ThisTime;
  927. UCHAR GaStatus;
  928. if (AdaptP->MemMapped) {
  929. //
  930. // Memory mapped, just copy over SourceBuffer.
  931. //
  932. CurAddress = AdaptP->XmitStart + XmitBufferNum*TX_BUF_SIZE + Offset;
  933. ELNKII_MOVE_MEM_TO_SHARED_RAM(CurAddress, SourceBuffer, Length);
  934. } else {
  935. //
  936. // Programmed I/O, have to transfer the data.
  937. //
  938. CurAddress = (PUCHAR)0x2000 + XmitBufferNum*TX_BUF_SIZE + Offset;
  939. //
  940. // Set up the Gate Array for programmed I/O transfer.
  941. //
  942. NdisAcquireSpinLock(&AdaptP->Lock);
  943. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_DMA_ADDR_MSB,
  944. MSB((ULONG)CurAddress));
  945. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_DMA_ADDR_LSB,
  946. LSB((ULONG)CurAddress));
  947. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_CONTROL,
  948. (UCHAR)((CTRL_START | CTRL_DIR_DOWN) | AdaptP->GaControlBits));
  949. //
  950. // Copy the data down in DMA_BURST_SIZE bursts.
  951. //
  952. TmpLen = Length;
  953. while (TmpLen > 0) {
  954. ThisTime = (TmpLen >= DMA_BURST_SIZE) ? DMA_BURST_SIZE : TmpLen;
  955. NdisRawWritePortBufferUchar(
  956. AdaptP->MappedGaBaseAddr+GA_REG_FILE_MSB,
  957. SourceBuffer, ThisTime);
  958. TmpLen -= ThisTime;
  959. SourceBuffer += ThisTime;
  960. //
  961. // Wait for the Gate Array FIFO to be ready.
  962. //
  963. do {
  964. NdisRawReadPortUchar(AdaptP->MappedGaBaseAddr+GA_STATUS, &GaStatus);
  965. if (GaStatus & (STREG_UNDERFLOW | STREG_OVERFLOW)) {
  966. #if DBG
  967. DbgPrint("DATA PORT READY ERROR IN ELNKII - CCDB\n");
  968. DbgPrint("\tStatus = 0x%x, BurstSize = 0x%x, PrevBurstSize = 0x%x\n",
  969. GaStatus, ThisTime, PrevBurstSize);
  970. #endif
  971. NdisWriteErrorLogEntry(
  972. AdaptP->NdisAdapterHandle,
  973. NDIS_ERROR_CODE_DRIVER_FAILURE,
  974. 2,
  975. cardCopyDownBuffer,
  976. ELNKII_ERRMSG_DATA_PORT_READY
  977. );
  978. NdisReleaseSpinLock(&AdaptP->Lock);
  979. return FALSE;
  980. }
  981. } while (!(GaStatus & STREG_DP_READY));
  982. #if DBG
  983. PrevBurstSize = (UCHAR)ThisTime;
  984. #endif
  985. }
  986. //
  987. // Done, turn off the start bit..
  988. //
  989. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_CONTROL,
  990. (UCHAR)(CTRL_STOP | AdaptP->GaControlBits));
  991. //
  992. // ... and wait for DMA_IN_PROGRESS to go off,
  993. // indicating end of flush.
  994. //
  995. do {
  996. NdisRawReadPortUchar(AdaptP->MappedGaBaseAddr+GA_STATUS, &GaStatus);
  997. } while (GaStatus & STREG_IN_PROG);
  998. NdisReleaseSpinLock(&AdaptP->Lock);
  999. }
  1000. #if DBG
  1001. IF_ELNKIIDEBUG( ELNKII_DEBUG_TRACK_PACKET_LENS ) {
  1002. if (Offset == 18 && Length == 42) {
  1003. UINT i;
  1004. for (i=0; i<20; i++) {
  1005. SourceBuffer[i] = ' ';
  1006. }
  1007. }
  1008. }
  1009. #endif
  1010. return TRUE;
  1011. }
  1012. BOOLEAN
  1013. CardCopyUp(
  1014. IN PELNKII_ADAPTER AdaptP,
  1015. IN PUCHAR Target,
  1016. IN PUCHAR Source,
  1017. IN UINT Length
  1018. )
  1019. /*++
  1020. Routine Description:
  1021. Copies data from the card to memory. It uses memory mapping
  1022. or programmed I/O as appropriate.
  1023. Arguments:
  1024. AdaptP - pointer to the adapter block
  1025. Target - the target address
  1026. Source - the source address (on the card)
  1027. Length - the number of bytes to copy
  1028. Return Value:
  1029. TRUE if the transfer completed with no problems.
  1030. --*/
  1031. {
  1032. UINT TmpLen, BurstSize;
  1033. UCHAR GaStatus;
  1034. if (Length == 0) {
  1035. return TRUE;
  1036. }
  1037. if (AdaptP->MemMapped) {
  1038. //
  1039. // Memory mapped, just copy the data over.
  1040. //
  1041. ELNKII_MOVE_SHARED_RAM_TO_MEM(Target, Source, Length);
  1042. } else { // programmed I/O
  1043. //
  1044. // Programmed I/O, have to transfer the data.
  1045. //
  1046. //
  1047. // Adjust the address to be a card address.
  1048. //
  1049. Source -= ((ULONG)AdaptP->XmitStart - 0x2000);
  1050. //
  1051. // Set up the Gate Array for programmed I/O transfer.
  1052. //
  1053. NdisAcquireSpinLock(&AdaptP->Lock);
  1054. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_DMA_ADDR_MSB, MSB((ULONG)Source));
  1055. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_DMA_ADDR_LSB, LSB((ULONG)Source));
  1056. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_CONTROL,
  1057. (UCHAR)((CTRL_START | CTRL_DIR_UP) | AdaptP->GaControlBits));
  1058. //
  1059. // First copy multiples of DMA_BURST_SIZE as USHORTs.
  1060. //
  1061. TmpLen = Length;
  1062. BurstSize = DMA_BURST_SIZE;
  1063. //
  1064. // Before doing this, transfer one byte if needed to
  1065. // align on a USHORT boundary.
  1066. //
  1067. while (TmpLen >= BurstSize) {
  1068. //
  1069. // First wait for the Gate Array FIFO to be ready.
  1070. //
  1071. do {
  1072. NdisRawReadPortUchar(AdaptP->MappedGaBaseAddr+GA_STATUS, &GaStatus);
  1073. if (GaStatus & (STREG_UNDERFLOW | STREG_OVERFLOW)) {
  1074. #if DBG
  1075. DbgPrint("DATA PORT READY ERROR IN ELNKII - CCU\n");
  1076. DbgPrint("\tStatus = 0x%x, BurstSize = 0x%x, PrevBurstSize = 0x%x\n",
  1077. GaStatus, PrevBurstSize, PrevPrevBurstSize);
  1078. #endif
  1079. NdisWriteErrorLogEntry(
  1080. AdaptP->NdisAdapterHandle,
  1081. NDIS_ERROR_CODE_DRIVER_FAILURE,
  1082. 2,
  1083. cardCopyUp,
  1084. ELNKII_ERRMSG_DATA_PORT_READY
  1085. );
  1086. NdisReleaseSpinLock(&AdaptP->Lock);
  1087. return FALSE;
  1088. }
  1089. } while (!(GaStatus & STREG_DP_READY));
  1090. if ((ULONG)Target & 0x01) {
  1091. //
  1092. // This is the first burst, and it starts on
  1093. // an odd boundary.
  1094. //
  1095. NdisRawReadPortBufferUchar(
  1096. AdaptP->MappedGaBaseAddr+GA_REG_FILE_MSB,
  1097. (PUCHAR)Target,
  1098. BurstSize);
  1099. TmpLen -= BurstSize;
  1100. Target += BurstSize;
  1101. #if DBG
  1102. PrevPrevBurstSize = PrevBurstSize;
  1103. PrevBurstSize = (UCHAR)BurstSize;
  1104. #endif
  1105. } else {
  1106. NdisRawReadPortBufferUshort(
  1107. AdaptP->MappedGaBaseAddr+GA_REG_FILE_MSB,
  1108. (PUSHORT)Target, BurstSize/2);
  1109. TmpLen -= BurstSize;
  1110. Target += BurstSize;
  1111. #if DBG
  1112. PrevPrevBurstSize = PrevBurstSize;
  1113. PrevBurstSize = (UCHAR)BurstSize;
  1114. #endif
  1115. }
  1116. }
  1117. //
  1118. // Now copy the last bit of data as UCHARs.
  1119. //
  1120. do {
  1121. NdisRawReadPortUchar(AdaptP->MappedGaBaseAddr+GA_STATUS, &GaStatus);
  1122. if (GaStatus & (STREG_UNDERFLOW | STREG_OVERFLOW)) {
  1123. #if DBG
  1124. DbgPrint("DATA PORT READY ERROR IN ELNKII - CCUII\n");
  1125. DbgPrint("\tStatus = 0x%x, BurstSize = 0x%x, PrevBurstSize = 0x%x\n",
  1126. GaStatus, BurstSize, PrevBurstSize);
  1127. #endif
  1128. NdisWriteErrorLogEntry(
  1129. AdaptP->NdisAdapterHandle,
  1130. NDIS_ERROR_CODE_DRIVER_FAILURE,
  1131. 2,
  1132. cardCopyUp,
  1133. ELNKII_ERRMSG_DATA_PORT_READY
  1134. );
  1135. NdisReleaseSpinLock(&AdaptP->Lock);
  1136. return FALSE;
  1137. }
  1138. } while (!(GaStatus & STREG_DP_READY));
  1139. NdisRawReadPortBufferUchar(
  1140. AdaptP->MappedGaBaseAddr+GA_REG_FILE_MSB,
  1141. Target, TmpLen);
  1142. //
  1143. // Done, turn off the start bit.
  1144. //
  1145. NdisRawWritePortUchar(AdaptP->MappedGaBaseAddr+GA_CONTROL,
  1146. (UCHAR)(CTRL_STOP | AdaptP->GaControlBits));
  1147. NdisReleaseSpinLock(&AdaptP->Lock);
  1148. }
  1149. return TRUE;
  1150. }
  1151. ULONG
  1152. CardComputeCrc(
  1153. IN PUCHAR Buffer,
  1154. IN UINT Length
  1155. )
  1156. /*++
  1157. Routine Description:
  1158. Runs the AUTODIN II CRC algorithm on buffer Buffer of
  1159. length Length.
  1160. Arguments:
  1161. Buffer - the input buffer
  1162. Length - the length of Buffer
  1163. Return Value:
  1164. The 32-bit CRC value.
  1165. Note:
  1166. This is adapted from the comments in the assembly language
  1167. version in _GENREQ.ASM of the DWB NE1000/2000 driver.
  1168. --*/
  1169. {
  1170. ULONG Crc, Carry;
  1171. UINT i, j;
  1172. UCHAR CurByte;
  1173. Crc = 0xffffffff;
  1174. for (i = 0; i < Length; i++) {
  1175. CurByte = Buffer[i];
  1176. for (j = 0; j < 8; j++) {
  1177. Carry = ((Crc & 0x80000000) ? 1 : 0) ^ (CurByte & 0x01);
  1178. Crc <<= 1;
  1179. CurByte >>= 1;
  1180. if (Carry) {
  1181. Crc = (Crc ^ 0x04c11db6) | Carry;
  1182. }
  1183. }
  1184. }
  1185. return Crc;
  1186. }
  1187. #pragma NDIS_INIT_FUNCTION(CardGetPacketCrc)
  1188. VOID
  1189. CardGetPacketCrc(
  1190. IN PUCHAR Buffer,
  1191. IN UINT Length,
  1192. OUT UCHAR Crc[4]
  1193. )
  1194. /*++
  1195. Routine Description:
  1196. For a given Buffer, computes the packet CRC for it.
  1197. It uses CardComputeCrc to determine the CRC value, then
  1198. inverts the order and value of all the bits (I don't
  1199. know why this is necessary).
  1200. Arguments:
  1201. Buffer - the input buffer
  1202. Length - the length of Buffer
  1203. Return Value:
  1204. The CRC will be stored in Crc.
  1205. --*/
  1206. {
  1207. static UCHAR InvertBits[16] = { 0x0, 0x8, 0x4, 0xc,
  1208. 0x2, 0xa, 0x6, 0xe,
  1209. 0x1, 0x9, 0x5, 0xd,
  1210. 0x3, 0xb, 0x7, 0xf };
  1211. ULONG CrcValue;
  1212. UCHAR Tmp;
  1213. UINT i;
  1214. //
  1215. // First compute the CRC.
  1216. //
  1217. CrcValue = CardComputeCrc(Buffer, Length);
  1218. //
  1219. // Now invert the bits in the result.
  1220. //
  1221. for (i=0; i<4; i++) {
  1222. Tmp = ((PUCHAR)&CrcValue)[3-i];
  1223. Crc[i] = (UCHAR)((InvertBits[Tmp >> 4] +
  1224. (InvertBits[Tmp & 0xf] << 4)) ^ 0xff);
  1225. }
  1226. }
  1227. VOID
  1228. CardGetMulticastBit(
  1229. IN UCHAR Address[ETH_LENGTH_OF_ADDRESS],
  1230. OUT UCHAR * Byte,
  1231. OUT UCHAR * Value
  1232. )
  1233. /*++
  1234. Routine Description:
  1235. For a given multicast address, returns the byte and bit in
  1236. the card multicast registers that it hashes to. Calls
  1237. CardComputeCrc() to determine the CRC value.
  1238. Arguments:
  1239. Address - the address
  1240. Byte - the byte that it hashes to
  1241. Value - will have a 1 in the relevant bit
  1242. Return Value:
  1243. None.
  1244. --*/
  1245. {
  1246. ULONG Crc;
  1247. UINT BitNumber;
  1248. //
  1249. // First compute the CRC.
  1250. //
  1251. Crc = CardComputeCrc(Address, ETH_LENGTH_OF_ADDRESS);
  1252. //
  1253. // The bit number is now in the 6 most significant bits of CRC.
  1254. //
  1255. BitNumber = (UINT)((Crc >> 26) & 0x3f);
  1256. *Byte = (UCHAR)(BitNumber / 8);
  1257. *Value = (UCHAR)((UCHAR)1 << (BitNumber % 8));
  1258. }
  1259. VOID
  1260. CardFillMulticastRegs(
  1261. IN PELNKII_ADAPTER AdaptP
  1262. )
  1263. /*++
  1264. Routine Description:
  1265. Erases and refills the card multicast registers. Used when
  1266. an address has been deleted and all bits must be recomputed.
  1267. Arguments:
  1268. AdaptP - pointer to the adapter block
  1269. Return Value:
  1270. None.
  1271. --*/
  1272. {
  1273. UINT i;
  1274. UCHAR Byte, Bit;
  1275. NDIS_STATUS Status;
  1276. //
  1277. // First turn all bits off.
  1278. //
  1279. for (i=0; i<8; i++) {
  1280. AdaptP->NicMulticastRegs[i] = 0;
  1281. }
  1282. NdisAcquireSpinLock(&AdaptP->Lock);
  1283. EthQueryGlobalFilterAddresses(
  1284. &Status,
  1285. AdaptP->FilterDB,
  1286. DEFAULT_MULTICASTLISTMAX * ETH_LENGTH_OF_ADDRESS,
  1287. &i,
  1288. Addresses
  1289. );
  1290. ASSERT(Status == NDIS_STATUS_SUCCESS);
  1291. //
  1292. // Now turn on the bit for each address in the multicast list.
  1293. //
  1294. for ( ; i > 0; ) {
  1295. i--;
  1296. CardGetMulticastBit(Addresses[i], &Byte, &Bit);
  1297. AdaptP->NicMulticastRegs[Byte] |= Bit;
  1298. }
  1299. NdisReleaseSpinLock(&AdaptP->Lock);
  1300. }
  1301. BOOLEAN
  1302. SyncCardStop(
  1303. IN PVOID SynchronizeContext
  1304. )
  1305. /*++
  1306. Routine Description:
  1307. Sets the NIC_COMMAND register to stop the card.
  1308. Arguments:
  1309. SynchronizeContext - pointer to the adapter block
  1310. Return Value:
  1311. TRUE if the power has failed.
  1312. --*/
  1313. {
  1314. PELNKII_ADAPTER AdaptP = ((PELNKII_ADAPTER)SynchronizeContext);
  1315. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND, CR_STOP | CR_NO_DMA);
  1316. return FALSE;
  1317. }
  1318. VOID
  1319. CardStartXmit(
  1320. IN PELNKII_ADAPTER AdaptP
  1321. )
  1322. /*++
  1323. Routine Description:
  1324. Sets the NIC_COMMAND register to start a transmission.
  1325. The transmit buffer number is taken from AdaptP->CurBufXmitting
  1326. and the length from AdaptP->PacketLens[AdaptP->CurBufXmitting].
  1327. Arguments:
  1328. AdaptP - pointer to the adapter block
  1329. Return Value:
  1330. TRUE if the power has failed.
  1331. --*/
  1332. {
  1333. XMIT_BUF XmitBufferNum = AdaptP->CurBufXmitting;
  1334. UINT Length = AdaptP->PacketLens[XmitBufferNum];
  1335. //
  1336. // Prepare the NIC registers for transmission.
  1337. //
  1338. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_START,
  1339. (UCHAR)(AdaptP->NicXmitStart + (UCHAR)(XmitBufferNum*BUFS_PER_TX)));
  1340. //
  1341. // Pad the length to 60 (plus CRC will be 64) if needed.
  1342. //
  1343. if (Length < 60) {
  1344. Length = 60;
  1345. }
  1346. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_COUNT_MSB, MSB(Length));
  1347. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_COUNT_LSB, LSB(Length));
  1348. //
  1349. // Start transmission, check for power failure first.
  1350. //
  1351. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  1352. CR_START | CR_XMIT | CR_NO_DMA);
  1353. IF_LOG( ElnkiiLog('x');)
  1354. }
  1355. BOOLEAN
  1356. SyncCardGetXmitStatus(
  1357. IN PVOID SynchronizeContext
  1358. )
  1359. /*++
  1360. Routine Description:
  1361. Gets the value of the "transmit status" NIC register and stores
  1362. it in AdaptP->XmitStatus.
  1363. Arguments:
  1364. SynchronizeContext - pointer to the adapter block
  1365. Return Value:
  1366. None.
  1367. --*/
  1368. {
  1369. PELNKII_ADAPTER AdaptP = ((PELNKII_ADAPTER)SynchronizeContext);
  1370. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_STATUS, &AdaptP->XmitStatus);
  1371. return FALSE;
  1372. }
  1373. BOOLEAN
  1374. SyncCardGetCurrent(
  1375. IN PVOID SynchronizeContext
  1376. )
  1377. /*++
  1378. Routine Description:
  1379. Gets the value of the CURRENT NIC register and stores
  1380. it in AdaptP->Current.
  1381. Arguments:
  1382. SynchronizeContext - pointer to the adapter block
  1383. Return Value:
  1384. None.
  1385. --*/
  1386. {
  1387. PELNKII_ADAPTER AdaptP = ((PELNKII_ADAPTER)SynchronizeContext);
  1388. //
  1389. // Have to go to page 1 to read this register.
  1390. //
  1391. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  1392. CR_START | CR_NO_DMA | CR_PAGE1);
  1393. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+NIC_CURRENT, &AdaptP->Current);
  1394. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  1395. CR_START | CR_NO_DMA | CR_PAGE0);
  1396. return FALSE;
  1397. }
  1398. VOID
  1399. CardSetBoundary(
  1400. IN PELNKII_ADAPTER AdaptP
  1401. )
  1402. /*++
  1403. Routine Description:
  1404. Sets the value of the "boundary" NIC register to one behind
  1405. AdaptP->NicNextPacket, to prevent packets from being received
  1406. on top of un-indicated ones.
  1407. Arguments:
  1408. AdaptP - pointer to the adapter block
  1409. Return Value:
  1410. None.
  1411. --*/
  1412. {
  1413. //
  1414. // Have to be careful with "one behin NicNextPacket" when
  1415. // NicNextPacket is the first buffer in receive area.
  1416. //
  1417. if (AdaptP->NicNextPacket == AdaptP->NicPageStart) {
  1418. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_BOUNDARY,
  1419. (UCHAR)(AdaptP->NicPageStop-(UCHAR)1));
  1420. } else {
  1421. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_BOUNDARY,
  1422. (UCHAR)(AdaptP->NicNextPacket-(UCHAR)1));
  1423. }
  1424. }
  1425. BOOLEAN
  1426. SyncCardSetReceiveConfig(
  1427. IN PVOID SynchronizeContext
  1428. )
  1429. /*++
  1430. Routine Description:
  1431. Sets the value of the "receive configuration" NIC register to
  1432. the value of AdaptP->NicReceiveConfig.
  1433. Arguments:
  1434. SynchronizeContext - pointer to the adapter block
  1435. Return Value:
  1436. None.
  1437. --*/
  1438. {
  1439. PELNKII_ADAPTER AdaptP = ((PELNKII_ADAPTER)SynchronizeContext);
  1440. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_RCV_CONFIG, AdaptP->NicReceiveConfig);
  1441. return FALSE;
  1442. }
  1443. BOOLEAN
  1444. SyncCardSetAllMulticast(
  1445. IN PVOID SynchronizeContext
  1446. )
  1447. /*++
  1448. Routine Description:
  1449. Turns on all the bits in the multicast register. Used when
  1450. the card must receive all multicast packets.
  1451. Arguments:
  1452. SynchronizeContext - pointer to the adapter block
  1453. Return Value:
  1454. None.
  1455. --*/
  1456. {
  1457. PELNKII_ADAPTER AdaptP = ((PELNKII_ADAPTER)SynchronizeContext);
  1458. UINT i;
  1459. //
  1460. // Have to move to page 1 to set these registers.
  1461. //
  1462. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  1463. CR_START | CR_NO_DMA | CR_PAGE1);
  1464. for (i=0; i<8; i++) {
  1465. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+(NIC_MC_ADDR+i), 0xff);
  1466. }
  1467. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  1468. CR_START | CR_NO_DMA | CR_PAGE0);
  1469. return FALSE;
  1470. }
  1471. BOOLEAN
  1472. SyncCardCopyMulticastRegs(
  1473. IN PVOID SynchronizeContext
  1474. )
  1475. /*++
  1476. Routine Description:
  1477. Sets the eight bytes in the card multicast registers.
  1478. Arguments:
  1479. SynchronizeContext - pointer to the adapter block
  1480. Return Value:
  1481. None.
  1482. --*/
  1483. {
  1484. PELNKII_ADAPTER AdaptP = ((PELNKII_ADAPTER)SynchronizeContext);
  1485. UINT i;
  1486. //
  1487. // Have to move to page 1 to set these registers.
  1488. //
  1489. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  1490. CR_START | CR_NO_DMA | CR_PAGE1);
  1491. for (i=0; i<8; i++) {
  1492. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+(NIC_MC_ADDR+i),
  1493. AdaptP->NicMulticastRegs[i]);
  1494. }
  1495. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  1496. CR_START | CR_NO_DMA | CR_PAGE0);
  1497. return FALSE;
  1498. }
  1499. BOOLEAN
  1500. SyncCardSetInterruptMask(
  1501. IN PVOID SynchronizeContext
  1502. )
  1503. /*++
  1504. Routine Description:
  1505. Sets the "interrupt mask" register of the NIC to the value of
  1506. AdaptP->NicInterruptMask.
  1507. Arguments:
  1508. SynchronizeContext - pointer to the adapter block
  1509. Return Value:
  1510. None.
  1511. --*/
  1512. {
  1513. PELNKII_ADAPTER AdaptP = ((PELNKII_ADAPTER)SynchronizeContext);
  1514. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_INTR_MASK, AdaptP->NicInterruptMask);
  1515. return FALSE;
  1516. }
  1517. BOOLEAN
  1518. SyncCardAcknowledgeReceive(
  1519. IN PVOID SynchronizeContext
  1520. )
  1521. /*++
  1522. Routine Description:
  1523. Sets the "packet received" bit in the NIC interrupt status register,
  1524. which re-enables interrupts of that type.
  1525. Arguments:
  1526. SynchronizeContext - pointer to the adapter block
  1527. Return Value:
  1528. None.
  1529. --*/
  1530. {
  1531. PELNKII_ADAPTER AdaptP = ((PELNKII_ADAPTER)SynchronizeContext);
  1532. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_INTR_STATUS, ISR_RCV);
  1533. //
  1534. // Interrupts were previously blocked in the interrupt handler.
  1535. //
  1536. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_INTR_MASK, AdaptP->NicInterruptMask);
  1537. return FALSE;
  1538. }
  1539. BOOLEAN
  1540. SyncCardAcknowledgeOverflow(
  1541. IN PVOID SynchronizeContext
  1542. )
  1543. /*++
  1544. Routine Description:
  1545. Sets the "buffer overflow" bit in the NIC interrupt status register,
  1546. which re-enables interrupts of that type.
  1547. Arguments:
  1548. SynchronizeContext - pointer to the adapter block
  1549. Return Value:
  1550. None.
  1551. --*/
  1552. {
  1553. PELNKII_ADAPTER AdaptP = ((PELNKII_ADAPTER)SynchronizeContext);
  1554. UCHAR InterruptStatus;
  1555. CardGetInterruptStatus(AdaptP, &InterruptStatus);
  1556. if (InterruptStatus & ISR_RCV_ERR) {
  1557. SyncCardUpdateCounters(AdaptP);
  1558. }
  1559. NdisRawWritePortUchar(
  1560. AdaptP->MappedIoBaseAddr+NIC_INTR_STATUS,
  1561. ISR_OVERFLOW
  1562. );
  1563. return FALSE;
  1564. }
  1565. BOOLEAN
  1566. SyncCardAcknowledgeTransmit(
  1567. IN PVOID SynchronizeContext
  1568. )
  1569. /*++
  1570. Routine Description:
  1571. Sets the "packet transmitted" bit in the NIC interrupt status register,
  1572. which re-enables interrupts of that type.
  1573. Arguments:
  1574. SynchronizeContext - pointer to the adapter block
  1575. Return Value:
  1576. None.
  1577. --*/
  1578. {
  1579. PELNKII_ADAPTER AdaptP = ((PELNKII_ADAPTER)SynchronizeContext);
  1580. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_INTR_STATUS, ISR_XMIT | ISR_XMIT_ERR);
  1581. //
  1582. // Interrupts were previously blocked in the interrupt handler.
  1583. //
  1584. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_INTR_MASK, AdaptP->NicInterruptMask);
  1585. return FALSE;
  1586. }
  1587. BOOLEAN
  1588. SyncCardAckAndGetCurrent(
  1589. IN PVOID SynchronizeContext
  1590. )
  1591. /*++
  1592. Routine Description:
  1593. Performs the functions of SyncCardAcknowledgeReceive followed by
  1594. SyncCardGetCurrent (since the two are always called
  1595. one after the other).
  1596. Arguments:
  1597. SynchronizeContext - pointer to the adapter block
  1598. Return Value:
  1599. None.
  1600. --*/
  1601. {
  1602. PELNKII_ADAPTER AdaptP = ((PELNKII_ADAPTER)SynchronizeContext);
  1603. //
  1604. // SyncCardAcknowledgeReceive.
  1605. //
  1606. #ifdef i386
  1607. _asm {
  1608. cli
  1609. }
  1610. #endif
  1611. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_INTR_STATUS, ISR_RCV);
  1612. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_INTR_MASK, AdaptP->NicInterruptMask);
  1613. #ifdef i386
  1614. _asm {
  1615. sti
  1616. }
  1617. #endif
  1618. //
  1619. // SyncCardGetCurrent.
  1620. //
  1621. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  1622. CR_START | CR_NO_DMA | CR_PAGE1);
  1623. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+NIC_CURRENT, &AdaptP->Current);
  1624. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND,
  1625. CR_START | CR_NO_DMA | CR_PAGE0);
  1626. return FALSE;
  1627. }
  1628. BOOLEAN
  1629. SyncCardGetXmitStatusAndAck(
  1630. IN PVOID SynchronizeContext
  1631. )
  1632. /*++
  1633. Routine Description:
  1634. Performs the functions of SyncCardGetXmitStatus followed by
  1635. SyncCardAcknowledgeTransmit (since the two are always
  1636. called one after the other).
  1637. Arguments:
  1638. SynchronizeContext - pointer to the adapter block
  1639. Return Value:
  1640. None.
  1641. --*/
  1642. {
  1643. PELNKII_ADAPTER AdaptP = ((PELNKII_ADAPTER)SynchronizeContext);
  1644. //
  1645. // SyncCardGetXmitStatus.
  1646. //
  1647. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_STATUS, &AdaptP->XmitStatus);
  1648. //
  1649. // SyncCardAcknowledgeTransmit.
  1650. //
  1651. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_INTR_STATUS, ISR_XMIT | ISR_XMIT_ERR);
  1652. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_INTR_MASK, AdaptP->NicInterruptMask);
  1653. return FALSE;
  1654. }
  1655. BOOLEAN
  1656. SyncCardUpdateCounters(
  1657. IN PVOID SynchronizeContext
  1658. )
  1659. /*++
  1660. Routine Description:
  1661. Updates the values of the three counters (frame alignment errors,
  1662. CRC errors, and missed packets).
  1663. Arguments:
  1664. SynchronizeContext - pointer to the adapter block
  1665. Return Value:
  1666. None.
  1667. --*/
  1668. {
  1669. PELNKII_ADAPTER AdaptP = ((PELNKII_ADAPTER)SynchronizeContext);
  1670. UCHAR Tmp;
  1671. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+NIC_FAE_ERR_CNTR, &Tmp);
  1672. AdaptP->FrameAlignmentErrors += Tmp;
  1673. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+NIC_CRC_ERR_CNTR, &Tmp);
  1674. AdaptP->CrcErrors += Tmp;
  1675. NdisRawReadPortUchar(AdaptP->MappedIoBaseAddr+NIC_MISSED_CNTR, &Tmp);
  1676. AdaptP->MissedPackets += Tmp;
  1677. return FALSE;
  1678. }
  1679. BOOLEAN
  1680. SyncCardHandleOverflow(
  1681. IN PVOID SynchronizeContext
  1682. )
  1683. /*++
  1684. Routine Description:
  1685. Sets all the flags for dealing with a receive overflow, stops the card
  1686. and acknowledges all outstanding interrupts.
  1687. Arguments:
  1688. SynchronizeContext - pointer to the adapter block
  1689. Return Value:
  1690. None.
  1691. --*/
  1692. {
  1693. PELNKII_ADAPTER AdaptP = ((PELNKII_ADAPTER)SynchronizeContext);
  1694. IF_LOG( ElnkiiLog('F');)
  1695. //
  1696. // This is a copy of CardStop(). This is changed in minor ways since
  1697. // we are already synchornized with interrupts.
  1698. //
  1699. //
  1700. // Turn on the STOP bit in the Command register.
  1701. //
  1702. SyncCardStop(AdaptP);
  1703. //
  1704. // Wait for ISR_RESET, but only for 1.6 milliseconds (as
  1705. // described in the March 1991 8390 addendum), since that
  1706. // is the maximum time for a software reset to occur.
  1707. //
  1708. //
  1709. NdisStallExecution(2000);
  1710. //
  1711. // Clear the Remote Byte Count register so that ISR_RESET
  1712. // will come on.
  1713. //
  1714. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_RMT_COUNT_MSB, 0);
  1715. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_RMT_COUNT_LSB, 0);
  1716. //
  1717. // According to National Semiconductor, the next check is necessary
  1718. // See Step 5. of the overflow process
  1719. //
  1720. // NOTE: The setting of variables to check if the transmit has completed
  1721. // cannot be done here because anything in the ISR has already been ack'ed
  1722. // inside the main DPC. Thus, the setting of the variables, described in
  1723. // the Handbook was moved to the main DPC.
  1724. //
  1725. // Continued: If you did the check here, you will doubly transmit most
  1726. // packets that happened to be on the card when the overflow occurred.
  1727. //
  1728. //
  1729. // Put the card in loopback mode, then start it.
  1730. //
  1731. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_XMIT_CONFIG, TCR_LOOPBACK);
  1732. //
  1733. // Start the card. This does not Undo the loopback mode.
  1734. //
  1735. NdisRawWritePortUchar(AdaptP->MappedIoBaseAddr+NIC_COMMAND, CR_START | CR_NO_DMA);
  1736. return FALSE;
  1737. }