Ax88772.c 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300
  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. Copyright (c) 2020, ARM Limited. All rights reserved.
  8. SPDX-License-Identifier: BSD-2-Clause-Patent
  9. **/
  10. #include "Ax88772.h"
  11. /**
  12. Compute the CRC
  13. @param [in] MacAddress Address of a six byte buffer to containing the MAC address.
  14. @returns The CRC-32 value associated with this MAC address
  15. **/
  16. UINT32
  17. Ax88772Crc (
  18. IN UINT8 *MacAddress
  19. )
  20. {
  21. UINT32 BitNumber;
  22. INT32 Carry;
  23. INT32 Crc;
  24. UINT32 Data;
  25. UINT8 *End;
  26. //
  27. // Walk the MAC address
  28. //
  29. Crc = -1;
  30. End = &MacAddress[PXE_HWADDR_LEN_ETHER];
  31. while (End > MacAddress) {
  32. Data = *MacAddress++;
  33. //
  34. // CRC32: x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
  35. //
  36. // 1 0000 0100 1100 0001 0001 1101 1011 0111
  37. //
  38. for (BitNumber = 0; 8 > BitNumber; BitNumber++) {
  39. Carry = ((Crc >> 31) & 1) ^ (Data & 1);
  40. Crc <<= 1;
  41. if (Carry != 0) {
  42. Crc ^= 0x04c11db7;
  43. }
  44. Data >>= 1;
  45. }
  46. }
  47. //
  48. // Return the CRC value
  49. //
  50. return (UINT32) Crc;
  51. }
  52. /**
  53. Get the MAC address
  54. This routine calls ::Ax88772UsbCommand to request the MAC
  55. address from the network adapter.
  56. @param [in] NicDevice Pointer to the NIC_DEVICE structure
  57. @param [out] MacAddress Address of a six byte buffer to receive the MAC address.
  58. @retval EFI_SUCCESS The MAC address is available.
  59. @retval other The MAC address is not valid.
  60. **/
  61. EFI_STATUS
  62. Ax88772MacAddressGet (
  63. IN NIC_DEVICE *NicDevice,
  64. OUT UINT8 *MacAddress
  65. )
  66. {
  67. USB_DEVICE_REQUEST SetupMsg;
  68. EFI_STATUS Status;
  69. //
  70. // Set the register address.
  71. //
  72. SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
  73. | USB_REQ_TYPE_VENDOR
  74. | USB_TARGET_DEVICE;
  75. SetupMsg.Request = CMD_MAC_ADDRESS_READ;
  76. SetupMsg.Value = 0;
  77. SetupMsg.Index = 0;
  78. SetupMsg.Length = PXE_HWADDR_LEN_ETHER;
  79. //
  80. // Read the PHY register
  81. //
  82. Status = Ax88772UsbCommand (NicDevice,
  83. &SetupMsg,
  84. MacAddress);
  85. //
  86. // Return the operation status
  87. //
  88. return Status;
  89. }
  90. /**
  91. Set the MAC address
  92. This routine calls ::Ax88772UsbCommand to set the MAC address
  93. in the network adapter.
  94. @param [in] NicDevice Pointer to the NIC_DEVICE structure
  95. @param [in] MacAddress Address of a six byte buffer to containing the new MAC address.
  96. @retval EFI_SUCCESS The MAC address was set.
  97. @retval other The MAC address was not set.
  98. **/
  99. EFI_STATUS
  100. Ax88772MacAddressSet (
  101. IN NIC_DEVICE *NicDevice,
  102. IN UINT8 *MacAddress
  103. )
  104. {
  105. USB_DEVICE_REQUEST SetupMsg;
  106. EFI_STATUS Status;
  107. //
  108. // Set the register address.
  109. //
  110. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  111. | USB_TARGET_DEVICE;
  112. SetupMsg.Request = CMD_MAC_ADDRESS_WRITE;
  113. SetupMsg.Value = 0;
  114. SetupMsg.Index = 0;
  115. SetupMsg.Length = PXE_HWADDR_LEN_ETHER;
  116. //
  117. // Read the PHY register
  118. //
  119. Status = Ax88772UsbCommand (NicDevice,
  120. &SetupMsg,
  121. MacAddress);
  122. //
  123. // Return the operation status
  124. //
  125. return Status;
  126. }
  127. /**
  128. Clear the multicast hash table
  129. @param [in] NicDevice Pointer to the NIC_DEVICE structure
  130. **/
  131. VOID
  132. Ax88772MulticastClear (
  133. IN NIC_DEVICE *NicDevice
  134. )
  135. {
  136. int Index = 0;
  137. //
  138. // Clear the multicast hash table
  139. //
  140. for (Index = 0 ; Index < 8 ; Index ++)
  141. NicDevice->MulticastHash[Index] = 0;
  142. }
  143. /**
  144. Enable a multicast address in the multicast hash table
  145. This routine calls ::Ax88772Crc to compute the hash bit for
  146. this MAC address.
  147. @param [in] NicDevice Pointer to the NIC_DEVICE structure
  148. @param [in] MacAddress Address of a six byte buffer to containing the MAC address.
  149. **/
  150. VOID
  151. Ax88772MulticastSet (
  152. IN NIC_DEVICE *NicDevice,
  153. IN UINT8 *MacAddress
  154. )
  155. {
  156. UINT32 Crc;
  157. //
  158. // Compute the CRC on the destination address
  159. //
  160. Crc = Ax88772Crc (MacAddress) >> 26;
  161. //
  162. // Set the bit corresponding to the destination address
  163. //
  164. NicDevice->MulticastHash [Crc >> 3] |= (1 << (Crc & 7));
  165. }
  166. /**
  167. Start the link negotiation
  168. This routine calls ::Ax88772PhyWrite to start the PHY's link
  169. negotiation.
  170. @param [in] NicDevice Pointer to the NIC_DEVICE structure
  171. @retval EFI_SUCCESS The link negotiation was started.
  172. @retval other Failed to start the link negotiation.
  173. **/
  174. EFI_STATUS
  175. Ax88772NegotiateLinkStart (
  176. IN NIC_DEVICE *NicDevice
  177. )
  178. {
  179. UINT16 Control;
  180. EFI_STATUS Status;
  181. //
  182. // Set the supported capabilities.
  183. //
  184. Status = Ax88772PhyWrite (NicDevice,
  185. PHY_ANAR,
  186. AN_CSMA_CD
  187. | AN_TX_FDX | AN_TX_HDX
  188. | AN_10_FDX | AN_10_HDX | AN_FCS);
  189. if (!EFI_ERROR (Status)) {
  190. //
  191. // Set the link speed and duplex
  192. //
  193. Control = BMCR_AUTONEGOTIATION_ENABLE
  194. | BMCR_RESTART_AUTONEGOTIATION;
  195. if (NicDevice->LinkSpeed100Mbps) {
  196. Control |= BMCR_100MBPS;
  197. }
  198. if (NicDevice->FullDuplex) {
  199. Control |= BMCR_FULL_DUPLEX;
  200. }
  201. Status = Ax88772PhyWrite (NicDevice, PHY_BMCR, Control);
  202. if (!EFI_ERROR(Status))
  203. gBS->Stall(3000000);
  204. }
  205. return Status;
  206. }
  207. /**
  208. Complete the negotiation of the PHY link
  209. This routine calls ::Ax88772PhyRead to determine if the
  210. link negotiation is complete.
  211. @param [in] NicDevice Pointer to the NIC_DEVICE structure
  212. @param [in, out] PollCount Address of number of times this routine was polled
  213. @param [out] Complete Address of boolean to receive complate status.
  214. @param [out] LinkUp Address of boolean to receive link status, TRUE=up.
  215. @param [out] HiSpeed Address of boolean to receive link speed, TRUE=100Mbps.
  216. @param [out] FullDuplex Address of boolean to receive link duplex, TRUE=full.
  217. @retval EFI_SUCCESS The MAC address is available.
  218. @retval other The MAC address is not valid.
  219. **/
  220. EFI_STATUS
  221. Ax88772NegotiateLinkComplete (
  222. IN NIC_DEVICE *NicDevice,
  223. IN OUT UINTN *PollCount,
  224. OUT BOOLEAN *Complete,
  225. OUT BOOLEAN *LinkUp,
  226. OUT BOOLEAN *HiSpeed,
  227. OUT BOOLEAN *FullDuplex
  228. )
  229. {
  230. UINT16 Mask;
  231. UINT16 PhyData;
  232. EFI_STATUS Status;
  233. //
  234. // Determine if the link is up.
  235. //
  236. *Complete = FALSE;
  237. //
  238. // Get the link status
  239. //
  240. Status = Ax88772PhyRead (NicDevice,
  241. PHY_BMSR,
  242. &PhyData);
  243. if (EFI_ERROR (Status)) {
  244. return Status;
  245. }
  246. *LinkUp = ((PhyData & BMSR_LINKST) != 0);
  247. if (0 == *LinkUp) {
  248. } else {
  249. *Complete = ((PhyData & 0x20) != 0);
  250. if (0 == *Complete) {
  251. } else {
  252. Status = Ax88772PhyRead (NicDevice,
  253. PHY_ANLPAR,
  254. &PhyData);
  255. if (!EFI_ERROR (Status)) {
  256. //
  257. // Autonegotiation is complete
  258. // Determine the link speed.
  259. //
  260. *HiSpeed = ((PhyData & (AN_TX_FDX | AN_TX_HDX))!= 0);
  261. //
  262. // Determine the link duplex.
  263. //
  264. Mask = (*HiSpeed) ? AN_TX_FDX : AN_10_FDX;
  265. *FullDuplex = (BOOLEAN)((PhyData & Mask) != 0);
  266. }
  267. }
  268. }
  269. return Status;
  270. }
  271. /**
  272. Read a register from the PHY
  273. This routine calls ::Ax88772UsbCommand to read a PHY register.
  274. @param [in] NicDevice Pointer to the NIC_DEVICE structure
  275. @param [in] RegisterAddress Number of the register to read.
  276. @param [in, out] PhyData Address of a buffer to receive the PHY register value
  277. @retval EFI_SUCCESS The PHY data is available.
  278. @retval other The PHY data is not valid.
  279. **/
  280. EFI_STATUS
  281. Ax88772PhyRead (
  282. IN NIC_DEVICE *NicDevice,
  283. IN UINT8 RegisterAddress,
  284. IN OUT UINT16 *PhyData
  285. )
  286. {
  287. USB_DEVICE_REQUEST SetupMsg;
  288. EFI_STATUS Status;
  289. //
  290. // Request access to the PHY
  291. //
  292. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  293. | USB_TARGET_DEVICE;
  294. SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE;
  295. SetupMsg.Value = 0;
  296. SetupMsg.Index = 0;
  297. SetupMsg.Length = 0;
  298. Status = Ax88772UsbCommand (NicDevice,
  299. &SetupMsg,
  300. NULL);
  301. if (EFI_ERROR (Status)) {
  302. return Status;
  303. }
  304. //
  305. // Read the PHY register address.
  306. //
  307. SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
  308. | USB_REQ_TYPE_VENDOR
  309. | USB_TARGET_DEVICE;
  310. SetupMsg.Request = CMD_PHY_REG_READ;
  311. SetupMsg.Value = NicDevice->PhyId;
  312. SetupMsg.Index = RegisterAddress;
  313. SetupMsg.Length = sizeof(*PhyData);
  314. Status = Ax88772UsbCommand(NicDevice,
  315. &SetupMsg,
  316. PhyData);
  317. if (EFI_ERROR (Status)) {
  318. return Status;
  319. }
  320. //
  321. // Release the PHY to the hardware
  322. //
  323. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  324. | USB_TARGET_DEVICE;
  325. SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE;
  326. SetupMsg.Value = 0;
  327. SetupMsg.Index = 0;
  328. SetupMsg.Length = 0;
  329. Status = Ax88772UsbCommand(NicDevice,
  330. &SetupMsg,
  331. NULL);
  332. //
  333. // Return the operation status.
  334. //
  335. return Status;
  336. }
  337. /**
  338. Write to a PHY register
  339. This routine calls ::Ax88772UsbCommand to write a PHY register.
  340. @param [in] NicDevice Pointer to the NIC_DEVICE structure
  341. @param [in] RegisterAddress Number of the register to read.
  342. @param [in] PhyData Address of a buffer to receive the PHY register value
  343. @retval EFI_SUCCESS The PHY data was written.
  344. @retval other Failed to wwrite the PHY register.
  345. **/
  346. EFI_STATUS
  347. Ax88772PhyWrite (
  348. IN NIC_DEVICE *NicDevice,
  349. IN UINT8 RegisterAddress,
  350. IN UINT16 PhyData
  351. )
  352. {
  353. USB_DEVICE_REQUEST SetupMsg;
  354. EFI_STATUS Status;
  355. //
  356. // Request access to the PHY
  357. //
  358. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  359. | USB_TARGET_DEVICE;
  360. SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE;
  361. SetupMsg.Value = 0;
  362. SetupMsg.Index = 0;
  363. SetupMsg.Length = 0;
  364. Status = Ax88772UsbCommand (NicDevice,
  365. &SetupMsg,
  366. NULL);
  367. if (EFI_ERROR (Status)) {
  368. return Status;
  369. }
  370. //
  371. // Write the PHY register
  372. //
  373. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  374. | USB_TARGET_DEVICE;
  375. SetupMsg.Request = CMD_PHY_REG_WRITE;
  376. SetupMsg.Value = NicDevice->PhyId;
  377. SetupMsg.Index = RegisterAddress;
  378. SetupMsg.Length = sizeof (PhyData);
  379. Status = Ax88772UsbCommand (NicDevice,
  380. &SetupMsg,
  381. &PhyData);
  382. if (EFI_ERROR (Status)) {
  383. return Status;
  384. }
  385. //
  386. // Release the PHY to the hardware
  387. //
  388. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  389. | USB_TARGET_DEVICE;
  390. SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE;
  391. SetupMsg.Value = 0;
  392. SetupMsg.Index = 0;
  393. SetupMsg.Length = 0;
  394. Status = Ax88772UsbCommand (NicDevice,
  395. &SetupMsg,
  396. NULL);
  397. //
  398. // Return the operation status.
  399. //
  400. return Status;
  401. }
  402. /**
  403. Reset the AX88772
  404. This routine uses ::Ax88772UsbCommand to reset the network
  405. adapter. This routine also uses ::Ax88772PhyWrite to reset
  406. the PHY.
  407. @param [in] NicDevice Pointer to the NIC_DEVICE structure
  408. @retval EFI_SUCCESS The MAC address is available.
  409. @retval other The MAC address is not valid.
  410. **/
  411. EFI_STATUS
  412. Ax88772Reset (
  413. IN NIC_DEVICE *NicDevice
  414. )
  415. {
  416. USB_DEVICE_REQUEST SetupMsg;
  417. EFI_STATUS Status;
  418. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  419. | USB_TARGET_DEVICE;
  420. SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE;
  421. SetupMsg.Value = 0;
  422. SetupMsg.Index = 0;
  423. SetupMsg.Length = 0;
  424. Status = Ax88772UsbCommand (NicDevice,
  425. &SetupMsg,
  426. NULL);
  427. if (EFI_ERROR(Status)) goto err;
  428. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  429. | USB_TARGET_DEVICE;
  430. SetupMsg.Request = CMD_PHY_SELECT;
  431. SetupMsg.Value = SPHY_PSEL;
  432. SetupMsg.Index = 0;
  433. SetupMsg.Length = 0;
  434. Status = Ax88772UsbCommand (NicDevice,
  435. &SetupMsg,
  436. NULL);
  437. if (EFI_ERROR(Status)) goto err;
  438. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  439. | USB_TARGET_DEVICE;
  440. SetupMsg.Request = CMD_RESET;
  441. SetupMsg.Value = SRR_IPRL ;
  442. SetupMsg.Index = 0;
  443. SetupMsg.Length = 0;
  444. Status = Ax88772UsbCommand (NicDevice,
  445. &SetupMsg,
  446. NULL);
  447. if (EFI_ERROR(Status)) goto err;
  448. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  449. | USB_TARGET_DEVICE;
  450. SetupMsg.Request = CMD_RESET;
  451. SetupMsg.Value = SRR_IPPD | SRR_IPRL ;
  452. SetupMsg.Index = 0;
  453. SetupMsg.Length = 0;
  454. Status = Ax88772UsbCommand (NicDevice,
  455. &SetupMsg,
  456. NULL);
  457. gBS->Stall (200000);
  458. if (EFI_ERROR(Status)) goto err;
  459. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  460. | USB_TARGET_DEVICE;
  461. SetupMsg.Request = CMD_RESET;
  462. SetupMsg.Value = SRR_IPRL ;
  463. SetupMsg.Index = 0;
  464. SetupMsg.Length = 0;
  465. Status = Ax88772UsbCommand (NicDevice,
  466. &SetupMsg,
  467. NULL);
  468. gBS->Stall (200000);
  469. if (EFI_ERROR(Status)) goto err;
  470. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  471. | USB_TARGET_DEVICE;
  472. SetupMsg.Request = CMD_RESET;
  473. SetupMsg.Value = 0;
  474. SetupMsg.Index = 0;
  475. SetupMsg.Length = 0;
  476. Status = Ax88772UsbCommand (NicDevice,
  477. &SetupMsg,
  478. NULL);
  479. if (EFI_ERROR(Status)) goto err;
  480. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  481. | USB_TARGET_DEVICE;
  482. SetupMsg.Request = CMD_PHY_SELECT;
  483. SetupMsg.Value = SPHY_PSEL;
  484. SetupMsg.Index = 0;
  485. SetupMsg.Length = 0;
  486. Status = Ax88772UsbCommand (NicDevice,
  487. &SetupMsg,
  488. NULL);
  489. if (EFI_ERROR(Status)) goto err;
  490. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  491. | USB_TARGET_DEVICE;
  492. SetupMsg.Request = CMD_RESET;
  493. SetupMsg.Value = SRR_IPRL | SRR_BZ | SRR_BZTYPE;
  494. SetupMsg.Index = 0;
  495. SetupMsg.Length = 0;
  496. Status = Ax88772UsbCommand (NicDevice,
  497. &SetupMsg,
  498. NULL);
  499. if (EFI_ERROR(Status)) goto err;
  500. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  501. | USB_TARGET_DEVICE;
  502. SetupMsg.Request = CMD_RX_CONTROL_WRITE;
  503. SetupMsg.Value = 0;
  504. SetupMsg.Index = 0;
  505. SetupMsg.Length = 0;
  506. Status = Ax88772UsbCommand (NicDevice,
  507. &SetupMsg,
  508. NULL);
  509. if (EFI_ERROR(Status)) goto err;
  510. if (!NicDevice->Flag772A) {
  511. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  512. | USB_TARGET_DEVICE;
  513. SetupMsg.Request = CMD_RXQTC;
  514. #if RXTHOU
  515. /*size cannot exceed 3K*/
  516. //SetupMsg.Value = 0x0;
  517. //SetupMsg.Index = 0x8001;
  518. /*size cannot exceed 16K*/
  519. SetupMsg.Value = 0x8300;
  520. SetupMsg.Index = 0x8500;
  521. /*size cannot exceed 32K*/
  522. //SetupMsg.Value = 0x8784;
  523. //SetupMsg.Index = 0x8A00;
  524. SetupMsg.Length = 0;
  525. #else
  526. SetupMsg.Value = 0x8000;
  527. SetupMsg.Index = 0x8001;
  528. #endif
  529. Status = Ax88772UsbCommand (NicDevice,
  530. &SetupMsg,
  531. NULL);
  532. }
  533. err:
  534. return Status;
  535. }
  536. /**
  537. Enable or disable the receiver
  538. This routine calls ::Ax88772UsbCommand to update the
  539. receiver state. This routine also calls ::Ax88772MacAddressSet
  540. to establish the MAC address for the network adapter.
  541. @param [in] NicDevice Pointer to the NIC_DEVICE structure
  542. @param [in] RxFilter Simple network RX filter mask value
  543. @retval EFI_SUCCESS The MAC address was set.
  544. @retval other The MAC address was not set.
  545. **/
  546. EFI_STATUS
  547. Ax88772RxControl (
  548. IN NIC_DEVICE *NicDevice,
  549. IN UINT32 RxFilter
  550. )
  551. {
  552. UINT16 MediumStatus;
  553. UINT16 RxControl;
  554. USB_DEVICE_REQUEST SetupMsg;
  555. EFI_STATUS Status = EFI_SUCCESS;
  556. //
  557. // Enable the receiver if something is to be received
  558. //
  559. if (RxFilter != 0) {
  560. //
  561. // Enable the receiver
  562. //
  563. SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
  564. | USB_REQ_TYPE_VENDOR
  565. | USB_TARGET_DEVICE;
  566. SetupMsg.Request = CMD_MEDIUM_STATUS_READ;
  567. SetupMsg.Value = 0;
  568. SetupMsg.Index = 0;
  569. SetupMsg.Length = sizeof (MediumStatus);
  570. Status = Ax88772UsbCommand (NicDevice,
  571. &SetupMsg,
  572. &MediumStatus);
  573. if (!EFI_ERROR (Status)) {
  574. if (0 == (MediumStatus & MS_RE)) {
  575. MediumStatus |= MS_RE | MS_ONE;
  576. if (NicDevice->FullDuplex)
  577. MediumStatus |= MS_TFC | MS_RFC | MS_FD;
  578. else
  579. MediumStatus &= ~(MS_TFC | MS_RFC | MS_FD);
  580. if (NicDevice->LinkSpeed100Mbps)
  581. MediumStatus |= MS_PS;
  582. else
  583. MediumStatus &= ~MS_PS;
  584. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  585. | USB_TARGET_DEVICE;
  586. SetupMsg.Request = CMD_MEDIUM_STATUS_WRITE;
  587. SetupMsg.Value = MediumStatus;
  588. SetupMsg.Index = 0;
  589. SetupMsg.Length = 0;
  590. Status = Ax88772UsbCommand (NicDevice,
  591. &SetupMsg,
  592. NULL);
  593. if (EFI_ERROR(Status))
  594. goto EXIT;
  595. }
  596. } else {
  597. goto EXIT;
  598. }
  599. }
  600. RxControl = RXC_SO;
  601. if (!NicDevice->Flag772A)
  602. RxControl |= RXC_RH1M;
  603. //
  604. // Enable multicast if requested
  605. //
  606. if ((RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
  607. RxControl |= RXC_AM;
  608. //
  609. // Update the multicast hash table
  610. //
  611. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  612. | USB_TARGET_DEVICE;
  613. SetupMsg.Request = CMD_MULTICAST_HASH_WRITE;
  614. SetupMsg.Value = 0;
  615. SetupMsg.Index = 0;
  616. SetupMsg.Length = sizeof (NicDevice ->MulticastHash);
  617. Status = Ax88772UsbCommand (NicDevice,
  618. &SetupMsg,
  619. &NicDevice->MulticastHash);
  620. if (EFI_ERROR(Status))
  621. goto EXIT;
  622. }
  623. //
  624. // Enable all multicast if requested
  625. //
  626. if ((RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
  627. RxControl |= RXC_AMALL;
  628. }
  629. //
  630. // Enable broadcast if requested
  631. //
  632. if ((RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {
  633. RxControl |= RXC_AB;
  634. }
  635. //
  636. // Enable promiscuous mode if requested
  637. //
  638. if ((RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
  639. RxControl |= RXC_PRO;
  640. }
  641. //
  642. // Update the receiver control
  643. //
  644. if (NicDevice->CurRxControl != RxControl) {
  645. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  646. | USB_TARGET_DEVICE;
  647. SetupMsg.Request = CMD_RX_CONTROL_WRITE;
  648. #if RXTHOU
  649. if (NicDevice->Flag772A)
  650. RxControl |= 0x0300;
  651. #endif
  652. if (NicDevice->Flag772A)
  653. RxControl &= ~(RXC_MFB);
  654. SetupMsg.Value = RxControl;
  655. SetupMsg.Index = 0;
  656. SetupMsg.Length = 0;
  657. Status = Ax88772UsbCommand (NicDevice,
  658. &SetupMsg,
  659. NULL);
  660. if (!EFI_ERROR (Status))
  661. NicDevice->CurRxControl = RxControl;
  662. }
  663. //
  664. // Return the operation status
  665. //
  666. EXIT:
  667. return Status;
  668. }
  669. EFI_STATUS
  670. Ax88772ReloadSrom (
  671. IN NIC_DEVICE *NicDevice
  672. )
  673. {
  674. USB_DEVICE_REQUEST SetupMsg;
  675. EFI_STATUS Status;
  676. //
  677. // Read a value from the SROM
  678. //
  679. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  680. | USB_TARGET_DEVICE;
  681. SetupMsg.Request = CMD_WRITE_GPIOS;
  682. SetupMsg.Value = 0x80;
  683. SetupMsg.Index = 0;
  684. SetupMsg.Length = 0 ;
  685. Status = Ax88772UsbCommand (NicDevice,
  686. &SetupMsg,
  687. NULL);
  688. if (EFI_SUCCESS == Status)
  689. gBS->Stall(500000);
  690. return Status;
  691. }
  692. /**
  693. Read an SROM location
  694. This routine calls ::Ax88772UsbCommand to read data from the
  695. SROM.
  696. @param [in] NicDevice Pointer to the NIC_DEVICE structure
  697. @param [in] Address SROM address
  698. @param [out] Data Buffer to receive the data
  699. @retval EFI_SUCCESS The read was successful
  700. @retval other The read failed
  701. **/
  702. EFI_STATUS
  703. Ax88772SromRead (
  704. IN NIC_DEVICE *NicDevice,
  705. IN UINT32 Address,
  706. OUT UINT16 *Data
  707. )
  708. {
  709. USB_DEVICE_REQUEST SetupMsg;
  710. EFI_STATUS Status;
  711. //
  712. // Read a value from the SROM
  713. //
  714. SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
  715. | USB_REQ_TYPE_VENDOR
  716. | USB_TARGET_DEVICE;
  717. SetupMsg.Request = CMD_SROM_READ;
  718. SetupMsg.Value = (UINT16) Address;
  719. SetupMsg.Index = 0;
  720. SetupMsg.Length = sizeof (*Data);
  721. Status = Ax88772UsbCommand (NicDevice,
  722. &SetupMsg,
  723. Data);
  724. //
  725. // Return the operation status
  726. //
  727. return Status;
  728. }
  729. EFI_STATUS
  730. Ax88772EnableSromWrite (
  731. IN NIC_DEVICE * NicDevice
  732. )
  733. {
  734. USB_DEVICE_REQUEST SetupMsg;
  735. EFI_STATUS Status;
  736. //
  737. // Read a value from the SROM
  738. //
  739. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  740. | USB_TARGET_DEVICE;
  741. SetupMsg.Request = CMD_SROM_WRITE_EN;
  742. SetupMsg.Value = 0;
  743. SetupMsg.Index = 0;
  744. SetupMsg.Length = 0 ;
  745. Status = Ax88772UsbCommand (NicDevice,
  746. &SetupMsg,
  747. NULL);
  748. if (EFI_SUCCESS == Status)
  749. gBS->Stall(500000);
  750. return Status;
  751. }
  752. EFI_STATUS
  753. Ax88772DisableSromWrite (
  754. IN NIC_DEVICE *NicDevice
  755. )
  756. {
  757. USB_DEVICE_REQUEST SetupMsg;
  758. EFI_STATUS Status;
  759. //
  760. // Read a value from the SROM
  761. //
  762. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  763. | USB_TARGET_DEVICE;
  764. SetupMsg.Request = CMD_SROM_WRITE_DIS;
  765. SetupMsg.Value = 0;
  766. SetupMsg.Index = 0;
  767. SetupMsg.Length = 0;
  768. Status = Ax88772UsbCommand (NicDevice,
  769. &SetupMsg,
  770. NULL);
  771. if (EFI_SUCCESS == Status)
  772. gBS->Stall(500000);
  773. return Status;
  774. }
  775. /**
  776. Write an SROM location
  777. This routine calls ::Ax88772UsbCommand to write data from the
  778. SROM.
  779. @param [in] NicDevice Pointer to the NIC_DEVICE structure
  780. @param [in] Address SROM address
  781. @param [out] Data Buffer of data to write
  782. @retval EFI_SUCCESS The write was successful
  783. @retval other The write failed
  784. **/
  785. EFI_STATUS
  786. Ax88772SromWrite (
  787. IN NIC_DEVICE *NicDevice,
  788. IN UINT32 Address,
  789. IN UINT16 *Data
  790. )
  791. {
  792. USB_DEVICE_REQUEST SetupMsg;
  793. EFI_STATUS Status;
  794. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  795. | USB_TARGET_DEVICE;
  796. SetupMsg.Request = CMD_SROM_WRITE;
  797. SetupMsg.Value = (UINT16) Address;
  798. SetupMsg.Index = (UINT16) (*Data);
  799. SetupMsg.Length = 0;
  800. Status = Ax88772UsbCommand (NicDevice,
  801. &SetupMsg,
  802. NULL);
  803. //
  804. // Return the operation status
  805. //
  806. return Status;
  807. }
  808. /**
  809. Send a command to the USB device.
  810. @param [in] NicDevice Pointer to the NIC_DEVICE structure
  811. @param [in] Request Pointer to the request structure
  812. @param [in, out] Buffer Data buffer address
  813. @retval EFI_SUCCESS The USB transfer was successful
  814. @retval other The USB transfer failed
  815. **/
  816. EFI_STATUS
  817. Ax88772UsbCommand (
  818. IN NIC_DEVICE *NicDevice,
  819. IN USB_DEVICE_REQUEST *Request,
  820. IN OUT VOID *Buffer
  821. )
  822. {
  823. UINT32 CmdStatus;
  824. EFI_USB_DATA_DIRECTION Direction;
  825. EFI_USB_IO_PROTOCOL *UsbIo;
  826. EFI_STATUS Status;
  827. //
  828. // Determine the transfer direction
  829. //
  830. Direction = EfiUsbNoData;
  831. if (Request->Length != 0) {
  832. Direction = ((Request->RequestType & USB_ENDPOINT_DIR_IN) != 0)
  833. ? EfiUsbDataIn : EfiUsbDataOut;
  834. }
  835. //
  836. // Issue the command
  837. //
  838. UsbIo = NicDevice->UsbIo;
  839. Status = UsbIo->UsbControlTransfer (UsbIo,
  840. Request,
  841. Direction,
  842. USB_BUS_TIMEOUT,
  843. Buffer,
  844. Request->Length,
  845. &CmdStatus);
  846. //
  847. // Determine the operation status
  848. //
  849. if (!EFI_ERROR (Status)) {
  850. Status = CmdStatus;
  851. } else {
  852. //
  853. // Only use status values associated with the Simple Network protocol
  854. //
  855. if (EFI_TIMEOUT == Status) {
  856. Status = EFI_DEVICE_ERROR;
  857. }
  858. }
  859. //
  860. // Return the operation status
  861. //
  862. return Status;
  863. }
  864. BOOLEAN
  865. Ax88772GetLinkStatus (
  866. IN NIC_DEVICE *NicDevice
  867. )
  868. {
  869. UINT32 CmdStatus;
  870. EFI_USB_IO_PROTOCOL *UsbIo;
  871. UINT64 IntData = 0;
  872. UINTN IntDataLeng = 8;
  873. EFI_STATUS Status;
  874. //
  875. // Issue the command
  876. //
  877. UsbIo = NicDevice->UsbIo;
  878. Status = UsbIo->UsbSyncInterruptTransfer(UsbIo,
  879. USB_ENDPOINT_DIR_IN | INTERRUPT_ENDPOINT,
  880. &IntData,
  881. &IntDataLeng,
  882. USB_BUS_TIMEOUT,
  883. &CmdStatus);
  884. if (EFI_ERROR(Status) || EFI_ERROR(CmdStatus) || 0 == IntDataLeng) {
  885. return FALSE;
  886. }
  887. return (IntData & 0x800000)? FALSE : TRUE;
  888. }
  889. #if RXTHOU
  890. EFI_STATUS
  891. Ax88772BulkIn(
  892. IN NIC_DEVICE * NicDevice
  893. )
  894. {
  895. UINTN Index;
  896. UINTN LengthInBytes = 0;
  897. UINTN TmpLen = AX88772_MAX_BULKIN_SIZE;
  898. UINTN OrigTmpLen = 0;
  899. UINT16 TmpLen2;
  900. UINT16 TmpLenBar;
  901. UINT16 TmpTotalLen = 0;
  902. UINTN TotalLen = LengthInBytes;
  903. EFI_STATUS Status = EFI_DEVICE_ERROR;
  904. EFI_USB_IO_PROTOCOL *UsbIo;
  905. UINT32 TransferStatus = 0;
  906. UINT16 TmpPktCnt = 0;
  907. UINT16 *TmpHdr = (UINT16 *)NicDevice->BulkInbuf;
  908. USB_DEVICE_REQUEST SetupMsg;
  909. UsbIo = NicDevice->UsbIo;
  910. for (Index = 0 ; Index < (AX88772_MAX_BULKIN_SIZE / 512) && UsbIo != NULL; Index++) {
  911. VOID* TmpAddr = 0;
  912. TmpPktCnt = 0;
  913. TmpAddr = (VOID*) &NicDevice->BulkInbuf[LengthInBytes];
  914. OrigTmpLen = TmpLen;
  915. Status = UsbIo->UsbBulkTransfer (UsbIo,
  916. USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT,
  917. TmpAddr,
  918. &TmpLen,
  919. BULKIN_TIMEOUT,
  920. &TransferStatus);
  921. if (OrigTmpLen == TmpLen) {
  922. Status = EFI_NOT_READY;
  923. goto no_pkt;
  924. }
  925. if ((!EFI_ERROR (Status)) &&
  926. (!EFI_ERROR (TransferStatus)) &&
  927. TmpLen != 0) {
  928. LengthInBytes += TmpLen;
  929. if ((TmpLen % 512) != 0) {
  930. goto done;
  931. }
  932. } else if ((!EFI_ERROR (Status)) &&
  933. (!EFI_ERROR (TransferStatus)) &&
  934. (TmpLen == 0)) {
  935. Status = EFI_NOT_READY;
  936. goto done;
  937. } else if (EFI_TIMEOUT == Status && EFI_USB_ERR_TIMEOUT == TransferStatus) {
  938. SetupMsg.RequestType = USB_REQ_TYPE_STANDARD | 0x02;
  939. SetupMsg.Request = 0x01;
  940. SetupMsg.Value = 0;
  941. SetupMsg.Index = 0x82;
  942. SetupMsg.Length = 0;
  943. Status = Ax88772UsbCommand (NicDevice,
  944. &SetupMsg,
  945. NULL);
  946. Status = EFI_NOT_READY;
  947. goto done;
  948. } else {
  949. Status = EFI_DEVICE_ERROR;
  950. goto done;
  951. }
  952. }
  953. done:
  954. if (LengthInBytes != 0) {
  955. do {
  956. TmpLen2 = (*TmpHdr) & 0x7FF;
  957. TmpLenBar = *(TmpHdr + 1);
  958. TmpTotalLen = ((TmpLen + 4 + 1) & 0xfffe);
  959. if ((TmpLen2 & 0x7FF) + (TmpLenBar & 0x7FF) == 0x7FF) {
  960. TmpPktCnt++;
  961. } else {
  962. if (TmpPktCnt != 0) {
  963. break;
  964. }
  965. Status = EFI_NOT_READY;
  966. goto no_pkt;
  967. }
  968. TmpHdr += (TmpTotalLen / 2);
  969. TotalLen -= TmpTotalLen;
  970. } while (TotalLen > 0);
  971. if (LengthInBytes >= 1000 && TmpPktCnt != 0) {
  972. if ((NicDevice->RxBurst) == 1) {
  973. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  974. | USB_TARGET_DEVICE;
  975. SetupMsg.Request = CMD_RESET;
  976. SetupMsg.Value = SRR_IPRL;
  977. SetupMsg.Index = 0;
  978. SetupMsg.Length = 0;
  979. Ax88772UsbCommand (NicDevice,
  980. &SetupMsg,
  981. NULL);
  982. }
  983. if (NicDevice->RxBurst < 2)
  984. NicDevice->RxBurst++;
  985. } else {
  986. if (NicDevice->RxBurst >= 2) {
  987. SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
  988. | USB_TARGET_DEVICE;
  989. SetupMsg.Request = CMD_RESET;
  990. SetupMsg.Value = SRR_IPRL| SRR_BZ | SRR_BZTYPE;
  991. SetupMsg.Index = 0;
  992. SetupMsg.Length = 0;
  993. Ax88772UsbCommand (NicDevice,
  994. &SetupMsg,
  995. NULL);
  996. }
  997. NicDevice->RxBurst = 0;
  998. }
  999. }
  1000. if (TmpPktCnt != 0) {
  1001. NicDevice->PktCnt = TmpPktCnt;
  1002. NicDevice->CurPktHdrOff = NicDevice->BulkInbuf;
  1003. NicDevice->CurPktOff = NicDevice->BulkInbuf + 4;
  1004. Status = EFI_SUCCESS;
  1005. }
  1006. no_pkt:
  1007. return Status;
  1008. }
  1009. #else
  1010. EFI_STATUS
  1011. Ax88772BulkIn(
  1012. IN NIC_DEVICE *NicDevice
  1013. )
  1014. {
  1015. UINTN Index;
  1016. UINTN LengthInBytes = 0;
  1017. UINTN TmpLen = AX88772_MAX_BULKIN_SIZE;
  1018. UINTN OrigTmpLen = 0;
  1019. UINT16 TmpLen2;
  1020. UINT16 TmpLenBar;
  1021. UINT16 TmpTotalLen = 0;
  1022. UINTN CURBufSize = AX88772_MAX_BULKIN_SIZE;
  1023. EFI_STATUS Status = EFI_DEVICE_ERROR;
  1024. EFI_USB_IO_PROTOCOL *UsbIo;
  1025. UINT32 TransferStatus = 0;
  1026. UINT16 TmpPktCnt = 0;
  1027. UINT16 *TmpHdr = (UINT16 *)NicDevice->BulkInbuf;
  1028. UsbIo = NicDevice->UsbIo;
  1029. for (Index = 0 ; Index < (AX88772_MAX_BULKIN_SIZE / 512) && UsbIo != NULL; Index++) {
  1030. VOID *TmpAddr = 0;
  1031. TmpPktCnt = 0;
  1032. TmpAddr = (VOID*) &NicDevice->BulkInbuf[LengthInBytes];
  1033. OrigTmpLen = TmpLen;
  1034. Status = UsbIo->UsbBulkTransfer (UsbIo,
  1035. USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT,
  1036. TmpAddr,
  1037. &TmpLen,
  1038. BULKIN_TIMEOUT,
  1039. &TransferStatus);
  1040. if (OrigTmpLen == TmpLen) {
  1041. Status = EFI_NOT_READY;
  1042. goto no_pkt;
  1043. }
  1044. if ((!EFI_ERROR (Status)) &&
  1045. (!EFI_ERROR (TransferStatus)) &&
  1046. TmpLen != 0) {
  1047. LengthInBytes += TmpLen;
  1048. CURBufSize = CURBufSize - TmpLen;
  1049. TmpLen = CURBufSize;
  1050. do {
  1051. TmpLen2 = *TmpHdr;
  1052. TmpLenBar = *(TmpHdr + 1);
  1053. TmpTotalLen += ((TmpLen2 + 4 + 1) & 0xfffe);
  1054. if (((TmpLen2 ^ TmpLenBar) == 0xffff)) {
  1055. if (TmpTotalLen == LengthInBytes) {
  1056. TmpPktCnt++;
  1057. Status = EFI_SUCCESS;
  1058. goto done;
  1059. } else if (TmpTotalLen > LengthInBytes) {
  1060. break;
  1061. }
  1062. } else if (((TmpLen2 ^ TmpLenBar) != 0xffff)) {
  1063. if (TmpPktCnt != 0) {
  1064. Status = EFI_SUCCESS;
  1065. goto done;
  1066. }
  1067. Status = EFI_NOT_READY;
  1068. goto no_pkt;
  1069. }
  1070. TmpHdr += (TmpTotalLen / 2);
  1071. TmpPktCnt++;
  1072. } while (TmpTotalLen < LengthInBytes);
  1073. } else if ((!EFI_ERROR (Status)) &&
  1074. (!EFI_ERROR (TransferStatus)) &&
  1075. (TmpLen == 0)) {
  1076. if (TmpPktCnt != 0) {
  1077. Status = EFI_SUCCESS;
  1078. goto done;
  1079. }
  1080. Status = EFI_NOT_READY;
  1081. goto no_pkt;
  1082. } else if (EFI_TIMEOUT == Status && EFI_USB_ERR_TIMEOUT == TransferStatus) {
  1083. if (TmpPktCnt != 0) {
  1084. Status = EFI_SUCCESS;
  1085. goto done;
  1086. }
  1087. Status = EFI_NOT_READY;
  1088. goto no_pkt;
  1089. } else {
  1090. if (TmpPktCnt != 0) {
  1091. Status = EFI_SUCCESS;
  1092. goto done;
  1093. }
  1094. Status = EFI_DEVICE_ERROR;
  1095. goto no_pkt;
  1096. }
  1097. }
  1098. done:
  1099. NicDevice->PktCnt = TmpPktCnt;
  1100. NicDevice->CurPktHdrOff = NicDevice->BulkInbuf;
  1101. NicDevice->CurPktOff = NicDevice->BulkInbuf + 4;
  1102. no_pkt:
  1103. return Status;
  1104. }
  1105. #endif