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 
00115 
00116 
00117 
00118 
00119 #include <cfg/os.h>
00120 #include <cfg/arch/avr.h>
00121 #include <cfg/dev.h>
00122 
00123 #include <string.h>
00124 
00125 #include <sys/atom.h>
00126 #include <sys/heap.h>
00127 #include <sys/thread.h>
00128 #include <sys/event.h>
00129 #include <sys/timer.h>
00130 #include <sys/confnet.h>
00131 
00132 #include <net/ether.h>
00133 #include <net/if_var.h>
00134 
00135 #include <dev/irqreg.h>
00136 #include <dev/nicrtl.h>
00137 #include "rtlregs.h"
00138 
00139 #ifdef NUTDEBUG
00140 #include <sys/osdebug.h>
00141 #include <net/netdebug.h>
00142 #endif
00143 
00144 #ifndef NUT_THREAD_NICRXSTACK
00145 #define NUT_THREAD_NICRXSTACK   640
00146 #endif
00147 
00148 
00149 
00150 
00151 #if (RTL_EESK_AVRPORT == AVRPORTB)
00152 #define RTL_EESK_PIN    PINB
00153 #define RTL_EESK_DDR    DDRB
00154 
00155 #elif (RTL_EESK_AVRPORT == AVRPORTC)
00156 #define RTL_EE_MEMBUS
00157 #define RTL_EESK_PIN    PINC
00158 #define RTL_EESK_DDR    DDRC
00159 
00160 #elif (RTL_EESK_AVRPORT == AVRPORTD)
00161 #define RTL_EESK_PIN    PIND
00162 #define RTL_EESK_DDR    DDRD
00163 
00164 #elif (RTL_EESK_AVRPORT == AVRPORTE)
00165 #define RTL_EESK_PIN    PINE
00166 #define RTL_EESK_DDR    DDRE
00167 
00168 #elif (RTL_EESK_AVRPORT == AVRPORTF)
00169 #define RTL_EESK_PIN    PINF
00170 #define RTL_EESK_DDR    DDRF
00171 
00172 #endif 
00173 
00174 #if (RTL_EEDO_AVRPORT == AVRPORTB)
00175 #define RTL_EEDO_PORT   PORTB
00176 #define RTL_EEDO_DDR    DDRB
00177 
00178 #elif (RTL_EEDO_AVRPORT == AVRPORTC)
00179 #define RTL_EE_MEMBUS
00180 #define RTL_EEDO_PORT   PORTC
00181 #define RTL_EEDO_DDR    DDRC
00182 
00183 #elif (RTL_EEDO_AVRPORT == AVRPORTD)
00184 #define RTL_EEDO_PORT   PORTD
00185 #define RTL_EEDO_DDR    DDRD
00186 
00187 #elif (RTL_EEDO_AVRPORT == AVRPORTE)
00188 #define RTL_EEDO_PORT   PORTE
00189 #define RTL_EEDO_DDR    DDRE
00190 
00191 #elif (RTL_EEDO_AVRPORT == AVRPORTF)
00192 #define RTL_EEDO_PORT   PORTF
00193 #define RTL_EEDO_DDR    DDRF
00194 
00195 #endif 
00196 
00197 #if (RTL_EEMU_AVRPORT == AVRPORTB)
00198 #define RTL_EEMU_PORT   PORTB
00199 #define RTL_EEMU_DDR    DDRB
00200 
00201 #elif (RTL_EEMU_AVRPORT == AVRPORTC)
00202 #define RTL_EE_MEMBUS
00203 #define RTL_EEMU_PORT   PORTC
00204 #define RTL_EEMU_DDR    DDRC
00205 
00206 #elif (RTL_EEMU_AVRPORT == AVRPORTD)
00207 #define RTL_EEMU_PORT   PORTD
00208 #define RTL_EEMU_DDR    DDRD
00209 
00210 #elif (RTL_EEMU_AVRPORT == AVRPORTE)
00211 #define RTL_EEMU_PORT   PORTE
00212 #define RTL_EEMU_DDR    DDRE
00213 
00214 #elif (RTL_EEMU_AVRPORT == AVRPORTF)
00215 #define RTL_EEMU_PORT   PORTF
00216 #define RTL_EEMU_DDR    DDRF
00217 
00218 #endif 
00219 
00220 #if (RTL_RESET_AVRPORT == AVRPORTB)
00221 #define RTL_RESET_PORT   PORTB
00222 #define RTL_RESET_DDR    DDRB
00223 
00224 #elif (RTL_RESET_AVRPORT == AVRPORTD)
00225 #define RTL_RESET_PORT   PORTD
00226 #define RTL_RESET_DDR    DDRD
00227 
00228 #elif (RTL_RESET_AVRPORT == AVRPORTE)
00229 #define RTL_RESET_PORT   PORTE
00230 #define RTL_RESET_DDR    DDRE
00231 
00232 #elif (RTL_RESET_AVRPORT == AVRPORTF)
00233 #define RTL_RESET_PORT   PORTF
00234 #define RTL_RESET_DDR    DDRF
00235 
00236 #endif 
00237 
00238 
00242 #if (RTL_SIGNAL_IRQ == INT0)
00243 #define RTL_SIGNAL sig_INTERRUPT0
00244 #ifdef __AVR_ENHANCED__
00245 #define RTL_RISING_EDGE_MODE()   sbi(EICRA, ISC00); sbi(EICRA, ISC01)
00246 #endif
00247 
00248 #elif (RTL_SIGNAL_IRQ == INT1)
00249 #define RTL_SIGNAL sig_INTERRUPT1
00250 #ifdef __AVR_ENHANCED__
00251 #define RTL_RISING_EDGE_MODE()   sbi(EICRA, ISC10); sbi(EICRA, ISC11)
00252 #endif
00253 
00254 #elif (RTL_SIGNAL_IRQ == INT2)
00255 #define RTL_SIGNAL sig_INTERRUPT2
00256 #ifdef __AVR_ENHANCED__
00257 #define RTL_RISING_EDGE_MODE()   sbi(EICRA, ISC20); sbi(EICRA, ISC21)
00258 #endif
00259 
00260 #elif (RTL_SIGNAL_IRQ == INT3)
00261 #define RTL_SIGNAL sig_INTERRUPT3
00262 #ifdef __AVR_ENHANCED__
00263 #define RTL_RISING_EDGE_MODE()   sbi(EICRA, ISC30); sbi(EICRA, ISC31)
00264 #endif
00265 
00266 #elif (RTL_SIGNAL_IRQ == INT4)
00267 #define RTL_SIGNAL sig_INTERRUPT4
00268 #ifdef __AVR_ENHANCED__
00269 #define RTL_RISING_EDGE_MODE()   sbi(EICRB, ISC40); sbi(EICRB, ISC41)
00270 #endif
00271 
00272 #elif (RTL_SIGNAL_IRQ == INT6)
00273 #define RTL_SIGNAL sig_INTERRUPT6
00274 #ifdef __AVR_ENHANCED__
00275 #define RTL_RISING_EDGE_MODE()   sbi(EICRB, ISC60); sbi(EICRB, ISC61)
00276 #endif
00277 
00278 #elif (RTL_SIGNAL_IRQ == INT7)
00279 #define RTL_SIGNAL sig_INTERRUPT7
00280 #ifdef __AVR_ENHANCED__
00281 #define RTL_RISING_EDGE_MODE()   sbi(EICRB, ISC70); sbi(EICRB, ISC71)
00282 #endif
00283 
00284 #else
00285 #define RTL_SIGNAL sig_INTERRUPT5
00286 #ifdef __AVR_ENHANCED__
00287 #define RTL_RISING_EDGE_MODE()   sbi(EICRB, ISC50); sbi(EICRB, ISC51)
00288 #endif
00289 
00290 #endif 
00291 
00292 
00296 #define NIC_PAGE_SIZE   0x100
00297 
00301 #define NIC_START_PAGE  0x40
00302 
00306 #define NIC_STOP_PAGE   0x60
00307 
00313 #define NIC_TX_PAGES    6
00314 
00335 #define NIC_TX_BUFFERS      1
00336 
00337 #define NIC_FIRST_TX_PAGE   NIC_START_PAGE
00338 #define NIC_FIRST_RX_PAGE   (NIC_FIRST_TX_PAGE + NIC_TX_PAGES * NIC_TX_BUFFERS)
00339 
00340 #define NIC_CR_PAGE0 (0)
00341 #define NIC_CR_PAGE1 (NIC_CR_PS0)
00342 #define NIC_CR_PAGE2 (NIC_CR_PS1)
00343 #define NIC_CR_PAGE3 (NIC_CR_PS1 | NIC_CR_PS0)
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353 
00354 static INLINE void Delay16Cycles(void)
00355 {
00356     _NOP();
00357     _NOP();
00358     _NOP();
00359     _NOP();
00360     _NOP();
00361     _NOP();
00362     _NOP();
00363     _NOP();
00364     _NOP();
00365     _NOP();
00366     _NOP();
00367     _NOP();
00368     _NOP();
00369     _NOP();
00370     _NOP();
00371     _NOP();
00372 }
00373 
00378 
00382 struct nic_pkt_header {
00383     uint8_t ph_status;           
00384     uint8_t ph_nextpg;           
00385     uint16_t ph_size;            
00386 };
00387 
00388 #define NICINB(reg)         (*((volatile uint8_t *)RTL_BASE_ADDR + reg))
00389 #define NICOUTB(reg, val)   (*((volatile uint8_t *)RTL_BASE_ADDR + reg) = val)
00390 
00395 static int NicReset(void)
00396 {
00397     uint8_t i;
00398     uint8_t j;
00399 
00400 
00401 
00402 
00403 
00404 
00405 #ifdef RTL_RESET_BIT
00406     sbi(RTL_RESET_DDR, RTL_RESET_BIT);
00407     sbi(RTL_RESET_PORT, RTL_RESET_BIT);
00408     NutDelay(WAIT100);
00409     cbi(RTL_RESET_PORT, RTL_RESET_BIT);
00410     NutDelay(WAIT250);
00411     NutDelay(WAIT250);
00412 #endif
00413 
00414     
00415 
00416 
00417 
00418 
00419     for (j = 0; j < 20; j++) {
00420         i = NICINB(NIC_RESET);
00421         NutDelay(WAIT5);
00422         NICOUTB(NIC_RESET, i);
00423         for (i = 0; i < 20; i++) {
00424             NutDelay(WAIT50);
00425             
00426 
00427 
00428 
00429 
00430 
00431 
00432             if ((NICINB(NIC_PG0_ISR) & NIC_ISR_RST) != 0 &&     
00433                 NICINB(NIC_PG0_RBCR0) == 0x50 &&        
00434                 NICINB(NIC_PG0_RBCR1) == 0x70)
00435                 return 0;
00436         }
00437     }
00438     return -1;
00439 }
00440 
00441 static int DetectNicEeprom(void)
00442 {
00443 #ifdef RTL_EESK_BIT
00444     register unsigned int cnt = 0;
00445 
00446     NutEnterCritical();
00447 
00448     
00449 
00450 
00451 
00452     sbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
00453     sbi(RTL_EEDO_DDR, RTL_EEDO_BIT);
00454 #ifdef RTL_EEMU_BIT
00455     sbi(RTL_EEMU_PORT, RTL_EEMU_BIT);
00456     sbi(RTL_EEMU_DDR, RTL_EEMU_BIT);
00457 #endif
00458     NutDelay(20);
00459 
00460     
00461 
00462 
00463     NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);
00464     NICOUTB(NIC_PG3_EECR, NIC_EECR_EEM0);
00465 
00466     
00467 
00468 
00469 #ifdef RTL_EE_MEMBUS
00470     
00471 
00472 
00473 #ifdef __AVR_ENHANCED__
00474     
00475     outb(XMCRB, inb(XMCRB) | _BV(XMM0) | _BV(XMM1));
00476 #else
00477     
00478     cbi(MCUCR, SRE);
00479 #endif
00480 #endif
00481 
00482     
00483 
00484 
00485 
00486     if (bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT)) {
00487         while (++cnt && bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT));
00488     } else {
00489         while (++cnt && bit_is_clear(RTL_EESK_PIN, RTL_EESK_BIT));
00490     }
00491 
00492 #ifdef RTL_EE_MEMBUS
00493     
00494 
00495 
00496 #ifdef __AVR_ENHANCED__
00497     
00498     outb(XMCRB, inb(XMCRB) & ~(_BV(XMM0) | _BV(XMM1)));
00499 #else
00500     
00501     sbi(MCUCR, SRE);
00502 #endif
00503 #endif
00504 
00505     
00506     cbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
00507     cbi(RTL_EEDO_DDR, RTL_EEDO_BIT);
00508 #ifdef RTL_EEMU_BIT
00509     cbi(RTL_EEMU_PORT, RTL_EEMU_BIT);
00510     cbi(RTL_EEMU_DDR, RTL_EEMU_BIT);
00511 #endif
00512 
00513     
00514     NutExitCritical();
00515 
00516     
00517     while (NICINB(NIC_CR) != (NIC_CR_STP | NIC_CR_RD2));
00518 
00519     return cnt ? 0 : -1;
00520 #else
00521     return -1;
00522 #endif
00523 }
00524 
00525 #ifdef RTL_EESK_BIT
00526 
00527 
00528 
00529 
00530 
00531 
00532 static prog_char nic_eeprom[18] = {
00533     0xFF,                       
00534     0xFF,                       
00535 
00536     0xFF,                       
00537     0x30,                       
00538 
00539     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
00540     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF      
00541 };
00542 #endif
00543 
00553 static void EmulateNicEeprom(void)
00554 {
00555 #ifdef RTL_EESK_BIT
00556     register uint8_t clk;
00557     register uint8_t cnt;
00558     register uint8_t val;
00559 
00560     
00561 
00562 
00563 
00564     NutEnterCritical();
00565 
00566     
00567 
00568 
00569 
00570     cbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
00571     sbi(RTL_EEDO_DDR, RTL_EEDO_BIT);
00572 #ifdef RTL_EEMU_BIT
00573     sbi(RTL_EEMU_PORT, RTL_EEMU_BIT);
00574     sbi(RTL_EEMU_DDR, RTL_EEMU_BIT);
00575 #endif
00576     NutDelay(20);
00577 
00578     
00579 
00580 
00581 
00582 
00583 
00584     
00585     NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);
00586     NICOUTB(NIC_PG3_EECR, NIC_EECR_EEM0);
00587 
00588     
00589 
00590 
00591 
00592 #ifdef RTL_EE_MEMBUS
00593     
00594 
00595 
00596 #ifdef __AVR_ENHANCED__
00597     
00598     outb(XMCRB, inb(XMCRB) | _BV(XMM0) | _BV(XMM1));
00599 #else
00600     
00601     cbi(MCUCR, SRE);
00602 #endif
00603 #endif
00604 
00605     
00606 
00607 
00608     for (cnt = 0; cnt < sizeof(nic_eeprom);) {
00609 
00610         
00611 
00612 
00613 
00614 
00615 
00616 
00617         for (clk = 0; clk < 11; clk++) {
00618             while (bit_is_clear(RTL_EESK_PIN, RTL_EESK_BIT));
00619             while (bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT));
00620         }
00621 
00622         
00623 
00624 
00625 
00626         val = PRG_RDB(nic_eeprom + cnt);
00627         cnt++;
00628         for (clk = 0x80; clk; clk >>= 1) {
00629             while (bit_is_clear(RTL_EESK_PIN, RTL_EESK_BIT));
00630             if (val & clk)
00631                 sbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
00632             while (bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT));
00633             cbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
00634         }
00635 
00636         
00637 
00638 
00639         val = PRG_RDB(nic_eeprom + cnt);
00640         cnt++;
00641         for (clk = 0x80; clk; clk >>= 1) {
00642             while (bit_is_clear(RTL_EESK_PIN, RTL_EESK_BIT));
00643             if (val & clk)
00644                 sbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
00645             while (bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT));
00646             cbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
00647         }
00648 
00649 
00650         
00651         for (clk = 0; clk < 5; clk++) {
00652             while (bit_is_clear(RTL_EESK_PIN, RTL_EESK_BIT));
00653             while (bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT));
00654         }
00655     }
00656 
00657 #ifdef RTL_EE_MEMBUS
00658     
00659 
00660 
00661 #ifdef __AVR_ENHANCED__
00662     
00663     outb(XMCRB, inb(XMCRB) & ~(_BV(XMM0) | _BV(XMM1)));
00664 #else
00665     
00666     sbi(MCUCR, SRE);
00667 #endif
00668 #endif
00669 
00670     
00671     cbi(RTL_EEDO_DDR, RTL_EEDO_BIT);
00672 #ifdef RTL_EEMU_BIT
00673     cbi(RTL_EEMU_PORT, RTL_EEMU_BIT);
00674     cbi(RTL_EEMU_DDR, RTL_EEMU_BIT);
00675 #endif
00676 
00677     
00678     NutExitCritical();
00679 #endif
00680 }
00681 
00682 
00683 
00684 
00685 
00686 
00687 static int NicStart(CONST uint8_t * mac)
00688 {
00689     uint8_t i;
00690 
00691     if (NicReset()) {
00692         return -1;
00693     }
00694     if (DetectNicEeprom() == 0) {
00695         EmulateNicEeprom();
00696     }
00697 
00698     
00699 
00700 
00701 
00702     NICOUTB(NIC_PG0_IMR, 0);
00703     NICOUTB(NIC_PG0_ISR, 0xff);
00704 
00705     
00706 
00707 
00708 
00709 
00710 
00711 
00712     NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);
00713 
00714     
00715 
00716 
00717 
00718     NICOUTB(NIC_PG3_EECR, NIC_EECR_EEM0 | NIC_EECR_EEM1);
00719 
00720     
00721 
00722 
00723 
00724 
00725     NICOUTB(NIC_PG3_CONFIG2, NIC_CONFIG2_BSELB);
00726 
00727     
00728 
00729 
00730 
00731 
00732 
00733 
00734 
00735     NICOUTB(NIC_PG3_CONFIG3, NIC_CONFIG3_LEDS1 | NIC_CONFIG3_LEDS1);
00736 
00737     
00738 
00739 
00740 
00741     NICOUTB(NIC_PG3_EECR, 0);
00742     NutDelay(255);
00743 
00744     
00745 
00746 
00747 
00748 
00749     NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2);
00750     NICOUTB(NIC_PG0_DCR, NIC_DCR_LS | NIC_DCR_FT1);
00751 
00752     
00753 
00754 
00755     NICOUTB(NIC_PG0_RBCR0, 0);
00756     NICOUTB(NIC_PG0_RBCR1, 0);
00757 
00758     
00759 
00760 
00761 
00762 
00763     NICOUTB(NIC_PG0_RCR, NIC_RCR_MON);
00764     NICOUTB(NIC_PG0_TCR, NIC_TCR_LB0);
00765 
00766     
00767 
00768 
00769 
00770 
00771 
00772     NICOUTB(NIC_PG0_TPSR, NIC_FIRST_TX_PAGE);
00773     NICOUTB(NIC_PG0_BNRY, NIC_STOP_PAGE - 1);
00774     NICOUTB(NIC_PG0_PSTART, NIC_FIRST_RX_PAGE);
00775     NICOUTB(NIC_PG0_PSTOP, NIC_STOP_PAGE);
00776 
00777     
00778 
00779 
00780     NICOUTB(NIC_PG0_ISR, 0xff);
00781 
00782     
00783 
00784 
00785 
00786     NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0);
00787     for (i = 0; i < 6; i++)
00788         NICOUTB(NIC_PG1_PAR0 + i, mac[i]);
00789 
00790     
00791 
00792 
00793     for (i = 0; i < 8; i++)
00794         NICOUTB(NIC_PG1_MAR0 + i, 0);
00795 
00796     
00797 
00798 
00799     NICOUTB(NIC_PG1_CURR, NIC_FIRST_RX_PAGE);
00800 
00801     
00802 
00803 
00804     NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2);
00805 
00806     
00807 
00808 
00809 
00810     NICOUTB(NIC_PG0_RCR, NIC_RCR_AB);
00811 
00812     
00813 
00814 
00815     NICOUTB(NIC_PG0_ISR, 0xff);
00816     
00817     NICOUTB(NIC_PG0_IMR, NIC_IMR_PRXE | NIC_IMR_RXEE | NIC_IMR_TXEE | NIC_IMR_OVWE);
00818 
00819     
00820 
00821 
00822 
00823 
00824     NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
00825     NICOUTB(NIC_PG0_TCR, 0);
00826 
00827     NutDelay(255);
00828 
00829     return 0;
00830 }
00831 
00835 static void NicCompleteDma(void)
00836 {
00837     uint8_t i;
00838 
00839     
00840 
00841 
00842     NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
00843 
00844     
00845 
00846 
00847     for (i = 0; i <= 20; i++)
00848         if (NICINB(NIC_PG0_ISR) & NIC_ISR_RDC)
00849             break;
00850 
00851     
00852 
00853 
00854     NICOUTB(NIC_PG0_ISR, NIC_ISR_RDC);
00855 }
00856 
00857 
00858 
00859 
00860 static void NicWrite(uint8_t * buf, uint16_t len)
00861 {
00862     register uint16_t l = len - 1;
00863     register uint8_t ih = (uint16_t) l >> 8;
00864     register uint8_t il = (uint8_t) l;
00865 
00866     if (!len)
00867         return;
00868 
00869     do {
00870         do {
00871             NICOUTB(NIC_IOPORT, *buf++);
00872         } while (il-- != 0);
00873     } while (ih-- != 0);
00874 }
00875 
00876 
00877 
00878 
00879 static void NicRead(uint8_t * buf, uint16_t len)
00880 {
00881     register uint16_t l = len - 1;
00882     register uint8_t ih = (uint16_t) l >> 8;
00883     register uint8_t il = (uint8_t) l;
00884 
00885     if (!len)
00886         return;
00887 
00888     do {
00889         do {
00890             *buf++ = NICINB(NIC_IOPORT);
00891         } while (il-- != 0);
00892     } while (ih-- != 0);
00893 }
00894 
00895 
00909 static int NicPutPacket(NETBUF * nb)
00910 {
00911     uint16_t sz;
00912     uint16_t i;
00913     uint8_t padding = 0;
00914 
00915     
00916 
00917 
00918 
00919 
00920 
00921 
00922 
00923 
00924     sz = nb->nb_dl.sz + nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz;
00925     if (sz > 1514)
00926         return -1;
00927 
00928     
00929 
00930 
00931 
00932     if (sz < 60) {
00933         padding = (uint8_t) (60 - sz);
00934         sz = 60;
00935     }
00936 
00937     
00938 
00939 
00940 
00941 
00942 
00943     while (NICINB(NIC_CR) & NIC_CR_TXP)
00944         NutThreadYield();
00945 
00946     
00947     cbi(EIMSK, RTL_SIGNAL_IRQ);
00948 
00949     
00950 
00951 
00952 
00953     NICOUTB(NIC_PG0_RBCR0, sz);
00954     NICOUTB(NIC_PG0_RBCR1, sz >> 8);
00955     NICOUTB(NIC_PG0_RSAR0, 0);
00956     NICOUTB(NIC_PG0_RSAR1, NIC_FIRST_TX_PAGE);
00957 
00958     
00959 
00960 
00961     NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD1);
00962 
00963     
00964 
00965 
00966     NicWrite(nb->nb_dl.vp, nb->nb_dl.sz);
00967     NicWrite(nb->nb_nw.vp, nb->nb_nw.sz);
00968     NicWrite(nb->nb_tp.vp, nb->nb_tp.sz);
00969     NicWrite(nb->nb_ap.vp, nb->nb_ap.sz);
00970 
00971     
00972 
00973 
00974     for (i = 0; i < padding; i++)
00975         NICOUTB(NIC_IOPORT, 0);
00976 
00977     
00978 
00979 
00980     NicCompleteDma();
00981 
00982     
00983 
00984 
00985     NICOUTB(NIC_PG0_TBCR0, (sz & 0xff));
00986     NICOUTB(NIC_PG0_TBCR1, ((sz >> 8) & 0xff));
00987 
00988     
00989 
00990 
00991     NICOUTB(NIC_PG0_TPSR, NIC_FIRST_TX_PAGE);
00992 
00993     
00994 
00995 
00996     NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_TXP | NIC_CR_RD2);
00997 
00998     sbi(EIMSK, RTL_SIGNAL_IRQ);
00999 
01000     return 0;
01001 }
01002 
01013 static NETBUF *NicGetPacket(void)
01014 {
01015     NETBUF *nb = 0;
01016     struct nic_pkt_header hdr;
01017     uint16_t count;
01018     uint8_t *buf;
01019     uint8_t nextpg;
01020     uint8_t bnry;
01021     uint8_t curr;
01022     uint16_t i;
01023     uint8_t drop = 0;
01024 
01025     
01026     cbi(EIMSK, RTL_SIGNAL_IRQ);
01027     
01028 
01029 
01030 
01031     NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD2 | NIC_CR_PS0);
01032     Delay16Cycles();
01033     curr = NICINB(NIC_PG1_CURR);
01034     NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
01035 
01036     
01037 
01038 
01039 
01040 
01041 
01042     if ((bnry = NICINB(NIC_PG0_BNRY) + 1) >= NIC_STOP_PAGE)
01043         bnry = NIC_FIRST_RX_PAGE;
01044 
01045     if (bnry == curr) {
01046         sbi(EIMSK, RTL_SIGNAL_IRQ);
01047         return 0;
01048     }
01049 
01050     
01051 
01052 
01053     NICOUTB(NIC_PG0_RBCR0, sizeof(struct nic_pkt_header));
01054     NICOUTB(NIC_PG0_RBCR1, 0);
01055     NICOUTB(NIC_PG0_RSAR0, 0);
01056     NICOUTB(NIC_PG0_RSAR1, bnry);
01057     buf = (uint8_t *) & hdr;
01058     NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD0);
01059     Delay16Cycles();
01060     for (i = 0; i < sizeof(struct nic_pkt_header); i++)
01061         *buf++ = NICINB(NIC_IOPORT);
01062     NicCompleteDma();
01063 
01064     
01065 
01066 
01067     if (hdr.ph_size < 60 + sizeof(struct nic_pkt_header) ||     
01068         hdr.ph_size > 1514 + sizeof(struct nic_pkt_header)) {
01069         drop = 1;
01070     }
01071 
01072     
01073 
01074 
01075 
01076     nextpg = bnry + (hdr.ph_size >> 8) + ((hdr.ph_size & 0xFF) != 0);
01077     if (nextpg >= NIC_STOP_PAGE) {
01078         nextpg -= NIC_STOP_PAGE;
01079         nextpg += NIC_FIRST_RX_PAGE;
01080     }
01081     if (nextpg != hdr.ph_nextpg) {
01082         uint8_t nextpg1 = nextpg + 1;
01083         if (nextpg1 >= NIC_STOP_PAGE) {
01084             nextpg1 -= NIC_STOP_PAGE;
01085             nextpg1 += NIC_FIRST_RX_PAGE;
01086         }
01087         if (nextpg1 != hdr.ph_nextpg) {
01088             sbi(EIMSK, RTL_SIGNAL_IRQ);
01089             return (NETBUF *) 0xFFFF;
01090         }
01091         nextpg = nextpg1;
01092     }
01093 
01094     
01095 
01096 
01097 
01098     if (!drop && ((hdr.ph_status & 0x0E) == 0)) {
01099         
01100 
01101 
01102 
01103         count = hdr.ph_size - 4;
01104         if ((nb = NutNetBufAlloc(0, NBAF_DATALINK, count))) {
01105             
01106 
01107 
01108 
01109 
01110             NICOUTB(NIC_PG0_RBCR0, count);
01111             NICOUTB(NIC_PG0_RBCR1, count >> 8);
01112             NICOUTB(NIC_PG0_RSAR0, sizeof(struct nic_pkt_header));
01113             NICOUTB(NIC_PG0_RSAR1, bnry);
01114 
01115             
01116 
01117 
01118             NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD0);
01119             Delay16Cycles();
01120             NicRead(nb->nb_dl.vp, count);
01121             NicCompleteDma();
01122         }
01123     }
01124 
01125     
01126 
01127 
01128 
01129     if (--nextpg < NIC_FIRST_RX_PAGE)
01130         nextpg = NIC_STOP_PAGE - 1;
01131     NICOUTB(NIC_PG0_BNRY, nextpg);
01132 
01133     sbi(EIMSK, RTL_SIGNAL_IRQ);
01134     return nb;
01135 }
01136 
01137 
01138 
01139 
01140 
01141 
01142 
01143 
01144 
01145 
01146 
01147 
01148 
01149 
01150 
01151 
01152 
01153 
01154 
01155 static uint8_t NicOverflow(void)
01156 {
01157     uint8_t cr;
01158     uint8_t resend = 0;
01159     uint8_t curr;
01160 
01161     
01162 
01163 
01164 
01165 
01166     while (NICINB(NIC_CR) & NIC_CR_TXP);
01167     cr = NICINB(NIC_CR);
01168 
01169     
01170 
01171 
01172 
01173     NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0);
01174     curr = NICINB(NIC_PG1_CURR);
01175     NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2);
01176 
01177     
01178     NICOUTB(NIC_PG0_RBCR0, 0);
01179     NICOUTB(NIC_PG0_RBCR1, 0);
01180 
01181     
01182     if ((cr & NIC_CR_TXP) && ((NICINB(NIC_PG0_ISR) & (NIC_ISR_PTX | NIC_ISR_TXE)) == 0)) {
01183         resend = 1;
01184     }
01185 
01186     
01187     NICOUTB(NIC_PG0_TCR, NIC_TCR_LB0);
01188     NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
01189 
01190     
01191 
01192 
01193 
01194     if (--curr < NIC_FIRST_RX_PAGE) {
01195         curr = NIC_STOP_PAGE - 1;
01196     }
01197     NICOUTB(NIC_PG0_BNRY, curr);
01198 
01199     
01200     NICOUTB(NIC_PG0_TCR, 0);
01201 
01202     
01203     if (resend) {
01204         NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_TXP | NIC_CR_RD2);
01205     }
01206 
01207     
01208     NICOUTB(NIC_PG0_ISR, NIC_ISR_OVW);
01209     return resend;
01210 }
01211 
01212 
01213 
01214 
01215 
01216 static void NicInterrupt(void *arg)
01217 {
01218     uint8_t isr;
01219     NICINFO *ni = (NICINFO *) ((NUTDEVICE *) arg)->dev_dcb;
01220 
01221     ni->ni_interrupts++;
01222 
01223 #ifdef RTL_IRQ_RISING_EDGE
01224     do
01225     {
01226 #endif 
01227     isr = NICINB(NIC_PG0_ISR);
01228     NICOUTB(NIC_PG0_ISR, isr);
01229 
01230     
01231 
01232 
01233 
01234 
01235     if (isr & NIC_ISR_OVW) {
01236         
01237 
01238 #if !defined(__AVR__)
01239         cbi(EIMSK, RTL_SIGNAL_IRQ);
01240         sei();
01241 #endif
01242         NicOverflow();
01243 #if !defined(__AVR__)
01244         cli();
01245         sbi(EIMSK, RTL_SIGNAL_IRQ);
01246 #endif
01247         ni->ni_rx_overruns++;
01248     } else {
01249         
01250 
01251 
01252 
01253 
01254         if (isr & NIC_ISR_TXE)
01255             ni->ni_tx_errors++;
01256 
01257         
01258 
01259 
01260 
01261         if (isr & NIC_ISR_PRX)
01262             NutEventPostFromIrq(&ni->ni_rx_rdy);
01263 
01264         if (isr & NIC_ISR_RXE) {
01265             ni->ni_rx_frame_errors += NICINB(NIC_PG0_CNTR0);
01266             ni->ni_rx_crc_errors += NICINB(NIC_PG0_CNTR1);
01267             ni->ni_rx_missed_errors += NICINB(NIC_PG0_CNTR2);
01268         }
01269     }
01270 #ifdef RTL_IRQ_RISING_EDGE
01271     
01272 
01273 
01274 
01275 
01276     }
01277     while (bit_is_set(PINE, RTL_SIGNAL_IRQ));
01278 #endif
01279 }
01280 
01287 THREAD(NicRx, arg)
01288 {
01289     NUTDEVICE *dev;
01290     IFNET *ifn;
01291     NICINFO *ni;
01292     NETBUF *nb;
01293 
01294     dev = arg;
01295     ifn = (IFNET *) dev->dev_icb;
01296     ni = (NICINFO *) dev->dev_dcb;
01297 
01298     NutThreadSetPriority(9);
01299     
01300 
01301 
01302 
01303 
01304     if ((ifn->if_mac[0] & ifn->if_mac[1] & ifn->if_mac[2]) == 0xFF) {
01305         while ((ifn->if_mac[0] & ifn->if_mac[1] & ifn->if_mac[2]) == 0xFF)
01306             NutSleep(125);
01307         cbi(EIMSK, RTL_SIGNAL_IRQ);
01308         NicStart(ifn->if_mac);
01309         sbi(EIMSK, RTL_SIGNAL_IRQ);
01310     }
01311 
01312     while (1) {
01313         NutEventWait(&ni->ni_rx_rdy, 0);
01314         
01315 
01316 
01317 
01318         do {
01319             nb = NicGetPacket();
01320 
01321             
01322 
01323             if ((uint16_t) nb == 0xFFFF) {
01324                 NicStart(ifn->if_mac);
01325                 ni->ni_rx_size_errors++;
01326             } else if (nb) {
01327                 ni->ni_rx_packets++;
01328                 (*ifn->if_recv) (dev, nb);
01329             }
01330         } while (nb);
01331     }
01332 }
01333 
01344 int NicOutput(NUTDEVICE * dev, NETBUF * nb)
01345 {
01346     int rc = -1;
01347     NICINFO *ni = (NICINFO *) dev->dev_dcb;
01348 
01349     if (NicPutPacket(nb) == 0) {
01350         ni->ni_tx_packets++;
01351         rc = 0;
01352     }
01353     return rc;
01354 }
01355 
01376 int NicInit(NUTDEVICE * dev)
01377 {
01378     IFNET *ifn;
01379     NICINFO *ni;
01380 
01381     
01382 
01383 
01384 
01385     if (confnet.cd_size == 0)
01386         NutNetLoadConfig(dev->dev_name);
01387 
01388     ifn = dev->dev_icb;
01389     memcpy(ifn->if_mac, confnet.cdn_mac, 6);
01390     ni = (NICINFO *) dev->dev_dcb;
01391     memset(ni, 0, sizeof(NICINFO));
01392 
01393     
01394 
01395 
01396     NutThreadCreate("rxi5", NicRx, dev, 
01397         (NUT_THREAD_NICRXSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
01398     NutSleep(WAIT500);
01399 
01400     
01401 
01402 
01403     if (NutRegisterIrqHandler(&RTL_SIGNAL, NicInterrupt, dev))
01404         return -1;
01405 
01406     cbi(EIMSK, RTL_SIGNAL_IRQ);
01407 #ifdef RTL_IRQ_RISING_EDGE
01408     
01409     RTL_RISING_EDGE_MODE();
01410 #endif
01411 
01412     if (ifn->if_mac[0] | ifn->if_mac[1] | ifn->if_mac[2])
01413         if (NicStart(ifn->if_mac))
01414             return -1;
01415 
01416     sbi(EIMSK, RTL_SIGNAL_IRQ);
01417 
01418     return 0;
01419 }
01420 
01421