lan91c111.c 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641
  1. /****************************************************************************
  2. * drivers/net/lan91c111.c
  3. *
  4. * Copyright (C) 2018 Pinecone Inc. All rights reserved.
  5. * Author: Xiang Xiao <xiaoxiang@pinecone.net>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <assert.h>
  40. #include <debug.h>
  41. #include <errno.h>
  42. #include <nuttx/arch.h>
  43. #include <nuttx/irq.h>
  44. #include <nuttx/kmalloc.h>
  45. #include <nuttx/wdog.h>
  46. #include <nuttx/wqueue.h>
  47. #include <nuttx/net/arp.h>
  48. #include <nuttx/net/lan91c111.h>
  49. #include <nuttx/net/netdev.h>
  50. #include <nuttx/net/pkt.h>
  51. #include "lan91c111.h"
  52. /****************************************************************************
  53. * Pre-processor Definitions
  54. ****************************************************************************/
  55. /* Work queue support is required. */
  56. #if !defined(CONFIG_SCHED_WORKQUEUE)
  57. # error Work queue support is required in this configuration (CONFIG_SCHED_WORKQUEUE)
  58. #endif
  59. /* The low priority work queue is preferred. If it is not enabled, LPWORK
  60. * will be the same as HPWORK.
  61. *
  62. * NOTE: However, the network should NEVER run on the high priority work
  63. * queue! That queue is intended only to service short back end interrupt
  64. * processing that never suspends. Suspending the high priority work queue
  65. * may bring the system to its knees!
  66. */
  67. #define LAN91C111_WORK LPWORK
  68. #ifdef CONFIG_NET_DUMPPACKET
  69. # define lan91c111_dumppacket lib_dumpbuffer
  70. #else
  71. # define lan91c111_dumppacket(m, b, l)
  72. #endif
  73. /* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per second */
  74. #define LAN91C111_WDDELAY (1*CLK_TCK)
  75. /* MII busy delay = 1 microsecond */
  76. #define LAN91C111_MIIDELAY 1
  77. /****************************************************************************
  78. * Private Types
  79. ****************************************************************************/
  80. /* lan91c111_driver_s encapsulates all state information for a single
  81. * hardware interface
  82. */
  83. struct lan91c111_driver_s
  84. {
  85. uintptr_t base; /* Base address */
  86. int irq; /* IRQ number */
  87. uint16_t bank; /* Current bank */
  88. WDOG_ID txpoll; /* TX poll timer */
  89. struct work_s irqwork; /* For deferring interrupt work to the work queue */
  90. struct work_s pollwork; /* For deferring poll work to the work queue */
  91. uint8_t pktbuf[MAX_NETDEV_PKTSIZE + 4]; /* +4 due to getregs32/putregs32 */
  92. /* This holds the information visible to the NuttX network */
  93. struct net_driver_s dev; /* Interface understood by the network */
  94. };
  95. /****************************************************************************
  96. * Private Function Prototypes
  97. ****************************************************************************/
  98. /* Common TX logic */
  99. static int lan91c111_transmit(FAR struct net_driver_s *dev);
  100. static int lan91c111_txpoll(FAR struct net_driver_s *dev);
  101. /* Interrupt handling */
  102. static void lan91c111_reply(FAR struct net_driver_s *dev);
  103. static void lan91c111_receive(FAR struct net_driver_s *dev);
  104. static void lan91c111_txdone(FAR struct net_driver_s *dev);
  105. static void lan91c111_interrupt_work(FAR void *arg);
  106. static int lan91c111_interrupt(int irq, FAR void *context, FAR void *arg);
  107. /* Watchdog timer expirations */
  108. static void lan91c111_poll_work(FAR void *arg);
  109. static void lan91c111_poll_expiry(int argc, wdparm_t arg, ...);
  110. /* NuttX callback functions */
  111. static int lan91c111_ifup(FAR struct net_driver_s *dev);
  112. static int lan91c111_ifdown(FAR struct net_driver_s *dev);
  113. static void lan91c111_txavail_work(FAR void *arg);
  114. static int lan91c111_txavail(FAR struct net_driver_s *dev);
  115. #if defined(CONFIG_NET_MCASTGROUP) || defined(CONFIG_NET_ICMPv6)
  116. static int lan91c111_addmac(FAR struct net_driver_s *dev,
  117. FAR const uint8_t *mac);
  118. #ifdef CONFIG_NET_MCASTGROUP
  119. static int lan91c111_rmmac(FAR struct net_driver_s *dev,
  120. FAR const uint8_t *mac);
  121. #endif
  122. #ifdef CONFIG_NET_ICMPv6
  123. static void lan91c111_ipv6multicast(FAR struct net_driver_s *dev);
  124. #endif
  125. #endif
  126. #ifdef CONFIG_NETDEV_IOCTL
  127. static int lan91c111_ioctl(FAR struct net_driver_s *dev, int cmd,
  128. unsigned long arg);
  129. #endif
  130. /****************************************************************************
  131. * Private Functions
  132. ****************************************************************************/
  133. /* MAC register access, assume lock hold by caller */
  134. static uint16_t updatebank(FAR struct lan91c111_driver_s *priv,
  135. uint16_t offset)
  136. {
  137. uint16_t bank = offset >> 8;
  138. if (bank != priv->bank)
  139. {
  140. *(FAR volatile uint16_t *)(priv->base + BSR_REG) = bank;
  141. priv->bank = bank;
  142. }
  143. return offset & 0xff;
  144. }
  145. static uint8_t getreg8(FAR struct lan91c111_driver_s *priv, uint16_t offset)
  146. {
  147. offset = updatebank(priv, offset);
  148. return *(FAR volatile uint8_t *)(priv->base + offset);
  149. }
  150. static uint16_t getreg16(FAR struct lan91c111_driver_s *priv, uint16_t offset)
  151. {
  152. offset = updatebank(priv, offset);
  153. return *(FAR volatile uint16_t *)(priv->base + offset);
  154. }
  155. static void putreg8(FAR struct lan91c111_driver_s *priv,
  156. uint16_t offset, uint8_t value)
  157. {
  158. offset = updatebank(priv, offset);
  159. *(FAR volatile uint8_t *)(priv->base + offset) = value;
  160. }
  161. static void putreg16(FAR struct lan91c111_driver_s *priv,
  162. uint16_t offset, uint16_t value)
  163. {
  164. offset = updatebank(priv, offset);
  165. *(FAR volatile uint16_t *)(priv->base + offset) = value;
  166. }
  167. static void modifyreg16(FAR struct lan91c111_driver_s *priv,
  168. uint16_t offset, uint16_t clearbits,
  169. uint16_t setbits)
  170. {
  171. uint16_t value;
  172. offset = updatebank(priv, offset);
  173. value = *(FAR volatile uint16_t *)(priv->base + offset);
  174. value &= ~clearbits;
  175. value |= setbits;
  176. *(FAR volatile uint16_t *)(priv->base + offset) = value;
  177. }
  178. static void getregs32(FAR struct lan91c111_driver_s *priv,
  179. uint16_t offset, void *value_, size_t length)
  180. {
  181. FAR uint32_t *value = value_;
  182. size_t i;
  183. offset = updatebank(priv, offset);
  184. for (i = 0; i < length; i += sizeof(*value))
  185. {
  186. *value++ = *(FAR volatile uint32_t *)(priv->base + offset);
  187. }
  188. }
  189. static void putregs32(FAR struct lan91c111_driver_s *priv,
  190. uint16_t offset, const void *value_, size_t length)
  191. {
  192. FAR const uint32_t *value = value_;
  193. size_t i;
  194. offset = updatebank(priv, offset);
  195. for (i = 0; i < length; i += sizeof(*value))
  196. {
  197. *(FAR volatile uint32_t *)(priv->base + offset) = *value++;
  198. }
  199. }
  200. static void copyfrom16(FAR struct lan91c111_driver_s *priv,
  201. uint16_t offset, FAR void *value_, size_t length)
  202. {
  203. FAR uint16_t *value = value_;
  204. size_t i;
  205. offset = updatebank(priv, offset);
  206. for (i = 0; i < length; i += sizeof(*value))
  207. {
  208. *value++ = *(FAR volatile uint16_t *)(priv->base + offset);
  209. offset += sizeof(*value);
  210. }
  211. }
  212. static void copyto16(FAR struct lan91c111_driver_s *priv,
  213. uint16_t offset, FAR const void *value_, size_t length)
  214. {
  215. FAR const uint16_t *value = value_;
  216. size_t i;
  217. offset = updatebank(priv, offset);
  218. for (i = 0; i < length; i += sizeof(*value))
  219. {
  220. *(FAR volatile uint16_t *)(priv->base + offset) = *value++;
  221. offset += sizeof(*value);
  222. }
  223. }
  224. /* PHY register access, assume lock hold by caller */
  225. static void outmii(FAR struct lan91c111_driver_s *priv,
  226. uint32_t value, size_t bits)
  227. {
  228. uint32_t mask;
  229. uint16_t mii;
  230. mii = getreg16(priv, MII_REG);
  231. mii &= ~MII_MCLK;
  232. mii |= MII_MDOE;
  233. for (mask = 1 << (bits - 1); mask; mask >>= 1)
  234. {
  235. if (value & mask)
  236. {
  237. mii |= MII_MDO;
  238. }
  239. else
  240. {
  241. mii &= ~MII_MDO;
  242. }
  243. putreg16(priv, MII_REG, mii);
  244. up_udelay(LAN91C111_MIIDELAY);
  245. putreg16(priv, MII_REG, mii | MII_MCLK);
  246. up_udelay(LAN91C111_MIIDELAY);
  247. }
  248. }
  249. static uint32_t inmii(FAR struct lan91c111_driver_s *priv, size_t bits)
  250. {
  251. uint32_t value = 0;
  252. uint32_t mask;
  253. uint16_t mii;
  254. mii = getreg16(priv, MII_REG);
  255. mii &= ~(MII_MCLK | MII_MDOE);
  256. for (mask = 1 << (bits - 1); mask; mask >>= 1)
  257. {
  258. putreg16(priv, MII_REG, mii);
  259. up_udelay(LAN91C111_MIIDELAY);
  260. if (getreg16(priv, MII_REG) & MII_MDI)
  261. {
  262. value |= mask;
  263. }
  264. putreg16(priv, MII_REG, mii | MII_MCLK);
  265. up_udelay(LAN91C111_MIIDELAY);
  266. }
  267. return value;
  268. }
  269. static uint16_t getphy(FAR struct lan91c111_driver_s *priv, uint8_t offset)
  270. {
  271. uint16_t value;
  272. /* Idle - 32 ones */
  273. outmii(priv, 0xffffffff, 32);
  274. /* Start(01) + read(10) + addr(00000) + offset(5bits) */
  275. outmii(priv, 6 << 10 | 0 << 5 | offset, 14);
  276. /* Turnaround(2bits) + value(16bits) */
  277. value = inmii(priv, 18); /* Cut the high 2bits */
  278. /* Return to idle state */
  279. modifyreg16(priv, MII_REG, MII_MCLK | MII_MDOE | MII_MDO, 0);
  280. return value;
  281. }
  282. static void putphy(FAR struct lan91c111_driver_s *priv,
  283. uint8_t offset, uint16_t value)
  284. {
  285. /* Idle - 32 ones */
  286. outmii(priv, 0xffffffff, 32);
  287. /* Start(01) + write(01) + addr(00000) + offset(5bits) + turnaround(10) +
  288. * value(16bits)
  289. */
  290. outmii(priv, 5 << 28 | 0 << 23 | offset << 18 | 2 << 16 | value, 32);
  291. /* Return to idle state */
  292. modifyreg16(priv, MII_REG, MII_MCLK | MII_MDOE | MII_MDO, 0);
  293. }
  294. /* Small utility function, assume lock hold by caller */
  295. static void lan91c111_command_mmu(FAR struct lan91c111_driver_s *priv,
  296. uint16_t cmd)
  297. {
  298. putreg16(priv, MMU_CMD_REG, cmd);
  299. while (getreg16(priv, MMU_CMD_REG) & MC_BUSY)
  300. {
  301. /* Wait until the current command finish */
  302. }
  303. }
  304. /****************************************************************************
  305. * Name: lan91c111_transmit
  306. *
  307. * Description:
  308. * Start hardware transmission. Called either from the txdone interrupt
  309. * handling or from watchdog based polling.
  310. *
  311. * Parameters:
  312. * dev - Reference to the NuttX driver state structure
  313. *
  314. * Returned Value:
  315. * OK on success; a negated errno on failure
  316. *
  317. * Assumptions:
  318. * The network is locked.
  319. *
  320. ****************************************************************************/
  321. static int lan91c111_transmit(FAR struct net_driver_s *dev)
  322. {
  323. FAR struct lan91c111_driver_s *priv = dev->d_private;
  324. uint32_t pages;
  325. uint8_t packet;
  326. /* Verify that the hardware is ready to send another packet. If we get
  327. * here, then we are committed to sending a packet; Higher level logic
  328. * must have assured that there is no transmission in progress.
  329. */
  330. /* The MMU wants the number of pages to be the number of 256 bytes
  331. * 'pages', minus 1 (since a packet can't ever have 0 pages :))
  332. *
  333. * Packet size for allocating is data length +6 (for additional status
  334. * words, length and ctl)
  335. *
  336. * If odd size then last byte is included in ctl word.
  337. */
  338. pages = ((dev->d_len & ~1) + 6) >> 8;
  339. while (1)
  340. {
  341. /* Release the received packet if no free memory */
  342. if (!(getreg16(priv, MIR_REG) & MIR_FREE_MASK) &&
  343. !(getreg8(priv, RXFIFO_REG) & RXFIFO_REMPTY))
  344. {
  345. lan91c111_command_mmu(priv, MC_RELEASE);
  346. NETDEV_RXERRORS(dev);
  347. }
  348. /* Now, try to allocate the memory */
  349. lan91c111_command_mmu(priv, MC_ALLOC | pages);
  350. while (1) /* Then wait the response */
  351. {
  352. if (getreg8(priv, INT_REG) & IM_ALLOC_INT)
  353. {
  354. /* Acknowledge the interrupt */
  355. putreg8(priv, INT_REG, IM_ALLOC_INT);
  356. break;
  357. }
  358. }
  359. /* Check the result */
  360. packet = getreg8(priv, AR_REG);
  361. if (!(packet & AR_FAILED))
  362. {
  363. break; /* Got the packet */
  364. }
  365. }
  366. /* Increment statistics */
  367. lan91c111_dumppacket("transmit", dev->d_buf, dev->d_len);
  368. NETDEV_TXPACKETS(dev);
  369. /* Send the packet: address=dev->d_buf, length=dev->d_len */
  370. /* Point to the beginning of the packet */
  371. putreg8(priv, PN_REG, packet);
  372. putreg16(priv, PTR_REG, PTR_AUTOINC);
  373. /* Send the status(set to zeros) and the packet
  374. * length(+6 for status, length and ctl byte)
  375. */
  376. putreg16(priv, DATA_REG, 0);
  377. putreg16(priv, DATA_REG, dev->d_len + 6);
  378. /* Append ctl byte */
  379. dev->d_buf[dev->d_len] = TC_ODD;
  380. dev->d_buf[dev->d_len + 1] = 0x00;
  381. /* Copy and enqueue the buffer */
  382. putregs32(priv, DATA_REG, dev->d_buf, dev->d_len + 2);
  383. lan91c111_command_mmu(priv, MC_ENQUEUE);
  384. /* Assume the transmission no error, otherwise
  385. * revert the increment in lan91c111_txdone */
  386. NETDEV_TXDONE(dev);
  387. return OK;
  388. }
  389. /****************************************************************************
  390. * Name: lan91c111_txpoll
  391. *
  392. * Description:
  393. * The transmitter is available, check if the network has any outgoing
  394. * packets ready to send. This is a callback from devif_poll().
  395. * devif_poll() may be called:
  396. *
  397. * 1. When the preceding TX packet send is complete,
  398. * 2. When the preceding TX packet send fail
  399. * 3. During normal TX polling
  400. *
  401. * Parameters:
  402. * dev - Reference to the NuttX driver state structure
  403. *
  404. * Returned Value:
  405. * OK on success; a negated errno on failure
  406. *
  407. * Assumptions:
  408. * The network is locked.
  409. *
  410. ****************************************************************************/
  411. static int lan91c111_txpoll(FAR struct net_driver_s *dev)
  412. {
  413. FAR struct lan91c111_driver_s *priv = dev->d_private;
  414. /* If the polling resulted in data that should be sent out on the network,
  415. * the field d_len is set to a value > 0.
  416. */
  417. if (dev->d_len > 0)
  418. {
  419. /* Look up the destination MAC address and add it to the Ethernet
  420. * header.
  421. */
  422. #ifdef CONFIG_NET_IPv4
  423. if (IFF_IS_IPv4(dev->d_flags))
  424. {
  425. arp_out(dev);
  426. }
  427. #endif /* CONFIG_NET_IPv4 */
  428. #ifdef CONFIG_NET_IPv6
  429. if (IFF_IS_IPv6(dev->d_flags))
  430. {
  431. neighbor_out(dev);
  432. }
  433. #endif /* CONFIG_NET_IPv6 */
  434. if (!devif_loopback(dev))
  435. {
  436. /* Send the packet */
  437. lan91c111_transmit(dev);
  438. /* Check if there is room in the device to hold another packet. If not,
  439. * return a non-zero value to terminate the poll.
  440. */
  441. return !(getreg16(priv, MIR_REG) & MIR_FREE_MASK);
  442. }
  443. }
  444. /* If zero is returned, the polling will continue until all connections have
  445. * been examined.
  446. */
  447. return 0;
  448. }
  449. /****************************************************************************
  450. * Name: lan91c111_reply
  451. *
  452. * Description:
  453. * After a packet has been received and dispatched to the network, it
  454. * may return with an outgoing packet. This function checks for
  455. * that case and performs the transmission if necessary.
  456. *
  457. * Parameters:
  458. * dev - Reference to the NuttX driver state structure
  459. *
  460. * Returned Value:
  461. * None
  462. *
  463. * Assumptions:
  464. * The network is locked.
  465. *
  466. ****************************************************************************/
  467. static void lan91c111_reply(FAR struct net_driver_s *dev)
  468. {
  469. /* If the packet dispatch resulted in data that should be sent out on the
  470. * network, the field d_len will set to a value > 0.
  471. */
  472. if (dev->d_len > 0)
  473. {
  474. /* Update the Ethernet header with the correct MAC address */
  475. #ifdef CONFIG_NET_IPv4
  476. if (IFF_IS_IPv4(dev->d_flags))
  477. {
  478. arp_out(dev);
  479. }
  480. #endif
  481. #ifdef CONFIG_NET_IPv6
  482. if (IFF_IS_IPv6(dev->d_flags))
  483. {
  484. neighbor_out(dev);
  485. }
  486. #endif
  487. /* And send the packet */
  488. lan91c111_transmit(dev);
  489. }
  490. }
  491. /****************************************************************************
  492. * Name: lan91c111_receive
  493. *
  494. * Description:
  495. * An interrupt was received indicating the availability of a new RX packet
  496. *
  497. * Parameters:
  498. * dev - Reference to the NuttX driver state structure
  499. *
  500. * Returned Value:
  501. * None
  502. *
  503. * Assumptions:
  504. * The network is locked.
  505. *
  506. ****************************************************************************/
  507. static void lan91c111_receive(FAR struct net_driver_s *dev)
  508. {
  509. FAR struct lan91c111_driver_s *priv = dev->d_private;
  510. FAR struct eth_hdr_s *eth = (FAR struct eth_hdr_s *)dev->d_buf;
  511. uint16_t status, length;
  512. /* If the RX FIFO is empty then nothing to do */
  513. if (getreg8(priv, RXFIFO_REG) & RXFIFO_REMPTY)
  514. {
  515. return;
  516. }
  517. /* Read from start of packet */
  518. putreg16(priv, PTR_REG, PTR_RCV | PTR_AUTOINC | PTR_READ);
  519. /* Check for errors and update statistics */
  520. status = getreg16(priv, DATA_REG);
  521. if (status & RS_ERRORS)
  522. {
  523. lan91c111_command_mmu(priv, MC_RELEASE);
  524. NETDEV_RXERRORS(dev);
  525. return;
  526. }
  527. /* Check if the packet is a valid size for the network buffer
  528. * configuration.
  529. */
  530. length = getreg16(priv, DATA_REG);
  531. length &= 0x07ff; /* Mask off top bits */
  532. /* Remove the header and tail space */
  533. length -= status & RS_ODDFRAME ? 5 : 6;
  534. if (length < ETH_HDRLEN || length > MAX_NETDEV_PKTSIZE)
  535. {
  536. lan91c111_command_mmu(priv, MC_RELEASE);
  537. NETDEV_RXERRORS(dev);
  538. return;
  539. }
  540. /* Copy the data from the hardware to dev->d_buf. Set
  541. * amount of data in dev->d_len
  542. */
  543. getregs32(priv, DATA_REG, dev->d_buf, length);
  544. dev->d_len = length;
  545. lan91c111_command_mmu(priv, MC_RELEASE);
  546. lan91c111_dumppacket("receive", dev->d_buf, dev->d_len);
  547. NETDEV_RXPACKETS(dev);
  548. #ifdef CONFIG_NET_PKT
  549. /* When packet sockets are enabled, feed the frame into the packet tap */
  550. pkt_input(dev);
  551. #endif
  552. /* We only accept IP packets of the configured type and ARP packets */
  553. #ifdef CONFIG_NET_IPv4
  554. if (eth->type == HTONS(ETHTYPE_IP))
  555. {
  556. ninfo("IPv4 frame\n");
  557. NETDEV_RXIPV4(dev);
  558. /* Handle ARP on input, then dispatch IPv4 packet to the network
  559. * layer.
  560. */
  561. arp_ipin(dev);
  562. ipv4_input(dev);
  563. /* Check for a reply to the IPv4 packet */
  564. lan91c111_reply(dev);
  565. }
  566. else
  567. #endif
  568. #ifdef CONFIG_NET_IPv6
  569. if (eth->type == HTONS(ETHTYPE_IP6))
  570. {
  571. ninfo("Iv6 frame\n");
  572. NETDEV_RXIPV6(dev);
  573. /* Dispatch IPv6 packet to the network layer */
  574. ipv6_input(dev);
  575. /* Check for a reply to the IPv6 packet */
  576. lan91c111_reply(dev);
  577. }
  578. else
  579. #endif
  580. #ifdef CONFIG_NET_ARP
  581. if (eth->type == htons(ETHTYPE_ARP))
  582. {
  583. ninfo("ARP frame\n");
  584. NETDEV_RXARP(dev);
  585. /* Dispatch ARP packet to the network layer */
  586. arp_arpin(dev);
  587. /* Check for a reply to the ARP packet */
  588. lan91c111_reply(dev);
  589. }
  590. else
  591. #endif
  592. {
  593. NETDEV_RXDROPPED(dev);
  594. }
  595. }
  596. /****************************************************************************
  597. * Name: lan91c111_txdone
  598. *
  599. * Description:
  600. * An interrupt was received indicating that the last TX packet(s) is done
  601. *
  602. * Parameters:
  603. * dev - Reference to the NuttX driver state structure
  604. *
  605. * Returned Value:
  606. * None
  607. *
  608. * Assumptions:
  609. * The network is locked.
  610. *
  611. ****************************************************************************/
  612. static void lan91c111_txdone(FAR struct net_driver_s *dev)
  613. {
  614. FAR struct lan91c111_driver_s *priv = dev->d_private;
  615. uint16_t status;
  616. uint8_t packet;
  617. /* If the TX FIFO is empty then nothing to do */
  618. packet = getreg8(priv, TXFIFO_REG);
  619. if (packet & TXFIFO_TEMPTY)
  620. {
  621. return;
  622. }
  623. /* Read the status word and free this packet */
  624. putreg8(priv, PN_REG, packet);
  625. putreg16(priv, PTR_REG, PTR_AUTOINC | PTR_READ);
  626. status = getreg16(priv, DATA_REG);
  627. lan91c111_command_mmu(priv, MC_FREEPKT);
  628. /* Check for errors and update statistics */
  629. if (status & ES_ERRORS)
  630. {
  631. /* Re-enable transmit */
  632. modifyreg16(priv, TCR_REG, 0, TCR_ENABLE);
  633. #ifdef CONFIG_NETDEV_STATISTICS
  634. /* Revert the increment in lan91c111_transmit */
  635. dev->d_statistics.tx_done--;
  636. #endif
  637. NETDEV_TXERRORS(dev);
  638. }
  639. else
  640. {
  641. DEBUGASSERT(0);
  642. }
  643. }
  644. /****************************************************************************
  645. * Name: lan91c111_phy_notify
  646. *
  647. * Description:
  648. * An interrupt was received indicating that the phy has status change
  649. *
  650. * Parameters:
  651. * dev - Reference to the NuttX driver state structure
  652. *
  653. * Returned Value:
  654. * None
  655. *
  656. * Assumptions:
  657. * The network is locked.
  658. *
  659. ****************************************************************************/
  660. static void lan91c111_phy_notify(FAR struct net_driver_s *dev)
  661. {
  662. FAR struct lan91c111_driver_s *priv = dev->d_private;
  663. do
  664. {
  665. if (getphy(priv, MII_MSR) & MII_MSR_LINKSTATUS)
  666. {
  667. if (getphy(priv, MII_LPA) & MII_LPA_FULL)
  668. {
  669. modifyreg16(priv, TCR_REG, 0, TCR_SWFDUP);
  670. }
  671. else
  672. {
  673. modifyreg16(priv, TCR_REG, TCR_SWFDUP, 0);
  674. }
  675. netdev_carrier_on(dev);
  676. }
  677. else
  678. {
  679. netdev_carrier_off(dev);
  680. }
  681. }
  682. while (getphy(priv, PHY_INT_REG) & PHY_INT_INT);
  683. }
  684. /****************************************************************************
  685. * Name: lan91c111_interrupt_work
  686. *
  687. * Description:
  688. * Perform interrupt related work from the worker thread
  689. *
  690. * Parameters:
  691. * arg - The argument passed when work_queue() was called.
  692. *
  693. * Returned Value:
  694. * OK on success
  695. *
  696. * Assumptions:
  697. * Runs on a worker thread.
  698. *
  699. ****************************************************************************/
  700. static void lan91c111_interrupt_work(FAR void *arg)
  701. {
  702. FAR struct net_driver_s *dev = arg;
  703. FAR struct lan91c111_driver_s *priv = dev->d_private;
  704. uint8_t status;
  705. /* Lock the network and serialize driver operations if necessary.
  706. * NOTE: Serialization is only required in the case where the driver work
  707. * is performed on an LP worker thread and where more than one LP worker
  708. * thread has been configured.
  709. */
  710. net_lock();
  711. /* Process pending Ethernet interrupts */
  712. while (1)
  713. {
  714. /* Get interrupt status bits */
  715. status = getreg8(priv, INT_REG);
  716. status &= getreg8(priv, IM_REG);
  717. if (!status)
  718. {
  719. break;
  720. }
  721. /* Handle interrupts according to status bit settings */
  722. /* Check if we received an incoming packet, if so, call lan91c111_receive() */
  723. if (status & IM_RCV_INT)
  724. {
  725. lan91c111_receive(dev);
  726. }
  727. if (status & IM_RX_OVRN_INT)
  728. {
  729. NETDEV_RXERRORS(dev);
  730. }
  731. /* Check if a packet transmission just completed. If so, call lan91c111_txdone. */
  732. if (status & IM_TX_INT)
  733. {
  734. lan91c111_txdone(dev);
  735. }
  736. /* Check if we have the phy interrupt, if so, call lan91c111_phy_notify() */
  737. if (status & IM_MDINT)
  738. {
  739. lan91c111_phy_notify(dev);
  740. }
  741. /* Clear interrupt status bits */
  742. putreg8(priv, INT_REG, status);
  743. /* In any event, poll the network for new TX data */
  744. if (getreg16(priv, MIR_REG) & MIR_FREE_MASK)
  745. {
  746. devif_poll(dev, lan91c111_txpoll);
  747. }
  748. }
  749. net_unlock();
  750. /* Re-enable Ethernet interrupts */
  751. up_enable_irq(priv->irq);
  752. }
  753. /****************************************************************************
  754. * Name: lan91c111_interrupt
  755. *
  756. * Description:
  757. * Hardware interrupt handler
  758. *
  759. * Parameters:
  760. * irq - Number of the IRQ that generated the interrupt
  761. * context - Interrupt register state save info (architecture-specific)
  762. *
  763. * Returned Value:
  764. * OK on success
  765. *
  766. * Assumptions:
  767. * Runs in the context of a the Ethernet interrupt handler. Local
  768. * interrupts are disabled by the interrupt logic.
  769. *
  770. ****************************************************************************/
  771. static int lan91c111_interrupt(int irq, FAR void *context, FAR void *arg)
  772. {
  773. FAR struct net_driver_s *dev = arg;
  774. FAR struct lan91c111_driver_s *priv = dev->d_private;
  775. /* Disable further Ethernet interrupts. */
  776. up_disable_irq(priv->irq);
  777. /* Schedule to perform the interrupt processing on the worker thread. */
  778. work_queue(LAN91C111_WORK, &priv->irqwork, lan91c111_interrupt_work, dev, 0);
  779. return OK;
  780. }
  781. /****************************************************************************
  782. * Name: lan91c111_poll_work
  783. *
  784. * Description:
  785. * Perform periodic polling from the worker thread
  786. *
  787. * Parameters:
  788. * arg - The argument passed when work_queue() as called.
  789. *
  790. * Returned Value:
  791. * OK on success
  792. *
  793. * Assumptions:
  794. * Run on a work queue thread.
  795. *
  796. ****************************************************************************/
  797. static void lan91c111_poll_work(FAR void *arg)
  798. {
  799. FAR struct net_driver_s *dev = arg;
  800. FAR struct lan91c111_driver_s *priv = dev->d_private;
  801. /* Lock the network and serialize driver operations if necessary.
  802. * NOTE: Serialization is only required in the case where the driver work
  803. * is performed on an LP worker thread and where more than one LP worker
  804. * thread has been configured.
  805. */
  806. net_lock();
  807. /* Perform the poll */
  808. /* Check if there is room in the send another TX packet. We cannot perform
  809. * the TX poll if he are unable to accept another packet for transmission.
  810. */
  811. if (getreg16(priv, MIR_REG) & MIR_FREE_MASK)
  812. {
  813. /* If so, update TCP timing states and poll the network for new XMIT data.
  814. * Hmmm.. might be bug here. Does this mean if there is a transmit in
  815. * progress, we will missing TCP time state updates?
  816. */
  817. devif_timer(dev, lan91c111_txpoll);
  818. }
  819. /* Setup the watchdog poll timer again */
  820. wd_start(priv->txpoll, LAN91C111_WDDELAY, lan91c111_poll_expiry, 1,
  821. (wdparm_t)dev);
  822. net_unlock();
  823. }
  824. /****************************************************************************
  825. * Name: lan91c111_poll_expiry
  826. *
  827. * Description:
  828. * Periodic timer handler. Called from the timer interrupt handler.
  829. *
  830. * Parameters:
  831. * argc - The number of available arguments
  832. * arg - The first argument
  833. *
  834. * Returned Value:
  835. * None
  836. *
  837. * Assumptions:
  838. * Runs in the context of a the timer interrupt handler. Local
  839. * interrupts are disabled by the interrupt logic.
  840. *
  841. ****************************************************************************/
  842. static void lan91c111_poll_expiry(int argc, wdparm_t arg, ...)
  843. {
  844. FAR struct net_driver_s *dev = (FAR struct net_driver_s *)arg;
  845. FAR struct lan91c111_driver_s *priv = dev->d_private;
  846. /* Schedule to perform the interrupt processing on the worker thread. */
  847. work_queue(LAN91C111_WORK, &priv->pollwork, lan91c111_poll_work, dev, 0);
  848. }
  849. /****************************************************************************
  850. * Name: lan91c111_ifup
  851. *
  852. * Description:
  853. * NuttX Callback: Bring up the Ethernet interface when an IP address is
  854. * provided
  855. *
  856. * Parameters:
  857. * dev - Reference to the NuttX driver state structure
  858. *
  859. * Returned Value:
  860. * None
  861. *
  862. * Assumptions:
  863. * The network is locked.
  864. *
  865. ****************************************************************************/
  866. static int lan91c111_ifup(FAR struct net_driver_s *dev)
  867. {
  868. FAR struct lan91c111_driver_s *priv = dev->d_private;
  869. #ifdef CONFIG_NET_IPv4
  870. ninfo("Bringing up: %d.%d.%d.%d\n",
  871. dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff,
  872. (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24);
  873. #endif
  874. #ifdef CONFIG_NET_IPv6
  875. ninfo("Bringing up: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
  876. dev->d_ipv6addr[0], dev->d_ipv6addr[1], dev->d_ipv6addr[2],
  877. dev->d_ipv6addr[3], dev->d_ipv6addr[4], dev->d_ipv6addr[5],
  878. dev->d_ipv6addr[6], dev->d_ipv6addr[7]);
  879. #endif
  880. net_lock();
  881. /* Initialize PHYs, the Ethernet interface, and setup up Ethernet interrupts */
  882. putreg16(priv, CONFIG_REG, CONFIG_DEFAULT);
  883. putreg16(priv, CTL_REG, CTL_DEFAULT);
  884. putreg16(priv, TCR_REG, TCR_DEFAULT);
  885. putreg16(priv, RCR_REG, RCR_DEFAULT);
  886. putreg16(priv, RPC_REG, RPC_DEFAULT);
  887. putreg8(priv, IM_REG,
  888. IM_MDINT | IM_RX_OVRN_INT | IM_RCV_INT | IM_TX_INT);
  889. putphy(priv, PHY_MASK_REG, /* Interrupts listed here are disabled */
  890. PHY_INT_LOSSSYNC | PHY_INT_CWRD | PHY_INT_SSD | PHY_INT_ESD |
  891. PHY_INT_RPOL | PHY_INT_JAB | PHY_INT_SPDDET | PHY_INT_DPLXDET);
  892. putphy(priv, MII_MCR, MII_MCR_ANENABLE | MII_MCR_ANRESTART);
  893. lan91c111_phy_notify(dev); /* Check the initial phy state */
  894. /* Instantiate the MAC address from dev->d_mac.ether.ether_addr_octet */
  895. copyto16(priv, ADDR0_REG, &dev->d_mac.ether, sizeof(dev->d_mac.ether));
  896. #ifdef CONFIG_NET_ICMPv6
  897. /* Set up IPv6 multicast address filtering */
  898. lan91c111_ipv6multicast(dev);
  899. #endif
  900. /* Set and activate a timer process */
  901. wd_start(priv->txpoll, LAN91C111_WDDELAY, lan91c111_poll_expiry, 1,
  902. (wdparm_t)dev);
  903. net_unlock();
  904. /* Enable the Ethernet interrupt */
  905. up_enable_irq(priv->irq);
  906. return OK;
  907. }
  908. /****************************************************************************
  909. * Name: lan91c111_ifdown
  910. *
  911. * Description:
  912. * NuttX Callback: Stop the interface.
  913. *
  914. * Parameters:
  915. * dev - Reference to the NuttX driver state structure
  916. *
  917. * Returned Value:
  918. * None
  919. *
  920. * Assumptions:
  921. * The network is locked.
  922. *
  923. ****************************************************************************/
  924. static int lan91c111_ifdown(FAR struct net_driver_s *dev)
  925. {
  926. FAR struct lan91c111_driver_s *priv = dev->d_private;
  927. irqstate_t flags;
  928. /* Disable the Ethernet interrupt */
  929. flags = enter_critical_section();
  930. up_disable_irq(priv->irq);
  931. /* Cancel the TX poll timer and work */
  932. wd_cancel(priv->txpoll);
  933. work_cancel(LAN91C111_WORK, &priv->irqwork);
  934. work_cancel(LAN91C111_WORK, &priv->pollwork);
  935. /* Put the EMAC in its reset, non-operational state. This should be
  936. * a known configuration that will guarantee the lan91c111_ifup() always
  937. * successfully brings the interface back up.
  938. */
  939. putreg8(priv, IM_REG, 0);
  940. putreg16(priv, RCR_REG, RCR_CLEAR);
  941. putreg16(priv, TCR_REG, TCR_CLEAR);
  942. putreg16(priv, CTL_REG, CTL_CLEAR);
  943. putreg16(priv, CONFIG_REG, CONFIG_CLEAR);
  944. leave_critical_section(flags);
  945. return OK;
  946. }
  947. /****************************************************************************
  948. * Name: lan91c111_txavail_work
  949. *
  950. * Description:
  951. * Perform an out-of-cycle poll on the worker thread.
  952. *
  953. * Parameters:
  954. * arg - Reference to the NuttX driver state structure (cast to void*)
  955. *
  956. * Returned Value:
  957. * None
  958. *
  959. * Assumptions:
  960. * Runs on a work queue thread.
  961. *
  962. ****************************************************************************/
  963. static void lan91c111_txavail_work(FAR void *arg)
  964. {
  965. FAR struct net_driver_s *dev = arg;
  966. FAR struct lan91c111_driver_s *priv = dev->d_private;
  967. /* Lock the network and serialize driver operations if necessary.
  968. * NOTE: Serialization is only required in the case where the driver work
  969. * is performed on an LP worker thread and where more than one LP worker
  970. * thread has been configured.
  971. */
  972. net_lock();
  973. /* Ignore the notification if the interface is not yet up */
  974. if (IFF_IS_UP(dev->d_flags))
  975. {
  976. /* Check if there is room in the hardware to hold another outgoing
  977. * packet.
  978. */
  979. if (getreg16(priv, MIR_REG) & MIR_FREE_MASK)
  980. {
  981. /* If so, then poll the network for new XMIT data */
  982. devif_poll(dev, lan91c111_txpoll);
  983. }
  984. }
  985. net_unlock();
  986. }
  987. /****************************************************************************
  988. * Name: lan91c111_txavail
  989. *
  990. * Description:
  991. * Driver callback invoked when new TX data is available. This is a
  992. * stimulus perform an out-of-cycle poll and, thereby, reduce the TX
  993. * latency.
  994. *
  995. * Parameters:
  996. * dev - Reference to the NuttX driver state structure
  997. *
  998. * Returned Value:
  999. * None
  1000. *
  1001. * Assumptions:
  1002. * The network is locked.
  1003. *
  1004. ****************************************************************************/
  1005. static int lan91c111_txavail(FAR struct net_driver_s *dev)
  1006. {
  1007. FAR struct lan91c111_driver_s *priv = dev->d_private;
  1008. /* Is our single work structure available? It may not be if there are
  1009. * pending interrupt actions and we will have to ignore the Tx
  1010. * availability action.
  1011. */
  1012. if (work_available(&priv->pollwork))
  1013. {
  1014. /* Schedule to serialize the poll on the worker thread. */
  1015. work_queue(LAN91C111_WORK, &priv->pollwork, lan91c111_txavail_work,
  1016. dev, 0);
  1017. }
  1018. return OK;
  1019. }
  1020. /****************************************************************************
  1021. * Name: lan91c111_addmac
  1022. *
  1023. * Description:
  1024. * NuttX Callback: Add the specified MAC address to the hardware multicast
  1025. * address filtering
  1026. *
  1027. * IEEE (CRC32) from http://www.microchip.com/wwwproducts/en/LAN91C111
  1028. *
  1029. * Parameters:
  1030. * dev - Reference to the NuttX driver state structure
  1031. * mac - The MAC address to be added
  1032. *
  1033. * Returned Value:
  1034. * Zero (OK) on success; a negated errno value on failure.
  1035. *
  1036. ****************************************************************************/
  1037. #if defined(CONFIG_NET_MCASTGROUP) || defined(CONFIG_NET_ICMPv6)
  1038. static uint32_t lan91c111_crc32(FAR const uint8_t *src, size_t len)
  1039. {
  1040. uint32_t crc = 0xffffffff;
  1041. uint8_t carry, temp;
  1042. size_t i, j;
  1043. for (i = 0; i < len; i++)
  1044. {
  1045. temp = *src++;
  1046. for (j = 0; j < 8; j++)
  1047. {
  1048. carry = (crc & 0x80000000 ? 1 : 0) ^ (temp & 0x01);
  1049. crc <<= 1;
  1050. if (carry)
  1051. {
  1052. crc = (crc ^ 0x04c11db6) | carry;
  1053. }
  1054. temp >>= 1;
  1055. }
  1056. }
  1057. return crc;
  1058. }
  1059. static int lan91c111_addmac(FAR struct net_driver_s *dev,
  1060. FAR const uint8_t *mac)
  1061. {
  1062. FAR struct lan91c111_driver_s *priv = dev->d_private;
  1063. uint16_t off, bit;
  1064. uint32_t hash;
  1065. /* Calculate Ethernet CRC32 for MAC */
  1066. hash = lan91c111_crc32(mac, ETHER_ADDR_LEN);
  1067. /* The multicast table is a register array of 4 16-bit registers
  1068. * and the hash value is defined as the six most significant bits
  1069. * of the CRC of the destination addresses. The two msb's determine
  1070. * the register to be used (MCAST1-MCAST4), while the other four
  1071. * determine the bit within the register. If the appropriate bit in
  1072. * the table is set, the packet is received.
  1073. */
  1074. off = (hash >> 29) & 0x06;
  1075. bit = (hash >> 26) & 0x0f;
  1076. /* Add the MAC address to the hardware multicast routing table */
  1077. net_lock();
  1078. modifyreg16(priv, MCAST_REG1 + off, 0, 1 << bit);
  1079. net_unlock();
  1080. return OK;
  1081. }
  1082. #endif
  1083. /****************************************************************************
  1084. * Name: lan91c111_rmmac
  1085. *
  1086. * Description:
  1087. * NuttX Callback: Remove the specified MAC address from the hardware
  1088. * multicast address filtering
  1089. *
  1090. * Parameters:
  1091. * dev - Reference to the NuttX driver state structure
  1092. * mac - The MAC address to be removed
  1093. *
  1094. * Returned Value:
  1095. * Zero (OK) on success; a negated errno value on failure.
  1096. *
  1097. ****************************************************************************/
  1098. #ifdef CONFIG_NET_MCASTGROUP
  1099. static int lan91c111_rmmac(FAR struct net_driver_s *dev,
  1100. FAR const uint8_t *mac)
  1101. {
  1102. FAR struct lan91c111_driver_s *priv = dev->d_private;
  1103. uint16_t off, bit;
  1104. uint32_t hash;
  1105. /* Calculate Ethernet CRC32 for MAC */
  1106. hash = lan91c111_crc32(mac, ETHER_ADDR_LEN);
  1107. /* TODO: since the six most significant bits of the CRC from two
  1108. * different destination addresses may have the same value. We
  1109. * need a reference count here to avoid clear the bit prematurely.
  1110. */
  1111. off = (hash >> 29) & 0x06;
  1112. bit = (hash >> 26) & 0x0f;
  1113. /* Remove the MAC address from the hardware multicast routing table */
  1114. net_lock();
  1115. modifyreg16(priv, MCAST_REG1 + off, 1 << bit, 0);
  1116. net_unlock();
  1117. return OK;
  1118. }
  1119. #endif
  1120. /****************************************************************************
  1121. * Name: lan91c111_ipv6multicast
  1122. *
  1123. * Description:
  1124. * Configure the IPv6 multicast MAC address.
  1125. *
  1126. * Parameters:
  1127. * dev - Reference to the NuttX driver state structure
  1128. *
  1129. * Returned Value:
  1130. * Zero (OK) on success; a negated errno value on failure.
  1131. *
  1132. ****************************************************************************/
  1133. #ifdef CONFIG_NET_ICMPv6
  1134. static void lan91c111_ipv6multicast(FAR struct net_driver_s *dev)
  1135. {
  1136. uint16_t tmp16;
  1137. uint8_t mac[6];
  1138. /* For ICMPv6, we need to add the IPv6 multicast address
  1139. *
  1140. * For IPv6 multicast addresses, the Ethernet MAC is derived by
  1141. * the four low-order octets OR'ed with the MAC 33:33:00:00:00:00,
  1142. * so for example the IPv6 address FF02:DEAD:BEEF::1:3 would map
  1143. * to the Ethernet MAC address 33:33:00:01:00:03.
  1144. *
  1145. * NOTES: This appears correct for the ICMPv6 Router Solicitation
  1146. * Message, but the ICMPv6 Neighbor Solicitation message seems to
  1147. * use 33:33:ff:01:00:03.
  1148. */
  1149. mac[0] = 0x33;
  1150. mac[1] = 0x33;
  1151. tmp16 = dev->d_ipv6addr[6];
  1152. mac[2] = 0xff;
  1153. mac[3] = tmp16 >> 8;
  1154. tmp16 = dev->d_ipv6addr[7];
  1155. mac[4] = tmp16 & 0xff;
  1156. mac[5] = tmp16 >> 8;
  1157. ninfo("IPv6 Multicast: %02x:%02x:%02x:%02x:%02x:%02x\n",
  1158. mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  1159. lan91c111_addmac(dev, mac);
  1160. #ifdef CONFIG_NET_ICMPv6_AUTOCONF
  1161. /* Add the IPv6 all link-local nodes Ethernet address. This is the
  1162. * address that we expect to receive ICMPv6 Router Advertisement
  1163. * packets.
  1164. */
  1165. lan91c111_addmac(dev, g_ipv6_ethallnodes.ether_addr_octet);
  1166. #endif /* CONFIG_NET_ICMPv6_AUTOCONF */
  1167. #ifdef CONFIG_NET_ICMPv6_ROUTER
  1168. /* Add the IPv6 all link-local routers Ethernet address. This is the
  1169. * address that we expect to receive ICMPv6 Router Solicitation
  1170. * packets.
  1171. */
  1172. lan91c111_addmac(dev, g_ipv6_ethallrouters.ether_addr_octet);
  1173. #endif /* CONFIG_NET_ICMPv6_ROUTER */
  1174. }
  1175. #endif /* CONFIG_NET_ICMPv6 */
  1176. /****************************************************************************
  1177. * Name: lan91c111_ioctl
  1178. *
  1179. * Description:
  1180. * Handle network IOCTL commands directed to this device.
  1181. *
  1182. * Parameters:
  1183. * dev - Reference to the NuttX driver state structure
  1184. * cmd - The IOCTL command
  1185. * arg - The argument for the IOCTL command
  1186. *
  1187. * Returned Value:
  1188. * OK on success; Negated errno on failure.
  1189. *
  1190. * Assumptions:
  1191. * The network is locked.
  1192. *
  1193. ****************************************************************************/
  1194. #ifdef CONFIG_NETDEV_IOCTL
  1195. static int lan91c111_ioctl(FAR struct net_driver_s *dev, int cmd,
  1196. unsigned long arg)
  1197. {
  1198. FAR struct lan91c111_driver_s *priv = dev->d_private;
  1199. struct mii_ioctl_data_s *req = (void *)arg;
  1200. int ret = OK;
  1201. net_lock();
  1202. /* Decode and dispatch the driver-specific IOCTL command */
  1203. switch (cmd)
  1204. {
  1205. case SIOCGMIIPHY: /* Get MII PHY address */
  1206. req->phy_id = 0;
  1207. break;
  1208. case SIOCGMIIREG: /* Get register from MII PHY */
  1209. req->val_out = getphy(priv, req->reg_num);
  1210. break;
  1211. case SIOCSMIIREG: /* Set register in MII PHY */
  1212. putphy(priv, req->reg_num, req->val_in);
  1213. break;
  1214. default:
  1215. nerr("ERROR: Unrecognized IOCTL command: %d\n", command);
  1216. ret = -ENOTTY; /* Special return value for this case */
  1217. }
  1218. net_unlock();
  1219. return ret;
  1220. }
  1221. #endif
  1222. /****************************************************************************
  1223. * Public Functions
  1224. ****************************************************************************/
  1225. /****************************************************************************
  1226. * Name: lan91c111_initialize
  1227. *
  1228. * Description:
  1229. * Initialize the Ethernet controller and driver
  1230. *
  1231. * Parameters:
  1232. * base - The controller base address
  1233. * irq - The controller irq number
  1234. *
  1235. * Returned Value:
  1236. * OK on success; Negated errno on failure.
  1237. *
  1238. * Assumptions:
  1239. * Called early in initialization before multi-tasking is initiated.
  1240. *
  1241. ****************************************************************************/
  1242. int lan91c111_initialize(uintptr_t base, int irq)
  1243. {
  1244. FAR struct lan91c111_driver_s *priv;
  1245. FAR struct net_driver_s *dev;
  1246. uint16_t macrev;
  1247. uint32_t phyid;
  1248. int ret;
  1249. /* Allocate the interface structure */
  1250. priv = kmm_zalloc(sizeof(*priv));
  1251. if (priv == NULL)
  1252. {
  1253. return -ENOMEM;
  1254. }
  1255. dev = &priv->dev;
  1256. priv->base = base;
  1257. priv->irq = irq;
  1258. /* Check if a Ethernet chip is recognized at its I/O base */
  1259. macrev = getreg16(priv, REV_REG);
  1260. phyid = getphy(priv, MII_PHYID1) << 16;
  1261. phyid |= getphy(priv, MII_PHYID2);
  1262. ninfo("base: %08x irq: %d rev: %04x phy: %08x\n", base, irq, macrev, phyid);
  1263. if ((macrev >> 4 & 0x0f) != CHIP_91111FD || phyid != PHY_LAN83C183)
  1264. {
  1265. nerr("ERROR: Unsupport LAN91C111's MAC/PHY\n");
  1266. ret = -ENODEV;
  1267. goto err;
  1268. }
  1269. /* Attach the IRQ to the driver */
  1270. ret = irq_attach(irq, lan91c111_interrupt, dev);
  1271. if (ret < 0)
  1272. {
  1273. /* We could not attach the ISR to the interrupt */
  1274. goto err;
  1275. }
  1276. /* Initialize the driver structure */
  1277. dev->d_buf = priv->pktbuf; /* Single packet buffer */
  1278. dev->d_ifup = lan91c111_ifup; /* I/F up (new IP address) callback */
  1279. dev->d_ifdown = lan91c111_ifdown; /* I/F down callback */
  1280. dev->d_txavail = lan91c111_txavail; /* New TX data callback */
  1281. #ifdef CONFIG_NET_MCASTGROUP
  1282. dev->d_addmac = lan91c111_addmac; /* Add multicast MAC address */
  1283. dev->d_rmmac = lan91c111_rmmac; /* Remove multicast MAC address */
  1284. #endif
  1285. #ifdef CONFIG_NETDEV_IOCTL
  1286. dev->d_ioctl = lan91c111_ioctl; /* Handle network IOCTL commands */
  1287. #endif
  1288. dev->d_private = priv; /* Used to recover private state from dev */
  1289. /* Create a watchdog for timing polling for transmissions */
  1290. priv->txpoll = wd_create(); /* Create periodic poll timer */
  1291. DEBUGASSERT(priv->txpoll != NULL);
  1292. /* Put the interface in the down state. This usually amounts to resetting
  1293. * the device and/or calling lan91c111_ifdown().
  1294. */
  1295. putreg16(priv, RCR_REG, RCR_SOFTRST);
  1296. up_udelay(10); /* Pause to make the chip happy */
  1297. putreg16(priv, RCR_REG, RCR_CLEAR);
  1298. putreg16(priv, CONFIG_REG, CONFIG_CLEAR);
  1299. lan91c111_command_mmu(priv, MC_RESET);
  1300. putphy(priv, MII_MCR, MII_MCR_RESET);
  1301. while (getphy(priv, MII_MCR) & MII_MCR_RESET)
  1302. {
  1303. /* Loop, reset don't finish yet */
  1304. }
  1305. /* Read the MAC address from the hardware into dev->d_mac.ether.ether_addr_octet */
  1306. copyfrom16(priv, ADDR0_REG, &dev->d_mac.ether, sizeof(dev->d_mac.ether));
  1307. /* Register the device with the OS so that socket IOCTLs can be performed */
  1308. netdev_register(dev, NET_LL_ETHERNET);
  1309. return OK;
  1310. err:
  1311. kmm_free(priv);
  1312. return ret;
  1313. }