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 #include <cfg/os.h>
00041 #include <arch/arm.h>
00042 #include <dev/board.h>
00043
00044 #include <string.h>
00045 #include <stdlib.h>
00046
00047 #include <sys/atom.h>
00048 #include <sys/heap.h>
00049 #include <sys/thread.h>
00050 #include <sys/event.h>
00051 #include <sys/timer.h>
00052 #include <sys/confnet.h>
00053
00054 #include <netinet/if_ether.h>
00055 #include <net/ether.h>
00056 #include <net/if_var.h>
00057
00058 #include <dev/irqreg.h>
00059 #include <dev/dm9000.h>
00060
00061 #ifdef NUTDEBUG
00062 #include <stdio.h>
00063 #endif
00064
00065 #ifndef NUT_THREAD_NICRXSTACK
00066 #define NUT_THREAD_NICRXSTACK 384
00067 #endif
00068
00069 #if !defined(NIC_DATA_ADDR) && defined(NIC_BASE_ADDR)
00070 #define NIC_DATA_ADDR (NIC_BASE_ADDR + 4)
00071 #endif
00072
00073 #define INT0 0
00074 #define INT1 1
00075 #define INT2 2
00076 #define INT3 3
00077 #define INT4 4
00078 #define INT5 5
00079 #define INT6 6
00080 #define INT7 7
00081
00082 #ifdef NIC_RESET_BIT
00083
00084 #if (NIC_RESET_AVRPORT == AVRPORTB)
00085 #define NIC_RESET_PORT PORTB
00086 #define NIC_RESET_DDR DDRB
00087
00088 #elif (NIC_RESET_AVRPORT == AVRPORTD)
00089 #define NIC_RESET_PORT PORTD
00090 #define NIC_RESET_DDR DDRD
00091
00092 #elif (NIC_RESET_AVRPORT == AVRPORTE)
00093 #define NIC_RESET_PORT PORTE
00094 #define NIC_RESET_DDR DDRE
00095
00096 #elif (NIC_RESET_AVRPORT == AVRPORTF)
00097 #define NIC_RESET_PORT PORTF
00098 #define NIC_RESET_DDR DDRF
00099
00100 #endif
00101
00102 #endif
00103
00104
00105
00106
00107
00108 #if (NIC_SIGNAL_IRQ == INT0)
00109 #define NIC_SIGNAL sig_INTERRUPT0
00110
00111 #elif (NIC_SIGNAL_IRQ == INT2)
00112 #define NIC_SIGNAL sig_INTERRUPT2
00113
00114 #elif (NIC_SIGNAL_IRQ == INT3)
00115 #define NIC_SIGNAL sig_INTERRUPT3
00116
00117 #elif (NIC_SIGNAL_IRQ == INT4)
00118 #define NIC_SIGNAL sig_INTERRUPT4
00119
00120 #elif (NIC_SIGNAL_IRQ == INT5)
00121 #define NIC_SIGNAL sig_INTERRUPT5
00122
00123 #elif (NIC_SIGNAL_IRQ == INT6)
00124 #define NIC_SIGNAL sig_INTERRUPT6
00125
00126 #elif (NIC_SIGNAL_IRQ == INT7)
00127 #define NIC_SIGNAL sig_INTERRUPT7
00128
00129 #else
00130 #define NIC_SIGNAL sig_INTERRUPT1
00131
00132 #endif
00133
00138
00139 #define NIC_NCR 0x00
00140 #define NIC_NCR_LBM 0x06
00141 #define NIC_NCR_LBNORM 0x00
00142 #define NIC_NCR_LBMAC 0x02
00143 #define NIC_NCR_LBPHY 0x04
00144 #define NIC_NCR_RST 0x01
00145
00146 #define NIC_NSR 0x01
00147 #define NIC_NSR_SPEED 0x80
00148 #define NIC_NSR_LINKST 0x40
00149 #define NIC_NSR_WAKEST 0x20
00150 #define NIC_NSR_TX2END 0x08
00151 #define NIC_NSR_TX1END 0x04
00152 #define NIC_NSR_RXOV 0x02
00153
00154 #define NIC_TCR 0x02
00155 #define NIC_TCR_TXREQ 0x01
00156
00157 #define NIC_TSR1 0x03
00158
00159 #define NIC_TSR2 0x04
00160
00161 #define NIC_RCR 0x05
00162 #define NIC_RCR_DIS_LONG 0x20
00163 #define NIC_RCR_DIS_CRC 0x10
00164 #define NIC_RCR_ALL 0x08
00165 #define NIC_RCR_PRMSC 0x02
00166 #define NIC_RCR_RXEN 0x01
00167
00168 #define NIC_RSR 0x06
00169 #define NIC_RSR_ERRORS 0xBF
00170 #define NIC_RSR_RF 0x80
00171 #define NIC_RSR_MF 0x40
00172 #define NIC_RSR_LCS 0x20
00173 #define NIC_RSR_RWTO 0x10
00174 #define NIC_RSR_PLE 0x08
00175 #define NIC_RSR_AE 0x04
00176 #define NIC_RSR_CE 0x02
00177 #define NIC_RSR_FOE 0x01
00178
00179 #define NIC_ROCR 0x07
00180
00181 #define NIC_BPTR 0x08
00182
00183 #define NIC_FCTR 0x09
00184
00185 #define NIC_FCR 0x0A
00186
00187 #define NIC_EPCR 0x0B
00188
00189 #define NIC_EPAR 0x0C
00190
00191 #define NIC_EPDRL 0x0D
00192
00193 #define NIC_EPDRH 0x0E
00194
00195 #define NIC_WCR 0x0F
00196
00197 #define NIC_PAR 0x10
00198
00199 #define NIC_MAR 0x16
00200
00201 #define NIC_GPCR 0x1E
00202
00203 #define NIC_GPR 0x1F
00204
00205 #define NIC_TRPA 0x22
00206
00207 #define NIC_RWPA 0x24
00208
00209 #define NIC_VID 0x28
00210
00211 #define NIC_PID 0x2A
00212
00213 #define NIC_CHIPR 0x2C
00214
00215 #define NIC_SMCR 0x2F
00216
00217 #define NIC_MRCMDX 0xF0
00218
00219 #define NIC_MRCMD 0xF2
00220
00221 #define NIC_MRR 0xF4
00222
00223 #define NIC_MWCMDX 0xF6
00224
00225 #define NIC_MWCMD 0xF8
00226
00227 #define NIC_MWR 0xFA
00228
00229 #define NIC_TXPL 0xFC
00230
00231 #define NIC_ISR 0xFE
00232 #define NIC_ISR_IOM 0xC0
00233 #define NIC_ISR_M16 0x00
00234 #define NIC_ISR_M32 0x40
00235 #define NIC_ISR_M8 0x80
00236 #define NIC_ISR_ROOS 0x08
00237 #define NIC_ISR_ROS 0x04
00238 #define NIC_ISR_PTS 0x02
00239 #define NIC_ISR_PRS 0x01
00240
00241 #define NIC_IMR 0xFF
00242 #define NIC_IMR_PAR 0x80
00243 #define NIC_IMR_ROOM 0x08
00244 #define NIC_IMR_ROM 0x04
00245 #define NIC_IMR_PTM 0x02
00246 #define NIC_IMR_PRM 0x01
00247
00248 #define NIC_PHY_BMCR 0x00
00249
00250 #define NIC_PHY_BMSR 0x01
00251 #define NIC_PHY_BMSR_ANCOMPL 0x0020
00252 #define NIC_PHY_BMSR_LINKSTAT 0x0004
00253
00254 #define NIC_PHY_ID1 0x02
00255
00256 #define NIC_PHY_ID2 0x03
00257
00258 #define NIC_PHY_ANAR 0x04
00259
00260 #define NIC_PHY_ANLPAR 0x05
00261
00262 #define NIC_PHY_ANER 0x06
00263
00264 #define NIC_PHY_DSCR 0x10
00265
00266 #define NIC_PHY_DSCSR 0x11
00267
00268 #define NIC_PHY_10BTCSR 0x12
00269
00273 struct _NICINFO {
00274 #ifdef NUT_PERFMON
00275 uint32_t ni_rx_packets;
00276 uint32_t ni_tx_packets;
00277 uint32_t ni_overruns;
00278 uint32_t ni_rx_frame_errors;
00279 uint32_t ni_rx_crc_errors;
00280 uint32_t ni_rx_missed_errors;
00281 #endif
00282 HANDLE volatile ni_rx_rdy;
00283 HANDLE volatile ni_tx_rdy;
00284 HANDLE ni_mutex;
00285 volatile int ni_tx_queued;
00286 volatile int ni_tx_quelen;
00287 volatile int ni_insane;
00288 int ni_iomode;
00289 uint8_t ni_mar[8];
00290 };
00291
00295 typedef struct _NICINFO NICINFO;
00296
00303
00304
00305
00306
00307 static const uint32_t crctab[] = {
00308 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
00309 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
00310 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
00311 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
00312 };
00313
00314 static uint32_t ether_crc32_le(const uint8_t * buf, uint8_t len)
00315 {
00316 uint32_t crc;
00317 uint8_t i;
00318
00319
00320 crc = 0xffffffff;
00321
00322 for (i = 0; i < len; i++) {
00323 crc ^= buf[i];
00324 crc = (crc >> 4) ^ crctab[crc & 0xf];
00325 crc = (crc >> 4) ^ crctab[crc & 0xf];
00326 }
00327
00328 return crc;
00329 }
00330
00331 static INLINE void nic_outb(uint8_t reg, uint8_t val)
00332 {
00333 #ifdef NIC_BASE_ADDR
00334 outb(NIC_BASE_ADDR, reg);
00335 outb(NIC_DATA_ADDR, val);
00336 #endif
00337 }
00338
00339 static INLINE uint8_t nic_inb(uint16_t reg)
00340 {
00341 #ifdef NIC_BASE_ADDR
00342 outb(NIC_BASE_ADDR, reg);
00343 return inb(NIC_DATA_ADDR);
00344 #else
00345 return 0;
00346 #endif
00347 }
00348
00356 static uint16_t phy_inw(uint8_t reg)
00357 {
00358
00359 nic_outb(NIC_EPAR, 0x40 | reg);
00360
00361
00362 nic_outb(NIC_EPCR, 0x0C);
00363 NutDelay(1);
00364 nic_outb(NIC_EPCR, 0x00);
00365
00366
00367 return ((uint16_t) nic_inb(NIC_EPDRH) << 8) | (uint16_t) nic_inb(NIC_EPDRL);
00368 }
00369
00378 static void phy_outw(uint8_t reg, uint16_t val)
00379 {
00380
00381 nic_outb(NIC_EPAR, 0x40 | reg);
00382
00383
00384 nic_outb(NIC_EPDRL, (uint8_t) val);
00385 nic_outb(NIC_EPDRH, (uint8_t) (val >> 8));
00386
00387
00388 nic_outb(NIC_EPCR, 0x0A);
00389 NutDelay(1);
00390 nic_outb(NIC_EPCR, 0x00);
00391 }
00392
00393 static int NicPhyInit(void)
00394 {
00395
00396 phy_outw(NIC_PHY_ANAR, 0x01E1);
00397 phy_outw(NIC_PHY_BMCR, 0x1200);
00398
00399 nic_outb(NIC_GPCR, 1);
00400 nic_outb(NIC_GPR, 0);
00401
00402 return 0;
00403 }
00404
00410 static int NicReset(void)
00411 {
00412
00413 #ifdef undef_NIC_RESET_BIT
00414 sbi(NIC_RESET_DDR, NIC_RESET_BIT);
00415 sbi(NIC_RESET_PORT, NIC_RESET_BIT);
00416 NutDelay(WAIT100);
00417 cbi(NIC_RESET_PORT, NIC_RESET_BIT);
00418 NutDelay(WAIT250);
00419 NutDelay(WAIT250);
00420 #else
00421
00422 nic_outb(NIC_NCR, NIC_NCR_RST | NIC_NCR_LBMAC);
00423 NutDelay(1);
00424
00425 #endif
00426
00427 return NicPhyInit();
00428 }
00429
00430
00431
00432
00433 static void NicInterrupt(void *arg)
00434 {
00435 uint8_t isr;
00436 NICINFO *ni = (NICINFO *) ((NUTDEVICE *) arg)->dev_dcb;
00437
00438
00439 isr = nic_inb(NIC_ISR);
00440
00441
00442 if (isr & NIC_ISR_PRS) {
00443 nic_outb(NIC_ISR, NIC_ISR_PRS);
00444 NutEventPostFromIrq(&ni->ni_rx_rdy);
00445 }
00446
00447
00448 if (isr & NIC_ISR_PTS) {
00449 if (ni->ni_tx_queued) {
00450 if (ni->ni_tx_quelen) {
00451
00452 nic_outb(NIC_TXPL, (uint8_t) ni->ni_tx_quelen);
00453 nic_outb(NIC_TXPL + 1, (uint8_t) (ni->ni_tx_quelen >> 8));
00454 ni->ni_tx_quelen = 0;
00455 nic_outb(NIC_TCR, NIC_TCR_TXREQ);
00456 }
00457 ni->ni_tx_queued--;
00458 }
00459 nic_outb(NIC_ISR, NIC_ISR_PTS);
00460 NutEventPostFromIrq(&ni->ni_tx_rdy);
00461 }
00462
00463
00464 if (isr & NIC_ISR_ROS) {
00465 nic_outb(NIC_ISR, NIC_ISR_ROS);
00466 ni->ni_insane = 1;
00467 NutEventPostFromIrq(&ni->ni_rx_rdy);
00468 }
00469
00470
00471 if (isr & NIC_ISR_ROOS) {
00472 nic_outb(NIC_ISR, NIC_ISR_ROOS);
00473 NutEventPostFromIrq(&ni->ni_rx_rdy);
00474 }
00475 }
00476
00477 #ifdef NIC_BASE_ADDR
00478
00483 static void NicWrite8(uint8_t * buf, uint16_t len)
00484 {
00485 while (len--) {
00486 outb(NIC_DATA_ADDR, *buf);
00487 buf++;
00488 }
00489 }
00490
00496 static void NicWrite16(uint8_t * buf, uint16_t len)
00497 {
00498 uint16_t *wp = (uint16_t *) buf;
00499
00500 len = (len + 1) / 2;
00501 while (len--) {
00502 outw(NIC_DATA_ADDR, *wp);
00503 wp++;
00504 }
00505 }
00506
00512 static void NicRead8(uint8_t * buf, uint16_t len)
00513 {
00514 while (len--) {
00515 *buf++ = inb(NIC_DATA_ADDR);
00516 }
00517 }
00518
00524 static void NicRead16(uint8_t * buf, uint16_t len)
00525 {
00526 uint16_t *wp = (uint16_t *) buf;
00527
00528 len = (len + 1) / 2;
00529 while (len--) {
00530 *wp++ = inw(NIC_DATA_ADDR);
00531 }
00532 }
00533 #endif
00534
00543 static int NicGetPacket(NICINFO * ni, NETBUF ** nbp)
00544 {
00545 int rc = -1;
00546 #ifdef NIC_BASE_ADDR
00547 uint16_t fsw;
00548 uint16_t fbc;
00549
00550 *nbp = NULL;
00551
00552
00553 NutIrqDisable(&NIC_SIGNAL);
00554
00555
00556
00557
00558
00559
00560 nic_inb(NIC_MRCMDX);
00561
00562 _NOP();
00563 _NOP();
00564 _NOP();
00565 _NOP();
00566 fsw = inb(NIC_DATA_ADDR);
00567 if (fsw > 1) {
00568 ni->ni_insane = 1;
00569 } else if (fsw) {
00570
00571 outb(NIC_BASE_ADDR, NIC_MRCMD);
00572 if (ni->ni_iomode == NIC_ISR_M16) {
00573 fsw = inw(NIC_DATA_ADDR);
00574 _NOP();
00575 _NOP();
00576 _NOP();
00577 _NOP();
00578 fbc = inw(NIC_DATA_ADDR);
00579 } else {
00580 fsw = inb(NIC_DATA_ADDR) + ((uint16_t) inb(NIC_DATA_ADDR) << 8);
00581 _NOP();
00582 _NOP();
00583 _NOP();
00584 _NOP();
00585 fbc = inb(NIC_DATA_ADDR) + ((uint16_t) inb(NIC_DATA_ADDR) << 8);
00586 }
00587
00588
00589
00590
00591
00592
00593 if (fbc > 1536) {
00594 ni->ni_insane = 1;
00595 } else {
00596
00597
00598
00599
00600 fsw >>= 8;
00601 fsw &= NIC_RSR_ERRORS;
00602 #ifdef NUT_PERMON
00603
00604 if (fsw) {
00605 if (RxStatus & NIC_RSR_CE) {
00606 ni->ni_crc_errors++;
00607 } else if (RxStatus & NIC_RSR_FOE) {
00608 ni->ni_overruns++;
00609 } else {
00610 ni->ni_rx_missed_errors++;
00611 }
00612 } else {
00613 ni->ni_rx_packets++;
00614 }
00615 #endif
00616
00617
00618
00619
00620 if (fsw || (*nbp = NutNetBufAlloc(0, NBAF_DATALINK, fbc - 4)) == NULL) {
00621 if (ni->ni_iomode == NIC_ISR_M16) {
00622 fbc = (fbc + 1) / 2;
00623 while (fbc--) {
00624 fsw = inw(NIC_DATA_ADDR);
00625 }
00626 } else {
00627 while (fbc--) {
00628 fsw = inb(NIC_DATA_ADDR);
00629 }
00630 }
00631 } else {
00632 if (ni->ni_iomode == NIC_ISR_M16) {
00633
00634 NicRead16((*nbp)->nb_dl.vp, (*nbp)->nb_dl.sz);
00635
00636 fsw = inw(NIC_DATA_ADDR);
00637 fsw = inw(NIC_DATA_ADDR);
00638 } else {
00639
00640 NicRead8((*nbp)->nb_dl.vp, (*nbp)->nb_dl.sz);
00641
00642 fsw = inb(NIC_DATA_ADDR);
00643 fsw = inb(NIC_DATA_ADDR);
00644 fsw = inb(NIC_DATA_ADDR);
00645 fsw = inb(NIC_DATA_ADDR);
00646 }
00647
00648 rc = 0;
00649 }
00650 }
00651 }
00652
00653
00654 if (ni->ni_insane == 0) {
00655 NutIrqEnable(&NIC_SIGNAL);
00656 }
00657 #endif
00658 return rc;
00659 }
00660
00673 static int NicPutPacket(NICINFO * ni, NETBUF * nb)
00674 {
00675 int rc = -1;
00676 #ifdef NIC_BASE_ADDR
00677 uint16_t sz;
00678
00679
00680
00681
00682
00683
00684
00685 if ((sz = nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz) > ETHERMTU) {
00686 return -1;
00687 }
00688 sz += nb->nb_dl.sz;
00689 if (sz & 1) {
00690 sz++;
00691 }
00692
00693
00694 NutIrqDisable(&NIC_SIGNAL);
00695
00696
00697 if (ni->ni_insane == 0) {
00698
00699 outb(NIC_BASE_ADDR, NIC_MWCMD);
00700
00701
00702 if (ni->ni_iomode == NIC_ISR_M16) {
00703 NicWrite16(nb->nb_dl.vp, nb->nb_dl.sz);
00704 NicWrite16(nb->nb_nw.vp, nb->nb_nw.sz);
00705 NicWrite16(nb->nb_tp.vp, nb->nb_tp.sz);
00706 NicWrite16(nb->nb_ap.vp, nb->nb_ap.sz);
00707 } else {
00708 NicWrite8(nb->nb_dl.vp, nb->nb_dl.sz);
00709 NicWrite8(nb->nb_nw.vp, nb->nb_nw.sz);
00710 NicWrite8(nb->nb_tp.vp, nb->nb_tp.sz);
00711 NicWrite8(nb->nb_ap.vp, nb->nb_ap.sz);
00712 }
00713
00714
00715 if (ni->ni_tx_queued == 0) {
00716 nic_outb(NIC_TXPL, (uint8_t) sz);
00717 nic_outb(NIC_TXPL + 1, (uint8_t) (sz >> 8));
00718 nic_outb(NIC_TCR, NIC_TCR_TXREQ);
00719 }
00720
00721 else {
00722 ni->ni_tx_quelen = sz;
00723 }
00724 ni->ni_tx_queued++;
00725 rc = 0;
00726 #ifdef NUT_PERFMON
00727 ni->ni_tx_packets++;
00728 #endif
00729 }
00730
00731
00732 NutIrqEnable(&NIC_SIGNAL);
00733
00734
00735
00736 if (rc == 0 && ni->ni_tx_queued > 1) {
00737 NutEventWait(&ni->ni_tx_rdy, 500);
00738 }
00739 #endif
00740 return rc;
00741 }
00742
00748 static void NicUpdateMCHardware(NICINFO * ni)
00749 {
00750 int i;
00751
00752
00753 ni->ni_mar[7] |= 0x80;
00754
00755
00756 for (i = 0; i < 7; i++) {
00757 nic_outb(NIC_MAR + i, ni->ni_mar[i]);
00758 }
00759 }
00760
00768 static int NicStart(CONST uint8_t * mac, NICINFO * ni)
00769 {
00770 int i;
00771 int link_wait = 20;
00772
00773
00774 nic_outb(NIC_GPR, 0);
00775 NutDelay(5);
00776
00777
00778 nic_outb(NIC_NCR, NIC_NCR_RST | NIC_NCR_LBMAC);
00779 NutDelay(5);
00780 nic_outb(NIC_NCR, NIC_NCR_RST | NIC_NCR_LBMAC);
00781 NutDelay(5);
00782
00783
00784
00785
00786
00787 nic_outb(NIC_GPR, 1);
00788 nic_outb(NIC_GPR, 0);
00789
00790
00791 for (i = 0; i < 6; i++) {
00792 nic_outb(NIC_PAR + i, mac[i]);
00793 }
00794
00795
00796 NicUpdateMCHardware(ni);
00797
00798
00799 nic_outb(NIC_ISR, NIC_ISR_ROOS | NIC_ISR_ROS | NIC_ISR_PTS | NIC_ISR_PRS);
00800
00801
00802 if (nic_inb(NIC_CHIPR) == 0x19) {
00803 nic_outb(0x2D, 0x40);
00804 }
00805
00806
00807 nic_outb(NIC_RCR, NIC_RCR_DIS_LONG | NIC_RCR_DIS_CRC | NIC_RCR_RXEN | NIC_RCR_ALL);
00808
00809
00810 for (link_wait = 20;; link_wait--) {
00811 if (phy_inw(NIC_PHY_BMSR) & NIC_PHY_BMSR_ANCOMPL) {
00812 break;
00813 }
00814 if (link_wait == 0) {
00815 return -1;
00816 }
00817 NutSleep(200);
00818 }
00819
00820
00821 nic_outb(NIC_IMR, NIC_IMR_PAR | NIC_IMR_PTM | NIC_IMR_PRM);
00822
00823 return 0;
00824 }
00825
00830 THREAD(NicRxLanc, arg)
00831 {
00832 NUTDEVICE *dev;
00833 IFNET *ifn;
00834 NICINFO *ni;
00835 NETBUF *nb;
00836
00837 dev = arg;
00838 ifn = (IFNET *) dev->dev_icb;
00839 ni = (NICINFO *) dev->dev_dcb;
00840
00841
00842
00843
00844
00845
00846 while (ETHER_IS_ZERO(ifn->if_mac) || ETHER_IS_BROADCAST(ifn->if_mac)) {
00847 NutSleep(10);
00848 }
00849
00850
00851
00852
00853
00854
00855
00856 while (NicStart(ifn->if_mac, ni)) {
00857 NutSleep(1000);
00858 }
00859
00860
00861 NutEventPost(&ni->ni_mutex);
00862
00863
00864 NutThreadSetPriority(9);
00865
00866
00867 #ifdef NIC_SIGNAL_XSR
00868 outr(NIC_SIGNAL_XSR, _BV(NIC_SIGNAL_BIT));
00869 #if defined(ELEKTOR_IR1)
00870
00871 outr(PMC_PCER, _BV(IRQ0_ID));
00872 #endif
00873 #endif
00874 #ifdef NIC_SIGNAL_BIT
00875 outr(NIC_SIGNAL_PDR, _BV(NIC_SIGNAL_BIT));
00876 #endif
00877 NutIrqEnable(&NIC_SIGNAL);
00878 #if defined(ELEKTOR_IR1)
00879
00880 NutIrqSetMode(&NIC_SIGNAL, NUT_IRQMODE_HIGHLEVEL);
00881 #endif
00882
00883 for (;;) {
00884
00885
00886
00887
00888 NutEventWait(&ni->ni_rx_rdy, 2000);
00889
00890
00891
00892
00893
00894 while (NicGetPacket(ni, &nb) == 0) {
00895
00896
00897 if (nb->nb_dl.sz < 60) {
00898 NutNetBufFree(nb);
00899 } else {
00900 (*ifn->if_recv) (dev, nb);
00901 }
00902 }
00903
00904
00905 while (ni->ni_insane) {
00906 if (NicStart(ifn->if_mac, ni) == 0) {
00907 ni->ni_insane = 0;
00908 ni->ni_tx_queued = 0;
00909 ni->ni_tx_quelen = 0;
00910 NutIrqEnable(&NIC_SIGNAL);
00911 } else {
00912 NutSleep(1000);
00913 }
00914 }
00915 }
00916 }
00917
00928 int DmOutput(NUTDEVICE * dev, NETBUF * nb)
00929 {
00930 static uint32_t mx_wait = 5000;
00931 int rc = -1;
00932 NICINFO *ni = (NICINFO *) dev->dev_dcb;
00933
00934
00935
00936
00937
00938 while (rc) {
00939 if (ni->ni_insane) {
00940 break;
00941 }
00942 if (NutEventWait(&ni->ni_mutex, mx_wait)) {
00943 break;
00944 }
00945
00946
00947 if (ni->ni_tx_queued > 1) {
00948 if (NutEventWait(&ni->ni_tx_rdy, 500)) {
00949
00950 NutEventPost(&ni->ni_mutex);
00951 break;
00952 }
00953 } else if (NicPutPacket(ni, nb) == 0) {
00954
00955
00956 rc = 0;
00957 mx_wait = 5000;
00958 }
00959 NutEventPost(&ni->ni_mutex);
00960 }
00961
00962
00963
00964
00965 if (rc) {
00966 mx_wait = 500;
00967 }
00968 return rc;
00969 }
00970
00988 int DmInit(NUTDEVICE * dev)
00989 {
00990 uint32_t id;
00991 NICINFO *ni = (NICINFO *) dev->dev_dcb;
00992
00993
00994 id = (uint32_t) nic_inb(NIC_VID);
00995 id |= (uint32_t) nic_inb(NIC_VID + 1) << 8;
00996 id |= (uint32_t) nic_inb(NIC_PID) << 16;
00997 id |= (uint32_t) nic_inb(NIC_PID + 1) << 24;
00998 if (id != 0x90000A46) {
00999 return -1;
01000 }
01001
01002
01003 if (NicReset()) {
01004 return -1;
01005 }
01006
01007
01008 memset(ni, 0, sizeof(NICINFO));
01009
01010
01011 ni->ni_iomode = nic_inb(NIC_ISR) & NIC_ISR_IOM;
01012 if (ni->ni_iomode == NIC_ISR_M32) {
01013 return -1;
01014 }
01015
01016
01017 if (NutRegisterIrqHandler(&NIC_SIGNAL, NicInterrupt, dev)) {
01018 return -1;
01019 }
01020
01021
01022 if (NutThreadCreate("rxi1", NicRxLanc, dev,
01023 (NUT_THREAD_NICRXSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD) == NULL) {
01024 return -1;
01025 }
01026 return 0;
01027 }
01028
01029 static int DmIOCtl(NUTDEVICE * dev, int req, void *conf)
01030 {
01031 int rc = 0;
01032 int i;
01033 IFNET *nif = (IFNET *) dev->dev_icb;
01034 NICINFO *ni = (NICINFO *) dev->dev_dcb;
01035 uint32_t index;
01036 uint32_t ip_addr;
01037 MCASTENTRY *mcast;
01038 MCASTENTRY *mcast_prev;
01039 MCASTENTRY *mcast_next;
01040
01041 uint8_t mac[6];
01042
01043 switch (req) {
01044 case SIOCSIFADDR:
01045
01046 memcpy(nif->if_mac, conf, sizeof(nif->if_mac));
01047 break;
01048
01049 case SIOCADDMULTI:
01050
01051 ip_addr = *((uint32_t *) conf);
01052
01053 mcast = nif->if_mcast;
01054 while (mcast) {
01055 if (ip_addr == mcast->mca_ip) {
01056
01057 return -1;
01058 }
01059 mcast = mcast->mca_next;
01060 }
01061
01062 mac[0] = 0x01;
01063 mac[1] = 0x00;
01064 mac[2] = 0x5E;
01065 mac[3] = ((uint8_t *) conf)[1] & 0x7f;
01066 mac[4] = ((uint8_t *) conf)[2];
01067 mac[5] = ((uint8_t *) conf)[3];
01068 mcast = malloc(sizeof(MCASTENTRY));
01069 if (mcast) {
01070
01071 index = ether_crc32_le(&mac[0], 6);
01072 index &= 0x3F;
01073
01074 ni->ni_mar[index / 8] |= (1 << (index % 8));
01075
01076 memcpy(mcast->mca_ha, mac, 6);
01077 mcast->mca_ip = *((uint32_t *) conf);
01078 mcast->mca_next = nif->if_mcast;
01079 nif->if_mcast = mcast;
01080
01081 NicUpdateMCHardware(ni);
01082 } else {
01083 rc = -1;
01084 }
01085 break;
01086
01087 case SIOCDELMULTI:
01088
01089 ip_addr = *((uint32_t *) conf);
01090
01091
01092 mcast = nif->if_mcast;
01093 mcast_prev = mcast;
01094 while (mcast) {
01095 if (ip_addr == mcast->mca_ip) {
01096
01097 break;
01098 }
01099 mcast_prev = mcast;
01100 mcast = mcast->mca_next;
01101 }
01102 if (NULL == mcast) {
01103
01104 return -1;
01105 }
01106
01107
01108
01109
01110 mcast_next = mcast->mca_next;
01111
01112
01113 if (nif->if_mcast == mcast) {
01114
01115
01116 nif->if_mcast = mcast_next;
01117 free(mcast);
01118 } else {
01119
01120
01121 mcast_prev->mca_next = mcast_next;
01122 free(mcast);
01123 }
01124
01125
01126 for (i = 0; i < 7; i++) {
01127 ni->ni_mar[i] = 0;
01128 }
01129
01130 mcast = nif->if_mcast;
01131 while (mcast) {
01132
01133 index = ether_crc32_le(&mcast->mca_ha[0], 6);
01134 index &= 0x3F;
01135
01136 ni->ni_mar[index / 8] |= (1 << (index % 8));
01137 mcast = mcast->mca_next;
01138 }
01139
01140 NicUpdateMCHardware(ni);
01141 break;
01142
01143 default:
01144 rc = -1;
01145 break;
01146 }
01147
01148 return rc;
01149 }
01150
01151 static NICINFO dcb_eth0;
01152
01158 static IFNET ifn_eth0 = {
01159 IFT_ETHER,
01160 0,
01161 {0, 0, 0, 0, 0, 0},
01162 0,
01163 0,
01164 0,
01165 ETHERMTU,
01166 0,
01167 0,
01168 0,
01169 NutEtherInput,
01170 DmOutput,
01171 NutEtherOutput
01172 };
01173
01183 NUTDEVICE devDm9000 = {
01184 0,
01185 {'e', 't', 'h', '0', 0, 0, 0, 0, 0},
01186 IFTYP_NET,
01187 0,
01188 0,
01189 &ifn_eth0,
01190 &dcb_eth0,
01191 DmInit,
01192 DmIOCtl,
01193 0,
01194 0,
01195 #ifdef __HARVARD_ARCH__
01196 0,
01197 #endif
01198 0,
01199 0,
01200 0
01201 };
01202