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 #include <arch/arm.h>
00076 
00077 #include <string.h>
00078 
00079 
00080 #include <sys/atom.h>
00081 #include <sys/heap.h>
00082 #include <sys/thread.h>
00083 #include <sys/event.h>
00084 #include <sys/timer.h>
00085 #include <sys/confnet.h>
00086 
00087 #include <dev/irqreg.h>
00088 #include <dev/ax88796.h>
00089 #include "reg_ax88796.h"
00090 
00091 #define ASIX_RESET_PIN 10
00092 
00093 static NICINFO dcb_eth0;
00094 
00099 
00100 
00106 static IFNET ifn_eth0 = {
00107     IFT_ETHER,                  
00108     0,                          
00109     {0, 0, 0, 0, 0, 0},         
00110     0,                          
00111     0,                          
00112     0,                          
00113     ETHERMTU,                   
00114     0,                          
00115     0,                          
00116     0,                          
00117     NutEtherInput,              
00118     AsixOutput,                 
00119     NutEtherOutput              
00120 };
00121 
00131 NUTDEVICE devAx88796 = {
00132     0,                          
00133     {'e', 't', 'h', '0', 0, 0, 0, 0, 0},        
00134     IFTYP_NET,                  
00135     0,                          
00136     0,                          
00137     &ifn_eth0,                  
00138     &dcb_eth0,                  
00139     AsixInit,                   
00140     0,                          
00141     0,                          
00142     0,                          
00143     0,                          
00144     0,                          
00145     0                           
00146 };
00147 
00151 struct nic_pkt_header {
00152     uint8_t ph_status;           
00153     uint8_t ph_nextpg;           
00154     uint16_t ph_size;            
00155 };
00156 
00157 
00158 
00159 
00160 
00161 
00162 
00163 
00164 
00165 
00166 void Delay16Cycles(void)
00167 {
00168     _NOP();
00169     _NOP();
00170     _NOP();
00171     _NOP();
00172     _NOP();
00173     _NOP();
00174     _NOP();
00175     _NOP();
00176     _NOP();
00177     _NOP();
00178     _NOP();
00179     _NOP();
00180     _NOP();
00181     _NOP();
00182     _NOP();
00183     _NOP();
00184 }
00185 
00186 
00192 static uint16_t MIIPutGet(uint16_t data, uint8_t bitCount)
00193 {
00194     uint16_t rc = 0;
00195     uint16_t mask;
00196     uint8_t i;
00197 
00198     mask = 1 << (bitCount - 1);
00199 
00200     for (i = 0; i < bitCount; i++) {
00201 
00202         
00203         if (data & mask) {
00204             Asix_Write(MII_EEP, (Asix_Read(MII_EEP) | MII_EEP_MDO));
00205         } else {
00206             Asix_Write(MII_EEP, (Asix_Read(MII_EEP) & ~(MII_EEP_MDO)));
00207         }
00208         
00209         Asix_Write(MII_EEP, (Asix_Read(MII_EEP) | MII_EEP_MDC));        
00210         Delay16Cycles();
00211 
00212         data <<= 1;
00213         rc <<= 1;
00214         rc |= (Asix_Read(MII_EEP) & MII_EEP_MDI) != 0;  
00215         Asix_Write(MII_EEP, (Asix_Read(MII_EEP) & ~(MII_EEP_MDC)));     
00216     }
00217     return rc;
00218 }
00219 
00220 
00227 uint16_t NicPhyRead(uint8_t reg)
00228 {
00229     uint16_t rc = 0;
00230 
00231     
00232     Asix_Write(CR, (Asix_Read(CR) & ~(CR_PS0)));
00233 
00234     
00235     MIIPutGet(0xFFFF, 16);
00236     MIIPutGet(0xFFFF, 16);
00237 
00238     
00239     MIIPutGet(0xD0, 9);
00240 
00241     
00242     MIIPutGet(reg, 5);
00243 
00244     
00245     MIIPutGet(0x0, 1);
00246 
00247     
00248     rc = MIIPutGet(0, 16);
00249 
00250     return rc;
00251 }
00252 
00253 
00262 void NicPhyWrite(uint8_t reg, uint16_t val)
00263 {
00264 
00265     
00266     Asix_Write(CR, (Asix_Read(CR) & ~(CR_PS0)));
00267 
00268     
00269     MIIPutGet(0xFFFF, 16);
00270     MIIPutGet(0xFFFF, 16);
00271 
00272     
00273     MIIPutGet(0xB0, 9);
00274 
00275     
00276     MIIPutGet(reg, 5);
00277 
00278     
00279     MIIPutGet(0x02, 2);
00280 
00281     
00282     MIIPutGet(val, 16);
00283 }
00284 
00285 
00286 
00290 static void NicCompleteDma(void)
00291 {
00292     uint8_t i;
00293 
00294     
00295     do {
00296         i = Asix_Read(PG0_ISR);
00297     } while ((i & ISR_RDC) == 0);
00298 
00299     
00300     Asix_Write(CR, CR_START | CR_RD2);
00301 
00302     
00303     Asix_Write(PG0_ISR, ISR_RDC);
00304 
00305     
00306     Delay16Cycles();
00307 }
00308 
00309 
00315 static int NicReset(void)
00316 {
00317     int tmp;
00318     
00319 
00320     
00321     outr(PIO_PER, _BV(ASIX_RESET_PIN));  
00322     outr(PIO_OER, _BV(ASIX_RESET_PIN));  
00323     outr(PIO_SODR, _BV(ASIX_RESET_PIN)); 
00324     NutDelay(100);
00325     outr(PIO_CODR, _BV(ASIX_RESET_PIN)); 
00326 
00327     
00328     tmp = 10;
00329     while (1) {
00330         NutDelay(255);
00331         if (!(Asix_Read(TR) & TR_RST_B))
00332             break;
00333         if (tmp-- == 0)
00334             return -1;
00335     }
00336 
00337     
00338     
00339     
00340     
00341 
00342 
00343 
00344 
00345 
00346 
00347     return 0;
00348 }
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00356 
00357 
00358 static int NicStart(CONST uint8_t * mac)
00359 {
00360     uint8_t i;
00361 
00362     
00363     if (NicReset())
00364         return -1;
00365 
00366     
00367     Asix_Write(CR, (CR_RD2 | CR_STOP));
00368 
00369     
00370     Asix_Write(PG0_DCR, DCR_WTS);
00371 
00372     
00373     Asix_Write(PG0_RBCR0, 0x00);
00374     Asix_Write(PG0_RBCR1, 0x00);
00375 
00376     
00377     Asix_Write(PG0_RCR, RCR_MON);
00378 
00379     
00380     Asix_Write(PG0_TCR, TCR_LB0);
00381 
00382     
00383     Asix_Write(PG0_BNRY, RXSTART_INIT);
00384     Asix_Write(PG0_PSTART, RXSTART_INIT);
00385     Asix_Write(PG0_PSTOP, RXSTOP_INIT);
00386 
00387     
00388     Asix_Write(PG0_ISR, 0xFF);
00389 
00390     
00391     Asix_Write(PG0_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE);
00392 
00393     
00394     Asix_Write(CR, (CR_PS0 | CR_RD2 | CR_STOP));
00395     Delay16Cycles();
00396 
00397     
00398     for (i = 0; i < 6; i++) {
00399         Asix_Write(PG1_PAR0 + i, mac[i]);
00400     }
00401 
00402     
00403     for (i = 0; i < 8; i++) {
00404         Asix_Write(PG1_MAR0 + i, 0x00);
00405     }
00406 
00407     
00408     Asix_Write(PG1_CPR, RXSTART_INIT + 1);
00409 
00410     
00411     Asix_Write(CR, (CR_RD2 | CR_START));        
00412     Delay16Cycles();
00413 
00414     
00415     Asix_Write(GPOC, 0x10);
00416 
00417     
00418     if (Asix_Read(GPI) & 0x04) {
00419         
00420         Asix_Write(PG0_TCR, TCR_FDU);
00421     }
00422     else {
00423         
00424         Asix_Write(PG0_TCR, 0);
00425     }
00426 
00427     
00428     
00429     Asix_Write(PG0_RCR, RCR_AB);
00430 
00431     return 0;
00432 }
00433 
00434 
00435 
00436 
00437 
00438 static void NicWrite(uint8_t * buf, uint16_t len)
00439 {
00440     register uint16_t *wp = (uint16_t *) buf;
00441 
00442     if (len & 1)
00443         len++;
00444     len >>= 1;
00445     
00446     while (len--) {
00447         
00448         Asix_WriteWord(DATAPORT, *wp);
00449         wp++;
00450     }
00451     
00452 }
00453 
00454 
00455 
00456 
00457 
00458 static void NicRead(uint8_t * buf, uint16_t len)
00459 {
00460     register uint16_t *wp = (uint16_t *) buf;
00461 
00462     if (len & 1)
00463         len++;
00464     len >>= 1;
00465     
00466     while (len--) {
00467         *wp = Asix_ReadWord(DATAPORT);
00468         
00469         wp++;
00470     }
00471     
00472 }
00473 
00474 
00485 static NETBUF *NicGetPacket(void)
00486 {
00487     NETBUF *nb = 0;
00488     struct nic_pkt_header hdr;
00489     uint16_t count;
00490     uint8_t nextpg;
00491     uint8_t bnry;
00492     uint8_t curr;
00493     uint8_t drop = 0;
00494 
00495     
00496     NutEnterCritical();
00497 
00498     
00499 
00500 
00501 
00502     curr = Asix_Read(PG0_CPR);
00503     
00504 
00505     
00506 
00507 
00508 
00509 
00510 
00511     if ((bnry = Asix_Read(PG0_BNRY) + 1) >= RXSTOP_INIT) {
00512         
00513         bnry = RXSTART_INIT;
00514     }
00515     if (bnry == curr) {
00516         
00517         NutJumpOutCritical();
00518         return 0;
00519     }
00520     
00521 
00522 
00523     Asix_Write(PG0_RBCR0, sizeof(struct nic_pkt_header));
00524     Asix_Write(PG0_RBCR1, 0);
00525     Asix_Write(PG0_RSAR0, 0);
00526     Asix_Write(PG0_RSAR1, bnry);
00527     Asix_Write(CR, CR_START | CR_RD0);
00528     Delay16Cycles();
00529 
00530     NicRead((uint8_t *) & hdr, sizeof(struct nic_pkt_header));
00531     NicCompleteDma();
00532     
00533 
00534     
00535 
00536 
00537     if (hdr.ph_size < 60 + sizeof(struct nic_pkt_header) || hdr.ph_size > 1514 + sizeof(struct nic_pkt_header)) {
00538         
00539         drop = 1;
00540     }
00541 
00542     
00543 
00544 
00545 
00546 
00547 
00548 
00549 
00550 
00551 
00552 
00553 
00554 
00555 
00556     nextpg = bnry + (hdr.ph_size >> 8) + ((hdr.ph_size & 0xFF) != 0);
00557     
00558 
00559     if (nextpg >= RXSTOP_INIT) {
00560         nextpg -= RXSTOP_INIT;
00561         nextpg += RXSTART_INIT;
00562     }
00563     if (nextpg != hdr.ph_nextpg) {
00564         uint8_t nextpg1 = nextpg + 1;
00565         if (nextpg1 >= RXSTOP_INIT) {
00566             nextpg1 -= RXSTOP_INIT;
00567             nextpg1 += RXSTART_INIT;
00568         }
00569         
00570         
00571         
00572         nextpg = nextpg1;
00573     }
00574     
00575 
00576 
00577     
00578 
00579 
00580 
00581     
00582     if (!drop && ((hdr.ph_status & 0x0E) == 0)) {
00583 
00584         
00585         count = hdr.ph_size - sizeof(struct nic_pkt_header);
00586         
00587         if ((nb = NutNetBufAlloc(0, NBAF_DATALINK, count))) {
00588             
00589 
00590 
00591 
00592 
00593             Asix_Write(PG0_RBCR0, count);
00594             Asix_Write(PG0_RBCR1, count >> 8);
00595             Asix_Write(PG0_RSAR0, sizeof(struct nic_pkt_header));
00596             Asix_Write(PG0_RSAR1, bnry);
00597 
00598             
00599 
00600 
00601             Asix_Write(CR, CR_START | CR_RD0);
00602             Delay16Cycles();
00603             NicRead(nb->nb_dl.vp, count);
00604             NicCompleteDma();
00605         }
00606     }
00607 
00608     
00609 
00610 
00611 
00612     if (--nextpg < RXSTART_INIT)
00613         nextpg = RXSTOP_INIT - 1;
00614     Asix_Write(PG0_BNRY, nextpg);
00615     NutExitCritical();
00616     return nb;
00617 
00618 }
00619 
00620 
00621 
00622 
00623 
00624 
00625 
00626 
00627 
00628 
00629 
00630 
00631 
00632 
00633 
00634 
00635 
00636 
00637 
00638 
00639 static uint8_t NicOverflow(volatile uint8_t * base)
00640 {
00641     unsigned int cr;
00642     unsigned int resend = 0;
00643     unsigned int curr;
00644 
00645     
00646 
00647 
00648 
00649 
00650     while (Asix_Read(CR) & CR_TXP);
00651     cr = Asix_Read(CR);
00652 
00653     
00654 
00655 
00656 
00657     Asix_Write(CR, CR_STOP | CR_RD2 | CR_PS0);
00658     curr = Asix_Read(PG1_CPR);
00659     Asix_Write(CR, CR_STOP | CR_RD2);
00660 
00661     
00662     Asix_Write(PG0_RBCR0, 0);
00663     Asix_Write(PG0_RBCR1, 0);
00664 
00665     
00666     if ((cr & CR_TXP) && ((Asix_Read(PG0_ISR) & (ISR_PTX | ISR_TXE)) == 0)) {
00667         resend = 1;
00668     }
00669 
00670     
00671     Asix_Write(PG0_TCR, TCR_LB0);
00672     Asix_Write(CR, CR_START | CR_RD2);
00673 
00674     
00675 
00676 
00677 
00678     if (--curr < TXSTART_INIT) {
00679         curr = RXSTOP_INIT - 1;
00680     }
00681     Asix_Write(PG0_BNRY, curr);
00682 
00683     
00684     Asix_Write(PG0_TCR, 0);
00685 
00686     
00687     if (resend) {
00688         Asix_Write(CR, CR_START | CR_TXP | CR_RD2);
00689     }
00690 
00691     
00692     Asix_Write(PG0_ISR, ISR_OVW);
00693     return resend;
00694 }
00695 
00696 
00697 static int NicPutPacket(NETBUF * nb)
00698 {
00699     uint16_t sz;                 
00700     uint16_t send_sz;            
00701     static uint8_t first_put = 0;
00702     int tmp;
00703 
00704 
00705     
00706 
00707 
00708     if (first_put != 1) {
00709         Asix_Write(CR, 0x21);
00710         NutDelay(1);
00711         Asix_Write(CR, 0x22);
00712         first_put = 1;
00713     }
00714 
00715     
00716 
00717 
00718 
00719     sz = nb->nb_dl.sz + nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz;
00720     if (sz > 1518)
00721         return -1;
00722     
00723 
00724     
00725 
00726 
00727 
00728     send_sz = sz;
00729     if (sz <= 60)
00730         send_sz = 60;
00731 
00732     
00733     NutEnterCritical();
00734     
00735     Asix_Write(CR, (CR_RD2 | CR_START));
00736 
00737     
00738 
00739 
00740 
00741 
00742 
00743     tmp = 120;
00744     while ((Asix_Read(CR) & CR_TXP) && tmp--)
00745         NutDelay(1);
00746 
00747 
00748     
00749     Asix_Write(PG0_RSAR0, 0x00);
00750     Asix_Write(PG0_RSAR1, TXSTART_INIT);
00751 
00752     
00753     Asix_Write(PG0_RBCR0, (unsigned char) (sz));
00754     Asix_Write(PG0_RBCR1, (unsigned char) (sz >> 8));
00755 
00756     
00757     Asix_Write(CR, (CR_RD1 | CR_START));
00758 
00759     
00760     NicWrite(nb->nb_dl.vp, nb->nb_dl.sz);
00761     NicWrite(nb->nb_nw.vp, nb->nb_nw.sz);
00762     NicWrite(nb->nb_tp.vp, nb->nb_tp.sz);
00763     NicWrite(nb->nb_ap.vp, nb->nb_ap.sz);
00764 
00765     
00766     NicCompleteDma();
00767 
00768     
00769     Asix_Write(PG0_ISR, (ISR_PTX | ISR_TXE));
00770     Delay16Cycles();
00771 
00772     
00773     Asix_Write(CR, CR_START | CR_RD2);
00774     
00775     Asix_Write(PG0_TBCR0, (unsigned char) (send_sz));
00776     Asix_Write(PG0_TBCR1, (unsigned char) ((send_sz) >> 8));
00777     Asix_Write(PG0_TPSR, TXSTART_INIT);
00778 
00779     
00780     Asix_Write(CR, CR_START | CR_TXP | CR_RD2);
00781 
00782     
00783     NutExitCritical();
00784     return 0;
00785 }
00786 
00787 
00792 THREAD(NicRxAsix, arg)
00793 {
00794 
00795     NUTDEVICE *dev;
00796     IFNET *ifn;
00797     NICINFO *ni;
00798     NETBUF *nb;
00799 
00800     
00801     dev = &devAx88796;
00802 
00803     ifn = (IFNET *) dev->dev_icb;
00804     ni = (NICINFO *) dev->dev_dcb;
00805 
00806     
00807 
00808 
00809 
00810 
00811     while (!ETHER_IS_UNICAST(ifn->if_mac)) {
00812         NutSleep(10);
00813     }
00814 
00815     NutEnterCritical();
00816     NicStart(ifn->if_mac);
00817     NutExitCritical();
00818 
00819     
00820     
00821     NutThreadSetPriority(9);
00822 
00823     while (1) {
00824         
00825         NutEventWait(&ni->ni_rx_rdy, 0);
00826         
00827         
00828 
00829 
00830 
00831         do {
00832             nb = NicGetPacket();
00833             
00834 
00835             if (0) {            
00836                 NicStart(ifn->if_mac);
00837 
00838             } else if (nb) {
00839                 ni->ni_rx_packets++;
00840                 (*ifn->if_recv) (dev, nb);
00841             }
00842         } while (nb);
00843     }
00844 }
00845 
00846 
00847 
00848 
00849 
00850 static void NicInterrupt(void *arg)
00851 {
00852     uint8_t isr;
00853     volatile uint8_t *base = (uint8_t *) (((NUTDEVICE *) arg)->dev_base);
00854     NICINFO *ni = (NICINFO *) ((NUTDEVICE *) arg)->dev_dcb;
00855 
00856     ni->ni_interrupts++;
00857 
00858     isr = Asix_Read(PG0_ISR);
00859     Delay16Cycles();
00860     Asix_Write(PG0_ISR, isr);
00861 
00862     
00863     
00864     
00865     
00866 
00867     
00868 
00869 
00870 
00871 
00872     if (isr & ISR_OVW) {
00873         ni->ni_rx_pending++;
00874         if (NicOverflow(base))
00875             ni->ni_tx_bsy++;
00876         else {
00877             NutEventPostAsync(&ni->ni_tx_rdy);
00878         }
00879         ni->ni_overruns++;
00880     } else {
00881 
00882         
00883 
00884 
00885 
00886 
00887         if (isr & (ISR_PTX | ISR_TXE)) {
00888             ni->ni_tx_bsy = 0;
00889         }
00890 
00891         
00892 
00893 
00894 
00895         if (isr & ISR_PRX) {
00896             ni->ni_rx_pending++;
00897             
00898             NutEventPostFromIrq(&ni->ni_rx_rdy);
00899         }
00900 
00901         
00902         if (isr & ISR_RXE) {
00903             if (Asix_Read(PG0_RSR) & RSR_FAE)
00904                 ni->ni_rx_frame_errors++;
00905             if (Asix_Read(PG0_RSR) & RSR_CR)
00906                 ni->ni_rx_crc_errors++;
00907             if (Asix_Read(PG0_RSR) & RSR_MPA)
00908                 ni->ni_rx_missed_errors++;
00909         }
00910     }
00911 }
00912 
00913 void NicInterruptEntry(void) __attribute__ ((naked));
00914 void NicInterruptEntry(void)
00915 {
00916     IRQ_ENTRY();
00917     
00918     NicInterrupt(&devAx88796);
00919     IRQ_EXIT();
00920 }
00921 
00922 
00933 int AsixOutput(NUTDEVICE * dev, NETBUF * nb)
00934 {
00935     int rc = -1;
00936     NICINFO *ni = (NICINFO *) dev->dev_dcb;
00937 
00938     if (NicPutPacket(nb) == 0) {
00939         ni->ni_tx_packets++;
00940         rc = 0;
00941     }
00942     return rc;
00943 }
00944 
00945 
00963 int AsixInit(NUTDEVICE * dev)
00964 {
00965     
00966     confnet.cd_size = sizeof(CONFNET);
00967     strcpy(confnet.cd_name, "eth0");
00968     memset(confnet.cdn_mac, 0xFF, 6);
00969 
00970     
00971     
00972     memset(dev->dev_dcb, 0, sizeof(NICINFO));
00973 
00974     
00975 
00976 
00977     
00978     NutThreadCreate("rxi5", NicRxAsix, dev, 1024);
00979 
00980     outr(PIO_PDR, _BV(9));
00981     
00982     
00983     outr(AIC_IDCR, _BV(IRQ0_ID));
00984     
00985     outr(AIC_SVR(IRQ0_ID), (unsigned int) NicInterruptEntry);
00986     
00987     
00988     outr(AIC_SMR(IRQ0_ID), (AIC_SRCTYPE_EXT_NEGATIVE_EDGE | 5));
00989     
00990     outr(AIC_ICCR, _BV(IRQ0_ID));
00991     
00992     outr(AIC_IECR, _BV(IRQ0_ID));
00993 
00994     
00995     return 0;
00996 }
00997