realtek.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. /*
  2. * Copyright (C) 2001-2006 by egnite Software GmbH
  3. * Copyright (C) 2009 by egnite GmbH
  4. *
  5. * All rights reserved.
  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 the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. Neither the name of the copyright holders nor the names of
  17. * contributors may be used to endorse or promote products derived
  18. * from this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  23. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  24. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  26. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  27. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  28. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  29. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  30. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. *
  33. * For additional information see http://www.ethernut.de/
  34. */
  35. /*
  36. * $Id: realtek.c 3597 2011-10-21 16:17:18Z haraldkipp $
  37. *
  38. * WARNING! Do not use any part of Basemon for your own applications. WARNING!
  39. *
  40. * This is not a typical application sample. It overrides parts of Nut/OS to
  41. * keep it running on broken hardware.
  42. */
  43. #include <stdio.h>
  44. #include <sys/timer.h>
  45. #include "basemon.h"
  46. #include "utils.h"
  47. #include "uart.h"
  48. #include "rtlregs.h"
  49. #include "realtek.h"
  50. #define RTL_EESK_BIT 5
  51. #define RTL_EESK_PORT PORTC
  52. #define RTL_EESK_PIN PINC
  53. #define RTL_EESK_DDR DDRC
  54. #define RTL_EEDO_BIT 6
  55. #define RTL_EEDO_PORT PORTC
  56. #define RTL_EEDO_DDR DDRC
  57. #define RTL_EEMU_BIT 7
  58. #define RTL_EEMU_PORT PORTC
  59. #define RTL_EEMU_DDR DDRC
  60. #define RTL_EE_MEMBUS
  61. static uint8_t *nic_base;
  62. static int NicReset(void)
  63. {
  64. volatile uint8_t *base = nic_base;
  65. uint8_t i;
  66. uint8_t j;
  67. /* Start command clears the reset bit. */
  68. nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
  69. //printf("[%02X]", nic_read(NIC_PG0_ISR));
  70. for (j = 0; j < 20; j++) {
  71. printf("SW-Reset...");
  72. i = nic_read(NIC_RESET);
  73. Delay(500);
  74. nic_write(NIC_RESET, i);
  75. for (i = 0; i < 20; i++) {
  76. //Delay(5000);
  77. /*
  78. * ID detection added for version 1.1 boards.
  79. */
  80. if ((nic_read(NIC_PG0_ISR) & NIC_ISR_RST) != 0 && nic_read(NIC_PG0_RBCR0) == 0x50 && nic_read(NIC_PG0_RBCR1) == 0x70) {
  81. puts("OK");
  82. return 0;
  83. }
  84. }
  85. puts("failed\x07");
  86. /*
  87. * Toggle the hardware reset line. Since Ethernut version 1.3 the
  88. * hardware reset pin of the nic is no longer connected to bit 4
  89. * on port E, but wired to the board reset line.
  90. */
  91. if (j == 10) {
  92. puts("HW-Reset");
  93. #if defined (__AVR__)
  94. sbi(DDRE, 4);
  95. sbi(PORTE, 4);
  96. Delay(100000);
  97. cbi(PORTE, 4);
  98. Delay(250000);
  99. #endif
  100. }
  101. }
  102. return -1;
  103. }
  104. static int DetectNicEeprom(void)
  105. {
  106. #ifdef __AVR_ENHANCED__
  107. register unsigned int cnt = 0;
  108. cli();
  109. /*
  110. * Prepare the EEPROM emulation port bits. Configure the EEDO
  111. * and the EEMU lines as outputs and set both lines to high.
  112. */
  113. outb(PORTC, 0xC0);
  114. outb(DDRC, 0xC0);
  115. /*
  116. * Force the chip to re-read the EEPROM contents.
  117. */
  118. nic_outlb(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);
  119. nic_outlb(NIC_PG3_EECR, NIC_EECR_EEM0);
  120. /*
  121. * No external memory access beyond this point.
  122. */
  123. #if defined(__AVR_AT90CAN128__) || defined(__AVR_ATmega2561__)
  124. cbi(XMCRA, SRE);
  125. #else
  126. cbi(MCUCR, SRE);
  127. #endif
  128. /*
  129. * Check, if the chip toggles our EESK input. If not, we do not
  130. * have EEPROM emulation hardware.
  131. */
  132. if(bit_is_set(PINC, 5)) {
  133. while(++cnt && bit_is_set(PINC, 5));
  134. }
  135. else {
  136. while(++cnt && bit_is_clear(PINC, 5));
  137. }
  138. /*
  139. * Enable memory interface.
  140. */
  141. #if defined(__AVR_AT90CAN128__) || defined(__AVR_ATmega2561__)
  142. sbi(XMCRA, SRE);
  143. #else
  144. sbi(MCUCR, SRE);
  145. #endif
  146. /* Reset port outputs to default. */
  147. outb(PORTC, 0x00);
  148. outb(DDRC, 0x00);
  149. /* Wait until controller ready. */
  150. while(nic_inlb(NIC_CR) != (NIC_CR_STP | NIC_CR_RD2));
  151. sei();
  152. return cnt ? 0 : -1;
  153. #else
  154. return -1;
  155. #endif
  156. }
  157. /*
  158. * Emulated EEPROM contents.
  159. *
  160. * In jumper mode our influence is quite limited, only CONFIG3 and CONFIG4
  161. * can be modified.
  162. */
  163. static prog_char nic_eeprom[18] = {
  164. 0xFF, /* CONFIG2: jPL1 jPL0 0 jBS4 jBS3 jBS2 jBS1 jBS0 */
  165. 0xFF, /* CONFIG1: 1 jIRQS2 jIRQS1 jIRQS0 jIOS3 jIOS2 jIOS1 jIOS0 */
  166. 0xFF, /* CONFIG4: - - - - - - - IOMS */
  167. 0x30, /* CONFIG3 PNP FUDUP LEDS1 LEDS0 - 0 PWRDN ACTB */
  168. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* MAC */
  169. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF /* ID */
  170. };
  171. /*!
  172. * \brief EEPROM emulator.
  173. *
  174. * Forces the chip to re-read the EEPROM contents and emulates a serial
  175. * EEPROM.
  176. *
  177. * If the hardware does not support this feature, then this call will
  178. * never return. Thus, make sure to have the driver properly configured.
  179. */
  180. static void EmulateNicEeprom(void)
  181. {
  182. #ifdef __AVR_ENHANCED__
  183. register uint8_t clk;
  184. register uint8_t cnt;
  185. register uint8_t val;
  186. /*
  187. * Prepare the EEPROM emulation port bits. Configure the EEDO and
  188. * the EEMU lines as outputs and set EEDO to low and EEMU to high.
  189. */
  190. outb(PORTC, 0xC0);
  191. outb(DDRC, 0xC0);
  192. /*
  193. * Start EEPROM configuration. Stop/abort any activity and select
  194. * configuration page 3. Setting bit EEM0 will force the controller
  195. * to read the EEPROM contents.
  196. */
  197. /* Select page 3, stop and abort/complete. */
  198. nic_outlb(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);
  199. nic_outlb(NIC_PG3_EECR, NIC_EECR_EEM0);
  200. /*
  201. * We can avoid wasting port pins for EEPROM emulation by using the
  202. * upper bits of the address bus.
  203. */
  204. /*
  205. * No external memory access beyond this point.
  206. */
  207. #if defined(__AVR_AT90CAN128__) || defined(__AVR_ATmega2561__)
  208. cbi(XMCRA, SRE);
  209. #else
  210. cbi(MCUCR, SRE);
  211. #endif
  212. /*
  213. * Loop for all EEPROM words.
  214. */
  215. for(cnt = 0; cnt < sizeof(nic_eeprom); ) {
  216. /*
  217. *
  218. * 1 start bit, always high
  219. * 2 op-code bits
  220. * 7 address bits
  221. * 1 dir change bit, always low
  222. */
  223. for(clk = 0; clk < 11; clk++) {
  224. while(bit_is_clear(RTL_EESK_PIN, RTL_EESK_BIT));
  225. while(bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT));
  226. }
  227. /*
  228. * Shift out the high byte, MSB first. Our data changes at the EESK
  229. * rising edge. Data is sampled by the Realtek at the falling edge.
  230. */
  231. val = PRG_RDB(nic_eeprom + cnt);
  232. cnt++;
  233. for(clk = 0x80; clk; clk >>= 1) {
  234. while(bit_is_clear(RTL_EESK_PIN, RTL_EESK_BIT));
  235. if(val & clk)
  236. sbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
  237. while(bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT));
  238. cbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
  239. }
  240. /*
  241. * Shift out the low byte.
  242. */
  243. val = PRG_RDB(nic_eeprom + cnt);
  244. cnt++;
  245. for(clk = 0x80; clk; clk >>= 1) {
  246. while(bit_is_clear(RTL_EESK_PIN, RTL_EESK_BIT));
  247. if(val & clk)
  248. sbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
  249. while(bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT));
  250. cbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
  251. }
  252. /* 5 remaining clock cycles. */
  253. for(clk = 0; clk < 5; clk++) {
  254. while(bit_is_clear(RTL_EESK_PIN, RTL_EESK_BIT));
  255. while(bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT));
  256. }
  257. }
  258. /*
  259. * Enable memory interface.
  260. */
  261. #if defined(__AVR_AT90CAN128__) || defined(__AVR_ATmega2561__)
  262. sbi(XMCRA, SRE);
  263. #else
  264. sbi(MCUCR, SRE);
  265. #endif
  266. /* Reset port outputs to default. */
  267. outb(PORTC, 0x00);
  268. outb(DDRC, 0x00);
  269. #endif
  270. }
  271. static int RealtekProbe(size_t addr)
  272. {
  273. uint8_t bv;
  274. nic_base = (uint8_t *)addr;
  275. bv = nic_inlb(NIC_CR);
  276. if(bv & (NIC_CR_PS0 | NIC_CR_PS1)) {
  277. nic_outlb(NIC_CR, NIC_CR_STP | NIC_CR_RD2);
  278. }
  279. if(nic_inw(NIC_PG0_RBCR0) != 0x7050) {
  280. return -1;
  281. }
  282. return 0;
  283. }
  284. /*!
  285. * \brief Detect an RTL8019AS chip.
  286. */
  287. int RealtekDetect(void)
  288. {
  289. size_t addr;
  290. if (RealtekProbe(NIC_BASE) == 0) {
  291. return 0;
  292. }
  293. for (addr = 0x8000; addr; addr += 0x100) {
  294. if (RealtekProbe(addr) == 0) {
  295. return 0;
  296. }
  297. }
  298. return -1;
  299. }
  300. void RealtekLoop(void)
  301. {
  302. printf_P(presskey_P);
  303. for (;;) {
  304. nic_outlb(NIC_CR, NIC_CR_STP | NIC_CR_RD2);
  305. printf("\rid=0x%04X", nic_inw(NIC_PG0_RBCR0));
  306. if (GetChar()) {
  307. puts("");
  308. return;
  309. }
  310. }
  311. }
  312. int RealtekTest(void)
  313. {
  314. int i;
  315. uint8_t force_swreset = 0;
  316. volatile uint8_t *base = nic_base;
  317. uint16_t nic_id;
  318. /*
  319. * NIC ID detection loop.
  320. */
  321. for (;;) {
  322. /*
  323. * Reset loop.
  324. */
  325. for (;;) {
  326. /*
  327. * The hardware reset pin of the nic is connected
  328. * to bit 4 on port E. Make this pin an output pin
  329. * and toggle it.
  330. */
  331. #if defined(__AVR__)
  332. sbi(DDRE, 4);
  333. sbi(PORTE, 4);
  334. Delay(2000);
  335. cbi(PORTE, 4);
  336. Delay(20000);
  337. #endif
  338. /*
  339. * If the hardware reset didn't set the nic in reset
  340. * state, perform an additional software reset and
  341. * wait until the controller enters the reset state.
  342. */
  343. if (force_swreset || (*(base + 7) & 0x80) == 0) {
  344. *(base + 0x1f) = *(base + 0x1f);
  345. Delay(200000);
  346. for (i = 0; i < 255; i++) {
  347. if (*(base + 7) & 0x80) {
  348. break;
  349. }
  350. }
  351. if (i < 255) {
  352. break;
  353. }
  354. puts("failed\x07");
  355. } else {
  356. break;
  357. }
  358. if (uart_bs >= 0)
  359. break;
  360. }
  361. nic_id = nic_inw(NIC_PG0_RBCR0);
  362. if (nic_id == 0x7050) {
  363. puts("OK");
  364. break;
  365. }
  366. printf("failed, got 0x%04X, expected 0x7050\n\x07", nic_id);
  367. if (force_swreset && uart_bs >= 0)
  368. break;
  369. force_swreset = 1;
  370. }
  371. return 0;
  372. }
  373. #define NIC_PAGE_SIZE 0x100
  374. #define NIC_START_PAGE 0x40
  375. #define NIC_STOP_PAGE 0x60
  376. #define NIC_TX_PAGES 6
  377. #define NIC_TX_BUFFERS 2
  378. #define NIC_FIRST_TX_PAGE NIC_START_PAGE
  379. #define NIC_FIRST_RX_PAGE (NIC_FIRST_TX_PAGE + NIC_TX_PAGES * NIC_TX_BUFFERS)
  380. #define TX_PAGES 12
  381. void RealtekSend(void)
  382. {
  383. uint8_t mac[] = {
  384. 0x00, 0x06, 0x98, 0x00, 0x00, 0x00
  385. };
  386. uint16_t sz;
  387. uint16_t i;
  388. volatile uint8_t *base = nic_base;
  389. uint8_t rb;
  390. uint32_t cnt = 0;
  391. printf("Init controller...");
  392. nic_write(NIC_PG0_IMR, 0);
  393. nic_write(NIC_PG0_ISR, 0xff);
  394. if (NicReset())
  395. return;
  396. printf(" detecting...");
  397. Delay(200000);
  398. if (DetectNicEeprom() == 0) {
  399. printf("EEPROM Emulation...");
  400. EmulateNicEeprom();
  401. }
  402. nic_write(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);
  403. nic_write(NIC_PG3_EECR, NIC_EECR_EEM0 | NIC_EECR_EEM1);
  404. nic_write(NIC_PG3_CONFIG3, 0);
  405. nic_write(NIC_PG3_CONFIG2, NIC_CONFIG2_BSELB);
  406. nic_write(NIC_PG3_EECR, 0);
  407. Delay(50000);
  408. nic_write(NIC_CR, NIC_CR_STP | NIC_CR_RD2);
  409. nic_write(NIC_PG0_DCR, NIC_DCR_LS | NIC_DCR_FT1);
  410. nic_write(NIC_PG0_RBCR0, 0);
  411. nic_write(NIC_PG0_RBCR1, 0);
  412. nic_write(NIC_PG0_RCR, NIC_RCR_MON);
  413. nic_write(NIC_PG0_TCR, NIC_TCR_LB0);
  414. nic_write(NIC_PG0_TPSR, NIC_FIRST_TX_PAGE);
  415. nic_write(NIC_PG0_BNRY, NIC_STOP_PAGE - 1);
  416. nic_write(NIC_PG0_PSTART, NIC_FIRST_RX_PAGE);
  417. nic_write(NIC_PG0_PSTOP, NIC_STOP_PAGE);
  418. nic_write(NIC_PG0_ISR, 0xff);
  419. nic_write(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0);
  420. for (i = 0; i < 6; i++)
  421. nic_write(NIC_PG1_PAR0 + i, mac[i]);
  422. for (i = 0; i < 8; i++)
  423. nic_write(NIC_PG1_MAR0 + i, 0);
  424. nic_write(NIC_PG1_CURR, NIC_START_PAGE + TX_PAGES);
  425. nic_write(NIC_CR, NIC_CR_STP | NIC_CR_RD2);
  426. nic_write(NIC_PG0_RCR, NIC_RCR_AB);
  427. nic_write(NIC_PG0_ISR, 0xff);
  428. nic_write(NIC_PG0_IMR, 0);
  429. nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
  430. nic_write(NIC_PG0_TCR, 0);
  431. Delay(1000000);
  432. puts("done");
  433. nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);
  434. rb = nic_read(NIC_PG3_CONFIG0);
  435. switch (rb & 0xC0) {
  436. case 0x00:
  437. printf("RTL8019AS ");
  438. if (rb & 0x08)
  439. printf("jumper mode: ");
  440. if (rb & 0x20)
  441. printf("AUI ");
  442. if (rb & 0x10)
  443. printf("PNP ");
  444. break;
  445. case 0xC0:
  446. printf("RTL8019 ");
  447. if (rb & 0x08)
  448. printf("jumper mode: ");
  449. break;
  450. default:
  451. printf("Unknown chip ");
  452. break;
  453. }
  454. if (rb & 0x04)
  455. printf("BNC\x07 ");
  456. if (rb & 0x03)
  457. printf("Failed\x07 ");
  458. rb = nic_read(NIC_PG3_CONFIG1);
  459. printf("IRQ%u ", (rb >> 4) & 7);
  460. rb = nic_read(NIC_PG3_CONFIG2);
  461. switch (rb & 0xC0) {
  462. case 0x00:
  463. printf("Auto ");
  464. break;
  465. case 0x40:
  466. printf("10BaseT ");
  467. break;
  468. case 0x80:
  469. printf("10Base5 ");
  470. break;
  471. case 0xC0:
  472. printf("10Base2 ");
  473. break;
  474. }
  475. printf("\n");
  476. nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
  477. for (;;) {
  478. Delay(500000);
  479. printf("\r%lu", cnt++);
  480. sz = 1500;
  481. nic_write(NIC_PG0_RBCR0, sz);
  482. nic_write(NIC_PG0_RBCR1, sz >> 8);
  483. nic_write(NIC_PG0_RSAR0, 0);
  484. nic_write(NIC_PG0_RSAR1, NIC_FIRST_TX_PAGE);
  485. nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD1);
  486. /*
  487. * Transfer ethernet physical header.
  488. */
  489. for (i = 0; i < 6; i++)
  490. nic_write(NIC_IOPORT, 0xFF);
  491. for (i = 0; i < 6; i++)
  492. nic_write(NIC_IOPORT, mac[i]);
  493. nic_write(NIC_IOPORT, 0x08);
  494. nic_write(NIC_IOPORT, 0x00);
  495. /*
  496. * Add pad bytes.
  497. */
  498. for (i = 0; i < sz; i++)
  499. nic_write(NIC_IOPORT, 0);
  500. /*
  501. * Complete remote dma.
  502. */
  503. nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
  504. for (i = 0; i <= 20; i++)
  505. if (nic_read(NIC_PG0_ISR) & NIC_ISR_RDC)
  506. break;
  507. nic_write(NIC_PG0_ISR, NIC_ISR_RDC);
  508. /*
  509. * Number of bytes to be transmitted.
  510. */
  511. nic_write(NIC_PG0_TBCR0, (sz & 0xff));
  512. nic_write(NIC_PG0_TBCR1, ((sz >> 8) & 0xff));
  513. /*
  514. * First page of packet to be transmitted.
  515. */
  516. nic_write(NIC_PG0_TPSR, NIC_FIRST_TX_PAGE);
  517. /*
  518. * Start transmission.
  519. */
  520. nic_write(NIC_CR, NIC_CR_STA | NIC_CR_TXP | NIC_CR_RD2);
  521. if (GetChar())
  522. break;
  523. Delay(10000);
  524. }
  525. }