Ax88772.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  1. /** @file
  2. Implement the interface to the AX88772 Ethernet controller.
  3. This module implements the interface to the ASIX AX88772
  4. USB to Ethernet MAC with integrated 10/100 PHY. Note that this implementation
  5. only supports the integrated PHY since no other test cases were available.
  6. Copyright (c) 2011, Intel Corporation. All rights reserved.
  7. SPDX-License-Identifier: BSD-2-Clause-Patent
  8. **/
  9. #include "Ax88772.h"
  10. /**
  11. Compute the CRC
  12. @param [in] pMacAddress Address of a six byte buffer to containing the MAC address.
  13. @returns The CRC-32 value associated with this MAC address
  14. **/
  15. UINT32
  16. Ax88772Crc (
  17. IN UINT8 * pMacAddress
  18. )
  19. {
  20. UINT32 BitNumber;
  21. INT32 Carry;
  22. INT32 Crc;
  23. UINT32 Data;
  24. UINT8 * pEnd;
  25. //
  26. // Walk the MAC address
  27. //
  28. Crc = -1;
  29. pEnd = &pMacAddress[ PXE_HWADDR_LEN_ETHER ];
  30. while ( pEnd > pMacAddress ) {
  31. Data = *pMacAddress++;
  32. //
  33. // CRC32: x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
  34. //
  35. // 1 0000 0100 1100 0001 0001 1101 1011 0111
  36. //
  37. for ( BitNumber = 0; 8 > BitNumber; BitNumber++ ) {
  38. Carry = (( Crc >> 31 ) & 1 ) ^ ( Data & 1 );
  39. Crc <<= 1;
  40. if ( 0 != Carry ) {
  41. Crc ^= 0x04c11db7;
  42. }
  43. Data >>= 1;
  44. }
  45. }
  46. //
  47. // Return the CRC value
  48. //
  49. return (UINT32) Crc;
  50. }
  51. /**
  52. Get the MAC address
  53. This routine calls ::Ax88772UsbCommand to request the MAC
  54. address from the network adapter.
  55. @param [in] pNicDevice Pointer to the NIC_DEVICE structure
  56. @param [out] pMacAddress Address of a six byte buffer to receive the MAC address.
  57. @retval EFI_SUCCESS The MAC address is available.
  58. @retval other The MAC address is not valid.
  59. **/
  60. EFI_STATUS
  61. Ax88772MacAddressGet (
  62. IN NIC_DEVICE * pNicDevice,
  63. OUT UINT8 * pMacAddress
  64. )
  65. {
  66. USB_DEVICE_REQUEST SetupMsg;
  67. EFI_STATUS Status;
  68. //
  69. // Set the register address.
  70. //
  71. SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
  72. | USB_REQ_TYPE_VENDOR
  73. | USB_TARGET_DEVICE;
  74. SetupMsg.Request = CMD_MAC_ADDRESS_READ;
  75. SetupMsg.Value = 0;
  76. SetupMsg.Index = 0;
  77. SetupMsg.Length = PXE_HWADDR_LEN_ETHER;
  78. //
  79. // Read the PHY register
  80. //
  81. Status = Ax88772UsbCommand ( pNicDevice,
  82. &SetupMsg,
  83. pMacAddress );
  84. return Status;
  85. }
  86. /**
  87. Set the MAC address
  88. This routine calls ::Ax88772UsbCommand to set the MAC address
  89. in the network adapter.
  90. @param [in] pNicDevice Pointer to the NIC_DEVICE structure
  91. @param [in] pMacAddress Address of a six byte buffer to containing the new MAC address.
  92. @retval EFI_SUCCESS The MAC address was set.
  93. @retval other The MAC address was not set.
  94. **/
  95. EFI_STATUS
  96. Ax88772MacAddressSet (
  97. IN NIC_DEVICE * pNicDevice,
  98. IN UINT8 * pMacAddress
  99. )
  100. {
  101. USB_DEVICE_REQUEST SetupMsg;
  102. EFI_STATUS Status;
  103. //
  104. // Set the register address.
  105. //
  106. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  107. | USB_TARGET_DEVICE;
  108. SetupMsg.Request = CMD_MAC_ADDRESS_WRITE;
  109. SetupMsg.Value = 0;
  110. SetupMsg.Index = 0;
  111. SetupMsg.Length = PXE_HWADDR_LEN_ETHER;
  112. //
  113. // Read the PHY register
  114. //
  115. Status = Ax88772UsbCommand ( pNicDevice,
  116. &SetupMsg,
  117. pMacAddress );
  118. return Status;
  119. }
  120. /**
  121. Clear the multicast hash table
  122. @param [in] pNicDevice Pointer to the NIC_DEVICE structure
  123. **/
  124. VOID
  125. Ax88772MulticastClear (
  126. IN NIC_DEVICE * pNicDevice
  127. )
  128. {
  129. int i = 0;
  130. //
  131. // Clear the multicast hash table
  132. //
  133. for ( i = 0 ; i < 8 ; i ++ )
  134. pNicDevice->MulticastHash[0] = 0;
  135. }
  136. /**
  137. Enable a multicast address in the multicast hash table
  138. This routine calls ::Ax88772Crc to compute the hash bit for
  139. this MAC address.
  140. @param [in] pNicDevice Pointer to the NIC_DEVICE structure
  141. @param [in] pMacAddress Address of a six byte buffer to containing the MAC address.
  142. **/
  143. VOID
  144. Ax88772MulticastSet (
  145. IN NIC_DEVICE * pNicDevice,
  146. IN UINT8 * pMacAddress
  147. )
  148. {
  149. UINT32 Crc;
  150. //
  151. // Compute the CRC on the destination address
  152. //
  153. Crc = Ax88772Crc ( pMacAddress ) >> 26;
  154. //
  155. // Set the bit corresponding to the destination address
  156. //
  157. pNicDevice->MulticastHash [ Crc >> 3 ] |= ( 1<< (Crc& 7));
  158. }
  159. /**
  160. Start the link negotiation
  161. This routine calls ::Ax88772PhyWrite to start the PHY's link
  162. negotiation.
  163. @param [in] pNicDevice Pointer to the NIC_DEVICE structure
  164. @retval EFI_SUCCESS The link negotiation was started.
  165. @retval other Failed to start the link negotiation.
  166. **/
  167. EFI_STATUS
  168. Ax88772NegotiateLinkStart (
  169. IN NIC_DEVICE * pNicDevice
  170. )
  171. {
  172. UINT16 Control;
  173. EFI_STATUS Status;
  174. int i;
  175. //
  176. // Set the supported capabilities.
  177. //
  178. Status = Ax88772PhyWrite ( pNicDevice,
  179. PHY_ANAR,
  180. AN_CSMA_CD
  181. | AN_TX_FDX | AN_TX_HDX
  182. | AN_10_FDX | AN_10_HDX );
  183. if ( !EFI_ERROR ( Status )) {
  184. //
  185. // Set the link speed and duplex
  186. //
  187. Control = BMCR_AUTONEGOTIATION_ENABLE
  188. | BMCR_RESTART_AUTONEGOTIATION;
  189. if ( pNicDevice->b100Mbps ) {
  190. Control |= BMCR_100MBPS;
  191. }
  192. if ( pNicDevice->bFullDuplex ) {
  193. Control |= BMCR_FULL_DUPLEX;
  194. }
  195. Status = Ax88772PhyWrite ( pNicDevice, PHY_BMCR, Control );
  196. }
  197. if (!EFI_ERROR(Status)) {
  198. i = 0;
  199. do {
  200. if (pNicDevice->bComplete && pNicDevice->bLinkUp) {
  201. pNicDevice->SimpleNetwork.Mode->MediaPresent
  202. = pNicDevice->bLinkUp & pNicDevice->bComplete;
  203. break;
  204. }
  205. else {
  206. gBS->Stall(AUTONEG_DELAY);
  207. Status = Ax88772NegotiateLinkComplete ( pNicDevice,
  208. &pNicDevice->PollCount,
  209. &pNicDevice->bComplete,
  210. &pNicDevice->bLinkUp,
  211. &pNicDevice->b100Mbps,
  212. &pNicDevice->bFullDuplex );
  213. i++;
  214. }
  215. }while(!pNicDevice->bLinkUp && i < AUTONEG_POLLCNT);
  216. }
  217. return Status;
  218. }
  219. /**
  220. Complete the negotiation of the PHY link
  221. This routine calls ::Ax88772PhyRead to determine if the
  222. link negotiation is complete.
  223. @param [in] pNicDevice Pointer to the NIC_DEVICE structure
  224. @param [in, out] pPollCount Address of number of times this routine was polled
  225. @param [out] pbComplete Address of boolean to receive complate status.
  226. @param [out] pbLinkUp Address of boolean to receive link status, TRUE=up.
  227. @param [out] pbHiSpeed Address of boolean to receive link speed, TRUE=100Mbps.
  228. @param [out] pbFullDuplex Address of boolean to receive link duplex, TRUE=full.
  229. @retval EFI_SUCCESS The MAC address is available.
  230. @retval other The MAC address is not valid.
  231. **/
  232. EFI_STATUS
  233. Ax88772NegotiateLinkComplete (
  234. IN NIC_DEVICE * pNicDevice,
  235. IN OUT UINTN * pPollCount,
  236. OUT BOOLEAN * pbComplete,
  237. OUT BOOLEAN * pbLinkUp,
  238. OUT BOOLEAN * pbHiSpeed,
  239. OUT BOOLEAN * pbFullDuplex
  240. )
  241. {
  242. UINT16 Mask;
  243. UINT16 PhyData;
  244. EFI_STATUS Status;
  245. //
  246. // Determine if the link is up.
  247. //
  248. *pbComplete = FALSE;
  249. //
  250. // Get the link status
  251. //
  252. Status = Ax88772PhyRead ( pNicDevice,
  253. PHY_BMSR,
  254. &PhyData );
  255. if ( !EFI_ERROR ( Status )) {
  256. *pbLinkUp = (BOOLEAN)( 0 != ( PhyData & BMSR_LINKST ));
  257. if ( 0 == *pbLinkUp ) {
  258. DEBUG (( EFI_D_INFO, "Link Down\n" ));
  259. }
  260. else {
  261. *pbComplete = (BOOLEAN)( 0 != ( PhyData & 0x20 ));
  262. if ( 0 == *pbComplete ) {
  263. DEBUG (( EFI_D_INFO, "Autoneg is not yet Complete\n" ));
  264. }
  265. else {
  266. Status = Ax88772PhyRead ( pNicDevice,
  267. PHY_ANLPAR,
  268. &PhyData );
  269. if ( !EFI_ERROR ( Status )) {
  270. //
  271. // Autonegotiation is complete
  272. // Determine the link speed.
  273. //
  274. *pbHiSpeed = (BOOLEAN)( 0 != ( PhyData & ( AN_TX_FDX | AN_TX_HDX )));
  275. //
  276. // Determine the link duplex.
  277. //
  278. Mask = ( *pbHiSpeed ) ? AN_TX_FDX : AN_10_FDX;
  279. *pbFullDuplex = (BOOLEAN)( 0 != ( PhyData & Mask ));
  280. }
  281. }
  282. }
  283. }
  284. else {
  285. DEBUG (( EFI_D_ERROR, "Failed to read BMCR\n" ));
  286. }
  287. return Status;
  288. }
  289. /**
  290. Read a register from the PHY
  291. This routine calls ::Ax88772UsbCommand to read a PHY register.
  292. @param [in] pNicDevice Pointer to the NIC_DEVICE structure
  293. @param [in] RegisterAddress Number of the register to read.
  294. @param [in, out] pPhyData Address of a buffer to receive the PHY register value
  295. @retval EFI_SUCCESS The PHY data is available.
  296. @retval other The PHY data is not valid.
  297. **/
  298. EFI_STATUS
  299. Ax88772PhyRead (
  300. IN NIC_DEVICE * pNicDevice,
  301. IN UINT8 RegisterAddress,
  302. IN OUT UINT16 * pPhyData
  303. )
  304. {
  305. USB_DEVICE_REQUEST SetupMsg;
  306. EFI_STATUS Status;
  307. //
  308. // Request access to the PHY
  309. //
  310. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  311. | USB_TARGET_DEVICE;
  312. SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE;
  313. SetupMsg.Value = 0;
  314. SetupMsg.Index = 0;
  315. SetupMsg.Length = 0;
  316. Status = Ax88772UsbCommand ( pNicDevice,
  317. &SetupMsg,
  318. NULL );
  319. if ( !EFI_ERROR ( Status )) {
  320. //
  321. // Read the PHY register address.
  322. //
  323. SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
  324. | USB_REQ_TYPE_VENDOR
  325. | USB_TARGET_DEVICE;
  326. SetupMsg.Request = CMD_PHY_REG_READ;
  327. SetupMsg.Value = pNicDevice->PhyId;
  328. SetupMsg.Index = RegisterAddress;
  329. SetupMsg.Length = sizeof ( *pPhyData );
  330. Status = Ax88772UsbCommand ( pNicDevice,
  331. &SetupMsg,
  332. pPhyData );
  333. if ( !EFI_ERROR ( Status )) {
  334. //
  335. // Release the PHY to the hardware
  336. //
  337. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  338. | USB_TARGET_DEVICE;
  339. SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE;
  340. SetupMsg.Value = 0;
  341. SetupMsg.Index = 0;
  342. SetupMsg.Length = 0;
  343. Status = Ax88772UsbCommand ( pNicDevice,
  344. &SetupMsg,
  345. NULL );
  346. }
  347. }
  348. return Status;
  349. }
  350. /**
  351. Write to a PHY register
  352. This routine calls ::Ax88772UsbCommand to write a PHY register.
  353. @param [in] pNicDevice Pointer to the NIC_DEVICE structure
  354. @param [in] RegisterAddress Number of the register to read.
  355. @param [in] PhyData Address of a buffer to receive the PHY register value
  356. @retval EFI_SUCCESS The PHY data was written.
  357. @retval other Failed to wwrite the PHY register.
  358. **/
  359. EFI_STATUS
  360. Ax88772PhyWrite (
  361. IN NIC_DEVICE * pNicDevice,
  362. IN UINT8 RegisterAddress,
  363. IN UINT16 PhyData
  364. )
  365. {
  366. USB_DEVICE_REQUEST SetupMsg;
  367. EFI_STATUS Status;
  368. //
  369. // Request access to the PHY
  370. //
  371. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  372. | USB_TARGET_DEVICE;
  373. SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE;
  374. SetupMsg.Value = 0;
  375. SetupMsg.Index = 0;
  376. SetupMsg.Length = 0;
  377. Status = Ax88772UsbCommand ( pNicDevice,
  378. &SetupMsg,
  379. NULL );
  380. if ( !EFI_ERROR ( Status )) {
  381. //
  382. // Write the PHY register
  383. //
  384. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  385. | USB_TARGET_DEVICE;
  386. SetupMsg.Request = CMD_PHY_REG_WRITE;
  387. SetupMsg.Value = pNicDevice->PhyId;
  388. SetupMsg.Index = RegisterAddress;
  389. SetupMsg.Length = sizeof ( PhyData );
  390. Status = Ax88772UsbCommand ( pNicDevice,
  391. &SetupMsg,
  392. &PhyData );
  393. if ( !EFI_ERROR ( Status )) {
  394. //
  395. // Release the PHY to the hardware
  396. //
  397. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  398. | USB_TARGET_DEVICE;
  399. SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE;
  400. SetupMsg.Value = 0;
  401. SetupMsg.Index = 0;
  402. SetupMsg.Length = 0;
  403. Status = Ax88772UsbCommand ( pNicDevice,
  404. &SetupMsg,
  405. NULL );
  406. }
  407. }
  408. return Status;
  409. }
  410. /**
  411. Reset the AX88772
  412. This routine uses ::Ax88772UsbCommand to reset the network
  413. adapter. This routine also uses ::Ax88772PhyWrite to reset
  414. the PHY.
  415. @param [in] pNicDevice Pointer to the NIC_DEVICE structure
  416. @retval EFI_SUCCESS The MAC address is available.
  417. @retval other The MAC address is not valid.
  418. **/
  419. EFI_STATUS
  420. Ax88772Reset (
  421. IN NIC_DEVICE * pNicDevice
  422. )
  423. {
  424. USB_DEVICE_REQUEST SetupMsg;
  425. EFI_STATUS Status;
  426. EFI_USB_IO_PROTOCOL *pUsbIo;
  427. EFI_USB_DEVICE_DESCRIPTOR Device;
  428. pUsbIo = pNicDevice->pUsbIo;
  429. Status = pUsbIo->UsbGetDeviceDescriptor ( pUsbIo, &Device );
  430. if (EFI_ERROR(Status)) goto err;
  431. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  432. | USB_TARGET_DEVICE;
  433. SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE;
  434. SetupMsg.Value = 0;
  435. SetupMsg.Index = 0;
  436. SetupMsg.Length = 0;
  437. Status = Ax88772UsbCommand ( pNicDevice,
  438. &SetupMsg,
  439. NULL );
  440. if (EFI_ERROR(Status)) goto err;
  441. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  442. | USB_TARGET_DEVICE;
  443. SetupMsg.Request = CMD_PHY_SELECT;
  444. SetupMsg.Value = SPHY_PSEL;
  445. SetupMsg.Index = 0;
  446. SetupMsg.Length = 0;
  447. Status = Ax88772UsbCommand ( pNicDevice,
  448. &SetupMsg,
  449. NULL );
  450. if (EFI_ERROR(Status)) goto err;
  451. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  452. | USB_TARGET_DEVICE;
  453. SetupMsg.Request = CMD_RESET;
  454. SetupMsg.Value = SRR_IPRL ;
  455. SetupMsg.Index = 0;
  456. SetupMsg.Length = 0;
  457. Status = Ax88772UsbCommand ( pNicDevice,
  458. &SetupMsg,
  459. NULL );
  460. if (EFI_ERROR(Status)) goto err;
  461. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  462. | USB_TARGET_DEVICE;
  463. SetupMsg.Request = CMD_RESET;
  464. SetupMsg.Value = SRR_IPPD | SRR_IPRL ;
  465. SetupMsg.Index = 0;
  466. SetupMsg.Length = 0;
  467. Status = Ax88772UsbCommand ( pNicDevice,
  468. &SetupMsg,
  469. NULL );
  470. gBS->Stall ( 200000 );
  471. if (EFI_ERROR(Status)) goto err;
  472. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  473. | USB_TARGET_DEVICE;
  474. SetupMsg.Request = CMD_RESET;
  475. SetupMsg.Value = SRR_IPRL ;
  476. SetupMsg.Index = 0;
  477. SetupMsg.Length = 0;
  478. Status = Ax88772UsbCommand ( pNicDevice,
  479. &SetupMsg,
  480. NULL );
  481. gBS->Stall ( 200000 );
  482. if (EFI_ERROR(Status)) goto err;
  483. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  484. | USB_TARGET_DEVICE;
  485. SetupMsg.Request = CMD_RESET;
  486. SetupMsg.Value = 0;
  487. SetupMsg.Index = 0;
  488. SetupMsg.Length = 0;
  489. Status = Ax88772UsbCommand ( pNicDevice,
  490. &SetupMsg,
  491. NULL );
  492. if (EFI_ERROR(Status)) goto err;
  493. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  494. | USB_TARGET_DEVICE;
  495. SetupMsg.Request = CMD_PHY_SELECT;
  496. SetupMsg.Value = SPHY_PSEL;
  497. SetupMsg.Index = 0;
  498. SetupMsg.Length = 0;
  499. Status = Ax88772UsbCommand ( pNicDevice,
  500. &SetupMsg,
  501. NULL );
  502. if (EFI_ERROR(Status)) goto err;
  503. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  504. | USB_TARGET_DEVICE;
  505. SetupMsg.Request = CMD_RESET;
  506. SetupMsg.Value = SRR_IPRL | SRR_BZ | SRR_BZTYPE;
  507. SetupMsg.Index = 0;
  508. SetupMsg.Length = 0;
  509. Status = Ax88772UsbCommand ( pNicDevice,
  510. &SetupMsg,
  511. NULL );
  512. if (EFI_ERROR(Status)) goto err;
  513. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  514. | USB_TARGET_DEVICE;
  515. SetupMsg.Request = CMD_RX_CONTROL_WRITE;
  516. SetupMsg.Value = 0;
  517. SetupMsg.Index = 0;
  518. SetupMsg.Length = 0;
  519. Status = Ax88772UsbCommand ( pNicDevice,
  520. &SetupMsg,
  521. NULL );
  522. if (EFI_ERROR(Status)) goto err;
  523. if (pNicDevice->Flags != FLAG_TYPE_AX88772) {
  524. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  525. | USB_TARGET_DEVICE;
  526. SetupMsg.Request = CMD_RXQTC;
  527. SetupMsg.Value = 0x8000;
  528. SetupMsg.Index = 0x8001;
  529. SetupMsg.Length = 0;
  530. Status = Ax88772UsbCommand ( pNicDevice,
  531. &SetupMsg,
  532. NULL );
  533. }
  534. err:
  535. return Status;
  536. }
  537. /**
  538. Enable or disable the receiver
  539. This routine calls ::Ax88772UsbCommand to update the
  540. receiver state. This routine also calls ::Ax88772MacAddressSet
  541. to establish the MAC address for the network adapter.
  542. @param [in] pNicDevice Pointer to the NIC_DEVICE structure
  543. @param [in] RxFilter Simple network RX filter mask value
  544. @retval EFI_SUCCESS The MAC address was set.
  545. @retval other The MAC address was not set.
  546. **/
  547. EFI_STATUS
  548. Ax88772RxControl (
  549. IN NIC_DEVICE * pNicDevice,
  550. IN UINT32 RxFilter
  551. )
  552. {
  553. UINT16 MediumStatus;
  554. UINT16 RxControl;
  555. USB_DEVICE_REQUEST SetupMsg;
  556. EFI_STATUS Status;
  557. EFI_USB_IO_PROTOCOL *pUsbIo;
  558. EFI_USB_DEVICE_DESCRIPTOR Device;
  559. pUsbIo = pNicDevice->pUsbIo;
  560. Status = pUsbIo->UsbGetDeviceDescriptor ( pUsbIo, &Device );
  561. if (EFI_ERROR(Status)) {
  562. DEBUG (( EFI_D_ERROR, "Failed to get device descriptor\n" ));
  563. return Status;
  564. }
  565. //
  566. // Enable the receiver if something is to be received
  567. //
  568. if ( 0 != RxFilter ) {
  569. //
  570. // Enable the receiver
  571. //
  572. SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
  573. | USB_REQ_TYPE_VENDOR
  574. | USB_TARGET_DEVICE;
  575. SetupMsg.Request = CMD_MEDIUM_STATUS_READ;
  576. SetupMsg.Value = 0;
  577. SetupMsg.Index = 0;
  578. SetupMsg.Length = sizeof ( MediumStatus );
  579. Status = Ax88772UsbCommand ( pNicDevice,
  580. &SetupMsg,
  581. &MediumStatus );
  582. if ( !EFI_ERROR ( Status )) {
  583. if ( 0 == ( MediumStatus & MS_RE )) {
  584. MediumStatus |= MS_RE | MS_ONE;
  585. if ( pNicDevice->bFullDuplex )
  586. MediumStatus |= MS_TFC | MS_RFC | MS_FD;
  587. else
  588. MediumStatus &= ~(MS_TFC | MS_RFC | MS_FD);
  589. if ( pNicDevice->b100Mbps )
  590. MediumStatus |= MS_PS;
  591. else
  592. MediumStatus &= ~MS_PS;
  593. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  594. | USB_TARGET_DEVICE;
  595. SetupMsg.Request = CMD_MEDIUM_STATUS_WRITE;
  596. SetupMsg.Value = MediumStatus;
  597. SetupMsg.Index = 0;
  598. SetupMsg.Length = 0;
  599. Status = Ax88772UsbCommand ( pNicDevice,
  600. &SetupMsg,
  601. NULL );
  602. if ( EFI_ERROR ( Status )) {
  603. DEBUG (( EFI_D_ERROR, "Failed to enable receiver, Status: %r\r\n",
  604. Status ));
  605. }
  606. }
  607. }
  608. else {
  609. DEBUG (( EFI_D_ERROR, "Failed to read receiver status, Status: %r\r\n",
  610. Status ));
  611. }
  612. }
  613. RxControl = RXC_SO | RXC_RH1M;
  614. //
  615. // Enable multicast if requested
  616. //
  617. if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST )) {
  618. RxControl |= RXC_AM;
  619. //
  620. // Update the multicast hash table
  621. //
  622. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  623. | USB_TARGET_DEVICE;
  624. SetupMsg.Request = CMD_MULTICAST_HASH_WRITE;
  625. SetupMsg.Value = 0;
  626. SetupMsg.Index = 0;
  627. SetupMsg.Length = sizeof ( pNicDevice ->MulticastHash );
  628. Status = Ax88772UsbCommand ( pNicDevice,
  629. &SetupMsg,
  630. &pNicDevice->MulticastHash );
  631. }
  632. //
  633. // Enable all multicast if requested
  634. //
  635. if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST )) {
  636. RxControl |= RXC_AMALL;
  637. }
  638. //
  639. // Enable broadcast if requested
  640. //
  641. if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST )) {
  642. RxControl |= RXC_AB;
  643. }
  644. //
  645. // Enable promiscuous mode if requested
  646. //
  647. if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS )) {
  648. RxControl |= RXC_PRO;
  649. }
  650. //
  651. // Update the receiver control
  652. //
  653. if (pNicDevice->CurRxControl != RxControl) {
  654. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  655. | USB_TARGET_DEVICE;
  656. SetupMsg.Request = CMD_RX_CONTROL_WRITE;
  657. SetupMsg.Value = RxControl;
  658. SetupMsg.Index = 0;
  659. SetupMsg.Length = 0;
  660. Status = Ax88772UsbCommand ( pNicDevice,
  661. &SetupMsg,
  662. NULL );
  663. if ( !EFI_ERROR ( Status )) {
  664. pNicDevice->CurRxControl = RxControl;
  665. }
  666. else {
  667. DEBUG (( EFI_D_ERROR, "ERROR - Failed to set receiver control, Status: %r\r\n",
  668. Status ));
  669. }
  670. }
  671. return Status;
  672. }
  673. /**
  674. Read an SROM location
  675. This routine calls ::Ax88772UsbCommand to read data from the
  676. SROM.
  677. @param [in] pNicDevice Pointer to the NIC_DEVICE structure
  678. @param [in] Address SROM address
  679. @param [out] pData Buffer to receive the data
  680. @retval EFI_SUCCESS The read was successful
  681. @retval other The read failed
  682. **/
  683. EFI_STATUS
  684. Ax88772SromRead (
  685. IN NIC_DEVICE * pNicDevice,
  686. IN UINT32 Address,
  687. OUT UINT16 * pData
  688. )
  689. {
  690. return EFI_UNSUPPORTED;
  691. }
  692. /**
  693. Send a command to the USB device.
  694. @param [in] pNicDevice Pointer to the NIC_DEVICE structure
  695. @param [in] pRequest Pointer to the request structure
  696. @param [in, out] pBuffer Data buffer address
  697. @retval EFI_SUCCESS The USB transfer was successful
  698. @retval other The USB transfer failed
  699. **/
  700. EFI_STATUS
  701. Ax88772UsbCommand (
  702. IN NIC_DEVICE * pNicDevice,
  703. IN USB_DEVICE_REQUEST * pRequest,
  704. IN OUT VOID * pBuffer
  705. )
  706. {
  707. UINT32 CmdStatus;
  708. EFI_USB_DATA_DIRECTION Direction;
  709. EFI_USB_IO_PROTOCOL * pUsbIo;
  710. EFI_STATUS Status;
  711. //
  712. // Determine the transfer direction
  713. //
  714. Direction = EfiUsbNoData;
  715. if ( 0 != pRequest->Length ) {
  716. Direction = ( 0 != ( pRequest->RequestType & USB_ENDPOINT_DIR_IN ))
  717. ? EfiUsbDataIn : EfiUsbDataOut;
  718. }
  719. //
  720. // Issue the command
  721. //
  722. pUsbIo = pNicDevice->pUsbIo;
  723. Status = pUsbIo->UsbControlTransfer ( pUsbIo,
  724. pRequest,
  725. Direction,
  726. USB_BUS_TIMEOUT,
  727. pBuffer,
  728. pRequest->Length,
  729. &CmdStatus );
  730. //
  731. // Determine the operation status
  732. //
  733. if ( !EFI_ERROR ( Status )) {
  734. Status = CmdStatus;
  735. }
  736. else {
  737. //
  738. // Only use status values associated with the Simple Network protocol
  739. //
  740. if ( EFI_TIMEOUT == Status ) {
  741. Status = EFI_DEVICE_ERROR;
  742. }
  743. }
  744. return Status;
  745. }