Lan9118Dxe.c 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531
  1. /** @file
  2. *
  3. * Copyright (c) 2012-2014, ARM Limited. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause-Patent
  6. *
  7. **/
  8. #include "Lan9118Dxe.h"
  9. typedef struct {
  10. MAC_ADDR_DEVICE_PATH Lan9118;
  11. EFI_DEVICE_PATH_PROTOCOL End;
  12. } LAN9118_DEVICE_PATH;
  13. LAN9118_DEVICE_PATH Lan9118PathTemplate = {
  14. {
  15. {
  16. MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP,
  17. { (UINT8) (sizeof(MAC_ADDR_DEVICE_PATH)), (UINT8) ((sizeof(MAC_ADDR_DEVICE_PATH)) >> 8) }
  18. },
  19. { { 0 } },
  20. 0
  21. },
  22. {
  23. END_DEVICE_PATH_TYPE,
  24. END_ENTIRE_DEVICE_PATH_SUBTYPE,
  25. { sizeof(EFI_DEVICE_PATH_PROTOCOL), 0 }
  26. }
  27. };
  28. /*
  29. ** Entry point for the LAN9118 driver
  30. **
  31. */
  32. EFI_STATUS
  33. Lan9118DxeEntry (
  34. IN EFI_HANDLE Handle,
  35. IN EFI_SYSTEM_TABLE *SystemTable
  36. )
  37. {
  38. EFI_STATUS Status;
  39. LAN9118_DRIVER *LanDriver;
  40. EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
  41. EFI_SIMPLE_NETWORK_MODE *SnpMode;
  42. LAN9118_DEVICE_PATH *Lan9118Path;
  43. EFI_HANDLE ControllerHandle;
  44. // The PcdLan9118DxeBaseAddress PCD must be defined
  45. ASSERT (PcdGet32 (PcdLan9118DxeBaseAddress) != 0);
  46. // Allocate Resources
  47. LanDriver = AllocateZeroPool (sizeof (LAN9118_DRIVER));
  48. if (LanDriver == NULL) {
  49. return EFI_OUT_OF_RESOURCES;
  50. }
  51. Lan9118Path = (LAN9118_DEVICE_PATH*)AllocateCopyPool (sizeof (LAN9118_DEVICE_PATH), &Lan9118PathTemplate);
  52. if (Lan9118Path == NULL) {
  53. return EFI_OUT_OF_RESOURCES;
  54. }
  55. // Initialize pointers
  56. Snp = &(LanDriver->Snp);
  57. SnpMode = &(LanDriver->SnpMode);
  58. Snp->Mode = SnpMode;
  59. // Set the signature of the LAN Driver structure
  60. LanDriver->Signature = LAN9118_SIGNATURE;
  61. // Assign fields and func pointers
  62. Snp->Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
  63. Snp->WaitForPacket = NULL;
  64. Snp->Initialize = SnpInitialize;
  65. Snp->Start = SnpStart;
  66. Snp->Stop = SnpStop;
  67. Snp->Reset = SnpReset;
  68. Snp->Shutdown = SnpShutdown;
  69. Snp->ReceiveFilters = SnpReceiveFilters;
  70. Snp->StationAddress = SnpStationAddress;
  71. Snp->Statistics = SnpStatistics;
  72. Snp->MCastIpToMac = SnpMcastIptoMac;
  73. Snp->NvData = SnpNvData;
  74. Snp->GetStatus = SnpGetStatus;
  75. Snp->Transmit = SnpTransmit;
  76. Snp->Receive = SnpReceive;
  77. // Start completing simple network mode structure
  78. SnpMode->State = EfiSimpleNetworkStopped;
  79. SnpMode->HwAddressSize = NET_ETHER_ADDR_LEN; // HW address is 6 bytes
  80. SnpMode->MediaHeaderSize = sizeof(ETHER_HEAD); // Not sure of this
  81. SnpMode->MaxPacketSize = EFI_PAGE_SIZE; // Preamble + SOF + Ether Frame (with VLAN tag +4bytes)
  82. SnpMode->NvRamSize = 0; // No NVRAM with this device
  83. SnpMode->NvRamAccessSize = 0; // No NVRAM with this device
  84. //
  85. // Claim that all receive filter settings are supported, though the MULTICAST mode
  86. // is not completely supported. The LAN9118 Ethernet controller is only able to
  87. // do a "hash filtering" and not a perfect filtering on multicast addresses. The
  88. // controller does not filter the multicast addresses directly but a hash value
  89. // of them. The hash value of a multicast address is derived from its CRC and
  90. // ranges from 0 to 63 included.
  91. // We claim that the perfect MULTICAST filtering mode is supported because
  92. // we do not want the user to switch directly to the PROMISCOUS_MULTICAST mode
  93. // and thus not being able to take advantage of the hash filtering.
  94. //
  95. SnpMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
  96. EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
  97. EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
  98. EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS |
  99. EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
  100. // We do not intend to receive anything for the time being.
  101. SnpMode->ReceiveFilterSetting = 0;
  102. // LAN9118 has 64bit hash table, can filter 64 MCast MAC Addresses
  103. SnpMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT;
  104. SnpMode->MCastFilterCount = 0;
  105. ZeroMem (&SnpMode->MCastFilter, MAX_MCAST_FILTER_CNT * sizeof(EFI_MAC_ADDRESS));
  106. // Set the interface type (1: Ethernet or 6: IEEE 802 Networks)
  107. SnpMode->IfType = NET_IFTYPE_ETHERNET;
  108. // Mac address is changeable as it is loaded from erasable memory
  109. SnpMode->MacAddressChangeable = TRUE;
  110. // Can only transmit one packet at a time
  111. SnpMode->MultipleTxSupported = FALSE;
  112. // MediaPresent checks for cable connection and partner link
  113. SnpMode->MediaPresentSupported = TRUE;
  114. SnpMode->MediaPresent = FALSE;
  115. // Set broadcast address
  116. SetMem (&SnpMode->BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF);
  117. // Power up the device so we can find the MAC address
  118. Status = Lan9118Initialize (Snp);
  119. if (EFI_ERROR (Status)) {
  120. DEBUG ((EFI_D_ERROR, "LAN9118: Error initialising hardware\n"));
  121. return EFI_DEVICE_ERROR;
  122. }
  123. // Assign fields for device path
  124. CopyMem (&Lan9118Path->Lan9118.MacAddress, &Snp->Mode->CurrentAddress, NET_ETHER_ADDR_LEN);
  125. Lan9118Path->Lan9118.IfType = Snp->Mode->IfType;
  126. // Initialise the protocol
  127. ControllerHandle = NULL;
  128. Status = gBS->InstallMultipleProtocolInterfaces (
  129. &ControllerHandle,
  130. &gEfiSimpleNetworkProtocolGuid, Snp,
  131. &gEfiDevicePathProtocolGuid, Lan9118Path,
  132. NULL
  133. );
  134. // Say what the status of loading the protocol structure is
  135. if (EFI_ERROR(Status)) {
  136. FreePool (LanDriver);
  137. } else {
  138. LanDriver->ControllerHandle = ControllerHandle;
  139. }
  140. return Status;
  141. }
  142. /*
  143. * UEFI Start() function
  144. *
  145. * Parameters:
  146. *
  147. * @param Snp: A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
  148. *
  149. * Description:
  150. *
  151. * This function starts a network interface. If the network interface successfully starts, then
  152. * EFI_SUCCESS will be returned.
  153. */
  154. EFI_STATUS
  155. EFIAPI
  156. SnpStart (
  157. IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp
  158. )
  159. {
  160. // Check Snp instance
  161. if (Snp == NULL) {
  162. return EFI_INVALID_PARAMETER;
  163. }
  164. // Check state
  165. if ((Snp->Mode->State == EfiSimpleNetworkStarted) ||
  166. (Snp->Mode->State == EfiSimpleNetworkInitialized) ) {
  167. return EFI_ALREADY_STARTED;
  168. }
  169. // Change state
  170. Snp->Mode->State = EfiSimpleNetworkStarted;
  171. return EFI_SUCCESS;
  172. }
  173. /*
  174. * UEFI Stop() function
  175. *
  176. */
  177. EFI_STATUS
  178. EFIAPI
  179. SnpStop (
  180. IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp
  181. )
  182. {
  183. // Check Snp Instance
  184. if (Snp == NULL) {
  185. return EFI_INVALID_PARAMETER;
  186. }
  187. // Check state of the driver
  188. if (Snp->Mode->State == EfiSimpleNetworkStopped) {
  189. return EFI_NOT_STARTED;
  190. }
  191. // Stop the Tx and Rx
  192. StopTx (STOP_TX_CFG | STOP_TX_MAC, Snp);
  193. StopRx (0, Snp);
  194. // Change the state
  195. switch (Snp->Mode->State) {
  196. case EfiSimpleNetworkStarted:
  197. case EfiSimpleNetworkInitialized:
  198. Snp->Mode->State = EfiSimpleNetworkStopped;
  199. break;
  200. default:
  201. return EFI_DEVICE_ERROR;
  202. }
  203. // Put the device into a power saving mode ?
  204. return EFI_SUCCESS;
  205. }
  206. // Allocated receive and transmit buffers
  207. STATIC UINT32 gTxBuffer = 0;
  208. /*
  209. * UEFI Initialize() function
  210. *
  211. */
  212. EFI_STATUS
  213. EFIAPI
  214. SnpInitialize (
  215. IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp,
  216. IN UINTN RxBufferSize OPTIONAL,
  217. IN UINTN TxBufferSize OPTIONAL
  218. )
  219. {
  220. EFI_STATUS Status;
  221. UINT32 PmConf;
  222. INT32 AllocResult;
  223. UINT32 RxStatusSize;
  224. UINT32 TxStatusSize;
  225. // Initialize variables
  226. // Global variables to hold tx and rx FIFO allocation
  227. gTxBuffer = 0;
  228. // Check Snp Instance
  229. if (Snp == NULL) {
  230. return EFI_INVALID_PARAMETER;
  231. }
  232. // First check that driver has not already been initialized
  233. if (Snp->Mode->State == EfiSimpleNetworkInitialized) {
  234. DEBUG ((EFI_D_WARN, "LAN9118 Driver already initialized\n"));
  235. return EFI_SUCCESS;
  236. } else
  237. if (Snp->Mode->State == EfiSimpleNetworkStopped) {
  238. DEBUG ((EFI_D_WARN, "LAN9118 Driver not started\n"));
  239. return EFI_NOT_STARTED;
  240. }
  241. // Initiate a PHY reset
  242. Status = PhySoftReset (PHY_RESET_PMT, Snp);
  243. if (EFI_ERROR (Status)) {
  244. Snp->Mode->State = EfiSimpleNetworkStopped;
  245. DEBUG ((EFI_D_WARN, "Warning: Link not ready after TimeOut. Check ethernet cable\n"));
  246. return EFI_NOT_STARTED;
  247. }
  248. // Initiate a software reset
  249. Status = SoftReset (0, Snp);
  250. if (EFI_ERROR(Status)) {
  251. DEBUG ((EFI_D_WARN, "Soft Reset Failed: Hardware Error\n"));
  252. return EFI_DEVICE_ERROR;
  253. }
  254. // Read the PM register
  255. PmConf = Lan9118MmioRead32 (LAN9118_PMT_CTRL);
  256. // MPTCTRL_WOL_EN: Allow Wake-On-Lan to detect wake up frames or magic packets
  257. // MPTCTRL_ED_EN: Allow energy detection to allow lowest power consumption mode
  258. // MPTCTRL_PME_EN: Allow Power Management Events
  259. PmConf = 0;
  260. PmConf |= (MPTCTRL_WOL_EN | MPTCTRL_ED_EN | MPTCTRL_PME_EN);
  261. // Write the current configuration to the register
  262. Lan9118MmioWrite32 (LAN9118_PMT_CTRL, PmConf);
  263. // Configure GPIO and HW
  264. Status = ConfigureHardware (HW_CONF_USE_LEDS, Snp);
  265. if (EFI_ERROR(Status)) {
  266. return Status;
  267. }
  268. // Assign the transmitter buffer size (default values)
  269. TxStatusSize = LAN9118_TX_STATUS_SIZE;
  270. RxStatusSize = LAN9118_RX_STATUS_SIZE;
  271. // Check that a buff size was specified
  272. if (TxBufferSize > 0) {
  273. if (RxBufferSize == 0) {
  274. RxBufferSize = LAN9118_RX_DATA_SIZE;
  275. }
  276. AllocResult = ChangeFifoAllocation (
  277. ALLOC_USE_FIFOS,
  278. &TxBufferSize,
  279. &RxBufferSize,
  280. &TxStatusSize,
  281. &RxStatusSize,
  282. Snp
  283. );
  284. if (AllocResult < 0) {
  285. return EFI_OUT_OF_RESOURCES;
  286. }
  287. }
  288. // Do auto-negotiation if supported
  289. Status = AutoNegotiate (AUTO_NEGOTIATE_ADVERTISE_ALL, Snp);
  290. if (EFI_ERROR(Status)) {
  291. DEBUG ((EFI_D_WARN, "LAN9118: Auto Negotiation failed.\n"));
  292. }
  293. // Configure flow control depending on speed capabilities
  294. Status = ConfigureFlow (0, 0, 0, 0, Snp);
  295. if (EFI_ERROR(Status)) {
  296. return Status;
  297. }
  298. // Enable the transmitter
  299. Status = StartTx (START_TX_MAC | START_TX_CFG, Snp);
  300. if (EFI_ERROR(Status)) {
  301. return Status;
  302. }
  303. // Now acknowledge all interrupts
  304. Lan9118MmioWrite32 (LAN9118_INT_STS, ~0);
  305. // Declare the driver as initialized
  306. Snp->Mode->State = EfiSimpleNetworkInitialized;
  307. return Status;
  308. }
  309. /*
  310. * UEFI Reset () function
  311. *
  312. */
  313. EFI_STATUS
  314. EFIAPI
  315. SnpReset (
  316. IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp,
  317. IN BOOLEAN Verification
  318. )
  319. {
  320. UINT32 PmConf;
  321. UINT32 HwConf;
  322. UINT32 ResetFlags;
  323. EFI_STATUS Status;
  324. PmConf = 0;
  325. HwConf = 0;
  326. ResetFlags = 0;
  327. // Check Snp Instance
  328. if (Snp == NULL) {
  329. return EFI_INVALID_PARAMETER;
  330. }
  331. // First check that driver has not already been initialized
  332. if (Snp->Mode->State == EfiSimpleNetworkStarted) {
  333. DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not yet initialized\n"));
  334. return EFI_DEVICE_ERROR;
  335. } else if (Snp->Mode->State == EfiSimpleNetworkStopped) {
  336. DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not started\n"));
  337. return EFI_NOT_STARTED;
  338. }
  339. // Initiate a PHY reset
  340. Status = PhySoftReset (PHY_RESET_PMT, Snp);
  341. if (EFI_ERROR (Status)) {
  342. Snp->Mode->State = EfiSimpleNetworkStopped;
  343. return EFI_NOT_STARTED;
  344. }
  345. // Initiate a software reset
  346. ResetFlags |= SOFT_RESET_CHECK_MAC_ADDR_LOAD | SOFT_RESET_CLEAR_INT;
  347. if (Verification) {
  348. ResetFlags |= SOFT_RESET_SELF_TEST;
  349. }
  350. Status = SoftReset (ResetFlags, Snp);
  351. if (EFI_ERROR (Status)) {
  352. DEBUG ((EFI_D_WARN, "Warning: Soft Reset Failed: Hardware Error\n"));
  353. return EFI_DEVICE_ERROR;
  354. }
  355. // Read the PM register
  356. PmConf = Lan9118MmioRead32 (LAN9118_PMT_CTRL);
  357. // MPTCTRL_WOL_EN: Allow Wake-On-Lan to detect wake up frames or magic packets
  358. // MPTCTRL_ED_EN: Allow energy detection to allow lowest power consumption mode
  359. // MPTCTRL_PME_EN: Allow Power Management Events
  360. PmConf |= (MPTCTRL_WOL_EN | MPTCTRL_ED_EN | MPTCTRL_PME_EN);
  361. // Write the current configuration to the register
  362. Lan9118MmioWrite32 (LAN9118_PMT_CTRL, PmConf);
  363. // Reactivate the LEDs
  364. Status = ConfigureHardware (HW_CONF_USE_LEDS, Snp);
  365. if (EFI_ERROR (Status)) {
  366. return Status;
  367. }
  368. // Check that a buffer size was specified in SnpInitialize
  369. if (gTxBuffer != 0) {
  370. HwConf = Lan9118MmioRead32 (LAN9118_HW_CFG); // Read the HW register
  371. HwConf &= ~HW_CFG_TX_FIFO_SIZE_MASK; // Clear buffer bits first
  372. HwConf |= HW_CFG_TX_FIFO_SIZE(gTxBuffer); // assign size chosen in SnpInitialize
  373. Lan9118MmioWrite32 (LAN9118_HW_CFG, HwConf); // Write the conf
  374. }
  375. // Enable the receiver and transmitter and clear their contents
  376. StartRx (START_RX_CLEAR, Snp);
  377. StartTx (START_TX_MAC | START_TX_CFG | START_TX_CLEAR, Snp);
  378. // Now acknowledge all interrupts
  379. Lan9118MmioWrite32 (LAN9118_INT_STS, ~0);
  380. return EFI_SUCCESS;
  381. }
  382. /*
  383. * UEFI Shutdown () function
  384. *
  385. */
  386. EFI_STATUS
  387. EFIAPI
  388. SnpShutdown (
  389. IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp
  390. )
  391. {
  392. EFI_STATUS Status;
  393. // Check Snp Instance
  394. if (Snp == NULL) {
  395. return EFI_INVALID_PARAMETER;
  396. }
  397. // First check that driver has not already been initialized
  398. if (Snp->Mode->State == EfiSimpleNetworkStarted) {
  399. DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not yet initialized\n"));
  400. return EFI_DEVICE_ERROR;
  401. } else if (Snp->Mode->State == EfiSimpleNetworkStopped) {
  402. DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not started\n"));
  403. return EFI_NOT_STARTED;
  404. }
  405. // Initiate a PHY reset
  406. Status = PhySoftReset (PHY_RESET_PMT, Snp);
  407. if (EFI_ERROR (Status)) {
  408. return Status;
  409. }
  410. // Initiate a software reset
  411. Status = SoftReset (0, Snp);
  412. if (EFI_ERROR (Status)) {
  413. DEBUG ((EFI_D_WARN, "Warning: Soft Reset Failed: Hardware Error\n"));
  414. return Status;
  415. }
  416. // Back to the started and thus not initialized state
  417. Snp->Mode->State = EfiSimpleNetworkStarted;
  418. return EFI_SUCCESS;
  419. }
  420. /**
  421. Enable and/or disable the receive filters of the LAN9118
  422. Please refer to the UEFI specification for the precedence rules among the
  423. Enable, Disable and ResetMCastFilter parameters.
  424. @param[in] Snp A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL
  425. instance.
  426. @param[in] Enable A bit mask of receive filters to enable.
  427. @param[in] Disable A bit mask of receive filters to disable.
  428. @param[in] ResetMCastFilter Set to TRUE to reset the contents of the multicast
  429. receive filters on the network interface to
  430. their default values.
  431. @param[in] MCastFilterCnt Number of multicast HW MAC addresses in the new
  432. MCastFilter list. This value must be less than or
  433. equal to the MCastFilterCnt field of
  434. EFI_SIMPLE_NETWORK_MODE. This field is optional if
  435. ResetMCastFilter is TRUE.
  436. @param[in] MCastFilter A pointer to a list of new multicast receive
  437. filter HW MAC addresses. This list will replace
  438. any existing multicast HW MAC address list. This
  439. field is optional if ResetMCastFilter is TRUE.
  440. @retval EFI_SUCCESS The receive filters of the LAN9118 were updated.
  441. @retval EFI_NOT_STARTED The LAN9118 has not been started.
  442. @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE :
  443. . This is NULL
  444. . Multicast is being enabled (the
  445. EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit is set in
  446. Enable, it is not set in Disable, and ResetMCastFilter
  447. is FALSE) and MCastFilterCount is zero.
  448. . Multicast is being enabled and MCastFilterCount is
  449. greater than Snp->Mode->MaxMCastFilterCount.
  450. . Multicast is being enabled and MCastFilter is NULL
  451. . Multicast is being enabled and one or more of the
  452. addresses in the MCastFilter list are not valid
  453. multicast MAC addresses.
  454. @retval EFI_DEVICE_ERROR The LAN9118 has been started but not initialized.
  455. **/
  456. EFI_STATUS
  457. EFIAPI
  458. SnpReceiveFilters (
  459. IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
  460. IN UINT32 Enable,
  461. IN UINT32 Disable,
  462. IN BOOLEAN ResetMCastFilter,
  463. IN UINTN MCastFilterCnt OPTIONAL,
  464. IN EFI_MAC_ADDRESS *MCastFilter OPTIONAL
  465. )
  466. {
  467. EFI_SIMPLE_NETWORK_MODE *Mode;
  468. UINT32 MultHashTableHigh;
  469. UINT32 MultHashTableLow;
  470. UINT32 Count;
  471. UINT32 Crc;
  472. UINT8 HashValue;
  473. UINT32 MacCSRValue;
  474. UINT32 ReceiveFilterSetting;
  475. EFI_MAC_ADDRESS *Mac;
  476. EFI_MAC_ADDRESS ZeroMac;
  477. // Check Snp Instance
  478. if (Snp == NULL) {
  479. return EFI_INVALID_PARAMETER;
  480. }
  481. Mode = Snp->Mode;
  482. // Check that driver was started and initialised
  483. if (Mode->State == EfiSimpleNetworkStarted) {
  484. DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n"));
  485. return EFI_DEVICE_ERROR;
  486. } else if (Mode->State == EfiSimpleNetworkStopped) {
  487. DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n"));
  488. return EFI_NOT_STARTED;
  489. }
  490. if ((Enable & (~Mode->ReceiveFilterMask)) ||
  491. (Disable & (~Mode->ReceiveFilterMask)) ) {
  492. return EFI_INVALID_PARAMETER;
  493. }
  494. //
  495. // Check the validity of the multicast setting and compute the
  496. // hash values of the multicast mac addresses to listen to.
  497. //
  498. MultHashTableHigh = 0;
  499. MultHashTableLow = 0;
  500. if ((!ResetMCastFilter) &&
  501. ((Disable & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) == 0) &&
  502. ((Enable & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) ) {
  503. if ((MCastFilterCnt == 0) ||
  504. (MCastFilterCnt > Mode->MaxMCastFilterCount) ||
  505. (MCastFilter == NULL) ) {
  506. return EFI_INVALID_PARAMETER;
  507. }
  508. //
  509. // Check the validity of all multicast addresses before to change
  510. // anything.
  511. //
  512. for (Count = 0; Count < MCastFilterCnt; Count++) {
  513. if ((MCastFilter[Count].Addr[0] & 1) == 0) {
  514. return EFI_INVALID_PARAMETER;
  515. }
  516. }
  517. //
  518. // Go through each filter address and set appropriate bits on hash table
  519. //
  520. for (Count = 0; Count < MCastFilterCnt; Count++) {
  521. Mac = &(MCastFilter[Count]);
  522. CopyMem (&Mode->MCastFilter[Count], Mac, sizeof(EFI_MAC_ADDRESS));
  523. Crc = GenEtherCrc32 (Mac, NET_ETHER_ADDR_LEN);
  524. //gBS->CalculateCrc32 ((VOID*)&Mfilter[Count],6,&Crc); <-- doesn't work as desired
  525. //
  526. // The most significant 6 bits of the MAC address CRC constitute the hash
  527. // value of the MAC address.
  528. //
  529. HashValue = (Crc >> 26) & 0x3F;
  530. // Select hashlow register if MSB is not set
  531. if ((HashValue & 0x20) == 0) {
  532. MultHashTableLow |= (1 << HashValue);
  533. } else {
  534. MultHashTableHigh |= (1 << (HashValue & 0x1F));
  535. }
  536. }
  537. Mode->MCastFilterCount = MCastFilterCnt;
  538. } else if (ResetMCastFilter) {
  539. Mode->MCastFilterCount = 0;
  540. } else {
  541. MultHashTableLow = IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHL);
  542. MultHashTableHigh = IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHH);
  543. }
  544. //
  545. // Before to change anything, stop and reset the reception of
  546. // packets.
  547. //
  548. StopRx (STOP_RX_CLEAR, Snp);
  549. //
  550. // Write the mask of the selected hash values for the multicast filtering.
  551. // The two masks are set to zero if the multicast filtering is not enabled.
  552. //
  553. IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHL, MultHashTableLow);
  554. IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHH, MultHashTableHigh);
  555. ReceiveFilterSetting = (Mode->ReceiveFilterSetting | Enable) & (~Disable);
  556. //
  557. // Read MAC controller
  558. //
  559. MacCSRValue = IndirectMACRead32 (INDIRECT_MAC_INDEX_CR);
  560. MacCSRValue &= ~(MACCR_HPFILT | MACCR_BCAST | MACCR_PRMS | MACCR_MCPAS);
  561. if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) {
  562. Lan9118SetMacAddress (&Mode->CurrentAddress, Snp);
  563. DEBUG ((DEBUG_NET, "Allowing Unicast Frame Reception\n"));
  564. } else {
  565. //
  566. // The Unicast packets do not have to be listen to, set the MAC
  567. // address of the LAN9118 to be the "not configured" all zeroes
  568. // ethernet MAC address.
  569. //
  570. ZeroMem (&ZeroMac, NET_ETHER_ADDR_LEN);
  571. Lan9118SetMacAddress (&ZeroMac, Snp);
  572. }
  573. if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) {
  574. MacCSRValue |= MACCR_HPFILT;
  575. DEBUG ((DEBUG_NET, "Allowing Multicast Frame Reception\n"));
  576. }
  577. if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) {
  578. MacCSRValue |= MACCR_MCPAS;
  579. DEBUG ((DEBUG_NET, "Enabling Promiscuous Multicast Mode\n"));
  580. }
  581. if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) == 0) {
  582. MacCSRValue |= MACCR_BCAST;
  583. } else {
  584. DEBUG ((DEBUG_NET, "Allowing Broadcast Frame Reception\n"));
  585. }
  586. if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) {
  587. MacCSRValue |= MACCR_PRMS;
  588. DEBUG ((DEBUG_NET, "Enabling Promiscuous Mode\n"));
  589. }
  590. //
  591. // Write the options to the MAC_CSR
  592. //
  593. IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR, MacCSRValue);
  594. //
  595. // If we have to retrieve something, start packet reception.
  596. //
  597. Mode->ReceiveFilterSetting = ReceiveFilterSetting;
  598. if (ReceiveFilterSetting != 0) {
  599. StartRx (0, Snp);
  600. }
  601. return EFI_SUCCESS;
  602. }
  603. /**
  604. Modify of reset the current station address
  605. @param[in] Snp A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL
  606. instance.
  607. @param[in] Reset Flag used to reset the station address to the
  608. LAN9118's permanent address.
  609. @param[in] New New station address to be used for the network interface.
  610. @retval EFI_SUCCESS The LAN9118's station address was updated.
  611. @retval EFI_NOT_STARTED The LAN9118 has not been started.
  612. @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE :
  613. . The "New" station address is invalid.
  614. . "Reset" is FALSE and "New" is NULL.
  615. @retval EFI_DEVICE_ERROR The LAN9118 has been started but not initialized.
  616. **/
  617. EFI_STATUS
  618. EFIAPI
  619. SnpStationAddress (
  620. IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
  621. IN BOOLEAN Reset,
  622. IN EFI_MAC_ADDRESS *New
  623. )
  624. {
  625. UINT32 Count;
  626. UINT8 PermAddr[NET_ETHER_ADDR_LEN];
  627. DEBUG ((DEBUG_NET, "SnpStationAddress()\n"));
  628. // Check Snp instance
  629. if (Snp == NULL) {
  630. return EFI_INVALID_PARAMETER;
  631. }
  632. // Check that driver was started and initialised
  633. if (Snp->Mode->State == EfiSimpleNetworkStarted) {
  634. DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n"));
  635. return EFI_DEVICE_ERROR;
  636. } else if (Snp->Mode->State == EfiSimpleNetworkStopped) {
  637. DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n"));
  638. return EFI_NOT_STARTED;
  639. }
  640. // Get the Permanent MAC address if need reset
  641. if (Reset) {
  642. // Try using EEPROM first. Read the first byte of data from EEPROM at the address 0x0
  643. if ((IndirectEEPROMRead32 (0) & 0xFF) == EEPROM_EXTERNAL_SERIAL_EEPROM) {
  644. for (Count = 0; Count < NET_ETHER_ADDR_LEN; Count++) {
  645. PermAddr[Count] = IndirectEEPROMRead32 (Count + 1);
  646. }
  647. New = (EFI_MAC_ADDRESS *) PermAddr;
  648. Lan9118SetMacAddress ((EFI_MAC_ADDRESS *) PermAddr, Snp);
  649. } else {
  650. DEBUG ((EFI_D_ERROR, "LAN9118: Warning: No valid MAC address in EEPROM, using fallback\n"));
  651. New = (EFI_MAC_ADDRESS*) (FixedPcdGet64 (PcdLan9118DefaultMacAddress));
  652. }
  653. } else {
  654. // Otherwise use the specified new MAC address
  655. if (New == NULL) {
  656. return EFI_INVALID_PARAMETER;
  657. }
  658. //
  659. // If it is a multicast address, it is not valid.
  660. //
  661. if (New->Addr[0] & 0x01) {
  662. return EFI_INVALID_PARAMETER;
  663. }
  664. }
  665. CopyMem (&Snp->Mode->CurrentAddress, New, NET_ETHER_ADDR_LEN);
  666. //
  667. // If packet reception is currently activated, stop and reset it,
  668. // set the new ethernet address and restart the packet reception.
  669. // Otherwise, nothing to do, the MAC address will be updated in
  670. // SnpReceiveFilters() when the UNICAST packet reception will be
  671. // activated.
  672. //
  673. if (Snp->Mode->ReceiveFilterSetting != 0) {
  674. StopRx (STOP_RX_CLEAR, Snp);
  675. Lan9118SetMacAddress (New, Snp);
  676. StartRx (0, Snp);
  677. }
  678. return EFI_SUCCESS;
  679. }
  680. /*
  681. * UEFI Statistics() function
  682. *
  683. */
  684. EFI_STATUS
  685. EFIAPI
  686. SnpStatistics (
  687. IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp,
  688. IN BOOLEAN Reset,
  689. IN OUT UINTN *StatSize,
  690. OUT EFI_NETWORK_STATISTICS *Statistics
  691. )
  692. {
  693. LAN9118_DRIVER *LanDriver;
  694. EFI_STATUS Status;
  695. LanDriver = INSTANCE_FROM_SNP_THIS (Snp);
  696. DEBUG ((DEBUG_NET, "SnpStatistics()\n"));
  697. // Check Snp instance
  698. if (Snp == NULL) {
  699. return EFI_INVALID_PARAMETER;
  700. }
  701. // Check that driver was started and initialised
  702. if (Snp->Mode->State == EfiSimpleNetworkStarted) {
  703. DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n"));
  704. return EFI_DEVICE_ERROR;
  705. } else if (Snp->Mode->State == EfiSimpleNetworkStopped) {
  706. DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n"));
  707. return EFI_NOT_STARTED;
  708. }
  709. //
  710. // Do a reset if required. It is not clearly stated in the UEFI specification
  711. // whether the reset has to be done before to copy the statistics in "Statictics"
  712. // or after. It is a bit strange to do it before but that is what is expected by
  713. // the SCT test on Statistics() with reset : "0x3de76704,0x4bf5,0x42cd,0x8c,0x89,
  714. // 0x54,0x7e,0x4f,0xad,0x4f,0x24".
  715. //
  716. if (Reset) {
  717. ZeroMem (&LanDriver->Stats, sizeof(EFI_NETWORK_STATISTICS));
  718. }
  719. Status = EFI_SUCCESS;
  720. if (StatSize == NULL) {
  721. if (Statistics != NULL) {
  722. return EFI_INVALID_PARAMETER;
  723. }
  724. } else {
  725. if (Statistics == NULL) {
  726. Status = EFI_BUFFER_TOO_SMALL;
  727. } else {
  728. // Fill in the statistics
  729. CopyMem (
  730. Statistics, &LanDriver->Stats,
  731. MIN (*StatSize, sizeof (EFI_NETWORK_STATISTICS))
  732. );
  733. if (*StatSize < sizeof (EFI_NETWORK_STATISTICS)) {
  734. Status = EFI_BUFFER_TOO_SMALL;
  735. }
  736. }
  737. *StatSize = sizeof (EFI_NETWORK_STATISTICS);
  738. }
  739. return Status;
  740. }
  741. /*
  742. * UEFI MCastIPtoMAC() function
  743. *
  744. */
  745. EFI_STATUS
  746. EFIAPI
  747. SnpMcastIptoMac (
  748. IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp,
  749. IN BOOLEAN IsIpv6,
  750. IN EFI_IP_ADDRESS *Ip,
  751. OUT EFI_MAC_ADDRESS *McastMac
  752. )
  753. {
  754. DEBUG ((DEBUG_NET, "SnpMcastIptoMac()\n"));
  755. // Check Snp instance
  756. if (Snp == NULL) {
  757. return EFI_INVALID_PARAMETER;
  758. }
  759. // Check that driver was started and initialised
  760. if (Snp->Mode->State == EfiSimpleNetworkStarted) {
  761. DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n"));
  762. return EFI_DEVICE_ERROR;
  763. } else if (Snp->Mode->State == EfiSimpleNetworkStopped) {
  764. DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n"));
  765. return EFI_NOT_STARTED;
  766. }
  767. // Check parameters
  768. if ((McastMac == NULL) || (Ip == NULL)) {
  769. return EFI_INVALID_PARAMETER;
  770. }
  771. // Make sure MAC address is empty
  772. ZeroMem (McastMac, sizeof(EFI_MAC_ADDRESS));
  773. // If we need ipv4 address
  774. if (!IsIpv6) {
  775. // Most significant 25 bits of a multicast HW address are set.
  776. // 01-00-5E is the IPv4 Ethernet Multicast Address (see RFC 1112)
  777. McastMac->Addr[0] = 0x01;
  778. McastMac->Addr[1] = 0x00;
  779. McastMac->Addr[2] = 0x5E;
  780. // Lower 23 bits from ipv4 address
  781. McastMac->Addr[3] = (Ip->v4.Addr[1] & 0x7F); // Clear the most significant bit (25th bit of MAC must be 0)
  782. McastMac->Addr[4] = Ip->v4.Addr[2];
  783. McastMac->Addr[5] = Ip->v4.Addr[3];
  784. } else {
  785. // Most significant 16 bits of multicast v6 HW address are set
  786. // 33-33 is the IPv6 Ethernet Multicast Address (see RFC 2464)
  787. McastMac->Addr[0] = 0x33;
  788. McastMac->Addr[1] = 0x33;
  789. // lower four octets are taken from ipv6 address
  790. McastMac->Addr[2] = Ip->v6.Addr[8];
  791. McastMac->Addr[3] = Ip->v6.Addr[9];
  792. McastMac->Addr[4] = Ip->v6.Addr[10];
  793. McastMac->Addr[5] = Ip->v6.Addr[11];
  794. }
  795. return EFI_SUCCESS;
  796. }
  797. /*
  798. * UEFI NvData() function
  799. *
  800. */
  801. EFI_STATUS
  802. EFIAPI
  803. SnpNvData (
  804. IN EFI_SIMPLE_NETWORK_PROTOCOL* pobj,
  805. IN BOOLEAN read_write,
  806. IN UINTN offset,
  807. IN UINTN buff_size,
  808. IN OUT VOID *data
  809. )
  810. {
  811. DEBUG ((DEBUG_NET, "SnpNvData()\n"));
  812. return EFI_UNSUPPORTED;
  813. }
  814. /*
  815. * UEFI GetStatus () function
  816. *
  817. */
  818. EFI_STATUS
  819. EFIAPI
  820. SnpGetStatus (
  821. IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
  822. OUT UINT32 *IrqStat OPTIONAL,
  823. OUT VOID **TxBuff OPTIONAL
  824. )
  825. {
  826. UINT32 FifoInt;
  827. EFI_STATUS Status;
  828. UINTN NumTxStatusEntries;
  829. UINT32 TxStatus;
  830. UINT16 PacketTag;
  831. UINT32 Interrupts;
  832. LAN9118_DRIVER *LanDriver;
  833. LanDriver = INSTANCE_FROM_SNP_THIS (Snp);
  834. // Check preliminaries
  835. if (Snp == NULL) {
  836. return EFI_INVALID_PARAMETER;
  837. }
  838. // Check that driver was started and initialised
  839. if (Snp->Mode->State == EfiSimpleNetworkStarted) {
  840. DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n"));
  841. return EFI_DEVICE_ERROR;
  842. } else if (Snp->Mode->State == EfiSimpleNetworkStopped) {
  843. DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n"));
  844. return EFI_NOT_STARTED;
  845. }
  846. // Check and acknowledge TX Status interrupt (this will happen if the
  847. // consumer of SNP does not call GetStatus.)
  848. // TODO will we lose TxStatuses if this happens? Maybe in SnpTransmit we
  849. // should check for it and dump the TX Status FIFO.
  850. FifoInt = Lan9118MmioRead32 (LAN9118_FIFO_INT);
  851. // Clear the TX Status FIFO Overflow
  852. if ((FifoInt & INSTS_TXSO) == 0) {
  853. FifoInt |= INSTS_TXSO;
  854. Lan9118MmioWrite32 (LAN9118_FIFO_INT, FifoInt);
  855. }
  856. // Read interrupt status if IrqStat is not NULL
  857. if (IrqStat != NULL) {
  858. *IrqStat = 0;
  859. // Check for receive interrupt
  860. if (Lan9118MmioRead32 (LAN9118_INT_STS) & INSTS_RSFL) { // Data moved from rx FIFO
  861. *IrqStat |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
  862. Lan9118MmioWrite32 (LAN9118_INT_STS,INSTS_RSFL);
  863. }
  864. // Check for transmit interrupt
  865. if (Lan9118MmioRead32 (LAN9118_INT_STS) & INSTS_TSFL) {
  866. *IrqStat |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
  867. Lan9118MmioWrite32 (LAN9118_INT_STS,INSTS_TSFL);
  868. }
  869. // Check for software interrupt
  870. if (Lan9118MmioRead32 (LAN9118_INT_STS) & INSTS_SW_INT) {
  871. *IrqStat |= EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT;
  872. Lan9118MmioWrite32 (LAN9118_INT_STS,INSTS_SW_INT);
  873. }
  874. }
  875. // Check Status of transmitted packets
  876. // (We ignore TXSTATUS_NO_CA has it might happen in Full Duplex)
  877. NumTxStatusEntries = Lan9118MmioRead32(LAN9118_TX_FIFO_INF) & TXFIFOINF_TXSUSED_MASK;
  878. if (NumTxStatusEntries > 0) {
  879. TxStatus = Lan9118MmioRead32 (LAN9118_TX_STATUS);
  880. PacketTag = TxStatus >> 16;
  881. TxStatus = TxStatus & 0xFFFF;
  882. if ((TxStatus & TXSTATUS_ES) && (TxStatus != (TXSTATUS_ES | TXSTATUS_NO_CA))) {
  883. DEBUG ((EFI_D_ERROR, "LAN9118: There was an error transmitting. TxStatus=0x%08x:", TxStatus));
  884. if (TxStatus & TXSTATUS_NO_CA) {
  885. DEBUG ((EFI_D_ERROR, "- No carrier\n"));
  886. }
  887. if (TxStatus & TXSTATUS_DEF) {
  888. DEBUG ((EFI_D_ERROR, "- Packet tx was deferred\n"));
  889. }
  890. if (TxStatus & TXSTATUS_EDEF) {
  891. DEBUG ((EFI_D_ERROR, "- Tx ended because of excessive deferral\n"));
  892. }
  893. if (TxStatus & TXSTATUS_ECOLL) {
  894. DEBUG ((EFI_D_ERROR, "- Tx ended because of Excessive Collisions\n"));
  895. }
  896. if (TxStatus & TXSTATUS_LCOLL) {
  897. DEBUG ((EFI_D_ERROR, "- Packet Tx aborted after coll window of 64 bytes\n"));
  898. }
  899. if (TxStatus & TXSTATUS_LOST_CA) {
  900. DEBUG ((EFI_D_ERROR, "- Lost carrier during Tx\n"));
  901. }
  902. return EFI_DEVICE_ERROR;
  903. } else if (TxBuff != NULL) {
  904. LanDriver->Stats.TxTotalFrames += 1;
  905. *TxBuff = LanDriver->TxRing[PacketTag % LAN9118_TX_RING_NUM_ENTRIES];
  906. }
  907. } else if (TxBuff != NULL) {
  908. *TxBuff = NULL;
  909. }
  910. // Check for a TX Error interrupt
  911. Interrupts = Lan9118MmioRead32 (LAN9118_INT_STS);
  912. if (Interrupts & INSTS_TXE) {
  913. DEBUG ((EFI_D_ERROR, "LAN9118: Transmitter error. Restarting..."));
  914. // Software reset, the TXE interrupt is cleared by the reset.
  915. Status = SoftReset (0, Snp);
  916. if (EFI_ERROR (Status)) {
  917. DEBUG ((EFI_D_ERROR, "\n\tSoft Reset Failed: Hardware Error\n"));
  918. return EFI_DEVICE_ERROR;
  919. }
  920. // Reactivate the LEDs
  921. Status = ConfigureHardware (HW_CONF_USE_LEDS, Snp);
  922. if (EFI_ERROR (Status)) {
  923. return Status;
  924. }
  925. //
  926. // Restart the transmitter and if necessary the receiver.
  927. // Do not ask for FIFO reset as it has already been done
  928. // by SoftReset().
  929. //
  930. StartTx (START_TX_MAC | START_TX_CFG, Snp);
  931. if (Snp->Mode->ReceiveFilterSetting != 0) {
  932. StartRx (0, Snp);
  933. }
  934. }
  935. // Update the media status
  936. Status = CheckLinkStatus (0, Snp);
  937. if (EFI_ERROR(Status)) {
  938. Snp->Mode->MediaPresent = FALSE;
  939. } else {
  940. Snp->Mode->MediaPresent = TRUE;
  941. }
  942. return EFI_SUCCESS;
  943. }
  944. /*
  945. * UEFI Transmit() function
  946. *
  947. */
  948. EFI_STATUS
  949. EFIAPI
  950. SnpTransmit (
  951. IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
  952. IN UINTN HdrSize,
  953. IN UINTN BuffSize,
  954. IN VOID* Data,
  955. IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL,
  956. IN EFI_MAC_ADDRESS *DstAddr OPTIONAL,
  957. IN UINT16 *Protocol OPTIONAL
  958. )
  959. {
  960. LAN9118_DRIVER *LanDriver;
  961. UINT32 TxFreeSpace;
  962. UINT32 TxStatusSpace;
  963. INT32 Count;
  964. UINT32 CommandA;
  965. UINT32 CommandB;
  966. UINT16 LocalProtocol;
  967. UINT32 *LocalData;
  968. UINT16 PacketTag;
  969. #if defined(EVAL_PERFORMANCE)
  970. UINT64 Perf;
  971. UINT64 StartClock;
  972. UINT64 EndClock;
  973. Perf = GetPerformanceCounterProperties (NULL, NULL);
  974. StartClock = GetPerformanceCounter ();
  975. #endif
  976. LanDriver = INSTANCE_FROM_SNP_THIS (Snp);
  977. // Check preliminaries
  978. if ((Snp == NULL) || (Data == NULL)) {
  979. return EFI_INVALID_PARAMETER;
  980. }
  981. // Check that driver was started and initialised
  982. if (Snp->Mode->State == EfiSimpleNetworkStarted) {
  983. DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n"));
  984. return EFI_DEVICE_ERROR;
  985. } else if (Snp->Mode->State == EfiSimpleNetworkStopped) {
  986. DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n"));
  987. return EFI_NOT_STARTED;
  988. }
  989. // Ensure header is correct size if non-zero
  990. if (HdrSize) {
  991. if (HdrSize != Snp->Mode->MediaHeaderSize) {
  992. return EFI_INVALID_PARAMETER;
  993. }
  994. if ((DstAddr == NULL) || (Protocol == NULL)) {
  995. return EFI_INVALID_PARAMETER;
  996. }
  997. }
  998. //
  999. // Check validity of BufferSize
  1000. //
  1001. if (BuffSize < Snp->Mode->MediaHeaderSize) {
  1002. return EFI_BUFFER_TOO_SMALL;
  1003. }
  1004. // Before transmitting check the link status
  1005. /*if (CheckLinkStatus (0, Snp) < 0) {
  1006. return EFI_NOT_READY;
  1007. }*/
  1008. // Get DATA FIFO free space in bytes
  1009. TxFreeSpace = TxDataFreeSpace (0, Snp);
  1010. if (TxFreeSpace < BuffSize) {
  1011. return EFI_NOT_READY;
  1012. }
  1013. // Get STATUS FIFO used space in bytes
  1014. TxStatusSpace = TxStatusUsedSpace (0, Snp);
  1015. if (TxStatusSpace > 500) {
  1016. return EFI_NOT_READY;
  1017. }
  1018. // If DstAddr is not provided, get it from Buffer (we trust that the caller
  1019. // has provided a well-formed frame).
  1020. if (DstAddr == NULL) {
  1021. DstAddr = (EFI_MAC_ADDRESS *) Data;
  1022. }
  1023. // Check for the nature of the frame
  1024. if ((DstAddr->Addr[0] & 0x1) == 1) {
  1025. LanDriver->Stats.TxMulticastFrames += 1;
  1026. } else {
  1027. LanDriver->Stats.TxUnicastFrames += 1;
  1028. }
  1029. // Check if broadcast
  1030. if (DstAddr->Addr[0] == 0xFF) {
  1031. LanDriver->Stats.TxBroadcastFrames += 1;
  1032. }
  1033. PacketTag = LanDriver->NextPacketTag;
  1034. LanDriver->NextPacketTag++;
  1035. if (HdrSize) {
  1036. // Format pointer
  1037. LocalData = (UINT32*) Data;
  1038. LocalProtocol = *Protocol;
  1039. // Create first buffer to pass to controller (for the header)
  1040. CommandA = TX_CMD_A_FIRST_SEGMENT | TX_CMD_A_BUFF_SIZE (HdrSize);
  1041. CommandB = TX_CMD_B_PACKET_TAG (PacketTag) | TX_CMD_B_PACKET_LENGTH (BuffSize);
  1042. // Write the commands first
  1043. Lan9118MmioWrite32 (LAN9118_TX_DATA, CommandA);
  1044. Lan9118MmioWrite32 (LAN9118_TX_DATA, CommandB);
  1045. // Write the destination address
  1046. Lan9118MmioWrite32 (LAN9118_TX_DATA,
  1047. (DstAddr->Addr[0]) |
  1048. (DstAddr->Addr[1] << 8) |
  1049. (DstAddr->Addr[2] << 16) |
  1050. (DstAddr->Addr[3] << 24)
  1051. );
  1052. Lan9118MmioWrite32 (LAN9118_TX_DATA,
  1053. (DstAddr->Addr[4]) |
  1054. (DstAddr->Addr[5] << 8) |
  1055. (SrcAddr->Addr[0] << 16) | // Write the Source Address
  1056. (SrcAddr->Addr[1] << 24)
  1057. );
  1058. Lan9118MmioWrite32 (LAN9118_TX_DATA,
  1059. (SrcAddr->Addr[2]) |
  1060. (SrcAddr->Addr[3] << 8) |
  1061. (SrcAddr->Addr[4] << 16) |
  1062. (SrcAddr->Addr[5] << 24)
  1063. );
  1064. // Write the Protocol
  1065. Lan9118MmioWrite32 (LAN9118_TX_DATA, (UINT32)(HTONS (LocalProtocol)));
  1066. // Next buffer is the payload
  1067. CommandA = TX_CMD_A_LAST_SEGMENT | TX_CMD_A_BUFF_SIZE (BuffSize - HdrSize) | TX_CMD_A_COMPLETION_INT | TX_CMD_A_DATA_START_OFFSET (2); // 2 bytes beginning offset
  1068. // Write the commands
  1069. Lan9118MmioWrite32 (LAN9118_TX_DATA, CommandA);
  1070. Lan9118MmioWrite32 (LAN9118_TX_DATA, CommandB);
  1071. // Write the payload
  1072. for (Count = 0; Count < ((BuffSize + 3) >> 2) - 3; Count++) {
  1073. Lan9118MmioWrite32 (LAN9118_TX_DATA, LocalData[Count + 3]);
  1074. }
  1075. } else {
  1076. // Format pointer
  1077. LocalData = (UINT32*) Data;
  1078. // Create a buffer to pass to controller
  1079. CommandA = TX_CMD_A_FIRST_SEGMENT | TX_CMD_A_LAST_SEGMENT | TX_CMD_A_BUFF_SIZE (BuffSize) | TX_CMD_A_COMPLETION_INT;
  1080. CommandB = TX_CMD_B_PACKET_TAG (PacketTag) | TX_CMD_B_PACKET_LENGTH (BuffSize);
  1081. // Write the commands first
  1082. Lan9118MmioWrite32 (LAN9118_TX_DATA, CommandA);
  1083. Lan9118MmioWrite32 (LAN9118_TX_DATA, CommandB);
  1084. // Write all the data
  1085. for (Count = 0; Count < ((BuffSize + 3) >> 2); Count++) {
  1086. Lan9118MmioWrite32 (LAN9118_TX_DATA, LocalData[Count]);
  1087. }
  1088. }
  1089. // Save the address of the submitted packet so we can notify the consumer that
  1090. // it has been sent in GetStatus. When the packet tag appears in the Tx Status
  1091. // Fifo, we will return Buffer in the TxBuff parameter of GetStatus.
  1092. LanDriver->TxRing[PacketTag % LAN9118_TX_RING_NUM_ENTRIES] = Data;
  1093. #if defined(EVAL_PERFORMANCE)
  1094. EndClock = GetPerformanceCounter ();
  1095. DEBUG ((EFI_D_ERROR, "Time processing: %d counts @ %d Hz\n", StartClock - EndClock,Perf));
  1096. #endif
  1097. LanDriver->Stats.TxGoodFrames += 1;
  1098. return EFI_SUCCESS;
  1099. }
  1100. /*
  1101. * UEFI Receive() function
  1102. *
  1103. */
  1104. EFI_STATUS
  1105. EFIAPI
  1106. SnpReceive (
  1107. IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp,
  1108. OUT UINTN *HdrSize OPTIONAL,
  1109. IN OUT UINTN *BuffSize,
  1110. OUT VOID *Data,
  1111. OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL,
  1112. OUT EFI_MAC_ADDRESS *DstAddr OPTIONAL,
  1113. OUT UINT16 *Protocol OPTIONAL
  1114. )
  1115. {
  1116. LAN9118_DRIVER *LanDriver;
  1117. UINT32 IntSts;
  1118. UINT32 RxFifoStatus;
  1119. UINT32 NumPackets;
  1120. UINT32 RxCfgValue;
  1121. UINT32 PLength; // Packet length
  1122. UINT32 ReadLimit;
  1123. UINT32 Count;
  1124. UINT32 Padding;
  1125. UINT32 *RawData;
  1126. EFI_MAC_ADDRESS Dst;
  1127. EFI_MAC_ADDRESS Src;
  1128. UINTN DroppedFrames;
  1129. EFI_STATUS Status;
  1130. LanDriver = INSTANCE_FROM_SNP_THIS (Snp);
  1131. #if defined(EVAL_PERFORMANCE)
  1132. UINT64 Perf = GetPerformanceCounterProperties (NULL, NULL);
  1133. UINT64 StartClock = GetPerformanceCounter ();
  1134. #endif
  1135. // Check preliminaries
  1136. if ((Snp == NULL) || (Data == NULL) || (BuffSize == NULL)) {
  1137. return EFI_INVALID_PARAMETER;
  1138. }
  1139. // Check that driver was started and initialised
  1140. if (Snp->Mode->State == EfiSimpleNetworkStarted) {
  1141. DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n"));
  1142. return EFI_DEVICE_ERROR;
  1143. } else if (Snp->Mode->State == EfiSimpleNetworkStopped) {
  1144. DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n"));
  1145. return EFI_NOT_STARTED;
  1146. }
  1147. //
  1148. // If the receiver raised the RXE error bit, check if the receiver status
  1149. // FIFO is full and if not just acknowledge the error. The two other
  1150. // conditions to get a RXE error are :
  1151. // . the RX data FIFO is read whereas being empty.
  1152. // . the RX status FIFO is read whereas being empty.
  1153. // The RX data and status FIFO are read by this driver only in the following
  1154. // code of this function. After the readings, the RXE error bit is checked
  1155. // and if raised, the controller is reset. Thus, at this point, we consider
  1156. // that the only valid reason to get an RXE error is the receiver status
  1157. // FIFO being full. And if this is not the case, we consider that this is
  1158. // a spurious error and we just get rid of it. We experienced such 'spurious'
  1159. // errors when running the driver on an A57 on Juno. No valid reason to
  1160. // explain those errors has been found so far and everything seems to
  1161. // work perfectly when they are just ignored.
  1162. //
  1163. IntSts = Lan9118MmioRead32 (LAN9118_INT_STS);
  1164. if ((IntSts & INSTS_RXE) && (!(IntSts & INSTS_RSFF))) {
  1165. Lan9118MmioWrite32 (LAN9118_INT_STS, INSTS_RXE);
  1166. }
  1167. // Count dropped frames
  1168. DroppedFrames = Lan9118MmioRead32 (LAN9118_RX_DROP);
  1169. LanDriver->Stats.RxDroppedFrames += DroppedFrames;
  1170. NumPackets = RxStatusUsedSpace (0, Snp) / 4;
  1171. if (!NumPackets) {
  1172. return EFI_NOT_READY;
  1173. }
  1174. // Read Rx Status (only if not empty)
  1175. RxFifoStatus = Lan9118MmioRead32 (LAN9118_RX_STATUS);
  1176. LanDriver->Stats.RxTotalFrames += 1;
  1177. // First check for errors
  1178. if ((RxFifoStatus & RXSTATUS_MII_ERROR) ||
  1179. (RxFifoStatus & RXSTATUS_RXW_TO) ||
  1180. (RxFifoStatus & RXSTATUS_FTL) ||
  1181. (RxFifoStatus & RXSTATUS_LCOLL) ||
  1182. (RxFifoStatus & RXSTATUS_LE) ||
  1183. (RxFifoStatus & RXSTATUS_DB))
  1184. {
  1185. DEBUG ((EFI_D_WARN, "Warning: There was an error on frame reception.\n"));
  1186. return EFI_DEVICE_ERROR;
  1187. }
  1188. // Check if we got a CRC error
  1189. if (RxFifoStatus & RXSTATUS_CRC_ERROR) {
  1190. DEBUG ((EFI_D_WARN, "Warning: Crc Error\n"));
  1191. LanDriver->Stats.RxCrcErrorFrames += 1;
  1192. LanDriver->Stats.RxDroppedFrames += 1;
  1193. return EFI_DEVICE_ERROR;
  1194. }
  1195. // Check if we got a runt frame
  1196. if (RxFifoStatus & RXSTATUS_RUNT) {
  1197. DEBUG ((EFI_D_WARN, "Warning: Runt Frame\n"));
  1198. LanDriver->Stats.RxUndersizeFrames += 1;
  1199. LanDriver->Stats.RxDroppedFrames += 1;
  1200. return EFI_DEVICE_ERROR;
  1201. }
  1202. // Check filtering status for this packet
  1203. if (RxFifoStatus & RXSTATUS_FILT_FAIL) {
  1204. DEBUG ((EFI_D_WARN, "Warning: Frame Failed Filtering\n"));
  1205. // fast forward?
  1206. }
  1207. // Check if we got a broadcast frame
  1208. if (RxFifoStatus & RXSTATUS_BCF) {
  1209. LanDriver->Stats.RxBroadcastFrames += 1;
  1210. }
  1211. // Check if we got a multicast frame
  1212. if (RxFifoStatus & RXSTATUS_MCF) {
  1213. LanDriver->Stats.RxMulticastFrames += 1;
  1214. }
  1215. // Check if we got a unicast frame
  1216. if ((RxFifoStatus & RXSTATUS_BCF) && ((RxFifoStatus & RXSTATUS_MCF) == 0)) {
  1217. LanDriver->Stats.RxUnicastFrames += 1;
  1218. }
  1219. // Get the received packet length
  1220. PLength = GET_RXSTATUS_PACKET_LENGTH(RxFifoStatus);
  1221. LanDriver->Stats.RxTotalBytes += (PLength - 4);
  1222. // If padding is applied, read more DWORDs
  1223. if (PLength % 4) {
  1224. Padding = 4 - (PLength % 4);
  1225. ReadLimit = (PLength + Padding)/4;
  1226. } else {
  1227. ReadLimit = PLength/4;
  1228. Padding = 0;
  1229. }
  1230. // Check buffer size
  1231. if (*BuffSize < (PLength + Padding)) {
  1232. *BuffSize = PLength + Padding;
  1233. return EFI_BUFFER_TOO_SMALL;
  1234. }
  1235. // Set the amount of data to be transfered out of FIFO for THIS packet
  1236. // This can be used to trigger an interrupt, and status can be checked
  1237. RxCfgValue = Lan9118MmioRead32 (LAN9118_RX_CFG);
  1238. RxCfgValue &= ~(RXCFG_RX_DMA_CNT_MASK);
  1239. RxCfgValue |= RXCFG_RX_DMA_CNT (ReadLimit);
  1240. // Set end alignment to 4-bytes
  1241. RxCfgValue &= ~(RXCFG_RX_END_ALIGN_MASK);
  1242. Lan9118MmioWrite32 (LAN9118_RX_CFG, RxCfgValue);
  1243. // Update buffer size
  1244. *BuffSize = PLength; // -4 bytes may be needed: Received in buffer as
  1245. // 4 bytes longer than packet actually is, unless
  1246. // packet is < 64 bytes
  1247. if (HdrSize != NULL)
  1248. *HdrSize = Snp->Mode->MediaHeaderSize;
  1249. // Format the pointer
  1250. RawData = (UINT32*)Data;
  1251. // Read Rx Packet
  1252. for (Count = 0; Count < ReadLimit; Count++) {
  1253. RawData[Count] = Lan9118MmioRead32 (LAN9118_RX_DATA);
  1254. }
  1255. // Get the destination address
  1256. if (DstAddr != NULL) {
  1257. Dst.Addr[0] = (RawData[0] & 0xFF);
  1258. Dst.Addr[1] = (RawData[0] & 0xFF00) >> 8;
  1259. Dst.Addr[2] = (RawData[0] & 0xFF0000) >> 16;
  1260. Dst.Addr[3] = (RawData[0] & 0xFF000000) >> 24;
  1261. Dst.Addr[4] = (RawData[1] & 0xFF);
  1262. Dst.Addr[5] = (RawData[1] & 0xFF00) >> 8;
  1263. CopyMem (DstAddr, &Dst, NET_ETHER_ADDR_LEN);
  1264. }
  1265. // Get the source address
  1266. if (SrcAddr != NULL) {
  1267. Src.Addr[0] = (RawData[1] & 0xFF0000) >> 16;
  1268. Src.Addr[1] = (RawData[1] & 0xFF000000) >> 24;
  1269. Src.Addr[2] = (RawData[2] & 0xFF);
  1270. Src.Addr[3] = (RawData[2] & 0xFF00) >> 8;
  1271. Src.Addr[4] = (RawData[2] & 0xFF0000) >> 16;
  1272. Src.Addr[5] = (RawData[2] & 0xFF000000) >> 24;
  1273. CopyMem (SrcAddr, &Src, NET_ETHER_ADDR_LEN);
  1274. }
  1275. // Get the protocol
  1276. if (Protocol != NULL) {
  1277. *Protocol = NTOHS (RawData[3] & 0xFFFF);
  1278. }
  1279. // Check for Rx errors (worst possible error)
  1280. if (Lan9118MmioRead32 (LAN9118_INT_STS) & INSTS_RXE) {
  1281. DEBUG ((EFI_D_WARN, "Warning: Receiver Error. Restarting...\n"));
  1282. // Software reset, the RXE interrupt is cleared by the reset.
  1283. Status = SoftReset (0, Snp);
  1284. if (EFI_ERROR (Status)) {
  1285. DEBUG ((EFI_D_ERROR, "Error: Soft Reset Failed: Hardware Error.\n"));
  1286. return EFI_DEVICE_ERROR;
  1287. }
  1288. // Reactivate the LEDs
  1289. Status = ConfigureHardware (HW_CONF_USE_LEDS, Snp);
  1290. if (EFI_ERROR (Status)) {
  1291. return Status;
  1292. }
  1293. //
  1294. // Restart the receiver and the transmitter without resetting the FIFOs
  1295. // as it has been done by SoftReset().
  1296. //
  1297. StartRx (0, Snp);
  1298. StartTx (START_TX_MAC | START_TX_CFG, Snp);
  1299. // Say that command could not be sent
  1300. return EFI_DEVICE_ERROR;
  1301. }
  1302. #if defined(EVAL_PERFORMANCE)
  1303. UINT64 EndClock = GetPerformanceCounter ();
  1304. DEBUG ((EFI_D_ERROR, "Receive Time processing: %d counts @ %d Hz\n", StartClock - EndClock,Perf));
  1305. #endif
  1306. LanDriver->Stats.RxGoodFrames += 1;
  1307. return EFI_SUCCESS;
  1308. }