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 <string.h>
00118
00119 #include <sys/atom.h>
00120 #include <sys/heap.h>
00121 #include <sys/thread.h>
00122 #include <sys/event.h>
00123 #include <sys/timer.h>
00124 #include <sys/confnet.h>
00125
00126 #include <netinet/if_ether.h>
00127 #include <net/ether.h>
00128 #include <net/if_var.h>
00129
00130 #include <dev/irqreg.h>
00131 #include <dev/lanc111.h>
00132
00133 #ifdef NUTDEBUG
00134 #include <stdio.h>
00135 #endif
00136
00137
00138
00139
00140 #ifndef LANC111_BASE_ADDR
00141 #define LANC111_BASE_ADDR 0xC000
00142 #endif
00143
00144 #ifndef LANC111_SIGNAL_IRQ
00145 #define LANC111_SIGNAL_IRQ INT5
00146 #endif
00147
00148 #ifdef LANC111_RESET_BIT
00149
00150 #if (LANC111_RESET_AVRPORT == AVRPORTB)
00151 #define LANC111_RESET_PORT PORTB
00152 #define LANC111_RESET_DDR DDRB
00153
00154 #elif (LANC111_RESET_AVRPORT == AVRPORTD)
00155 #define LANC111_RESET_PORT PORTD
00156 #define LANC111_RESET_DDR DDRD
00157
00158 #elif (LANC111_RESET_AVRPORT == AVRPORTE)
00159 #define LANC111_RESET_PORT PORTE
00160 #define LANC111_RESET_DDR DDRE
00161
00162 #elif (LANC111_RESET_AVRPORT == AVRPORTF)
00163 #define LANC111_RESET_PORT PORTF
00164 #define LANC111_RESET_DDR DDRF
00165
00166 #endif
00167
00168 #endif
00169
00170
00171
00172
00173 #if (LANC111_SIGNAL_IRQ == INT0)
00174 #define LANC111_SIGNAL sig_INTERRUPT0
00175 #define LANC111_SIGNAL_MODE() sbi(EICRA, ISC00); sbi(EICRA, ISC01)
00176
00177 #elif (LANC111_SIGNAL_IRQ == INT1)
00178 #define LANC111_SIGNAL sig_INTERRUPT1
00179 #define LANC111_SIGNAL_MODE() sbi(EICRA, ISC10); sbi(EICRA, ISC11)
00180
00181 #elif (LANC111_SIGNAL_IRQ == INT2)
00182 #define LANC111_SIGNAL sig_INTERRUPT2
00183 #define LANC111_SIGNAL_MODE() sbi(EICRA, ISC20); sbi(EICRA, ISC21)
00184
00185 #elif (LANC111_SIGNAL_IRQ == INT3)
00186 #define LANC111_SIGNAL sig_INTERRUPT3
00187 #define LANC111_SIGNAL_MODE() sbi(EICRA, ISC30); sbi(EICRA, ISC31)
00188
00189 #elif (LANC111_SIGNAL_IRQ == INT4)
00190 #define LANC111_SIGNAL sig_INTERRUPT4
00191 #define LANC111_SIGNAL_MODE() sbi(EICR, ISC40); sbi(EICR, ISC41)
00192
00193 #elif (LANC111_SIGNAL_IRQ == INT6)
00194 #define LANC111_SIGNAL sig_INTERRUPT6
00195 #define LANC111_SIGNAL_MODE() sbi(EICR, ISC60); sbi(EICR, ISC61)
00196
00197 #elif (LANC111_SIGNAL_IRQ == INT7)
00198 #define LANC111_SIGNAL sig_INTERRUPT7
00199 #define LANC111_SIGNAL_MODE() sbi(EICR, ISC70); sbi(EICR, ISC71)
00200
00201 #else
00202 #define LANC111_SIGNAL sig_INTERRUPT5
00203 #define LANC111_SIGNAL_MODE() sbi(EICR, ISC50); sbi(EICR, ISC51)
00204
00205 #endif
00206
00211
00215 #define NIC_BSR (LANC111_BASE_ADDR + 0x0E)
00216
00220 #define NIC_TCR (LANC111_BASE_ADDR + 0x00)
00221
00222 #define TCR_SWFDUP 0x8000
00223 #define TCR_EPH_LOOP 0x2000
00224 #define TCR_STP_SQET 0x1000
00225 #define TCR_FDUPLX 0x0800
00226 #define TCR_MON_CSN 0x0400
00227 #define TCR_NOCRC 0x0100
00228 #define TCR_PAD_EN 0x0080
00229 #define TCR_FORCOL 0x0004
00230 #define TCR_LOOP 0x0002
00231 #define TCR_TXENA 0x0001
00237 #define NIC_EPHSR (LANC111_BASE_ADDR + 0x02)
00238
00242 #define NIC_RCR (LANC111_BASE_ADDR + 0x04)
00243
00244 #define RCR_SOFT_RST 0x8000
00245 #define RCR_FILT_CAR 0x4000
00246 #define RCR_ABORT_ENB 0x2000
00247 #define RCR_STRIP_CRC 0x0200
00248 #define RCR_RXEN 0x0100
00249 #define RCR_ALMUL 0x0004
00250 #define RCR_PRMS 0x0002
00251 #define RCR_RX_ABORT 0x0001
00256 #define NIC_ECR (LANC111_BASE_ADDR + 0x06)
00257
00261 #define NIC_MIR (LANC111_BASE_ADDR + 0x08)
00262
00266 #define NIC_RPCR (LANC111_BASE_ADDR + 0x0A)
00267
00268 #define RPCR_SPEED 0x2000
00269 #define RPCR_DPLX 0x1000
00270 #define RPCR_ANEG 0x0800
00271 #define RPCR_LEDA_PAT 0x0000
00272 #define RPCR_LEDB_PAT 0x0010
00277 #define NIC_CR (LANC111_BASE_ADDR + 0x00)
00278
00279 #define CR_EPH_EN 0x8000
00284 #define NIC_BAR (LANC111_BASE_ADDR + 0x02)
00285
00289 #define NIC_IAR (LANC111_BASE_ADDR + 0x04)
00290
00294 #define NIC_GPR (LANC111_BASE_ADDR + 0x0A)
00295
00299 #define NIC_CTR (LANC111_BASE_ADDR + 0x0C)
00300
00301 #define CTR_RCV_BAD 0x4000
00302 #define CTR_AUTO_RELEASE 0x0800
00307 #define NIC_MMUCR (LANC111_BASE_ADDR + 0x00)
00308
00309 #define MMUCR_BUSY 0x0001
00310
00311 #define MMU_NOP 0
00312 #define MMU_ALO (1<<5)
00313 #define MMU_RST (2<<5)
00314 #define MMU_REM (3<<5)
00315 #define MMU_TOP (4<<5)
00316 #define MMU_PKT (5<<5)
00317 #define MMU_ENQ (6<<5)
00318 #define MMU_RTX (7<<5)
00319
00325 #define NIC_PNR (LANC111_BASE_ADDR + 0x02)
00326
00332 #define NIC_ARR (LANC111_BASE_ADDR + 0x03)
00333
00334 #define ARR_FAILED 0x80
00335
00339 #define NIC_FIFO (LANC111_BASE_ADDR + 0x04)
00340
00344 #define NIC_PTR (LANC111_BASE_ADDR + 0x06)
00345
00346 #define PTR_RCV 0x8000
00347 #define PTR_AUTO_INCR 0x4000
00348 #define PTR_READ 0x2000
00349 #define PTR_ETEN 0x1000
00350 #define PTR_NOT_EMPTY 0x0800
00355 #define NIC_DATA (LANC111_BASE_ADDR + 0x08)
00356
00360 #define NIC_IST (LANC111_BASE_ADDR + 0x0C)
00361
00365 #define NIC_ACK (LANC111_BASE_ADDR + 0x0C)
00366
00370 #define NIC_MSK (LANC111_BASE_ADDR + 0x0D)
00371
00372 #define INT_MD 0x80
00373 #define INT_ERCV 0x40
00374 #define INT_EPH 0x20
00375 #define INT_RX_OVRN 0x10
00376 #define INT_ALLOC 0x08
00377 #define INT_TX_EMPTY 0x04
00378 #define INT_TX 0x02
00379 #define INT_RCV 0x01
00384 #define NIC_MT (LANC111_BASE_ADDR + 0x00)
00385
00389 #define NIC_MGMT (LANC111_BASE_ADDR + 0x08)
00390
00391 #define MGMT_MDOE 0x08
00392 #define MGMT_MCLK 0x04
00393 #define MGMT_MDI 0x02
00394 #define MGMT_MDO 0x01
00399 #define NIC_REV (LANC111_BASE_ADDR + 0x0A)
00400
00404 #define NIC_ERCV (LANC111_BASE_ADDR + 0x0C)
00405
00409 #define NIC_PHYCR 0
00410
00411 #define PHYCR_RST 0x8000
00412 #define PHYCR_LPBK 0x4000
00413 #define PHYCR_SPEED 0x2000
00414 #define PHYCR_ANEG_EN 0x1000
00415 #define PHYCR_PDN 0x0800
00416 #define PHYCR_MII_DIS 0x0400
00417 #define PHYCR_ANEG_RST 0x0200
00418 #define PHYCR_DPLX 0x0100
00419 #define PHYCR_COLST 0x0080
00425 #define NIC_PHYSR 1
00426
00427 #define PHYSR_CAP_T4 0x8000
00428 #define PHYSR_CAP_TXF 0x4000
00429 #define PHYSR_CAP_TXH 0x2000
00430 #define PHYSR_CAP_TF 0x1000
00431 #define PHYSR_CAP_TH 0x0800
00432 #define PHYSR_CAP_SUPR 0x0040
00433 #define PHYSR_ANEG_ACK 0x0020
00434 #define PHYSR_REM_FLT 0x0010
00435 #define PHYSR_CAP_ANEG 0x0008
00436 #define PHYSR_LINK 0x0004
00437 #define PHYSR_JAB 0x0002
00438 #define PHYSR_EXREG 0x0001
00444 #define NIC_PHYID1 2
00445
00449 #define NIC_PHYID2 3
00450
00454 #define NIC_PHYANAD 4
00455
00456 #define PHYANAD_NP 0x8000
00457 #define PHYANAD_ACK 0x4000
00458 #define PHYANAD_RF 0x2000
00459 #define PHYANAD_T4 0x0200
00460 #define PHYANAD_TX_FDX 0x0100
00461 #define PHYANAD_TX_HDX 0x0080
00462 #define PHYANAD_10FDX 0x0040
00463 #define PHYANAD_10_HDX 0x0020
00464 #define PHYANAD_CSMA 0x0001
00469 #define NIC_PHYANRC 5
00470
00474 #define NIC_PHYCFR1 16
00475
00479 #define NIC_PHYCFR2 17
00480
00484 #define NIC_PHYSOR 18
00485
00486 #define PHYSOR_INT 0x8000
00487 #define PHYSOR_LNKFAIL 0x4000
00488 #define PHYSOR_LOSSSYNC 0x2000
00489 #define PHYSOR_CWRD 0x1000
00490 #define PHYSOR_SSD 0x0800
00491 #define PHYSOR_ESD 0x0400
00492 #define PHYSOR_RPOL 0x0200
00493 #define PHYSOR_JAB 0x0100
00494 #define PHYSOR_SPDDET 0x0080
00495 #define PHYSOR_DPLXDET 0x0040
00500 #define NIC_PHYMSK 19
00501
00502 #define PHYMSK_MINT 0x8000
00503 #define PHYMSK_MLNKFAIL 0x4000
00504 #define PHYMSK_MLOSSSYN 0x2000
00505 #define PHYMSK_MCWRD 0x1000
00506 #define PHYMSK_MSSD 0x0800
00507 #define PHYMSK_MESD 0x0400
00508 #define PHYMSK_MRPOL 0x0200
00509 #define PHYMSK_MJAB 0x0100
00510 #define PHYMSK_MSPDDT 0x0080
00511 #define PHYMSK_MDPLDT 0x0040
00515 #define MSBV(bit) (1 << ((bit) - 8))
00516
00517 #define nic_outlb(addr, val) (*(volatile uint8_t *)(addr) = (val))
00518 #define nic_outhb(addr, val) (*(volatile uint8_t *)((addr) + 1) = (val))
00519 #define nic_outwx(addr, val) (*(volatile uint16_t *)(addr) = (val))
00520 #define nic_outw(addr, val) { \
00521 *(volatile uint8_t *)(addr) = (uint8_t)(val); \
00522 *((volatile uint8_t *)(addr) + 1) = (uint8_t)((val) >> 8); \
00523 }
00524
00525 #define nic_inlb(addr) (*(volatile uint8_t *)(addr))
00526 #define nic_inhb(addr) (*(volatile uint8_t *)((addr) + 1))
00527 #define nic_inw(addr) (*(volatile uint16_t *)(addr))
00528
00529 #define nic_bs(bank) nic_outlb(NIC_BSR, bank)
00530
00535 struct _NICINFO {
00536 HANDLE volatile ni_rx_rdy;
00537 uint16_t ni_tx_cnt;
00538 uint32_t ni_rx_packets;
00539 uint32_t ni_tx_packets;
00540 uint32_t ni_interrupts;
00541 uint32_t ni_overruns;
00542 uint32_t ni_rx_frame_errors;
00543 uint32_t ni_rx_crc_errors;
00544 uint32_t ni_rx_missed_errors;
00545 };
00546
00550 typedef struct _NICINFO NICINFO;
00551
00558
00559
00560 static HANDLE mutex;
00561 static HANDLE maq;
00562
00573 static uint8_t NicPhyRegSelect(uint8_t reg, uint8_t we)
00574 {
00575 uint8_t rs;
00576 uint8_t msk;
00577 uint8_t i;
00578
00579 nic_bs(3);
00580 rs = (nic_inlb(NIC_MGMT) & ~(MGMT_MCLK | MGMT_MDO)) | MGMT_MDOE;
00581
00582
00583 for (i = 0; i < 33; i++) {
00584 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00585 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00586 }
00587
00588
00589 nic_outlb(NIC_MGMT, rs);
00590 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00591 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00592 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00593
00594
00595 if (we) {
00596 nic_outlb(NIC_MGMT, rs);
00597 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00598 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00599 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00600 } else {
00601 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00602 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00603 nic_outlb(NIC_MGMT, rs);
00604 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00605 }
00606
00607
00608 for (i = 0; i < 5; i++) {
00609 nic_outlb(NIC_MGMT, rs);
00610 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00611 }
00612
00613
00614 for (msk = 0x10; msk; msk >>= 1) {
00615 if (reg & msk) {
00616 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00617 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00618 } else {
00619 nic_outlb(NIC_MGMT, rs);
00620 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00621 }
00622 }
00623 nic_outlb(NIC_MGMT, rs);
00624
00625 return rs;
00626 }
00627
00637 static uint16_t NicPhyRead(uint8_t reg)
00638 {
00639 uint16_t rc = 0;
00640 uint8_t rs;
00641 uint8_t i;
00642
00643
00644 rs = NicPhyRegSelect(reg, 0);
00645
00646
00647 rs &= ~MGMT_MDOE;
00648 nic_outlb(NIC_MGMT, rs);
00649 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00650
00651
00652 for (i = 0; i < 16; i++) {
00653 nic_outlb(NIC_MGMT, rs);
00654 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00655 rc <<= 1;
00656 rc |= (nic_inlb(NIC_MGMT) & MGMT_MDI) != 0;
00657 }
00658
00659
00660 nic_outlb(NIC_MGMT, rs);
00661
00662 return rc;
00663 }
00664
00673 static void NicPhyWrite(uint8_t reg, uint16_t val)
00674 {
00675 uint16_t msk;
00676 uint8_t rs;
00677
00678
00679 rs = NicPhyRegSelect(reg, 1);
00680
00681
00682 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00683 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00684 nic_outlb(NIC_MGMT, rs);
00685 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00686
00687
00688 for (msk = 0x8000; msk; msk >>= 1) {
00689 if (val & msk) {
00690 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00691 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00692 } else {
00693 nic_outlb(NIC_MGMT, rs);
00694 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00695 }
00696 }
00697
00698
00699 nic_outlb(NIC_MGMT, rs & ~MGMT_MDOE);
00700 }
00701
00707 static int NicPhyConfig(void)
00708 {
00709 uint16_t phy_sor;
00710 uint16_t phy_sr;
00711 uint16_t phy_to;
00712 uint16_t mode;
00713
00714
00715
00716
00717
00718
00719
00720 NicPhyWrite(NIC_PHYCR, PHYCR_RST);
00721 for (phy_to = 0;; phy_to++) {
00722 NutSleep(63);
00723 if ((NicPhyRead(NIC_PHYCR) & PHYCR_RST) == 0)
00724 break;
00725 if (phy_to > 3)
00726 return -1;
00727 }
00728
00729
00730
00731 phy_sor = NicPhyRead(NIC_PHYSOR);
00732
00733
00734 NicPhyWrite(NIC_PHYMSK, PHYMSK_MLOSSSYN | PHYMSK_MCWRD | PHYMSK_MSSD |
00735 PHYMSK_MESD | PHYMSK_MRPOL | PHYMSK_MJAB | PHYMSK_MSPDDT | PHYMSK_MDPLDT);
00736
00737
00738 mode = RPCR_ANEG | RPCR_LEDA_PAT | RPCR_LEDB_PAT;
00739 nic_bs(0);
00740 nic_outw(NIC_RPCR, mode);
00741
00742 #ifdef NIC_FIXED
00743
00744 phy_sr = NicPhyRead(NIC_PHYCFR1);
00745 NicPhyWrite(NIC_PHYCFR1, phy_sr | 0x8000);
00746 NutSleep(63);
00747
00748
00749 NicPhyWrite(NIC_PHYCR, NIC_FIXED);
00750 nic_bs(0);
00751 nic_outw(NIC_RPCR, mode);
00752
00753
00754 phy_sr = NicPhyRead(NIC_PHYCFR1);
00755 NicPhyWrite(NIC_PHYCFR1, phy_sr & ~0x8000);
00756 phy_sr = NicPhyRead(NIC_PHYCFR1);
00757
00758 #else
00759
00760
00761
00762
00763
00764 NicPhyWrite(NIC_PHYANAD, PHYANAD_TX_FDX | PHYANAD_TX_HDX | PHYANAD_10FDX | PHYANAD_10_HDX | PHYANAD_CSMA);
00765 NutSleep(63);
00766 for (phy_to = 0, phy_sr = 0;; phy_to++) {
00767
00768 if (phy_to >= 1024)
00769 return -1;
00770
00771 if ((phy_to & 127) == 0 ) {
00772 NicPhyWrite(NIC_PHYCR, PHYCR_ANEG_EN | PHYCR_ANEG_RST);
00773
00774 NutSleep(63);
00775 }
00776
00777 phy_sr = NicPhyRead(NIC_PHYSR);
00778
00779 if (phy_sr & PHYSR_ANEG_ACK)
00780 break;
00781 NutSleep(63);
00782 }
00783
00784 #endif
00785
00786 return 0;
00787 }
00788
00799 static INLINE int NicMmuWait(uint16_t tmo)
00800 {
00801 while (tmo--) {
00802 if ((nic_inlb(NIC_MMUCR) & MMUCR_BUSY) == 0)
00803 break;
00804 NutDelay(1);
00805 }
00806 return tmo ? 0 : -1;
00807 }
00808
00814 static int NicReset(void)
00815 {
00816 #ifdef LANC111_RESET_BIT
00817 sbi(LANC111_RESET_DDR, LANC111_RESET_BIT);
00818 sbi(LANC111_RESET_PORT, LANC111_RESET_BIT);
00819 NutDelay(WAIT100);
00820 cbi(LANC111_RESET_PORT, LANC111_RESET_BIT);
00821 NutDelay(WAIT250);
00822 NutDelay(WAIT250);
00823 #endif
00824
00825
00826 nic_outlb(NIC_MSK, 0);
00827
00828
00829 nic_bs(0);
00830 nic_outw(NIC_RCR, RCR_SOFT_RST);
00831
00832
00833 nic_bs(1);
00834 nic_outw(NIC_CR, CR_EPH_EN);
00835
00836 NutDelay(10);
00837
00838
00839 nic_bs(0);
00840 nic_outw(NIC_RCR, 0);
00841 nic_outw(NIC_TCR, 0);
00842
00843
00844 nic_bs(1);
00845 nic_outw(NIC_CTR, CTR_AUTO_RELEASE);
00846
00847
00848 nic_bs(2);
00849 nic_outlb(NIC_MMUCR, MMU_RST);
00850 if (NicMmuWait(1000))
00851 return -1;
00852
00853 return 0;
00854 }
00855
00856
00857
00858
00859
00860
00861
00862
00863 static int NicStart(CONST uint8_t * mac)
00864 {
00865 uint8_t i;
00866
00867 if (NicReset())
00868 return -1;
00869
00870
00871 nic_bs(3);
00872 nic_outlb(NIC_ERCV, 7);
00873 nic_bs(0);
00874 nic_outw(NIC_RCR, RCR_RXEN);
00875
00876
00877 nic_outw(NIC_TCR, TCR_PAD_EN | TCR_TXENA);
00878
00879
00880 if (NicPhyConfig())
00881 return -1;
00882
00883
00884
00885 nic_bs(1);
00886 for (i = 0; i < 6; i++)
00887 nic_outlb(NIC_IAR + i, mac[i]);
00888
00889
00890
00891 nic_bs(2);
00892 nic_outlb(NIC_MSK, INT_ERCV | INT_RCV | INT_RX_OVRN);
00893
00894 return 0;
00895 }
00896
00897
00898
00899
00900 static void NicInterrupt(void *arg)
00901 {
00902 uint8_t isr;
00903 uint8_t imr;
00904 NICINFO *ni = (NICINFO *) ((NUTDEVICE *) arg)->dev_dcb;
00905
00906 ni->ni_interrupts++;
00907
00908
00909 nic_bs(2);
00910 imr = nic_inlb(NIC_MSK);
00911 nic_outlb(NIC_MSK, 0);
00912
00913
00914 isr = nic_inlb(NIC_IST);
00915
00916 isr &= imr;
00917
00918
00919
00920
00921
00922
00923 if (isr & INT_TX_EMPTY) {
00924 nic_outlb(NIC_ACK, INT_TX_EMPTY);
00925 imr &= ~INT_TX_EMPTY;
00926 }
00927
00928 else if (isr & INT_TX) {
00929
00930 nic_bs(0);
00931 nic_outw(NIC_TCR, nic_inlb(NIC_TCR) | TCR_TXENA);
00932 nic_bs(2);
00933 nic_outlb(NIC_ACK, INT_TX);
00934
00935 nic_outlb(NIC_MMUCR, MMU_PKT);
00936 }
00937
00938
00939
00940
00941
00942
00943 if (isr & INT_RX_OVRN) {
00944 nic_outlb(NIC_ACK, INT_RX_OVRN);
00945
00946 NutEventPostFromIrq(&ni->ni_rx_rdy);
00947 }
00948 if (isr & INT_ERCV) {
00949 nic_outlb(NIC_ACK, INT_ERCV);
00950 NutEventPostFromIrq(&ni->ni_rx_rdy);
00951 }
00952 if (isr & INT_RCV) {
00953 nic_outlb(NIC_ACK, INT_RCV);
00954 imr &= ~INT_RCV;
00955 NutEventPostFromIrq(&ni->ni_rx_rdy);
00956 }
00957
00958 if (isr & INT_ALLOC) {
00959 imr &= ~INT_ALLOC;
00960 NutEventPostFromIrq(&maq);
00961 }
00962
00963 nic_outlb(NIC_MSK, imr);
00964 }
00965
00966
00967
00968
00969 static void NicWrite(uint8_t * buf, uint16_t len)
00970 {
00971 register uint16_t l = len - 1;
00972 register uint8_t ih = (uint16_t) l >> 8;
00973 register uint8_t il = (uint8_t) l;
00974
00975 if (!len)
00976 return;
00977
00978 do {
00979 do {
00980 nic_outlb(NIC_DATA, *buf++);
00981 } while (il-- != 0);
00982 } while (ih-- != 0);
00983 }
00984
00985
00986
00987
00988 static void NicRead(uint8_t * buf, uint16_t len)
00989 {
00990 register uint16_t l = len - 1;
00991 register uint8_t ih = (uint16_t) l >> 8;
00992 register uint8_t il = (uint8_t) l;
00993
00994 if (!len)
00995 return;
00996
00997 do {
00998 do {
00999 *buf++ = nic_inlb(NIC_DATA);
01000 } while (il-- != 0);
01001 } while (ih-- != 0);
01002 }
01003
01014 static NETBUF *NicGetPacket(void)
01015 {
01016 NETBUF *nb = 0;
01017
01018 uint16_t fsw;
01019 uint16_t fbc;
01020
01021
01022
01023 nic_bs(2);
01024 if (nic_inw(NIC_FIFO) & 0x8000) {
01025 return 0;
01026 }
01027
01028
01029 nic_outw(NIC_PTR, PTR_READ | PTR_RCV | PTR_AUTO_INCR);
01030 _NOP();
01031 _NOP();
01032 _NOP();
01033 _NOP();
01034
01035
01036 fsw = nic_inw(NIC_DATA);
01037 fbc = nic_inw(NIC_DATA);
01038
01039
01040
01041 if (fsw & 0xAC00) {
01042 nb = (NETBUF *) 0xFFFF;
01043 }
01044
01045 else if (fbc < 66 || fbc > 1524) {
01046 nb = (NETBUF *) 0xFFFF;
01047 }
01048
01049 else {
01050
01051
01052
01053
01054 fbc -= 3;
01055 nb = NutNetBufAlloc(0, NBAF_DATALINK, fbc);
01056
01057
01058 if (nb)
01059 NicRead(nb->nb_dl.vp, fbc);
01060 }
01061
01062
01063 nic_outlb(NIC_MMUCR, MMU_TOP);
01064
01065 return nb;
01066 }
01067
01082 static int NicPutPacket(NETBUF * nb)
01083 {
01084 uint16_t sz;
01085 uint8_t odd = 0;
01086 uint8_t imsk;
01087
01088
01089
01090
01091
01092
01093
01094
01095 if ((sz = nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz) > ETHERMTU)
01096 return -1;
01097
01098
01099 imsk = nic_inlb(NIC_MSK);
01100 nic_outlb(NIC_MSK, 0);
01101
01102
01103 nic_bs(2);
01104 nic_outlb(NIC_MMUCR, MMU_ALO);
01105 if (NicMmuWait(100))
01106 return -1;
01107
01108
01109 nic_outlb(NIC_MSK, imsk | INT_ALLOC);
01110
01111
01112 sz += nb->nb_dl.sz;
01113 sz += 6;
01114 if (sz & 1) {
01115 sz++;
01116 odd++;
01117 }
01118
01119
01120 while ((nic_inlb(NIC_IST) & INT_ALLOC) == 0) {
01121 if (NutEventWait(&maq, 125)) {
01122 nic_outlb(NIC_MMUCR, MMU_RST);
01123 NicMmuWait(1000);
01124 nic_outlb(NIC_MMUCR, MMU_ALO);
01125 if (NicMmuWait(100) || (nic_inlb(NIC_IST) & INT_ALLOC) == 0) {
01126 if (NutEventWait(&maq, 125)) {
01127 return -1;
01128 }
01129 }
01130 }
01131 }
01132
01133
01134 imsk = nic_inlb(NIC_MSK);
01135 nic_outlb(NIC_MSK, 0);
01136
01137
01138 nic_outlb(NIC_PNR, nic_inhb(NIC_PNR));
01139
01140 nic_outw(NIC_PTR, 0x4000);
01141
01142
01143 nic_outlb(NIC_DATA, 0);
01144 nic_outlb(NIC_DATA, 0);
01145
01146
01147 nic_outw(NIC_DATA, sz);
01148
01149
01150 NicWrite(nb->nb_dl.vp, nb->nb_dl.sz);
01151 NicWrite(nb->nb_nw.vp, nb->nb_nw.sz);
01152 NicWrite(nb->nb_tp.vp, nb->nb_tp.sz);
01153 NicWrite(nb->nb_ap.vp, nb->nb_ap.sz);
01154
01155 if (odd)
01156 nic_outlb(NIC_DATA, 0);
01157
01158
01159 nic_outw(NIC_DATA, 0);
01160
01161
01162 if (NicMmuWait(100))
01163 return -1;
01164 nic_outlb(NIC_MMUCR, MMU_ENQ);
01165
01166
01167 imsk |= INT_TX | INT_TX_EMPTY;
01168 nic_outlb(NIC_MSK, imsk);
01169
01170 return 0;
01171 }
01172
01173
01178 THREAD(NicRxLanc, arg)
01179 {
01180 NUTDEVICE *dev;
01181 IFNET *ifn;
01182 NICINFO *ni;
01183 NETBUF *nb;
01184 uint8_t imsk;
01185
01186 dev = arg;
01187 ifn = (IFNET *) dev->dev_icb;
01188 ni = (NICINFO *) dev->dev_dcb;
01189
01190
01191
01192
01193
01194
01195 for (;;) {
01196 if (*((uint32_t *) (ifn->if_mac)) && *((uint32_t *) (ifn->if_mac)) != 0xFFFFFFFFUL) {
01197 break;
01198 }
01199 NutSleep(63);
01200 }
01201
01202
01203
01204
01205
01206
01207
01208 while(NicStart(ifn->if_mac)) {
01209 NutSleep(1000);
01210 }
01211
01212 LANC111_SIGNAL_MODE();
01213 sbi(EIMSK, LANC111_SIGNAL_IRQ);
01214
01215 NutEventPost(&mutex);
01216
01217
01218 NutThreadSetPriority(9);
01219
01220 for (;;) {
01221
01222
01223
01224
01225
01226 NutEventWait(&ni->ni_rx_rdy, 2000);
01227
01228
01229
01230
01231
01232 imsk = nic_inlb(NIC_MSK);
01233 nic_outlb(NIC_MSK, 0);
01234 while ((nb = NicGetPacket()) != 0) {
01235 if (nb != (NETBUF *) 0xFFFF) {
01236 ni->ni_rx_packets++;
01237 (*ifn->if_recv) (dev, nb);
01238 }
01239 }
01240 nic_outlb(NIC_MSK, imsk | INT_RCV | INT_ERCV);
01241 }
01242 }
01243
01254 int LancOutput(NUTDEVICE * dev, NETBUF * nb)
01255 {
01256 static uint32_t mx_wait = 5000;
01257 int rc = -1;
01258 NICINFO *ni;
01259
01260
01261
01262
01263
01264 if (NutEventWait(&mutex, mx_wait) == 0) {
01265 ni = (NICINFO *) dev->dev_dcb;
01266
01267 if (NicPutPacket(nb) == 0) {
01268 ni->ni_tx_packets++;
01269 rc = 0;
01270
01271
01272 mx_wait = 5000;
01273 }
01274 NutEventPost(&mutex);
01275 }
01276
01277
01278
01279
01280 else {
01281 mx_wait = 500;
01282 }
01283 return rc;
01284 }
01285
01303 int LancInit(NUTDEVICE * dev)
01304 {
01305
01306 cbi(EIMSK, LANC111_SIGNAL_IRQ);
01307 memset(dev->dev_dcb, 0, sizeof(NICINFO));
01308
01309
01310 if (NutRegisterIrqHandler(&LANC111_SIGNAL, NicInterrupt, dev))
01311 return -1;
01312
01313
01314
01315
01316
01317
01318 NutThreadCreate("rxi5", NicRxLanc, dev, (128 * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
01319
01320
01321
01322 return 0;
01323 }
01324
01325 static NICINFO dcb_eth0;
01326
01332 static IFNET ifn_eth0 = {
01333 IFT_ETHER,
01334 0,
01335 {0, 0, 0, 0, 0, 0},
01336 0,
01337 0,
01338 0,
01339 ETHERMTU,
01340 0,
01341 0,
01342 0,
01343 NutEtherInput,
01344 LancOutput,
01345 NutEtherOutput
01346 };
01347
01357 NUTDEVICE devSmsc111 = {
01358 0,
01359 {'e', 't', 'h', '0', 0, 0, 0, 0, 0},
01360 IFTYP_NET,
01361 0,
01362 0,
01363 &ifn_eth0,
01364 &dcb_eth0,
01365 LancInit,
01366 0,
01367 0,
01368 0,
01369 0,
01370 0,
01371 0,
01372 0
01373 };
01374