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 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00112 
00113 
00114 #include <cfg/os.h>
00115 #include <cfg/arch/avr.h>
00116 
00117 #include <sys/atom.h>
00118 #include <sys/heap.h>
00119 #include <sys/thread.h>
00120 #include <sys/event.h>
00121 #include <sys/timer.h>
00122 #include <sys/confnet.h>
00123 
00124 #include <netinet/if_ether.h>
00125 #include <net/ether.h>
00126 #include <net/if_var.h>
00127 
00128 #include <dev/irqreg.h>
00129 #include <dev/lanc111.h>
00130 
00131 #include <stdlib.h>
00132 #include <string.h>
00133 
00134 #ifdef NUTDEBUG
00135 #include <stdio.h>
00136 #endif
00137 
00138 #ifndef NUT_THREAD_LANCRXSTACK
00139 #if defined(__GNUC__)
00140 
00141 
00142 #define NUT_THREAD_LANCRXSTACK  256
00143 #else
00144 
00145 #define NUT_THREAD_LANCRXSTACK  384
00146 #endif
00147 #endif
00148 
00149 
00150 
00151 
00152 #ifndef LANC111_BASE_ADDR
00153 #define LANC111_BASE_ADDR   0xC000
00154 #endif
00155 
00156 #ifndef LANC111_SIGNAL_IRQ
00157 #define LANC111_SIGNAL_IRQ  INT5
00158 #endif
00159 
00160 #ifdef LANC111_RESET_BIT
00161 
00162 #if (LANC111_RESET_AVRPORT == AVRPORTB)
00163 #define LANC111_RESET_PORT   PORTB
00164 #define LANC111_RESET_DDR    DDRB
00165 
00166 #elif (LANC111_RESET_AVRPORT == AVRPORTD)
00167 #define LANC111_RESET_PORT   PORTD
00168 #define LANC111_RESET_DDR    DDRD
00169 
00170 #elif (LANC111_RESET_AVRPORT == AVRPORTE)
00171 #define LANC111_RESET_PORT   PORTE
00172 #define LANC111_RESET_DDR    DDRE
00173 
00174 #elif (LANC111_RESET_AVRPORT == AVRPORTF)
00175 #define LANC111_RESET_PORT   PORTF
00176 #define LANC111_RESET_DDR    DDRF
00177 
00178 #endif                          
00179 
00180 #endif                          
00181 
00182 
00183 
00184 
00185 #if (LANC111_SIGNAL_IRQ == INT0)
00186 #define LANC111_SIGNAL          sig_INTERRUPT0
00187 #define LANC111_SIGNAL_MODE()   sbi(EICRA, ISC00); sbi(EICRA, ISC01)
00188 
00189 #elif (LANC111_SIGNAL_IRQ == INT1)
00190 #define LANC111_SIGNAL          sig_INTERRUPT1
00191 #define LANC111_SIGNAL_MODE()   sbi(EICRA, ISC10); sbi(EICRA, ISC11)
00192 
00193 #elif (LANC111_SIGNAL_IRQ == INT2)
00194 #define LANC111_SIGNAL          sig_INTERRUPT2
00195 #define LANC111_SIGNAL_MODE()   sbi(EICRA, ISC20); sbi(EICRA, ISC21)
00196 
00197 #elif (LANC111_SIGNAL_IRQ == INT3)
00198 #define LANC111_SIGNAL          sig_INTERRUPT3
00199 #define LANC111_SIGNAL_MODE()   sbi(EICRA, ISC30); sbi(EICRA, ISC31)
00200 
00201 #elif (LANC111_SIGNAL_IRQ == INT4)
00202 #define LANC111_SIGNAL          sig_INTERRUPT4
00203 #define LANC111_SIGNAL_MODE()   sbi(EICR, ISC40); sbi(EICR, ISC41)
00204 
00205 #elif (LANC111_SIGNAL_IRQ == INT6)
00206 #define LANC111_SIGNAL          sig_INTERRUPT6
00207 #define LANC111_SIGNAL_MODE()   sbi(EICR, ISC60); sbi(EICR, ISC61)
00208 
00209 #elif (LANC111_SIGNAL_IRQ == INT7)
00210 #define LANC111_SIGNAL          sig_INTERRUPT7
00211 #define LANC111_SIGNAL_MODE()   sbi(EICR, ISC70); sbi(EICR, ISC71)
00212 
00213 #else
00214 #define LANC111_SIGNAL          sig_INTERRUPT5
00215 #define LANC111_SIGNAL_MODE()   sbi(EICR, ISC50); sbi(EICR, ISC51)
00216 
00217 #endif
00218 
00223 
00227 #define NIC_BSR         (LANC111_BASE_ADDR + 0x0E)
00228 
00232 #define NIC_TCR         (LANC111_BASE_ADDR + 0x00)
00233 
00234 #define TCR_SWFDUP      0x8000  
00235 #define TCR_EPH_LOOP    0x2000  
00236 #define TCR_STP_SQET    0x1000  
00237 #define TCR_FDUPLX      0x0800  
00238 #define TCR_MON_CSN     0x0400  
00239 #define TCR_NOCRC       0x0100  
00240 #define TCR_PAD_EN      0x0080  
00241 #define TCR_FORCOL      0x0004  
00242 #define TCR_LOOP        0x0002  
00243 #define TCR_TXENA       0x0001  
00249 #define NIC_EPHSR       (LANC111_BASE_ADDR + 0x02)
00250 
00254 #define NIC_RCR         (LANC111_BASE_ADDR + 0x04)
00255 
00256 #define RCR_SOFT_RST    0x8000  
00257 #define RCR_FILT_CAR    0x4000  
00258 #define RCR_ABORT_ENB   0x2000  
00259 #define RCR_STRIP_CRC   0x0200  
00260 #define RCR_RXEN        0x0100  
00261 #define RCR_ALMUL       0x0004  
00262 #define RCR_PRMS        0x0002  
00263 #define RCR_RX_ABORT    0x0001  
00268 #define NIC_ECR         (LANC111_BASE_ADDR + 0x06)
00269 
00273 #define NIC_MIR         (LANC111_BASE_ADDR + 0x08)
00274 
00278 #define NIC_RPCR        (LANC111_BASE_ADDR + 0x0A)
00279 
00280 #define RPCR_SPEED      0x2000  
00281 #define RPCR_DPLX       0x1000  
00282 #define RPCR_ANEG       0x0800  
00283 #define RPCR_LEDA_PAT   0x0000  
00284 #define RPCR_LEDB_PAT   0x0010  
00289 #define NIC_CR          (LANC111_BASE_ADDR + 0x00)
00290 
00291 #define CR_EPH_EN       0x8000  
00296 #define NIC_BAR         (LANC111_BASE_ADDR + 0x02)
00297 
00301 #define NIC_IAR         (LANC111_BASE_ADDR + 0x04)
00302 
00306 #define NIC_GPR         (LANC111_BASE_ADDR + 0x0A)
00307 
00311 #define NIC_CTR         (LANC111_BASE_ADDR + 0x0C)
00312 
00313 #define CTR_RCV_BAD     0x4000  
00314 #define CTR_AUTO_RELEASE 0x0800 
00319 #define NIC_MMUCR       (LANC111_BASE_ADDR + 0x00)
00320 
00321 #define MMUCR_BUSY      0x0001
00322 
00323 #define MMU_NOP         0
00324 #define MMU_ALO         (1<<5)
00325 #define MMU_RST         (2<<5)
00326 #define MMU_REM         (3<<5)
00327 #define MMU_TOP         (4<<5)
00328 #define MMU_PKT         (5<<5)
00329 #define MMU_ENQ         (6<<5)
00330 #define MMU_RTX         (7<<5)
00331 
00337 #define NIC_PNR         (LANC111_BASE_ADDR + 0x02)
00338 
00344 #define NIC_ARR         (LANC111_BASE_ADDR + 0x03)
00345 
00346 #define ARR_FAILED      0x80
00347 
00351 #define NIC_FIFO        (LANC111_BASE_ADDR + 0x04)
00352 
00356 #define NIC_PTR         (LANC111_BASE_ADDR + 0x06)
00357 
00358 #define PTR_RCV         0x8000  
00359 #define PTR_AUTO_INCR   0x4000  
00360 #define PTR_READ        0x2000  
00361 #define PTR_ETEN        0x1000  
00362 #define PTR_NOT_EMPTY   0x0800  
00367 #define NIC_DATA        (LANC111_BASE_ADDR + 0x08)
00368 
00372 #define NIC_IST         (LANC111_BASE_ADDR + 0x0C)
00373 
00377 #define NIC_ACK         (LANC111_BASE_ADDR + 0x0C)
00378 
00382 #define NIC_MSK         (LANC111_BASE_ADDR + 0x0D)
00383 
00384 #define INT_MD          0x80    
00385 #define INT_ERCV        0x40    
00386 #define INT_EPH         0x20    
00387 #define INT_RX_OVRN     0x10    
00388 #define INT_ALLOC       0x08    
00389 #define INT_TX_EMPTY    0x04    
00390 #define INT_TX          0x02    
00391 #define INT_RCV         0x01    
00396 #define NIC_MT          (LANC111_BASE_ADDR + 0x00)
00397 
00401 #define NIC_MGMT        (LANC111_BASE_ADDR + 0x08)
00402 
00403 #define MGMT_MDOE       0x08    
00404 #define MGMT_MCLK       0x04    
00405 #define MGMT_MDI        0x02    
00406 #define MGMT_MDO        0x01    
00411 #define NIC_REV         (LANC111_BASE_ADDR + 0x0A)
00412 
00416 #define NIC_ERCV        (LANC111_BASE_ADDR + 0x0C)
00417 
00421 #define NIC_PHYCR       0
00422 
00423 #define PHYCR_RST       0x8000  
00424 #define PHYCR_LPBK      0x4000  
00425 #define PHYCR_SPEED     0x2000  
00426 #define PHYCR_ANEG_EN   0x1000  
00427 #define PHYCR_PDN       0x0800  
00428 #define PHYCR_MII_DIS   0x0400  
00429 #define PHYCR_ANEG_RST  0x0200  
00430 #define PHYCR_DPLX      0x0100  
00431 #define PHYCR_COLST     0x0080  
00437 #define NIC_PHYSR       1
00438 
00439 #define PHYSR_CAP_T4    0x8000  
00440 #define PHYSR_CAP_TXF   0x4000  
00441 #define PHYSR_CAP_TXH   0x2000  
00442 #define PHYSR_CAP_TF    0x1000  
00443 #define PHYSR_CAP_TH    0x0800  
00444 #define PHYSR_CAP_SUPR  0x0040  
00445 #define PHYSR_ANEG_ACK  0x0020  
00446 #define PHYSR_REM_FLT   0x0010  
00447 #define PHYSR_CAP_ANEG  0x0008  
00448 #define PHYSR_LINK      0x0004  
00449 #define PHYSR_JAB       0x0002  
00450 #define PHYSR_EXREG     0x0001  
00456 #define NIC_PHYID1      2
00457 
00461 #define NIC_PHYID2      3
00462 
00466 #define NIC_PHYANAD     4
00467 
00468 #define PHYANAD_NP      0x8000  
00469 #define PHYANAD_ACK     0x4000  
00470 #define PHYANAD_RF      0x2000  
00471 #define PHYANAD_T4      0x0200  
00472 #define PHYANAD_TX_FDX  0x0100  
00473 #define PHYANAD_TX_HDX  0x0080  
00474 #define PHYANAD_10FDX   0x0040  
00475 #define PHYANAD_10_HDX  0x0020  
00476 #define PHYANAD_CSMA    0x0001  
00481 #define NIC_PHYANRC     5
00482 
00486 #define NIC_PHYCFR1     16
00487 
00491 #define NIC_PHYCFR2     17
00492 
00496 #define NIC_PHYSOR      18
00497 
00498 #define PHYSOR_INT      0x8000  
00499 #define PHYSOR_LNKFAIL  0x4000  
00500 #define PHYSOR_LOSSSYNC 0x2000  
00501 #define PHYSOR_CWRD     0x1000  
00502 #define PHYSOR_SSD      0x0800  
00503 #define PHYSOR_ESD      0x0400  
00504 #define PHYSOR_RPOL     0x0200  
00505 #define PHYSOR_JAB      0x0100  
00506 #define PHYSOR_SPDDET   0x0080  
00507 #define PHYSOR_DPLXDET  0x0040  
00512 #define NIC_PHYMSK      19
00513 
00514 #define PHYMSK_MINT     0x8000  
00515 #define PHYMSK_MLNKFAIL 0x4000  
00516 #define PHYMSK_MLOSSSYN 0x2000  
00517 #define PHYMSK_MCWRD    0x1000  
00518 #define PHYMSK_MSSD     0x0800  
00519 #define PHYMSK_MESD     0x0400  
00520 #define PHYMSK_MRPOL    0x0200  
00521 #define PHYMSK_MJAB     0x0100  
00522 #define PHYMSK_MSPDDT   0x0080  
00523 #define PHYMSK_MDPLDT   0x0040  
00527 #define MSBV(bit)       (1 << ((bit) - 8))
00528 
00529 #define nic_outlb(addr, val) (*(volatile uint8_t *)(addr) = (val))
00530 #define nic_outhb(addr, val) (*(volatile uint8_t *)((addr) + 1) = (val))
00531 #define nic_outwx(addr, val) (*(volatile uint16_t *)(addr) = (val))
00532 #define nic_outw(addr, val) { \
00533     *(volatile uint8_t *)(addr) = (uint8_t)(val); \
00534     *((volatile uint8_t *)(addr) + 1) = (uint8_t)((val) >> 8); \
00535 }
00536 
00537 #define nic_inlb(addr) (*(volatile uint8_t *)(addr))
00538 #define nic_inhb(addr) (*(volatile uint8_t *)((addr) + 1))
00539 #define nic_inw(addr) (*(volatile uint16_t *)(addr))
00540 
00541 #define nic_bs(bank)    nic_outlb(NIC_BSR, bank)
00542 
00547 struct _NICINFO {
00548     HANDLE volatile ni_rx_rdy;    
00549     uint16_t ni_tx_cnt;           
00550     uint32_t ni_rx_packets;       
00551     uint32_t ni_tx_packets;       
00552     uint32_t ni_interrupts;       
00553     uint32_t ni_overruns;         
00554     uint32_t ni_rx_frame_errors;  
00555     uint32_t ni_rx_crc_errors;    
00556     uint32_t ni_rx_missed_errors; 
00557     uint8_t ni_mar[8];            
00558 };
00559 
00563 typedef struct _NICINFO NICINFO;
00564 
00571 
00572 
00573 static HANDLE mutex;
00574 static HANDLE maq;
00575 
00586 static uint8_t NicPhyRegSelect(uint8_t reg, uint8_t we)
00587 {
00588     uint8_t rs;
00589     uint8_t msk;
00590     uint8_t i;
00591 
00592     nic_bs(3);
00593     rs = (nic_inlb(NIC_MGMT) & ~(MGMT_MCLK | MGMT_MDO)) | MGMT_MDOE;
00594 
00595     
00596     for (i = 0; i < 33; i++) {
00597         nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00598         nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00599     }
00600 
00601     
00602     nic_outlb(NIC_MGMT, rs);
00603     nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00604     nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00605     nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00606 
00607     
00608     if (we) {
00609         nic_outlb(NIC_MGMT, rs);
00610         nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00611         nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00612         nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00613     } else {
00614         nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00615         nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00616         nic_outlb(NIC_MGMT, rs);
00617         nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00618     }
00619 
00620     
00621     for (i = 0; i < 5; i++) {
00622         nic_outlb(NIC_MGMT, rs);
00623         nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00624     }
00625 
00626     
00627     for (msk = 0x10; msk; msk >>= 1) {
00628         if (reg & msk) {
00629             nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00630             nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00631         } else {
00632             nic_outlb(NIC_MGMT, rs);
00633             nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00634         }
00635     }
00636     nic_outlb(NIC_MGMT, rs);
00637 
00638     return rs;
00639 }
00640 
00650 static uint16_t NicPhyRead(uint8_t reg)
00651 {
00652     uint16_t rc = 0;
00653     uint8_t rs;
00654     uint8_t i;
00655 
00656     
00657     rs = NicPhyRegSelect(reg, 0);
00658 
00659     
00660     rs &= ~MGMT_MDOE;
00661     nic_outlb(NIC_MGMT, rs);
00662     nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00663 
00664     
00665     for (i = 0; i < 16; i++) {
00666         nic_outlb(NIC_MGMT, rs);
00667         nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00668         rc <<= 1;
00669         rc |= (nic_inlb(NIC_MGMT) & MGMT_MDI) != 0;
00670     }
00671 
00672     
00673     nic_outlb(NIC_MGMT, rs);
00674 
00675     return rc;
00676 }
00677 
00686 static void NicPhyWrite(uint8_t reg, uint16_t val)
00687 {
00688     uint16_t msk;
00689     uint8_t rs;
00690 
00691     
00692     rs = NicPhyRegSelect(reg, 1);
00693 
00694     
00695     nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00696     nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00697     nic_outlb(NIC_MGMT, rs);
00698     nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00699 
00700     
00701     for (msk = 0x8000; msk; msk >>= 1) {
00702         if (val & msk) {
00703             nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00704             nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00705         } else {
00706             nic_outlb(NIC_MGMT, rs);
00707             nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00708         }
00709     }
00710 
00711     
00712     nic_outlb(NIC_MGMT, rs & ~MGMT_MDOE);
00713 }
00714 
00720 static int NicPhyConfig(void)
00721 {
00722     uint16_t phy_sor;
00723     uint16_t phy_sr;
00724     uint16_t phy_to;
00725     uint16_t mode;
00726 
00727     
00728 
00729 
00730 
00731 
00732     
00733     NicPhyWrite(NIC_PHYCR, PHYCR_RST);
00734     for (phy_to = 0;; phy_to++) {
00735         NutSleep(63);
00736         if ((NicPhyRead(NIC_PHYCR) & PHYCR_RST) == 0)
00737             break;
00738         if (phy_to > 3)
00739             return -1;
00740     }
00741     
00742 
00743     
00744     phy_sor = NicPhyRead(NIC_PHYSOR);
00745 
00746     
00747     NicPhyWrite(NIC_PHYMSK, PHYMSK_MLOSSSYN | PHYMSK_MCWRD | PHYMSK_MSSD |
00748                 PHYMSK_MESD | PHYMSK_MRPOL | PHYMSK_MJAB | PHYMSK_MSPDDT | PHYMSK_MDPLDT);
00749 
00750     
00751     mode = RPCR_ANEG | RPCR_LEDA_PAT | RPCR_LEDB_PAT;
00752     nic_bs(0);
00753     nic_outw(NIC_RPCR, mode);
00754 
00755 #ifdef NIC_FIXED
00756     
00757     phy_sr = NicPhyRead(NIC_PHYCFR1);
00758     NicPhyWrite(NIC_PHYCFR1, phy_sr | 0x8000);
00759     NutSleep(63);
00760 
00761     
00762     NicPhyWrite(NIC_PHYCR, NIC_FIXED);
00763     nic_bs(0);
00764     nic_outw(NIC_RPCR, mode);
00765 
00766     
00767     phy_sr = NicPhyRead(NIC_PHYCFR1);
00768     NicPhyWrite(NIC_PHYCFR1, phy_sr & ~0x8000);
00769     phy_sr = NicPhyRead(NIC_PHYCFR1);
00770 
00771 #else
00772     
00773 
00774 
00775 
00776     
00777     NicPhyWrite(NIC_PHYANAD, PHYANAD_TX_FDX | PHYANAD_TX_HDX | PHYANAD_10FDX | PHYANAD_10_HDX | PHYANAD_CSMA);
00778     NutSleep(63);
00779     for (phy_to = 0, phy_sr = 0;; phy_to++) {
00780         
00781         if (phy_to >= 1024)
00782             return -1;
00783         
00784         if ((phy_to & 127) == 0  ) {
00785             NicPhyWrite(NIC_PHYCR, PHYCR_ANEG_EN | PHYCR_ANEG_RST);
00786             
00787             NutSleep(63);
00788         }
00789         
00790         phy_sr = NicPhyRead(NIC_PHYSR);
00791         
00792         if (phy_sr & PHYSR_ANEG_ACK)
00793             break;
00794         NutSleep(63);
00795     }
00796     
00797 #endif
00798 
00799     return 0;
00800 }
00801 
00812 static INLINE int NicMmuWait(uint16_t tmo)
00813 {
00814     while (tmo--) {
00815         if ((nic_inlb(NIC_MMUCR) & MMUCR_BUSY) == 0)
00816             break;
00817         NutDelay(1);
00818     }
00819     return tmo ? 0 : -1;
00820 }
00821 
00827 static int NicReset(void)
00828 {
00829 #ifdef LANC111_RESET_BIT
00830     sbi(LANC111_RESET_DDR, LANC111_RESET_BIT);
00831     sbi(LANC111_RESET_PORT, LANC111_RESET_BIT);
00832     NutDelay(WAIT100);
00833     cbi(LANC111_RESET_PORT, LANC111_RESET_BIT);
00834     NutDelay(WAIT250);
00835     NutDelay(WAIT250);
00836 #endif
00837 
00838     
00839     nic_outlb(NIC_MSK, 0);
00840 
00841     
00842     nic_bs(0);
00843     nic_outw(NIC_RCR, RCR_SOFT_RST);
00844 
00845     
00846     nic_bs(1);
00847     nic_outw(NIC_CR, CR_EPH_EN);
00848 
00849     NutDelay(10);
00850 
00851     
00852     nic_bs(0);
00853     nic_outw(NIC_RCR, 0);
00854     nic_outw(NIC_TCR, 0);
00855 
00856     
00857     nic_bs(1);
00858     nic_outw(NIC_CTR, CTR_AUTO_RELEASE);
00859 
00860     
00861     nic_bs(2);
00862     nic_outlb(NIC_MMUCR, MMU_RST);
00863     if (NicMmuWait(1000))
00864         return -1;
00865 
00866     return 0;
00867 }
00868 
00874 static void NicUpdateMCHardware(NICINFO * ni)
00875 {
00876     int i;
00877 
00878     
00879     nic_bs(3);
00880     for (i = 0; i < 7; i++) {
00881         nic_outlb(NIC_MT + i, ni->ni_mar[i]);
00882     }
00883 }
00884 
00885 
00886 
00887 
00888 
00889 
00890 
00891 
00892 static int NicStart(CONST uint8_t * mac, NICINFO * ni)
00893 {
00894     uint8_t i;
00895 
00896     if (NicReset())
00897         return -1;
00898 
00899     
00900     nic_bs(3);
00901     nic_outlb(NIC_ERCV, 7);
00902     nic_bs(0);
00903     nic_outw(NIC_RCR, RCR_RXEN);
00904 
00905     
00906     nic_outw(NIC_TCR, TCR_PAD_EN | TCR_TXENA);
00907 
00908     
00909     if (NicPhyConfig())
00910         return -1;
00911 
00912     
00913     
00914     nic_bs(1);
00915     for (i = 0; i < 6; i++)
00916         nic_outlb(NIC_IAR + i, mac[i]);
00917     
00918 
00919     
00920     NicUpdateMCHardware(ni);
00921 
00922     
00923     nic_bs(2);
00924     nic_outlb(NIC_MSK, INT_ERCV | INT_RCV | INT_RX_OVRN);
00925 
00926     return 0;
00927 }
00928 
00929 
00930 
00931 
00932 static void NicInterrupt(void *arg)
00933 {
00934     uint8_t isr;
00935     uint8_t imr;
00936     NICINFO *ni = (NICINFO *) ((NUTDEVICE *) arg)->dev_dcb;
00937 
00938     ni->ni_interrupts++;
00939 
00940     
00941     nic_bs(2);
00942     imr = nic_inlb(NIC_MSK);
00943     nic_outlb(NIC_MSK, 0);
00944 
00945     
00946     isr = nic_inlb(NIC_IST);
00947     
00948     isr &= imr;
00949 
00950     
00951 
00952 
00953 
00954 
00955     if (isr & INT_TX_EMPTY) {
00956         nic_outlb(NIC_ACK, INT_TX_EMPTY);
00957         imr &= ~INT_TX_EMPTY;
00958     }
00959     
00960     else if (isr & INT_TX) {
00961         
00962         nic_bs(0);
00963         nic_outw(NIC_TCR, nic_inlb(NIC_TCR) | TCR_TXENA);
00964         nic_bs(2);
00965         nic_outlb(NIC_ACK, INT_TX);
00966         
00967         nic_outlb(NIC_MMUCR, MMU_PKT);
00968     }
00969 
00970 
00971     
00972 
00973 
00974 
00975     if (isr & INT_RX_OVRN) {
00976         nic_outlb(NIC_ACK, INT_RX_OVRN);
00977         
00978         NutEventPostFromIrq(&ni->ni_rx_rdy);
00979     }
00980     if (isr & INT_ERCV) {
00981         nic_outlb(NIC_ACK, INT_ERCV);
00982         NutEventPostFromIrq(&ni->ni_rx_rdy);
00983     }
00984     if (isr & INT_RCV) {
00985         nic_outlb(NIC_ACK, INT_RCV);
00986         imr &= ~INT_RCV;
00987         NutEventPostFromIrq(&ni->ni_rx_rdy);
00988     }
00989 
00990     if (isr & INT_ALLOC) {
00991         imr &= ~INT_ALLOC;
00992         NutEventPostFromIrq(&maq);
00993     }
00994     
00995     nic_outlb(NIC_MSK, imr);
00996 }
00997 
00998 
00999 
01000 
01001 static void NicWrite(uint8_t * buf, uint16_t len)
01002 {
01003     register uint16_t l = len - 1;
01004     register uint8_t ih = (uint16_t) l >> 8;
01005     register uint8_t il = (uint8_t) l;
01006 
01007     if (!len)
01008         return;
01009 
01010     do {
01011         do {
01012             nic_outlb(NIC_DATA, *buf++);
01013         } while (il-- != 0);
01014     } while (ih-- != 0);
01015 }
01016 
01017 
01018 
01019 
01020 static void NicRead(uint8_t * buf, uint16_t len)
01021 {
01022     register uint16_t l = len - 1;
01023     register uint8_t ih = (uint16_t) l >> 8;
01024     register uint8_t il = (uint8_t) l;
01025 
01026     if (!len)
01027         return;
01028 
01029     do {
01030         do {
01031             *buf++ = nic_inlb(NIC_DATA);
01032         } while (il-- != 0);
01033     } while (ih-- != 0);
01034 }
01035 
01046 static NETBUF *NicGetPacket(void)
01047 {
01048     NETBUF *nb = 0;
01049     
01050     uint16_t fsw;
01051     uint16_t fbc;
01052 
01053     
01054 
01055     nic_bs(2);
01056     if (nic_inw(NIC_FIFO) & 0x8000) {
01057         return 0;
01058     }
01059 
01060     
01061     nic_outw(NIC_PTR, PTR_READ | PTR_RCV | PTR_AUTO_INCR);
01062     _NOP();
01063     _NOP();
01064     _NOP();
01065     _NOP();
01066 
01067     
01068     fsw = nic_inw(NIC_DATA);
01069     fbc = nic_inw(NIC_DATA);
01070     
01071 
01072     
01073     if (fsw & 0xAC00) {
01074         nb = (NETBUF *) 0xFFFF;
01075     }
01076     
01077     else if (fbc < 66 || fbc > 1524) {
01078         nb = (NETBUF *) 0xFFFF;
01079     }
01080 
01081     else {
01082         
01083 
01084 
01085 
01086         fbc -= 3;
01087         nb = NutNetBufAlloc(0, NBAF_DATALINK, fbc);
01088 
01089         
01090         if (nb)
01091             NicRead(nb->nb_dl.vp, fbc);
01092     }
01093 
01094     
01095     nic_outlb(NIC_MMUCR, MMU_TOP);
01096 
01097     return nb;
01098 }
01099 
01114 static int NicPutPacket(NETBUF * nb)
01115 {
01116     uint16_t sz;
01117     uint8_t odd = 0;
01118     uint8_t imsk;
01119 
01120     
01121     
01122 
01123 
01124 
01125 
01126 
01127     if ((sz = nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz) > ETHERMTU)
01128         return -1;
01129 
01130     
01131     imsk = nic_inlb(NIC_MSK);
01132     nic_outlb(NIC_MSK, 0);
01133 
01134     
01135     nic_bs(2);
01136     nic_outlb(NIC_MMUCR, MMU_ALO);
01137     if (NicMmuWait(100))
01138         return -1;
01139 
01140     
01141     nic_outlb(NIC_MSK, imsk | INT_ALLOC);
01142 
01143     
01144     sz += nb->nb_dl.sz;
01145     sz += 6;
01146     if (sz & 1) {
01147         sz++;
01148         odd++;
01149     }
01150 
01151     
01152     while ((nic_inlb(NIC_IST) & INT_ALLOC) == 0) {
01153         if (NutEventWait(&maq, 125)) {
01154             nic_outlb(NIC_MMUCR, MMU_RST);
01155             NicMmuWait(1000);
01156             nic_outlb(NIC_MMUCR, MMU_ALO);
01157             if (NicMmuWait(100) || (nic_inlb(NIC_IST) & INT_ALLOC) == 0) {
01158                 if (NutEventWait(&maq, 125)) {
01159                     return -1;
01160                 }
01161             }
01162         }
01163     }
01164 
01165     
01166     imsk = nic_inlb(NIC_MSK);
01167     nic_outlb(NIC_MSK, 0);
01168 
01169 
01170     nic_outlb(NIC_PNR, nic_inhb(NIC_PNR));
01171 
01172     nic_outw(NIC_PTR, 0x4000);
01173 
01174     
01175     nic_outlb(NIC_DATA, 0);
01176     nic_outlb(NIC_DATA, 0);
01177 
01178     
01179     nic_outw(NIC_DATA, sz);
01180 
01181     
01182     NicWrite(nb->nb_dl.vp, nb->nb_dl.sz);
01183     NicWrite(nb->nb_nw.vp, nb->nb_nw.sz);
01184     NicWrite(nb->nb_tp.vp, nb->nb_tp.sz);
01185     NicWrite(nb->nb_ap.vp, nb->nb_ap.sz);
01186 
01187     if (odd)
01188         nic_outlb(NIC_DATA, 0);
01189 
01190     
01191     nic_outw(NIC_DATA, 0);
01192 
01193     
01194     if (NicMmuWait(100))
01195         return -1;
01196     nic_outlb(NIC_MMUCR, MMU_ENQ);
01197 
01198     
01199     imsk |= INT_TX | INT_TX_EMPTY;
01200     nic_outlb(NIC_MSK, imsk);
01201 
01202     return 0;
01203 }
01204 
01205 
01210 THREAD(NicRxLanc, arg)
01211 {
01212     NUTDEVICE *dev;
01213     IFNET *ifn;
01214     NICINFO *ni;
01215     NETBUF *nb;
01216     uint8_t imsk;
01217 
01218     dev = arg;
01219     ifn = (IFNET *) dev->dev_icb;
01220     ni = (NICINFO *) dev->dev_dcb;
01221 
01222     
01223 
01224 
01225 
01226 
01227     while (!ETHER_IS_UNICAST(ifn->if_mac)) {
01228         NutSleep(10);
01229     }
01230 
01231     
01232 
01233 
01234 
01235 
01236 
01237     while (NicStart(ifn->if_mac, ni)) {
01238         NutSleep(1000);
01239     }
01240 
01241     LANC111_SIGNAL_MODE();
01242     sbi(EIMSK, LANC111_SIGNAL_IRQ);
01243 
01244     NutEventPost(&mutex);
01245 
01246     
01247     NutThreadSetPriority(9);
01248 
01249     for (;;) {
01250 
01251         
01252 
01253 
01254 
01255         NutEventWait(&ni->ni_rx_rdy, 2000);
01256 
01257         
01258 
01259 
01260 
01261         imsk = nic_inlb(NIC_MSK);
01262         nic_outlb(NIC_MSK, 0);
01263         while ((nb = NicGetPacket()) != 0) {
01264             if (nb != (NETBUF *) 0xFFFF) {
01265                 ni->ni_rx_packets++;
01266                 (*ifn->if_recv) (dev, nb);
01267             }
01268         }
01269         nic_outlb(NIC_MSK, imsk | INT_RCV | INT_ERCV);
01270     }
01271 }
01272 
01283 int LancOutput(NUTDEVICE * dev, NETBUF * nb)
01284 {
01285     static uint32_t mx_wait = 5000;
01286     int rc = -1;
01287     NICINFO *ni;
01288 
01289     
01290 
01291 
01292 
01293     if (NutEventWait(&mutex, mx_wait) == 0) {
01294         ni = (NICINFO *) dev->dev_dcb;
01295 
01296         if (NicPutPacket(nb) == 0) {
01297             ni->ni_tx_packets++;
01298             rc = 0;
01299             
01300 
01301             mx_wait = 5000;
01302         }
01303         NutEventPost(&mutex);
01304     }
01305     
01306 
01307 
01308 
01309     else {
01310         mx_wait = 500;
01311     }
01312     return rc;
01313 }
01314 
01332 int LancInit(NUTDEVICE * dev)
01333 {
01334     
01335     cbi(EIMSK, LANC111_SIGNAL_IRQ);
01336     memset(dev->dev_dcb, 0, sizeof(NICINFO));
01337 
01338     
01339     if (NutRegisterIrqHandler(&LANC111_SIGNAL, NicInterrupt, dev))
01340         return -1;
01341 
01342     
01343 
01344 
01345 
01346 
01347     NutThreadCreate("rxi5", NicRxLanc, dev, (NUT_THREAD_LANCRXSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
01348 
01349     
01350 
01351     return 0;
01352 }
01353 
01354 static int LancIOCtl(NUTDEVICE * dev, int req, void *conf)
01355 {
01356     int rc = 0;
01357     IFNET *nif = (IFNET *) dev->dev_icb;
01358     NICINFO *ni = (NICINFO *) dev->dev_dcb;
01359     uint32_t i;
01360     MCASTENTRY *mcast;
01361 
01362     uint8_t mac[6];
01363 
01364     switch (req) {
01365         
01366     case SIOCSIFADDR:
01367         
01368         memcpy(nif->if_mac, conf, sizeof(nif->if_mac));
01369         break;
01370 
01371         
01372     case SIOCADDMULTI:
01373         mac[0] = 0x01;
01374         mac[1] = 0x00;
01375         mac[2] = 0x5E;
01376         mac[3] = ((uint8_t *) conf)[1] & 0x7f;
01377         mac[4] = ((uint8_t *) conf)[2];
01378         mac[5] = ((uint8_t *) conf)[3];
01379 
01380         mcast = malloc(sizeof(MCASTENTRY));
01381         if (mcast != NULL) {
01382             
01383 
01384 
01385 
01386 
01387 
01388             for (i = 0; i < 7; i++) {
01389                 ni->ni_mar[i] = 0xFF;
01390             }
01391 
01392             
01393             memcpy(mcast->mca_ha, mac, 6);
01394             mcast->mca_ip = *((uint32_t *) conf);
01395             mcast->mca_next = nif->if_mcast;
01396             nif->if_mcast = mcast;
01397 
01398             
01399             NicUpdateMCHardware(ni);
01400         } else {
01401             rc = -1;
01402         }
01403         break;
01404 
01405         
01406     case SIOCDELMULTI:
01407         
01408         rc = -1;
01409         break;
01410 
01411     default:
01412         rc = -1;
01413         break;
01414     }
01415 
01416     return rc;
01417 }
01418 
01419 static NICINFO dcb_eth0;
01420 
01426 static IFNET ifn_eth0 = {
01427     IFT_ETHER,                  
01428     0,                          
01429     {0, 0, 0, 0, 0, 0},         
01430     0,                          
01431     0,                          
01432     0,                          
01433     ETHERMTU,                   
01434     0,                          
01435     0,                          
01436     0,                          
01437     NutEtherInput,              
01438     LancOutput,                 
01439     NutEtherOutput,             
01440     0                           
01441 };
01442 
01452 NUTDEVICE devSmsc111 = {
01453     0,                          
01454     {'e', 't', 'h', '0', 0, 0, 0, 0, 0},        
01455     IFTYP_NET,                  
01456     0,                          
01457     0,                          
01458     &ifn_eth0,                  
01459     &dcb_eth0,                  
01460     LancInit,                   
01461     LancIOCtl,                  
01462     0,                          
01463     0,                          
01464     0,                          
01465     0,                          
01466     0,                          
01467     0                           
01468 };
01469