Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3221 lines
67 KiB

  1. /*++
  2. Copyright (c) 1990-1998 Microsoft Corporation, All Rights Reserved.
  3. Module Name:
  4. card.c
  5. Abstract:
  6. Card-specific functions for the NDIS 3.0 Novell 2000 driver.
  7. Author:
  8. Sean Selitrennikoff
  9. Environment:
  10. Kernel mode, FSD
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. BOOLEAN
  15. CardSlotTest(
  16. IN PNE2000_ADAPTER Adapter
  17. );
  18. BOOLEAN
  19. CardRamTest(
  20. IN PNE2000_ADAPTER Adapter
  21. );
  22. #pragma NDIS_PAGEABLE_FUNCTION(CardCheckParameters)
  23. BOOLEAN CardCheckParameters(
  24. IN PNE2000_ADAPTER Adapter
  25. )
  26. /*++
  27. Routine Description:
  28. Checks that the I/O base address is correct.
  29. Arguments:
  30. Adapter - pointer to the adapter block.
  31. Return Value:
  32. TRUE, if IoBaseAddress appears correct.
  33. --*/
  34. {
  35. UCHAR Tmp;
  36. //
  37. // If adapter responds to a stop command correctly -- assume it is there.
  38. //
  39. //
  40. // Turn off interrupts first.
  41. //
  42. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_MASK, 0);
  43. //
  44. // Stop the card.
  45. //
  46. SyncCardStop(Adapter);
  47. //
  48. // Pause
  49. //
  50. NdisStallExecution(2000);
  51. //
  52. // Read response
  53. //
  54. NdisRawReadPortUchar(Adapter->IoPAddr + NIC_COMMAND, &Tmp);
  55. if ((Tmp == (CR_NO_DMA | CR_STOP)) ||
  56. (Tmp == (CR_NO_DMA | CR_STOP | CR_START))
  57. )
  58. {
  59. return(TRUE);
  60. }
  61. else
  62. {
  63. return(FALSE);
  64. }
  65. }
  66. #ifdef NE2000
  67. #pragma NDIS_PAGEABLE_FUNCTION(CardSlotTest)
  68. BOOLEAN CardSlotTest(
  69. IN PNE2000_ADAPTER Adapter
  70. )
  71. /*++
  72. Routine Description:
  73. Checks if the card is in an 8 or 16 bit slot and sets a flag in the
  74. adapter structure.
  75. Arguments:
  76. Adapter - pointer to the adapter block.
  77. Return Value:
  78. TRUE, if all goes well, else FALSE.
  79. --*/
  80. {
  81. UCHAR Tmp;
  82. UCHAR RomCopy[32];
  83. UCHAR i;
  84. BOOLEAN found;
  85. //
  86. // Reset the chip
  87. //
  88. NdisRawReadPortUchar(Adapter->IoPAddr + NIC_RESET, &Tmp);
  89. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RESET, 0xFF);
  90. //
  91. // Go to page 0 and stop
  92. //
  93. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_STOP | CR_NO_DMA);
  94. //
  95. // Pause
  96. //
  97. NdisStallExecution(2000);
  98. //
  99. // Check that it is stopped
  100. //
  101. NdisRawReadPortUchar(Adapter->IoPAddr + NIC_COMMAND, &Tmp);
  102. if (Tmp != (CR_NO_DMA | CR_STOP))
  103. {
  104. IF_LOUD(DbgPrint("Could not stop the card\n");)
  105. return(FALSE);
  106. }
  107. //
  108. // Setup to read from ROM
  109. //
  110. NdisRawWritePortUchar(
  111. Adapter->IoPAddr + NIC_DATA_CONFIG,
  112. DCR_BYTE_WIDE | DCR_FIFO_8_BYTE | DCR_NORMAL
  113. );
  114. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_MASK, 0x0);
  115. //
  116. // Ack any interrupts that may be hanging around
  117. //
  118. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_STATUS, 0xFF);
  119. //
  120. // Setup to read in the ROM, the address and byte count.
  121. //
  122. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_LSB, 0x0);
  123. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_MSB, 0x0);
  124. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 32);
  125. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0);
  126. NdisRawWritePortUchar(
  127. Adapter->IoPAddr + NIC_COMMAND,
  128. CR_DMA_READ | CR_START
  129. );
  130. //
  131. // Read first 32 bytes in 16 bit mode
  132. //
  133. for (i = 0; i < 32; i++)
  134. {
  135. NdisRawReadPortUchar(Adapter->IoPAddr + NIC_RACK_NIC, RomCopy + i);
  136. }
  137. IF_VERY_LOUD( DbgPrint("Resetting the chip\n"); )
  138. //
  139. // Reset the chip
  140. //
  141. NdisRawReadPortUchar(Adapter->IoPAddr + NIC_RESET, &Tmp);
  142. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RESET, 0xFF);
  143. //
  144. // Check ROM for 'B' (byte) or 'W' (word)
  145. // NOTE: If the buffer has bot BB and WW then use WW instead of BB
  146. IF_VERY_LOUD( DbgPrint("Checking slot type\n"); )
  147. found = FALSE;
  148. for (i = 16; i < 31; i++)
  149. {
  150. if (((RomCopy[i] == 'B') && (RomCopy[i+1] == 'B')) ||
  151. ((RomCopy[i] == 'W') && (RomCopy[i+1] == 'W'))
  152. )
  153. {
  154. if (RomCopy[i] == 'B')
  155. {
  156. Adapter->EightBitSlot = TRUE;
  157. found = TRUE;
  158. }
  159. else
  160. {
  161. Adapter->EightBitSlot = FALSE;
  162. found = TRUE;
  163. break; // Go no farther
  164. }
  165. }
  166. }
  167. if (found)
  168. {
  169. IF_VERY_LOUD( (Adapter->EightBitSlot?DbgPrint("8 bit slot\n"):
  170. DbgPrint("16 bit slot\n")); )
  171. }
  172. else
  173. {
  174. //
  175. // If neither found -- then not an NE2000
  176. //
  177. IF_VERY_LOUD( DbgPrint("Failed slot type\n"); )
  178. }
  179. return(found);
  180. }
  181. #endif // NE2000
  182. #pragma NDIS_PAGEABLE_FUNCTION(CardRamTest)
  183. BOOLEAN
  184. CardRamTest(
  185. IN PNE2000_ADAPTER Adapter
  186. )
  187. /*++
  188. Routine Description:
  189. Finds out how much RAM the adapter has. It starts at 1K and checks thru
  190. 60K. It will set Adapter->RamSize to the appropriate value iff this
  191. function returns TRUE.
  192. Arguments:
  193. Adapter - pointer to the adapter block.
  194. Return Value:
  195. TRUE, if all goes well, else FALSE.
  196. --*/
  197. {
  198. PUCHAR RamBase, RamPointer;
  199. PUCHAR RamEnd;
  200. UCHAR TestPattern[]={ 0xAA, 0x55, 0xFF, 0x00 };
  201. PULONG pTestPattern = (PULONG)TestPattern;
  202. UCHAR ReadPattern[4];
  203. PULONG pReadPattern = (PULONG)ReadPattern;
  204. for (RamBase = (PUCHAR)0x400; RamBase < (PUCHAR)0x10000; RamBase += 0x400) {
  205. //
  206. // Write Test pattern
  207. //
  208. if (!CardCopyDown(Adapter, RamBase, TestPattern, 4)) {
  209. continue;
  210. }
  211. //
  212. // Read pattern
  213. //
  214. if (!CardCopyUp(Adapter, ReadPattern, RamBase, 4)) {
  215. continue;
  216. }
  217. IF_VERY_LOUD( DbgPrint("Addr 0x%x: 0x%x, 0x%x, 0x%x, 0x%x\n",
  218. RamBase,
  219. ReadPattern[0],
  220. ReadPattern[1],
  221. ReadPattern[2],
  222. ReadPattern[3]
  223. );
  224. )
  225. //
  226. // If they are the same, find the end
  227. //
  228. if (*pReadPattern == *pTestPattern) {
  229. for (RamEnd = RamBase; !(PtrToUlong(RamEnd) & 0xFFFF0000); RamEnd += 0x400) {
  230. //
  231. // Write test pattern
  232. //
  233. if (!CardCopyDown(Adapter, RamEnd, TestPattern, 4)) {
  234. break;
  235. }
  236. //
  237. // Read pattern
  238. //
  239. if (!CardCopyUp(Adapter, ReadPattern, RamEnd, 4)) {
  240. break;
  241. }
  242. if (*pReadPattern != *pTestPattern) {
  243. break;
  244. }
  245. }
  246. break;
  247. }
  248. }
  249. IF_LOUD( DbgPrint("RamBase 0x%x, RamEnd 0x%x\n", RamBase, RamEnd); )
  250. //
  251. // If not found, error out
  252. //
  253. if ((RamBase >= (PUCHAR)0x10000) || (RamBase == RamEnd)) {
  254. return(FALSE);
  255. }
  256. //
  257. // Watch for boundary case when RamEnd is maximum value
  258. //
  259. if ((ULONG_PTR)RamEnd & 0xFFFF0000) {
  260. RamEnd -= 0x100;
  261. }
  262. //
  263. // Check all of ram
  264. //
  265. for (RamPointer = RamBase; RamPointer < RamEnd; RamPointer += 4) {
  266. //
  267. // Write test pattern
  268. //
  269. if (!CardCopyDown(Adapter, RamPointer, TestPattern, 4)) {
  270. return(FALSE);
  271. }
  272. //
  273. // Read pattern
  274. //
  275. if (!CardCopyUp(Adapter, ReadPattern, RamBase, 4)) {
  276. return(FALSE);
  277. }
  278. if (*pReadPattern != *pTestPattern) {
  279. return(FALSE);
  280. }
  281. }
  282. //
  283. // Store Results
  284. //
  285. Adapter->RamBase = RamBase;
  286. Adapter->RamSize = (ULONG)(RamEnd - RamBase);
  287. return(TRUE);
  288. }
  289. #pragma NDIS_PAGEABLE_FUNCTION(CardInitialize)
  290. BOOLEAN
  291. CardInitialize(
  292. IN PNE2000_ADAPTER Adapter
  293. )
  294. /*++
  295. Routine Description:
  296. Initializes the card into a running state.
  297. Arguments:
  298. Adapter - pointer to the adapter block.
  299. Return Value:
  300. TRUE, if all goes well, else FALSE.
  301. --*/
  302. {
  303. UCHAR Tmp;
  304. USHORT i;
  305. //
  306. // Stop the card.
  307. //
  308. SyncCardStop(Adapter);
  309. //
  310. // Initialize the Data Configuration register.
  311. //
  312. NdisRawWritePortUchar(
  313. Adapter->IoPAddr + NIC_DATA_CONFIG,
  314. DCR_AUTO_INIT | DCR_FIFO_8_BYTE
  315. );
  316. //
  317. // Set Xmit start location
  318. //
  319. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_START, 0xA0);
  320. //
  321. // Set Xmit configuration
  322. //
  323. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_CONFIG, 0x0);
  324. //
  325. // Set Receive configuration
  326. //
  327. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RCV_CONFIG, RCR_MONITOR);
  328. //
  329. // Set Receive start
  330. //
  331. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_PAGE_START, 0x4);
  332. //
  333. // Set Receive end
  334. //
  335. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_PAGE_STOP, 0xFF);
  336. //
  337. // Set Receive boundary
  338. //
  339. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_BOUNDARY, 0x4);
  340. //
  341. // Set Xmit bytes
  342. //
  343. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_COUNT_LSB, 0x3C);
  344. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_COUNT_MSB, 0x0);
  345. //
  346. // Pause
  347. //
  348. NdisStallExecution(2000);
  349. //
  350. // Ack all interrupts that we might have produced
  351. //
  352. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_STATUS, 0xFF);
  353. //
  354. // Change to page 1
  355. //
  356. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_PAGE1 | CR_STOP);
  357. //
  358. // Set current
  359. //
  360. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_CURRENT, 0x4);
  361. //
  362. // Back to page 0
  363. //
  364. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_PAGE0 | CR_STOP);
  365. //
  366. // Pause
  367. //
  368. NdisStallExecution(2000);
  369. //
  370. // Check that Command register reflects this last command
  371. //
  372. NdisRawReadPortUchar(Adapter->IoPAddr + NIC_COMMAND, &Tmp);
  373. if (!(Tmp & CR_STOP))
  374. {
  375. IF_LOUD(DbgPrint("Invalid command register\n");)
  376. return(FALSE);
  377. }
  378. //
  379. // Do initialization errata
  380. //
  381. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 55);
  382. //
  383. // Setup for a read
  384. //
  385. NdisRawWritePortUchar(
  386. Adapter->IoPAddr + NIC_COMMAND,
  387. CR_DMA_READ | CR_START
  388. );
  389. #ifdef NE2000
  390. //
  391. // Check if the slot is 8 or 16 bit (affects data transfer rate).
  392. //
  393. if ((Adapter->BusType == NdisInterfaceMca) ||
  394. (NE2000_PCMCIA == Adapter->CardType))
  395. {
  396. Adapter->EightBitSlot = FALSE;
  397. }
  398. else
  399. {
  400. IF_VERY_LOUD(DbgPrint("CardSlotTest\n");)
  401. if (CardSlotTest(Adapter) == FALSE)
  402. {
  403. //
  404. // Stop chip
  405. //
  406. SyncCardStop(Adapter);
  407. IF_LOUD(DbgPrint(" -- Failed\n");)
  408. return(FALSE);
  409. }
  410. }
  411. #else // NE2000
  412. Adapter->EightBitSlot = TRUE;
  413. #endif // NE2000
  414. //
  415. // Mask Interrupts
  416. //
  417. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_MASK, 0x0);
  418. //
  419. // Setup the Adapter for reading ram
  420. //
  421. // NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_PAGE0); // robin
  422. if (Adapter->EightBitSlot)
  423. {
  424. NdisRawWritePortUchar(
  425. Adapter->IoPAddr + NIC_DATA_CONFIG,
  426. DCR_FIFO_8_BYTE | DCR_NORMAL | DCR_BYTE_WIDE
  427. );
  428. }
  429. else
  430. {
  431. NdisRawWritePortUchar(
  432. Adapter->IoPAddr + NIC_DATA_CONFIG,
  433. DCR_FIFO_8_BYTE | DCR_NORMAL | DCR_WORD_WIDE
  434. );
  435. }
  436. //
  437. // Clear transmit configuration.
  438. //
  439. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_CONFIG, 0);
  440. //
  441. // Clear receive configuration.
  442. //
  443. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RCV_CONFIG, 0);
  444. //
  445. // Clear any interrupts
  446. //
  447. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_STATUS, 0xFF);
  448. //
  449. // Stop the chip
  450. //
  451. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_NO_DMA | CR_STOP);
  452. //
  453. // Clear any DMA values
  454. //
  455. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0);
  456. //
  457. // Clear any DMA values
  458. //
  459. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0);
  460. //
  461. // Wait for the reset to complete.
  462. //
  463. i = 0x3FFF;
  464. while (--i)
  465. {
  466. NdisRawReadPortUchar(Adapter->IoPAddr + NIC_INTR_STATUS, &Tmp);
  467. if (Tmp & ISR_RESET)
  468. break;
  469. NdisStallExecution(4);
  470. }
  471. //
  472. // Put card in loopback mode
  473. //
  474. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_CONFIG, TCR_LOOPBACK);
  475. //
  476. // Start the chip.
  477. //
  478. NdisRawWritePortUchar(
  479. Adapter->IoPAddr + NIC_COMMAND,
  480. CR_NO_DMA | CR_START
  481. );
  482. //
  483. // Test for the amount of RAM
  484. //
  485. if (NE2000_ISA == Adapter->CardType)
  486. {
  487. if (CardRamTest(Adapter) == FALSE)
  488. {
  489. //
  490. // Stop the chip
  491. //
  492. SyncCardStop(Adapter);
  493. return(FALSE);
  494. }
  495. }
  496. else
  497. {
  498. //
  499. // We know what it is for the pcmcia adapters,
  500. // so don't waste time on detecting it.
  501. //
  502. Adapter->RamBase = (PUCHAR)0x4000;
  503. Adapter->RamSize = 0x4000;
  504. }
  505. //
  506. // Stop the chip
  507. //
  508. SyncCardStop(Adapter);
  509. return(TRUE);
  510. }
  511. #pragma NDIS_PAGEABLE_FUNCTION(CardReadEthernetAddress)
  512. BOOLEAN CardReadEthernetAddress(
  513. IN PNE2000_ADAPTER Adapter
  514. )
  515. /*++
  516. Routine Description:
  517. Reads in the Ethernet address from the Novell 2000.
  518. Arguments:
  519. Adapter - pointer to the adapter block.
  520. Return Value:
  521. The address is stored in Adapter->PermanentAddress, and StationAddress if it
  522. is currently zero.
  523. --*/
  524. {
  525. UINT c;
  526. //
  527. // Things are done a little differently for PCMCIA adapters.
  528. //
  529. if (NE2000_PCMCIA == Adapter->CardType)
  530. {
  531. #if 0
  532. NDIS_STATUS Status;
  533. PUCHAR pAttributeWindow;
  534. NDIS_PHYSICAL_ADDRESS AttributePhysicalAddress;
  535. //
  536. // Setup the physical address for the attribute window.
  537. //
  538. NdisSetPhysicalAddressHigh(AttributePhysicalAddress, 0);
  539. NdisSetPhysicalAddressLow(
  540. AttributePhysicalAddress,
  541. Adapter->AttributeMemoryAddress
  542. );
  543. //
  544. // We need to get the pcmcia information from the tuple.
  545. //
  546. Status = NdisMMapIoSpace(
  547. (PVOID *)&pAttributeWindow,
  548. Adapter->MiniportAdapterHandle,
  549. AttributePhysicalAddress,
  550. Adapter->AttributeMemorySize
  551. );
  552. if (NDIS_STATUS_SUCCESS != Status)
  553. {
  554. //
  555. // Failed to setup the attribute window.
  556. //
  557. return(FALSE);
  558. }
  559. //
  560. // Read the ethernet address from the card.
  561. //
  562. for (c = 0; c < ETH_LENGTH_OF_ADDRESS; c++)
  563. {
  564. NdisReadRegisterUchar(
  565. (PUCHAR)(pAttributeWindow + CIS_NET_ADDR_OFFSET + c * 2),
  566. &Adapter->PermanentAddress[c]);
  567. }
  568. #endif
  569. if (ETH_LENGTH_OF_ADDRESS != NdisReadPcmciaAttributeMemory(
  570. Adapter->MiniportAdapterHandle,
  571. CIS_NET_ADDR_OFFSET/2,
  572. Adapter->PermanentAddress,
  573. ETH_LENGTH_OF_ADDRESS
  574. ))
  575. {
  576. return(FALSE);
  577. }
  578. }
  579. else
  580. {
  581. //
  582. // Setup to read the ethernet address
  583. //
  584. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 12);
  585. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0);
  586. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_LSB, 0);
  587. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_MSB, 0);
  588. NdisRawWritePortUchar(
  589. Adapter->IoPAddr + NIC_COMMAND,
  590. CR_START | CR_DMA_READ
  591. );
  592. //
  593. // Read in the station address. (We have to read words -- 2 * 6 -- bytes)
  594. //
  595. for (c = 0; c < NE2000_LENGTH_OF_ADDRESS; c++)
  596. {
  597. NdisRawReadPortUchar(
  598. Adapter->IoPAddr + NIC_RACK_NIC,
  599. &Adapter->PermanentAddress[c]
  600. );
  601. }
  602. }
  603. IF_LOUD(
  604. DbgPrint(
  605. "Ne2000: PermanentAddress [ %02x-%02x-%02x-%02x-%02x-%02x ]\n",
  606. Adapter->PermanentAddress[0],
  607. Adapter->PermanentAddress[1],
  608. Adapter->PermanentAddress[2],
  609. Adapter->PermanentAddress[3],
  610. Adapter->PermanentAddress[4],
  611. Adapter->PermanentAddress[5]
  612. );
  613. )
  614. //
  615. // Use the burned in address as the station address, unless the
  616. // registry specified an override value.
  617. //
  618. if ((Adapter->StationAddress[0] == 0x00) &&
  619. (Adapter->StationAddress[1] == 0x00) &&
  620. (Adapter->StationAddress[2] == 0x00) &&
  621. (Adapter->StationAddress[3] == 0x00) &&
  622. (Adapter->StationAddress[4] == 0x00) &&
  623. (Adapter->StationAddress[5] == 0x00)
  624. )
  625. {
  626. Adapter->StationAddress[0] = Adapter->PermanentAddress[0];
  627. Adapter->StationAddress[1] = Adapter->PermanentAddress[1];
  628. Adapter->StationAddress[2] = Adapter->PermanentAddress[2];
  629. Adapter->StationAddress[3] = Adapter->PermanentAddress[3];
  630. Adapter->StationAddress[4] = Adapter->PermanentAddress[4];
  631. Adapter->StationAddress[5] = Adapter->PermanentAddress[5];
  632. }
  633. return(TRUE);
  634. }
  635. BOOLEAN
  636. CardSetup(
  637. IN PNE2000_ADAPTER Adapter
  638. )
  639. /*++
  640. Routine Description:
  641. Sets up the card.
  642. Arguments:
  643. Adapter - pointer to the adapter block, which must be initialized.
  644. Return Value:
  645. TRUE if successful.
  646. --*/
  647. {
  648. UINT i;
  649. UINT Filter;
  650. UCHAR Tmp;
  651. //
  652. // Write to and read from CR to make sure it is there.
  653. //
  654. NdisRawWritePortUchar(
  655. Adapter->IoPAddr + NIC_COMMAND,
  656. CR_STOP | CR_NO_DMA | CR_PAGE0
  657. );
  658. NdisRawReadPortUchar(
  659. Adapter->IoPAddr + NIC_COMMAND,
  660. &Tmp
  661. );
  662. if ((Tmp & (CR_STOP | CR_NO_DMA | CR_PAGE0)) !=
  663. (CR_STOP | CR_NO_DMA | CR_PAGE0)
  664. )
  665. {
  666. return(FALSE);
  667. }
  668. //
  669. // Set up the registers in the correct sequence, as defined by
  670. // the 8390 specification.
  671. //
  672. if (Adapter->EightBitSlot)
  673. {
  674. NdisRawWritePortUchar(
  675. Adapter->IoPAddr + NIC_DATA_CONFIG,
  676. DCR_BYTE_WIDE | DCR_NORMAL | DCR_FIFO_8_BYTE
  677. );
  678. }
  679. else
  680. {
  681. NdisRawWritePortUchar(
  682. Adapter->IoPAddr + NIC_DATA_CONFIG,
  683. DCR_WORD_WIDE | DCR_NORMAL | DCR_FIFO_8_BYTE
  684. );
  685. }
  686. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0);
  687. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0);
  688. NdisRawWritePortUchar(
  689. Adapter->IoPAddr + NIC_RCV_CONFIG,
  690. Adapter->NicReceiveConfig
  691. );
  692. NdisRawWritePortUchar(
  693. Adapter->IoPAddr + NIC_XMIT_CONFIG,
  694. TCR_LOOPBACK
  695. );
  696. NdisRawWritePortUchar(
  697. Adapter->IoPAddr + NIC_BOUNDARY,
  698. Adapter->NicPageStart
  699. );
  700. NdisRawWritePortUchar(
  701. Adapter->IoPAddr + NIC_PAGE_START,
  702. Adapter->NicPageStart
  703. );
  704. NdisRawWritePortUchar(
  705. Adapter->IoPAddr + NIC_PAGE_STOP,
  706. Adapter->NicPageStop
  707. );
  708. Adapter->Current = Adapter->NicPageStart + (UCHAR)1;
  709. Adapter->NicNextPacket = Adapter->NicPageStart + (UCHAR)1;
  710. Adapter->BufferOverflow = FALSE;
  711. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_STATUS, 0xff);
  712. NdisRawWritePortUchar(
  713. Adapter->IoPAddr + NIC_INTR_MASK,
  714. Adapter->NicInterruptMask
  715. );
  716. //
  717. // Move to page 1 to write the station address
  718. //
  719. NdisRawWritePortUchar(
  720. Adapter->IoPAddr + NIC_COMMAND,
  721. CR_STOP | CR_NO_DMA | CR_PAGE1
  722. );
  723. for (i = 0; i < NE2000_LENGTH_OF_ADDRESS; i++)
  724. {
  725. NdisRawWritePortUchar(
  726. Adapter->IoPAddr + (NIC_PHYS_ADDR + i),
  727. Adapter->StationAddress[i]
  728. );
  729. }
  730. Filter = Adapter->PacketFilter;
  731. //
  732. // Write out the multicast addresses
  733. //
  734. for (i = 0; i < 8; i++)
  735. {
  736. NdisRawWritePortUchar(
  737. Adapter->IoPAddr + (NIC_MC_ADDR + i),
  738. (UCHAR)((Filter & NDIS_PACKET_TYPE_ALL_MULTICAST) ?
  739. 0xff : Adapter->NicMulticastRegs[i])
  740. );
  741. }
  742. //
  743. // Write out the current receive buffer to receive into
  744. //
  745. NdisRawWritePortUchar(
  746. Adapter->IoPAddr + NIC_CURRENT,
  747. Adapter->Current
  748. );
  749. //
  750. // move back to page 0 and start the card...
  751. //
  752. NdisRawWritePortUchar(
  753. Adapter->IoPAddr + NIC_COMMAND,
  754. CR_STOP | CR_NO_DMA | CR_PAGE0
  755. );
  756. NdisRawWritePortUchar(
  757. Adapter->IoPAddr + NIC_COMMAND,
  758. CR_START | CR_NO_DMA | CR_PAGE0
  759. );
  760. //
  761. // ... but it is still in loopback mode.
  762. //
  763. return(TRUE);
  764. }
  765. VOID CardStop(
  766. IN PNE2000_ADAPTER Adapter
  767. )
  768. /*++
  769. Routine Description:
  770. Stops the card.
  771. Arguments:
  772. Adapter - pointer to the adapter block
  773. Return Value:
  774. None.
  775. --*/
  776. {
  777. UINT i;
  778. UCHAR Tmp;
  779. //
  780. // Turn on the STOP bit in the Command register.
  781. //
  782. SyncCardStop(Adapter);
  783. //
  784. // Clear the Remote Byte Count register so that ISR_RESET
  785. // will come on.
  786. //
  787. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0);
  788. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0);
  789. //
  790. // Wait for ISR_RESET, but only for 1.6 milliseconds (as
  791. // described in the March 1991 8390 addendum), since that
  792. // is the maximum time for a software reset to occur.
  793. //
  794. //
  795. for (i = 0; i < 4; i++)
  796. {
  797. NdisRawReadPortUchar(Adapter->IoPAddr+NIC_INTR_STATUS, &Tmp);
  798. if (Tmp & ISR_RESET)
  799. break;
  800. NdisStallExecution(500);
  801. }
  802. if (i == 4)
  803. {
  804. IF_LOUD( DbgPrint("RESET\n");)
  805. IF_LOG( Ne2000Log('R');)
  806. }
  807. //
  808. // Put the card in loopback mode, then start it.
  809. //
  810. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_CONFIG, TCR_LOOPBACK);
  811. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_START | CR_NO_DMA);
  812. //
  813. // At this point the card is still in loopback mode.
  814. //
  815. }
  816. BOOLEAN CardReset(
  817. IN PNE2000_ADAPTER Adapter
  818. )
  819. /*++
  820. Routine Description:
  821. Resets the card.
  822. Arguments:
  823. Adapter - pointer to the adapter block
  824. Return Value:
  825. TRUE if everything is OK.
  826. --*/
  827. {
  828. //
  829. // Stop the chip
  830. //
  831. CardStop(Adapter);
  832. //
  833. // Wait for the card to finish any receives or transmits
  834. //
  835. NdisStallExecution(2000);
  836. //
  837. // CardSetup() does a software reset.
  838. //
  839. if (!CardSetup(Adapter))
  840. {
  841. NdisWriteErrorLogEntry(
  842. Adapter->MiniportAdapterHandle,
  843. NDIS_ERROR_CODE_HARDWARE_FAILURE,
  844. 2,
  845. cardReset,
  846. NE2000_ERRMSG_CARD_SETUP
  847. );
  848. return(FALSE);
  849. }
  850. //
  851. // Restart the chip
  852. //
  853. CardStart(Adapter);
  854. return TRUE;
  855. }
  856. BOOLEAN CardCopyDownPacket(
  857. IN PNE2000_ADAPTER Adapter,
  858. IN PNDIS_PACKET Packet,
  859. OUT PUINT Length
  860. )
  861. /*++
  862. Routine Description:
  863. Copies the packet Packet down starting at the beginning of
  864. transmit buffer XmitBufferNum, fills in Length to be the
  865. length of the packet.
  866. Arguments:
  867. Adapter - pointer to the adapter block
  868. Packet - the packet to copy down
  869. Return Value:
  870. Length - the length of the data in the packet in bytes.
  871. TRUE if the transfer completed with no problems.
  872. --*/
  873. {
  874. //
  875. // Addresses of the Buffers to copy from and to.
  876. //
  877. PUCHAR CurBufAddress;
  878. PUCHAR OddBufAddress;
  879. PUCHAR XmitBufAddress;
  880. //
  881. // Length of each of the above buffers
  882. //
  883. UINT CurBufLen;
  884. UINT PacketLength;
  885. //
  886. // Was the last transfer of an odd length?
  887. //
  888. BOOLEAN OddBufLen = FALSE;
  889. //
  890. // Current NDIS_BUFFER that is being copied from
  891. //
  892. PNDIS_BUFFER CurBuffer;
  893. //
  894. // Programmed I/O, have to transfer the data.
  895. //
  896. NdisQueryPacket(Packet, NULL, NULL, &CurBuffer, &PacketLength);
  897. //
  898. // Skip 0 length copies
  899. //
  900. if (PacketLength == 0) {
  901. return(TRUE);
  902. }
  903. //
  904. // Get the starting buffer address
  905. //
  906. XmitBufAddress = (PUCHAR)Adapter->XmitStart +
  907. Adapter->NextBufToFill*TX_BUF_SIZE;
  908. //
  909. // Get address and length of the first buffer in the packet
  910. //
  911. NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
  912. while (CurBuffer && (CurBufLen == 0)) {
  913. NdisGetNextBuffer(CurBuffer, &CurBuffer);
  914. NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
  915. }
  916. //
  917. // set up the card
  918. //
  919. {
  920. //
  921. // Temporary places for holding values for transferring to
  922. // an odd aligned address on 16-bit slots.
  923. //
  924. UCHAR Tmp;
  925. UCHAR Tmp1;
  926. USHORT TmpShort;
  927. //
  928. // Values for waiting for noticing when a DMA completes.
  929. //
  930. USHORT OldAddr, NewAddr;
  931. //
  932. // Count of transfers to do
  933. //
  934. USHORT Count;
  935. //
  936. // Buffer to read from for odd aligned transfers
  937. //
  938. PUCHAR ReadBuffer;
  939. if (!Adapter->EightBitSlot && ((ULONG_PTR)XmitBufAddress & 0x1)) {
  940. //
  941. // Avoid transfers to odd addresses in word mode.
  942. //
  943. // For odd addresses we need to read first to get the previous
  944. // byte and then merge it with our first byte.
  945. //
  946. //
  947. // Set Count and Source address
  948. //
  949. // NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_PAGE0); // robin
  950. NdisRawWritePortUchar(
  951. Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  952. LSB(PtrToUlong(XmitBufAddress - 1))
  953. );
  954. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  955. MSB((PtrToUlong(XmitBufAddress) - 1))
  956. );
  957. // NE2000 PCMCIA CHANGE START
  958. //
  959. // NE2000 PCMCIA CHANGE!!!
  960. //
  961. //NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x1 );
  962. //NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0 );
  963. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2 );
  964. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0 );
  965. //
  966. // Set direction (Read)
  967. //
  968. NdisRawWritePortUchar( Adapter->IoPAddr + NIC_COMMAND,
  969. CR_START | CR_PAGE0 | CR_DMA_READ );
  970. //
  971. // NE2000 PCMCIA CHANGE!!!
  972. //
  973. //NdisRawReadPortUchar( Adapter->IoPAddr + NIC_RACK_NIC, &Tmp1 );
  974. NdisRawReadPortUshort( Adapter->IoPAddr + NIC_RACK_NIC, &TmpShort );
  975. Tmp1 = LSB(TmpShort);
  976. // NE2000 PCMCIA CHANGE END
  977. //
  978. // Do Write errata as described on pages 1-143 and
  979. // 1-144 of the 1992 LAN databook
  980. //
  981. //
  982. // Set Count and destination address
  983. //
  984. ReadBuffer = XmitBufAddress + ((ULONG_PTR)XmitBufAddress & 1);
  985. OldAddr = NewAddr = (USHORT)(ReadBuffer);
  986. // NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, // robin
  987. // CR_PAGE0 // robin
  988. // ); // robin
  989. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  990. LSB(PtrToUlong(ReadBuffer))
  991. );
  992. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  993. MSB(PtrToUlong(ReadBuffer))
  994. );
  995. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2 );
  996. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0 );
  997. //
  998. // Set direction (Read)
  999. //
  1000. NdisRawWritePortUchar(
  1001. Adapter->IoPAddr + NIC_COMMAND,
  1002. CR_START | CR_PAGE0 | CR_DMA_READ
  1003. );
  1004. //
  1005. // Read from port
  1006. //
  1007. NdisRawReadPortUshort( Adapter->IoPAddr + NIC_RACK_NIC, &TmpShort );
  1008. //
  1009. // Wait for addr to change
  1010. //
  1011. TmpShort = 0xFFFF;
  1012. while (TmpShort != 0) {
  1013. NdisRawReadPortUchar( Adapter->IoPAddr + NIC_CRDA_LSB, &Tmp );
  1014. NewAddr = Tmp;
  1015. NdisRawReadPortUchar( Adapter->IoPAddr + NIC_CRDA_MSB, &Tmp );
  1016. NewAddr |= (Tmp << 8);
  1017. if (NewAddr != OldAddr) {
  1018. break;
  1019. }
  1020. NdisStallExecution(1);
  1021. TmpShort--;
  1022. }
  1023. if (NewAddr == OldAddr) {
  1024. NdisWriteErrorLogEntry(
  1025. Adapter->MiniportAdapterHandle,
  1026. NDIS_ERROR_CODE_HARDWARE_FAILURE,
  1027. 2,
  1028. cardCopyDownPacket,
  1029. (ULONG_PTR)XmitBufAddress
  1030. );
  1031. return(FALSE);
  1032. }
  1033. //
  1034. // Set Count and destination address
  1035. //
  1036. NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1037. LSB(PtrToUlong(XmitBufAddress - 1)) );
  1038. NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1039. MSB(PtrToUlong(XmitBufAddress - 1)) );
  1040. NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2 );
  1041. NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0 );
  1042. //
  1043. // Set direction (Write)
  1044. //
  1045. NdisRawWritePortUchar( Adapter->IoPAddr + NIC_COMMAND,
  1046. CR_START | CR_PAGE0 | CR_DMA_WRITE );
  1047. //
  1048. // It seems that the card stores words in LOW:HIGH order
  1049. //
  1050. NdisRawWritePortUshort( Adapter->IoPAddr + NIC_RACK_NIC,
  1051. (USHORT)(Tmp1 | ((*CurBufAddress) << 8)) );
  1052. //
  1053. // Wait for DMA to complete
  1054. //
  1055. Count = 0xFFFF;
  1056. while (Count) {
  1057. NdisRawReadPortUchar( Adapter->IoPAddr + NIC_INTR_STATUS, &Tmp1 );
  1058. if (Tmp1 & ISR_DMA_DONE) {
  1059. break;
  1060. } else {
  1061. Count--;
  1062. NdisStallExecution(4);
  1063. }
  1064. }
  1065. CurBufAddress++;
  1066. XmitBufAddress++;
  1067. PacketLength--;
  1068. CurBufLen--;
  1069. }
  1070. //
  1071. // Do Write errata as described on pages 1-143 and 1-144 of
  1072. // the 1992 LAN databook
  1073. //
  1074. //
  1075. // Set Count and destination address
  1076. //
  1077. ReadBuffer = XmitBufAddress + ((ULONG_PTR)XmitBufAddress & 1);
  1078. OldAddr = NewAddr = (USHORT)(ReadBuffer);
  1079. // NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, // robin
  1080. // CR_PAGE0 // robin
  1081. // ); // robin
  1082. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1083. LSB(PtrToUlong(ReadBuffer))
  1084. );
  1085. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1086. MSB(PtrToUlong(ReadBuffer))
  1087. );
  1088. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
  1089. 0x2
  1090. );
  1091. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
  1092. 0x0
  1093. );
  1094. //
  1095. // Set direction (Read)
  1096. //
  1097. NdisRawWritePortUchar(
  1098. Adapter->IoPAddr + NIC_COMMAND,
  1099. CR_START | CR_PAGE0 | CR_DMA_READ
  1100. );
  1101. if (Adapter->EightBitSlot) {
  1102. //
  1103. // Read from port
  1104. //
  1105. NdisRawReadPortUchar( Adapter->IoPAddr + NIC_RACK_NIC, &Tmp );
  1106. NdisRawReadPortUchar( Adapter->IoPAddr + NIC_RACK_NIC, &Tmp );
  1107. } else {
  1108. //
  1109. // Read from port
  1110. //
  1111. NdisRawReadPortUshort( Adapter->IoPAddr + NIC_RACK_NIC, &TmpShort );
  1112. }
  1113. //
  1114. // Wait for addr to change
  1115. //
  1116. TmpShort = 0xFFFF;
  1117. while (TmpShort != 0) {
  1118. NdisRawReadPortUchar( Adapter->IoPAddr + NIC_CRDA_LSB, &Tmp );
  1119. NewAddr = Tmp;
  1120. NdisRawReadPortUchar( Adapter->IoPAddr + NIC_CRDA_MSB, &Tmp );
  1121. NewAddr |= (Tmp << 8);
  1122. if (NewAddr != OldAddr) {
  1123. break;
  1124. }
  1125. NdisStallExecution(1);
  1126. TmpShort--;
  1127. }
  1128. if (NewAddr == OldAddr) {
  1129. NdisWriteErrorLogEntry(
  1130. Adapter->MiniportAdapterHandle,
  1131. NDIS_ERROR_CODE_HARDWARE_FAILURE,
  1132. 2,
  1133. cardCopyDownPacket,
  1134. (ULONG_PTR)XmitBufAddress
  1135. );
  1136. return(FALSE);
  1137. }
  1138. //
  1139. // Set Count and destination address
  1140. //
  1141. // NdisRawWritePortUchar( Adapter->IoPAddr + NIC_COMMAND, CR_PAGE0 ); // robin
  1142. NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1143. LSB(PtrToUlong(XmitBufAddress)) );
  1144. NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1145. MSB(PtrToUlong(XmitBufAddress)) );
  1146. NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
  1147. LSB(PacketLength) );
  1148. NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
  1149. MSB(PacketLength) );
  1150. //
  1151. // Set direction (Write)
  1152. //
  1153. NdisRawWritePortUchar( Adapter->IoPAddr + NIC_COMMAND,
  1154. CR_START | CR_PAGE0 | CR_DMA_WRITE );
  1155. } // setup
  1156. //
  1157. // Copy the data now
  1158. //
  1159. do {
  1160. UINT Count;
  1161. UCHAR Tmp;
  1162. //
  1163. // Write the previous byte with this one
  1164. //
  1165. if (OddBufLen) {
  1166. //
  1167. // It seems that the card stores words in LOW:HIGH order
  1168. //
  1169. NdisRawWritePortUshort( Adapter->IoPAddr + NIC_RACK_NIC,
  1170. (USHORT)(*OddBufAddress | ((*CurBufAddress) << 8)) );
  1171. OddBufLen = FALSE;
  1172. CurBufAddress++;
  1173. CurBufLen--;
  1174. }
  1175. if (Adapter->EightBitSlot) { // byte mode
  1176. NdisRawWritePortBufferUchar(
  1177. Adapter->IoPAddr + NIC_RACK_NIC,
  1178. CurBufAddress,
  1179. CurBufLen
  1180. );
  1181. } else { // word mode
  1182. NdisRawWritePortBufferUshort(
  1183. Adapter->IoPAddr + NIC_RACK_NIC,
  1184. (PUSHORT)CurBufAddress,
  1185. (CurBufLen >> 1));
  1186. //
  1187. // Save trailing byte (if an odd lengthed transfer)
  1188. //
  1189. if (CurBufLen & 0x1) {
  1190. OddBufAddress = CurBufAddress + (CurBufLen - 1);
  1191. OddBufLen = TRUE;
  1192. }
  1193. }
  1194. //
  1195. // Wait for DMA to complete
  1196. //
  1197. Count = 0xFFFF;
  1198. while (Count) {
  1199. NdisRawReadPortUchar(
  1200. Adapter->IoPAddr + NIC_INTR_STATUS,
  1201. &Tmp );
  1202. if (Tmp & ISR_DMA_DONE) {
  1203. break;
  1204. } else {
  1205. Count--;
  1206. NdisStallExecution(4);
  1207. }
  1208. }
  1209. //
  1210. // Move to the next buffer
  1211. //
  1212. NdisGetNextBuffer(CurBuffer, &CurBuffer);
  1213. if (CurBuffer){
  1214. NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
  1215. }
  1216. //
  1217. // Get address and length of the next buffer
  1218. //
  1219. while (CurBuffer && (CurBufLen == 0)) {
  1220. NdisGetNextBuffer(CurBuffer, &CurBuffer);
  1221. if (CurBuffer){
  1222. NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
  1223. }
  1224. }
  1225. } while (CurBuffer);
  1226. //
  1227. // Write trailing byte (if necessary)
  1228. //
  1229. if (OddBufLen)
  1230. {
  1231. UINT Count;
  1232. UCHAR Tmp;
  1233. USHORT TmpShort;
  1234. if (NE2000_PCMCIA == Adapter->CardType) {
  1235. // NE2000 PCMCIA CHANGE!!! start
  1236. TmpShort = (USHORT)*OddBufAddress;
  1237. NdisRawWritePortUshort(Adapter->IoPAddr + NIC_RACK_NIC, TmpShort);
  1238. // NE2000 PCMCIA CHANGE!!! end
  1239. }
  1240. else {
  1241. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RACK_NIC, *OddBufAddress);
  1242. }
  1243. //
  1244. // Wait for DMA to complete robin-2
  1245. //
  1246. Count = 0xFFFF;
  1247. while (Count) {
  1248. NdisRawReadPortUchar(
  1249. Adapter->IoPAddr + NIC_INTR_STATUS,
  1250. &Tmp );
  1251. if (Tmp & ISR_DMA_DONE) {
  1252. break;
  1253. } else {
  1254. Count--;
  1255. NdisStallExecution(4);
  1256. }
  1257. }
  1258. }
  1259. //
  1260. // Return length written
  1261. //
  1262. *Length = PacketLength;
  1263. return TRUE;
  1264. }
  1265. BOOLEAN
  1266. CardCopyDown(
  1267. IN PNE2000_ADAPTER Adapter,
  1268. IN PUCHAR TargetBuffer,
  1269. IN PUCHAR SourceBuffer,
  1270. IN UINT Length
  1271. )
  1272. /*++
  1273. Routine Description:
  1274. Copies Length bytes from the SourceBuffer to the card buffer space
  1275. at card address TargetBuffer.
  1276. Arguments:
  1277. Adapter - pointer to the adapter block
  1278. SourceBuffer - Buffer in virtual address space
  1279. TargetBuffer - Buffer in card address space
  1280. Length - number of bytes to transfer to card
  1281. Return Value:
  1282. TRUE if the transfer completed with no problems.
  1283. --*/
  1284. {
  1285. //
  1286. // Temporary place holders for odd alignment transfers
  1287. //
  1288. UCHAR Tmp, TmpSave;
  1289. USHORT TmpShort;
  1290. //
  1291. // Values for waiting for noticing when a DMA completes.
  1292. //
  1293. USHORT OldAddr, NewAddr;
  1294. //
  1295. // Count of transfers to do
  1296. //
  1297. USHORT Count;
  1298. //
  1299. // Address the copy if coming from
  1300. //
  1301. PUCHAR ReadBuffer;
  1302. //
  1303. // Skip 0 length copies
  1304. //
  1305. if (Length == 0) {
  1306. return(TRUE);
  1307. }
  1308. if (!Adapter->EightBitSlot && ((ULONG_PTR)TargetBuffer & 0x1)) {
  1309. //
  1310. // For odd addresses we need to read first to get the previous
  1311. // byte and then merge it with our first byte.
  1312. //
  1313. //
  1314. // Set Count and Source address
  1315. //
  1316. NdisRawWritePortUchar(
  1317. Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1318. LSB(PtrToUlong(TargetBuffer - 1))
  1319. );
  1320. NdisRawWritePortUchar(
  1321. Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1322. MSB(PtrToUlong(TargetBuffer - 1))
  1323. );
  1324. // NE2000 PCMCIA CHANGE!!! start
  1325. //NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x1);
  1326. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2);
  1327. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0);
  1328. // NE2000 PCMCIA CHANGE!!! end
  1329. //
  1330. // Set direction (Read)
  1331. //
  1332. NdisRawWritePortUchar(
  1333. Adapter->IoPAddr + NIC_COMMAND,
  1334. CR_START | CR_PAGE0 | CR_DMA_READ
  1335. );
  1336. // NE2000 PCMCIA CHANGE!!! start
  1337. //NdisRawReadPortUchar(Adapter->IoPAddr + NIC_RACK_NIC, &TmpSave);
  1338. NdisRawReadPortUshort(Adapter->IoPAddr + NIC_RACK_NIC, &TmpShort);
  1339. TmpSave = LSB(TmpShort);
  1340. // NE2000 PCMCIA CHANGE!!! end
  1341. //
  1342. // Do Write errata as described on pages 1-143 and 1-144 of the 1992
  1343. // LAN databook
  1344. //
  1345. //
  1346. // Set Count and destination address
  1347. //
  1348. ReadBuffer = TargetBuffer + ((ULONG_PTR)TargetBuffer & 1);
  1349. OldAddr = NewAddr = (USHORT)(ReadBuffer);
  1350. // NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_PAGE0); // robin
  1351. NdisRawWritePortUchar(
  1352. Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1353. LSB(PtrToUlong(ReadBuffer))
  1354. );
  1355. NdisRawWritePortUchar(
  1356. Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1357. MSB(PtrToUlong(ReadBuffer))
  1358. );
  1359. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2);
  1360. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0);
  1361. //
  1362. // Set direction (Read)
  1363. //
  1364. NdisRawWritePortUchar(
  1365. Adapter->IoPAddr + NIC_COMMAND,
  1366. CR_START | CR_PAGE0 | CR_DMA_READ
  1367. );
  1368. //
  1369. // Read from port
  1370. //
  1371. NdisRawReadPortUshort(Adapter->IoPAddr + NIC_RACK_NIC, &TmpShort);
  1372. //
  1373. // Wait for addr to change
  1374. //
  1375. TmpShort = 0xFFFF;
  1376. while (TmpShort != 0) {
  1377. NdisRawReadPortUchar(
  1378. Adapter->IoPAddr + NIC_CRDA_LSB,
  1379. &Tmp
  1380. );
  1381. NewAddr = Tmp;
  1382. NdisRawReadPortUchar(
  1383. Adapter->IoPAddr + NIC_CRDA_MSB,
  1384. &Tmp
  1385. );
  1386. NewAddr |= (Tmp << 8);
  1387. if (NewAddr != OldAddr) {
  1388. break;
  1389. }
  1390. NdisStallExecution(1);
  1391. TmpShort--;
  1392. }
  1393. if (NewAddr == OldAddr) {
  1394. return(FALSE);
  1395. }
  1396. //
  1397. // Set Count and destination address
  1398. //
  1399. NdisRawWritePortUchar(
  1400. Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1401. LSB(PtrToUlong(TargetBuffer - 1))
  1402. );
  1403. NdisRawWritePortUchar(
  1404. Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1405. MSB(PtrToUlong(TargetBuffer - 1))
  1406. );
  1407. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2);
  1408. NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0);
  1409. //
  1410. // Set direction (Write)
  1411. //
  1412. NdisRawWritePortUchar(
  1413. Adapter->IoPAddr + NIC_COMMAND,
  1414. CR_START | CR_PAGE0 | CR_DMA_WRITE
  1415. );
  1416. //
  1417. // It seems that the card stores words in LOW:HIGH order
  1418. //
  1419. NdisRawWritePortUshort(
  1420. Adapter->IoPAddr + NIC_RACK_NIC,
  1421. (USHORT)(TmpSave | ((*SourceBuffer) << 8))
  1422. );
  1423. //
  1424. // Wait for DMA to complete
  1425. //
  1426. Count = 0xFFFF;
  1427. while (Count) {
  1428. NdisRawReadPortUchar(
  1429. Adapter->IoPAddr + NIC_INTR_STATUS,
  1430. &Tmp
  1431. );
  1432. if (Tmp & ISR_DMA_DONE) {
  1433. break;
  1434. } else {
  1435. Count--;
  1436. NdisStallExecution(4);
  1437. }
  1438. }
  1439. SourceBuffer++;
  1440. TargetBuffer++;
  1441. Length--;
  1442. }
  1443. //
  1444. // Do Write errata as described on pages 1-143 and 1-144 of the 1992
  1445. // LAN databook
  1446. //
  1447. //
  1448. // Set Count and destination address
  1449. //
  1450. ReadBuffer = TargetBuffer + ((ULONG_PTR)TargetBuffer & 1);
  1451. OldAddr = NewAddr = (USHORT)(ReadBuffer);
  1452. // NdisRawWritePortUchar( // robin
  1453. // Adapter->IoPAddr + NIC_COMMAND, // robin
  1454. // CR_PAGE0 // robin
  1455. // ); // robin
  1456. NdisRawWritePortUchar(
  1457. Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1458. LSB(PtrToUlong(ReadBuffer))
  1459. );
  1460. NdisRawWritePortUchar(
  1461. Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1462. MSB(PtrToUlong(ReadBuffer))
  1463. );
  1464. NdisRawWritePortUchar(
  1465. Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
  1466. 0x2
  1467. );
  1468. NdisRawWritePortUchar(
  1469. Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
  1470. 0x0
  1471. );
  1472. //
  1473. // Set direction (Read)
  1474. //
  1475. NdisRawWritePortUchar(
  1476. Adapter->IoPAddr + NIC_COMMAND,
  1477. CR_START | CR_PAGE0 | CR_DMA_READ
  1478. );
  1479. if (Adapter->EightBitSlot) {
  1480. //
  1481. // Read from port
  1482. //
  1483. NdisRawReadPortUchar(
  1484. Adapter->IoPAddr + NIC_RACK_NIC,
  1485. &Tmp
  1486. );
  1487. NdisRawReadPortUchar(
  1488. Adapter->IoPAddr + NIC_RACK_NIC,
  1489. &Tmp
  1490. );
  1491. } else {
  1492. //
  1493. // Read from port
  1494. //
  1495. NdisRawReadPortUshort(
  1496. Adapter->IoPAddr + NIC_RACK_NIC,
  1497. &TmpShort
  1498. );
  1499. }
  1500. //
  1501. // Wait for addr to change
  1502. //
  1503. TmpShort = 0xFFFF;
  1504. while (TmpShort != 0) {
  1505. NdisRawReadPortUchar(
  1506. Adapter->IoPAddr + NIC_CRDA_LSB,
  1507. &Tmp
  1508. );
  1509. NewAddr = Tmp;
  1510. NdisRawReadPortUchar(
  1511. Adapter->IoPAddr + NIC_CRDA_MSB,
  1512. &Tmp
  1513. );
  1514. NewAddr |= (Tmp << 8);
  1515. if (NewAddr != OldAddr) {
  1516. break;
  1517. }
  1518. NdisStallExecution(1);
  1519. TmpShort--;
  1520. }
  1521. if (NewAddr == OldAddr) {
  1522. return(FALSE);
  1523. }
  1524. //
  1525. // Set Count and destination address
  1526. //
  1527. // NdisRawWritePortUchar( // robin
  1528. // Adapter->IoPAddr + NIC_COMMAND, // robin
  1529. // CR_PAGE0 // robin
  1530. // ); // robin
  1531. NdisRawWritePortUchar(
  1532. Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1533. LSB(PtrToUlong(TargetBuffer))
  1534. );
  1535. NdisRawWritePortUchar(
  1536. Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1537. MSB(PtrToUlong(TargetBuffer))
  1538. );
  1539. NdisRawWritePortUchar(
  1540. Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
  1541. LSB(Length)
  1542. );
  1543. NdisRawWritePortUchar(
  1544. Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
  1545. MSB(Length)
  1546. );
  1547. //
  1548. // Set direction (Write)
  1549. //
  1550. NdisRawWritePortUchar(
  1551. Adapter->IoPAddr + NIC_COMMAND,
  1552. CR_START | CR_PAGE0 | CR_DMA_WRITE
  1553. );
  1554. if (Adapter->EightBitSlot) {
  1555. //
  1556. // Repeatedly write to out port
  1557. //
  1558. NdisRawWritePortBufferUchar(
  1559. Adapter->IoPAddr + NIC_RACK_NIC,
  1560. SourceBuffer,
  1561. Length);
  1562. } else {
  1563. //
  1564. // Write words to out ports
  1565. //
  1566. NdisRawWritePortBufferUshort(
  1567. Adapter->IoPAddr + NIC_RACK_NIC,
  1568. (PUSHORT)SourceBuffer,
  1569. (Length >> 1));
  1570. //
  1571. // Write trailing byte (if necessary)
  1572. //
  1573. if (Length & 0x1)
  1574. {
  1575. SourceBuffer += (Length - 1);
  1576. // NE2000 PCMCIA CHANGE!!! start
  1577. //NdisRawWritePortUchar(
  1578. // Adapter->IoPAddr + NIC_RACK_NIC,
  1579. // *SourceBuffer
  1580. //);
  1581. TmpShort = (USHORT)(*SourceBuffer);
  1582. NdisRawWritePortUshort(
  1583. Adapter->IoPAddr + NIC_RACK_NIC,
  1584. TmpShort
  1585. );
  1586. // NE2000 PCMCIA CHANGE!!! end
  1587. }
  1588. }
  1589. //
  1590. // Wait for DMA to complete
  1591. //
  1592. Count = 0xFFFF;
  1593. while (Count) {
  1594. NdisRawReadPortUchar(
  1595. Adapter->IoPAddr + NIC_INTR_STATUS,
  1596. &Tmp
  1597. );
  1598. if (Tmp & ISR_DMA_DONE) {
  1599. break;
  1600. } else {
  1601. Count--;
  1602. NdisStallExecution(4);
  1603. }
  1604. #if DBG
  1605. if (!(Tmp & ISR_DMA_DONE)) {
  1606. DbgPrint("CopyDownDMA didn't finish!");
  1607. }
  1608. #endif // DBG
  1609. }
  1610. IF_LOG(Ne2000Log('>');)
  1611. return TRUE;
  1612. }
  1613. BOOLEAN
  1614. CardCopyUp(
  1615. IN PNE2000_ADAPTER Adapter,
  1616. IN PUCHAR TargetBuffer,
  1617. IN PUCHAR SourceBuffer,
  1618. IN UINT BufferLength
  1619. )
  1620. /*++
  1621. Routine Description:
  1622. Copies data from the card to memory.
  1623. Arguments:
  1624. Adapter - pointer to the adapter block
  1625. Target - the target address
  1626. Source - the source address (on the card)
  1627. BufferLength - the number of bytes to copy
  1628. Return Value:
  1629. TRUE if the transfer completed with no problems.
  1630. --*/
  1631. {
  1632. //
  1633. // Used to check when the dma is done
  1634. //
  1635. UCHAR IsrValue;
  1636. //
  1637. // Count of the number of transfers to do
  1638. //
  1639. USHORT Count;
  1640. //
  1641. // Place holder for port values
  1642. //
  1643. UCHAR Temp;
  1644. if (BufferLength == 0) {
  1645. return TRUE;
  1646. }
  1647. //
  1648. // Read the Command Register, to make sure it is ready for a write
  1649. //
  1650. NdisRawReadPortUchar(Adapter->IoPAddr+NIC_COMMAND, &Temp);
  1651. if (Adapter->EightBitSlot) {
  1652. //
  1653. // If byte mode
  1654. //
  1655. //
  1656. // Set Count and destination address
  1657. //
  1658. // NdisRawWritePortUchar( // robin
  1659. // Adapter->IoPAddr + NIC_COMMAND, // robin
  1660. // CR_PAGE0 // robin
  1661. // ); // robin
  1662. NdisRawWritePortUchar(
  1663. Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1664. LSB(PtrToUlong(SourceBuffer))
  1665. );
  1666. NdisRawWritePortUchar(
  1667. Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1668. MSB(PtrToUlong(SourceBuffer))
  1669. );
  1670. NdisRawWritePortUchar(
  1671. Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
  1672. LSB(BufferLength)
  1673. );
  1674. NdisRawWritePortUchar(
  1675. Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
  1676. MSB(BufferLength)
  1677. );
  1678. //
  1679. // Set direction (Read)
  1680. //
  1681. NdisRawWritePortUchar(
  1682. Adapter->IoPAddr + NIC_COMMAND,
  1683. CR_START | CR_PAGE0 | CR_DMA_READ
  1684. );
  1685. //
  1686. // Repeatedly read from port
  1687. //
  1688. NdisRawReadPortBufferUchar(
  1689. Adapter->IoPAddr + NIC_RACK_NIC,
  1690. TargetBuffer,
  1691. BufferLength
  1692. );
  1693. } else {
  1694. //
  1695. // Else word mode
  1696. //
  1697. USHORT Tmp;
  1698. // NdisRawWritePortUchar( // robin
  1699. // Adapter->IoPAddr + NIC_COMMAND, // robin
  1700. // CR_PAGE0 // robin
  1701. // ); // robin
  1702. //
  1703. // Avoid transfers to odd addresses
  1704. //
  1705. if ((ULONG_PTR)SourceBuffer & 0x1) {
  1706. //
  1707. // For odd addresses we need to read previous word and store the
  1708. // second byte
  1709. //
  1710. //
  1711. // Set Count and Source address
  1712. //
  1713. NdisRawWritePortUchar(
  1714. Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1715. LSB(PtrToUlong(SourceBuffer - 1))
  1716. );
  1717. NdisRawWritePortUchar(
  1718. Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1719. MSB(PtrToUlong(SourceBuffer - 1))
  1720. );
  1721. NdisRawWritePortUchar(
  1722. Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
  1723. 0x2
  1724. );
  1725. NdisRawWritePortUchar(
  1726. Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
  1727. 0x0
  1728. );
  1729. //
  1730. // Set direction (Read)
  1731. //
  1732. NdisRawWritePortUchar(
  1733. Adapter->IoPAddr + NIC_COMMAND,
  1734. CR_START | CR_PAGE0 | CR_DMA_READ
  1735. );
  1736. NdisRawReadPortUshort(
  1737. Adapter->IoPAddr + NIC_RACK_NIC,
  1738. &Tmp
  1739. );
  1740. *TargetBuffer = MSB(Tmp);
  1741. //
  1742. // Wait for DMA to complete
  1743. //
  1744. Count = 0xFFFF;
  1745. while (Count) {
  1746. NdisRawReadPortUchar(
  1747. Adapter->IoPAddr + NIC_INTR_STATUS,
  1748. &IsrValue
  1749. );
  1750. if (IsrValue & ISR_DMA_DONE) {
  1751. break;
  1752. } else {
  1753. Count--;
  1754. NdisStallExecution(4);
  1755. }
  1756. #if DBG
  1757. if (!(IsrValue & ISR_DMA_DONE)) {
  1758. DbgPrint("CopyUpDMA didn't finish!");
  1759. }
  1760. #endif // DBG
  1761. }
  1762. SourceBuffer++;
  1763. TargetBuffer++;
  1764. BufferLength--;
  1765. }
  1766. //
  1767. // Set Count and destination address
  1768. //
  1769. NdisRawWritePortUchar(
  1770. Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1771. LSB(PtrToUlong(SourceBuffer))
  1772. );
  1773. NdisRawWritePortUchar(
  1774. Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1775. MSB(PtrToUlong(SourceBuffer))
  1776. );
  1777. // NE2000 PCMCIA CHANGE!!! start
  1778. // NdisRawWritePortUchar(
  1779. // Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
  1780. // LSB(BufferLength)
  1781. // );
  1782. //
  1783. // NdisRawWritePortUchar(
  1784. // Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
  1785. // MSB(BufferLength)
  1786. // );
  1787. if (BufferLength & 1)
  1788. {
  1789. NdisRawWritePortUchar(
  1790. Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
  1791. LSB(BufferLength + 1)
  1792. );
  1793. NdisRawWritePortUchar(
  1794. Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
  1795. MSB(BufferLength + 1)
  1796. );
  1797. }
  1798. else
  1799. {
  1800. NdisRawWritePortUchar(
  1801. Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
  1802. LSB(BufferLength)
  1803. );
  1804. NdisRawWritePortUchar(
  1805. Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
  1806. MSB(BufferLength)
  1807. );
  1808. }
  1809. // NE2000 PCMCIA CHANGE!!! end
  1810. //
  1811. // Set direction (Read)
  1812. //
  1813. NdisRawWritePortUchar(
  1814. Adapter->IoPAddr + NIC_COMMAND,
  1815. CR_START | CR_PAGE0 | CR_DMA_READ
  1816. );
  1817. //
  1818. // Read words from port
  1819. //
  1820. NdisRawReadPortBufferUshort(
  1821. Adapter->IoPAddr + NIC_RACK_NIC,
  1822. (PUSHORT)TargetBuffer,
  1823. (BufferLength >> 1));
  1824. //
  1825. // Read trailing byte (if necessary)
  1826. //
  1827. if (BufferLength & 1) {
  1828. TargetBuffer += (BufferLength - 1);
  1829. // NE2000 PCMCIA CHANGE!!! start
  1830. //NdisRawReadPortUchar(
  1831. // Adapter->IoPAddr + NIC_RACK_NIC,
  1832. // TargetBuffer
  1833. //);
  1834. NdisRawReadPortUshort(
  1835. Adapter->IoPAddr + NIC_RACK_NIC,
  1836. &Tmp
  1837. );
  1838. *TargetBuffer = LSB(Tmp);
  1839. // NE2000 PCMCIA CHANGE!!! end
  1840. }
  1841. }
  1842. //
  1843. // Wait for DMA to complete
  1844. //
  1845. Count = 0xFFFF;
  1846. while (Count) {
  1847. NdisRawReadPortUchar(
  1848. Adapter->IoPAddr + NIC_INTR_STATUS,
  1849. &IsrValue
  1850. );
  1851. if (IsrValue & ISR_DMA_DONE) {
  1852. break;
  1853. } else {
  1854. Count--;
  1855. NdisStallExecution(4);
  1856. }
  1857. }
  1858. #if DBG
  1859. if (!(IsrValue & ISR_DMA_DONE)) {
  1860. DbgPrint("CopyUpDMA didn't finish!\n");
  1861. }
  1862. IF_LOG(Ne2000Log('<');)
  1863. #endif // DBG
  1864. return TRUE;
  1865. }
  1866. ULONG
  1867. CardComputeCrc(
  1868. IN PUCHAR Buffer,
  1869. IN UINT Length
  1870. )
  1871. /*++
  1872. Routine Description:
  1873. Runs the AUTODIN II CRC algorithm on buffer Buffer of
  1874. length Length.
  1875. Arguments:
  1876. Buffer - the input buffer
  1877. Length - the length of Buffer
  1878. Return Value:
  1879. The 32-bit CRC value.
  1880. Note:
  1881. This is adapted from the comments in the assembly language
  1882. version in _GENREQ.ASM of the DWB NE1000/2000 driver.
  1883. --*/
  1884. {
  1885. ULONG Crc, Carry;
  1886. UINT i, j;
  1887. UCHAR CurByte;
  1888. Crc = 0xffffffff;
  1889. for (i = 0; i < Length; i++) {
  1890. CurByte = Buffer[i];
  1891. for (j = 0; j < 8; j++) {
  1892. Carry = ((Crc & 0x80000000) ? 1 : 0) ^ (CurByte & 0x01);
  1893. Crc <<= 1;
  1894. CurByte >>= 1;
  1895. if (Carry) {
  1896. Crc = (Crc ^ 0x04c11db6) | Carry;
  1897. }
  1898. }
  1899. }
  1900. return Crc;
  1901. }
  1902. VOID
  1903. CardGetMulticastBit(
  1904. IN UCHAR Address[NE2000_LENGTH_OF_ADDRESS],
  1905. OUT UCHAR * Byte,
  1906. OUT UCHAR * Value
  1907. )
  1908. /*++
  1909. Routine Description:
  1910. For a given multicast address, returns the byte and bit in
  1911. the card multicast registers that it hashes to. Calls
  1912. CardComputeCrc() to determine the CRC value.
  1913. Arguments:
  1914. Address - the address
  1915. Byte - the byte that it hashes to
  1916. Value - will have a 1 in the relevant bit
  1917. Return Value:
  1918. None.
  1919. --*/
  1920. {
  1921. ULONG Crc;
  1922. UINT BitNumber;
  1923. //
  1924. // First compute the CRC.
  1925. //
  1926. Crc = CardComputeCrc(Address, NE2000_LENGTH_OF_ADDRESS);
  1927. //
  1928. // The bit number is now in the 6 most significant bits of CRC.
  1929. //
  1930. BitNumber = (UINT)((Crc >> 26) & 0x3f);
  1931. *Byte = (UCHAR)(BitNumber / 8);
  1932. *Value = (UCHAR)((UCHAR)1 << (BitNumber % 8));
  1933. }
  1934. VOID
  1935. CardFillMulticastRegs(
  1936. IN PNE2000_ADAPTER Adapter
  1937. )
  1938. /*++
  1939. Routine Description:
  1940. Erases and refills the card multicast registers. Used when
  1941. an address has been deleted and all bits must be recomputed.
  1942. Arguments:
  1943. Adapter - pointer to the adapter block
  1944. Return Value:
  1945. None.
  1946. --*/
  1947. {
  1948. UINT i;
  1949. UCHAR Byte, Bit;
  1950. //
  1951. // First turn all bits off.
  1952. //
  1953. for (i=0; i<8; i++) {
  1954. Adapter->NicMulticastRegs[i] = 0;
  1955. }
  1956. //
  1957. // Now turn on the bit for each address in the multicast list.
  1958. //
  1959. for ( ; i > 0; ) {
  1960. i--;
  1961. CardGetMulticastBit(Adapter->Addresses[i], &Byte, &Bit);
  1962. Adapter->NicMulticastRegs[Byte] |= Bit;
  1963. }
  1964. }
  1965. BOOLEAN SyncCardStop(
  1966. IN PVOID SynchronizeContext
  1967. )
  1968. /*++
  1969. Routine Description:
  1970. Sets the NIC_COMMAND register to stop the card.
  1971. Arguments:
  1972. SynchronizeContext - pointer to the adapter block
  1973. Return Value:
  1974. TRUE if the power has failed.
  1975. --*/
  1976. {
  1977. PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)SynchronizeContext);
  1978. NdisRawWritePortUchar(
  1979. Adapter->IoPAddr + NIC_COMMAND,
  1980. CR_STOP | CR_NO_DMA
  1981. );
  1982. return(FALSE);
  1983. }
  1984. VOID
  1985. CardStartXmit(
  1986. IN PNE2000_ADAPTER Adapter
  1987. )
  1988. /*++
  1989. Routine Description:
  1990. Sets the NIC_COMMAND register to start a transmission.
  1991. The transmit buffer number is taken from Adapter->CurBufXmitting
  1992. and the length from Adapter->PacketLens[Adapter->CurBufXmitting].
  1993. Arguments:
  1994. Adapter - pointer to the adapter block
  1995. Return Value:
  1996. TRUE if the power has failed.
  1997. --*/
  1998. {
  1999. UINT Length = Adapter->PacketLens[Adapter->CurBufXmitting];
  2000. UCHAR Tmp;
  2001. //
  2002. // Prepare the NIC registers for transmission.
  2003. //
  2004. NdisRawWritePortUchar(Adapter->IoPAddr+NIC_XMIT_START,
  2005. (UCHAR)(Adapter->NicXmitStart + (UCHAR)(Adapter->CurBufXmitting*BUFS_PER_TX)));
  2006. //
  2007. // Pad the length to 60 (plus CRC will be 64) if needed.
  2008. //
  2009. if (Length < 60) {
  2010. Length = 60;
  2011. }
  2012. NdisRawWritePortUchar(Adapter->IoPAddr+NIC_XMIT_COUNT_MSB, MSB(Length));
  2013. NdisRawWritePortUchar(Adapter->IoPAddr+NIC_XMIT_COUNT_LSB, LSB(Length));
  2014. //
  2015. // Start transmission, check for power failure first.
  2016. //
  2017. NdisRawReadPortUchar(Adapter->IoPAddr+NIC_COMMAND, &Tmp);
  2018. NdisRawWritePortUchar(Adapter->IoPAddr+NIC_COMMAND,
  2019. CR_START | CR_XMIT | CR_NO_DMA);
  2020. IF_LOG( Ne2000Log('x');)
  2021. }
  2022. BOOLEAN
  2023. SyncCardGetCurrent(
  2024. IN PVOID SynchronizeContext
  2025. )
  2026. /*++
  2027. Routine Description:
  2028. Gets the value of the CURRENT NIC register and stores it in Adapter->Current
  2029. Arguments:
  2030. SynchronizeContext - pointer to the adapter block
  2031. Return Value:
  2032. None.
  2033. --*/
  2034. {
  2035. PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)SynchronizeContext);
  2036. //
  2037. // Have to go to page 1 to read this register
  2038. //
  2039. NdisRawWritePortUchar(Adapter->IoPAddr+NIC_COMMAND,
  2040. CR_START | CR_NO_DMA | CR_PAGE1);
  2041. NdisRawReadPortUchar(Adapter->IoPAddr+NIC_CURRENT,
  2042. &Adapter->Current);
  2043. NdisRawWritePortUchar(Adapter->IoPAddr+NIC_COMMAND,
  2044. CR_START | CR_NO_DMA | CR_PAGE0);
  2045. return FALSE;
  2046. }
  2047. BOOLEAN
  2048. SyncCardGetXmitStatus(
  2049. IN PVOID SynchronizeContext
  2050. )
  2051. /*++
  2052. Routine Description:
  2053. Gets the value of the "transmit status" NIC register and stores
  2054. it in Adapter->XmitStatus.
  2055. Arguments:
  2056. SynchronizeContext - pointer to the adapter block
  2057. Return Value:
  2058. None.
  2059. --*/
  2060. {
  2061. PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)SynchronizeContext);
  2062. NdisRawReadPortUchar( Adapter->IoPAddr+NIC_XMIT_STATUS, &Adapter->XmitStatus);
  2063. return FALSE;
  2064. }
  2065. VOID
  2066. CardSetBoundary(
  2067. IN PNE2000_ADAPTER Adapter
  2068. )
  2069. /*++
  2070. Routine Description:
  2071. Sets the value of the "boundary" NIC register to one behind
  2072. Adapter->NicNextPacket, to prevent packets from being received
  2073. on top of un-indicated ones.
  2074. Arguments:
  2075. Adapter - pointer to the adapter block
  2076. Return Value:
  2077. None.
  2078. --*/
  2079. {
  2080. //
  2081. // Have to be careful with "one behind NicNextPacket" when
  2082. // NicNextPacket is the first buffer in receive area.
  2083. //
  2084. if (Adapter->NicNextPacket == Adapter->NicPageStart) {
  2085. NdisRawWritePortUchar( Adapter->IoPAddr+NIC_BOUNDARY,
  2086. (UCHAR)(Adapter->NicPageStop-(UCHAR)1));
  2087. } else {
  2088. NdisRawWritePortUchar( Adapter->IoPAddr+NIC_BOUNDARY,
  2089. (UCHAR)(Adapter->NicNextPacket-(UCHAR)1));
  2090. }
  2091. }
  2092. BOOLEAN
  2093. SyncCardSetReceiveConfig(
  2094. IN PVOID SynchronizeContext
  2095. )
  2096. /*++
  2097. Routine Description:
  2098. Sets the value of the "receive configuration" NIC register to
  2099. the value of Adapter->NicReceiveConfig.
  2100. Arguments:
  2101. SynchronizeContext - pointer to the adapter block
  2102. Return Value:
  2103. None.
  2104. --*/
  2105. {
  2106. PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)SynchronizeContext);
  2107. NdisRawWritePortUchar( Adapter->IoPAddr+NIC_RCV_CONFIG, Adapter->NicReceiveConfig);
  2108. return FALSE;
  2109. }
  2110. BOOLEAN
  2111. SyncCardSetAllMulticast(
  2112. IN PVOID SynchronizeContext
  2113. )
  2114. /*++
  2115. Routine Description:
  2116. Turns on all the bits in the multicast register. Used when
  2117. the card must receive all multicast packets.
  2118. Arguments:
  2119. SynchronizeContext - pointer to the adapter block
  2120. Return Value:
  2121. None.
  2122. --*/
  2123. {
  2124. PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)SynchronizeContext);
  2125. UINT i;
  2126. //
  2127. // Have to move to page 1 to set these registers.
  2128. //
  2129. NdisRawWritePortUchar( Adapter->IoPAddr+NIC_COMMAND,
  2130. CR_START | CR_NO_DMA | CR_PAGE1);
  2131. for (i=0; i<8; i++) {
  2132. NdisRawWritePortUchar( Adapter->IoPAddr+(NIC_MC_ADDR+i), 0xff);
  2133. }
  2134. NdisRawWritePortUchar( Adapter->IoPAddr+NIC_COMMAND,
  2135. CR_START | CR_NO_DMA | CR_PAGE0);
  2136. return FALSE;
  2137. }
  2138. BOOLEAN
  2139. SyncCardCopyMulticastRegs(
  2140. IN PVOID SynchronizeContext
  2141. )
  2142. /*++
  2143. Routine Description:
  2144. Sets the eight bytes in the card multicast registers.
  2145. Arguments:
  2146. SynchronizeContext - pointer to the adapter block
  2147. Return Value:
  2148. None.
  2149. --*/
  2150. {
  2151. PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)SynchronizeContext);
  2152. UINT i;
  2153. //
  2154. // Have to move to page 1 to set these registers.
  2155. //
  2156. NdisRawWritePortUchar( Adapter->IoPAddr+NIC_COMMAND,
  2157. CR_START | CR_NO_DMA | CR_PAGE1);
  2158. for (i=0; i<8; i++) {
  2159. NdisRawWritePortUchar( Adapter->IoPAddr+(NIC_MC_ADDR+i),
  2160. Adapter->NicMulticastRegs[i]);
  2161. }
  2162. NdisRawWritePortUchar( Adapter->IoPAddr+NIC_COMMAND,
  2163. CR_START | CR_NO_DMA | CR_PAGE0);
  2164. return FALSE;
  2165. }
  2166. BOOLEAN
  2167. SyncCardAcknowledgeOverflow(
  2168. IN PVOID SynchronizeContext
  2169. )
  2170. /*++
  2171. Routine Description:
  2172. Sets the "buffer overflow" bit in the NIC interrupt status register,
  2173. which re-enables interrupts of that type.
  2174. Arguments:
  2175. SynchronizeContext - pointer to the adapter block
  2176. Return Value:
  2177. None.
  2178. --*/
  2179. {
  2180. PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)SynchronizeContext);
  2181. UCHAR AcknowledgeMask = 0;
  2182. if (Adapter->InterruptStatus & ISR_RCV_ERR) {
  2183. SyncCardUpdateCounters(Adapter);
  2184. }
  2185. return FALSE;
  2186. }
  2187. BOOLEAN
  2188. SyncCardUpdateCounters(
  2189. IN PVOID SynchronizeContext
  2190. )
  2191. /*++
  2192. Routine Description:
  2193. Updates the values of the three counters (frame alignment errors,
  2194. CRC errors, and missed packets).
  2195. Arguments:
  2196. SynchronizeContext - pointer to the adapter block
  2197. Return Value:
  2198. None.
  2199. --*/
  2200. {
  2201. PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)SynchronizeContext);
  2202. UCHAR Tmp;
  2203. NdisRawReadPortUchar( Adapter->IoPAddr+NIC_FAE_ERR_CNTR, &Tmp);
  2204. Adapter->FrameAlignmentErrors += Tmp;
  2205. NdisRawReadPortUchar( Adapter->IoPAddr+NIC_CRC_ERR_CNTR, &Tmp);
  2206. Adapter->CrcErrors += Tmp;
  2207. NdisRawReadPortUchar( Adapter->IoPAddr+NIC_MISSED_CNTR, &Tmp);
  2208. Adapter->MissedPackets += Tmp;
  2209. return FALSE;
  2210. }
  2211. BOOLEAN
  2212. SyncCardHandleOverflow(
  2213. IN PVOID SynchronizeContext
  2214. )
  2215. /*++<
  2216. Routine Description:
  2217. Sets all the flags for dealing with a receive overflow, stops the card
  2218. and acknowledges all outstanding interrupts.
  2219. Arguments:
  2220. SynchronizeContext - pointer to the adapter block
  2221. Return Value:
  2222. None.
  2223. --*/
  2224. {
  2225. PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)SynchronizeContext);
  2226. UCHAR Status;
  2227. IF_LOG( Ne2000Log('F');)
  2228. //
  2229. // Turn on the STOP bit in the Command register.
  2230. //
  2231. SyncCardStop(Adapter);
  2232. //
  2233. // Wait for ISR_RESET, but only for 1.6 milliseconds (as
  2234. // described in the March 1991 8390 addendum), since that
  2235. // is the maximum time for a software reset to occur.
  2236. //
  2237. //
  2238. NdisStallExecution(2000);
  2239. //
  2240. // Save whether we were transmitting to avoid a timing problem
  2241. // where an indication resulted in a send.
  2242. //
  2243. if (!(Adapter->InterruptStatus & (ISR_XMIT | ISR_XMIT_ERR))) {
  2244. CardGetInterruptStatus(Adapter,&Status);
  2245. if (!(Status & (ISR_XMIT | ISR_XMIT_ERR))) {
  2246. Adapter->OverflowRestartXmitDpc = Adapter->TransmitInterruptPending;
  2247. IF_LOUD( DbgPrint("ORXD=%x\n",Adapter->OverflowRestartXmitDpc); )
  2248. }
  2249. }
  2250. Adapter->TransmitInterruptPending = FALSE;
  2251. //
  2252. // Clear the Remote Byte Count register so that ISR_RESET
  2253. // will come on.
  2254. //
  2255. NdisRawWritePortUchar( Adapter->IoPAddr+NIC_RMT_COUNT_MSB, 0);
  2256. NdisRawWritePortUchar( Adapter->IoPAddr+NIC_RMT_COUNT_LSB, 0);
  2257. //
  2258. // According to National Semiconductor, the next check is necessary
  2259. // See Step 5. of the overflow process
  2260. //
  2261. // NOTE: The setting of variables to check if the transmit has completed
  2262. // cannot be done here because anything in the ISR has already been ack'ed
  2263. // inside the main DPC. Thus, the setting of the variables, described in
  2264. // the Handbook was moved to the main DPC.
  2265. //
  2266. // Continued: If you did the check here, you will doubly transmit most
  2267. // packets that happened to be on the card when the overflow occurred.
  2268. //
  2269. //
  2270. // Put the card in loopback mode, then start it.
  2271. //
  2272. NdisRawWritePortUchar( Adapter->IoPAddr+NIC_XMIT_CONFIG, TCR_LOOPBACK);
  2273. //
  2274. // Start the card. This does not Undo the loopback mode.
  2275. //
  2276. NdisRawWritePortUchar( Adapter->IoPAddr+NIC_COMMAND, CR_START | CR_NO_DMA);
  2277. return FALSE;
  2278. }