nicrtl.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982
  1. /*
  2. * Copyright (C) 2001-2004 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 EGNITE SOFTWARE GMBH 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 EGNITE
  21. * SOFTWARE GMBH 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. * $Log$
  35. * Revision 1.1 2005/07/26 18:02:40 haraldkipp
  36. * Moved from dev.
  37. *
  38. * Revision 1.4 2005/04/30 16:42:41 chaac
  39. * Fixed bug in handling of NUTDEBUG. Added include for cfg/os.h. If NUTDEBUG
  40. * is defined in NutConf, it will make effect where it is used.
  41. *
  42. * Revision 1.3 2005/01/24 21:11:52 freckle
  43. * renamed NutEventPostFromIRQ into NutEventPostFromIrq
  44. *
  45. * Revision 1.2 2005/01/21 16:49:46 freckle
  46. * Seperated calls to NutEventPostAsync between Threads and IRQs
  47. *
  48. * Revision 1.1 2004/03/16 16:48:27 haraldkipp
  49. * Added Jan Dubiec's H8/300 port.
  50. *
  51. */
  52. #include <cfg/os.h>
  53. #include <string.h>
  54. #include <sys/nutconfig.h>
  55. #include <sys/atom.h>
  56. #include <sys/heap.h>
  57. #include <sys/thread.h>
  58. #include <sys/event.h>
  59. #include <sys/timer.h>
  60. #include <sys/confnet.h>
  61. #include <netinet/if_ether.h>
  62. #include <net/ether.h>
  63. #include <net/if_var.h>
  64. #include <dev/irqreg.h>
  65. #include <dev/nicrtl.h>
  66. #include "rtlregs.h"
  67. #ifdef NUTDEBUG
  68. #include <sys/osdebug.h>
  69. #include <net/netdebug.h>
  70. #endif
  71. /*!
  72. * \brief Read word from controller DMA port.
  73. */
  74. #define nic_read_dma() *((volatile u_short*) (base + NIC_IOPORT))
  75. /*!
  76. * \brief Write word to controller DMA port.
  77. */
  78. #define nic_write_dma(data) *((u_short*) (base + NIC_IOPORT)) = data
  79. /*!
  80. * \brief Size of a single ring buffer page.
  81. */
  82. #define NIC_PAGE_SIZE 0x100
  83. /*!
  84. * \brief First ring buffer page address.
  85. */
  86. #define NIC_START_PAGE 0x40
  87. /*!
  88. * \brief Last ring buffer page address plus 1.
  89. */
  90. #define NIC_STOP_PAGE 0x60
  91. /*!
  92. * \brief Number of pages in a single transmit buffer.
  93. *
  94. * This should be at least the MTU size.
  95. */
  96. #define NIC_TX_PAGES 6
  97. /*!
  98. * \brief Number of transmit buffers.
  99. */
  100. #define NIC_TX_BUFFERS 2
  101. /*!
  102. * \brief Controller memory layout:
  103. *
  104. * 0x4000 - 0x4bff 3k bytes transmit buffer
  105. * 0x4c00 - 0x5fff 5k bytes receive buffer
  106. */
  107. #define NIC_FIRST_TX_PAGE NIC_START_PAGE
  108. #define NIC_FIRST_RX_PAGE (NIC_FIRST_TX_PAGE + NIC_TX_PAGES * NIC_TX_BUFFERS)
  109. /*!
  110. * \brief Standard sizing information
  111. */
  112. #define TX_PAGES 12 /* Allow for 2 back-to-back frames */
  113. /*!
  114. * \addtogroup xgNicRtl
  115. */
  116. /*@{*/
  117. /*!
  118. * Realtek packet header.
  119. */
  120. struct nic_pkt_header {
  121. u_char ph_status; /*!< \brief Status, contents of RSR register */
  122. u_char ph_nextpg; /*!< \brief Page for next packet */
  123. u_short ph_size; /*!< \brief Size of header and packet in octets */
  124. };
  125. /*!
  126. * \brief Reset the Ethernet controller.
  127. *
  128. */
  129. static int NicReset(volatile u_char * base)
  130. {
  131. u_char i;
  132. u_char j;
  133. /*
  134. * Do the software reset by reading from the reset register followed
  135. * by writing to the reset register. Wait until the controller enters
  136. * the reset state.
  137. */
  138. for (j = 0; j < 20; j++) {
  139. i = nic_read(NIC_RESET);
  140. NutDelay(WAIT5);
  141. nic_write(NIC_RESET, i);
  142. for (i = 0; i < 20; i++) {
  143. NutDelay(WAIT50);
  144. /*
  145. * We got the reset bit. However, Ethernut 1.1 may
  146. * still fail because the NIC hasn't got it's hardware
  147. * reset and the data lines remain in tristate. So we
  148. * read noise instead of the register. To solve this
  149. * problem, we will verify the NIC's id.
  150. */
  151. if ((nic_read(NIC_PG0_ISR) & NIC_ISR_RST) != 0 && nic_read(NIC_PG0_RBCR0) == 0x50 && nic_read(NIC_PG0_RBCR1) == 0x70)
  152. return 0;
  153. }
  154. }
  155. return -1;
  156. }
  157. /*
  158. * Fires up the network interface. NIC interrupts
  159. * should have been disabled when calling this
  160. * function.
  161. */
  162. static int NicStart(volatile u_char * base, CONST u_char * mac)
  163. {
  164. u_char i;
  165. if (NicReset(base))
  166. return -1;
  167. /*
  168. * Mask all interrupts and clear any interrupt status flag to set the
  169. * INT pin back to low.
  170. */
  171. nic_write(NIC_PG0_IMR, 0);
  172. nic_write(NIC_PG0_ISR, 0xff);
  173. /*
  174. * During reset the nic loaded its initial configuration from an
  175. * external eeprom. On the ethernut board we do not have any
  176. * configuration eeprom, but simply tied the eeprom data line to
  177. * high level. So we have to clear some bits in the configuration
  178. * register. Switch to register page 3.
  179. */
  180. nic_write(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);
  181. /*
  182. * The nic configuration registers are write protected unless both
  183. * EEM bits are set to 1.
  184. */
  185. nic_write(NIC_PG3_EECR, NIC_EECR_EEM0 | NIC_EECR_EEM1);
  186. /*
  187. * Disable sleep and power down.
  188. */
  189. nic_write(NIC_PG3_CONFIG3, 0);
  190. /*
  191. * Network media had been set to 10Base2 by the virtual EEPROM and
  192. * will be set now to auto detect. This will initiate a link test.
  193. * We don't force 10BaseT, because this would disable the link test.
  194. */
  195. nic_write(NIC_PG3_CONFIG2, NIC_CONFIG2_BSELB);
  196. /*
  197. * Reenable write protection of the nic configuration registers
  198. * and wait for link test to complete.
  199. */
  200. nic_write(NIC_PG3_EECR, 0);
  201. NutDelay(255);
  202. /*
  203. * Switch to register page 0 and set data configuration register
  204. * to byte-wide DMA transfers, normal operation (no loopback),
  205. * send command not executed and 8 byte fifo threshold.
  206. */
  207. nic_write(NIC_CR, NIC_CR_STP | NIC_CR_RD2);
  208. /* nic_write(NIC_PG0_DCR, NIC_DCR_LS | NIC_DCR_FT1); */
  209. nic_write(NIC_PG0_DCR, NIC_DCR_WTS | NIC_DCR_LS | NIC_DCR_FT1);
  210. /*
  211. * Clear remote dma byte count register.
  212. */
  213. nic_write(NIC_PG0_RBCR0, 0);
  214. nic_write(NIC_PG0_RBCR1, 0);
  215. /*
  216. * Temporarily set receiver to monitor mode and transmitter to
  217. * internal loopback mode. Incoming packets will not be stored
  218. * in the nic ring buffer and no data will be send to the network.
  219. */
  220. nic_write(NIC_PG0_RCR, NIC_RCR_MON);
  221. nic_write(NIC_PG0_TCR, NIC_TCR_LB0);
  222. /*
  223. * Configure the nic's ring buffer page layout.
  224. * NIC_PG0_BNRY: Last page read.
  225. * NIC_PG0_PSTART: First page of receiver buffer.
  226. * NIC_PG0_PSTOP: Last page of receiver buffer.
  227. */
  228. nic_write(NIC_PG0_TPSR, NIC_FIRST_TX_PAGE);
  229. nic_write(NIC_PG0_BNRY, NIC_STOP_PAGE - 1);
  230. nic_write(NIC_PG0_PSTART, NIC_FIRST_RX_PAGE);
  231. nic_write(NIC_PG0_PSTOP, NIC_STOP_PAGE);
  232. /*
  233. * Once again clear interrupt status register.
  234. */
  235. nic_write(NIC_PG0_ISR, 0xff);
  236. /*
  237. * Switch to register page 1 and copy our MAC address into the nic.
  238. * We are still in stop mode.
  239. */
  240. nic_write(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0);
  241. for (i = 0; i < 6; i++)
  242. nic_write(NIC_PG1_PAR0 + i, mac[i]);
  243. /*
  244. * Clear multicast filter bits to disable all packets.
  245. */
  246. for (i = 0; i < 8; i++)
  247. nic_write(NIC_PG1_MAR0 + i, 0);
  248. /*
  249. * Set current page pointer to one page after the boundary pointer.
  250. */
  251. nic_write(NIC_PG1_CURR, NIC_START_PAGE + TX_PAGES);
  252. /*
  253. * Switch back to register page 0, remaining in stop mode.
  254. */
  255. nic_write(NIC_CR, NIC_CR_STP | NIC_CR_RD2);
  256. /*
  257. * Take receiver out of monitor mode and enable it for accepting
  258. * broadcasts.
  259. */
  260. nic_write(NIC_PG0_RCR, NIC_RCR_AB);
  261. /*
  262. * Clear all interrupt status flags and enable interrupts.
  263. */
  264. nic_write(NIC_PG0_ISR, 0xff);
  265. nic_write(NIC_PG0_IMR, NIC_IMR_PRXE | NIC_IMR_PTXE | NIC_IMR_RXEE | NIC_IMR_TXEE | NIC_IMR_OVWE);
  266. /*
  267. * Fire up the nic by clearing the stop bit and setting the start bit.
  268. * To activate the local receive dma we must also take the nic out of
  269. * the local loopback mode.
  270. */
  271. nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
  272. nic_write(NIC_PG0_TCR, 0);
  273. NutDelay(255);
  274. return 0;
  275. }
  276. /*!
  277. * Complete remote DMA.
  278. */
  279. static void NicCompleteDma(volatile u_char * base)
  280. {
  281. u_char i;
  282. /*
  283. * Complete remote dma.
  284. */
  285. nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
  286. /*
  287. * Check that we have a DMA complete flag.
  288. */
  289. for (i = 0; i <= 20; i++)
  290. if (nic_read(NIC_PG0_ISR) & NIC_ISR_RDC)
  291. break;
  292. /*
  293. * Reset remote dma complete flag.
  294. */
  295. nic_write(NIC_PG0_ISR, NIC_ISR_RDC);
  296. }
  297. /*!
  298. * \brief Load a packet into the nic's transmit ring buffer.
  299. *
  300. * Interupts must have been disabled when calling this function.
  301. *
  302. * \param base NIC hardware base address.
  303. * \param nb Network buffer structure containing the packet to be sent.
  304. * The structure must have been allocated by a previous
  305. * call NutNetBufAlloc(). This routine will automatically
  306. * release the buffer in case of an error.
  307. *
  308. * \return 0 on success, -1 in case of any errors. Errors
  309. * will automatically release the network buffer
  310. * structure.
  311. */
  312. static int NicPutPacket(volatile u_char * base, NETBUF * nb)
  313. {
  314. u_short sz;
  315. u_short i;
  316. u_short *p;
  317. u_char padding = 0;
  318. /*
  319. * Calculate the number of bytes to be send. Do not
  320. * send packets larger than 1518 bytes.
  321. */
  322. sz = nb->nb_dl.sz + nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz;
  323. if (sz > 1518)
  324. return -1;
  325. /*
  326. * The controller will not append pad bytes,
  327. * so we have to do this.
  328. */
  329. if (sz < 60) {
  330. padding = (u_char) (60 - sz);
  331. sz = 60;
  332. }
  333. /*
  334. * Set remote dma byte count
  335. * and start address.
  336. */
  337. nic_write(NIC_PG0_RBCR0, sz);
  338. nic_write(NIC_PG0_RBCR1, sz >> 8);
  339. nic_write(NIC_PG0_RSAR0, 0);
  340. nic_write(NIC_PG0_RSAR1, NIC_FIRST_TX_PAGE);
  341. /*
  342. * Peform the write.
  343. */
  344. nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD1);
  345. /*
  346. * Switch MCU data bus to 16-bit mode
  347. */
  348. NicMcu16bitBus();
  349. /*
  350. * Transfer the Ethernet frame.
  351. */
  352. p = nb->nb_dl.vp;
  353. for (i = nb->nb_dl.sz >> 1; i; i--)
  354. nic_write_dma(*p++);
  355. p = nb->nb_nw.vp;
  356. for (i = nb->nb_nw.sz >> 1; i; i--)
  357. nic_write_dma(*p++);
  358. p = nb->nb_tp.vp;
  359. for (i = nb->nb_tp.sz >> 1; i; i--)
  360. nic_write_dma(*p++);
  361. p = nb->nb_ap.vp;
  362. for (i = (nb->nb_ap.sz + 1) >> 1; i; i--)
  363. nic_write_dma(*p++);
  364. /*
  365. * Add pad bytes.
  366. */
  367. if ((nb->nb_ap.sz & 0x0001) != 0)
  368. padding--;
  369. for (i = 0; i < (padding + 1) >> 1; i++)
  370. nic_write_dma(0);
  371. /*
  372. * Switch MCU data bus to 8-bit mode
  373. */
  374. NicMcu8bitBus();
  375. /*
  376. * Complete remote dma.
  377. */
  378. NicCompleteDma(base);
  379. /*
  380. * Number of bytes to be transmitted.
  381. */
  382. nic_write(NIC_PG0_TBCR0, (sz & 0xff));
  383. nic_write(NIC_PG0_TBCR1, ((sz >> 8) & 0xff));
  384. /*
  385. * First page of packet to be transmitted.
  386. */
  387. nic_write(NIC_PG0_TPSR, NIC_FIRST_TX_PAGE);
  388. /*
  389. * Start transmission.
  390. */
  391. nic_write(NIC_CR, NIC_CR_STA | NIC_CR_TXP | NIC_CR_RD2);
  392. return 0;
  393. }
  394. /*!
  395. * \brief Fetch the next packet out of the receive ring buffer.
  396. *
  397. * Nic interrupts must be disabled when calling this funtion.
  398. *
  399. * \return Pointer to an allocated ::NETBUF. If there is no
  400. * no data available, then the function returns a
  401. * null pointer. If the NIC's buffer seems to be
  402. * corrupted, a pointer to 0xFFFF is returned.
  403. */
  404. static NETBUF *NicGetPacket(volatile u_char * base, u_char dflg)
  405. {
  406. NETBUF *nb = 0;
  407. struct nic_pkt_header hdr;
  408. u_short count;
  409. u_char nextpg;
  410. u_char bnry;
  411. u_char curr;
  412. u_short i;
  413. u_short *buf;
  414. /*
  415. * Get the current page pointer. It points to the page where the NIC
  416. * will start saving the next incoming packet.
  417. */
  418. nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD2 | NIC_CR_PS0);
  419. curr = nic_read(NIC_PG1_CURR);
  420. nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
  421. /*
  422. * Get the pointer to the last page we read from. The following page
  423. * is the one where we start reading. If it's equal to the current
  424. * page pointer, then there's nothing to read. In this case we return
  425. * a null pointer.
  426. */
  427. if ((bnry = nic_read(NIC_PG0_BNRY) + 1) >= NIC_STOP_PAGE)
  428. bnry = NIC_FIRST_RX_PAGE;
  429. if (bnry == curr)
  430. return 0;
  431. /*
  432. * Read the NIC specific packet header.
  433. */
  434. nic_write(NIC_PG0_RBCR0, sizeof(struct nic_pkt_header));
  435. nic_write(NIC_PG0_RBCR1, 0);
  436. nic_write(NIC_PG0_RSAR0, 0);
  437. nic_write(NIC_PG0_RSAR1, bnry);
  438. nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD0);
  439. buf = (u_short *) & hdr;
  440. NicMcu16bitBus(); /* Switch MCU data bus to 16-bit mode */
  441. *buf++ = nic_read_dma(); /* Read status byte and next page pointer */
  442. *buf = nic_read_dma(); /* Read frame length */
  443. NicMcu8bitBus(); /* Switch MCU data bus to 8-bit mode */
  444. NicCompleteDma(base);
  445. #ifdef __BIG_ENDIAN__
  446. hdr.ph_size = __byte_swap2(hdr.ph_size);
  447. #endif
  448. /*
  449. * Check packet length.
  450. */
  451. if (hdr.ph_size < 60 + sizeof(struct nic_pkt_header) || hdr.ph_size > 1518 + sizeof(struct nic_pkt_header)) {
  452. return dflg ? 0 : (NETBUF *) - 1;
  453. }
  454. /*
  455. * Calculate the page of the next packet. If it differs from the
  456. * pointer in the packet header, we discard the whole buffer
  457. * and return a null pointer.
  458. */
  459. nextpg = bnry + (hdr.ph_size >> 8) + ((hdr.ph_size & 0xFF) != 0);
  460. if (nextpg >= NIC_STOP_PAGE) {
  461. nextpg -= NIC_STOP_PAGE;
  462. nextpg += NIC_FIRST_RX_PAGE;
  463. }
  464. if (nextpg != hdr.ph_nextpg) {
  465. u_char nextpg1 = nextpg + 1;
  466. if (nextpg1 >= NIC_STOP_PAGE) {
  467. nextpg1 -= NIC_STOP_PAGE;
  468. nextpg1 += NIC_FIRST_RX_PAGE;
  469. }
  470. if (nextpg1 != hdr.ph_nextpg) {
  471. return dflg ? 0 : (NETBUF *) - 1;
  472. }
  473. nextpg = nextpg1;
  474. }
  475. /*
  476. * Check packet status. It should have set bit 0, but
  477. * even without this bit packets seem to be OK.
  478. */
  479. if ((hdr.ph_status & 0x0E) == 0) {
  480. /*
  481. * Allocate a NETBUF.
  482. */
  483. count = hdr.ph_size - sizeof(struct nic_pkt_header);
  484. if (dflg == 0) {
  485. nb = NutNetBufAlloc(0, NBAF_DATALINK, count);
  486. }
  487. /*
  488. * Set remote dma byte count and
  489. * start address. Don't read the
  490. * header again.
  491. */
  492. nic_write(NIC_PG0_RBCR0, count);
  493. nic_write(NIC_PG0_RBCR1, count >> 8);
  494. nic_write(NIC_PG0_RSAR0, sizeof(struct nic_pkt_header));
  495. nic_write(NIC_PG0_RSAR1, bnry);
  496. /*
  497. * Perform the read.
  498. */
  499. nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD0);
  500. /*
  501. * Switch MCU data bus to 16-bit mode
  502. */
  503. NicMcu16bitBus();
  504. count = (count + 1) >> 1;
  505. if (nb) {
  506. buf = nb->nb_dl.vp;
  507. for (i = 0; i < count; i++)
  508. *buf++ = nic_read_dma();
  509. } else {
  510. for (i = 0; i < count; i++)
  511. nic_read_dma();
  512. }
  513. /*
  514. * Switch MCU data bus to 8-bit mode
  515. */
  516. NicMcu8bitBus();
  517. /*
  518. * Complete remote dma.
  519. */
  520. NicCompleteDma(base);
  521. }
  522. /*
  523. * Set boundary register to the last page we read.
  524. */
  525. if (--nextpg < NIC_FIRST_RX_PAGE)
  526. nextpg = NIC_STOP_PAGE - 1;
  527. nic_write(NIC_PG0_BNRY, nextpg);
  528. return dflg ? (NETBUF *) ((uptr_t) dflg) : nb;
  529. }
  530. /*
  531. * When a receiver buffer overflow occurs, the NIC will defer any
  532. * subsequent action until properly restarted.
  533. */
  534. static int NicOverflow(volatile u_char * base)
  535. {
  536. u_char cr;
  537. u_char resend;
  538. /*
  539. * Save the command register, so we can later determine, if NIC
  540. * transmitter has been interrupted. Then stop the NIC and wait
  541. * 5 ms for any transmission or reception in progress.
  542. */
  543. cr = nic_read(NIC_CR);
  544. nic_write(NIC_CR, NIC_CR_STP | NIC_CR_RD2);
  545. NutDelay(WAIT5);
  546. /*
  547. * Clear remote byte count register.
  548. */
  549. nic_write(NIC_PG0_RBCR0, 0);
  550. nic_write(NIC_PG0_RBCR1, 0);
  551. /*
  552. * Check for any incomplete transmission.
  553. */
  554. resend = 0;
  555. if (cr & NIC_CR_TXP) {
  556. if ((nic_read(NIC_PG0_ISR) & (NIC_ISR_PTX | NIC_ISR_TXE)) == 0)
  557. resend = 1;
  558. }
  559. /*
  560. * Enter loopback mode and restart the NIC.
  561. */
  562. nic_write(NIC_PG0_TCR, NIC_TCR_LB0);
  563. nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
  564. /*
  565. * Discard all packets from the receiver buffer.
  566. */
  567. while (NicGetPacket(base, 1));
  568. /*
  569. * Switch from loopback to normal mode mode.
  570. */
  571. nic_write(NIC_PG0_TCR, 0);
  572. /*
  573. * Re-invoke any interrupted transmission.
  574. */
  575. if (resend) {
  576. nic_write(NIC_CR, NIC_CR_STA | NIC_CR_TXP | NIC_CR_RD2);
  577. }
  578. /* Finally clear the overflow flag. */
  579. nic_write(NIC_PG0_ISR, NIC_ISR_OVW);
  580. return resend;
  581. }
  582. /*
  583. * NIC interrupt entry.
  584. */
  585. static void NicInterrupt(void *arg)
  586. {
  587. u_char isr;
  588. volatile u_char *base = (u_char *) (((NUTDEVICE *) arg)->dev_base);
  589. NICINFO *ni = (NICINFO *) ((NUTDEVICE *) arg)->dev_dcb;
  590. ni->ni_interrupts++;
  591. isr = nic_read(NIC_PG0_ISR);
  592. nic_write(NIC_PG0_ISR, isr);
  593. /*
  594. * Recover from receive buffer overflow. This may take some
  595. * time, so we enable global interrupts but keep NIC
  596. * interrupts disabled.
  597. */
  598. if (isr & NIC_ISR_OVW) {
  599. NicDisableInt();
  600. NutEnableInt();
  601. ni->ni_rx_pending++;
  602. if (NicOverflow(base))
  603. ni->ni_tx_bsy++;
  604. else {
  605. NutEventPostFromIrq(&ni->ni_tx_rdy);
  606. }
  607. ni->ni_overruns++;
  608. NutDisableInt();
  609. NicEnableInt();
  610. } else {
  611. /*
  612. * If this is a transmit interrupt, then a packet has been sent.
  613. * So we can clear the transmitter busy flag and wake up the
  614. * transmitter thread.
  615. */
  616. if (isr & (NIC_ISR_PTX | NIC_ISR_TXE)) {
  617. ni->ni_tx_bsy = 0;
  618. NutEventPostFromIrq(&ni->ni_tx_rdy);
  619. }
  620. /*
  621. * If this is a receive interrupt, then wake up the receiver
  622. * thread.
  623. */
  624. if (isr & NIC_ISR_PRX) {
  625. ni->ni_rx_pending++;
  626. NutEventPostFromIrq(&ni->ni_rx_rdy);
  627. }
  628. if (isr & NIC_ISR_RXE) {
  629. ni->ni_rx_frame_errors += nic_read(NIC_PG0_CNTR0);
  630. ni->ni_rx_crc_errors += nic_read(NIC_PG0_CNTR1);
  631. ni->ni_rx_missed_errors += nic_read(NIC_PG0_CNTR2);
  632. }
  633. }
  634. }
  635. /*! \fn NicRx(void *arg)
  636. * \brief NIC receiver thread.
  637. *
  638. *
  639. * It runs with high priority.
  640. */
  641. THREAD(NicRx, arg)
  642. {
  643. NUTDEVICE *dev;
  644. IFNET *ifn;
  645. NICINFO *ni;
  646. NETBUF *nb;
  647. u_char rlcnt;
  648. dev = arg;
  649. ifn = (IFNET *) dev->dev_icb;
  650. ni = (NICINFO *) dev->dev_dcb;
  651. NutThreadSetPriority(9);
  652. /*
  653. * This is a temporary hack. Due to a change in initialization,
  654. * we may not have got a MAC address yet. Wait until one has been
  655. * set.
  656. */
  657. if ((ifn->if_mac[0] & ifn->if_mac[1] & ifn->if_mac[2]) == 0xFF) {
  658. while ((ifn->if_mac[0] & ifn->if_mac[1] & ifn->if_mac[2]) == 0xFF)
  659. NutSleep(125);
  660. NicDisableInt();
  661. NicStart((u_char *) (dev->dev_base), ifn->if_mac);
  662. ni->ni_curr_page = NIC_START_PAGE + TX_PAGES;
  663. NicEnableInt();
  664. }
  665. for (;;) {
  666. /*
  667. * Wait for the arrival of new packets or check
  668. * the receiver every two second.
  669. */
  670. if (ni->ni_rx_pending > 10) {
  671. NicDisableInt();
  672. if (NicStart((u_char *) (dev->dev_base), ifn->if_mac) == 0)
  673. ni->ni_rx_pending = 0;
  674. ni->ni_curr_page = NIC_START_PAGE + TX_PAGES;
  675. NicEnableInt();
  676. }
  677. NutEventWait(&ni->ni_rx_rdy, 2000);
  678. /*
  679. * Fetch all packets from the NIC's internal
  680. * buffer and pass them to the registered handler.
  681. */
  682. rlcnt = 0;
  683. NicDisableInt();
  684. while (rlcnt++ < 10) {
  685. if ((nb = NicGetPacket((u_char *) (dev->dev_base), 0)) == 0)
  686. break;
  687. /* The sanity check may fail because the controller is too busy.
  688. try another read before giving up and restarting the NIC. */
  689. if (nb == (void *) -1) {
  690. if ((nb = NicGetPacket((u_char *) (dev->dev_base), 0)) == 0)
  691. break;
  692. }
  693. if (nb == (void *) -1) {
  694. if (NicStart((u_char *) (dev->dev_base), ifn->if_mac) == 0)
  695. ni->ni_rx_pending = 0;
  696. ni->ni_curr_page = NIC_START_PAGE + TX_PAGES;
  697. ni->ni_rx_pending = 0;
  698. } else {
  699. ni->ni_rx_pending = 0;
  700. ni->ni_rx_packets++;
  701. NicEnableInt();
  702. (*ifn->if_recv) (dev, nb);
  703. NicDisableInt();
  704. }
  705. }
  706. NicEnableInt();
  707. }
  708. }
  709. /*!
  710. * \brief Send Ethernet packet.
  711. *
  712. * \param dev Identifies the device to use.
  713. * \param nb Network buffer structure containing the packet to be sent.
  714. * The structure must have been allocated by a previous
  715. * call NutNetBufAlloc().
  716. *
  717. * \return 0 on success, -1 in case of any errors.
  718. */
  719. int NicOutput(NUTDEVICE * dev, NETBUF * nb)
  720. {
  721. int rc = -1;
  722. NICINFO *ni;
  723. u_char retries = 10;
  724. u_char sigmod = 0;
  725. ni = (NICINFO *) dev->dev_dcb;
  726. while (ni->ni_tx_bsy && retries--) {
  727. if (NutEventWait(&ni->ni_tx_rdy, 200)) {
  728. volatile u_char *base = (u_char *) (dev->dev_base);
  729. /*
  730. * If hanging around here too long, there's something wrong
  731. * with the transmit interrupt. Force sending the packet,
  732. * if the transmitter has become inactive.
  733. */
  734. if (NicIntIsEnabled()) {
  735. NicDisableInt();
  736. sigmod = 1;
  737. }
  738. if ((nic_read(NIC_CR) & NIC_CR_TXP) == 0)
  739. ni->ni_tx_bsy = 0;
  740. if (sigmod) {
  741. NicEnableInt();
  742. sigmod = 0;
  743. }
  744. }
  745. }
  746. if (NicIntIsEnabled()) {
  747. NicDisableInt();
  748. sigmod = 1;
  749. }
  750. if (ni->ni_tx_bsy == 0) {
  751. ni->ni_tx_bsy++;
  752. if (NicPutPacket((u_char *) (dev->dev_base), nb) == 0) {
  753. ni->ni_tx_packets++;
  754. rc = 0;
  755. }
  756. }
  757. if (sigmod)
  758. NicEnableInt();
  759. return rc;
  760. }
  761. /*!
  762. * \brief Initialize Ethernet hardware.
  763. *
  764. * Resets RTL8019AS Ethernet controller, initializes all required
  765. * hardware registers and starts a background thread for incoming
  766. * Ethernet traffic.
  767. *
  768. * Applications should do not directly call this function. It is
  769. * automatically executed during during device registration by
  770. * NutRegisterDevice().
  771. *
  772. * If the network configuration hasn't been set by the application
  773. * before registering the specified device, this function will
  774. * call NutNetLoadConfig() to get the MAC address.
  775. *
  776. * \param dev Identifies the device to initialize.
  777. */
  778. int NicInit(NUTDEVICE * dev)
  779. {
  780. volatile u_char *base;
  781. IFNET *ifn;
  782. NICINFO *ni;
  783. /*
  784. * We need to know our MAC address. If no configuration is
  785. * available, load it now.
  786. */
  787. if (confnet.cd_size == 0)
  788. NutNetLoadConfig(dev->dev_name);
  789. ifn = dev->dev_icb;
  790. memcpy(ifn->if_mac, confnet.cdn_mac, 6);
  791. ni = (NICINFO *) dev->dev_dcb;
  792. memset(ni, 0, sizeof(NICINFO));
  793. base = (u_char *) (dev->dev_base);
  794. NicDisableInt();
  795. NutInitSysIrq();
  796. if (ifn->if_mac[0] | ifn->if_mac[1] | ifn->if_mac[2])
  797. if (NicStart(base, ifn->if_mac))
  798. return -1;
  799. ni->ni_curr_page = NIC_START_PAGE + TX_PAGES;
  800. /*
  801. * Start the receiver thread.
  802. */
  803. NutThreadCreate("rxi0", NicRx, dev, 640);
  804. NutSleep(WAIT500);
  805. /*
  806. * Register interrupt handler and enable interrupts.
  807. */
  808. if (NutRegisterIrqHandler(&RTL_SIGNAL, NicInterrupt, dev))
  809. return -1;
  810. NicEnableInt();
  811. return 0;
  812. }
  813. /*!
  814. * \brief Network interface device control block structure.
  815. *
  816. * Used to call.
  817. */
  818. static NICINFO dcb_eth0rtl;
  819. /*!
  820. * \brief Network interface information structure.
  821. *
  822. * Used to call.
  823. */
  824. static IFNET ifn_eth0rtl = {
  825. IFT_ETHER, /*!< \brief Interface type. */
  826. {0, 0, 0, 0, 0, 0}, /*!< \brief Hardware net address. */
  827. 0, /*!< \brief IP address. */
  828. 0, /*!< \brief Remote IP address for point to point. */
  829. 0, /*!< \brief IP network mask. */
  830. ETHERMTU, /*!< \brief Maximum size of a transmission unit. */
  831. 0, /*!< \brief Packet identifier. */
  832. 0, /*!< \brief Linked list of arp entries. */
  833. NutEtherInput, /*!< \brief Routine to pass received data to, if_recv(). */
  834. NicOutput, /*!< \brief Driver output routine, if_send(). */
  835. NutEtherOutput /*!< \brief Media output routine, if_output(). */
  836. };
  837. /*!
  838. * \brief Device information structure.
  839. *
  840. * A pointer to this structure must be passed to NutRegisterDevice()
  841. * to bind this Ethernet device driver to the Nut/OS kernel.
  842. * An application may then call NutNetIfConfig() with the name \em eth0
  843. * of this driver to initialize the network interface.
  844. *
  845. */
  846. NUTDEVICE devEth0 = {
  847. 0, /* Pointer to next device. */
  848. {'e', 't', 'h', '0', 0, 0, 0, 0, 0}, /* Unique device name. */
  849. IFTYP_NET, /* Type of device. */
  850. 0, /* Base address. */
  851. 0, /* First interrupt number. */
  852. &ifn_eth0rtl, /* Interface control block. */
  853. &dcb_eth0rtl, /* Driver control block. */
  854. NicInit, /* Driver initialization routine. */
  855. 0, /* Driver specific control function. */
  856. 0, /* Read from device. */
  857. 0, /* Write to device. */
  858. /* Write from program space data to device. */
  859. 0, /* Open a device or file. */
  860. 0, /* Close a device or file. */
  861. 0, /* Request file size. */
  862. 0, /* Select function, optional, not yet implemented */
  863. };
  864. /*@}*/