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.

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