Leaked source code of windows server 2003
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.

999 lines
32 KiB

  1. /****************************************************************************
  2. ** COPYRIGHT (C) 1994-1997 INTEL CORPORATION **
  3. ** DEVELOPED FOR MICROSOFT BY INTEL CORP., HILLSBORO, OREGON **
  4. ** HTTP://WWW.INTEL.COM/ **
  5. ** THIS FILE IS PART OF THE INTEL ETHEREXPRESS PRO/100B(TM) AND **
  6. ** ETHEREXPRESS PRO/100+(TM) NDIS 5.0 MINIPORT SAMPLE DRIVER **
  7. ****************************************************************************/
  8. /****************************************************************************
  9. Module Name:
  10. physet.c
  11. This driver runs on the following hardware:
  12. - 82558 based PCI 10/100Mb ethernet adapters
  13. (aka Intel EtherExpress(TM) PRO Adapters)
  14. Environment:
  15. Kernel Mode - Or whatever is the equivalent on WinNT
  16. Revision History
  17. - JCB 8/14/97 Example Driver Created
  18. - Dchen 11-01-99 Modified for the new sample driver
  19. *****************************************************************************/
  20. #include "precomp.h"
  21. #pragma hdrstop
  22. #pragma warning (disable: 4514)
  23. //-----------------------------------------------------------------------------
  24. // Procedure: PhyDetect
  25. //
  26. // Description: This routine will detect what phy we are using, set the line
  27. // speed, FDX or HDX, and configure the phy if necessary.
  28. //
  29. // The following combinations are supported:
  30. // - TX or T4 PHY alone at PHY address 1
  31. // - T4 or TX PHY at address 1 and MII PHY at address 0
  32. // - 82503 alone (10Base-T mode, no full duplex support)
  33. // - 82503 and MII PHY (TX or T4) at address 0
  34. //
  35. // The sequence / priority of detection is as follows:
  36. // If there is a PHY Address override use that address.
  37. // else scan based on the 'Connector' setting.
  38. // Switch Connector
  39. // 0 = AutoScan
  40. // 1 = Onboard TPE only
  41. // 2 = MII connector only
  42. //
  43. // Each of the above cases is explained below.
  44. //
  45. // AutoScan means:
  46. // Look for link on addresses 1, 0, 2..31 (in that order). Use the first
  47. // address found that has link.
  48. // If link is not found then use the first valid PHY found in the same scan
  49. // order 1,0,2..31. NOTE: this means that NO LINK or Multi-link cases will
  50. // default to the onboard PHY (address 1).
  51. //
  52. // Onboard TPE only:
  53. // Phy address is set to 1 (No Scanning).
  54. //
  55. // MII connector only means:
  56. // Look for link on addresses 0, 2..31 (again in that order, Note address 1 is
  57. // NOT scanned). Use the first address found that has link.
  58. // If link is not found then use the first valid Phy found in the same scan
  59. // order 0, 2..31.
  60. // In the AutoScan case above we should always find a valid PHY at address 1,
  61. // there is no such guarantee here, so, If NO Phy is found then the driver
  62. // should default to address 0 and continue to load. Note: External
  63. // transceivers should be at address 0 but our early Nitro3 testing found
  64. // transceivers at several non-zero addresses (6,10,14).
  65. //
  66. //
  67. // NWAY
  68. // Additionally auto-negotiation capable (NWAY) and parallel
  69. // detection PHYs are supported. The flow-chart is described in
  70. // the 82557 software writer's manual.
  71. //
  72. // NOTE: 1. All PHY MDI registers are read in polled mode.
  73. // 2. The routines assume that the 82557 has been RESET and we have
  74. // obtained the virtual memory address of the CSR.
  75. // 3. PhyDetect will not RESET the PHY.
  76. // 4. If FORCEFDX is set, SPEED should also be set. The driver will
  77. // check the values for inconsistency with the detected PHY
  78. // technology.
  79. // 5. PHY 1 (the PHY on the adapter) MUST be at address 1.
  80. // 6. Driver ignores FORCEFDX and SPEED overrides if a 503 interface
  81. // is detected.
  82. //
  83. //
  84. // Arguments:
  85. // Adapter - ptr to Adapter object instance
  86. //
  87. // Result:
  88. // Returns:
  89. // NDIS_STATUS_SUCCESS
  90. // NDIS_STATUS_FAILURE
  91. //-----------------------------------------------------------------------------
  92. NDIS_STATUS PhyDetect(
  93. IN PMP_ADAPTER Adapter
  94. )
  95. {
  96. #if DBG
  97. USHORT MdiControlReg;
  98. USHORT MdiStatusReg;
  99. #endif
  100. //
  101. // Check for a phy address over-ride of 32 which indicates a 503
  102. //
  103. if (Adapter->PhyAddress == 32)
  104. {
  105. //
  106. // 503 interface over-ride
  107. //
  108. DBGPRINT(MP_INFO, (" 503 serial component over-ride\n"));
  109. Adapter->PhyAddress = 32;
  110. //
  111. // Record the current speed and duplex. We will be in half duplex
  112. // mode unless the user used the force full duplex over-ride.
  113. //
  114. Adapter->usLinkSpeed = 10;
  115. Adapter->usDuplexMode = (USHORT) Adapter->AiForceDpx;
  116. if (!Adapter->usDuplexMode)
  117. {
  118. Adapter->usDuplexMode = 1;
  119. }
  120. return(NDIS_STATUS_SUCCESS);
  121. }
  122. //
  123. // Check for other phy address over-rides.
  124. // If the Phy Address is between 0-31 then there is an over-ride.
  125. // Or the connector was set to 1
  126. //
  127. if ((Adapter->PhyAddress < 32) || (Adapter->Connector == CONNECTOR_TPE))
  128. {
  129. //
  130. // User Override nothing to do but setup Phy and leave
  131. //
  132. if ((Adapter->PhyAddress > 32) && (Adapter->Connector == CONNECTOR_TPE))
  133. {
  134. Adapter->PhyAddress = 1; // Connector was forced
  135. // Isolate all other PHYs and unisolate this one
  136. SelectPhy(Adapter, Adapter->PhyAddress, FALSE);
  137. }
  138. DBGPRINT(MP_INFO,
  139. (" Phy address Override to address %d\n", Adapter->PhyAddress));
  140. #if DBG
  141. //
  142. // Read the MDI control register at override address.
  143. //
  144. MdiRead(Adapter, MDI_CONTROL_REG, Adapter->PhyAddress, FALSE, &MdiControlReg);
  145. //
  146. // Read the status register at override address.
  147. //
  148. MdiRead(Adapter, MDI_STATUS_REG, Adapter->PhyAddress, FALSE, &MdiStatusReg);
  149. //
  150. // Read the status register again because of sticky bits
  151. //
  152. MdiRead(Adapter, MDI_STATUS_REG, Adapter->PhyAddress, FALSE, &MdiStatusReg);
  153. //
  154. // check if we found a valid phy
  155. //
  156. if (!((MdiControlReg == 0xffff) || ((MdiStatusReg == 0) && (MdiControlReg == 0))))
  157. {
  158. //
  159. // we have a valid phy1
  160. //
  161. DBGPRINT(MP_INFO, (" Over-ride address %d has a valid Phy.\n", Adapter->PhyAddress));
  162. //
  163. // Read the status register again
  164. //
  165. MdiRead(Adapter, MDI_STATUS_REG, Adapter->PhyAddress, FALSE, &MdiStatusReg);
  166. //
  167. // If there is a valid link then use this Phy.
  168. //
  169. if (MdiStatusReg & MDI_SR_LINK_STATUS)
  170. {
  171. DBGPRINT(MP_INFO, (" Phy at address %d has link\n", Adapter->PhyAddress));
  172. }
  173. }
  174. else
  175. {
  176. //
  177. // no PHY at over-ride address
  178. //
  179. DBGPRINT(MP_INFO, (" Over-ride address %d has no Phy!!!!\n", Adapter->PhyAddress));
  180. }
  181. #endif
  182. return(SetupPhy(Adapter));
  183. }
  184. else // Need to scan - No address over-ride and Connector is AUTO or MII
  185. {
  186. Adapter->CurrentScanPhyIndex = 0;
  187. Adapter->LinkDetectionWaitCount = 0;
  188. Adapter->FoundPhyAt = 0xff;
  189. Adapter->bLookForLink = TRUE;
  190. return(ScanAndSetupPhy(Adapter));
  191. } // End else scan
  192. }
  193. NDIS_STATUS ScanAndSetupPhy(
  194. IN PMP_ADAPTER Adapter
  195. )
  196. {
  197. USHORT MdiControlReg = 0;
  198. USHORT MdiStatusReg = 0;
  199. if (Adapter->bLinkDetectionWait)
  200. {
  201. goto NEGOTIATION_WAIT;
  202. }
  203. SCAN_PHY_START:
  204. //
  205. // For each PhyAddress 0 - 31
  206. //
  207. DBGPRINT(MP_INFO, (" Index=%d, bLookForLink=%d\n",
  208. Adapter->CurrentScanPhyIndex, Adapter->bLookForLink));
  209. if (Adapter->bLookForLink)
  210. {
  211. //
  212. // Phy Addresses must be tested in the order 1,0,2..31.
  213. //
  214. switch(Adapter->CurrentScanPhyIndex)
  215. {
  216. case 0:
  217. Adapter->PhyAddress = 1;
  218. break;
  219. case 1:
  220. Adapter->PhyAddress = 0;
  221. break;
  222. default:
  223. Adapter->PhyAddress = Adapter->CurrentScanPhyIndex;
  224. break;
  225. }
  226. //
  227. // Skip OnBoard for MII only case
  228. //
  229. if ((Adapter->PhyAddress == 1)&&(Adapter->Connector == CONNECTOR_MII))
  230. {
  231. goto SCAN_PHY_NEXT;
  232. }
  233. DBGPRINT(MP_INFO, (" Scanning Phy address %d for link\n", Adapter->PhyAddress));
  234. //
  235. // Read the MDI control register
  236. //
  237. MdiRead(Adapter, MDI_CONTROL_REG, Adapter->PhyAddress, FALSE, &MdiControlReg);
  238. //
  239. // Read the status register
  240. //
  241. MdiRead(Adapter, MDI_STATUS_REG, Adapter->PhyAddress, FALSE, &MdiStatusReg);
  242. MdiRead(Adapter, MDI_STATUS_REG, Adapter->PhyAddress, FALSE, &MdiStatusReg);
  243. // Sticky Bits
  244. }
  245. else
  246. {
  247. //
  248. // Not looking for link
  249. //
  250. if (Adapter->FoundPhyAt < 32)
  251. {
  252. Adapter->PhyAddress = Adapter->FoundPhyAt;
  253. }
  254. else if (Adapter->Connector == CONNECTOR_MII)
  255. {
  256. //
  257. // No valid PHYs were found last time so just default
  258. //
  259. Adapter->PhyAddress = 0; // Default for MII
  260. }
  261. else
  262. {
  263. //
  264. // assume a 503 interface
  265. //
  266. Adapter->PhyAddress = 32;
  267. //
  268. // Record the current speed and duplex. We will be in half duplex
  269. // mode unless the user used the force full duplex over-ride.
  270. //
  271. Adapter->usLinkSpeed = 10;
  272. Adapter->usDuplexMode = (USHORT) Adapter->AiForceDpx;
  273. if (!Adapter->usDuplexMode)
  274. {
  275. Adapter->usDuplexMode = 1;
  276. }
  277. return(NDIS_STATUS_SUCCESS);
  278. }
  279. DBGPRINT(MP_INFO, (" No Links Found!!\n"));
  280. }
  281. //
  282. // check if we found a valid phy or on !LookForLink pass
  283. //
  284. if (!( (MdiControlReg == 0xffff) || ((MdiStatusReg == 0) && (MdiControlReg == 0)))
  285. || (!Adapter->bLookForLink))
  286. {
  287. //
  288. // Valid phy or Not looking for Link
  289. //
  290. #if DBG
  291. if (!( (MdiControlReg == 0xffff) || ((MdiStatusReg == 0) && (MdiControlReg == 0))))
  292. {
  293. DBGPRINT(MP_INFO, (" Found a Phy at address %d\n", Adapter->PhyAddress));
  294. }
  295. #endif
  296. //
  297. // Store highest priority phy found for NO link case
  298. //
  299. if (Adapter->CurrentScanPhyIndex < Adapter->FoundPhyAt && Adapter->FoundPhyAt != 1)
  300. {
  301. // this phy is higher priority
  302. Adapter->FoundPhyAt = (UCHAR) Adapter->PhyAddress;
  303. }
  304. //
  305. // Select Phy before checking link status
  306. // NOTE: may take up to 3.5 Sec if LookForLink == TRUE
  307. //SelectPhy(Adapter, Adapter->PhyAddress, (BOOLEAN)LookForLink);
  308. //
  309. SelectPhy(Adapter, Adapter->PhyAddress, FALSE);
  310. NEGOTIATION_WAIT:
  311. //
  312. // wait for auto-negotiation to complete (up to 3.5 seconds)
  313. //
  314. if (Adapter->LinkDetectionWaitCount++ < RENEGOTIATE_TIME)
  315. {
  316. // Read the status register twice because of sticky bits
  317. MdiRead(Adapter, MDI_STATUS_REG, Adapter->PhyAddress, FALSE, &MdiStatusReg);
  318. MdiRead(Adapter, MDI_STATUS_REG, Adapter->PhyAddress, FALSE, &MdiStatusReg);
  319. if (!(MdiStatusReg & MDI_SR_AUTO_NEG_COMPLETE))
  320. {
  321. return NDIS_STATUS_PENDING;
  322. }
  323. }
  324. else
  325. {
  326. Adapter->LinkDetectionWaitCount = 0;
  327. }
  328. //
  329. // Read the MDI control register
  330. //
  331. MdiRead(Adapter, MDI_CONTROL_REG, Adapter->PhyAddress, FALSE, &MdiControlReg);
  332. //
  333. // Read the status register
  334. //
  335. MdiRead(Adapter, MDI_STATUS_REG, Adapter->PhyAddress, FALSE, &MdiStatusReg);
  336. MdiRead(Adapter, MDI_STATUS_REG, Adapter->PhyAddress, FALSE, &MdiStatusReg);
  337. //
  338. // If there is a valid link or we alreadry tried once then use this Phy.
  339. //
  340. if ((MdiStatusReg & MDI_SR_LINK_STATUS) || (!Adapter->bLookForLink))
  341. {
  342. #if DBG
  343. if (MdiStatusReg & MDI_SR_LINK_STATUS)
  344. {
  345. DBGPRINT(MP_INFO, (" Using Phy at address %d with link\n", Adapter->PhyAddress));
  346. }
  347. else
  348. {
  349. DBGPRINT(MP_INFO, (" Using Phy at address %d WITHOUT link!!!\n", Adapter->PhyAddress));
  350. }
  351. #endif
  352. return(SetupPhy(Adapter)); // Exit with Link Path
  353. }
  354. } // End if valid PHY
  355. SCAN_PHY_NEXT:
  356. Adapter->CurrentScanPhyIndex++;
  357. if (Adapter->CurrentScanPhyIndex >= 32)
  358. {
  359. Adapter->bLookForLink = FALSE;
  360. }
  361. goto SCAN_PHY_START;
  362. }
  363. //***************************************************************************
  364. //
  365. // Name: SelectPhy
  366. //
  367. // Description: This routine will Isolate all Phy addresses on the MII
  368. // Bus except for the one address to be 'selected'. This
  369. // Phy address will be un-isolated and auto-negotiation will
  370. // be enabled, started, and completed. The Phy will NOT be
  371. // reset and the speed will NOT be set to any value (that is
  372. // done in SetupPhy).
  373. //
  374. // Arguments: SelectPhyAddress - PhyAddress to select
  375. // WaitAutoNeg - Flag TRUE = Wait for Auto Negociation to complete.
  376. // FALSE = don't wait. Good for 'No Link' case.
  377. //
  378. // Returns: Nothing
  379. //
  380. // Modification log:
  381. // Date Who Description
  382. // -------- --- --------------------------------------------------------
  383. //***************************************************************************
  384. VOID SelectPhy(
  385. IN PMP_ADAPTER Adapter,
  386. IN UINT SelectPhyAddress,
  387. IN BOOLEAN WaitAutoNeg
  388. )
  389. {
  390. UCHAR i;
  391. USHORT MdiControlReg = 0;
  392. USHORT MdiStatusReg = 0;
  393. //
  394. // Isolate all other phys and unisolate the one to query
  395. //
  396. for (i = 0; i < 32; i++)
  397. {
  398. if (i != SelectPhyAddress)
  399. {
  400. // isolate this phy
  401. MdiWrite(Adapter, MDI_CONTROL_REG, i, MDI_CR_ISOLATE);
  402. // wait 100 microseconds for the phy to isolate.
  403. NdisStallExecution(100);
  404. }
  405. }
  406. // unisolate the phy to query
  407. //
  408. // Read the MDI control register
  409. //
  410. MdiRead(Adapter, MDI_CONTROL_REG, SelectPhyAddress, FALSE, &MdiControlReg);
  411. //
  412. // Set/Clear bit unisolate this phy
  413. //
  414. MdiControlReg &= ~MDI_CR_ISOLATE; // Clear the Isolate Bit
  415. //
  416. // issue the command to unisolate this Phy
  417. //
  418. MdiWrite(Adapter, MDI_CONTROL_REG, SelectPhyAddress, MdiControlReg);
  419. //
  420. // sticky bits on link
  421. //
  422. MdiRead(Adapter, MDI_STATUS_REG, SelectPhyAddress, FALSE, &MdiStatusReg);
  423. MdiRead(Adapter, MDI_STATUS_REG, SelectPhyAddress, FALSE, &MdiStatusReg);
  424. //
  425. // if we have link, don't mess with the phy
  426. //
  427. if (MdiStatusReg & MDI_SR_LINK_STATUS)
  428. return;
  429. //
  430. // Read the MDI control register
  431. //
  432. MdiRead(Adapter, MDI_CONTROL_REG, SelectPhyAddress, FALSE, &MdiControlReg);
  433. //
  434. // set Restart auto-negotiation
  435. //
  436. MdiControlReg |= MDI_CR_AUTO_SELECT; // Set Auto Neg Enable
  437. MdiControlReg |= MDI_CR_RESTART_AUTO_NEG; // Restart Auto Neg
  438. //
  439. // restart the auto-negotion process
  440. //
  441. MdiWrite(Adapter, MDI_CONTROL_REG, SelectPhyAddress, MdiControlReg);
  442. //
  443. // wait 200 microseconds for the phy to unisolate.
  444. //
  445. NdisStallExecution(200);
  446. if (WaitAutoNeg)
  447. {
  448. //
  449. // wait for auto-negotiation to complete (up to 3.5 seconds)
  450. //
  451. for (i = RENEGOTIATE_TIME; i != 0; i--)
  452. {
  453. // Read the status register twice because of sticky bits
  454. MdiRead(Adapter, MDI_STATUS_REG, SelectPhyAddress, FALSE, &MdiStatusReg);
  455. MdiRead(Adapter, MDI_STATUS_REG, SelectPhyAddress, FALSE, &MdiStatusReg);
  456. if (MdiStatusReg & MDI_SR_AUTO_NEG_COMPLETE)
  457. break;
  458. MP_STALL_EXECUTION(100);
  459. }
  460. }
  461. }
  462. //-----------------------------------------------------------------------------
  463. // Procedure: SetupPhy
  464. //
  465. // Description: This routine will setup phy 1 or phy 0 so that it is configured
  466. // to match a speed and duplex over-ride option. If speed or
  467. // duplex mode is not explicitly specified in the registry, the
  468. // driver will skip the speed and duplex over-ride code, and
  469. // assume the adapter is automatically setting the line speed, and
  470. // the duplex mode. At the end of this routine, any truly Phy
  471. // specific code will be executed (each Phy has its own quirks,
  472. // and some require that certain special bits are set).
  473. //
  474. // NOTE: The driver assumes that SPEED and FORCEFDX are specified at the
  475. // same time. If FORCEDPX is set without speed being set, the driver
  476. // will encouter a fatal error and log a message into the event viewer.
  477. //
  478. // Arguments:
  479. // Adapter - ptr to Adapter object instance
  480. //
  481. // Result:
  482. // Returns:
  483. // NDIS_STATUS_SUCCESS
  484. // NDIS_STATUS_FAILURE
  485. //-----------------------------------------------------------------------------
  486. NDIS_STATUS SetupPhy(
  487. IN PMP_ADAPTER Adapter)
  488. {
  489. USHORT MdiControlReg = 0;
  490. USHORT MdiStatusReg = 0;
  491. USHORT MdiIdLowReg = 0;
  492. USHORT MdiIdHighReg = 0;
  493. USHORT MdiMiscReg = 0;
  494. UINT PhyId;
  495. BOOLEAN ForcePhySetting = FALSE;
  496. //
  497. // If we are NOT forcing a setting for line speed or full duplex, then
  498. // we won't force a link setting, and we'll jump down to the phy
  499. // specific code.
  500. //
  501. if (((Adapter->AiTempSpeed) || (Adapter->AiForceDpx)))
  502. {
  503. //
  504. // Find out what kind of technology this Phy is capable of.
  505. //
  506. MdiRead(Adapter, MDI_STATUS_REG, Adapter->PhyAddress, FALSE, &MdiStatusReg);
  507. //
  508. // Read the MDI control register at our phy
  509. //
  510. MdiRead(Adapter, MDI_CONTROL_REG, Adapter->PhyAddress, FALSE, &MdiControlReg);
  511. //
  512. // Now check the validity of our forced option. If the force option is
  513. // valid, then force the setting. If the force option is not valid,
  514. // we'll set a flag indicating that we should error out.
  515. //
  516. //
  517. // If speed is forced to 10mb
  518. //
  519. if (Adapter->AiTempSpeed == 10)
  520. {
  521. // If half duplex is forced
  522. if (Adapter->AiForceDpx == 1)
  523. {
  524. if (MdiStatusReg & MDI_SR_10T_HALF_DPX)
  525. {
  526. DBGPRINT(MP_INFO, (" Forcing 10mb 1/2 duplex\n"));
  527. MdiControlReg &= ~(MDI_CR_10_100 | MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF);
  528. ForcePhySetting = TRUE;
  529. }
  530. }
  531. // If full duplex is forced
  532. else if (Adapter->AiForceDpx == 2)
  533. {
  534. if (MdiStatusReg & MDI_SR_10T_FULL_DPX)
  535. {
  536. DBGPRINT(MP_INFO, (" Forcing 10mb full duplex\n"));
  537. MdiControlReg &= ~(MDI_CR_10_100 | MDI_CR_AUTO_SELECT);
  538. MdiControlReg |= MDI_CR_FULL_HALF;
  539. ForcePhySetting = TRUE;
  540. }
  541. }
  542. // If auto duplex (we actually set phy to 1/2)
  543. else
  544. {
  545. if (MdiStatusReg & (MDI_SR_10T_FULL_DPX | MDI_SR_10T_HALF_DPX))
  546. {
  547. DBGPRINT(MP_INFO, (" Forcing 10mb auto duplex\n"));
  548. MdiControlReg &= ~(MDI_CR_10_100 | MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF);
  549. ForcePhySetting = TRUE;
  550. Adapter->AiForceDpx = 1;
  551. }
  552. }
  553. }
  554. //
  555. // If speed is forced to 100mb
  556. //
  557. else if (Adapter->AiTempSpeed == 100)
  558. {
  559. // If half duplex is forced
  560. if (Adapter->AiForceDpx == 1)
  561. {
  562. if (MdiStatusReg & (MDI_SR_TX_HALF_DPX | MDI_SR_T4_CAPABLE))
  563. {
  564. DBGPRINT(MP_INFO, (" Forcing 100mb half duplex\n"));
  565. MdiControlReg &= ~(MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF);
  566. MdiControlReg |= MDI_CR_10_100;
  567. ForcePhySetting = TRUE;
  568. }
  569. }
  570. // If full duplex is forced
  571. else if (Adapter->AiForceDpx == 2)
  572. {
  573. if (MdiStatusReg & MDI_SR_TX_FULL_DPX)
  574. {
  575. DBGPRINT(MP_INFO, (" Forcing 100mb full duplex\n"));
  576. MdiControlReg &= ~MDI_CR_AUTO_SELECT;
  577. MdiControlReg |= (MDI_CR_10_100 | MDI_CR_FULL_HALF);
  578. ForcePhySetting = TRUE;
  579. }
  580. }
  581. // If auto duplex (we set phy to 1/2)
  582. else
  583. {
  584. if (MdiStatusReg & (MDI_SR_TX_HALF_DPX | MDI_SR_T4_CAPABLE))
  585. {
  586. DBGPRINT(MP_INFO, (" Forcing 100mb auto duplex\n"));
  587. MdiControlReg &= ~(MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF);
  588. MdiControlReg |= MDI_CR_10_100;
  589. ForcePhySetting = TRUE;
  590. Adapter->AiForceDpx = 1;
  591. }
  592. }
  593. }
  594. if (ForcePhySetting == FALSE)
  595. {
  596. DBGPRINT(MP_INFO, (" Can't force speed=%d, duplex=%d\n",Adapter->AiTempSpeed, Adapter->AiForceDpx));
  597. return(NDIS_STATUS_FAILURE);
  598. }
  599. //
  600. // Write the MDI control register with our new Phy configuration
  601. //
  602. MdiWrite(Adapter, MDI_CONTROL_REG, Adapter->PhyAddress, MdiControlReg);
  603. //
  604. // wait 100 milliseconds for auto-negotiation to complete
  605. //
  606. MP_STALL_EXECUTION(100);
  607. }
  608. //
  609. // Find out specifically what Phy this is. We do this because for certain
  610. // phys there are specific bits that must be set so that the phy and the
  611. // 82557 work together properly.
  612. //
  613. MdiRead(Adapter, PHY_ID_REG_1, Adapter->PhyAddress, FALSE, &MdiIdLowReg);
  614. MdiRead(Adapter, PHY_ID_REG_2, Adapter->PhyAddress, FALSE, &MdiIdHighReg);
  615. PhyId = ((UINT) MdiIdLowReg | ((UINT) MdiIdHighReg << 16));
  616. DBGPRINT(MP_INFO, (" Phy ID is %x\n", PhyId));
  617. //
  618. // And out the revsion field of the Phy ID so that we'll be able to detect
  619. // future revs of the same Phy.
  620. //
  621. PhyId &= PHY_MODEL_REV_ID_MASK;
  622. //
  623. // Handle the National TX
  624. //
  625. if (PhyId == PHY_NSC_TX)
  626. {
  627. DBGPRINT(MP_INFO, (" Found a NSC TX Phy\n"));
  628. MdiRead(Adapter, NSC_CONG_CONTROL_REG, Adapter->PhyAddress, FALSE, &MdiMiscReg);
  629. MdiMiscReg |= (NSC_TX_CONG_TXREADY | NSC_TX_CONG_F_CONNECT);
  630. //
  631. // If we are configured to do congestion control, then enable the
  632. // congestion control bit in the National Phy
  633. //
  634. if (Adapter->Congest)
  635. MdiMiscReg |= NSC_TX_CONG_ENABLE;
  636. else
  637. MdiMiscReg &= ~NSC_TX_CONG_ENABLE;
  638. MdiWrite(Adapter, NSC_CONG_CONTROL_REG, Adapter->PhyAddress, MdiMiscReg);
  639. }
  640. FindPhySpeedAndDpx(Adapter, PhyId);
  641. DBGPRINT(MP_WARN, (" Current Speed=%d, Current Duplex=%d\n",Adapter->usLinkSpeed, Adapter->usDuplexMode));
  642. return(NDIS_STATUS_SUCCESS);
  643. }
  644. //-----------------------------------------------------------------------------
  645. // Procedure: FindPhySpeedAndDpx
  646. //
  647. // Description: This routine will figure out what line speed and duplex mode
  648. // the PHY is currently using.
  649. //
  650. // Arguments:
  651. // Adapter - ptr to Adapter object instance
  652. // PhyId - The ID of the PHY in question.
  653. //
  654. // Returns:
  655. // NOTHING
  656. //-----------------------------------------------------------------------------
  657. VOID FindPhySpeedAndDpx(
  658. IN PMP_ADAPTER Adapter,
  659. IN UINT PhyId
  660. )
  661. {
  662. USHORT MdiStatusReg = 0;
  663. USHORT MdiMiscReg = 0;
  664. USHORT MdiOwnAdReg = 0;
  665. USHORT MdiLinkPartnerAdReg = 0;
  666. //
  667. // If there was a speed and/or duplex override, then set our current
  668. // value accordingly
  669. //
  670. Adapter->usLinkSpeed = Adapter->AiTempSpeed;
  671. Adapter->usDuplexMode = (USHORT) Adapter->AiForceDpx;
  672. //
  673. // If speed and duplex were forced, then we know our current settings, so
  674. // we'll just return. Otherwise, we'll need to figure out what NWAY set
  675. // us to.
  676. //
  677. if (Adapter->usLinkSpeed && Adapter->usDuplexMode)
  678. {
  679. return;
  680. }
  681. //
  682. // If we didn't have a valid link, then we'll assume that our current
  683. // speed is 10mb half-duplex.
  684. //
  685. //
  686. // Read the status register twice because of sticky bits
  687. //
  688. MdiRead(Adapter, MDI_STATUS_REG, Adapter->PhyAddress, FALSE, &MdiStatusReg);
  689. MdiRead(Adapter, MDI_STATUS_REG, Adapter->PhyAddress, FALSE, &MdiStatusReg);
  690. //
  691. // If there wasn't a valid link then use default speed & duplex
  692. //
  693. if (!(MdiStatusReg & MDI_SR_LINK_STATUS))
  694. {
  695. DBGPRINT(MP_INFO, (" Link Not found for speed detection!!! Using defaults.\n"));
  696. Adapter->usLinkSpeed = 10;
  697. Adapter->usDuplexMode = 1;
  698. return;
  699. }
  700. //
  701. // If this is an Intel PHY (a T4 PHY_100 or a TX PHY_TX), then read bits
  702. // 1 and 0 of extended register 0, to get the current speed and duplex
  703. // settings.
  704. //
  705. if ((PhyId == PHY_100_A) || (PhyId == PHY_100_C) || (PhyId == PHY_TX_ID))
  706. {
  707. DBGPRINT(MP_INFO, (" Detecting Speed/Dpx for an Intel PHY\n"));
  708. //
  709. // Read extended register 0
  710. //
  711. MdiRead(Adapter, EXTENDED_REG_0, Adapter->PhyAddress, FALSE, &MdiMiscReg);
  712. //
  713. // Get current speed setting
  714. //
  715. if (MdiMiscReg & PHY_100_ER0_SPEED_INDIC)
  716. {
  717. Adapter->usLinkSpeed = 100;
  718. }
  719. else
  720. {
  721. Adapter->usLinkSpeed = 10;
  722. }
  723. //
  724. //
  725. // Get current duplex setting -- if bit is set then FDX is enabled
  726. //
  727. if (MdiMiscReg & PHY_100_ER0_FDX_INDIC)
  728. {
  729. Adapter->usDuplexMode = 2;
  730. }
  731. else
  732. {
  733. Adapter->usDuplexMode = 1;
  734. }
  735. return;
  736. }
  737. //
  738. // Read our link partner's advertisement register
  739. //
  740. MdiRead(Adapter,
  741. AUTO_NEG_LINK_PARTNER_REG,
  742. Adapter->PhyAddress,
  743. FALSE,
  744. &MdiLinkPartnerAdReg);
  745. //
  746. // See if Auto-Negotiation was complete (bit 5, reg 1)
  747. //
  748. MdiRead(Adapter, MDI_STATUS_REG, Adapter->PhyAddress, FALSE, &MdiStatusReg);
  749. //
  750. // If a True NWAY connection was made, then we can detect speed/duplex by
  751. // ANDing our adapter's advertised abilities with our link partner's
  752. // advertised ablilities, and then assuming that the highest common
  753. // denominator was chosed by NWAY.
  754. //
  755. if ((MdiLinkPartnerAdReg & NWAY_LP_ABILITY) &&
  756. (MdiStatusReg & MDI_SR_AUTO_NEG_COMPLETE))
  757. {
  758. DBGPRINT(MP_INFO, (" Detecting Speed/Dpx from NWAY connection\n"));
  759. //
  760. // Read our advertisement register
  761. //
  762. MdiRead(Adapter, AUTO_NEG_ADVERTISE_REG, Adapter->PhyAddress, FALSE, &MdiOwnAdReg);
  763. //
  764. // AND the two advertisement registers together, and get rid of any
  765. // extraneous bits.
  766. //
  767. MdiOwnAdReg &= (MdiLinkPartnerAdReg & NWAY_LP_ABILITY);
  768. //
  769. // Get speed setting
  770. //
  771. if (MdiOwnAdReg & (NWAY_AD_TX_HALF_DPX | NWAY_AD_TX_FULL_DPX | NWAY_AD_T4_CAPABLE))
  772. {
  773. Adapter->usLinkSpeed = 100;
  774. }
  775. else
  776. {
  777. Adapter->usLinkSpeed = 10;
  778. }
  779. //
  780. // Get duplex setting -- use priority resolution algorithm
  781. //
  782. if (MdiOwnAdReg & (NWAY_AD_T4_CAPABLE))
  783. {
  784. Adapter->usDuplexMode = 1;
  785. return;
  786. }
  787. else if (MdiOwnAdReg & (NWAY_AD_TX_FULL_DPX))
  788. {
  789. Adapter->usDuplexMode = 2;
  790. return;
  791. }
  792. else if (MdiOwnAdReg & (NWAY_AD_TX_HALF_DPX))
  793. {
  794. Adapter->usDuplexMode = 1;
  795. return;
  796. }
  797. else if (MdiOwnAdReg & (NWAY_AD_10T_FULL_DPX))
  798. {
  799. Adapter->usDuplexMode = 2;
  800. return;
  801. }
  802. else
  803. {
  804. Adapter->usDuplexMode = 1;
  805. return;
  806. }
  807. }
  808. //
  809. // If we are connected to a non-NWAY repeater or hub, and the line
  810. // speed was determined automatically by parallel detection, then we have
  811. // no way of knowing exactly what speed the PHY is set to unless that PHY
  812. // has a propietary register which indicates speed in this situation. The
  813. // NSC TX PHY does have such a register. Also, since NWAY didn't establish
  814. // the connection, the duplex setting should HALF duplex.
  815. //
  816. Adapter->usDuplexMode = 1;
  817. if (PhyId == PHY_NSC_TX)
  818. {
  819. DBGPRINT(MP_INFO, (" Detecting Speed/Dpx from non-NWAY NSC connection\n"));
  820. //
  821. // Read register 25 to get the SPEED_10 bit
  822. //
  823. MdiRead(Adapter, NSC_SPEED_IND_REG, Adapter->PhyAddress, FALSE, &MdiMiscReg);
  824. //
  825. // If bit 6 was set then we're at 10mb
  826. //
  827. if (MdiMiscReg & NSC_TX_SPD_INDC_SPEED)
  828. {
  829. Adapter->usLinkSpeed = 10;
  830. }
  831. else
  832. {
  833. Adapter->usLinkSpeed = 100;
  834. }
  835. }
  836. //
  837. // If we don't know what line speed we are set at, then we'll default to
  838. // 10mbs
  839. //
  840. else
  841. {
  842. Adapter->usLinkSpeed = 10;
  843. }
  844. }
  845. //-----------------------------------------------------------------------------
  846. // Procedure: ResetPhy
  847. //
  848. // Description: This routine will reset the PHY that the adapter is currently
  849. // configured to use.
  850. //
  851. // Arguments:
  852. // Adapter - ptr to Adapter object instance
  853. //
  854. // Returns:
  855. // NOTHING
  856. //-----------------------------------------------------------------------------
  857. VOID ResetPhy(
  858. IN PMP_ADAPTER Adapter
  859. )
  860. {
  861. USHORT MdiControlReg;
  862. //
  863. // Reset the Phy, enable auto-negotiation, and restart auto-negotiation.
  864. //
  865. MdiControlReg = (MDI_CR_AUTO_SELECT | MDI_CR_RESTART_AUTO_NEG | MDI_CR_RESET);
  866. //
  867. // Write the MDI control register with our new Phy configuration
  868. //
  869. MdiWrite(Adapter, MDI_CONTROL_REG, Adapter->PhyAddress, MdiControlReg);
  870. }