nicrtl.c 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033
  1. /*
  2. * Copyright (C) 2001-2005 by egnite Software GmbH. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. *
  32. */
  33. /*!
  34. * \file arch/avr/dev/nicrtl.c
  35. * \brief AVR network driver for RTL8019AS.
  36. *
  37. * \verbatim
  38. * $Id: nicrtl.c 4711 2012-10-07 14:38:49Z haraldkipp $
  39. * \endverbatim
  40. */
  41. #include <cfg/os.h>
  42. #include <cfg/arch/avr.h>
  43. #include <cfg/dev.h>
  44. #include <string.h>
  45. #include <sys/atom.h>
  46. #include <sys/heap.h>
  47. #include <sys/thread.h>
  48. #include <sys/event.h>
  49. #include <sys/timer.h>
  50. #include <sys/confnet.h>
  51. #include <net/ether.h>
  52. #include <net/if_var.h>
  53. #include <dev/irqreg.h>
  54. #include <dev/nicrtl.h>
  55. #include "rtlregs.h"
  56. #ifdef NUTDEBUG
  57. #include <sys/osdebug.h>
  58. #include <net/netdebug.h>
  59. #endif
  60. #ifndef NUT_THREAD_NICRXSTACK
  61. #define NUT_THREAD_NICRXSTACK 256
  62. #endif
  63. /*
  64. * Determine ports, which had not been explicitely configured.
  65. */
  66. #if (RTL_RESET_AVRPORT == AVRPORTB)
  67. #define RTL_RESET_PORT PORTB
  68. #define RTL_RESET_DDR DDRB
  69. #elif (RTL_RESET_AVRPORT == AVRPORTD)
  70. #define RTL_RESET_PORT PORTD
  71. #define RTL_RESET_DDR DDRD
  72. #elif (RTL_RESET_AVRPORT == AVRPORTE)
  73. #define RTL_RESET_PORT PORTE
  74. #define RTL_RESET_DDR DDRE
  75. #elif (RTL_RESET_AVRPORT == AVRPORTF)
  76. #define RTL_RESET_PORT PORTF
  77. #define RTL_RESET_DDR DDRF
  78. #endif /* RTL_RESET_AVRPORT */
  79. /*!
  80. * \brief Interrupt used.
  81. */
  82. #if (RTL_SIGNAL_IRQ == INT0)
  83. #define RTL_SIGNAL sig_INTERRUPT0
  84. #ifdef __AVR_ENHANCED__
  85. #define RTL_RISING_EDGE_MODE() sbi(EICRA, ISC00); sbi(EICRA, ISC01)
  86. #endif
  87. #elif (RTL_SIGNAL_IRQ == INT1)
  88. #define RTL_SIGNAL sig_INTERRUPT1
  89. #ifdef __AVR_ENHANCED__
  90. #define RTL_RISING_EDGE_MODE() sbi(EICRA, ISC10); sbi(EICRA, ISC11)
  91. #endif
  92. #elif (RTL_SIGNAL_IRQ == INT2)
  93. #define RTL_SIGNAL sig_INTERRUPT2
  94. #ifdef __AVR_ENHANCED__
  95. #define RTL_RISING_EDGE_MODE() sbi(EICRA, ISC20); sbi(EICRA, ISC21)
  96. #endif
  97. #elif (RTL_SIGNAL_IRQ == INT3)
  98. #define RTL_SIGNAL sig_INTERRUPT3
  99. #ifdef __AVR_ENHANCED__
  100. #define RTL_RISING_EDGE_MODE() sbi(EICRA, ISC30); sbi(EICRA, ISC31)
  101. #endif
  102. #elif (RTL_SIGNAL_IRQ == INT4)
  103. #define RTL_SIGNAL sig_INTERRUPT4
  104. #ifdef __AVR_ENHANCED__
  105. #define RTL_RISING_EDGE_MODE() sbi(EICRB, ISC40); sbi(EICRB, ISC41)
  106. #endif
  107. #elif (RTL_SIGNAL_IRQ == INT6)
  108. #define RTL_SIGNAL sig_INTERRUPT6
  109. #ifdef __AVR_ENHANCED__
  110. #define RTL_RISING_EDGE_MODE() sbi(EICRB, ISC60); sbi(EICRB, ISC61)
  111. #endif
  112. #elif (RTL_SIGNAL_IRQ == INT7)
  113. #define RTL_SIGNAL sig_INTERRUPT7
  114. #ifdef __AVR_ENHANCED__
  115. #define RTL_RISING_EDGE_MODE() sbi(EICRB, ISC70); sbi(EICRB, ISC71)
  116. #endif
  117. #else
  118. #define RTL_SIGNAL sig_INTERRUPT5
  119. #ifdef __AVR_ENHANCED__
  120. #define RTL_RISING_EDGE_MODE() sbi(EICRB, ISC50); sbi(EICRB, ISC51)
  121. #endif
  122. #endif /* RTL_SIGNAL_IRQ */
  123. /*!
  124. * \brief Size of a single ring buffer page.
  125. */
  126. #define NIC_PAGE_SIZE 0x100
  127. /*!
  128. * \brief First ring buffer page address.
  129. */
  130. #define NIC_START_PAGE 0x40
  131. /*!
  132. * \brief Last ring buffer page address plus 1.
  133. */
  134. #define NIC_STOP_PAGE 0x60
  135. /*!
  136. * \brief Number of pages in a single transmit buffer.
  137. *
  138. * This should be at least the MTU size.
  139. */
  140. #define NIC_TX_PAGES 6
  141. /*!
  142. * \brief Number of transmit buffers.
  143. *
  144. * The initial value had been 2. The idea was to use two alternating
  145. * buffers. However, this had never been implemented and we took over
  146. * Bengt Florin's change, defining 1 transmit buffer only and give
  147. * more buffer space to the receiver.
  148. *
  149. * The controller memory layout is now
  150. *
  151. * - 0x4000..0x45ff 1.5K bytes transmit buffer
  152. * - 0x4600..0x5fff 6.5K bytes receive buffer
  153. *
  154. * The routines are still not using the buffers in an optimal way,
  155. * as transmission is limited to 1 packet at a time. In fact several
  156. * smaller packets would fit into the 1.5 kByte buffer. On the other
  157. * hand, filling the buffer with more than one transmission packet
  158. * may result in other bad effects, like pulling the IORDY line more
  159. * often.
  160. */
  161. #define NIC_TX_BUFFERS 1
  162. #define NIC_FIRST_TX_PAGE NIC_START_PAGE
  163. #define NIC_FIRST_RX_PAGE (NIC_FIRST_TX_PAGE + NIC_TX_PAGES * NIC_TX_BUFFERS)
  164. #define NIC_CR_PAGE0 (0)
  165. #define NIC_CR_PAGE1 (NIC_CR_PS0)
  166. #define NIC_CR_PAGE2 (NIC_CR_PS1)
  167. #define NIC_CR_PAGE3 (NIC_CR_PS1 | NIC_CR_PS0)
  168. /*
  169. * This delay has been added by Bengt Florin and is used to minimize
  170. * the effect of the IORDY line during reads. Bengt contributed a
  171. * more versatile loop, which unfortunately wasn't portable to the
  172. * ImageCraft compiler.
  173. *
  174. * Both versions depend on the CPU clock and had been tested with
  175. * 14.7456 MHz.
  176. */
  177. static INLINE void Delay16Cycles(void)
  178. {
  179. _NOP();
  180. _NOP();
  181. _NOP();
  182. _NOP();
  183. _NOP();
  184. _NOP();
  185. _NOP();
  186. _NOP();
  187. _NOP();
  188. _NOP();
  189. _NOP();
  190. _NOP();
  191. _NOP();
  192. _NOP();
  193. _NOP();
  194. _NOP();
  195. }
  196. /*!
  197. * \addtogroup xgNicRtl
  198. */
  199. /*@{*/
  200. /*!
  201. * Realtek packet header.
  202. */
  203. struct nic_pkt_header {
  204. uint8_t ph_status; /*!< \brief Status, contents of RSR register */
  205. uint8_t ph_nextpg; /*!< \brief Page for next packet */
  206. uint16_t ph_size; /*!< \brief Size of header and packet in octets */
  207. };
  208. #define NICINB(reg) (*((volatile uint8_t *)RTL_BASE_ADDR + reg))
  209. #define NICOUTB(reg, val) (*((volatile uint8_t *)RTL_BASE_ADDR + reg) = val)
  210. /*!
  211. * \brief Reset the Ethernet controller.
  212. *
  213. */
  214. static int NicReset(void)
  215. {
  216. uint8_t i;
  217. uint8_t j;
  218. /*
  219. * Toggle the hardware reset line. Since Ethernut version 1.3 the
  220. * hardware reset pin of the nic is no longer connected to bit 4
  221. * on port E, but wired to the board reset line.
  222. */
  223. #ifdef RTL_RESET_BIT
  224. sbi(RTL_RESET_DDR, RTL_RESET_BIT);
  225. sbi(RTL_RESET_PORT, RTL_RESET_BIT);
  226. NutDelay(WAIT100);
  227. cbi(RTL_RESET_PORT, RTL_RESET_BIT);
  228. NutDelay(WAIT250);
  229. NutDelay(WAIT250);
  230. #endif
  231. /*
  232. * Do the software reset by reading from the reset register followed
  233. * by writing to the reset register. Wait until the controller enters
  234. * the reset state.
  235. */
  236. for (j = 0; j < 20; j++) {
  237. i = NICINB(NIC_RESET);
  238. NutDelay(WAIT5);
  239. NICOUTB(NIC_RESET, i);
  240. for (i = 0; i < 20; i++) {
  241. NutDelay(WAIT50);
  242. /*
  243. * We got the reset bit. However, Ethernut 1.1 may
  244. * still fail because the NIC hasn't got it's hardware
  245. * reset and the data lines remain in tristate. So we
  246. * read noise instead of the register. To solve this
  247. * problem, we will verify the NIC's id.
  248. */
  249. if ((NICINB(NIC_PG0_ISR) & NIC_ISR_RST) != 0 && /* */
  250. NICINB(NIC_PG0_RBCR0) == 0x50 && /* */
  251. NICINB(NIC_PG0_RBCR1) == 0x70)
  252. return 0;
  253. }
  254. }
  255. return -1;
  256. }
  257. /*
  258. * Fires up the network interface. NIC interrupts
  259. * should have been disabled when calling this
  260. * function.
  261. */
  262. static int NicStart(const uint8_t * mac)
  263. {
  264. uint8_t i;
  265. if (NicReset()) {
  266. return -1;
  267. }
  268. /*
  269. * Mask all interrupts and clear any interrupt status flag to set the
  270. * INT pin back to low.
  271. */
  272. NICOUTB(NIC_PG0_IMR, 0);
  273. NICOUTB(NIC_PG0_ISR, 0xff);
  274. /*
  275. * During reset the nic loaded its initial configuration from an
  276. * external eeprom. On the ethernut board we do not have any
  277. * configuration eeprom, but simply tied the eeprom data line to
  278. * high level. So we have to clear some bits in the configuration
  279. * register. Switch to register page 3.
  280. */
  281. NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);
  282. /*
  283. * The nic configuration registers are write protected unless both
  284. * EEM bits are set to 1.
  285. */
  286. NICOUTB(NIC_PG3_EECR, NIC_EECR_EEM0 | NIC_EECR_EEM1);
  287. /*
  288. * Network media had been set to 10Base2 by the virtual EEPROM and
  289. * will be set now to auto detect. This will initiate a link test.
  290. * We don't force 10BaseT, because this would disable the link test.
  291. */
  292. NICOUTB(NIC_PG3_CONFIG2, NIC_CONFIG2_BSELB);
  293. /*
  294. * Disable sleep and power down.
  295. *
  296. * The virtual EEPROM (resistor tight to VCC) will set all bits of
  297. * CONFIG3 to 1. Unfortunately we are not able to modify the full
  298. * duplex bit. The only solution is to use a real EEPROM or emulate
  299. * one.
  300. */
  301. NICOUTB(NIC_PG3_CONFIG3, NIC_CONFIG3_LEDS1 | NIC_CONFIG3_LEDS1);
  302. /*
  303. * Reenable write protection of the nic configuration registers
  304. * and wait for link test to complete.
  305. */
  306. NICOUTB(NIC_PG3_EECR, 0);
  307. NutDelay(255);
  308. /*
  309. * Switch to register page 0 and set data configuration register
  310. * to byte-wide DMA transfers, normal operation (no loopback),
  311. * send command not executed and 8 byte fifo threshold.
  312. */
  313. NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2);
  314. NICOUTB(NIC_PG0_DCR, NIC_DCR_LS | NIC_DCR_FT1);
  315. /*
  316. * Clear remote dma byte count register.
  317. */
  318. NICOUTB(NIC_PG0_RBCR0, 0);
  319. NICOUTB(NIC_PG0_RBCR1, 0);
  320. /*
  321. * Temporarily set receiver to monitor mode and transmitter to
  322. * internal loopback mode. Incoming packets will not be stored
  323. * in the nic ring buffer and no data will be send to the network.
  324. */
  325. NICOUTB(NIC_PG0_RCR, NIC_RCR_MON);
  326. NICOUTB(NIC_PG0_TCR, NIC_TCR_LB0);
  327. /*
  328. * Configure the nic's ring buffer page layout.
  329. * NIC_PG0_BNRY: Last page read.
  330. * NIC_PG0_PSTART: First page of receiver buffer.
  331. * NIC_PG0_PSTOP: Last page of receiver buffer.
  332. */
  333. NICOUTB(NIC_PG0_TPSR, NIC_FIRST_TX_PAGE);
  334. NICOUTB(NIC_PG0_BNRY, NIC_STOP_PAGE - 1);
  335. NICOUTB(NIC_PG0_PSTART, NIC_FIRST_RX_PAGE);
  336. NICOUTB(NIC_PG0_PSTOP, NIC_STOP_PAGE);
  337. /*
  338. * Once again clear interrupt status register.
  339. */
  340. NICOUTB(NIC_PG0_ISR, 0xff);
  341. /*
  342. * Switch to register page 1 and copy our MAC address into the nic.
  343. * We are still in stop mode.
  344. */
  345. NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0);
  346. for (i = 0; i < 6; i++)
  347. NICOUTB(NIC_PG1_PAR0 + i, mac[i]);
  348. /*
  349. * Clear multicast filter bits to disable all packets.
  350. */
  351. for (i = 0; i < 8; i++)
  352. NICOUTB(NIC_PG1_MAR0 + i, 0);
  353. /*
  354. * Set current page pointer to one page after the boundary pointer.
  355. */
  356. NICOUTB(NIC_PG1_CURR, NIC_FIRST_RX_PAGE);
  357. /*
  358. * Switch back to register page 0, remaining in stop mode.
  359. */
  360. NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2);
  361. /*
  362. * Take receiver out of monitor mode and enable it for accepting
  363. * broadcasts.
  364. */
  365. NICOUTB(NIC_PG0_RCR, NIC_RCR_AB);
  366. /*
  367. * Clear all interrupt status flags and enable interrupts.
  368. */
  369. NICOUTB(NIC_PG0_ISR, 0xff);
  370. /* Note: transmitter if polled, thus no NIC_IMR_PTXE */
  371. NICOUTB(NIC_PG0_IMR, NIC_IMR_PRXE | NIC_IMR_RXEE | NIC_IMR_TXEE | NIC_IMR_OVWE);
  372. /*
  373. * Fire up the nic by clearing the stop bit and setting the start bit.
  374. * To activate the local receive dma we must also take the nic out of
  375. * the local loopback mode.
  376. */
  377. NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
  378. NICOUTB(NIC_PG0_TCR, 0);
  379. NutDelay(255);
  380. return 0;
  381. }
  382. /*!
  383. * Complete remote DMA.
  384. */
  385. static void NicCompleteDma(void)
  386. {
  387. uint8_t i;
  388. /*
  389. * Complete remote dma.
  390. */
  391. NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
  392. /*
  393. * Check that we have a DMA complete flag.
  394. */
  395. for (i = 0; i <= 20; i++)
  396. if (NICINB(NIC_PG0_ISR) & NIC_ISR_RDC)
  397. break;
  398. /*
  399. * Reset remote dma complete flag.
  400. */
  401. NICOUTB(NIC_PG0_ISR, NIC_ISR_RDC);
  402. }
  403. /*
  404. * Write data block to the NIC.
  405. */
  406. static void NicWrite(uint8_t * buf, uint16_t len)
  407. {
  408. register uint16_t l = len - 1;
  409. register uint8_t ih = (uint16_t) l >> 8;
  410. register uint8_t il = (uint8_t) l;
  411. if (!len)
  412. return;
  413. do {
  414. do {
  415. NICOUTB(NIC_IOPORT, *buf++);
  416. } while (il-- != 0);
  417. } while (ih-- != 0);
  418. }
  419. /*
  420. * Read data block from the NIC.
  421. */
  422. static void NicRead(uint8_t * buf, uint16_t len)
  423. {
  424. register uint16_t l = len - 1;
  425. register uint8_t ih = (uint16_t) l >> 8;
  426. register uint8_t il = (uint8_t) l;
  427. if (!len)
  428. return;
  429. do {
  430. do {
  431. *buf++ = NICINB(NIC_IOPORT);
  432. } while (il-- != 0);
  433. } while (ih-- != 0);
  434. }
  435. /*!
  436. * \brief Load a packet into the nic's transmit ring buffer.
  437. *
  438. *
  439. * \param base NIC hardware base address.
  440. * \param nb Network buffer structure containing the packet to be sent.
  441. * The structure must have been allocated by a previous
  442. * call NutNetBufAlloc().
  443. *
  444. * \return 0 on success, -1 in case of any errors. Errors
  445. * will automatically release the network buffer
  446. * structure.
  447. */
  448. static int NicPutPacket(NETBUF * nb)
  449. {
  450. uint16_t sz;
  451. uint16_t i;
  452. uint8_t padding = 0;
  453. /*
  454. * Calculate the number of bytes to be send. Do not
  455. * send packets larger than 1514 bytes.
  456. *
  457. * The previous version was wrong by specifying a maximum
  458. * of 1518, because it didn't take the CRC into account,
  459. * which is generated by the hardware and automatically
  460. * appended. Thanks to Bengt Florin, who discovered this.
  461. */
  462. sz = nb->nb_dl.sz + nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz;
  463. if (sz > 1514)
  464. return -1;
  465. /*
  466. * The controller will not append pad bytes,
  467. * so we have to do this.
  468. */
  469. if (sz < 60) {
  470. padding = (uint8_t) (60 - sz);
  471. sz = 60;
  472. }
  473. /*
  474. * Bengt Florin introduces polling mode for the transmitter. Be
  475. * aware, that this may introduce other problems. If a high
  476. * priority thread is waiting for the transmitter, it may hold
  477. * the CPU for more than 1.2 milliseconds in worst cases.
  478. */
  479. while (NICINB(NIC_CR) & NIC_CR_TXP)
  480. NutThreadYield();
  481. /* we don't want to be interrupted by NIC owerflow */
  482. cbi(EIMSK, RTL_SIGNAL_IRQ);
  483. /*
  484. * Set remote dma byte count
  485. * and start address.
  486. */
  487. NICOUTB(NIC_PG0_RBCR0, sz);
  488. NICOUTB(NIC_PG0_RBCR1, sz >> 8);
  489. NICOUTB(NIC_PG0_RSAR0, 0);
  490. NICOUTB(NIC_PG0_RSAR1, NIC_FIRST_TX_PAGE);
  491. /*
  492. * Peform the write.
  493. */
  494. NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD1);
  495. /*
  496. * Transfer the Ethernet frame.
  497. */
  498. NicWrite(nb->nb_dl.vp, nb->nb_dl.sz);
  499. NicWrite(nb->nb_nw.vp, nb->nb_nw.sz);
  500. NicWrite(nb->nb_tp.vp, nb->nb_tp.sz);
  501. NicWrite(nb->nb_ap.vp, nb->nb_ap.sz);
  502. /*
  503. * Add pad bytes.
  504. */
  505. for (i = 0; i < padding; i++)
  506. NICOUTB(NIC_IOPORT, 0);
  507. /*
  508. * Complete remote dma.
  509. */
  510. NicCompleteDma();
  511. /*
  512. * Number of bytes to be transmitted.
  513. */
  514. NICOUTB(NIC_PG0_TBCR0, (sz & 0xff));
  515. NICOUTB(NIC_PG0_TBCR1, ((sz >> 8) & 0xff));
  516. /*
  517. * First page of packet to be transmitted.
  518. */
  519. NICOUTB(NIC_PG0_TPSR, NIC_FIRST_TX_PAGE);
  520. /*
  521. * Start transmission.
  522. */
  523. NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_TXP | NIC_CR_RD2);
  524. sbi(EIMSK, RTL_SIGNAL_IRQ);
  525. return 0;
  526. }
  527. /*!
  528. * \brief Fetch the next packet out of the receive ring buffer.
  529. *
  530. * Nic interrupts must be disabled when calling this funtion.
  531. *
  532. * \return Pointer to an allocated ::NETBUF. If there is no
  533. * no data available, then the function returns a
  534. * null pointer. If the NIC's buffer seems to be
  535. * corrupted, a pointer to 0xFFFF is returned.
  536. */
  537. static NETBUF *NicGetPacket(void)
  538. {
  539. NETBUF *nb = 0;
  540. struct nic_pkt_header hdr;
  541. uint16_t count;
  542. uint8_t *buf;
  543. uint8_t nextpg;
  544. uint8_t bnry;
  545. uint8_t curr;
  546. uint16_t i;
  547. uint8_t drop = 0;
  548. /* we don't want to be interrupted by NIC owerflow */
  549. cbi(EIMSK, RTL_SIGNAL_IRQ);
  550. /*
  551. * Get the current page pointer. It points to the page where the NIC
  552. * will start saving the next incoming packet.
  553. */
  554. NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD2 | NIC_CR_PS0);
  555. Delay16Cycles();
  556. curr = NICINB(NIC_PG1_CURR);
  557. NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
  558. /*
  559. * Get the pointer to the last page we read from. The following page
  560. * is the one where we start reading. If it's equal to the current
  561. * page pointer, then there's nothing to read. In this case we return
  562. * a null pointer.
  563. */
  564. if ((bnry = NICINB(NIC_PG0_BNRY) + 1) >= NIC_STOP_PAGE)
  565. bnry = NIC_FIRST_RX_PAGE;
  566. if (bnry == curr) {
  567. sbi(EIMSK, RTL_SIGNAL_IRQ);
  568. return 0;
  569. }
  570. /*
  571. * Read the NIC specific packet header.
  572. */
  573. NICOUTB(NIC_PG0_RBCR0, sizeof(struct nic_pkt_header));
  574. NICOUTB(NIC_PG0_RBCR1, 0);
  575. NICOUTB(NIC_PG0_RSAR0, 0);
  576. NICOUTB(NIC_PG0_RSAR1, bnry);
  577. buf = (uint8_t *) & hdr;
  578. NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD0);
  579. Delay16Cycles();
  580. for (i = 0; i < sizeof(struct nic_pkt_header); i++)
  581. *buf++ = NICINB(NIC_IOPORT);
  582. NicCompleteDma();
  583. /*
  584. * Check packet length. Silently discard packets of illegal size.
  585. */
  586. if (hdr.ph_size < 60 + sizeof(struct nic_pkt_header) || /* */
  587. hdr.ph_size > 1514 + sizeof(struct nic_pkt_header)) {
  588. drop = 1;
  589. }
  590. /*
  591. * Calculate the page of the next packet. If it differs from the
  592. * pointer in the packet header, we return with errorcode.
  593. */
  594. nextpg = bnry + (hdr.ph_size >> 8) + ((hdr.ph_size & 0xFF) != 0);
  595. if (nextpg >= NIC_STOP_PAGE) {
  596. nextpg -= NIC_STOP_PAGE;
  597. nextpg += NIC_FIRST_RX_PAGE;
  598. }
  599. if (nextpg != hdr.ph_nextpg) {
  600. uint8_t nextpg1 = nextpg + 1;
  601. if (nextpg1 >= NIC_STOP_PAGE) {
  602. nextpg1 -= NIC_STOP_PAGE;
  603. nextpg1 += NIC_FIRST_RX_PAGE;
  604. }
  605. if (nextpg1 != hdr.ph_nextpg) {
  606. sbi(EIMSK, RTL_SIGNAL_IRQ);
  607. return (NETBUF *) 0xFFFF;
  608. }
  609. nextpg = nextpg1;
  610. }
  611. /*
  612. * Check packet status. It should have set bit 0, but
  613. * even without this bit packets seem to be OK.
  614. */
  615. if (!drop && ((hdr.ph_status & 0x0E) == 0)) {
  616. /*
  617. * Allocate a NETBUF.
  618. * Omit the fcs.
  619. */
  620. count = hdr.ph_size - 4;
  621. if ((nb = NutNetBufAlloc(0, NBAF_DATALINK, count))) {
  622. /*
  623. * Set remote dma byte count and
  624. * start address. Don't read the
  625. * header again.
  626. */
  627. NICOUTB(NIC_PG0_RBCR0, count);
  628. NICOUTB(NIC_PG0_RBCR1, count >> 8);
  629. NICOUTB(NIC_PG0_RSAR0, sizeof(struct nic_pkt_header));
  630. NICOUTB(NIC_PG0_RSAR1, bnry);
  631. /*
  632. * Perform the read.
  633. */
  634. NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD0);
  635. Delay16Cycles();
  636. NicRead(nb->nb_dl.vp, count);
  637. NicCompleteDma();
  638. }
  639. }
  640. /*
  641. * Set boundary register to the last page we read.
  642. * This also drops packets with errors
  643. */
  644. if (--nextpg < NIC_FIRST_RX_PAGE)
  645. nextpg = NIC_STOP_PAGE - 1;
  646. NICOUTB(NIC_PG0_BNRY, nextpg);
  647. sbi(EIMSK, RTL_SIGNAL_IRQ);
  648. return nb;
  649. }
  650. /*
  651. * \brief Handle NIC overflows.
  652. *
  653. * When a receiver buffer overflow occurs, the NIC will defer any subsequent
  654. * action until properly restarted.
  655. *
  656. * This routine is called within interrupt context, which introduces a big
  657. * problem. It waits for the last transmission to finish, which may take
  658. * several milliseconds. Since Nut/OS 3.5, we do not support nested interrupts
  659. * on AVR systems anymore. So this routine may now increase interrupt
  660. * latency in an unacceptable way. The solution might be to handle overflows
  661. * in the receiver thread.
  662. *
  663. * In any case, this routines needs a major redesign. But it has been
  664. * tested in its current form to gracefully withstand ping floods. Thanks
  665. * to Bengt Florin for contributing his code, which provides much more
  666. * stability than its predecessor.
  667. */
  668. static uint8_t NicOverflow(void)
  669. {
  670. uint8_t cr;
  671. uint8_t resend = 0;
  672. uint8_t curr;
  673. /*
  674. * Wait for any transmission in progress. Save the command register,
  675. * so we can later determine, if NIC transmitter has been interrupted.
  676. * or reception in progress.
  677. */
  678. while (NICINB(NIC_CR) & NIC_CR_TXP);
  679. cr = NICINB(NIC_CR);
  680. /*
  681. * Get the current page pointer. It points to the page where the NIC
  682. * will start saving the next incoming packet.
  683. */
  684. NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0);
  685. curr = NICINB(NIC_PG1_CURR);
  686. NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2);
  687. /* Clear remote byte count register. */
  688. NICOUTB(NIC_PG0_RBCR0, 0);
  689. NICOUTB(NIC_PG0_RBCR1, 0);
  690. /* Check for any incomplete transmission. */
  691. if ((cr & NIC_CR_TXP) && ((NICINB(NIC_PG0_ISR) & (NIC_ISR_PTX | NIC_ISR_TXE)) == 0)) {
  692. resend = 1;
  693. }
  694. /* Enter loopback mode and restart the NIC. */
  695. NICOUTB(NIC_PG0_TCR, NIC_TCR_LB0);
  696. NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
  697. /*
  698. * Discard all packets from the receiver buffer. Set boundary
  699. * register to the last page we read.
  700. */
  701. if (--curr < NIC_FIRST_RX_PAGE) {
  702. curr = NIC_STOP_PAGE - 1;
  703. }
  704. NICOUTB(NIC_PG0_BNRY, curr);
  705. /* Switch from loopback to normal mode mode. */
  706. NICOUTB(NIC_PG0_TCR, 0);
  707. /* Re-invoke any interrupted transmission. */
  708. if (resend) {
  709. NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_TXP | NIC_CR_RD2);
  710. }
  711. /* Finally clear the overflow flag */
  712. NICOUTB(NIC_PG0_ISR, NIC_ISR_OVW);
  713. return resend;
  714. }
  715. /*
  716. * \brief NIC interrupt entry.
  717. */
  718. static void NicInterrupt(void *arg)
  719. {
  720. uint8_t isr;
  721. NICINFO *ni = (NICINFO *) ((NUTDEVICE *) arg)->dev_dcb;
  722. ni->ni_interrupts++;
  723. #ifdef RTL_IRQ_RISING_EDGE
  724. do
  725. {
  726. #endif
  727. isr = NICINB(NIC_PG0_ISR);
  728. NICOUTB(NIC_PG0_ISR, isr);
  729. /*
  730. * Recover from receive buffer overflow. This may take some
  731. * time, so we enable global interrupts but keep NIC
  732. * interrupts disabled.
  733. */
  734. if (isr & NIC_ISR_OVW) {
  735. /* The AVR platform uses a dedicated interrupt stack, which
  736. * forbids interrupt nesting. */
  737. #if !defined(__AVR__)
  738. cbi(EIMSK, RTL_SIGNAL_IRQ);
  739. sei();
  740. #endif
  741. NicOverflow();
  742. #if !defined(__AVR__)
  743. cli();
  744. sbi(EIMSK, RTL_SIGNAL_IRQ);
  745. #endif
  746. ni->ni_rx_overruns++;
  747. } else {
  748. /*
  749. * If this is a transmit interrupt, then a packet has been sent.
  750. * So we can clear the transmitter busy flag and wake up the
  751. * transmitter thread.
  752. */
  753. if (isr & NIC_ISR_TXE)
  754. ni->ni_tx_errors++;
  755. /*
  756. * If this is a receive interrupt, then wake up the receiver
  757. * thread.
  758. */
  759. if (isr & NIC_ISR_PRX)
  760. NutEventPostFromIrq(&ni->ni_rx_rdy);
  761. if (isr & NIC_ISR_RXE) {
  762. ni->ni_rx_frame_errors += NICINB(NIC_PG0_CNTR0);
  763. ni->ni_rx_crc_errors += NICINB(NIC_PG0_CNTR1);
  764. ni->ni_rx_missed_errors += NICINB(NIC_PG0_CNTR2);
  765. }
  766. }
  767. #ifdef RTL_IRQ_RISING_EDGE
  768. /* Check that all unmasked interrupts are cleared before we
  769. * leave the ISR to assert the INT line goes back to low
  770. * and a new interrupt edge will be generated for following
  771. * interrupts.
  772. */
  773. }
  774. while (bit_is_set(PINE, RTL_SIGNAL_IRQ));
  775. #endif
  776. }
  777. /*! \fn NicRx(void *arg)
  778. * \brief NIC receiver thread.
  779. *
  780. *
  781. * It runs with high priority.
  782. */
  783. THREAD(NicRx, arg)
  784. {
  785. NUTDEVICE *dev;
  786. IFNET *ifn;
  787. NICINFO *ni;
  788. NETBUF *nb;
  789. dev = arg;
  790. ifn = (IFNET *) dev->dev_icb;
  791. ni = (NICINFO *) dev->dev_dcb;
  792. NutThreadSetPriority(9);
  793. /*
  794. * This is a temporary hack. Due to a change in initialization,
  795. * we may not have got a MAC address yet. Wait until one has been
  796. * set.
  797. */
  798. if ((ifn->if_mac[0] & ifn->if_mac[1] & ifn->if_mac[2]) == 0xFF) {
  799. while ((ifn->if_mac[0] & ifn->if_mac[1] & ifn->if_mac[2]) == 0xFF)
  800. NutSleep(125);
  801. cbi(EIMSK, RTL_SIGNAL_IRQ);
  802. NicStart(ifn->if_mac);
  803. sbi(EIMSK, RTL_SIGNAL_IRQ);
  804. }
  805. while (1) {
  806. NutEventWait(&ni->ni_rx_rdy, 0);
  807. /*
  808. * Fetch all packets from the NIC's internal
  809. * buffer and pass them to the registered handler.
  810. */
  811. do {
  812. nb = NicGetPacket();
  813. /* The sanity check may fail because the controller is too busy.
  814. restart the NIC. */
  815. if ((uint16_t) nb == 0xFFFF) {
  816. NicStart(ifn->if_mac);
  817. ni->ni_rx_size_errors++;
  818. } else if (nb) {
  819. ni->ni_rx_packets++;
  820. (*ifn->if_recv) (dev, nb);
  821. }
  822. } while (nb);
  823. }
  824. }
  825. /*!
  826. * \brief Send Ethernet packet.
  827. *
  828. * \param dev Identifies the device to use.
  829. * \param nb Network buffer structure containing the packet to be sent.
  830. * The structure must have been allocated by a previous
  831. * call NutNetBufAlloc().
  832. *
  833. * \return 0 on success, -1 in case of any errors.
  834. */
  835. int NicOutput(NUTDEVICE * dev, NETBUF * nb)
  836. {
  837. int rc = -1;
  838. NICINFO *ni = (NICINFO *) dev->dev_dcb;
  839. if (NicPutPacket(nb) == 0) {
  840. ni->ni_tx_packets++;
  841. rc = 0;
  842. }
  843. return rc;
  844. }
  845. /*!
  846. * \brief Initialize Ethernet hardware.
  847. *
  848. * Resets RTL8019AS Ethernet controller, initializes all required
  849. * hardware registers and starts a background thread for incoming
  850. * Ethernet traffic.
  851. *
  852. * Applications should do not directly call this function. It is
  853. * automatically executed during during device registration by
  854. * NutRegisterDevice(). Note, that base address and interrupt number
  855. * passed to NutRegisterDevice() are silently ignored by this driver
  856. * for performance reasons. These values can be changed only by
  857. * using the Nut/OS Configurator to rebuild the system.
  858. *
  859. * If the network configuration hasn't been set by the application
  860. * before registering the specified device, this function will
  861. * call NutNetLoadConfig() to get the MAC address.
  862. *
  863. * \param dev Identifies the device to initialize.
  864. */
  865. int NicInit(NUTDEVICE * dev)
  866. {
  867. IFNET *ifn;
  868. NICINFO *ni;
  869. /*
  870. * We need to know our MAC address. If no configuration is
  871. * available, load it now.
  872. */
  873. if (confnet.cd_size == 0)
  874. NutNetLoadConfig(dev->dev_name);
  875. ifn = dev->dev_icb;
  876. memcpy(ifn->if_mac, confnet.cdn_mac, 6);
  877. ni = (NICINFO *) dev->dev_dcb;
  878. memset(ni, 0, sizeof(NICINFO));
  879. /*
  880. * Start the receiver thread.
  881. */
  882. NutThreadCreate("rxi5", NicRx, dev,
  883. (NUT_THREAD_NICRXSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
  884. NutSleep(WAIT500);
  885. /*
  886. * Register interrupt handler and enable interrupts.
  887. */
  888. if (NutRegisterIrqHandler(&RTL_SIGNAL, NicInterrupt, dev))
  889. return -1;
  890. cbi(EIMSK, RTL_SIGNAL_IRQ);
  891. #ifdef RTL_IRQ_RISING_EDGE
  892. /* Support of rising edge interrupts for HW w/o inverter gate */
  893. RTL_RISING_EDGE_MODE();
  894. #endif
  895. if (ifn->if_mac[0] | ifn->if_mac[1] | ifn->if_mac[2])
  896. if (NicStart(ifn->if_mac))
  897. return -1;
  898. sbi(EIMSK, RTL_SIGNAL_IRQ);
  899. return 0;
  900. }
  901. /*@}*/