ether.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. /*
  2. * Copyright (C) 2001-2003 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. * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  34. *
  35. * Permission to use, copy, modify, and distribute this software for any
  36. * purpose with or without fee is hereby granted, provided that the above
  37. * copyright notice and this permission notice appear in all copies, and that
  38. * the name of Digital Equipment Corporation not be used in advertising or
  39. * publicity pertaining to distribution of the document or software without
  40. * specific, written prior permission.
  41. *
  42. * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  43. * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  44. * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
  45. * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  46. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  47. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  48. * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  49. * SOFTWARE.
  50. */
  51. #include <avr/io.h>
  52. #include "debug.h"
  53. #include "smscregs.h"
  54. #include "arp.h"
  55. #include "ether.h"
  56. #include "appload.h"
  57. /*!
  58. * \brief Select specified PHY register for reading or writing.
  59. *
  60. * \param reg PHY register number.
  61. * \param we Should be 1 for write access, 0 for read access.
  62. *
  63. * \return Contents of the PHY interface rgister.
  64. */
  65. u_char NicPhyRegSelect(u_char reg, u_char we)
  66. {
  67. u_char rs;
  68. u_char msk;
  69. u_char i;
  70. nic_bs(3);
  71. rs = (nic_inlb(NIC_MGMT) & ~(MGMT_MCLK | MGMT_MDO)) | MGMT_MDOE;
  72. /* Send idle pattern. */
  73. for (i = 0; i < 33; i++) {
  74. nic_outlb(NIC_MGMT, rs | MGMT_MDO);
  75. nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
  76. }
  77. /* Send start sequence. */
  78. nic_outlb(NIC_MGMT, rs);
  79. nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
  80. nic_outlb(NIC_MGMT, rs | MGMT_MDO);
  81. nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
  82. /* Write or read mode. */
  83. if (we) {
  84. nic_outlb(NIC_MGMT, rs);
  85. nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
  86. nic_outlb(NIC_MGMT, rs | MGMT_MDO);
  87. nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
  88. } else {
  89. nic_outlb(NIC_MGMT, rs | MGMT_MDO);
  90. nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
  91. nic_outlb(NIC_MGMT, rs);
  92. nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
  93. }
  94. /* Send PHY address. Zero is used for the internal PHY. */
  95. for (i = 0; i < 5; i++) {
  96. nic_outlb(NIC_MGMT, rs);
  97. nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
  98. }
  99. /* Send PHY register number. */
  100. for (msk = 0x10; msk; msk >>= 1) {
  101. if (reg & msk) {
  102. nic_outlb(NIC_MGMT, rs | MGMT_MDO);
  103. nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
  104. } else {
  105. nic_outlb(NIC_MGMT, rs);
  106. nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
  107. }
  108. }
  109. nic_outlb(NIC_MGMT, rs);
  110. return rs;
  111. }
  112. /*!
  113. * \brief Read contents of PHY register.
  114. *
  115. * \param reg PHY register number.
  116. *
  117. * \return Contents of the specified register.
  118. */
  119. u_short NicPhyRead(u_char reg)
  120. {
  121. u_short rc = 0;
  122. u_char rs;
  123. u_char i;
  124. /* Select register for reading. */
  125. rs = NicPhyRegSelect(reg, 0);
  126. /* Switch data direction. */
  127. rs &= ~MGMT_MDOE;
  128. nic_outlb(NIC_MGMT, rs);
  129. nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
  130. /* Clock data in. */
  131. for (i = 0; i < 16; i++) {
  132. nic_outlb(NIC_MGMT, rs);
  133. nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
  134. rc <<= 1;
  135. rc |= (nic_inlb(NIC_MGMT) & MGMT_MDI) != 0;
  136. }
  137. /* This will set the clock line to low. */
  138. nic_outlb(NIC_MGMT, rs);
  139. return rc;
  140. }
  141. /*!
  142. * \brief Write value to PHY register.
  143. *
  144. * \param reg PHY register number.
  145. * \param val Value to write.
  146. */
  147. void NicPhyWrite(u_char reg, u_short val)
  148. {
  149. u_short msk;
  150. u_char rs;
  151. /* Select register for writing. */
  152. rs = NicPhyRegSelect(reg, 1);
  153. /* Switch data direction dummy. */
  154. nic_outlb(NIC_MGMT, rs | MGMT_MDO);
  155. nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
  156. nic_outlb(NIC_MGMT, rs);
  157. nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
  158. /* Clock data out. */
  159. for (msk = 0x8000; msk; msk >>= 1) {
  160. if (val & msk) {
  161. nic_outlb(NIC_MGMT, rs | MGMT_MDO);
  162. nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
  163. } else {
  164. nic_outlb(NIC_MGMT, rs);
  165. nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
  166. }
  167. }
  168. /* Set clock line low and output line int z-state. */
  169. nic_outlb(NIC_MGMT, rs & ~MGMT_MDOE);
  170. }
  171. /*!
  172. * \brief Configure the internal PHY.
  173. *
  174. * Reset the PHY and initiate auto-negotiation.
  175. */
  176. int NicPhyConfig(void)
  177. {
  178. u_short phy_sor;
  179. u_short phy_sr;
  180. u_short phy_to;
  181. u_short mode;
  182. /*
  183. * Reset the PHY and wait until this self clearing bit
  184. * becomes zero. We sleep 63 ms before each poll and
  185. * give up after 3 retries.
  186. */
  187. NicPhyWrite(NIC_PHYCR, PHYCR_RST);
  188. for (phy_to = 0;; phy_to++) {
  189. Delay(1);
  190. if ((NicPhyRead(NIC_PHYCR) & PHYCR_RST) == 0)
  191. break;
  192. if (phy_to > 3) {
  193. return -1;
  194. }
  195. }
  196. Delay(1);
  197. /* Store PHY status output. */
  198. phy_sor = NicPhyRead(NIC_PHYSOR);
  199. /* Enable PHY interrupts. */
  200. NicPhyWrite(NIC_PHYMSK, PHYMSK_MLOSSSYN | PHYMSK_MCWRD | PHYMSK_MSSD |
  201. PHYMSK_MESD | PHYMSK_MRPOL | PHYMSK_MJAB | PHYMSK_MSPDDT | PHYMSK_MDPLDT);
  202. /* Set RPC register. */
  203. mode = RPCR_ANEG | RPCR_LEDA_PAT | RPCR_LEDB_PAT;
  204. nic_bs(0);
  205. nic_outw(NIC_RPCR, mode);
  206. /*
  207. * Advertise our capabilities, initiate auto negotiation
  208. * and wait until this has been completed.
  209. */
  210. NicPhyWrite(NIC_PHYANAD, PHYANAD_TX_FDX | PHYANAD_TX_HDX | PHYANAD_10FDX | PHYANAD_10_HDX | PHYANAD_CSMA);
  211. for (phy_to = 0, phy_sr = 0;; phy_to++) {
  212. /* Give up after long time wait. */
  213. if (phy_to >= 1024) {
  214. return -1;
  215. }
  216. /* Restart auto negotiation every 4 seconds or on failures. */
  217. if ((phy_to & 127) == 0 /* || (phy_sr & PHYSR_REM_FLT) != 0 */ ) {
  218. NicPhyWrite(NIC_PHYCR, PHYCR_ANEG_EN | PHYCR_ANEG_RST);
  219. Delay(2);
  220. }
  221. /* Check if link status detected. */
  222. phy_sr = NicPhyRead(NIC_PHYSR);
  223. if (phy_sr & PHYSR_ANEG_ACK)
  224. break;
  225. Delay(3);
  226. }
  227. return 0;
  228. }
  229. /*!
  230. * \brief Wait until MMU is ready.
  231. *
  232. * Poll the MMU command register until \ref MMUCR_BUSY
  233. * is cleared.
  234. *
  235. * \param tmo Timeout in milliseconds.
  236. *
  237. * \return 0 on success or -1 on timeout.
  238. */
  239. static int NicMmuWait(u_short tmo)
  240. {
  241. while (tmo--) {
  242. if ((nic_inlb(NIC_MMUCR) & MMUCR_BUSY) == 0)
  243. break;
  244. MicroDelay(1000);
  245. }
  246. return tmo ? 0 : -1;
  247. }
  248. /*!
  249. * \brief Reset the Ethernet controller.
  250. *
  251. * \return 0 on success, -1 otherwise.
  252. */
  253. int NicReset(void)
  254. {
  255. /* Disable all interrupts. */
  256. nic_outlb(NIC_MSK, 0);
  257. /* MAC and PHY software reset. */
  258. nic_bs(0);
  259. nic_outw(NIC_RCR, RCR_SOFT_RST);
  260. /* Enable Ethernet protocol handler. */
  261. nic_bs(1);
  262. nic_outw(NIC_CR, CR_EPH_EN);
  263. Delay(1);
  264. /* Disable transmit and receive. */
  265. nic_bs(0);
  266. nic_outw(NIC_RCR, 0);
  267. nic_outw(NIC_TCR, 0);
  268. /* Enable auto release. */
  269. nic_bs(1);
  270. nic_outw(NIC_CTR, CTR_AUTO_RELEASE);
  271. /* Reset MMU. */
  272. nic_bs(2);
  273. nic_outlb(NIC_MMUCR, MMU_RST);
  274. if (NicMmuWait(1000))
  275. return -1;
  276. return 0;
  277. }
  278. /*!
  279. * \brief Initialize the NIC.
  280. *
  281. * \return 0 on success, -1 otherwise.
  282. */
  283. int EtherInit(void)
  284. {
  285. u_char i;
  286. /* NIC reset. */
  287. if (NicReset()) {
  288. return -1;
  289. }
  290. /* Enable receiver. */
  291. nic_bs(3);
  292. nic_outlb(NIC_ERCV, 7);
  293. nic_bs(0);
  294. nic_outw(NIC_RCR, RCR_RXEN);
  295. /* Enable transmitter and padding. */
  296. nic_outw(NIC_TCR, TCR_PAD_EN | TCR_TXENA);
  297. /* Configure the PHY. */
  298. if (NicPhyConfig()) {
  299. return -1;
  300. }
  301. /* Set MAC address. */
  302. nic_bs(1);
  303. for (i = 0; i < 6; i++) {
  304. nic_outlb(NIC_IAR + i, confnet.cdn_mac[i]);
  305. }
  306. return 0;
  307. }
  308. /*!
  309. * \brief Send an Ethernet frame.
  310. *
  311. * \param dmac Destination MAC address.
  312. * \param type Frame type.
  313. * \param len Frame size.
  314. *
  315. * \return 0 on success, -1 otherwise.
  316. */
  317. int EtherOutput(const u_char * dmac, u_short type, u_short len)
  318. {
  319. ETHERHDR *eh;
  320. u_char *cp;
  321. /*
  322. * Set the Ethernet header.
  323. */
  324. if (type == ETHERTYPE_ARP) {
  325. cp = (u_char *) & arpframe;
  326. } else {
  327. cp = (u_char *) & sframe;
  328. }
  329. eh = (ETHERHDR *)cp;
  330. memcpy_(eh->ether_shost, confnet.cdn_mac, 6);
  331. memcpy_(eh->ether_dhost, dmac, 6);
  332. eh->ether_type = type;
  333. /*
  334. * The total packet length includes
  335. * - status word (2 bytes)
  336. * - byte count (2 bytes)
  337. * - destination address (6 bytes)
  338. * - source address (6 bytes)
  339. * - Ethernet type (2 bytes)
  340. * - data bytes (variable)
  341. * - control word (2 bytes)
  342. * Thus we add 20 to the number of data bytes. We didn't
  343. * manage to get an odd number of bytes transmitted, so
  344. * add another byte.
  345. */
  346. if((len += 20) & 1) {
  347. len++;
  348. }
  349. DEBUG(" Tx(");
  350. DEBUGUSHORT(len);
  351. DEBUG(")");
  352. /* Allocate transmit packet buffer space. */
  353. nic_bs(2);
  354. nic_outlb(NIC_MMUCR, MMU_ALO);
  355. if (NicMmuWait(100)) {
  356. return -1;
  357. }
  358. /*
  359. * An allocation error might appear when incoming packets occupy
  360. * all the buffer. Reset the MMU to release all memory. This is
  361. * very drastic, but OK for our sequential boot loader.
  362. */
  363. if ((nic_inlb(NIC_IST) & INT_ALLOC) == 0) {
  364. DEBUG("[MMURST]");
  365. nic_outlb(NIC_MMUCR, MMU_RST);
  366. NicMmuWait(1000);
  367. nic_outlb(NIC_MMUCR, MMU_ALO);
  368. if (NicMmuWait(100) || (nic_inlb(NIC_IST) & INT_ALLOC) == 0) {
  369. return -1;
  370. }
  371. }
  372. /*
  373. * Read the number of the allcocated packet from the allocation
  374. * result register and write it to the packet number register.
  375. */
  376. nic_outlb(NIC_PNR, nic_inhb(NIC_PNR));
  377. /*
  378. * Initially set the pointer register address to 2 and enable
  379. * auto increment. The first two bytes will be used by the CSMA
  380. * to store the status word upon transmit completion.
  381. */
  382. nic_outw(NIC_PTR, PTR_AUTO_INCR | 2);
  383. /*
  384. * Transfer the byte count and the data bytes.
  385. */
  386. nic_outw(NIC_DATA, len);
  387. while (len--) {
  388. nic_outlb(NIC_DATA, *cp);
  389. cp++;
  390. }
  391. /*
  392. * Transfer the control word. As stated above, we never succeeded
  393. * in sending an odd number of bytes.
  394. */
  395. nic_outw(NIC_DATA, 0);
  396. /* Enqueue packet. */
  397. NicMmuWait(100);
  398. nic_outlb(NIC_MMUCR, MMU_ENQ);
  399. return 0;
  400. }
  401. /*!
  402. * \brief Receive an Ethernet frame.
  403. *
  404. * \param tms Return with timeout after the specified
  405. * number of waiting loops. On a 14 Mhz ATmega
  406. * this value represents approximately the number
  407. * of milliseconds to wait.
  408. *
  409. * \return The number of bytes received, 0 on timeout
  410. * or -1 in case of a failure.
  411. */
  412. int EtherInput(u_short type, u_short tms)
  413. {
  414. register u_short fsw;
  415. register u_char *buf;
  416. u_short fbc;
  417. /* Check the fifo empty bit. If it is set, then there is
  418. nothing in the receiver fifo. */
  419. nic_bs(2);
  420. while (tms--) {
  421. if ((nic_inw(NIC_FIFO) & 0x8000) == 0) {
  422. break;
  423. }
  424. MicroDelay(1000);
  425. }
  426. if (nic_inw(NIC_FIFO) & 0x8000) {
  427. return 0;
  428. }
  429. /* Inialize pointer register. */
  430. nic_outw(NIC_PTR, PTR_READ | PTR_RCV | PTR_AUTO_INCR);
  431. MicroDelay(1);
  432. /* Read status word and byte count. */
  433. fsw = nic_inw(NIC_DATA);
  434. fbc = nic_inw(NIC_DATA) - 3;
  435. /* Check for frame errors. */
  436. if ((fsw & 0xAC00) == 0) {
  437. DEBUG("\nRx(");
  438. DEBUGUSHORT(fbc);
  439. DEBUG(")");
  440. if(fbc > sizeof(rframe)) {
  441. fbc = sizeof(rframe);
  442. }
  443. /* Perform the read. */
  444. buf = (u_char *) & rframe;
  445. fsw = fbc;
  446. while (fsw--) {
  447. *buf++ = nic_inlb(NIC_DATA);
  448. }
  449. }
  450. else {
  451. fbc = -1;
  452. }
  453. /* Release the packet. */
  454. nic_outlb(NIC_MMUCR, MMU_TOP);
  455. return fbc;
  456. }