Lan91xDxe.c 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229
  1. /** @file
  2. * SMSC LAN91x series Network Controller Driver.
  3. *
  4. * Copyright (c) 2013-2017 Linaro.org
  5. *
  6. * Derived from the LAN9118 driver. Original sources
  7. * Copyright (c) 2012-2013, ARM Limited. All rights reserved.
  8. *
  9. * SPDX-License-Identifier: BSD-2-Clause-Patent
  10. *
  11. **/
  12. #include <Uefi.h>
  13. #include <Uefi/UefiSpec.h>
  14. #include <Base.h>
  15. // Protocols used by this driver
  16. #include <Protocol/SimpleNetwork.h>
  17. #include <Protocol/ComponentName2.h>
  18. #include <Protocol/PxeBaseCode.h>
  19. #include <Protocol/DevicePath.h>
  20. // Libraries used by this driver
  21. #include <Library/UefiLib.h>
  22. #include <Library/DebugLib.h>
  23. #include <Library/UefiBootServicesTableLib.h>
  24. #include <Library/MemoryAllocationLib.h>
  25. #include <Library/IoLib.h>
  26. #include <Library/PcdLib.h>
  27. #include <Library/NetLib.h>
  28. #include <Library/DevicePathLib.h>
  29. // Hardware register definitions
  30. #include "Lan91xDxeHw.h"
  31. // Debugging output options
  32. //#define LAN91X_PRINT_REGISTERS 1
  33. //#define LAN91X_PRINT_PACKET_HEADERS 1
  34. //#define LAN91X_PRINT_RECEIVE_FILTERS 1
  35. // Chip power-down option -- UNTESTED
  36. //#define LAN91X_POWER_DOWN 1
  37. /*---------------------------------------------------------------------------------------------------------------------
  38. LAN91x Information Structure
  39. ---------------------------------------------------------------------------------------------------------------------*/
  40. typedef struct _LAN91X_DRIVER {
  41. // Driver signature
  42. UINT32 Signature;
  43. EFI_HANDLE ControllerHandle;
  44. // EFI SNP protocol instances
  45. EFI_SIMPLE_NETWORK_PROTOCOL Snp;
  46. EFI_SIMPLE_NETWORK_MODE SnpMode;
  47. // EFI Snp statistics instance
  48. EFI_NETWORK_STATISTICS Stats;
  49. // Transmit Buffer recycle queue
  50. LIST_ENTRY TransmitQueueHead;
  51. // Register access variables
  52. UINTN IoBase; // I/O Base Address
  53. UINT8 Revision; // Chip Revision Number
  54. INT8 PhyAd; // Phy Address
  55. UINT8 BankSel; // Currently selected register bank
  56. } LAN91X_DRIVER;
  57. #define LAN91X_NO_PHY (-1) // PhyAd value if PHY not detected
  58. #define LAN91X_SIGNATURE SIGNATURE_32('S', 'M', '9', '1')
  59. #define INSTANCE_FROM_SNP_THIS(a) CR(a, LAN91X_DRIVER, Snp, LAN91X_SIGNATURE)
  60. #define LAN91X_STALL 2
  61. #define LAN91X_MEMORY_ALLOC_POLLS 100 // Max times to poll for memory allocation
  62. #define LAN91X_PKT_OVERHEAD 6 // Overhead bytes in packet buffer
  63. // Synchronization TPLs
  64. #define LAN91X_TPL TPL_CALLBACK
  65. // Most common CRC32 Polynomial for little endian machines
  66. #define CRC_POLYNOMIAL 0xEDB88320
  67. typedef struct {
  68. MAC_ADDR_DEVICE_PATH Lan91x;
  69. EFI_DEVICE_PATH_PROTOCOL End;
  70. } LAN91X_DEVICE_PATH;
  71. LAN91X_DEVICE_PATH Lan91xPathTemplate = {
  72. {
  73. {
  74. MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP,
  75. { (UINT8) (sizeof(MAC_ADDR_DEVICE_PATH)), (UINT8) ((sizeof(MAC_ADDR_DEVICE_PATH)) >> 8) }
  76. },
  77. { { 0 } },
  78. 0
  79. },
  80. {
  81. END_DEVICE_PATH_TYPE,
  82. END_ENTIRE_DEVICE_PATH_SUBTYPE,
  83. { sizeof(EFI_DEVICE_PATH_PROTOCOL), 0 }
  84. }
  85. };
  86. // Chip ID numbers and name strings
  87. #define CHIP_9192 3
  88. #define CHIP_9194 4
  89. #define CHIP_9195 5
  90. #define CHIP_9196 6
  91. #define CHIP_91100 7
  92. #define CHIP_91100FD 8
  93. #define CHIP_91111FD 9
  94. STATIC CHAR16 CONST * CONST ChipIds[ 16 ] = {
  95. NULL, NULL, NULL,
  96. /* 3 */ L"SMC91C90/91C92",
  97. /* 4 */ L"SMC91C94",
  98. /* 5 */ L"SMC91C95",
  99. /* 6 */ L"SMC91C96",
  100. /* 7 */ L"SMC91C100",
  101. /* 8 */ L"SMC91C100FD",
  102. /* 9 */ L"SMC91C11xFD",
  103. NULL, NULL, NULL,
  104. NULL, NULL, NULL
  105. };
  106. /* ------------------ TxBuffer Queue structures ------------------- */
  107. typedef struct {
  108. VOID *Buf;
  109. UINTN Length;
  110. } MSK_SYSTEM_BUF;
  111. typedef struct {
  112. UINTN Signature;
  113. LIST_ENTRY Link;
  114. MSK_SYSTEM_BUF SystemBuf;
  115. } MSK_LINKED_SYSTEM_BUF;
  116. #define TX_MBUF_SIGNATURE SIGNATURE_32 ('t','x','m','b')
  117. /* ------------------ MAC Address Hash Calculations ------------------- */
  118. /*
  119. ** Generate a hash value from a multicast address
  120. **
  121. ** This uses the Ethernet standard CRC32 algorithm
  122. **
  123. ** INFO USED:
  124. ** 1: http://en.wikipedia.org/wiki/Cyclic_redundancy_check
  125. **
  126. ** 2: http://www.erg.abdn.ac.uk/~gorry/eg3567/dl-pages/crc.html
  127. **
  128. ** 3: http://en.wikipedia.org/wiki/Computation_of_CRC
  129. */
  130. STATIC
  131. UINT32
  132. MulticastHash (
  133. IN EFI_MAC_ADDRESS *Mac,
  134. IN UINT32 AddrLen
  135. )
  136. {
  137. UINT32 Iter;
  138. UINT32 Remainder;
  139. UINT32 Crc32;
  140. UINT8 *Addr;
  141. // 0xFFFFFFFF is standard seed for Ethernet
  142. Remainder = 0xFFFFFFFF;
  143. // Generate the remainder byte-by-byte (LSB first)
  144. Addr = &Mac->Addr[0];
  145. while (AddrLen-- > 0) {
  146. Remainder ^= *Addr++;
  147. for (Iter = 0; Iter < 8; ++Iter) {
  148. // Check if exponent is set
  149. if ((Remainder & 1) != 0) {
  150. Remainder = (Remainder >> 1) ^ CRC_POLYNOMIAL;
  151. } else {
  152. Remainder = (Remainder >> 1) ^ 0;
  153. }
  154. }
  155. }
  156. // Reverse the bits of the remainder
  157. Crc32 = 0;
  158. for (Iter = 0; Iter < 32; ++Iter) {
  159. Crc32 <<= 1;
  160. Crc32 |= Remainder & 1;
  161. Remainder >>= 1;
  162. }
  163. return Crc32;
  164. }
  165. /* ---------------- Banked Register Operations ------------------ */
  166. // Select the proper I/O bank
  167. STATIC
  168. VOID
  169. SelectIoBank (
  170. LAN91X_DRIVER *LanDriver,
  171. UINTN Register
  172. )
  173. {
  174. UINT8 Bank;
  175. Bank = RegisterToBank (Register);
  176. // Select the proper I/O bank
  177. if (LanDriver->BankSel != Bank) {
  178. MmioWrite16 (LanDriver->IoBase + LAN91X_BANK_OFFSET, Bank);
  179. LanDriver->BankSel = Bank;
  180. }
  181. }
  182. // Read a 16-bit I/O-space register
  183. STATIC
  184. UINT16
  185. ReadIoReg16 (
  186. LAN91X_DRIVER *LanDriver,
  187. UINTN Register
  188. )
  189. {
  190. UINT8 Offset;
  191. // Select the proper I/O bank
  192. SelectIoBank (LanDriver, Register);
  193. // Read the requested register
  194. Offset = RegisterToOffset (Register);
  195. return MmioRead16 (LanDriver->IoBase + Offset);
  196. }
  197. // Write a 16-bit I/O-space register
  198. STATIC
  199. UINT16
  200. WriteIoReg16 (
  201. LAN91X_DRIVER *LanDriver,
  202. UINTN Register,
  203. UINT16 Value
  204. )
  205. {
  206. UINT8 Offset;
  207. // Select the proper I/O bank
  208. SelectIoBank (LanDriver, Register);
  209. // Write the requested register
  210. Offset = RegisterToOffset (Register);
  211. return MmioWrite16 (LanDriver->IoBase + Offset, Value);
  212. }
  213. // Read an 8-bit I/O-space register
  214. STATIC
  215. UINT8
  216. ReadIoReg8 (
  217. LAN91X_DRIVER *LanDriver,
  218. UINTN Register
  219. )
  220. {
  221. UINT8 Offset;
  222. // Select the proper I/O bank
  223. SelectIoBank (LanDriver, Register);
  224. // Read the requested register
  225. Offset = RegisterToOffset (Register);
  226. return MmioRead8 (LanDriver->IoBase + Offset);
  227. }
  228. // Write an 8-bit I/O-space register
  229. STATIC
  230. UINT8
  231. WriteIoReg8 (
  232. LAN91X_DRIVER *LanDriver,
  233. UINTN Register,
  234. UINT8 Value
  235. )
  236. {
  237. UINT8 Offset;
  238. // Select the proper I/O bank
  239. SelectIoBank (LanDriver, Register);
  240. // Write the requested register
  241. Offset = RegisterToOffset (Register);
  242. return MmioWrite8 (LanDriver->IoBase + Offset, Value);
  243. }
  244. /* ---------------- MII/PHY Access Operations ------------------ */
  245. #define LAN91X_MDIO_STALL 1
  246. STATIC
  247. VOID
  248. MdioOutput (
  249. LAN91X_DRIVER *LanDriver,
  250. UINTN Bits,
  251. UINT32 Value
  252. )
  253. {
  254. UINT16 MgmtReg;
  255. UINT32 Mask;
  256. MgmtReg = ReadIoReg16 (LanDriver, LAN91X_MGMT);
  257. MgmtReg &= ~MGMT_MCLK;
  258. MgmtReg |= MGMT_MDOE;
  259. for (Mask = (1 << (Bits - 1)); Mask != 0; Mask >>= 1) {
  260. if ((Value & Mask) != 0) {
  261. MgmtReg |= MGMT_MDO;
  262. } else {
  263. MgmtReg &= ~MGMT_MDO;
  264. }
  265. WriteIoReg16 (LanDriver, LAN91X_MGMT, MgmtReg);
  266. gBS->Stall (LAN91X_MDIO_STALL);
  267. WriteIoReg16 (LanDriver, LAN91X_MGMT, MgmtReg | MGMT_MCLK);
  268. gBS->Stall (LAN91X_MDIO_STALL);
  269. }
  270. }
  271. #define PHY_OUTPUT_TIME (2 * LAN91X_MDIO_STALL)
  272. STATIC
  273. UINT32
  274. MdioInput (
  275. LAN91X_DRIVER *LanDriver,
  276. UINTN Bits
  277. )
  278. {
  279. UINT16 MgmtReg;
  280. UINT32 Mask;
  281. UINT32 Value;
  282. MgmtReg = ReadIoReg16 (LanDriver, LAN91X_MGMT);
  283. MgmtReg &= ~(MGMT_MDOE | MGMT_MCLK | MGMT_MDO);
  284. WriteIoReg16 (LanDriver, LAN91X_MGMT, MgmtReg);
  285. Value = 0;
  286. for (Mask = (1 << (Bits - 1)); Mask != 0; Mask >>= 1) {
  287. if ((ReadIoReg16 (LanDriver, LAN91X_MGMT) & MGMT_MDI) != 0) {
  288. Value |= Mask;
  289. }
  290. WriteIoReg16 (LanDriver, LAN91X_MGMT, MgmtReg);
  291. gBS->Stall (LAN91X_MDIO_STALL);
  292. WriteIoReg16 (LanDriver, LAN91X_MGMT, MgmtReg | MGMT_MCLK);
  293. gBS->Stall (LAN91X_MDIO_STALL);
  294. }
  295. return Value;
  296. }
  297. #define PHY_INPUT_TIME (2 * LAN91X_MDIO_STALL)
  298. STATIC
  299. VOID
  300. MdioIdle (
  301. LAN91X_DRIVER *LanDriver
  302. )
  303. {
  304. UINT16 MgmtReg;
  305. MgmtReg = ReadIoReg16 (LanDriver, LAN91X_MGMT);
  306. MgmtReg &= ~(MGMT_MDOE | MGMT_MCLK | MGMT_MDO);
  307. WriteIoReg16 (LanDriver, LAN91X_MGMT, MgmtReg);
  308. }
  309. // Write to a PHY register
  310. STATIC
  311. VOID
  312. WritePhyReg16 (
  313. LAN91X_DRIVER *LanDriver,
  314. UINTN RegAd,
  315. UINT16 Value
  316. )
  317. {
  318. // Bit-bang the MII Serial Frame write operation
  319. MdioOutput (LanDriver, 32, 0xffffffff); // Send 32 Ones as a preamble
  320. MdioOutput (LanDriver, 2, 0x01); // Send Start (01)
  321. MdioOutput (LanDriver, 2, 0x01); // Send Write (01)
  322. MdioOutput (LanDriver, 5, LanDriver->PhyAd); // Send PHYAD[4:0]
  323. MdioOutput (LanDriver, 5, RegAd); // Send REGAD[4:0]
  324. MdioOutput (LanDriver, 2, 0x02); // Send TurnAround (10)
  325. MdioOutput (LanDriver, 16, Value); // Write 16 data bits
  326. // Idle the MDIO bus
  327. MdioIdle (LanDriver);
  328. }
  329. // Calculate approximate time to write a PHY register in microseconds
  330. #define PHY_WRITE_TIME ((32 + 2 + 2 + 5 + 5 + 2 + 16) * PHY_OUTPUT_TIME)
  331. // Read from a PHY register
  332. STATIC
  333. UINT16
  334. ReadPhyReg16 (
  335. LAN91X_DRIVER *LanDriver,
  336. UINTN RegAd
  337. )
  338. {
  339. UINT32 Value;
  340. // Bit-bang the MII Serial Frame read operation
  341. MdioOutput (LanDriver, 32, 0xffffffff); // Send 32 Ones as a preamble
  342. MdioOutput (LanDriver, 2, 0x01); // Send Start (01)
  343. MdioOutput (LanDriver, 2, 0x02); // Send Read (10)
  344. MdioOutput (LanDriver, 5, LanDriver->PhyAd); // Send PHYAD[4:0]
  345. MdioOutput (LanDriver, 5, RegAd); // Send REGAD[4:0]
  346. (VOID) MdioInput (LanDriver, 2); // Discard TurnAround bits
  347. Value = MdioInput (LanDriver, 16); // Read 16 data bits
  348. // Idle the MDIO bus
  349. MdioIdle (LanDriver);
  350. return (Value & 0xffff);
  351. }
  352. // Calculate approximate time to read a PHY register in microseconds
  353. #define PHY_READ_TIME (((32 + 2 + 2 + 5 + 5) * PHY_OUTPUT_TIME) + \
  354. ((2 + 16) * PHY_INPUT_TIME))
  355. /* ---------------- Debug Functions ------------------ */
  356. #ifdef LAN91X_PRINT_REGISTERS
  357. STATIC
  358. VOID
  359. PrintIoRegisters (
  360. IN LAN91X_DRIVER *LanDriver
  361. )
  362. {
  363. UINTN Bank;
  364. UINTN Offset;
  365. UINT16 Value;
  366. DEBUG ((DEBUG_ERROR, "\nLAN91x I/O Register Dump:\n"));
  367. // Print currrent bank select register
  368. Value = MmioRead16 (LanDriver->IoBase + LAN91X_BANK_OFFSET);
  369. DEBUG ((DEBUG_ERROR, " BankSel: %d Bank Register %04x (%d)\n",
  370. LanDriver->BankSel, Value, Value & 0x0007));
  371. // Print all I/O registers
  372. for (Offset = 0; Offset < 0x0e; Offset += 2) {
  373. DEBUG ((DEBUG_ERROR, " %02x:", Offset));
  374. for (Bank = 0; Bank <= 3; ++Bank) {
  375. DEBUG ((DEBUG_ERROR, " %04x", ReadIoReg16 (LanDriver, MakeRegister (Bank, Offset))));
  376. }
  377. DEBUG ((DEBUG_ERROR, "\n"));
  378. }
  379. }
  380. STATIC
  381. VOID
  382. PrintPhyRegisters (
  383. IN LAN91X_DRIVER *LanDriver
  384. )
  385. {
  386. UINTN RegNum;
  387. DEBUG ((DEBUG_ERROR, "\nLAN91x Phy %d Register Dump:\n", LanDriver->PhyAd));
  388. // Print all Phy registers
  389. for (RegNum = 0; RegNum <= 5; ++RegNum) {
  390. DEBUG ((DEBUG_ERROR, " %2d: %04x\n",
  391. RegNum,
  392. ReadPhyReg16 (LanDriver, RegNum)
  393. ));
  394. }
  395. for (RegNum = 16; RegNum <= 20; ++RegNum) {
  396. DEBUG ((DEBUG_ERROR, " %2d: %04x\n",
  397. RegNum,
  398. ReadPhyReg16 (LanDriver, RegNum)
  399. ));
  400. }
  401. }
  402. #endif
  403. #if LAN91X_PRINT_PACKET_HEADERS
  404. STATIC
  405. VOID
  406. PrintIpDgram (
  407. IN CONST VOID *DstMac,
  408. IN CONST VOID *SrcMac,
  409. IN CONST VOID *Proto,
  410. IN CONST VOID *IpDgram
  411. )
  412. {
  413. CONST UINT8 *Ptr;
  414. UINT16 SrcPort;
  415. UINT16 DstPort;
  416. Ptr = DstMac;
  417. DEBUG ((DEBUG_ERROR, " Dst: %02x-%02x-%02x",
  418. Ptr[0], Ptr[1], Ptr[2]));
  419. DEBUG ((DEBUG_ERROR, "-%02x-%02x-%02x",
  420. Ptr[3], Ptr[4], Ptr[5]));
  421. Ptr = SrcMac;
  422. DEBUG ((DEBUG_ERROR, " Src: %02x-%02x-%02x",
  423. Ptr[0], Ptr[1], Ptr[2]));
  424. DEBUG ((DEBUG_ERROR, "-%02x-%02x-%02x",
  425. Ptr[3], Ptr[4], Ptr[5]));
  426. Ptr = Proto;
  427. DEBUG ((DEBUG_ERROR, " Proto: %02x%02x\n",
  428. Ptr[0], Ptr[1]));
  429. Ptr = IpDgram;
  430. switch (Ptr[9]) {
  431. case EFI_IP_PROTO_ICMP:
  432. DEBUG ((DEBUG_ERROR, " ICMP"));
  433. break;
  434. case EFI_IP_PROTO_TCP:
  435. DEBUG ((DEBUG_ERROR, " TCP"));
  436. break;
  437. case EFI_IP_PROTO_UDP:
  438. DEBUG ((DEBUG_ERROR, " UDP"));
  439. break;
  440. default:
  441. DEBUG ((DEBUG_ERROR, " IpProto %d\n", Ptr[9]));
  442. return;
  443. }
  444. DEBUG ((DEBUG_ERROR, " SrcIp: %d.%d.%d.%d",
  445. Ptr[12], Ptr[13], Ptr[14], Ptr[15]));
  446. DEBUG ((DEBUG_ERROR, " DstIp: %d.%d.%d.%d",
  447. Ptr[16], Ptr[17], Ptr[18], Ptr[19]));
  448. SrcPort = (Ptr[20] << 8) | Ptr[21];
  449. DstPort = (Ptr[22] << 8) | Ptr[23];
  450. DEBUG ((DEBUG_ERROR, " SrcPort: %d DstPort: %d\n", SrcPort, DstPort));
  451. }
  452. #endif
  453. /* ---------------- PHY Management Operations ----------------- */
  454. STATIC
  455. EFI_STATUS
  456. PhyDetect (
  457. IN LAN91X_DRIVER *LanDriver
  458. )
  459. {
  460. UINT16 PhyId1;
  461. UINT16 PhyId2;
  462. for (LanDriver->PhyAd = 0x1f; LanDriver->PhyAd >= 0 ; --LanDriver->PhyAd) {
  463. PhyId1 = ReadPhyReg16 (LanDriver, PHY_INDEX_ID1);
  464. PhyId2 = ReadPhyReg16 (LanDriver, PHY_INDEX_ID2);
  465. if ((PhyId1 != 0x0000) && (PhyId1 != 0xffff) &&
  466. (PhyId2 != 0x0000) && (PhyId2 != 0xffff)) {
  467. if ((PhyId1 == 0x0016) && ((PhyId2 & 0xfff0) == 0xf840)) {
  468. DEBUG ((DEBUG_ERROR, "LAN91x: PHY type LAN83C183 (LAN91C111 Internal)\n"));
  469. } else if ((PhyId1 == 0x0282) && ((PhyId2 & 0xfff0) == 0x1c50)) {
  470. DEBUG ((DEBUG_ERROR, "LAN91x: PHY type LAN83C180\n"));
  471. } else {
  472. DEBUG ((DEBUG_ERROR, "LAN91x: PHY id %04x:%04x\n", PhyId1, PhyId2));
  473. }
  474. return EFI_SUCCESS;
  475. }
  476. }
  477. DEBUG ((DEBUG_ERROR, "LAN91x: PHY detection failed\n"));
  478. return EFI_NO_MEDIA;
  479. }
  480. // Check the Link Status and take appropriate action
  481. STATIC
  482. BOOLEAN
  483. CheckLinkStatus (
  484. IN LAN91X_DRIVER *LanDriver
  485. )
  486. {
  487. UINT16 PhyStatus;
  488. // Get the PHY Status
  489. PhyStatus = ReadPhyReg16 (LanDriver, PHY_INDEX_BASIC_STATUS);
  490. return (PhyStatus & PHYSTS_LINK_STS) != 0;
  491. }
  492. // Do auto-negotiation
  493. STATIC
  494. EFI_STATUS
  495. PhyAutoNegotiate (
  496. IN LAN91X_DRIVER *LanDriver
  497. )
  498. {
  499. UINTN Retries;
  500. UINT16 PhyControl;
  501. UINT16 PhyStatus;
  502. UINT16 PhyAdvert;
  503. // If there isn't a PHY, don't try to reset it
  504. if (LanDriver->PhyAd == LAN91X_NO_PHY) {
  505. return EFI_SUCCESS;
  506. }
  507. // Next check that auto-negotiation is supported
  508. PhyStatus = ReadPhyReg16 (LanDriver, PHY_INDEX_BASIC_STATUS);
  509. if ((PhyStatus & PHYSTS_AUTO_CAP) == 0) {
  510. return EFI_SUCCESS;
  511. }
  512. // Translate capabilities to advertise
  513. PhyAdvert = PHYANA_CSMA;
  514. if ((PhyStatus & PHYSTS_10BASET_HDPLX) != 0) {
  515. PhyAdvert |= PHYANA_10BASET;
  516. }
  517. if ((PhyStatus & PHYSTS_10BASET_FDPLX) != 0) {
  518. PhyAdvert |= PHYANA_10BASETFD;
  519. }
  520. if ((PhyStatus & PHYSTS_100BASETX_HDPLX) != 0) {
  521. PhyAdvert |= PHYANA_100BASETX;
  522. }
  523. if ((PhyStatus & PHYSTS_100BASETX_FDPLX) != 0) {
  524. PhyAdvert |= PHYANA_100BASETXFD;
  525. }
  526. if ((PhyStatus & PHYSTS_100BASE_T4) != 0) {
  527. PhyAdvert |= PHYANA_100BASET4;
  528. }
  529. // Set the capabilities to advertise
  530. WritePhyReg16 (LanDriver, PHY_INDEX_AUTO_NEG_ADVERT, PhyAdvert);
  531. (VOID) ReadPhyReg16 (LanDriver, PHY_INDEX_AUTO_NEG_ADVERT);
  532. // Restart Auto-Negotiation
  533. PhyControl = ReadPhyReg16 (LanDriver, PHY_INDEX_BASIC_CTRL);
  534. PhyControl &= ~(PHYCR_SPEED_SEL | PHYCR_DUPLEX_MODE);
  535. PhyControl |= PHYCR_AUTO_EN | PHYCR_RST_AUTO;
  536. WritePhyReg16 (LanDriver, PHY_INDEX_BASIC_CTRL, PhyControl);
  537. // Wait up to 2 seconds for the process to complete
  538. Retries = 2000000 / (PHY_READ_TIME + 100);
  539. while ((ReadPhyReg16 (LanDriver, PHY_INDEX_BASIC_STATUS) & PHYSTS_AUTO_COMP) == 0) {
  540. if (--Retries == 0) {
  541. DEBUG ((DEBUG_ERROR, "LAN91x: PHY auto-negotiation timed-out\n"));
  542. return EFI_TIMEOUT;
  543. }
  544. gBS->Stall (100);
  545. }
  546. return EFI_SUCCESS;
  547. }
  548. // Perform PHY software reset
  549. STATIC
  550. EFI_STATUS
  551. PhySoftReset (
  552. IN LAN91X_DRIVER *LanDriver
  553. )
  554. {
  555. UINTN Retries;
  556. // If there isn't a PHY, don't try to reset it
  557. if (LanDriver->PhyAd == LAN91X_NO_PHY) {
  558. return EFI_SUCCESS;
  559. }
  560. // Request a PHY reset
  561. WritePhyReg16 (LanDriver, PHY_INDEX_BASIC_CTRL, PHYCR_RESET);
  562. // The internal PHY will reset within 50ms. Allow 100ms.
  563. Retries = 100000 / (PHY_READ_TIME + 100);
  564. while (ReadPhyReg16 (LanDriver, PHY_INDEX_BASIC_CTRL) & PHYCR_RESET) {
  565. if (--Retries == 0) {
  566. DEBUG ((DEBUG_ERROR, "LAN91x: PHY reset timed-out\n"));
  567. return EFI_TIMEOUT;
  568. }
  569. gBS->Stall (100);
  570. }
  571. return EFI_SUCCESS;
  572. }
  573. /* ---------------- General Operations ----------------- */
  574. STATIC
  575. EFI_MAC_ADDRESS
  576. GetCurrentMacAddress (
  577. IN LAN91X_DRIVER *LanDriver
  578. )
  579. {
  580. UINTN RegNum;
  581. UINT8 *Addr;
  582. EFI_MAC_ADDRESS MacAddress;
  583. SetMem (&MacAddress, sizeof(MacAddress), 0);
  584. Addr = &MacAddress.Addr[0];
  585. for (RegNum = LAN91X_IAR0; RegNum <= LAN91X_IAR5; ++RegNum) {
  586. *Addr = ReadIoReg8 (LanDriver, RegNum);
  587. ++Addr;
  588. }
  589. return MacAddress;
  590. }
  591. STATIC
  592. EFI_STATUS
  593. SetCurrentMacAddress (
  594. IN LAN91X_DRIVER *LanDriver,
  595. IN EFI_MAC_ADDRESS *MacAddress
  596. )
  597. {
  598. UINTN RegNum;
  599. UINT8 *Addr;
  600. Addr = &MacAddress->Addr[0];
  601. for (RegNum = LAN91X_IAR0; RegNum <= LAN91X_IAR5; ++RegNum) {
  602. WriteIoReg8 (LanDriver, RegNum, *Addr);
  603. ++Addr;
  604. }
  605. return EFI_SUCCESS;
  606. }
  607. STATIC
  608. EFI_STATUS
  609. MmuOperation (
  610. IN LAN91X_DRIVER *LanDriver,
  611. IN UINTN MmuOp
  612. )
  613. {
  614. UINTN Polls;
  615. WriteIoReg16 (LanDriver, LAN91X_MMUCR, MmuOp);
  616. Polls = 100;
  617. while ((ReadIoReg16 (LanDriver, LAN91X_MMUCR) & MMUCR_BUSY) != 0) {
  618. if (--Polls == 0) {
  619. DEBUG ((DEBUG_ERROR, "LAN91x: MMU operation %04x timed-out\n", MmuOp));
  620. return EFI_TIMEOUT;
  621. }
  622. gBS->Stall (LAN91X_STALL);
  623. }
  624. return EFI_SUCCESS;
  625. }
  626. // Read bytes from the DATA register
  627. STATIC
  628. EFI_STATUS
  629. ReadIoData (
  630. IN LAN91X_DRIVER *LanDriver,
  631. IN VOID *Buffer,
  632. IN UINTN BufLen
  633. )
  634. {
  635. UINT8 *Ptr;
  636. Ptr = Buffer;
  637. for (; BufLen > 0; --BufLen) {
  638. *Ptr = ReadIoReg8 (LanDriver, LAN91X_DATA0);
  639. ++Ptr;
  640. }
  641. return EFI_SUCCESS;
  642. }
  643. // Write bytes to the DATA register
  644. STATIC
  645. EFI_STATUS
  646. WriteIoData (
  647. IN LAN91X_DRIVER *LanDriver,
  648. IN VOID *Buffer,
  649. IN UINTN BufLen
  650. )
  651. {
  652. UINT8 *Ptr;
  653. Ptr = Buffer;
  654. for (; BufLen > 0; --BufLen) {
  655. WriteIoReg8 (LanDriver, LAN91X_DATA0, *Ptr);
  656. ++Ptr;
  657. }
  658. return EFI_SUCCESS;
  659. }
  660. // Disable the interface
  661. STATIC
  662. EFI_STATUS
  663. ChipDisable (
  664. IN LAN91X_DRIVER *LanDriver
  665. )
  666. {
  667. #ifdef LAN91X_POWER_DOWN
  668. UINT16 Val16;
  669. #endif
  670. // Stop Rx and Tx operations
  671. WriteIoReg16 (LanDriver, LAN91X_RCR, RCR_CLEAR);
  672. WriteIoReg16 (LanDriver, LAN91X_TCR, TCR_CLEAR);
  673. #ifdef LAN91X_POWER_DOWN
  674. // Power-down the chip
  675. Val16 = ReadIoReg16 (LanDriver, LAN91X_CR);
  676. Val16 &= ~CR_EPH_POWER_EN;
  677. WriteIoReg16 (LanDriver, LAN91X_CR, Val16);
  678. #endif
  679. return EFI_SUCCESS;
  680. }
  681. // Enable the interface
  682. STATIC
  683. EFI_STATUS
  684. ChipEnable (
  685. IN LAN91X_DRIVER *LanDriver
  686. )
  687. {
  688. #ifdef LAN91X_POWER_DOWN
  689. UINT16 Val16;
  690. // Power-up the chip
  691. Val16 = ReadIoReg16 (LanDriver, LAN91X_CR);
  692. Val16 |= CR_EPH_POWER_EN;
  693. WriteIoReg16 (LanDriver, LAN91X_CR, Val16);
  694. gBS->Stall (LAN91X_STALL);
  695. #endif
  696. // Start Rx and Tx operations
  697. WriteIoReg16 (LanDriver, LAN91X_TCR, TCR_DEFAULT);
  698. WriteIoReg16 (LanDriver, LAN91X_RCR, RCR_DEFAULT);
  699. return EFI_SUCCESS;
  700. }
  701. // Perform software reset on the LAN91x
  702. STATIC
  703. EFI_STATUS
  704. SoftReset (
  705. IN LAN91X_DRIVER *LanDriver
  706. )
  707. {
  708. UINT16 Val16;
  709. // Issue the reset
  710. WriteIoReg16 (LanDriver, LAN91X_RCR, RCR_SOFT_RST);
  711. gBS->Stall (LAN91X_STALL);
  712. WriteIoReg16 (LanDriver, LAN91X_RCR, RCR_CLEAR);
  713. // Set the configuration register
  714. WriteIoReg16 (LanDriver, LAN91X_CR, CR_DEFAULT);
  715. gBS->Stall (LAN91X_STALL);
  716. // Stop Rx and Tx
  717. WriteIoReg16 (LanDriver, LAN91X_RCR, RCR_CLEAR);
  718. WriteIoReg16 (LanDriver, LAN91X_TCR, TCR_CLEAR);
  719. // Initialize the Control Register
  720. Val16 = ReadIoReg16 (LanDriver, LAN91X_CTR);
  721. Val16 |= CTR_AUTO_REL;
  722. WriteIoReg16 (LanDriver, LAN91X_CTR, Val16);
  723. // Reset the MMU
  724. MmuOperation (LanDriver, MMUCR_OP_RESET_MMU);
  725. return EFI_SUCCESS;
  726. }
  727. /*
  728. ** Probe()
  729. **
  730. ** Validate that there is a LAN91x device.
  731. **
  732. */
  733. STATIC
  734. EFI_STATUS
  735. Probe (
  736. IN LAN91X_DRIVER *LanDriver
  737. )
  738. {
  739. UINT16 Bank;
  740. UINT16 Val16;
  741. CHAR16 CONST *ChipId;
  742. UINTN ResetTime;
  743. // First check that the Bank Select register is valid
  744. Bank = MmioRead16 (LanDriver->IoBase + LAN91X_BANK_OFFSET);
  745. if ((Bank & 0xff00) != 0x3300) {
  746. DEBUG ((DEBUG_ERROR, "LAN91x: signature error: expecting 33xx, read %04x\n", Bank));
  747. return EFI_DEVICE_ERROR;
  748. }
  749. // Try reading the revision register next
  750. LanDriver->BankSel = 0xff;
  751. Val16 = ReadIoReg16 (LanDriver, LAN91X_REV);
  752. Bank = MmioRead16 (LanDriver->IoBase + LAN91X_BANK_OFFSET);
  753. if ((Bank & 0xff03) != 0x3303) {
  754. DEBUG ((DEBUG_ERROR, "LAN91x: signature error: expecting 33x3, read %04x\n", Bank));
  755. return EFI_DEVICE_ERROR;
  756. }
  757. // Validate the revision register
  758. if ((Val16 & 0xff00) != 0x3300) {
  759. DEBUG ((DEBUG_ERROR, "LAN91x: revision error: expecting 33xx, read %04x\n", Val16));
  760. return EFI_DEVICE_ERROR;
  761. }
  762. ChipId = ChipIds[(Val16 >> 4) & 0x0f];
  763. if (ChipId == NULL) {
  764. DEBUG ((DEBUG_ERROR, "LAN91x: unrecognized revision: %04x\n", Val16));
  765. return EFI_DEVICE_ERROR;
  766. }
  767. DEBUG ((DEBUG_ERROR, "LAN91x: detected chip %s rev %d\n", ChipId, Val16 & 0xf));
  768. LanDriver->Revision = Val16 & 0xff;
  769. // Reload from EEPROM to get the hardware MAC address
  770. WriteIoReg16 (LanDriver, LAN91X_CTR, CTR_RESERVED | CTR_RELOAD);
  771. ResetTime = 1000;
  772. while ((ReadIoReg16 (LanDriver, LAN91X_CTR) & CTR_RELOAD) != 0) {
  773. if (--ResetTime == 0) {
  774. DEBUG ((DEBUG_ERROR, "LAN91x: reload from EEPROM timed-out\n"));
  775. WriteIoReg16 (LanDriver, LAN91X_CTR, CTR_RESERVED);
  776. return EFI_DEVICE_ERROR;
  777. }
  778. gBS->Stall (LAN91X_STALL);
  779. }
  780. // Read and save the Permanent MAC Address
  781. LanDriver->SnpMode.PermanentAddress = GetCurrentMacAddress (LanDriver);
  782. LanDriver->SnpMode.CurrentAddress = LanDriver->SnpMode.PermanentAddress;
  783. DEBUG ((DEBUG_ERROR, //DEBUG_NET | DEBUG_INFO,
  784. "LAN91x: HW MAC Address: %02x-%02x-%02x-%02x-%02x-%02x\n",
  785. LanDriver->SnpMode.PermanentAddress.Addr[0],
  786. LanDriver->SnpMode.PermanentAddress.Addr[1],
  787. LanDriver->SnpMode.PermanentAddress.Addr[2],
  788. LanDriver->SnpMode.PermanentAddress.Addr[3],
  789. LanDriver->SnpMode.PermanentAddress.Addr[4],
  790. LanDriver->SnpMode.PermanentAddress.Addr[5]
  791. ));
  792. // Reset the device
  793. SoftReset (LanDriver);
  794. // Try to detect a PHY
  795. if (LanDriver->Revision > (CHIP_91100 << 4)) {
  796. PhyDetect (LanDriver);
  797. } else {
  798. LanDriver->PhyAd = LAN91X_NO_PHY;
  799. }
  800. return EFI_SUCCESS;
  801. }
  802. /*------------------ Simple Network Driver entry point functions ------------------*/
  803. // Refer to the Simple Network Protocol section (21.1)
  804. // in the UEFI 2.3.1 Specification for documentation.
  805. #define ReturnUnlock(s) do { Status = (s); goto exit_unlock; } while(0)
  806. /*
  807. ** UEFI Start() function
  808. **
  809. */
  810. EFI_STATUS
  811. EFIAPI
  812. SnpStart (
  813. IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp
  814. )
  815. {
  816. EFI_SIMPLE_NETWORK_MODE *Mode;
  817. EFI_TPL SavedTpl;
  818. EFI_STATUS Status;
  819. // Check Snp instance
  820. if (Snp == NULL) {
  821. return EFI_INVALID_PARAMETER;
  822. }
  823. // Serialize access to data and registers
  824. SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
  825. Mode = Snp->Mode;
  826. // Check state of the driver
  827. switch (Mode->State) {
  828. case EfiSimpleNetworkStopped:
  829. break;
  830. case EfiSimpleNetworkStarted:
  831. case EfiSimpleNetworkInitialized:
  832. DEBUG ((DEBUG_WARN, "LAN91x: Driver already started\n"));
  833. ReturnUnlock (EFI_ALREADY_STARTED);
  834. default:
  835. DEBUG ((DEBUG_ERROR, "LAN91x: Driver in an invalid state: %u\n",
  836. (UINTN)Snp->Mode->State));
  837. ReturnUnlock (EFI_DEVICE_ERROR);
  838. }
  839. // Change state
  840. Mode->State = EfiSimpleNetworkStarted;
  841. Status = EFI_SUCCESS;
  842. // Restore TPL and return
  843. exit_unlock:
  844. gBS->RestoreTPL (SavedTpl);
  845. return Status;
  846. }
  847. /*
  848. ** UEFI Stop() function
  849. **
  850. */
  851. EFI_STATUS
  852. EFIAPI
  853. SnpStop (
  854. IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp
  855. )
  856. {
  857. LAN91X_DRIVER *LanDriver;
  858. EFI_TPL SavedTpl;
  859. EFI_STATUS Status;
  860. // Check Snp Instance
  861. if (Snp == NULL) {
  862. return EFI_INVALID_PARAMETER;
  863. }
  864. // Serialize access to data and registers
  865. SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
  866. // Check state of the driver
  867. switch (Snp->Mode->State) {
  868. case EfiSimpleNetworkStarted:
  869. case EfiSimpleNetworkInitialized:
  870. break;
  871. case EfiSimpleNetworkStopped:
  872. DEBUG ((DEBUG_WARN, "LAN91x: Driver not started\n"));
  873. ReturnUnlock (EFI_NOT_STARTED);
  874. default:
  875. DEBUG ((DEBUG_ERROR, "LAN91x: Driver in an invalid state: %u\n",
  876. (UINTN)Snp->Mode->State));
  877. ReturnUnlock (EFI_DEVICE_ERROR);
  878. }
  879. // Find the LanDriver structure
  880. LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
  881. // Stop the Tx and Rx
  882. ChipDisable (LanDriver);
  883. // Change the state
  884. Snp->Mode->State = EfiSimpleNetworkStopped;
  885. Status = EFI_SUCCESS;
  886. // Restore TPL and return
  887. exit_unlock:
  888. gBS->RestoreTPL (SavedTpl);
  889. return Status;
  890. }
  891. /*
  892. ** UEFI Initialize() function
  893. **
  894. */
  895. EFI_STATUS
  896. EFIAPI
  897. SnpInitialize (
  898. IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp,
  899. IN UINTN RxBufferSize OPTIONAL,
  900. IN UINTN TxBufferSize OPTIONAL
  901. )
  902. {
  903. LAN91X_DRIVER *LanDriver;
  904. EFI_TPL SavedTpl;
  905. EFI_STATUS Status;
  906. // Check Snp Instance
  907. if (Snp == NULL) {
  908. return EFI_INVALID_PARAMETER;
  909. }
  910. // Serialize access to data and registers
  911. SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
  912. // Check that driver was started but not initialised
  913. switch (Snp->Mode->State) {
  914. case EfiSimpleNetworkStarted:
  915. break;
  916. case EfiSimpleNetworkInitialized:
  917. DEBUG ((DEBUG_WARN, "LAN91x: Driver already initialized\n"));
  918. ReturnUnlock (EFI_SUCCESS);
  919. case EfiSimpleNetworkStopped:
  920. DEBUG ((DEBUG_WARN, "LAN91x: Driver not started\n"));
  921. ReturnUnlock (EFI_NOT_STARTED);
  922. default:
  923. DEBUG ((DEBUG_ERROR, "LAN91x: Driver in an invalid state: %u\n",
  924. (UINTN)Snp->Mode->State));
  925. ReturnUnlock (EFI_DEVICE_ERROR);
  926. }
  927. // Find the LanDriver structure
  928. LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
  929. // Initiate a software reset
  930. Status = SoftReset (LanDriver);
  931. if (EFI_ERROR(Status)) {
  932. DEBUG ((DEBUG_WARN, "LAN91x: Soft reset failed\n"));
  933. ReturnUnlock (EFI_DEVICE_ERROR);
  934. }
  935. // Initiate a PHY reset
  936. if (PhySoftReset (LanDriver) < 0) {
  937. Snp->Mode->State = EfiSimpleNetworkStopped;
  938. DEBUG ((DEBUG_WARN, "LAN91x: PHY soft reset timeout\n"));
  939. ReturnUnlock (EFI_NOT_STARTED);
  940. }
  941. // Do auto-negotiation
  942. Status = PhyAutoNegotiate (LanDriver);
  943. if (EFI_ERROR(Status)) {
  944. DEBUG ((DEBUG_WARN, "LAN91x: PHY auto-negotiation failed\n"));
  945. }
  946. // Enable the receiver and transmitter
  947. ChipEnable (LanDriver);
  948. // Now acknowledge all interrupts
  949. WriteIoReg8 (LanDriver, LAN91X_IST, 0xFF);
  950. // Declare the driver as initialized
  951. Snp->Mode->State = EfiSimpleNetworkInitialized;
  952. Status = EFI_SUCCESS;
  953. // Restore TPL and return
  954. exit_unlock:
  955. gBS->RestoreTPL (SavedTpl);
  956. return Status;
  957. }
  958. /*
  959. ** UEFI Reset () function
  960. **
  961. */
  962. EFI_STATUS
  963. EFIAPI
  964. SnpReset (
  965. IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp,
  966. IN BOOLEAN Verification
  967. )
  968. {
  969. LAN91X_DRIVER *LanDriver;
  970. EFI_TPL SavedTpl;
  971. EFI_STATUS Status;
  972. // Check Snp Instance
  973. if (Snp == NULL) {
  974. return EFI_INVALID_PARAMETER;
  975. }
  976. // Serialize access to data and registers
  977. SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
  978. // Check that driver was started and initialised
  979. switch (Snp->Mode->State) {
  980. case EfiSimpleNetworkInitialized:
  981. break;
  982. case EfiSimpleNetworkStarted:
  983. DEBUG ((DEBUG_WARN, "LAN91x: Driver not yet initialized\n"));
  984. ReturnUnlock (EFI_DEVICE_ERROR);
  985. case EfiSimpleNetworkStopped:
  986. DEBUG ((DEBUG_WARN, "LAN91x: Driver not started\n"));
  987. ReturnUnlock (EFI_NOT_STARTED);
  988. default:
  989. DEBUG ((DEBUG_ERROR, "LAN91x: Driver in an invalid state: %u\n",
  990. (UINTN)Snp->Mode->State));
  991. ReturnUnlock (EFI_DEVICE_ERROR);
  992. }
  993. // Find the LanDriver structure
  994. LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
  995. // Initiate a software reset
  996. if (EFI_ERROR (SoftReset (LanDriver))) {
  997. DEBUG ((DEBUG_WARN, "LAN91x: Soft reset failed\n"));
  998. ReturnUnlock (EFI_DEVICE_ERROR);
  999. }
  1000. // Initiate a PHY reset
  1001. if (EFI_ERROR (PhySoftReset (LanDriver))) {
  1002. DEBUG ((DEBUG_WARN, "LAN91x: PHY soft reset failed\n"));
  1003. ReturnUnlock (EFI_DEVICE_ERROR);
  1004. }
  1005. // Enable the receiver and transmitter
  1006. Status = ChipEnable (LanDriver);
  1007. // Restore TPL and return
  1008. exit_unlock:
  1009. gBS->RestoreTPL (SavedTpl);
  1010. return Status;
  1011. }
  1012. /*
  1013. ** UEFI Shutdown () function
  1014. **
  1015. */
  1016. EFI_STATUS
  1017. EFIAPI
  1018. SnpShutdown (
  1019. IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp
  1020. )
  1021. {
  1022. LAN91X_DRIVER *LanDriver;
  1023. EFI_TPL SavedTpl;
  1024. EFI_STATUS Status;
  1025. // Check Snp Instance
  1026. if (Snp == NULL) {
  1027. return EFI_INVALID_PARAMETER;
  1028. }
  1029. // Serialize access to data and registers
  1030. SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
  1031. // First check that driver has already been initialized
  1032. switch (Snp->Mode->State) {
  1033. case EfiSimpleNetworkInitialized:
  1034. break;
  1035. case EfiSimpleNetworkStarted:
  1036. DEBUG ((DEBUG_WARN, "LAN91x: Driver not yet initialized\n"));
  1037. ReturnUnlock (EFI_DEVICE_ERROR);
  1038. case EfiSimpleNetworkStopped:
  1039. DEBUG ((DEBUG_WARN, "LAN91x: Driver in stopped state\n"));
  1040. ReturnUnlock (EFI_NOT_STARTED);
  1041. default:
  1042. DEBUG ((DEBUG_ERROR, "LAN91x: Driver in an invalid state: %u\n",
  1043. (UINTN)Snp->Mode->State));
  1044. ReturnUnlock (EFI_DEVICE_ERROR);
  1045. }
  1046. // Find the LanDriver structure
  1047. LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
  1048. // Disable the interface
  1049. Status = ChipDisable (LanDriver);
  1050. // Restore TPL and return
  1051. exit_unlock:
  1052. gBS->RestoreTPL (SavedTpl);
  1053. return Status;
  1054. }
  1055. /*
  1056. ** UEFI ReceiveFilters() function
  1057. **
  1058. */
  1059. EFI_STATUS
  1060. EFIAPI
  1061. SnpReceiveFilters (
  1062. IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp,
  1063. IN UINT32 Enable,
  1064. IN UINT32 Disable,
  1065. IN BOOLEAN Reset,
  1066. IN UINTN NumMfilter OPTIONAL,
  1067. IN EFI_MAC_ADDRESS *Mfilter OPTIONAL
  1068. )
  1069. {
  1070. #define MCAST_HASH_BYTES 8
  1071. LAN91X_DRIVER *LanDriver;
  1072. EFI_SIMPLE_NETWORK_MODE *SnpMode;
  1073. EFI_TPL SavedTpl;
  1074. EFI_STATUS Status;
  1075. UINTN i;
  1076. UINT32 Crc;
  1077. UINT16 RcvCtrl;
  1078. UINT8 McastHash[MCAST_HASH_BYTES];
  1079. // Check Snp Instance
  1080. if (Snp == NULL) {
  1081. return EFI_INVALID_PARAMETER;
  1082. }
  1083. // Serialize access to data and registers
  1084. SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
  1085. // First check that driver has already been initialized
  1086. switch (Snp->Mode->State) {
  1087. case EfiSimpleNetworkInitialized:
  1088. break;
  1089. case EfiSimpleNetworkStarted:
  1090. DEBUG ((DEBUG_WARN, "LAN91x: Driver not yet initialized\n"));
  1091. ReturnUnlock (EFI_DEVICE_ERROR);
  1092. case EfiSimpleNetworkStopped:
  1093. DEBUG ((DEBUG_WARN, "LAN91x: Driver not started\n"));
  1094. ReturnUnlock (EFI_NOT_STARTED);
  1095. default:
  1096. DEBUG ((DEBUG_ERROR, "LAN91x: Driver in an invalid state: %u\n",
  1097. (UINTN)Snp->Mode->State));
  1098. ReturnUnlock (EFI_DEVICE_ERROR);
  1099. }
  1100. // Find the LanDriver structure
  1101. LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
  1102. SnpMode = Snp->Mode;
  1103. #ifdef LAN91X_PRINT_RECEIVE_FILTERS
  1104. DEBUG ((DEBUG_ERROR, "LAN91x:SnpReceiveFilters()\n"));
  1105. DEBUG ((DEBUG_ERROR, " Enable = %08x\n", Enable));
  1106. DEBUG ((DEBUG_ERROR, " Disable = %08x\n", Disable));
  1107. DEBUG ((DEBUG_ERROR, " Reset = %d\n", Reset));
  1108. DEBUG ((DEBUG_ERROR, " NumMfilter = %d\n", NumMfilter));
  1109. for (i = 0; i < NumMfilter; ++i) {
  1110. DEBUG ((DEBUG_ERROR,
  1111. " [%2d] = %02x-%02x-%02x-%02x-%02x-%02x\n",
  1112. i,
  1113. Mfilter[i].Addr[0],
  1114. Mfilter[i].Addr[1],
  1115. Mfilter[i].Addr[2],
  1116. Mfilter[i].Addr[3],
  1117. Mfilter[i].Addr[4],
  1118. Mfilter[i].Addr[5]));
  1119. }
  1120. #endif
  1121. // Update the Multicast Hash registers
  1122. if (Reset) {
  1123. // Clear the hash table
  1124. SetMem (McastHash, MCAST_HASH_BYTES, 0);
  1125. SnpMode->MCastFilterCount = 0;
  1126. } else {
  1127. // Read the current hash table
  1128. for (i = 0; i < MCAST_HASH_BYTES; ++i) {
  1129. McastHash[i] = ReadIoReg8 (LanDriver, LAN91X_MT0 + i);
  1130. }
  1131. // Set the new additions
  1132. for (i = 0; i < NumMfilter; ++i) {
  1133. Crc = MulticastHash (&Mfilter[i], NET_ETHER_ADDR_LEN);
  1134. McastHash[(Crc >> 29) & 0x3] |= 1 << ((Crc >> 26) & 0x3);
  1135. }
  1136. SnpMode->MCastFilterCount = NumMfilter;
  1137. }
  1138. // If the hash registers need updating, write them
  1139. if (Reset || NumMfilter > 0) {
  1140. for (i = 0; i < MCAST_HASH_BYTES; ++i) {
  1141. WriteIoReg8 (LanDriver, LAN91X_MT0 + i, McastHash[i]);
  1142. }
  1143. }
  1144. RcvCtrl = ReadIoReg16 (LanDriver, LAN91X_RCR);
  1145. if ((Enable & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
  1146. RcvCtrl |= RCR_PRMS;
  1147. SnpMode->ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
  1148. }
  1149. if ((Disable & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
  1150. RcvCtrl &= ~RCR_PRMS;
  1151. SnpMode->ReceiveFilterSetting &= ~EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
  1152. }
  1153. if ((Enable & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
  1154. RcvCtrl |= RCR_ALMUL;
  1155. SnpMode->ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
  1156. }
  1157. if ((Disable & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
  1158. RcvCtrl &= ~RCR_ALMUL;
  1159. SnpMode->ReceiveFilterSetting &= ~EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
  1160. }
  1161. WriteIoReg16 (LanDriver, LAN91X_RCR, RcvCtrl);
  1162. Status = SetCurrentMacAddress (LanDriver, &SnpMode->CurrentAddress);
  1163. // Restore TPL and return
  1164. exit_unlock:
  1165. gBS->RestoreTPL (SavedTpl);
  1166. return Status;
  1167. }
  1168. /*
  1169. ** UEFI StationAddress() function
  1170. **
  1171. */
  1172. EFI_STATUS
  1173. EFIAPI
  1174. SnpStationAddress (
  1175. IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
  1176. IN BOOLEAN Reset,
  1177. IN EFI_MAC_ADDRESS *NewMac
  1178. )
  1179. {
  1180. LAN91X_DRIVER *LanDriver;
  1181. EFI_TPL SavedTpl;
  1182. EFI_STATUS Status;
  1183. // Check Snp instance
  1184. if (Snp == NULL) {
  1185. return EFI_INVALID_PARAMETER;
  1186. }
  1187. // Serialize access to data and registers
  1188. SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
  1189. // Check that driver was started and initialised
  1190. switch (Snp->Mode->State) {
  1191. case EfiSimpleNetworkInitialized:
  1192. break;
  1193. case EfiSimpleNetworkStarted:
  1194. DEBUG ((DEBUG_WARN, "LAN91x: Driver not yet initialized\n"));
  1195. ReturnUnlock (EFI_DEVICE_ERROR);
  1196. case EfiSimpleNetworkStopped:
  1197. DEBUG ((DEBUG_WARN, "LAN91x: Driver not started\n"));
  1198. ReturnUnlock (EFI_NOT_STARTED);
  1199. default:
  1200. DEBUG ((DEBUG_ERROR, "LAN91x: Driver in an invalid state: %u\n",
  1201. (UINTN)Snp->Mode->State));
  1202. ReturnUnlock (EFI_DEVICE_ERROR);
  1203. }
  1204. // Find the LanDriver structure
  1205. LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
  1206. if (Reset) {
  1207. Snp->Mode->CurrentAddress = Snp->Mode->PermanentAddress;
  1208. } else {
  1209. if (NewMac == NULL) {
  1210. ReturnUnlock (EFI_INVALID_PARAMETER);
  1211. }
  1212. Snp->Mode->CurrentAddress = *NewMac;
  1213. }
  1214. Status = SetCurrentMacAddress (LanDriver, &Snp->Mode->CurrentAddress);
  1215. // Restore TPL and return
  1216. exit_unlock:
  1217. gBS->RestoreTPL (SavedTpl);
  1218. return Status;
  1219. }
  1220. /*
  1221. ** UEFI Statistics() function
  1222. **
  1223. */
  1224. EFI_STATUS
  1225. EFIAPI
  1226. SnpStatistics (
  1227. IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp,
  1228. IN BOOLEAN Reset,
  1229. IN OUT UINTN *StatSize,
  1230. OUT EFI_NETWORK_STATISTICS *Statistics
  1231. )
  1232. {
  1233. LAN91X_DRIVER *LanDriver;
  1234. EFI_TPL SavedTpl;
  1235. EFI_STATUS Status;
  1236. // Check Snp instance
  1237. if (Snp == NULL) {
  1238. return EFI_INVALID_PARAMETER;
  1239. }
  1240. // Check pointless condition
  1241. if ((!Reset) && (StatSize == NULL) && (Statistics == NULL)) {
  1242. return EFI_SUCCESS;
  1243. }
  1244. // Check the parameters
  1245. if ((StatSize == NULL) && (Statistics != NULL)) {
  1246. return EFI_INVALID_PARAMETER;
  1247. }
  1248. // Serialize access to data and registers
  1249. SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
  1250. // Check that driver was started and initialised
  1251. switch (Snp->Mode->State) {
  1252. case EfiSimpleNetworkInitialized:
  1253. break;
  1254. case EfiSimpleNetworkStarted:
  1255. DEBUG ((DEBUG_WARN, "LAN91x: Driver not yet initialized\n"));
  1256. ReturnUnlock (EFI_DEVICE_ERROR);
  1257. case EfiSimpleNetworkStopped:
  1258. DEBUG ((DEBUG_WARN, "LAN91x: Driver not started\n"));
  1259. ReturnUnlock (EFI_NOT_STARTED);
  1260. default:
  1261. DEBUG ((DEBUG_ERROR, "LAN91x: Driver in an invalid state: %u\n",
  1262. (UINTN)Snp->Mode->State));
  1263. ReturnUnlock (EFI_DEVICE_ERROR);
  1264. }
  1265. // Find the LanDriver structure
  1266. LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
  1267. // Do a reset if required
  1268. if (Reset) {
  1269. ZeroMem (&LanDriver->Stats, sizeof(EFI_NETWORK_STATISTICS));
  1270. }
  1271. // Check buffer size
  1272. if (*StatSize < sizeof(EFI_NETWORK_STATISTICS)) {
  1273. *StatSize = sizeof(EFI_NETWORK_STATISTICS);
  1274. ReturnUnlock (EFI_BUFFER_TOO_SMALL);
  1275. goto exit_unlock;
  1276. }
  1277. // Fill in the statistics
  1278. CopyMem(&Statistics, &LanDriver->Stats, sizeof(EFI_NETWORK_STATISTICS));
  1279. Status = EFI_SUCCESS;
  1280. // Restore TPL and return
  1281. exit_unlock:
  1282. gBS->RestoreTPL (SavedTpl);
  1283. return Status;
  1284. }
  1285. /*
  1286. ** UEFI MCastIPtoMAC() function
  1287. **
  1288. */
  1289. EFI_STATUS
  1290. EFIAPI
  1291. SnpMcastIptoMac (
  1292. IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp,
  1293. IN BOOLEAN IsIpv6,
  1294. IN EFI_IP_ADDRESS *Ip,
  1295. OUT EFI_MAC_ADDRESS *McastMac
  1296. )
  1297. {
  1298. // Check Snp instance
  1299. if (Snp == NULL) {
  1300. return EFI_INVALID_PARAMETER;
  1301. }
  1302. // Check parameters
  1303. if ((McastMac == NULL) || (Ip == NULL)) {
  1304. return EFI_INVALID_PARAMETER;
  1305. }
  1306. // Make sure MAC address is empty
  1307. ZeroMem (McastMac, sizeof(EFI_MAC_ADDRESS));
  1308. // If we need ipv4 address
  1309. if (!IsIpv6) {
  1310. // Most significant 25 bits of a multicast HW address are set
  1311. McastMac->Addr[0] = 0x01;
  1312. McastMac->Addr[1] = 0x00;
  1313. McastMac->Addr[2] = 0x5E;
  1314. // Lower 23 bits from ipv4 address
  1315. McastMac->Addr[3] = (Ip->v4.Addr[1] & 0x7F); // Clear the ms bit (25th bit of MAC must be 0)
  1316. McastMac->Addr[4] = Ip->v4.Addr[2];
  1317. McastMac->Addr[5] = Ip->v4.Addr[3];
  1318. } else {
  1319. // Most significant 16 bits of multicast v6 HW address are set
  1320. McastMac->Addr[0] = 0x33;
  1321. McastMac->Addr[1] = 0x33;
  1322. // lower four octets are taken from ipv6 address
  1323. McastMac->Addr[2] = Ip->v6.Addr[8];
  1324. McastMac->Addr[3] = Ip->v6.Addr[9];
  1325. McastMac->Addr[4] = Ip->v6.Addr[10];
  1326. McastMac->Addr[5] = Ip->v6.Addr[11];
  1327. }
  1328. return EFI_SUCCESS;
  1329. }
  1330. /*
  1331. ** UEFI NvData() function
  1332. **
  1333. */
  1334. EFI_STATUS
  1335. EFIAPI
  1336. SnpNvData (
  1337. IN EFI_SIMPLE_NETWORK_PROTOCOL* pobj,
  1338. IN BOOLEAN read_write,
  1339. IN UINTN offset,
  1340. IN UINTN buff_size,
  1341. IN OUT VOID *data
  1342. )
  1343. {
  1344. DEBUG ((DEBUG_ERROR, "LAN91x: Non-volatile storage not supported\n"));
  1345. return EFI_UNSUPPORTED;
  1346. }
  1347. /*
  1348. ** UEFI GetStatus () function
  1349. **
  1350. */
  1351. EFI_STATUS
  1352. EFIAPI
  1353. SnpGetStatus (
  1354. IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
  1355. OUT UINT32 *IrqStat OPTIONAL,
  1356. OUT VOID **TxBuff OPTIONAL
  1357. )
  1358. {
  1359. LAN91X_DRIVER *LanDriver;
  1360. EFI_TPL SavedTpl;
  1361. EFI_STATUS Status;
  1362. BOOLEAN MediaPresent;
  1363. UINT8 IstReg;
  1364. MSK_LINKED_SYSTEM_BUF *LinkedTXRecycleBuff;
  1365. // Check preliminaries
  1366. if (Snp == NULL) {
  1367. return EFI_INVALID_PARAMETER;
  1368. }
  1369. // Serialize access to data and registers
  1370. SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
  1371. // Check that driver was started and initialised
  1372. switch (Snp->Mode->State) {
  1373. case EfiSimpleNetworkInitialized:
  1374. break;
  1375. case EfiSimpleNetworkStarted:
  1376. DEBUG ((DEBUG_WARN, "LAN91x: Driver not yet initialized\n"));
  1377. ReturnUnlock (EFI_DEVICE_ERROR);
  1378. case EfiSimpleNetworkStopped:
  1379. DEBUG ((DEBUG_WARN, "LAN91x: Driver not started\n"));
  1380. ReturnUnlock (EFI_NOT_STARTED);
  1381. default:
  1382. DEBUG ((DEBUG_ERROR, "LAN91x: Driver in an invalid state: %u\n",
  1383. (UINTN)Snp->Mode->State));
  1384. ReturnUnlock (EFI_DEVICE_ERROR);
  1385. }
  1386. // Find the LanDriver structure
  1387. LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
  1388. // Arbitrarily set the interrupt status to 0
  1389. if (IrqStat != NULL) {
  1390. *IrqStat = 0;
  1391. IstReg = ReadIoReg8 (LanDriver, LAN91X_IST);
  1392. if ((IstReg & IST_RCV) != 0) {
  1393. *IrqStat |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
  1394. }
  1395. if ((IstReg & IST_TX) != 0) {
  1396. *IrqStat |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
  1397. }
  1398. }
  1399. // Pass back the completed buffer address
  1400. // The transmit buffer status is not read when TxBuf is NULL
  1401. if (TxBuff != NULL) {
  1402. *((UINT8 **) TxBuff) = (UINT8 *) 0;
  1403. if( !IsListEmpty (&LanDriver->TransmitQueueHead))
  1404. {
  1405. LinkedTXRecycleBuff = CR (GetFirstNode (&LanDriver->TransmitQueueHead), MSK_LINKED_SYSTEM_BUF, Link, TX_MBUF_SIGNATURE);
  1406. if(LinkedTXRecycleBuff != NULL) {
  1407. *TxBuff = LinkedTXRecycleBuff->SystemBuf.Buf;
  1408. RemoveEntryList (&LinkedTXRecycleBuff->Link);
  1409. FreePool (LinkedTXRecycleBuff);
  1410. }
  1411. }
  1412. }
  1413. // Update the media status
  1414. MediaPresent = CheckLinkStatus (LanDriver);
  1415. if (MediaPresent != Snp->Mode->MediaPresent) {
  1416. DEBUG ((DEBUG_WARN, "LAN91x: Link %s\n", MediaPresent ? L"up" : L"down"));
  1417. }
  1418. Snp->Mode->MediaPresent = MediaPresent;
  1419. Status = EFI_SUCCESS;
  1420. // Restore TPL and return
  1421. exit_unlock:
  1422. gBS->RestoreTPL (SavedTpl);
  1423. return Status;
  1424. }
  1425. /*
  1426. ** UEFI Transmit() function
  1427. **
  1428. */
  1429. EFI_STATUS
  1430. EFIAPI
  1431. SnpTransmit (
  1432. IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
  1433. IN UINTN HdrSize,
  1434. IN UINTN BufSize,
  1435. IN VOID *BufAddr,
  1436. IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL,
  1437. IN EFI_MAC_ADDRESS *DstAddr OPTIONAL,
  1438. IN UINT16 *Protocol OPTIONAL
  1439. )
  1440. {
  1441. LAN91X_DRIVER *LanDriver;
  1442. EFI_TPL SavedTpl;
  1443. EFI_STATUS Status;
  1444. UINT8 *Ptr;
  1445. UINTN Len;
  1446. UINTN MmuPages;
  1447. UINTN Retries;
  1448. UINT16 Proto;
  1449. UINT8 PktNum;
  1450. MSK_LINKED_SYSTEM_BUF *LinkedTXRecycleBuff;
  1451. // Check preliminaries
  1452. if ((Snp == NULL) || (BufAddr == NULL)) {
  1453. DEBUG ((DEBUG_ERROR, "LAN91x: SnpTransmit(): NULL Snp (%p) or BufAddr (%p)\n",
  1454. Snp, BufAddr));
  1455. return EFI_INVALID_PARAMETER;
  1456. }
  1457. // Serialize access to data and registers
  1458. SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
  1459. // Check that driver was started and initialised
  1460. switch (Snp->Mode->State) {
  1461. case EfiSimpleNetworkInitialized:
  1462. break;
  1463. case EfiSimpleNetworkStarted:
  1464. DEBUG ((DEBUG_WARN, "LAN91x: Driver not yet initialized\n"));
  1465. ReturnUnlock (EFI_DEVICE_ERROR);
  1466. case EfiSimpleNetworkStopped:
  1467. DEBUG ((DEBUG_WARN, "LAN91x: Driver not started\n"));
  1468. ReturnUnlock (EFI_NOT_STARTED);
  1469. default:
  1470. DEBUG ((DEBUG_ERROR, "LAN91x: Driver in an invalid state: %u\n",
  1471. (UINTN)Snp->Mode->State));
  1472. ReturnUnlock (EFI_DEVICE_ERROR);
  1473. }
  1474. // Find the LanDriver structure
  1475. LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
  1476. // Ensure header is correct size if non-zero
  1477. if (HdrSize != 0) {
  1478. if (HdrSize != Snp->Mode->MediaHeaderSize) {
  1479. DEBUG ((DEBUG_ERROR, "LAN91x: SnpTransmit(): Invalid HdrSize %d\n", HdrSize));
  1480. ReturnUnlock (EFI_INVALID_PARAMETER);
  1481. }
  1482. if ((DstAddr == NULL) || (Protocol == NULL)) {
  1483. DEBUG ((DEBUG_ERROR, "LAN91x: SnpTransmit(): NULL DstAddr %p or Protocol %p\n",
  1484. DstAddr, Protocol));
  1485. ReturnUnlock (EFI_INVALID_PARAMETER);
  1486. }
  1487. }
  1488. // Before transmitting check the link status
  1489. if (!Snp->Mode->MediaPresent) {
  1490. DEBUG ((DEBUG_WARN, "LAN91x: SnpTransmit(): Link not ready\n"));
  1491. ReturnUnlock (EFI_NOT_READY);
  1492. }
  1493. // Calculate the request size in 256-byte "pages" minus 1
  1494. // The 91C111 ignores this, but some older devices need it.
  1495. MmuPages = ((BufSize & ~1) + LAN91X_PKT_OVERHEAD - 1) >> 8;
  1496. if (MmuPages > 7) {
  1497. DEBUG ((DEBUG_WARN, "LAN91x: Tx buffer too large (%d bytes)\n", BufSize));
  1498. LanDriver->Stats.TxOversizeFrames += 1;
  1499. LanDriver->Stats.TxDroppedFrames += 1;
  1500. ReturnUnlock (EFI_BAD_BUFFER_SIZE);
  1501. }
  1502. // Request allocation of a transmit buffer
  1503. Status = MmuOperation (LanDriver, MMUCR_OP_TX_ALLOC | MmuPages);
  1504. if (EFI_ERROR (Status)) {
  1505. DEBUG ((DEBUG_ERROR, "LAN91x: Tx buffer request failure: %d\n", Status));
  1506. ReturnUnlock (EFI_DEVICE_ERROR);
  1507. }
  1508. // Wait for allocation request completion
  1509. Retries = LAN91X_MEMORY_ALLOC_POLLS;
  1510. while ((ReadIoReg8 (LanDriver, LAN91X_IST) & IST_ALLOC) == 0) {
  1511. if (--Retries == 0) {
  1512. DEBUG ((DEBUG_ERROR, "LAN91x: Tx buffer allocation timeout\n"));
  1513. ReturnUnlock (EFI_TIMEOUT);
  1514. }
  1515. }
  1516. // Check for successful allocation
  1517. PktNum = ReadIoReg8 (LanDriver, LAN91X_ARR);
  1518. if ((PktNum & ARR_FAILED) != 0) {
  1519. DEBUG ((DEBUG_ERROR, "LAN91x: Tx buffer allocation failure: %02x\n", PktNum));
  1520. ReturnUnlock (EFI_NOT_READY);
  1521. }
  1522. PktNum &= ARR_PACKET;
  1523. // Check for the nature of the frame
  1524. // If no destination address, it's ARP broadcast
  1525. if(DstAddr != NULL)
  1526. {
  1527. if (DstAddr->Addr[0] == 0xFF) {
  1528. LanDriver->Stats.TxBroadcastFrames += 1;
  1529. } else if ((DstAddr->Addr[0] & 0x1) == 1) {
  1530. LanDriver->Stats.TxMulticastFrames += 1;
  1531. } else {
  1532. LanDriver->Stats.TxUnicastFrames += 1;
  1533. }
  1534. } else {
  1535. LanDriver->Stats.TxBroadcastFrames += 1;
  1536. }
  1537. // Set the Packet Number and Pointer registers
  1538. WriteIoReg8 (LanDriver, LAN91X_PNR, PktNum);
  1539. WriteIoReg16 (LanDriver, LAN91X_PTR, PTR_AUTO_INCR);
  1540. // Set up mutable buffer information variables
  1541. Ptr = BufAddr;
  1542. Len = BufSize;
  1543. // Write Status and Byte Count first
  1544. WriteIoReg16 (LanDriver, LAN91X_DATA0, 0);
  1545. WriteIoReg16 (LanDriver, LAN91X_DATA0, (Len + LAN91X_PKT_OVERHEAD) & BCW_COUNT);
  1546. // This packet may come with a preconfigured Ethernet header.
  1547. // If not, we need to construct one from optional parameters.
  1548. if (HdrSize) {
  1549. // Write the destination address
  1550. WriteIoData (LanDriver, DstAddr, NET_ETHER_ADDR_LEN);
  1551. // Write the Source Address
  1552. if (SrcAddr != NULL) {
  1553. WriteIoData (LanDriver, SrcAddr, NET_ETHER_ADDR_LEN);
  1554. } else {
  1555. WriteIoData (LanDriver, &LanDriver->SnpMode.CurrentAddress, NET_ETHER_ADDR_LEN);
  1556. }
  1557. // Write the Protocol word
  1558. Proto = HTONS (*Protocol);
  1559. WriteIoReg16 (LanDriver, LAN91X_DATA0, Proto);
  1560. // Adjust the data start and length
  1561. Ptr += sizeof(ETHER_HEAD);
  1562. Len -= sizeof(ETHER_HEAD);
  1563. }
  1564. // Copy the remainder data buffer, except the odd byte
  1565. WriteIoData (LanDriver, Ptr, Len & ~1);
  1566. Ptr += Len & ~1;
  1567. Len &= 1;
  1568. // Write the Packet Control Word and odd byte
  1569. WriteIoReg16 (LanDriver, LAN91X_DATA0,
  1570. (Len != 0) ? (PCW_ODD | PCW_CRC | *Ptr) : PCW_CRC);
  1571. // Release the packet for transmission
  1572. Status = MmuOperation (LanDriver, MMUCR_OP_TX_PUSH);
  1573. if (EFI_ERROR (Status)) {
  1574. DEBUG ((DEBUG_ERROR, "LAN91x: Tx buffer release failure: %d\n", Status));
  1575. ReturnUnlock (EFI_DEVICE_ERROR);
  1576. }
  1577. // Update the Tx statistics
  1578. LanDriver->Stats.TxTotalBytes += BufSize;
  1579. LanDriver->Stats.TxGoodFrames += 1;
  1580. // Update the Tx Buffer cache
  1581. LinkedTXRecycleBuff = AllocateZeroPool (sizeof (MSK_LINKED_SYSTEM_BUF));
  1582. if (LinkedTXRecycleBuff == NULL) {
  1583. return EFI_OUT_OF_RESOURCES;
  1584. }
  1585. LinkedTXRecycleBuff->Signature = TX_MBUF_SIGNATURE;
  1586. //
  1587. // Add the passed Buffer to the transmit queue. Don't copy.
  1588. //
  1589. LinkedTXRecycleBuff->SystemBuf.Buf = BufAddr;
  1590. LinkedTXRecycleBuff->SystemBuf.Length = BufSize;
  1591. InsertTailList (&LanDriver->TransmitQueueHead, &LinkedTXRecycleBuff->Link);
  1592. Status = EFI_SUCCESS;
  1593. // Dump the packet header
  1594. #if LAN91X_PRINT_PACKET_HEADERS
  1595. Ptr = BufAddr;
  1596. DEBUG ((DEBUG_ERROR, "LAN91X:SnpTransmit()\n"));
  1597. DEBUG ((DEBUG_ERROR, " HdrSize: %d, SrcAddr: %p, Length: %d, Last byte: %02x\n",
  1598. HdrSize, SrcAddr, BufSize, Ptr[BufSize - 1]));
  1599. PrintIpDgram (
  1600. (HdrSize == 0) ? (EFI_MAC_ADDRESS *)&Ptr[0] : DstAddr,
  1601. (HdrSize == 0) ? (EFI_MAC_ADDRESS *)&Ptr[6] : (SrcAddr != NULL) ? SrcAddr : &LanDriver->SnpMode.CurrentAddress,
  1602. (HdrSize == 0) ? (UINT16 *)&Ptr[12] : &Proto,
  1603. &Ptr[14]
  1604. );
  1605. #endif
  1606. // Restore TPL and return
  1607. exit_unlock:
  1608. gBS->RestoreTPL (SavedTpl);
  1609. return Status;
  1610. }
  1611. /*
  1612. ** UEFI Receive() function
  1613. **
  1614. */
  1615. EFI_STATUS
  1616. EFIAPI
  1617. SnpReceive (
  1618. IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
  1619. OUT UINTN *HdrSize OPTIONAL,
  1620. IN OUT UINTN *BuffSize,
  1621. OUT VOID *Data,
  1622. OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL,
  1623. OUT EFI_MAC_ADDRESS *DstAddr OPTIONAL,
  1624. OUT UINT16 *Protocol OPTIONAL
  1625. )
  1626. {
  1627. EFI_TPL SavedTpl;
  1628. EFI_STATUS Status;
  1629. LAN91X_DRIVER *LanDriver;
  1630. UINT8 *DataPtr;
  1631. UINT16 PktStatus;
  1632. UINT16 PktLength;
  1633. UINT16 PktControl;
  1634. UINT8 IstReg;
  1635. // Check preliminaries
  1636. if ((Snp == NULL) || (Data == NULL)) {
  1637. return EFI_INVALID_PARAMETER;
  1638. }
  1639. // Serialize access to data and registers
  1640. SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
  1641. // Check that driver was started and initialised
  1642. switch (Snp->Mode->State) {
  1643. case EfiSimpleNetworkInitialized:
  1644. break;
  1645. case EfiSimpleNetworkStarted:
  1646. DEBUG ((DEBUG_WARN, "LAN91x: Driver not yet initialized\n"));
  1647. ReturnUnlock (EFI_DEVICE_ERROR);
  1648. case EfiSimpleNetworkStopped:
  1649. DEBUG ((DEBUG_WARN, "LAN91x: Driver not started\n"));
  1650. ReturnUnlock (EFI_NOT_STARTED);
  1651. default:
  1652. DEBUG ((DEBUG_ERROR, "LAN91x: Driver in an invalid state: %u\n",
  1653. (UINTN)Snp->Mode->State));
  1654. ReturnUnlock (EFI_DEVICE_ERROR);
  1655. }
  1656. // Find the LanDriver structure
  1657. LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
  1658. // Check for Rx Overrun
  1659. IstReg = ReadIoReg8 (LanDriver, LAN91X_IST);
  1660. if ((IstReg & IST_RX_OVRN) != 0) {
  1661. LanDriver->Stats.RxTotalFrames += 1;
  1662. LanDriver->Stats.RxDroppedFrames += 1;
  1663. WriteIoReg8 (LanDriver, LAN91X_IST, IST_RX_OVRN);
  1664. DEBUG ((DEBUG_WARN, "LAN91x: Receiver overrun\n"));
  1665. }
  1666. // Check for Rx data available
  1667. if ((IstReg & IST_RCV) == 0) {
  1668. ReturnUnlock (EFI_NOT_READY);
  1669. }
  1670. // Configure the PTR register for reading
  1671. WriteIoReg16 (LanDriver, LAN91X_PTR, PTR_RCV | PTR_AUTO_INCR | PTR_READ);
  1672. // Read the Packet Status and Packet Length words
  1673. PktStatus = ReadIoReg16 (LanDriver, LAN91X_DATA0);
  1674. PktLength = ReadIoReg16 (LanDriver, LAN91X_DATA0) & BCW_COUNT;
  1675. // Check for valid received packet
  1676. if ((PktStatus == 0) && (PktLength == 0)) {
  1677. DEBUG ((DEBUG_WARN, "LAN91x: Received zero-length packet. IST=%04x\n", IstReg));
  1678. ReturnUnlock (EFI_NOT_READY);
  1679. }
  1680. LanDriver->Stats.RxTotalFrames += 1;
  1681. // Check if we got a CRC error
  1682. if ((PktStatus & RX_BAD_CRC) != 0) {
  1683. DEBUG ((DEBUG_WARN, "LAN91x: Received frame CRC error\n"));
  1684. LanDriver->Stats.RxCrcErrorFrames += 1;
  1685. LanDriver->Stats.RxDroppedFrames += 1;
  1686. Status = EFI_DEVICE_ERROR;
  1687. goto exit_release;
  1688. }
  1689. // Check if we got a too-short frame
  1690. if ((PktStatus & RX_TOO_SHORT) != 0) {
  1691. DEBUG ((DEBUG_WARN, "LAN91x: Received frame too short (%d bytes)\n", PktLength));
  1692. LanDriver->Stats.RxUndersizeFrames += 1;
  1693. LanDriver->Stats.RxDroppedFrames += 1;
  1694. Status = EFI_DEVICE_ERROR;
  1695. goto exit_release;
  1696. }
  1697. // Check if we got a too-long frame
  1698. if ((PktStatus & RX_TOO_LONG) != 0) {
  1699. DEBUG ((DEBUG_WARN, "LAN91x: Received frame too long (%d bytes)\n", PktLength));
  1700. LanDriver->Stats.RxOversizeFrames += 1;
  1701. LanDriver->Stats.RxDroppedFrames += 1;
  1702. Status = EFI_DEVICE_ERROR;
  1703. goto exit_release;
  1704. }
  1705. // Check if we got an alignment error
  1706. if ((PktStatus & RX_ALGN_ERR) != 0) {
  1707. DEBUG ((DEBUG_WARN, "LAN91x: Received frame alignment error\n"));
  1708. // Don't seem to keep track of these specifically
  1709. LanDriver->Stats.RxDroppedFrames += 1;
  1710. Status = EFI_DEVICE_ERROR;
  1711. goto exit_release;
  1712. }
  1713. // Classify the received fram
  1714. if ((PktStatus & RX_MULTICAST) != 0) {
  1715. LanDriver->Stats.RxMulticastFrames += 1;
  1716. } else if ((PktStatus & RX_BROADCAST) != 0) {
  1717. LanDriver->Stats.RxBroadcastFrames += 1;
  1718. } else {
  1719. LanDriver->Stats.RxUnicastFrames += 1;
  1720. }
  1721. // Calculate the received packet data length
  1722. PktLength -= LAN91X_PKT_OVERHEAD;
  1723. if ((PktStatus & RX_ODD_FRAME) != 0) {
  1724. PktLength += 1;
  1725. }
  1726. // Check buffer size
  1727. if (*BuffSize < PktLength) {
  1728. DEBUG ((DEBUG_WARN, "LAN91x: Receive buffer too small for packet (%d < %d)\n",
  1729. *BuffSize, PktLength));
  1730. *BuffSize = PktLength;
  1731. Status = EFI_BUFFER_TOO_SMALL;
  1732. goto exit_release;
  1733. }
  1734. // Transfer the data bytes
  1735. DataPtr = Data;
  1736. ReadIoData (LanDriver, DataPtr, PktLength & ~0x0001);
  1737. // Read the PktControl and Odd Byte from the FIFO
  1738. PktControl = ReadIoReg16 (LanDriver, LAN91X_DATA0);
  1739. if ((PktControl & PCW_ODD) != 0) {
  1740. DataPtr[PktLength - 1] = PktControl & PCW_ODD_BYTE;
  1741. }
  1742. // Update buffer size
  1743. *BuffSize = PktLength;
  1744. if (HdrSize != NULL) {
  1745. *HdrSize = LanDriver->SnpMode.MediaHeaderSize;
  1746. }
  1747. // Extract the destination address
  1748. if (DstAddr != NULL) {
  1749. CopyMem (DstAddr, &DataPtr[0], NET_ETHER_ADDR_LEN);
  1750. }
  1751. // Get the source address
  1752. if (SrcAddr != NULL) {
  1753. CopyMem (SrcAddr, &DataPtr[6], NET_ETHER_ADDR_LEN);
  1754. }
  1755. // Get the protocol
  1756. if (Protocol != NULL) {
  1757. *Protocol = NTOHS (*(UINT16*)(&DataPtr[12]));
  1758. }
  1759. // Update the Rx statistics
  1760. LanDriver->Stats.RxTotalBytes += PktLength;
  1761. LanDriver->Stats.RxGoodFrames += 1;
  1762. Status = EFI_SUCCESS;
  1763. #if LAN91X_PRINT_PACKET_HEADERS
  1764. // Dump the packet header
  1765. DEBUG ((DEBUG_ERROR, "LAN91X:SnpReceive()\n"));
  1766. DEBUG ((DEBUG_ERROR, " HdrSize: %p, SrcAddr: %p, DstAddr: %p, Protocol: %p\n",
  1767. HdrSize, SrcAddr, DstAddr, Protocol));
  1768. DEBUG ((DEBUG_ERROR, " Length: %d, Last byte: %02x\n", PktLength, DataPtr[PktLength - 1]));
  1769. PrintIpDgram (&DataPtr[0], &DataPtr[6], &DataPtr[12], &DataPtr[14]);
  1770. #endif
  1771. // Release the FIFO buffer
  1772. exit_release:
  1773. MmuOperation (LanDriver, MMUCR_OP_RX_POP_REL);
  1774. // Restore TPL and return
  1775. exit_unlock:
  1776. gBS->RestoreTPL (SavedTpl);
  1777. return Status;
  1778. }
  1779. /*------------------ Driver Execution Environment main entry point ------------------*/
  1780. /*
  1781. ** Entry point for the LAN91x driver
  1782. **
  1783. */
  1784. EFI_STATUS
  1785. Lan91xDxeEntry (
  1786. IN EFI_HANDLE Handle,
  1787. IN EFI_SYSTEM_TABLE *SystemTable
  1788. )
  1789. {
  1790. EFI_STATUS Status;
  1791. LAN91X_DRIVER *LanDriver;
  1792. EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
  1793. EFI_SIMPLE_NETWORK_MODE *SnpMode;
  1794. LAN91X_DEVICE_PATH *Lan91xPath;
  1795. // The PcdLan91xDxeBaseAddress PCD must be defined
  1796. ASSERT(PcdGet32 (PcdLan91xDxeBaseAddress) != 0);
  1797. // Allocate Resources
  1798. LanDriver = AllocateZeroPool (sizeof(LAN91X_DRIVER));
  1799. Lan91xPath = AllocateCopyPool (sizeof(LAN91X_DEVICE_PATH), &Lan91xPathTemplate);
  1800. // Initialize I/O Space access info
  1801. LanDriver->IoBase = PcdGet32 (PcdLan91xDxeBaseAddress);
  1802. LanDriver->PhyAd = LAN91X_NO_PHY;
  1803. LanDriver->BankSel = 0xff;
  1804. // Initialize pointers
  1805. Snp = &(LanDriver->Snp);
  1806. SnpMode = &(LanDriver->SnpMode);
  1807. Snp->Mode = SnpMode;
  1808. // Set the signature of the LAN Driver structure
  1809. LanDriver->Signature = LAN91X_SIGNATURE;
  1810. // Probe the device
  1811. Status = Probe (LanDriver);
  1812. if (EFI_ERROR(Status)) {
  1813. DEBUG ((DEBUG_ERROR, "LAN91x:Lan91xDxeEntry(): Probe failed with status %d\n", Status));
  1814. return Status;
  1815. }
  1816. #ifdef LAN91X_PRINT_REGISTERS
  1817. PrintIoRegisters (LanDriver);
  1818. PrintPhyRegisters (LanDriver);
  1819. #endif
  1820. // Initialize transmit queue
  1821. InitializeListHead (&LanDriver->TransmitQueueHead);
  1822. // Assign fields and func pointers
  1823. Snp->Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
  1824. Snp->WaitForPacket = NULL;
  1825. Snp->Initialize = SnpInitialize;
  1826. Snp->Start = SnpStart;
  1827. Snp->Stop = SnpStop;
  1828. Snp->Reset = SnpReset;
  1829. Snp->Shutdown = SnpShutdown;
  1830. Snp->ReceiveFilters = SnpReceiveFilters;
  1831. Snp->StationAddress = SnpStationAddress;
  1832. Snp->Statistics = SnpStatistics;
  1833. Snp->MCastIpToMac = SnpMcastIptoMac;
  1834. Snp->NvData = SnpNvData;
  1835. Snp->GetStatus = SnpGetStatus;
  1836. Snp->Transmit = SnpTransmit;
  1837. Snp->Receive = SnpReceive;
  1838. // Fill in simple network mode structure
  1839. SnpMode->State = EfiSimpleNetworkStopped;
  1840. SnpMode->HwAddressSize = NET_ETHER_ADDR_LEN; // HW address is 6 bytes
  1841. SnpMode->MediaHeaderSize = sizeof(ETHER_HEAD); // Size of an Ethernet header
  1842. SnpMode->MaxPacketSize = EFI_PAGE_SIZE; // Ethernet Frame (with VLAN tag +4 bytes)
  1843. // Supported receive filters
  1844. SnpMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
  1845. EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
  1846. EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
  1847. EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS |
  1848. EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
  1849. // Initially-enabled receive filters
  1850. SnpMode->ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
  1851. EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
  1852. EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
  1853. // LAN91x has 64bit hash table. We can filter an infinite MACs, but
  1854. // higher-level software must filter out any hash collisions.
  1855. SnpMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT;
  1856. SnpMode->MCastFilterCount = 0;
  1857. ZeroMem (&SnpMode->MCastFilter, MAX_MCAST_FILTER_CNT * sizeof(EFI_MAC_ADDRESS));
  1858. // Set the interface type (1: Ethernet or 6: IEEE 802 Networks)
  1859. SnpMode->IfType = NET_IFTYPE_ETHERNET;
  1860. // Mac address is changeable
  1861. SnpMode->MacAddressChangeable = TRUE;
  1862. // We can only transmit one packet at a time
  1863. SnpMode->MultipleTxSupported = FALSE;
  1864. // MediaPresent checks for cable connection and partner link
  1865. SnpMode->MediaPresentSupported = TRUE;
  1866. SnpMode->MediaPresent = FALSE;
  1867. // Set broadcast address
  1868. SetMem (&SnpMode->BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF);
  1869. // Assign fields for device path
  1870. Lan91xPath->Lan91x.MacAddress = SnpMode->PermanentAddress;
  1871. Lan91xPath->Lan91x.IfType = SnpMode->IfType;
  1872. // Initialise the protocol
  1873. Status = gBS->InstallMultipleProtocolInterfaces (
  1874. &LanDriver->ControllerHandle,
  1875. &gEfiSimpleNetworkProtocolGuid, Snp,
  1876. &gEfiDevicePathProtocolGuid, Lan91xPath,
  1877. NULL
  1878. );
  1879. // Say what the status of loading the protocol structure is
  1880. if (EFI_ERROR(Status)) {
  1881. FreePool (LanDriver);
  1882. }
  1883. return Status;
  1884. }