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