00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 #include <cfg/os.h>
00082 #include <arch/arm.h>
00083
00084 #include <string.h>
00085 #include <stdlib.h>
00086
00087 #include <sys/atom.h>
00088 #include <sys/heap.h>
00089 #include <sys/thread.h>
00090 #include <sys/event.h>
00091 #include <sys/timer.h>
00092 #include <sys/confnet.h>
00093
00094 #include <netinet/if_ether.h>
00095 #include <net/ether.h>
00096 #include <net/if_var.h>
00097
00098 #include <dev/irqreg.h>
00099 #include <dev/dm9000e.h>
00100
00101
00102 #ifdef NUTDEBUG
00103 #include <stdio.h>
00104 #define DMPRINTF(args,...) printf(args,##__VA_ARGS__)
00105 #else
00106 #define DMPRINTF(args,...)
00107 #endif
00108
00109 #ifndef NUT_THREAD_NICRXSTACK
00110
00111 #define NUT_THREAD_NICRXSTACK 384
00112 #endif
00113
00114
00115
00116
00117 #if defined(ETHERNUT3)
00118
00119 #ifndef NIC_BASE_ADDR
00120 #define NIC_BASE_ADDR 0x20000000
00121 #endif
00122
00123 #ifndef NIC_SIGNAL_IRQ
00124 #define NIC_SIGNAL_IRQ INT1
00125 #endif
00126
00127 #ifndef NIC_SIGNAL_PDR
00128 #define NIC_SIGNAL_PDR PIO_PDR
00129 #endif
00130
00131 #ifndef NIC_SIGNAL_BIT
00132 #define NIC_SIGNAL_BIT 10
00133 #endif
00134
00135 #elif defined(ELEKTOR_IR1)
00136
00137 #ifndef NIC_BASE_ADDR
00138 #define NIC_BASE_ADDR 0x30000000
00139 #endif
00140
00141 #ifndef NIC_SIGNAL_IRQ
00142 #define NIC_SIGNAL_IRQ INT0
00143 #endif
00144
00145 #ifndef NIC_SIGNAL_PDR
00146 #define NIC_SIGNAL_PDR PIOB_PDR
00147 #endif
00148
00149 #ifndef NIC_SIGNAL_XSR
00150 #define NIC_SIGNAL_XSR PIOB_ASR
00151 #endif
00152
00153 #ifndef NIC_SIGNAL_BIT
00154 #define NIC_SIGNAL_BIT PB20_IRQ0_A
00155 #endif
00156
00157 #endif
00158
00159 #ifdef NIC_BASE_ADDR
00160
00161 #ifndef NIC_DATA_ADDR
00162 #define NIC_DATA_ADDR (NIC_BASE_ADDR + 4)
00163 #endif
00164
00165 #define INT0 0
00166 #define INT1 1
00167 #define INT2 2
00168 #define INT3 3
00169 #define INT4 4
00170 #define INT5 5
00171 #define INT6 6
00172 #define INT7 7
00173
00174 #ifdef NIC_RESET_BIT
00175
00176 #if (NIC_RESET_AVRPORT == AVRPORTB)
00177 #define NIC_RESET_PORT PORTB
00178 #define NIC_RESET_DDR DDRB
00179
00180 #elif (NIC_RESET_AVRPORT == AVRPORTD)
00181 #define NIC_RESET_PORT PORTD
00182 #define NIC_RESET_DDR DDRD
00183
00184 #elif (NIC_RESET_AVRPORT == AVRPORTE)
00185 #define NIC_RESET_PORT PORTE
00186 #define NIC_RESET_DDR DDRE
00187
00188 #elif (NIC_RESET_AVRPORT == AVRPORTF)
00189 #define NIC_RESET_PORT PORTF
00190 #define NIC_RESET_DDR DDRF
00191
00192 #endif
00193
00194 #endif
00195
00196
00197
00198
00199
00200 #if (NIC_SIGNAL_IRQ == INT0)
00201 #define NIC_SIGNAL sig_INTERRUPT0
00202
00203 #elif (NIC_SIGNAL_IRQ == INT2)
00204 #define NIC_SIGNAL sig_INTERRUPT2
00205
00206 #elif (NIC_SIGNAL_IRQ == INT3)
00207 #define NIC_SIGNAL sig_INTERRUPT3
00208
00209 #elif (NIC_SIGNAL_IRQ == INT4)
00210 #define NIC_SIGNAL sig_INTERRUPT4
00211
00212 #elif (NIC_SIGNAL_IRQ == INT5)
00213 #define NIC_SIGNAL sig_INTERRUPT5
00214
00215 #elif (NIC_SIGNAL_IRQ == INT6)
00216 #define NIC_SIGNAL sig_INTERRUPT6
00217
00218 #elif (NIC_SIGNAL_IRQ == INT7)
00219 #define NIC_SIGNAL sig_INTERRUPT7
00220
00221 #else
00222 #define NIC_SIGNAL sig_INTERRUPT1
00223
00224 #endif
00225
00230
00231 #define NIC_NCR 0x00
00232 #define NIC_NCR_LBM 0x06
00233 #define NIC_NCR_LBNORM 0x00
00234 #define NIC_NCR_LBMAC 0x02
00235 #define NIC_NCR_LBPHY 0x04
00236 #define NIC_NCR_RST 0x01
00237
00238 #define NIC_NSR 0x01
00239 #define NIC_NSR_SPEED 0x80
00240 #define NIC_NSR_LINKST 0x40
00241 #define NIC_NSR_WAKEST 0x20
00242 #define NIC_NSR_TX2END 0x08
00243 #define NIC_NSR_TX1END 0x04
00244 #define NIC_NSR_RXOV 0x02
00245
00246 #define NIC_TCR 0x02
00247 #define NIC_TCR_TXREQ 0x01
00248
00249 #define NIC_TSR1 0x03
00250
00251 #define NIC_TSR2 0x04
00252
00253 #define NIC_RCR 0x05
00254 #define NIC_RCR_DIS_LONG 0x20
00255 #define NIC_RCR_DIS_CRC 0x10
00256 #define NIC_RCR_ALL 0x08
00257 #define NIC_RCR_PRMSC 0x02
00258 #define NIC_RCR_RXEN 0x01
00259
00260 #define NIC_RSR 0x06
00261 #define NIC_RSR_ERRORS 0xBF
00262 #define NIC_RSR_RF 0x80
00263 #define NIC_RSR_MF 0x40
00264 #define NIC_RSR_LCS 0x20
00265 #define NIC_RSR_RWTO 0x10
00266 #define NIC_RSR_PLE 0x08
00267 #define NIC_RSR_AE 0x04
00268 #define NIC_RSR_CE 0x02
00269 #define NIC_RSR_FOE 0x01
00270
00271 #define NIC_ROCR 0x07
00272
00273 #define NIC_BPTR 0x08
00274
00275 #define NIC_FCTR 0x09
00276
00277 #define NIC_FCR 0x0A
00278
00279 #define NIC_EPCR 0x0B
00280
00281 #define NIC_EPAR 0x0C
00282
00283 #define NIC_EPDRL 0x0D
00284
00285 #define NIC_EPDRH 0x0E
00286
00287 #define NIC_WCR 0x0F
00288
00289 #define NIC_PAR 0x10
00290
00291 #define NIC_MAR 0x16
00292
00293 #define NIC_GPCR 0x1E
00294
00295 #define NIC_GPR 0x1F
00296
00297 #define NIC_TRPA 0x22
00298
00299 #define NIC_RWPA 0x24
00300
00301 #define NIC_VID 0x28
00302
00303 #define NIC_PID 0x2A
00304
00305 #define NIC_CHIPR 0x2C
00306
00307 #define NIC_SMCR 0x2F
00308
00309 #define NIC_MRCMDX 0xF0
00310
00311 #define NIC_MRCMD 0xF2
00312
00313 #define NIC_MRR 0xF4
00314
00315 #define NIC_MWCMDX 0xF6
00316
00317 #define NIC_MWCMD 0xF8
00318
00319 #define NIC_MWR 0xFA
00320
00321 #define NIC_TXPL 0xFC
00322
00323 #define NIC_ISR 0xFE
00324 #define NIC_ISR_IOM 0xC0
00325 #define NIC_ISR_M16 0x00
00326 #define NIC_ISR_M32 0x40
00327 #define NIC_ISR_M8 0x80
00328 #define NIC_ISR_ROOS 0x08
00329 #define NIC_ISR_ROS 0x04
00330 #define NIC_ISR_PTS 0x02
00331 #define NIC_ISR_PRS 0x01
00332
00333 #define NIC_IMR 0xFF
00334 #define NIC_IMR_PAR 0x80
00335 #define NIC_IMR_ROOM 0x08
00336 #define NIC_IMR_ROM 0x04
00337 #define NIC_IMR_PTM 0x02
00338 #define NIC_IMR_PRM 0x01
00339
00340 #define NIC_PHY_BMCR 0x00
00341
00342 #define NIC_PHY_BMSR 0x01
00343 #define NIC_PHY_BMSR_ANCOMPL 0x0020
00344 #define NIC_PHY_BMSR_LINKSTAT 0x0004
00345
00346 #define NIC_PHY_ID1 0x02
00347
00348 #define NIC_PHY_ID2 0x03
00349
00350 #define NIC_PHY_ANAR 0x04
00351
00352 #define NIC_PHY_ANLPAR 0x05
00353
00354 #define NIC_PHY_ANER 0x06
00355
00356 #define NIC_PHY_DSCR 0x10
00357
00358 #define NIC_PHY_DSCSR 0x11
00359
00360 #define NIC_PHY_10BTCSR 0x12
00361
00365 struct _NICINFO {
00366 #ifdef NUT_PERFMON
00367 uint32_t ni_rx_packets;
00368 uint32_t ni_tx_packets;
00369 uint32_t ni_overruns;
00370 uint32_t ni_rx_frame_errors;
00371 uint32_t ni_rx_crc_errors;
00372 uint32_t ni_rx_missed_errors;
00373 #endif
00374 HANDLE volatile ni_rx_rdy;
00375 HANDLE volatile ni_tx_rdy;
00376 HANDLE ni_mutex;
00377 volatile int ni_tx_queued;
00378 volatile int ni_tx_quelen;
00379 volatile int ni_insane;
00380 int ni_iomode;
00381 uint8_t ni_mar[8];
00382 };
00383
00387 typedef struct _NICINFO NICINFO;
00388
00395
00396
00397
00398
00399
00400 static const uint32_t crctab[] = {
00401 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
00402 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
00403 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
00404 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
00405 };
00406
00407 static uint32_t ether_crc32_le(const uint8_t *buf, uint8_t len)
00408 {
00409 uint32_t crc;
00410 uint8_t i;
00411
00412 crc = 0xffffffff;
00413
00414 for (i = 0; i < len; i++) {
00415 crc ^= buf[i];
00416 crc = (crc >> 4) ^ crctab[crc & 0xf];
00417 crc = (crc >> 4) ^ crctab[crc & 0xf];
00418 }
00419
00420 return (crc);
00421 }
00422
00423 static INLINE void nic_outb(uint8_t reg, uint8_t val)
00424 {
00425 outb(NIC_BASE_ADDR, reg);
00426 outb(NIC_DATA_ADDR, val);
00427 }
00428
00429 static INLINE uint8_t nic_inb(uint16_t reg)
00430 {
00431 outb(NIC_BASE_ADDR, reg);
00432 return inb(NIC_DATA_ADDR);
00433 }
00434
00442 static uint16_t phy_inw(uint8_t reg)
00443 {
00444
00445 nic_outb(NIC_EPAR, 0x40 | reg);
00446
00447
00448 nic_outb(NIC_EPCR, 0x0C);
00449 NutDelay(1);
00450 nic_outb(NIC_EPCR, 0x00);
00451
00452
00453 return ((uint16_t) nic_inb(NIC_EPDRH) << 8) | (uint16_t) nic_inb(NIC_EPDRL);
00454 }
00455
00464 static void phy_outw(uint8_t reg, uint16_t val)
00465 {
00466
00467 nic_outb(NIC_EPAR, 0x40 | reg);
00468
00469
00470 nic_outb(NIC_EPDRL, (uint8_t) val);
00471 nic_outb(NIC_EPDRH, (uint8_t) (val >> 8));
00472
00473
00474 nic_outb(NIC_EPCR, 0x0A);
00475 NutDelay(1);
00476 nic_outb(NIC_EPCR, 0x00);
00477 }
00478
00479 static int NicPhyInit(void)
00480 {
00481
00482 phy_outw(NIC_PHY_ANAR, 0x01E1);
00483 phy_outw(NIC_PHY_BMCR, 0x1200);
00484
00485 nic_outb(NIC_GPCR, 1);
00486 nic_outb(NIC_GPR, 0);
00487
00488 return 0;
00489 }
00490
00496 static int NicReset(void)
00497 {
00498
00499 #ifdef undef_NIC_RESET_BIT
00500 sbi(NIC_RESET_DDR, NIC_RESET_BIT);
00501 sbi(NIC_RESET_PORT, NIC_RESET_BIT);
00502 NutDelay(WAIT100);
00503 cbi(NIC_RESET_PORT, NIC_RESET_BIT);
00504 NutDelay(WAIT250);
00505 NutDelay(WAIT250);
00506 #else
00507
00508 nic_outb(NIC_NCR, NIC_NCR_RST | NIC_NCR_LBMAC);
00509 NutDelay(1);
00510
00511 #endif
00512 DMPRINTF("\n*DMRES*\n");
00513 return NicPhyInit();
00514 }
00515
00516
00517
00518
00519 static void NicInterrupt(void *arg)
00520 {
00521 uint_fast8_t isr;
00522 NICINFO *ni = (NICINFO *) ((NUTDEVICE *) arg)->dev_dcb;
00523
00524
00525 isr = nic_inb(NIC_ISR);
00526 DMPRINTF("*DMIRQ %02x:", isr);
00527
00528
00529 if (isr & NIC_ISR_PRS) {
00530 DMPRINTF("RX*");
00531 nic_outb(NIC_ISR, NIC_ISR_PRS);
00532 NutEventPostFromIrq(&ni->ni_rx_rdy);
00533 }
00534
00535
00536 if (isr & NIC_ISR_PTS) {
00537 DMPRINTF("TX*");
00538 if (ni->ni_tx_queued) {
00539 if (ni->ni_tx_quelen) {
00540
00541 nic_outb(NIC_TXPL, (uint8_t) ni->ni_tx_quelen);
00542 nic_outb(NIC_TXPL + 1, (uint8_t) (ni->ni_tx_quelen >> 8));
00543 ni->ni_tx_quelen = 0;
00544 nic_outb(NIC_TCR, NIC_TCR_TXREQ);
00545 }
00546 ni->ni_tx_queued--;
00547 }
00548 nic_outb(NIC_ISR, NIC_ISR_PTS);
00549 NutEventPostFromIrq(&ni->ni_tx_rdy);
00550 }
00551
00552
00553 if (isr & NIC_ISR_ROS) {
00554 DMPRINTF("OVI*");
00555 nic_outb(NIC_ISR, NIC_ISR_ROS);
00556 ni->ni_insane = 1;
00557 NutEventPostFromIrq(&ni->ni_rx_rdy);
00558 }
00559
00560
00561 if (isr & NIC_ISR_ROOS) {
00562 DMPRINTF("OVC*");
00563 nic_outb(NIC_ISR, NIC_ISR_ROOS);
00564 NutEventPostFromIrq(&ni->ni_rx_rdy);
00565 }
00566
00567 if( ni->ni_insane)
00568 DMPRINTF("INS\n");
00569 else
00570 DMPRINTF("\n");
00571 }
00572
00578 static void NicWrite8(uint8_t * buf, uint16_t len)
00579 {
00580 while (len--) {
00581 outb(NIC_DATA_ADDR, *buf);
00582 buf++;
00583 }
00584 }
00585
00591 static void NicWrite16(uint8_t * buf, uint16_t len)
00592 {
00593 uint16_t *wp = (uint16_t *) buf;
00594
00595 len = (len + 1) / 2;
00596 while (len--) {
00597 outw(NIC_DATA_ADDR, *wp);
00598 wp++;
00599 }
00600 }
00601
00607 static void NicRead8(uint8_t * buf, uint16_t len)
00608 {
00609 while (len--) {
00610 *buf++ = inb(NIC_DATA_ADDR);
00611 }
00612 }
00613
00619 static void NicRead16(uint8_t * buf, uint16_t len)
00620 {
00621 uint16_t *wp = (uint16_t *) buf;
00622
00623 len = (len + 1) / 2;
00624 while (len--) {
00625 *wp++ = inw(NIC_DATA_ADDR);
00626 }
00627 }
00628
00637 static int NicGetPacket(NICINFO * ni, NETBUF ** nbp)
00638 {
00639 int rc = -1;
00640 uint16_t fsw;
00641 uint16_t fbc;
00642
00643 *nbp = NULL;
00644
00645
00646 NutIrqDisable(&NIC_SIGNAL);
00647
00648
00649
00650
00651
00652
00653 nic_inb(NIC_MRCMDX);
00654
00655 _NOP(); _NOP(); _NOP(); _NOP();
00656 fsw = inb(NIC_DATA_ADDR);
00657 if (fsw > 1) {
00658 ni->ni_insane = 1;
00659 } else if (fsw) {
00660
00661 outb(NIC_BASE_ADDR, NIC_MRCMD);
00662 if (ni->ni_iomode == NIC_ISR_M16) {
00663 fsw = inw(NIC_DATA_ADDR);
00664 _NOP(); _NOP(); _NOP(); _NOP();
00665 fbc = inw(NIC_DATA_ADDR);
00666 } else {
00667 fsw = inb(NIC_DATA_ADDR) + ((uint16_t) inb(NIC_DATA_ADDR) << 8);
00668 _NOP(); _NOP(); _NOP(); _NOP();
00669 fbc = inb(NIC_DATA_ADDR) + ((uint16_t) inb(NIC_DATA_ADDR) << 8);
00670 }
00671
00672
00673
00674
00675
00676
00677 if (fbc > 1536) {
00678 ni->ni_insane = 1;
00679 } else {
00680
00681
00682
00683
00684 fsw >>= 8;
00685 fsw &= NIC_RSR_ERRORS;
00686 #ifdef NUT_PERMON
00687
00688 if (fsw) {
00689 if (RxStatus & NIC_RSR_CE) {
00690 ni->ni_crc_errors++;
00691 } else if (RxStatus & NIC_RSR_FOE) {
00692 ni->ni_overruns++;
00693 } else {
00694 ni->ni_rx_missed_errors++;
00695 }
00696 } else {
00697 ni->ni_rx_packets++;
00698 }
00699 #endif
00700
00701
00702
00703
00704 if (fsw || (*nbp = NutNetBufAlloc(0, NBAF_DATALINK, fbc - 4)) == NULL) {
00705 if (ni->ni_iomode == NIC_ISR_M16) {
00706 fbc = (fbc + 1) / 2;
00707 while (fbc--) {
00708 fsw = inw(NIC_DATA_ADDR);
00709 }
00710 } else {
00711 while (fbc--) {
00712 fsw = inb(NIC_DATA_ADDR);
00713 }
00714 }
00715 } else {
00716 if (ni->ni_iomode == NIC_ISR_M16) {
00717
00718 NicRead16((*nbp)->nb_dl.vp, (*nbp)->nb_dl.sz);
00719
00720 fsw = inw(NIC_DATA_ADDR);
00721 fsw = inw(NIC_DATA_ADDR);
00722 } else {
00723
00724 NicRead8((*nbp)->nb_dl.vp, (*nbp)->nb_dl.sz);
00725
00726 fsw = inb(NIC_DATA_ADDR);
00727 fsw = inb(NIC_DATA_ADDR);
00728 fsw = inb(NIC_DATA_ADDR);
00729 fsw = inb(NIC_DATA_ADDR);
00730 }
00731
00732 rc = 0;
00733 }
00734 }
00735 }
00736
00737
00738 if (ni->ni_insane == 0) {
00739 NutIrqEnable(&NIC_SIGNAL);
00740 }
00741 return rc;
00742 }
00743
00756 static int NicPutPacket(NICINFO * ni, NETBUF * nb)
00757 {
00758 int rc = -1;
00759 uint16_t sz;
00760
00761
00762
00763
00764
00765
00766
00767 if ((sz = nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz) > ETHERMTU) {
00768 return -1;
00769 }
00770 sz += nb->nb_dl.sz;
00771 if (sz & 1) {
00772 sz++;
00773 }
00774
00775
00776 NutIrqDisable(&NIC_SIGNAL);
00777
00778
00779 if (ni->ni_insane == 0) {
00780
00781 outb(NIC_BASE_ADDR, NIC_MWCMD);
00782
00783
00784 if (ni->ni_iomode == NIC_ISR_M16) {
00785 NicWrite16(nb->nb_dl.vp, nb->nb_dl.sz);
00786 NicWrite16(nb->nb_nw.vp, nb->nb_nw.sz);
00787 NicWrite16(nb->nb_tp.vp, nb->nb_tp.sz);
00788 NicWrite16(nb->nb_ap.vp, nb->nb_ap.sz);
00789 } else {
00790 NicWrite8(nb->nb_dl.vp, nb->nb_dl.sz);
00791 NicWrite8(nb->nb_nw.vp, nb->nb_nw.sz);
00792 NicWrite8(nb->nb_tp.vp, nb->nb_tp.sz);
00793 NicWrite8(nb->nb_ap.vp, nb->nb_ap.sz);
00794 }
00795
00796
00797 if (ni->ni_tx_queued == 0) {
00798 nic_outb(NIC_TXPL, (uint8_t) sz);
00799 nic_outb(NIC_TXPL + 1, (uint8_t) (sz >> 8));
00800 nic_outb(NIC_TCR, NIC_TCR_TXREQ);
00801 }
00802
00803 else {
00804 ni->ni_tx_quelen = sz;
00805 }
00806 ni->ni_tx_queued++;
00807 rc = 0;
00808 #ifdef NUT_PERFMON
00809 ni->ni_tx_packets++;
00810 #endif
00811 }
00812
00813
00814 NutIrqEnable(&NIC_SIGNAL);
00815
00816
00817
00818 if (rc == 0 && ni->ni_tx_queued > 1) {
00819 NutEventWait(&ni->ni_tx_rdy, 500);
00820 }
00821 return rc;
00822 }
00823
00829 static void NicUpdateMCHardware(NICINFO *ni)
00830 {
00831 int i;
00832
00833
00834 ni->ni_mar[7] |= 0x80;
00835
00836
00837 for (i = 0; i < 7; i++) {
00838 nic_outb(NIC_MAR + i, ni->ni_mar[i]);
00839 }
00840 }
00841
00849 static int NicStart(CONST uint8_t * mac, NICINFO * ni)
00850 {
00851 int i;
00852 int link_wait = 20;
00853
00854
00855 nic_outb(NIC_GPR, 0);
00856 NutDelay(5);
00857
00858
00859 nic_outb(NIC_NCR, NIC_NCR_RST | NIC_NCR_LBMAC);
00860 NutDelay(5);
00861 nic_outb(NIC_NCR, NIC_NCR_RST | NIC_NCR_LBMAC);
00862 NutDelay(5);
00863
00864
00865
00866
00867
00868 nic_outb(NIC_GPR, 1);
00869 nic_outb(NIC_GPR, 0);
00870
00871
00872 for (i = 0; i < 6; i++) {
00873 nic_outb(NIC_PAR + i, mac[i]);
00874 }
00875
00876
00877 NicUpdateMCHardware(ni);
00878
00879
00880 nic_outb(NIC_ISR, NIC_ISR_ROOS | NIC_ISR_ROS | NIC_ISR_PTS | NIC_ISR_PRS);
00881
00882
00883 if (nic_inb(NIC_CHIPR) == 0x19) {
00884 nic_outb(0x2D, 0x40);
00885 }
00886
00887
00888 nic_outb(NIC_RCR, NIC_RCR_DIS_LONG | NIC_RCR_DIS_CRC | NIC_RCR_RXEN | NIC_RCR_ALL);
00889
00890
00891 for (link_wait = 20;; link_wait--) {
00892 if (phy_inw(NIC_PHY_BMSR) & NIC_PHY_BMSR_ANCOMPL) {
00893 break;
00894 }
00895 if (link_wait == 0) {
00896 return -1;
00897 }
00898 NutSleep(200);
00899 }
00900
00901
00902 nic_outb(NIC_IMR, NIC_IMR_PAR | NIC_IMR_PTM | NIC_IMR_PRM);
00903
00904 return 0;
00905 }
00906
00911 THREAD(NicRxLanc, arg)
00912 {
00913 NUTDEVICE *dev;
00914 IFNET *ifn;
00915 NICINFO *ni;
00916 NETBUF *nb;
00917
00918 dev = arg;
00919 ifn = (IFNET *) dev->dev_icb;
00920 ni = (NICINFO *) dev->dev_dcb;
00921
00922
00923
00924
00925
00926
00927 while (!ETHER_IS_UNICAST(ifn->if_mac)) {
00928 NutSleep(10);
00929 }
00930
00931
00932
00933
00934
00935
00936
00937 while (NicStart(ifn->if_mac, ni)) {
00938 NutSleep(1000);
00939 }
00940
00941
00942 NutEventPost(&ni->ni_mutex);
00943
00944
00945 NutThreadSetPriority(9);
00946
00947
00948 #ifdef NIC_SIGNAL_XSR
00949 outr(NIC_SIGNAL_XSR, _BV(NIC_SIGNAL_BIT));
00950 #if defined(ELEKTOR_IR1)
00951
00952 outr(PMC_PCER, _BV(IRQ0_ID));
00953 #endif
00954 #endif
00955 outr(NIC_SIGNAL_PDR, _BV(NIC_SIGNAL_BIT));
00956 NutIrqEnable(&NIC_SIGNAL);
00957 #if defined(ELEKTOR_IR1)
00958
00959 NutIrqSetMode(&NIC_SIGNAL, NUT_IRQMODE_HIGHLEVEL);
00960 #endif
00961
00962 for (;;) {
00963
00964
00965
00966
00967 NutEventWait(&ni->ni_rx_rdy, 2000);
00968
00969
00970
00971
00972
00973 while (NicGetPacket(ni, &nb) == 0) {
00974
00975
00976 if (nb->nb_dl.sz < 60) {
00977 NutNetBufFree(nb);
00978 } else {
00979 (*ifn->if_recv) (dev, nb);
00980 }
00981 }
00982
00983
00984 while (ni->ni_insane) {
00985 if (NicStart(ifn->if_mac, ni) == 0) {
00986 ni->ni_insane = 0;
00987 ni->ni_tx_queued = 0;
00988 ni->ni_tx_quelen = 0;
00989 NutIrqEnable(&NIC_SIGNAL);
00990 } else {
00991 NutSleep(1000);
00992 }
00993 }
00994 }
00995 }
00996
01007 int DmOutput(NUTDEVICE * dev, NETBUF * nb)
01008 {
01009 static uint32_t mx_wait = 5000;
01010 int rc = -1;
01011 NICINFO *ni = (NICINFO *) dev->dev_dcb;
01012
01013
01014
01015
01016
01017 while (rc) {
01018 if (ni->ni_insane) {
01019 break;
01020 }
01021 if (NutEventWait(&ni->ni_mutex, mx_wait)) {
01022 break;
01023 }
01024
01025
01026 if (ni->ni_tx_queued > 1) {
01027 if (NutEventWait(&ni->ni_tx_rdy, 500)) {
01028
01029 NutEventPost(&ni->ni_mutex);
01030 break;
01031 }
01032 } else if (NicPutPacket(ni, nb) == 0) {
01033
01034
01035 rc = 0;
01036 mx_wait = 5000;
01037 }
01038 NutEventPost(&ni->ni_mutex);
01039 }
01040
01041
01042
01043
01044 if (rc) {
01045 mx_wait = 500;
01046 }
01047 return rc;
01048 }
01049
01067 int DmInit(NUTDEVICE * dev)
01068 {
01069 uint32_t id;
01070 NICINFO *ni = (NICINFO *) dev->dev_dcb;
01071
01072 #if defined(ELEKTOR_IR1)
01073
01074
01075 outr(PIOC_SODR, _BV(PC17_NANDOE_B));
01076 outr(PIOC_PER, _BV(PC17_NANDOE_B));
01077 outr(PIOC_OER, _BV(PC17_NANDOE_B));
01078 outr(PIOC_CODR, _BV(PC17_NANDOE_B));
01079 NutDelay(WAIT250);
01080 NutDelay(WAIT250);
01081 NutDelay(WAIT250);
01082 NutDelay(WAIT250);
01083 outr(PIOC_SODR, _BV(PC17_NANDOE_B));
01084 NutDelay(WAIT250);
01085 NutDelay(WAIT250);
01086 NutDelay(WAIT250);
01087 NutDelay(WAIT250);
01088
01089
01090 outr(PIOA_BSR, _BV(PA20_NCS2_B));
01091 outr(PIOA_PDR, _BV(PA20_NCS2_B));
01092 outr(PIOC_BSR, _BV(PC16_NWAIT_B) | _BV(PC21_NWR0_B) | _BV(PC22_NRD_B));
01093 outr(PIOC_PDR, _BV(PC16_NWAIT_B) | _BV(PC21_NWR0_B) | _BV(PC22_NRD_B));
01094
01095 outr(SMC_CSR(2)
01096 , (1 << SMC_NWS_LSB)
01097 | SMC_WSEN
01098 | (2 << SMC_TDF_LSB)
01099 | SMC_BAT
01100 | SMC_DBW_16
01101 | (1 << SMC_RWSETUP_LSB)
01102 | (1 << SMC_RWHOLD_LSB)
01103 );
01104 #endif
01105
01106
01107 id = (uint32_t) nic_inb(NIC_VID);
01108 id |= (uint32_t) nic_inb(NIC_VID + 1) << 8;
01109 id |= (uint32_t) nic_inb(NIC_PID) << 16;
01110 id |= (uint32_t) nic_inb(NIC_PID + 1) << 24;
01111 if (id != 0x90000A46) {
01112 return -1;
01113 }
01114
01115
01116 if (NicReset()) {
01117 return -1;
01118 }
01119
01120
01121 memset(ni, 0, sizeof(NICINFO));
01122
01123
01124 ni->ni_iomode = nic_inb(NIC_ISR) & NIC_ISR_IOM;
01125 if (ni->ni_iomode == NIC_ISR_M32) {
01126 return -1;
01127 }
01128
01129
01130 if (NutRegisterIrqHandler(&NIC_SIGNAL, NicInterrupt, dev)) {
01131 return -1;
01132 }
01133
01134
01135 if (NutThreadCreate("rxi1", NicRxLanc, dev,
01136 (NUT_THREAD_NICRXSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD) == NULL) {
01137 return -1;
01138 }
01139 return 0;
01140 }
01141
01142 static int DmIOCtl(NUTDEVICE * dev, int req, void *conf)
01143 {
01144 int rc = 0;
01145 int i;
01146 IFNET *nif = (IFNET *) dev->dev_icb;
01147 NICINFO *ni = (NICINFO *) dev->dev_dcb;
01148 uint32_t index;
01149 uint32_t ip_addr;
01150 MCASTENTRY *mcast;
01151 MCASTENTRY *mcast_prev;
01152 MCASTENTRY *mcast_next;
01153
01154 uint8_t mac[6];
01155
01156 switch (req) {
01157
01158 case SIOCSIFADDR:
01159
01160 memcpy(nif->if_mac, conf, sizeof(nif->if_mac));
01161 break;
01162
01163
01164 case SIOCADDMULTI:
01165 ip_addr = *((uint32_t*)conf);
01166
01167
01168 mcast = nif->if_mcast;
01169 while(mcast)
01170 {
01171 if (ip_addr == mcast->mca_ip)
01172 {
01173
01174 return -1;
01175 }
01176 mcast = mcast->mca_next;
01177 }
01178
01179
01180 mac[0] = 0x01;
01181 mac[1] = 0x00;
01182 mac[2] = 0x5E;
01183 mac[3] = ((uint8_t*)conf)[1] & 0x7f;
01184 mac[4] = ((uint8_t*)conf)[2];
01185 mac[5] = ((uint8_t*)conf)[3];
01186
01187 mcast = malloc(sizeof(MCASTENTRY));
01188 if (mcast != NULL) {
01189
01190 index = ether_crc32_le(&mac[0], 6);
01191 index &= 0x3F;
01192
01193
01194 ni->ni_mar[index / 8] |= (1 << (index % 8));
01195
01196
01197 memcpy(mcast->mca_ha, mac, 6);
01198 mcast->mca_ip = *((uint32_t*)conf);
01199 mcast->mca_next = nif->if_mcast;
01200 nif->if_mcast = mcast;
01201
01202
01203 NicUpdateMCHardware(ni);
01204 }
01205 else {
01206 rc = -1;
01207 }
01208 break;
01209
01210
01211 case SIOCDELMULTI:
01212 ip_addr = *((uint32_t*)conf);
01213
01214
01215 mcast = nif->if_mcast;
01216 mcast_prev = mcast;
01217 while(mcast)
01218 {
01219 if (ip_addr == mcast->mca_ip)
01220 {
01221
01222 break;
01223 }
01224 mcast_prev = mcast;
01225 mcast = mcast->mca_next;
01226 }
01227
01228 if (NULL == mcast)
01229 {
01230
01231 return -1;
01232 }
01233
01234
01235
01236
01237 mcast_next = mcast->mca_next;
01238
01239
01240 if (nif->if_mcast == mcast)
01241 {
01242
01243
01244
01245
01246
01247 nif->if_mcast = mcast_next;
01248 free(mcast);
01249 } else {
01250
01251
01252
01253
01254
01255 mcast_prev->mca_next = mcast_next;
01256 free(mcast);
01257 }
01258
01259
01260
01261
01262
01263
01264 for (i = 0; i < 7; i++) {
01265 ni->ni_mar[i] = 0;
01266 }
01267
01268
01269 mcast = nif->if_mcast;
01270 while(mcast)
01271 {
01272
01273 index = ether_crc32_le(&mcast->mca_ha[0], 6);
01274 index &= 0x3F;
01275
01276
01277 ni->ni_mar[index / 8] |= (1 << (index % 8));
01278
01279 mcast = mcast->mca_next;
01280 }
01281
01282
01283 NicUpdateMCHardware(ni);
01284 break;
01285
01286 default:
01287 rc = -1;
01288 break;
01289 }
01290
01291 return rc;
01292 }
01293
01294
01295 static NICINFO dcb_eth0;
01296
01302 static IFNET ifn_eth0 = {
01303 IFT_ETHER,
01304 0,
01305 {0, 0, 0, 0, 0, 0},
01306 0,
01307 0,
01308 0,
01309 ETHERMTU,
01310 0,
01311 0,
01312 0,
01313 NutEtherInput,
01314 DmOutput,
01315 NutEtherOutput,
01316 0
01317 };
01318
01328 NUTDEVICE devDM9000E = {
01329 0,
01330 {'e', 't', 'h', '0', 0, 0, 0, 0, 0},
01331 IFTYP_NET,
01332 0,
01333 0,
01334 &ifn_eth0,
01335 &dcb_eth0,
01336 DmInit,
01337 DmIOCtl,
01338 0,
01339 0,
01340 #ifdef __HARVARD_ARCH__
01341 0,
01342 #endif
01343 0,
01344 0,
01345 0
01346 };
01347
01348 #endif
01349