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.

1805 lines
42 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. reset.c
  5. Abstract:
  6. This is the file containing the reset code for the Novell NE3200 EISA
  7. Ethernet adapter. This driver conforms to the NDIS 3.0 miniport
  8. interface.
  9. Author:
  10. Keith Moore (KeithMo) 08-Jan-1991
  11. Environment:
  12. Revision History:
  13. --*/
  14. #include <ne3200sw.h>
  15. //
  16. // Global information stored in ne3200.c. This is used for
  17. // getting at the download software
  18. //
  19. extern NE3200_GLOBAL_DATA NE3200Globals;
  20. //
  21. // Forward declarations of functions in this file
  22. //
  23. extern
  24. VOID
  25. NE3200ProcessRequestQueue(
  26. IN PNE3200_ADAPTER Adapter,
  27. IN BOOLEAN StatisticsUpdated
  28. );
  29. STATIC
  30. VOID
  31. NE3200SetConfigurationBlock(
  32. IN PNE3200_ADAPTER Adapter
  33. );
  34. STATIC
  35. BOOLEAN
  36. NE3200SetConfigurationBlockAndInit(
  37. IN PNE3200_ADAPTER Adapter
  38. );
  39. NDIS_STATUS
  40. NE3200ChangeCurrentAddress(
  41. IN PNE3200_ADAPTER Adapter
  42. );
  43. VOID
  44. NE3200ResetCommandBlocks(
  45. IN PNE3200_ADAPTER Adapter
  46. );
  47. extern
  48. VOID
  49. NE3200GetStationAddress(
  50. IN PNE3200_ADAPTER Adapter
  51. );
  52. extern
  53. VOID
  54. NE3200SetupForReset(
  55. IN PNE3200_ADAPTER Adapter
  56. );
  57. STATIC
  58. VOID
  59. NE3200DoResetIndications(
  60. IN PNE3200_ADAPTER Adapter,
  61. IN NDIS_STATUS Status
  62. );
  63. VOID
  64. NE3200ResetHandler(
  65. IN PVOID SystemSpecific1,
  66. IN PNE3200_ADAPTER Adapter,
  67. IN PVOID SystemSpecific2,
  68. IN PVOID SystemSpecific3
  69. );
  70. BOOLEAN
  71. NE3200InitialInit(
  72. IN PNE3200_ADAPTER Adapter,
  73. IN UINT NE3200InterruptVector,
  74. IN NDIS_INTERRUPT_MODE NE3200InterruptMode
  75. );
  76. #pragma NDIS_INIT_FUNCTION(NE3200InitialInit)
  77. BOOLEAN
  78. NE3200InitialInit(
  79. IN PNE3200_ADAPTER Adapter,
  80. IN UINT NE3200InterruptVector,
  81. IN NDIS_INTERRUPT_MODE NE3200InterruptMode
  82. )
  83. /*++
  84. Routine Description:
  85. This routine sets up the initial init of the driver, by
  86. stopping the adapter, connecting the interrupt and initializing
  87. the adapter.
  88. Arguments:
  89. Adapter - The adapter for the hardware.
  90. Return Value:
  91. TRUE if the initialization succeeds, else FALSE.
  92. --*/
  93. {
  94. //
  95. // Status of NDIS calls
  96. //
  97. NDIS_STATUS Status;
  98. //
  99. // First we make sure that the device is stopped.
  100. //
  101. NE3200StopChip(Adapter);
  102. //
  103. // The ISR will set this to FALSE if we get an interrupt
  104. //
  105. Adapter->InitialInit = TRUE;
  106. //
  107. // Initialize the interrupt.
  108. //
  109. Status = NdisMRegisterInterrupt(
  110. &Adapter->Interrupt,
  111. Adapter->MiniportAdapterHandle,
  112. NE3200InterruptVector,
  113. NE3200InterruptVector,
  114. FALSE,
  115. FALSE,
  116. NE3200InterruptMode
  117. );
  118. //
  119. // So far so good
  120. //
  121. if (Status == NDIS_STATUS_SUCCESS) {
  122. //
  123. // Now try to initialize the adapter
  124. //
  125. if (!NE3200SetConfigurationBlockAndInit(Adapter)) {
  126. //
  127. // Failed. Write out an error log entry.
  128. //
  129. NdisWriteErrorLogEntry(
  130. Adapter->MiniportAdapterHandle,
  131. NDIS_ERROR_CODE_TIMEOUT,
  132. 2,
  133. initialInit,
  134. NE3200_ERRMSG_NO_DELAY
  135. );
  136. //
  137. // Unhook the interrupt
  138. //
  139. NdisMDeregisterInterrupt(&Adapter->Interrupt);
  140. Adapter->InitialInit = FALSE;
  141. return FALSE;
  142. }
  143. //
  144. // Get hardware assigned network address.
  145. //
  146. NE3200GetStationAddress(
  147. Adapter
  148. );
  149. //
  150. // We can start the chip. We may not
  151. // have any bindings to indicate to but this
  152. // is unimportant.
  153. //
  154. Status = NE3200ChangeCurrentAddress(Adapter);
  155. Adapter->InitialInit = FALSE;
  156. return(Status == NDIS_STATUS_SUCCESS);
  157. } else {
  158. //
  159. // Interrupt line appears to be taken. Notify user.
  160. //
  161. NdisWriteErrorLogEntry(
  162. Adapter->MiniportAdapterHandle,
  163. NDIS_ERROR_CODE_INTERRUPT_CONNECT,
  164. 2,
  165. initialInit,
  166. NE3200_ERRMSG_INIT_INTERRUPT
  167. );
  168. Adapter->InitialInit = FALSE;
  169. return(FALSE);
  170. }
  171. }
  172. VOID
  173. NE3200StartChipAndDisableInterrupts(
  174. IN PNE3200_ADAPTER Adapter,
  175. IN PNE3200_SUPER_RECEIVE_ENTRY FirstReceiveEntry
  176. )
  177. /*++
  178. Routine Description:
  179. This routine is used to start an already initialized NE3200,
  180. but to keep the interrupt line masked.
  181. Arguments:
  182. Adapter - The adapter for the NE3200 to start.
  183. FirstReceiveEntry - Pointer to the first receive entry to be
  184. used by the adapter.
  185. Return Value:
  186. None.
  187. --*/
  188. {
  189. IF_LOG('%');
  190. //
  191. // Write the new receive pointer.
  192. //
  193. NE3200_WRITE_RECEIVE_POINTER(
  194. Adapter,
  195. NdisGetPhysicalAddressLow(FirstReceiveEntry->Self)
  196. );
  197. NE3200_WRITE_LOCAL_DOORBELL_INTERRUPT(
  198. Adapter,
  199. NE3200_LOCAL_DOORBELL_NEW_RECEIVE
  200. );
  201. //
  202. // Initialize the doorbell & system interrupt masks
  203. //
  204. NE3200_WRITE_SYSTEM_DOORBELL_MASK(
  205. Adapter,
  206. 0
  207. );
  208. NE3200_WRITE_SYSTEM_INTERRUPT(
  209. Adapter,
  210. NE3200_SYSTEM_INTERRUPT_ENABLE
  211. );
  212. NE3200_WRITE_MAILBOX_UCHAR(
  213. Adapter,
  214. NE3200_MAILBOX_STATUS,
  215. 0
  216. );
  217. }
  218. VOID
  219. NE3200EnableAdapter(
  220. IN NDIS_HANDLE Context
  221. )
  222. /*++
  223. Routine Description:
  224. This routine is used to start an already initialized NE3200.
  225. Arguments:
  226. Context - The adapter for the NE3200 to start.
  227. Return Value:
  228. None.
  229. --*/
  230. {
  231. PNE3200_ADAPTER Adapter = (PNE3200_ADAPTER)Context;
  232. IF_LOG('#');
  233. //
  234. // Initialize the doorbell & system interrupt masks
  235. //
  236. NE3200_WRITE_SYSTEM_INTERRUPT(
  237. Adapter,
  238. NE3200_SYSTEM_INTERRUPT_ENABLE
  239. );
  240. if (!Adapter->InterruptsDisabled) {
  241. NE3200_WRITE_SYSTEM_DOORBELL_MASK(
  242. Adapter,
  243. NE3200_SYSTEM_DOORBELL_MASK
  244. );
  245. }
  246. NE3200_WRITE_SYSTEM_DOORBELL_INTERRUPT(
  247. Adapter,
  248. NE3200_SYSTEM_DOORBELL_MASK
  249. );
  250. NE3200_WRITE_MAILBOX_UCHAR(
  251. Adapter,
  252. NE3200_MAILBOX_STATUS,
  253. 0
  254. );
  255. }
  256. VOID
  257. NE3200EnableInterrupt(
  258. IN NDIS_HANDLE Context
  259. )
  260. /*++
  261. Routine Description:
  262. This routine is used to turn on the interrupt mask.
  263. Arguments:
  264. Context - The adapter for the NE3200 to start.
  265. Return Value:
  266. None.
  267. --*/
  268. {
  269. PNE3200_ADAPTER Adapter = (PNE3200_ADAPTER)Context;
  270. IF_LOG('E');
  271. //
  272. // Enable further interrupts.
  273. //
  274. Adapter->InterruptsDisabled = FALSE;
  275. NE3200_WRITE_SYSTEM_DOORBELL_MASK(
  276. Adapter,
  277. NE3200_SYSTEM_DOORBELL_MASK
  278. );
  279. }
  280. VOID
  281. NE3200DisableInterrupt(
  282. IN NDIS_HANDLE Context
  283. )
  284. /*++
  285. Routine Description:
  286. This routine is used to turn off the interrupt mask.
  287. Arguments:
  288. Context - The adapter for the NE3200 to start.
  289. Return Value:
  290. None.
  291. --*/
  292. {
  293. PNE3200_ADAPTER Adapter = (PNE3200_ADAPTER)Context;
  294. //
  295. // Initialize the doorbell mask
  296. //
  297. Adapter->InterruptsDisabled = TRUE;
  298. NE3200_WRITE_SYSTEM_DOORBELL_MASK(
  299. Adapter,
  300. 0
  301. );
  302. IF_LOG('D');
  303. }
  304. VOID
  305. NE3200StopChip(
  306. IN PNE3200_ADAPTER Adapter
  307. )
  308. /*++
  309. Routine Description:
  310. This routine is used to stop the NE3200.
  311. Arguments:
  312. Adapter - The NE3200 adapter to stop.
  313. Return Value:
  314. None.
  315. --*/
  316. {
  317. IF_LOG('h');
  318. //
  319. // Packet reception can be stopped by writing a
  320. // (ULONG)-1 to the Receive Packet Mailbox port.
  321. // Also, commands can be stopped by writing a -1
  322. // to the Command Pointer Mailbox port.
  323. //
  324. NE3200_WRITE_RECEIVE_POINTER(
  325. Adapter,
  326. NE3200_NULL
  327. );
  328. NE3200_WRITE_COMMAND_POINTER(
  329. Adapter,
  330. NE3200_NULL
  331. );
  332. //
  333. // Ack any outstanding interrupts
  334. //
  335. NE3200_WRITE_LOCAL_DOORBELL_INTERRUPT(
  336. Adapter,
  337. NE3200_LOCAL_DOORBELL_NEW_RECEIVE | NE3200_LOCAL_DOORBELL_NEW_COMMAND
  338. );
  339. //
  340. // Disable the doorbell & system interrupt masks.
  341. //
  342. NE3200_WRITE_SYSTEM_INTERRUPT(
  343. Adapter,
  344. 0
  345. );
  346. NE3200_WRITE_SYSTEM_DOORBELL_MASK(
  347. Adapter,
  348. 0
  349. );
  350. NE3200_WRITE_SYSTEM_DOORBELL_INTERRUPT(
  351. Adapter,
  352. 0
  353. );
  354. }
  355. STATIC
  356. VOID
  357. NE3200SetConfigurationBlock(
  358. IN PNE3200_ADAPTER Adapter
  359. )
  360. /*++
  361. Routine Description:
  362. This routine simply fills the configuration block
  363. with the information necessary for initialization.
  364. Arguments:
  365. Adapter - The adapter which holds the initialization block
  366. to initialize.
  367. Return Value:
  368. None.
  369. --*/
  370. {
  371. PNE3200_CONFIGURATION_BLOCK Configuration;
  372. //
  373. // Get the configuration block
  374. //
  375. Configuration = Adapter->ConfigurationBlock;
  376. //
  377. // Initialize it to zero
  378. //
  379. NdisZeroMemory(
  380. Configuration,
  381. sizeof(NE3200_CONFIGURATION_BLOCK)
  382. );
  383. //
  384. // Set up default values
  385. //
  386. Configuration->ByteCount = 12;
  387. Configuration->FifoThreshold = 8;
  388. Configuration->AddressLength = 6;
  389. Configuration->SeparateAddressAndLength = 1;
  390. Configuration->PreambleLength = 2;
  391. Configuration->InterframeSpacing = 96;
  392. Configuration->SlotTime = 512;
  393. Configuration->MaximumRetries = 15;
  394. Configuration->DisableBroadcast = 1;
  395. Configuration->MinimumFrameLength = 64;
  396. }
  397. VOID
  398. NE3200DoAdapterReset(
  399. IN PNE3200_ADAPTER Adapter
  400. )
  401. /*++
  402. Routine Description:
  403. This is the resetting the adapter hardware.
  404. It makes the following assumptions:
  405. 1) That the hardware has been stopped.
  406. 2) That no other adapter activity can occur.
  407. When this routine is finished all of the adapter information
  408. will be as if the driver was just initialized.
  409. Arguments:
  410. Adapter - The adapter whose hardware is to be reset.
  411. Return Value:
  412. not.
  413. --*/
  414. {
  415. //
  416. // Recover all of the adapter transmit merge buffers.
  417. //
  418. {
  419. UINT i;
  420. for (
  421. i = 0;
  422. i < NE3200_NUMBER_OF_TRANSMIT_BUFFERS;
  423. i++
  424. ) {
  425. Adapter->NE3200Buffers[i].Next = i+1;
  426. }
  427. Adapter->NE3200BufferListHead = 0;
  428. Adapter->NE3200Buffers[NE3200_NUMBER_OF_TRANSMIT_BUFFERS-1].Next = -1;
  429. }
  430. //
  431. // Reset all state variables
  432. //
  433. NE3200ResetVariables(Adapter);
  434. //
  435. // Recover all command blocks
  436. //
  437. NE3200ResetCommandBlocks(Adapter);
  438. //
  439. // Initialize the adapter
  440. //
  441. NE3200SetConfigurationBlockAndInit(Adapter);
  442. }
  443. STATIC
  444. BOOLEAN
  445. NE3200SetConfigurationBlockAndInit(
  446. IN PNE3200_ADAPTER Adapter
  447. )
  448. /*++
  449. Routine Description:
  450. It is this routine's responsibility to make sure that the
  451. Configuration block is filled and the adapter is initialized
  452. *but not* started.
  453. Arguments:
  454. Adapter - The adapter whose hardware is to be initialized.
  455. Return Value:
  456. If ResetAsynchoronous is FALSE, then returns TRUE if reset successful,
  457. FALSE if reset unsuccessful.
  458. If ResetAsynchoronous is TRUE, then always returns TRUE.
  459. --*/
  460. {
  461. //
  462. // Fill in the adapter's initialization block.
  463. //
  464. NE3200SetConfigurationBlock(Adapter);
  465. //
  466. // Set the initial state for the ResetDpc state machine.
  467. //
  468. Adapter->ResetState = NE3200ResetStateStarting;
  469. //
  470. // Go through the reset
  471. //
  472. NE3200ResetHandler(NULL, Adapter, NULL, NULL);
  473. //
  474. // Is Synchronous resets, then check the final result
  475. //
  476. if (!Adapter->ResetAsynchronous) {
  477. return((Adapter->ResetResult == NE3200ResetResultSuccessful));
  478. } else {
  479. return(TRUE);
  480. }
  481. }
  482. VOID
  483. NE3200ResetHandler(
  484. IN PVOID SystemSpecific1,
  485. IN PNE3200_ADAPTER Adapter,
  486. IN PVOID SystemSpecific2,
  487. IN PVOID SystemSpecific3
  488. )
  489. /*++
  490. Routine Description:
  491. This manages the reset/download process. It is
  492. responsible for resetting the adapter, waiting for proper
  493. status, downloading MAC.BIN, waiting for MAC.BIN initialization,
  494. and optionally sending indications to the appropriate protocol.
  495. Since the NE3200's status registers must be polled during the
  496. reset/download process, this is implemented as a state machine.
  497. Arguments:
  498. Adapter - The adapter whose hardware is to be initialized.
  499. Return Value:
  500. None.
  501. --*/
  502. {
  503. //
  504. // Physical address of the MAC.BIN buffer.
  505. //
  506. NDIS_PHYSICAL_ADDRESS MacBinPhysicalAddress;
  507. //
  508. // Status from the adapter.
  509. //
  510. UCHAR Status;
  511. //
  512. // Simple iteration counter.
  513. //
  514. UINT i;
  515. //
  516. // Loop until the reset has completed.
  517. //
  518. while (Adapter->ResetState != NE3200ResetStateComplete) {
  519. switch (Adapter->ResetState) {
  520. //
  521. // The first stage of resetting an NE3200
  522. //
  523. case NE3200ResetStateStarting :
  524. //
  525. // Unfortunately, a hardware reset to the NE3200 does *not*
  526. // reset the BMIC chip. To ensure that we read a proper status,
  527. // we'll clear all of the BMIC's registers.
  528. //
  529. NE3200_WRITE_SYSTEM_INTERRUPT(
  530. Adapter,
  531. 0
  532. );
  533. //
  534. // I changed this to ff since the original 0 didn't work for
  535. // some cases. since we don't have the specs....
  536. //
  537. NE3200_WRITE_LOCAL_DOORBELL_INTERRUPT(
  538. Adapter,
  539. 0xff
  540. );
  541. NE3200_WRITE_SYSTEM_DOORBELL_MASK(
  542. Adapter,
  543. 0
  544. );
  545. NE3200_SYNC_CLEAR_SYSTEM_DOORBELL_INTERRUPT(
  546. Adapter
  547. );
  548. for (i = 0 ; i < 16 ; i += 4 ) {
  549. NE3200_WRITE_MAILBOX_ULONG(
  550. Adapter,
  551. i,
  552. 0L
  553. );
  554. }
  555. //
  556. // Toggle the NE3200's reset line.
  557. //
  558. NE3200_WRITE_RESET(
  559. Adapter,
  560. NE3200_RESET_BIT_ON
  561. );
  562. NE3200_WRITE_RESET(
  563. Adapter,
  564. NE3200_RESET_BIT_OFF
  565. );
  566. //
  567. // Switch to the next state.
  568. //
  569. Adapter->ResetState = NE3200ResetStateResetting;
  570. Adapter->ResetTimeoutCounter = NE3200_TIMEOUT_RESET;
  571. //
  572. // Loop to the next processing
  573. //
  574. break;
  575. //
  576. // Part Deux. The actual downloading of the software.
  577. //
  578. case NE3200ResetStateResetting :
  579. //
  580. // Read the status mailbox.
  581. //
  582. NE3200_READ_MAILBOX_UCHAR(Adapter, NE3200_MAILBOX_RESET_STATUS, &Status);
  583. if (Status == NE3200_RESET_PASSED) {
  584. //
  585. // We have good reset. Initiate the MAC.BIN download.
  586. //
  587. //
  588. // The station address for this adapter can be forced to
  589. // a specific value at initialization time. When MAC.BIN
  590. // first gets control, it reads mailbox 10. If this mailbox
  591. // contains a 0xFF, then the burned-in PROM station address
  592. // is used. If this mailbox contains any value other than
  593. // 0xFF, then mailboxes 10-15 are read. The six bytes
  594. // stored in these mailboxes then become the station address.
  595. //
  596. // Since we have no need for this feature, we will always
  597. // initialize mailbox 10 with a 0xFF.
  598. //
  599. NE3200_WRITE_MAILBOX_UCHAR(
  600. Adapter,
  601. NE3200_MAILBOX_STATION_ID,
  602. 0xFF
  603. );
  604. //
  605. // Get the MAC.BIN buffer.
  606. //
  607. MacBinPhysicalAddress = NE3200Globals.MacBinPhysicalAddress;
  608. //
  609. // Download MAC.BIN to the card.
  610. //
  611. NE3200_WRITE_MAILBOX_USHORT(
  612. Adapter,
  613. NE3200_MAILBOX_MACBIN_LENGTH,
  614. NE3200Globals.MacBinLength
  615. );
  616. NE3200_WRITE_MAILBOX_UCHAR(
  617. Adapter,
  618. NE3200_MAILBOX_MACBIN_DOWNLOAD_MODE,
  619. NE3200_MACBIN_DIRECT
  620. );
  621. NE3200_WRITE_MAILBOX_ULONG(
  622. Adapter,
  623. NE3200_MAILBOX_MACBIN_POINTER,
  624. NdisGetPhysicalAddressLow(MacBinPhysicalAddress)
  625. );
  626. NE3200_WRITE_MAILBOX_USHORT(
  627. Adapter,
  628. NE3200_MAILBOX_MACBIN_TARGET,
  629. NE3200_MACBIN_TARGET_ADDRESS >> 1
  630. );
  631. //
  632. // This next OUT "kicks" the loader into action.
  633. //
  634. NE3200_WRITE_MAILBOX_UCHAR(
  635. Adapter,
  636. NE3200_MAILBOX_RESET_STATUS,
  637. 0
  638. );
  639. //
  640. // Switch to the next state.
  641. //
  642. Adapter->ResetState = NE3200ResetStateDownloading;
  643. Adapter->ResetTimeoutCounter = NE3200_TIMEOUT_DOWNLOAD;
  644. //
  645. // Loop to the next state.
  646. //
  647. } else if (Status == NE3200_RESET_FAILED) {
  648. //
  649. // Reset failure. Notify the authorities and
  650. // next of kin.
  651. //
  652. Adapter->ResetResult = NE3200ResetResultResetFailure;
  653. Adapter->ResetState = NE3200ResetStateComplete;
  654. NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS);
  655. } else {
  656. //
  657. // Still waiting for results, check if we have
  658. // timed out waiting.
  659. //
  660. Adapter->ResetTimeoutCounter--;
  661. if (Adapter->ResetTimeoutCounter == 0) {
  662. //
  663. // We've timed-out. Bad news. Notify the death.
  664. //
  665. Adapter->ResetResult = NE3200ResetResultResetTimeout;
  666. Adapter->ResetState = NE3200ResetStateComplete;
  667. NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS);
  668. } else {
  669. //
  670. // For Synchronous resets, we stall. For async,
  671. // we set a timer to check later.
  672. //
  673. if (!Adapter->ResetAsynchronous) {
  674. //
  675. // Otherwise, wait and try again.
  676. //
  677. NdisStallExecution(10000);
  678. } else{
  679. //
  680. // Try again later.
  681. //
  682. NdisMSetTimer(&Adapter->ResetTimer, 100);
  683. return;
  684. }
  685. }
  686. }
  687. break;
  688. //
  689. // Part Three: The download was started. Check for completion,
  690. // and reload the current station address.
  691. //
  692. case NE3200ResetStateDownloading :
  693. //
  694. // Read the download status.
  695. //
  696. NE3200_READ_MAILBOX_UCHAR(Adapter, NE3200_MAILBOX_STATUS, &Status);
  697. if (Status == NE3200_INITIALIZATION_PASSED) {
  698. //
  699. // According to documentation from Compaq, this next port
  700. // write will (in a future MAC.BIN) tell MAC.BIN whether or
  701. // not to handle loopback internally. This value is currently
  702. // not used, but must still be written to the port.
  703. //
  704. NE3200_WRITE_MAILBOX_UCHAR(
  705. Adapter,
  706. NE3200_MAILBOX_STATUS,
  707. 1
  708. );
  709. //
  710. // Initialization is good, the card is ready.
  711. //
  712. NE3200StartChipAndDisableInterrupts(Adapter,
  713. Adapter->ReceiveQueueHead
  714. );
  715. {
  716. //
  717. // Do the work for updating the current address
  718. //
  719. //
  720. // This points to the public Command Block.
  721. //
  722. PNE3200_SUPER_COMMAND_BLOCK CommandBlock;
  723. //
  724. // This points to the adapter's configuration block.
  725. //
  726. PNE3200_CONFIGURATION_BLOCK ConfigurationBlock =
  727. Adapter->ConfigurationBlock;
  728. //
  729. // Get a public command block.
  730. //
  731. NE3200AcquirePublicCommandBlock(Adapter,
  732. &CommandBlock
  733. );
  734. Adapter->ResetHandlerCommandBlock = CommandBlock;
  735. //
  736. // Setup the command block.
  737. //
  738. CommandBlock->NextCommand = NULL;
  739. CommandBlock->Hardware.State = NE3200_STATE_WAIT_FOR_ADAPTER;
  740. CommandBlock->Hardware.Status = 0;
  741. CommandBlock->Hardware.NextPending = NE3200_NULL;
  742. CommandBlock->Hardware.CommandCode =
  743. NE3200_COMMAND_CONFIGURE_82586;
  744. CommandBlock->Hardware.PARAMETERS.CONFIGURE.ConfigurationBlock =
  745. NdisGetPhysicalAddressLow(Adapter->ConfigurationBlockPhysical);
  746. //
  747. // Now that we've got the command block built,
  748. // let's do it!
  749. //
  750. NE3200SubmitCommandBlock(Adapter, CommandBlock);
  751. Adapter->ResetState = NE3200ResetStateReloadAddress;
  752. Adapter->ResetTimeoutCounter = NE3200_TIMEOUT_DOWNLOAD;
  753. }
  754. } else if (Status == NE3200_INITIALIZATION_FAILED) {
  755. //
  756. // Initialization failed. Notify the wrapper.
  757. //
  758. Adapter->ResetResult = NE3200ResetResultInitializationFailure;
  759. Adapter->ResetState = NE3200ResetStateComplete;
  760. NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS);
  761. } else {
  762. //
  763. // See if we've timed-out waiting for the download to
  764. // complete.
  765. //
  766. Adapter->ResetTimeoutCounter--;
  767. if (Adapter->ResetTimeoutCounter == 0) {
  768. //
  769. // We've timed-out. Bad news.
  770. //
  771. Adapter->ResetResult = NE3200ResetResultInitializationTimeout;
  772. Adapter->ResetState = NE3200ResetStateComplete;
  773. NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS);
  774. } else {
  775. //
  776. // For Synchronous resets, we stall. For async,
  777. // we set a timer to check later.
  778. //
  779. if (!Adapter->ResetAsynchronous) {
  780. //
  781. // Otherwise, wait and try again.
  782. //
  783. NdisStallExecution(10000);
  784. } else{
  785. //
  786. // Try again later.
  787. //
  788. NdisMSetTimer(&Adapter->ResetTimer, 100);
  789. return;
  790. }
  791. }
  792. }
  793. break;
  794. //
  795. // Part Last: Waiting for the configuring of the adapter
  796. // to complete
  797. //
  798. case NE3200ResetStateReloadAddress :
  799. //
  800. // Read the command block status.
  801. //
  802. if (Adapter->ResetHandlerCommandBlock->Hardware.State ==
  803. NE3200_STATE_EXECUTION_COMPLETE) {
  804. //
  805. // return this command block
  806. //
  807. NE3200RelinquishCommandBlock(Adapter,
  808. Adapter->ResetHandlerCommandBlock
  809. );
  810. //
  811. // Reset is complete. Do those indications.
  812. //
  813. Adapter->ResetResult = NE3200ResetResultSuccessful;
  814. Adapter->ResetState = NE3200ResetStateComplete;
  815. NE3200DoResetIndications(Adapter, NDIS_STATUS_SUCCESS);
  816. } else {
  817. //
  818. // See if we've timed-out.
  819. //
  820. Adapter->ResetTimeoutCounter--;
  821. if (Adapter->ResetTimeoutCounter == 0) {
  822. //
  823. // We've timed-out. Bad news.
  824. //
  825. //
  826. // return this command block
  827. //
  828. NE3200RelinquishCommandBlock(Adapter,
  829. Adapter->ResetHandlerCommandBlock
  830. );
  831. Adapter->ResetResult = NE3200ResetResultInitializationTimeout;
  832. Adapter->ResetState = NE3200ResetStateComplete;
  833. NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS);
  834. } else {
  835. if ( Adapter->ResetTimeoutCounter ==
  836. (NE3200_TIMEOUT_DOWNLOAD/2) ) {
  837. //
  838. // The command may have stalled, try again.
  839. //
  840. NE3200_WRITE_LOCAL_DOORBELL_INTERRUPT(
  841. Adapter,
  842. NE3200_LOCAL_DOORBELL_NEW_COMMAND
  843. );
  844. }
  845. //
  846. // For Synchronous resets, we stall. For async,
  847. // we set a timer to check later.
  848. //
  849. if (!Adapter->ResetAsynchronous) {
  850. //
  851. // Otherwise, wait and try again.
  852. //
  853. NdisStallExecution(10000);
  854. } else{
  855. //
  856. // Check again later
  857. //
  858. NdisMSetTimer(&Adapter->ResetTimer, 100);
  859. return;
  860. }
  861. }
  862. }
  863. break;
  864. default :
  865. //
  866. // Somehow, we reached an invalid state.
  867. //
  868. //
  869. // We'll try to salvage our way out of this.
  870. //
  871. Adapter->ResetResult = NE3200ResetResultInvalidState;
  872. Adapter->ResetState = NE3200ResetStateComplete;
  873. NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS);
  874. NdisWriteErrorLogEntry(
  875. Adapter->MiniportAdapterHandle,
  876. NDIS_ERROR_CODE_HARDWARE_FAILURE,
  877. 3,
  878. resetDpc,
  879. NE3200_ERRMSG_BAD_STATE,
  880. (ULONG)(Adapter->ResetState)
  881. );
  882. break;
  883. }
  884. }
  885. }
  886. STATIC
  887. VOID
  888. NE3200DoResetIndications(
  889. IN PNE3200_ADAPTER Adapter,
  890. IN NDIS_STATUS Status
  891. )
  892. /*++
  893. Routine Description:
  894. This routine is called by NE3200ResetHandler to perform any
  895. indications which need to be done after a reset. Note that
  896. this routine will be called after either a successful reset
  897. or a failed reset.
  898. Arguments:
  899. Adapter - The adapter whose hardware has been initialized.
  900. Status - The status of the reset to send to the protocol(s).
  901. Return Value:
  902. None.
  903. --*/
  904. {
  905. //
  906. // Re-start the card if the reset was successful, else stop it.
  907. //
  908. if (Status == NDIS_STATUS_SUCCESS) {
  909. NdisMSynchronizeWithInterrupt(
  910. &(Adapter->Interrupt),
  911. NE3200EnableAdapter,
  912. (PVOID)(Adapter)
  913. );
  914. } else {
  915. //
  916. // Reset has failed.
  917. //
  918. NE3200StopChip(Adapter);
  919. NdisWriteErrorLogEntry(
  920. Adapter->MiniportAdapterHandle,
  921. NDIS_ERROR_CODE_HARDWARE_FAILURE,
  922. 0
  923. );
  924. }
  925. //
  926. // Setup the network address.
  927. //
  928. NE3200ChangeCurrentAddress(Adapter);
  929. Adapter->ResetInProgress = FALSE;
  930. //
  931. // Reset default reset method
  932. //
  933. Adapter->ResetAsynchronous = FALSE;
  934. if (!Adapter->InitialInit) {
  935. //
  936. // Signal the end of the reset
  937. //
  938. NdisMResetComplete(
  939. Adapter->MiniportAdapterHandle,
  940. Status,
  941. TRUE
  942. );
  943. }
  944. }
  945. extern
  946. VOID
  947. NE3200SetupForReset(
  948. IN PNE3200_ADAPTER Adapter
  949. )
  950. /*++
  951. Routine Description:
  952. This routine is used to fill in the who and why a reset is
  953. being set up as well as setting the appropriate fields in the
  954. adapter.
  955. NOTE: This routine must be called with the lock acquired.
  956. Arguments:
  957. Adapter - The adapter whose hardware is to be initialized.
  958. Return Value:
  959. None.
  960. --*/
  961. {
  962. //
  963. // Ndis buffer mapped
  964. //
  965. PNDIS_BUFFER CurrentBuffer;
  966. //
  967. // Map register that was used
  968. //
  969. UINT CurMapRegister;
  970. //
  971. // Packet to abort
  972. //
  973. PNDIS_PACKET Packet;
  974. //
  975. // Reserved portion of the packet.
  976. //
  977. PNE3200_RESERVED Reserved;
  978. //
  979. // Pointer to command block being processed.
  980. //
  981. PNE3200_SUPER_COMMAND_BLOCK CurrentCommandBlock = Adapter->FirstCommandOnCard;
  982. Adapter->ResetInProgress = TRUE;
  983. //
  984. // Shut down the chip. We won't be doing any more work until
  985. // the reset is complete.
  986. //
  987. NE3200StopChip(Adapter);
  988. //
  989. // Un-map all outstanding transmits
  990. //
  991. while (CurrentCommandBlock != NULL) {
  992. if (CurrentCommandBlock->Hardware.CommandCode == NE3200_COMMAND_TRANSMIT) {
  993. //
  994. // Remove first packet from the queue
  995. //
  996. Packet = CurrentCommandBlock->OwningPacket;
  997. Reserved = PNE3200_RESERVED_FROM_PACKET(Packet);
  998. if (Reserved->UsedNE3200Buffer) {
  999. goto GetNextCommandBlock;
  1000. }
  1001. //
  1002. // The transmit is finished, so we can release
  1003. // the physical mapping used for it.
  1004. //
  1005. NdisQueryPacket(
  1006. Packet,
  1007. NULL,
  1008. NULL,
  1009. &CurrentBuffer,
  1010. NULL
  1011. );
  1012. //
  1013. // Get starting map register
  1014. //
  1015. CurMapRegister = Reserved->CommandBlockIndex *
  1016. NE3200_MAXIMUM_BLOCKS_PER_PACKET;
  1017. //
  1018. // For each buffer
  1019. //
  1020. while (CurrentBuffer) {
  1021. //
  1022. // Finish the mapping
  1023. //
  1024. NdisMCompleteBufferPhysicalMapping(
  1025. Adapter->MiniportAdapterHandle,
  1026. CurrentBuffer,
  1027. CurMapRegister
  1028. );
  1029. ++CurMapRegister;
  1030. NdisGetNextBuffer(
  1031. CurrentBuffer,
  1032. &CurrentBuffer
  1033. );
  1034. }
  1035. }
  1036. GetNextCommandBlock:
  1037. CurrentCommandBlock = CurrentCommandBlock->NextCommand;
  1038. //
  1039. // Now do the pending queue
  1040. //
  1041. if (CurrentCommandBlock == NULL) {
  1042. if (Adapter->FirstWaitingCommand != NULL) {
  1043. CurrentCommandBlock = Adapter->FirstWaitingCommand;
  1044. Adapter->FirstWaitingCommand = NULL;
  1045. }
  1046. }
  1047. }
  1048. }
  1049. #pragma NDIS_INIT_FUNCTION(NE3200GetStationAddress)
  1050. VOID
  1051. NE3200GetStationAddress(
  1052. IN PNE3200_ADAPTER Adapter
  1053. )
  1054. /*++
  1055. Routine Description:
  1056. This routine gets the network address from the hardware.
  1057. NOTE: This routine assumes that it is called *immediately*
  1058. after MAC.BIN has been downloaded. It should only be called
  1059. immediately after SetConfigurationBlockAndInit() has completed.
  1060. Arguments:
  1061. Adapter - Where to store the network address.
  1062. Return Value:
  1063. None.
  1064. --*/
  1065. {
  1066. //
  1067. // Read the station address from the ports
  1068. //
  1069. NE3200_READ_MAILBOX_UCHAR(
  1070. Adapter,
  1071. NE3200_MAILBOX_STATION_ID,
  1072. &Adapter->NetworkAddress[0]
  1073. );
  1074. NE3200_READ_MAILBOX_UCHAR(
  1075. Adapter,
  1076. NE3200_MAILBOX_STATION_ID + 1,
  1077. &Adapter->NetworkAddress[1]
  1078. );
  1079. NE3200_READ_MAILBOX_UCHAR(
  1080. Adapter,
  1081. NE3200_MAILBOX_STATION_ID + 2,
  1082. &Adapter->NetworkAddress[2]
  1083. );
  1084. NE3200_READ_MAILBOX_UCHAR(
  1085. Adapter,
  1086. NE3200_MAILBOX_STATION_ID + 3,
  1087. &Adapter->NetworkAddress[3]
  1088. );
  1089. NE3200_READ_MAILBOX_UCHAR(
  1090. Adapter,
  1091. NE3200_MAILBOX_STATION_ID + 4,
  1092. &Adapter->NetworkAddress[4]
  1093. );
  1094. NE3200_READ_MAILBOX_UCHAR(
  1095. Adapter,
  1096. NE3200_MAILBOX_STATION_ID +5,
  1097. &Adapter->NetworkAddress[5]
  1098. );
  1099. if (!Adapter->AddressChanged) {
  1100. //
  1101. // Copy the real address to be used as the current address.
  1102. //
  1103. NdisMoveMemory(
  1104. Adapter->CurrentAddress,
  1105. Adapter->NetworkAddress,
  1106. NE3200_LENGTH_OF_ADDRESS
  1107. );
  1108. }
  1109. }
  1110. VOID
  1111. NE3200ResetVariables(
  1112. IN PNE3200_ADAPTER Adapter
  1113. )
  1114. /*++
  1115. Routine Description:
  1116. This routine sets variables to their proper value after a reset.
  1117. Arguments:
  1118. Adapter - Adapter we are resetting.
  1119. Return Value:
  1120. None.
  1121. --*/
  1122. {
  1123. //
  1124. // Clear the command queues
  1125. //
  1126. Adapter->FirstCommandOnCard = NULL;
  1127. Adapter->FirstWaitingCommand = NULL;
  1128. //
  1129. // Reset the receive buffer ring
  1130. //
  1131. Adapter->ReceiveQueueHead = Adapter->ReceiveQueue;
  1132. Adapter->ReceiveQueueTail =
  1133. Adapter->ReceiveQueue + Adapter->NumberOfReceiveBuffers - 1;
  1134. //
  1135. // Reset count of available command blocks
  1136. //
  1137. Adapter->NumberOfAvailableCommandBlocks = Adapter->NumberOfCommandBlocks;
  1138. Adapter->NumberOfPublicCommandBlocks = NE3200_NUMBER_OF_PUBLIC_CMD_BLOCKS;
  1139. Adapter->NextPublicCommandBlock = 0;
  1140. Adapter->NextCommandBlock = Adapter->CommandQueue;
  1141. //
  1142. // Reset transmitting and receiving states
  1143. //
  1144. Adapter->PacketResubmission = FALSE;
  1145. Adapter->TransmitsQueued = 0;
  1146. Adapter->CurrentReceiveIndex = 0;
  1147. }
  1148. VOID
  1149. NE3200ResetCommandBlocks(
  1150. IN PNE3200_ADAPTER Adapter
  1151. )
  1152. /*++
  1153. Routine Description:
  1154. This routine sets command block elementsto their proper value after a reset.
  1155. Arguments:
  1156. Adapter - Adapter we are resetting.
  1157. Return Value:
  1158. None.
  1159. --*/
  1160. {
  1161. //
  1162. // Pointer to a Receive Entry. Used while initializing
  1163. // the Receive Queue.
  1164. //
  1165. PNE3200_SUPER_RECEIVE_ENTRY CurrentReceiveEntry;
  1166. //
  1167. // Pointer to a Command Block. Used while initializing
  1168. // the Command Queue.
  1169. //
  1170. PNE3200_SUPER_COMMAND_BLOCK CurrentCommandBlock;
  1171. //
  1172. // Simple iteration variable.
  1173. //
  1174. UINT i;
  1175. //
  1176. // Put the Command Blocks into a known state.
  1177. //
  1178. for(
  1179. i = 0, CurrentCommandBlock = Adapter->CommandQueue;
  1180. i < Adapter->NumberOfCommandBlocks;
  1181. i++, CurrentCommandBlock++
  1182. ) {
  1183. CurrentCommandBlock->Hardware.State = NE3200_STATE_FREE;
  1184. CurrentCommandBlock->Hardware.NextPending = NE3200_NULL;
  1185. CurrentCommandBlock->NextCommand = NULL;
  1186. CurrentCommandBlock->AvailableCommandBlockCounter =
  1187. &Adapter->NumberOfAvailableCommandBlocks;
  1188. CurrentCommandBlock->Timeout = FALSE;
  1189. }
  1190. //
  1191. // Now do the same for the public command queue.
  1192. //
  1193. for(
  1194. i = 0, CurrentCommandBlock = Adapter->PublicCommandQueue;
  1195. i < NE3200_NUMBER_OF_PUBLIC_CMD_BLOCKS;
  1196. i++, CurrentCommandBlock++
  1197. ) {
  1198. CurrentCommandBlock->Hardware.State = NE3200_STATE_FREE;
  1199. CurrentCommandBlock->Hardware.NextPending = NE3200_NULL;
  1200. CurrentCommandBlock->NextCommand = NULL;
  1201. CurrentCommandBlock->AvailableCommandBlockCounter =
  1202. &Adapter->NumberOfPublicCommandBlocks;
  1203. CurrentCommandBlock->CommandBlockIndex = (USHORT)i;
  1204. CurrentCommandBlock->Timeout = FALSE;
  1205. }
  1206. //
  1207. // Reset the receive buffers.
  1208. //
  1209. for(
  1210. i = 0, CurrentReceiveEntry = Adapter->ReceiveQueue;
  1211. i < Adapter->NumberOfReceiveBuffers;
  1212. i++, CurrentReceiveEntry++
  1213. ) {
  1214. //
  1215. // Initialize receive buffers
  1216. //
  1217. CurrentReceiveEntry->Hardware.State = NE3200_STATE_FREE;
  1218. CurrentReceiveEntry->Hardware.NextPending =
  1219. NdisGetPhysicalAddressLow(Adapter->ReceiveQueuePhysical) +
  1220. (i + 1) * sizeof(NE3200_SUPER_RECEIVE_ENTRY);
  1221. CurrentReceiveEntry->NextEntry = CurrentReceiveEntry + 1;
  1222. }
  1223. //
  1224. // Make sure the last entry is properly terminated.
  1225. //
  1226. (CurrentReceiveEntry - 1)->Hardware.NextPending = NE3200_NULL;
  1227. (CurrentReceiveEntry - 1)->NextEntry = Adapter->ReceiveQueue;
  1228. }
  1229. NDIS_STATUS
  1230. NE3200ChangeCurrentAddress(
  1231. IN PNE3200_ADAPTER Adapter
  1232. )
  1233. /*++
  1234. Routine Description:
  1235. This routine is used to modify the card address.
  1236. Arguments:
  1237. Adapter - The adapter for the NE3200 to change address.
  1238. Return Value:
  1239. NDIS_STATUS_SUCCESS, if everything went ok
  1240. NDIS_STATUS_FAILURE, otherwise
  1241. --*/
  1242. {
  1243. //
  1244. // Modify the card address if needed
  1245. //
  1246. if (Adapter->AddressChanged) {
  1247. //
  1248. // The command block for submitting the change
  1249. //
  1250. PNE3200_SUPER_COMMAND_BLOCK CommandBlock;
  1251. //
  1252. // Temporary looping variable
  1253. //
  1254. UINT i;
  1255. //
  1256. // Get a public command block for the request
  1257. //
  1258. NE3200AcquirePublicCommandBlock(Adapter,
  1259. &CommandBlock
  1260. );
  1261. //
  1262. // Setup the command block.
  1263. //
  1264. CommandBlock->NextCommand = NULL;
  1265. CommandBlock->Hardware.State = NE3200_STATE_WAIT_FOR_ADAPTER;
  1266. CommandBlock->Hardware.Status = 0;
  1267. CommandBlock->Hardware.NextPending = NE3200_NULL;
  1268. CommandBlock->Hardware.CommandCode = NE3200_COMMAND_SET_STATION_ADDRESS;
  1269. //
  1270. // Copy in the address
  1271. //
  1272. NdisMoveMemory(
  1273. CommandBlock->Hardware.PARAMETERS.SET_ADDRESS.NewStationAddress,
  1274. Adapter->CurrentAddress,
  1275. NE3200_LENGTH_OF_ADDRESS
  1276. );
  1277. //
  1278. // Now that we've got the command block built,
  1279. // let's do it!
  1280. //
  1281. NE3200SubmitCommandBlock(Adapter, CommandBlock);
  1282. //
  1283. // Wait for the command block to finish
  1284. //
  1285. for (i = 0; i < 100000; i++) {
  1286. NdisStallExecution(100);
  1287. if (CommandBlock->Hardware.State == NE3200_STATE_EXECUTION_COMPLETE) {
  1288. break;
  1289. }
  1290. }
  1291. //
  1292. // Check the status of the command.
  1293. //
  1294. if (CommandBlock->Hardware.State != NE3200_STATE_EXECUTION_COMPLETE) {
  1295. //
  1296. // Failed
  1297. //
  1298. NdisWriteErrorLogEntry(
  1299. Adapter->MiniportAdapterHandle,
  1300. NDIS_ERROR_CODE_HARDWARE_FAILURE,
  1301. 0
  1302. );
  1303. return NDIS_STATUS_FAILURE;
  1304. }
  1305. //
  1306. // return this command block
  1307. //
  1308. NE3200RelinquishCommandBlock(Adapter, CommandBlock);
  1309. }
  1310. return NDIS_STATUS_SUCCESS;
  1311. }
  1312. BOOLEAN
  1313. SyncNE3200ClearDoorbellInterrupt(
  1314. IN PVOID SyncContext
  1315. )
  1316. /*++
  1317. Routine Description:
  1318. Clears the Doorbell Interrupt Port.
  1319. Arguments:
  1320. SyncContext - pointer to the adapter block
  1321. Return Value:
  1322. Always TRUE
  1323. --*/
  1324. {
  1325. PNE3200_ADAPTER Adapter = (PNE3200_ADAPTER)SyncContext;
  1326. //
  1327. // Clear the value
  1328. //
  1329. NdisRawWritePortUchar(
  1330. (ULONG)(Adapter->SystemDoorbellInterruptPort),
  1331. (UCHAR)0
  1332. );
  1333. return(FALSE);
  1334. }