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 #ifndef NUT_THREAD_LANCRXSTACK
00138 #if defined(__GNUC__)
00139
00140 #define NUT_THREAD_LANCRXSTACK 128
00141 #else
00142
00143 #define NUT_THREAD_LANCRXSTACK 384
00144 #endif
00145 #endif
00146
00147
00148
00149
00150 #ifndef LANC111_BASE_ADDR
00151 #define LANC111_BASE_ADDR 0xC000
00152 #endif
00153
00154 #ifndef LANC111_SIGNAL_IRQ
00155 #define LANC111_SIGNAL_IRQ INT5
00156 #endif
00157
00158 #ifdef LANC111_RESET_BIT
00159
00160 #if (LANC111_RESET_AVRPORT == AVRPORTB)
00161 #define LANC111_RESET_PORT PORTB
00162 #define LANC111_RESET_DDR DDRB
00163
00164 #elif (LANC111_RESET_AVRPORT == AVRPORTD)
00165 #define LANC111_RESET_PORT PORTD
00166 #define LANC111_RESET_DDR DDRD
00167
00168 #elif (LANC111_RESET_AVRPORT == AVRPORTE)
00169 #define LANC111_RESET_PORT PORTE
00170 #define LANC111_RESET_DDR DDRE
00171
00172 #elif (LANC111_RESET_AVRPORT == AVRPORTF)
00173 #define LANC111_RESET_PORT PORTF
00174 #define LANC111_RESET_DDR DDRF
00175
00176 #endif
00177
00178 #endif
00179
00180
00181
00182
00183 #if (LANC111_SIGNAL_IRQ == INT0)
00184 #define LANC111_SIGNAL sig_INTERRUPT0
00185 #define LANC111_SIGNAL_MODE() sbi(EICRA, ISC00); sbi(EICRA, ISC01)
00186
00187 #elif (LANC111_SIGNAL_IRQ == INT1)
00188 #define LANC111_SIGNAL sig_INTERRUPT1
00189 #define LANC111_SIGNAL_MODE() sbi(EICRA, ISC10); sbi(EICRA, ISC11)
00190
00191 #elif (LANC111_SIGNAL_IRQ == INT2)
00192 #define LANC111_SIGNAL sig_INTERRUPT2
00193 #define LANC111_SIGNAL_MODE() sbi(EICRA, ISC20); sbi(EICRA, ISC21)
00194
00195 #elif (LANC111_SIGNAL_IRQ == INT3)
00196 #define LANC111_SIGNAL sig_INTERRUPT3
00197 #define LANC111_SIGNAL_MODE() sbi(EICRA, ISC30); sbi(EICRA, ISC31)
00198
00199 #elif (LANC111_SIGNAL_IRQ == INT4)
00200 #define LANC111_SIGNAL sig_INTERRUPT4
00201 #define LANC111_SIGNAL_MODE() sbi(EICR, ISC40); sbi(EICR, ISC41)
00202
00203 #elif (LANC111_SIGNAL_IRQ == INT6)
00204 #define LANC111_SIGNAL sig_INTERRUPT6
00205 #define LANC111_SIGNAL_MODE() sbi(EICR, ISC60); sbi(EICR, ISC61)
00206
00207 #elif (LANC111_SIGNAL_IRQ == INT7)
00208 #define LANC111_SIGNAL sig_INTERRUPT7
00209 #define LANC111_SIGNAL_MODE() sbi(EICR, ISC70); sbi(EICR, ISC71)
00210
00211 #else
00212 #define LANC111_SIGNAL sig_INTERRUPT5
00213 #define LANC111_SIGNAL_MODE() sbi(EICR, ISC50); sbi(EICR, ISC51)
00214
00215 #endif
00216
00221
00225 #define NIC_BSR (LANC111_BASE_ADDR + 0x0E)
00226
00230 #define NIC_TCR (LANC111_BASE_ADDR + 0x00)
00231
00232 #define TCR_SWFDUP 0x8000
00233 #define TCR_EPH_LOOP 0x2000
00234 #define TCR_STP_SQET 0x1000
00235 #define TCR_FDUPLX 0x0800
00236 #define TCR_MON_CSN 0x0400
00237 #define TCR_NOCRC 0x0100
00238 #define TCR_PAD_EN 0x0080
00239 #define TCR_FORCOL 0x0004
00240 #define TCR_LOOP 0x0002
00241 #define TCR_TXENA 0x0001
00247 #define NIC_EPHSR (LANC111_BASE_ADDR + 0x02)
00248
00252 #define NIC_RCR (LANC111_BASE_ADDR + 0x04)
00253
00254 #define RCR_SOFT_RST 0x8000
00255 #define RCR_FILT_CAR 0x4000
00256 #define RCR_ABORT_ENB 0x2000
00257 #define RCR_STRIP_CRC 0x0200
00258 #define RCR_RXEN 0x0100
00259 #define RCR_ALMUL 0x0004
00260 #define RCR_PRMS 0x0002
00261 #define RCR_RX_ABORT 0x0001
00266 #define NIC_ECR (LANC111_BASE_ADDR + 0x06)
00267
00271 #define NIC_MIR (LANC111_BASE_ADDR + 0x08)
00272
00276 #define NIC_RPCR (LANC111_BASE_ADDR + 0x0A)
00277
00278 #define RPCR_SPEED 0x2000
00279 #define RPCR_DPLX 0x1000
00280 #define RPCR_ANEG 0x0800
00281 #define RPCR_LEDA_PAT 0x0000
00282 #define RPCR_LEDB_PAT 0x0010
00287 #define NIC_CR (LANC111_BASE_ADDR + 0x00)
00288
00289 #define CR_EPH_EN 0x8000
00294 #define NIC_BAR (LANC111_BASE_ADDR + 0x02)
00295
00299 #define NIC_IAR (LANC111_BASE_ADDR + 0x04)
00300
00304 #define NIC_GPR (LANC111_BASE_ADDR + 0x0A)
00305
00309 #define NIC_CTR (LANC111_BASE_ADDR + 0x0C)
00310
00311 #define CTR_RCV_BAD 0x4000
00312 #define CTR_AUTO_RELEASE 0x0800
00317 #define NIC_MMUCR (LANC111_BASE_ADDR + 0x00)
00318
00319 #define MMUCR_BUSY 0x0001
00320
00321 #define MMU_NOP 0
00322 #define MMU_ALO (1<<5)
00323 #define MMU_RST (2<<5)
00324 #define MMU_REM (3<<5)
00325 #define MMU_TOP (4<<5)
00326 #define MMU_PKT (5<<5)
00327 #define MMU_ENQ (6<<5)
00328 #define MMU_RTX (7<<5)
00329
00335 #define NIC_PNR (LANC111_BASE_ADDR + 0x02)
00336
00342 #define NIC_ARR (LANC111_BASE_ADDR + 0x03)
00343
00344 #define ARR_FAILED 0x80
00345
00349 #define NIC_FIFO (LANC111_BASE_ADDR + 0x04)
00350
00354 #define NIC_PTR (LANC111_BASE_ADDR + 0x06)
00355
00356 #define PTR_RCV 0x8000
00357 #define PTR_AUTO_INCR 0x4000
00358 #define PTR_READ 0x2000
00359 #define PTR_ETEN 0x1000
00360 #define PTR_NOT_EMPTY 0x0800
00365 #define NIC_DATA (LANC111_BASE_ADDR + 0x08)
00366
00370 #define NIC_IST (LANC111_BASE_ADDR + 0x0C)
00371
00375 #define NIC_ACK (LANC111_BASE_ADDR + 0x0C)
00376
00380 #define NIC_MSK (LANC111_BASE_ADDR + 0x0D)
00381
00382 #define INT_MD 0x80
00383 #define INT_ERCV 0x40
00384 #define INT_EPH 0x20
00385 #define INT_RX_OVRN 0x10
00386 #define INT_ALLOC 0x08
00387 #define INT_TX_EMPTY 0x04
00388 #define INT_TX 0x02
00389 #define INT_RCV 0x01
00394 #define NIC_MT (LANC111_BASE_ADDR + 0x00)
00395
00399 #define NIC_MGMT (LANC111_BASE_ADDR + 0x08)
00400
00401 #define MGMT_MDOE 0x08
00402 #define MGMT_MCLK 0x04
00403 #define MGMT_MDI 0x02
00404 #define MGMT_MDO 0x01
00409 #define NIC_REV (LANC111_BASE_ADDR + 0x0A)
00410
00414 #define NIC_ERCV (LANC111_BASE_ADDR + 0x0C)
00415
00419 #define NIC_PHYCR 0
00420
00421 #define PHYCR_RST 0x8000
00422 #define PHYCR_LPBK 0x4000
00423 #define PHYCR_SPEED 0x2000
00424 #define PHYCR_ANEG_EN 0x1000
00425 #define PHYCR_PDN 0x0800
00426 #define PHYCR_MII_DIS 0x0400
00427 #define PHYCR_ANEG_RST 0x0200
00428 #define PHYCR_DPLX 0x0100
00429 #define PHYCR_COLST 0x0080
00435 #define NIC_PHYSR 1
00436
00437 #define PHYSR_CAP_T4 0x8000
00438 #define PHYSR_CAP_TXF 0x4000
00439 #define PHYSR_CAP_TXH 0x2000
00440 #define PHYSR_CAP_TF 0x1000
00441 #define PHYSR_CAP_TH 0x0800
00442 #define PHYSR_CAP_SUPR 0x0040
00443 #define PHYSR_ANEG_ACK 0x0020
00444 #define PHYSR_REM_FLT 0x0010
00445 #define PHYSR_CAP_ANEG 0x0008
00446 #define PHYSR_LINK 0x0004
00447 #define PHYSR_JAB 0x0002
00448 #define PHYSR_EXREG 0x0001
00454 #define NIC_PHYID1 2
00455
00459 #define NIC_PHYID2 3
00460
00464 #define NIC_PHYANAD 4
00465
00466 #define PHYANAD_NP 0x8000
00467 #define PHYANAD_ACK 0x4000
00468 #define PHYANAD_RF 0x2000
00469 #define PHYANAD_T4 0x0200
00470 #define PHYANAD_TX_FDX 0x0100
00471 #define PHYANAD_TX_HDX 0x0080
00472 #define PHYANAD_10FDX 0x0040
00473 #define PHYANAD_10_HDX 0x0020
00474 #define PHYANAD_CSMA 0x0001
00479 #define NIC_PHYANRC 5
00480
00484 #define NIC_PHYCFR1 16
00485
00489 #define NIC_PHYCFR2 17
00490
00494 #define NIC_PHYSOR 18
00495
00496 #define PHYSOR_INT 0x8000
00497 #define PHYSOR_LNKFAIL 0x4000
00498 #define PHYSOR_LOSSSYNC 0x2000
00499 #define PHYSOR_CWRD 0x1000
00500 #define PHYSOR_SSD 0x0800
00501 #define PHYSOR_ESD 0x0400
00502 #define PHYSOR_RPOL 0x0200
00503 #define PHYSOR_JAB 0x0100
00504 #define PHYSOR_SPDDET 0x0080
00505 #define PHYSOR_DPLXDET 0x0040
00510 #define NIC_PHYMSK 19
00511
00512 #define PHYMSK_MINT 0x8000
00513 #define PHYMSK_MLNKFAIL 0x4000
00514 #define PHYMSK_MLOSSSYN 0x2000
00515 #define PHYMSK_MCWRD 0x1000
00516 #define PHYMSK_MSSD 0x0800
00517 #define PHYMSK_MESD 0x0400
00518 #define PHYMSK_MRPOL 0x0200
00519 #define PHYMSK_MJAB 0x0100
00520 #define PHYMSK_MSPDDT 0x0080
00521 #define PHYMSK_MDPLDT 0x0040
00525 #define MSBV(bit) (1 << ((bit) - 8))
00526
00527 #define nic_outlb(addr, val) (*(volatile uint8_t *)(addr) = (val))
00528 #define nic_outhb(addr, val) (*(volatile uint8_t *)((addr) + 1) = (val))
00529 #define nic_outwx(addr, val) (*(volatile uint16_t *)(addr) = (val))
00530 #define nic_outw(addr, val) { \
00531 *(volatile uint8_t *)(addr) = (uint8_t)(val); \
00532 *((volatile uint8_t *)(addr) + 1) = (uint8_t)((val) >> 8); \
00533 }
00534
00535 #define nic_inlb(addr) (*(volatile uint8_t *)(addr))
00536 #define nic_inhb(addr) (*(volatile uint8_t *)((addr) + 1))
00537 #define nic_inw(addr) (*(volatile uint16_t *)(addr))
00538
00539 #define nic_bs(bank) nic_outlb(NIC_BSR, bank)
00540
00545 struct _NICINFO {
00546 HANDLE volatile ni_rx_rdy;
00547 uint16_t ni_tx_cnt;
00548 uint32_t ni_rx_packets;
00549 uint32_t ni_tx_packets;
00550 uint32_t ni_interrupts;
00551 uint32_t ni_overruns;
00552 uint32_t ni_rx_frame_errors;
00553 uint32_t ni_rx_crc_errors;
00554 uint32_t ni_rx_missed_errors;
00555 };
00556
00560 typedef struct _NICINFO NICINFO;
00561
00568
00569
00570 static HANDLE mutex;
00571 static HANDLE maq;
00572
00583 static uint8_t NicPhyRegSelect(uint8_t reg, uint8_t we)
00584 {
00585 uint8_t rs;
00586 uint8_t msk;
00587 uint8_t i;
00588
00589 nic_bs(3);
00590 rs = (nic_inlb(NIC_MGMT) & ~(MGMT_MCLK | MGMT_MDO)) | MGMT_MDOE;
00591
00592
00593 for (i = 0; i < 33; i++) {
00594 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00595 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00596 }
00597
00598
00599 nic_outlb(NIC_MGMT, rs);
00600 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00601 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00602 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00603
00604
00605 if (we) {
00606 nic_outlb(NIC_MGMT, rs);
00607 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00608 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00609 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00610 } else {
00611 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00612 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00613 nic_outlb(NIC_MGMT, rs);
00614 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00615 }
00616
00617
00618 for (i = 0; i < 5; i++) {
00619 nic_outlb(NIC_MGMT, rs);
00620 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00621 }
00622
00623
00624 for (msk = 0x10; msk; msk >>= 1) {
00625 if (reg & msk) {
00626 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00627 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00628 } else {
00629 nic_outlb(NIC_MGMT, rs);
00630 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00631 }
00632 }
00633 nic_outlb(NIC_MGMT, rs);
00634
00635 return rs;
00636 }
00637
00647 static uint16_t NicPhyRead(uint8_t reg)
00648 {
00649 uint16_t rc = 0;
00650 uint8_t rs;
00651 uint8_t i;
00652
00653
00654 rs = NicPhyRegSelect(reg, 0);
00655
00656
00657 rs &= ~MGMT_MDOE;
00658 nic_outlb(NIC_MGMT, rs);
00659 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00660
00661
00662 for (i = 0; i < 16; i++) {
00663 nic_outlb(NIC_MGMT, rs);
00664 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00665 rc <<= 1;
00666 rc |= (nic_inlb(NIC_MGMT) & MGMT_MDI) != 0;
00667 }
00668
00669
00670 nic_outlb(NIC_MGMT, rs);
00671
00672 return rc;
00673 }
00674
00683 static void NicPhyWrite(uint8_t reg, uint16_t val)
00684 {
00685 uint16_t msk;
00686 uint8_t rs;
00687
00688
00689 rs = NicPhyRegSelect(reg, 1);
00690
00691
00692 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00693 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00694 nic_outlb(NIC_MGMT, rs);
00695 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00696
00697
00698 for (msk = 0x8000; msk; msk >>= 1) {
00699 if (val & msk) {
00700 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00701 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00702 } else {
00703 nic_outlb(NIC_MGMT, rs);
00704 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00705 }
00706 }
00707
00708
00709 nic_outlb(NIC_MGMT, rs & ~MGMT_MDOE);
00710 }
00711
00717 static int NicPhyConfig(void)
00718 {
00719 uint16_t phy_sor;
00720 uint16_t phy_sr;
00721 uint16_t phy_to;
00722 uint16_t mode;
00723
00724
00725
00726
00727
00728
00729
00730 NicPhyWrite(NIC_PHYCR, PHYCR_RST);
00731 for (phy_to = 0;; phy_to++) {
00732 NutSleep(63);
00733 if ((NicPhyRead(NIC_PHYCR) & PHYCR_RST) == 0)
00734 break;
00735 if (phy_to > 3)
00736 return -1;
00737 }
00738
00739
00740
00741 phy_sor = NicPhyRead(NIC_PHYSOR);
00742
00743
00744 NicPhyWrite(NIC_PHYMSK, PHYMSK_MLOSSSYN | PHYMSK_MCWRD | PHYMSK_MSSD |
00745 PHYMSK_MESD | PHYMSK_MRPOL | PHYMSK_MJAB | PHYMSK_MSPDDT | PHYMSK_MDPLDT);
00746
00747
00748 mode = RPCR_ANEG | RPCR_LEDA_PAT | RPCR_LEDB_PAT;
00749 nic_bs(0);
00750 nic_outw(NIC_RPCR, mode);
00751
00752 #ifdef NIC_FIXED
00753
00754 phy_sr = NicPhyRead(NIC_PHYCFR1);
00755 NicPhyWrite(NIC_PHYCFR1, phy_sr | 0x8000);
00756 NutSleep(63);
00757
00758
00759 NicPhyWrite(NIC_PHYCR, NIC_FIXED);
00760 nic_bs(0);
00761 nic_outw(NIC_RPCR, mode);
00762
00763
00764 phy_sr = NicPhyRead(NIC_PHYCFR1);
00765 NicPhyWrite(NIC_PHYCFR1, phy_sr & ~0x8000);
00766 phy_sr = NicPhyRead(NIC_PHYCFR1);
00767
00768 #else
00769
00770
00771
00772
00773
00774 NicPhyWrite(NIC_PHYANAD, PHYANAD_TX_FDX | PHYANAD_TX_HDX | PHYANAD_10FDX | PHYANAD_10_HDX | PHYANAD_CSMA);
00775 NutSleep(63);
00776 for (phy_to = 0, phy_sr = 0;; phy_to++) {
00777
00778 if (phy_to >= 1024)
00779 return -1;
00780
00781 if ((phy_to & 127) == 0 ) {
00782 NicPhyWrite(NIC_PHYCR, PHYCR_ANEG_EN | PHYCR_ANEG_RST);
00783
00784 NutSleep(63);
00785 }
00786
00787 phy_sr = NicPhyRead(NIC_PHYSR);
00788
00789 if (phy_sr & PHYSR_ANEG_ACK)
00790 break;
00791 NutSleep(63);
00792 }
00793
00794 #endif
00795
00796 return 0;
00797 }
00798
00809 static INLINE int NicMmuWait(uint16_t tmo)
00810 {
00811 while (tmo--) {
00812 if ((nic_inlb(NIC_MMUCR) & MMUCR_BUSY) == 0)
00813 break;
00814 NutDelay(1);
00815 }
00816 return tmo ? 0 : -1;
00817 }
00818
00824 static int NicReset(void)
00825 {
00826 #ifdef LANC111_RESET_BIT
00827 sbi(LANC111_RESET_DDR, LANC111_RESET_BIT);
00828 sbi(LANC111_RESET_PORT, LANC111_RESET_BIT);
00829 NutDelay(WAIT100);
00830 cbi(LANC111_RESET_PORT, LANC111_RESET_BIT);
00831 NutDelay(WAIT250);
00832 NutDelay(WAIT250);
00833 #endif
00834
00835
00836 nic_outlb(NIC_MSK, 0);
00837
00838
00839 nic_bs(0);
00840 nic_outw(NIC_RCR, RCR_SOFT_RST);
00841
00842
00843 nic_bs(1);
00844 nic_outw(NIC_CR, CR_EPH_EN);
00845
00846 NutDelay(10);
00847
00848
00849 nic_bs(0);
00850 nic_outw(NIC_RCR, 0);
00851 nic_outw(NIC_TCR, 0);
00852
00853
00854 nic_bs(1);
00855 nic_outw(NIC_CTR, CTR_AUTO_RELEASE);
00856
00857
00858 nic_bs(2);
00859 nic_outlb(NIC_MMUCR, MMU_RST);
00860 if (NicMmuWait(1000))
00861 return -1;
00862
00863 return 0;
00864 }
00865
00866
00867
00868
00869
00870
00871
00872
00873 static int NicStart(CONST uint8_t * mac)
00874 {
00875 uint8_t i;
00876
00877 if (NicReset())
00878 return -1;
00879
00880
00881 nic_bs(3);
00882 nic_outlb(NIC_ERCV, 7);
00883 nic_bs(0);
00884 nic_outw(NIC_RCR, RCR_RXEN);
00885
00886
00887 nic_outw(NIC_TCR, TCR_PAD_EN | TCR_TXENA);
00888
00889
00890 if (NicPhyConfig())
00891 return -1;
00892
00893
00894
00895 nic_bs(1);
00896 for (i = 0; i < 6; i++)
00897 nic_outlb(NIC_IAR + i, mac[i]);
00898
00899
00900
00901 nic_bs(2);
00902 nic_outlb(NIC_MSK, INT_ERCV | INT_RCV | INT_RX_OVRN);
00903
00904 return 0;
00905 }
00906
00907
00908
00909
00910 static void NicInterrupt(void *arg)
00911 {
00912 uint8_t isr;
00913 uint8_t imr;
00914 NICINFO *ni = (NICINFO *) ((NUTDEVICE *) arg)->dev_dcb;
00915
00916 ni->ni_interrupts++;
00917
00918
00919 nic_bs(2);
00920 imr = nic_inlb(NIC_MSK);
00921 nic_outlb(NIC_MSK, 0);
00922
00923
00924 isr = nic_inlb(NIC_IST);
00925
00926 isr &= imr;
00927
00928
00929
00930
00931
00932
00933 if (isr & INT_TX_EMPTY) {
00934 nic_outlb(NIC_ACK, INT_TX_EMPTY);
00935 imr &= ~INT_TX_EMPTY;
00936 }
00937
00938 else if (isr & INT_TX) {
00939
00940 nic_bs(0);
00941 nic_outw(NIC_TCR, nic_inlb(NIC_TCR) | TCR_TXENA);
00942 nic_bs(2);
00943 nic_outlb(NIC_ACK, INT_TX);
00944
00945 nic_outlb(NIC_MMUCR, MMU_PKT);
00946 }
00947
00948
00949
00950
00951
00952
00953 if (isr & INT_RX_OVRN) {
00954 nic_outlb(NIC_ACK, INT_RX_OVRN);
00955
00956 NutEventPostFromIrq(&ni->ni_rx_rdy);
00957 }
00958 if (isr & INT_ERCV) {
00959 nic_outlb(NIC_ACK, INT_ERCV);
00960 NutEventPostFromIrq(&ni->ni_rx_rdy);
00961 }
00962 if (isr & INT_RCV) {
00963 nic_outlb(NIC_ACK, INT_RCV);
00964 imr &= ~INT_RCV;
00965 NutEventPostFromIrq(&ni->ni_rx_rdy);
00966 }
00967
00968 if (isr & INT_ALLOC) {
00969 imr &= ~INT_ALLOC;
00970 NutEventPostFromIrq(&maq);
00971 }
00972
00973 nic_outlb(NIC_MSK, imr);
00974 }
00975
00976
00977
00978
00979 static void NicWrite(uint8_t * buf, uint16_t len)
00980 {
00981 register uint16_t l = len - 1;
00982 register uint8_t ih = (uint16_t) l >> 8;
00983 register uint8_t il = (uint8_t) l;
00984
00985 if (!len)
00986 return;
00987
00988 do {
00989 do {
00990 nic_outlb(NIC_DATA, *buf++);
00991 } while (il-- != 0);
00992 } while (ih-- != 0);
00993 }
00994
00995
00996
00997
00998 static void NicRead(uint8_t * buf, uint16_t len)
00999 {
01000 register uint16_t l = len - 1;
01001 register uint8_t ih = (uint16_t) l >> 8;
01002 register uint8_t il = (uint8_t) l;
01003
01004 if (!len)
01005 return;
01006
01007 do {
01008 do {
01009 *buf++ = nic_inlb(NIC_DATA);
01010 } while (il-- != 0);
01011 } while (ih-- != 0);
01012 }
01013
01024 static NETBUF *NicGetPacket(void)
01025 {
01026 NETBUF *nb = 0;
01027
01028 uint16_t fsw;
01029 uint16_t fbc;
01030
01031
01032
01033 nic_bs(2);
01034 if (nic_inw(NIC_FIFO) & 0x8000) {
01035 return 0;
01036 }
01037
01038
01039 nic_outw(NIC_PTR, PTR_READ | PTR_RCV | PTR_AUTO_INCR);
01040 _NOP();
01041 _NOP();
01042 _NOP();
01043 _NOP();
01044
01045
01046 fsw = nic_inw(NIC_DATA);
01047 fbc = nic_inw(NIC_DATA);
01048
01049
01050
01051 if (fsw & 0xAC00) {
01052 nb = (NETBUF *) 0xFFFF;
01053 }
01054
01055 else if (fbc < 66 || fbc > 1524) {
01056 nb = (NETBUF *) 0xFFFF;
01057 }
01058
01059 else {
01060
01061
01062
01063
01064 fbc -= 3;
01065 nb = NutNetBufAlloc(0, NBAF_DATALINK, fbc);
01066
01067
01068 if (nb)
01069 NicRead(nb->nb_dl.vp, fbc);
01070 }
01071
01072
01073 nic_outlb(NIC_MMUCR, MMU_TOP);
01074
01075 return nb;
01076 }
01077
01092 static int NicPutPacket(NETBUF * nb)
01093 {
01094 uint16_t sz;
01095 uint8_t odd = 0;
01096 uint8_t imsk;
01097
01098
01099
01100
01101
01102
01103
01104
01105 if ((sz = nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz) > ETHERMTU)
01106 return -1;
01107
01108
01109 imsk = nic_inlb(NIC_MSK);
01110 nic_outlb(NIC_MSK, 0);
01111
01112
01113 nic_bs(2);
01114 nic_outlb(NIC_MMUCR, MMU_ALO);
01115 if (NicMmuWait(100))
01116 return -1;
01117
01118
01119 nic_outlb(NIC_MSK, imsk | INT_ALLOC);
01120
01121
01122 sz += nb->nb_dl.sz;
01123 sz += 6;
01124 if (sz & 1) {
01125 sz++;
01126 odd++;
01127 }
01128
01129
01130 while ((nic_inlb(NIC_IST) & INT_ALLOC) == 0) {
01131 if (NutEventWait(&maq, 125)) {
01132 nic_outlb(NIC_MMUCR, MMU_RST);
01133 NicMmuWait(1000);
01134 nic_outlb(NIC_MMUCR, MMU_ALO);
01135 if (NicMmuWait(100) || (nic_inlb(NIC_IST) & INT_ALLOC) == 0) {
01136 if (NutEventWait(&maq, 125)) {
01137 return -1;
01138 }
01139 }
01140 }
01141 }
01142
01143
01144 imsk = nic_inlb(NIC_MSK);
01145 nic_outlb(NIC_MSK, 0);
01146
01147
01148 nic_outlb(NIC_PNR, nic_inhb(NIC_PNR));
01149
01150 nic_outw(NIC_PTR, 0x4000);
01151
01152
01153 nic_outlb(NIC_DATA, 0);
01154 nic_outlb(NIC_DATA, 0);
01155
01156
01157 nic_outw(NIC_DATA, sz);
01158
01159
01160 NicWrite(nb->nb_dl.vp, nb->nb_dl.sz);
01161 NicWrite(nb->nb_nw.vp, nb->nb_nw.sz);
01162 NicWrite(nb->nb_tp.vp, nb->nb_tp.sz);
01163 NicWrite(nb->nb_ap.vp, nb->nb_ap.sz);
01164
01165 if (odd)
01166 nic_outlb(NIC_DATA, 0);
01167
01168
01169 nic_outw(NIC_DATA, 0);
01170
01171
01172 if (NicMmuWait(100))
01173 return -1;
01174 nic_outlb(NIC_MMUCR, MMU_ENQ);
01175
01176
01177 imsk |= INT_TX | INT_TX_EMPTY;
01178 nic_outlb(NIC_MSK, imsk);
01179
01180 return 0;
01181 }
01182
01183
01188 THREAD(NicRxLanc, arg)
01189 {
01190 NUTDEVICE *dev;
01191 IFNET *ifn;
01192 NICINFO *ni;
01193 NETBUF *nb;
01194 uint8_t imsk;
01195
01196 dev = arg;
01197 ifn = (IFNET *) dev->dev_icb;
01198 ni = (NICINFO *) dev->dev_dcb;
01199
01200
01201
01202
01203
01204
01205 for (;;) {
01206 if (*((uint32_t *) (ifn->if_mac)) && *((uint32_t *) (ifn->if_mac)) != 0xFFFFFFFFUL) {
01207 break;
01208 }
01209 NutSleep(63);
01210 }
01211
01212
01213
01214
01215
01216
01217
01218 while(NicStart(ifn->if_mac)) {
01219 NutSleep(1000);
01220 }
01221
01222 LANC111_SIGNAL_MODE();
01223 sbi(EIMSK, LANC111_SIGNAL_IRQ);
01224
01225 NutEventPost(&mutex);
01226
01227
01228 NutThreadSetPriority(9);
01229
01230 for (;;) {
01231
01232
01233
01234
01235
01236 NutEventWait(&ni->ni_rx_rdy, 2000);
01237
01238
01239
01240
01241
01242 imsk = nic_inlb(NIC_MSK);
01243 nic_outlb(NIC_MSK, 0);
01244 while ((nb = NicGetPacket()) != 0) {
01245 if (nb != (NETBUF *) 0xFFFF) {
01246 ni->ni_rx_packets++;
01247 (*ifn->if_recv) (dev, nb);
01248 }
01249 }
01250 nic_outlb(NIC_MSK, imsk | INT_RCV | INT_ERCV);
01251 }
01252 }
01253
01264 int LancOutput(NUTDEVICE * dev, NETBUF * nb)
01265 {
01266 static uint32_t mx_wait = 5000;
01267 int rc = -1;
01268 NICINFO *ni;
01269
01270
01271
01272
01273
01274 if (NutEventWait(&mutex, mx_wait) == 0) {
01275 ni = (NICINFO *) dev->dev_dcb;
01276
01277 if (NicPutPacket(nb) == 0) {
01278 ni->ni_tx_packets++;
01279 rc = 0;
01280
01281
01282 mx_wait = 5000;
01283 }
01284 NutEventPost(&mutex);
01285 }
01286
01287
01288
01289
01290 else {
01291 mx_wait = 500;
01292 }
01293 return rc;
01294 }
01295
01313 int LancInit(NUTDEVICE * dev)
01314 {
01315
01316 cbi(EIMSK, LANC111_SIGNAL_IRQ);
01317 memset(dev->dev_dcb, 0, sizeof(NICINFO));
01318
01319
01320 if (NutRegisterIrqHandler(&LANC111_SIGNAL, NicInterrupt, dev))
01321 return -1;
01322
01323
01324
01325
01326
01327
01328 NutThreadCreate("rxi5", NicRxLanc, dev, (NUT_THREAD_LANCRXSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
01329
01330
01331
01332 return 0;
01333 }
01334
01335 static NICINFO dcb_eth0;
01336
01342 static IFNET ifn_eth0 = {
01343 IFT_ETHER,
01344 0,
01345 {0, 0, 0, 0, 0, 0},
01346 0,
01347 0,
01348 0,
01349 ETHERMTU,
01350 0,
01351 0,
01352 0,
01353 NutEtherInput,
01354 LancOutput,
01355 NutEtherOutput
01356 };
01357
01367 NUTDEVICE devSmsc111 = {
01368 0,
01369 {'e', 't', 'h', '0', 0, 0, 0, 0, 0},
01370 IFTYP_NET,
01371 0,
01372 0,
01373 &ifn_eth0,
01374 &dcb_eth0,
01375 LancInit,
01376 0,
01377 0,
01378 0,
01379 0,
01380 0,
01381 0,
01382 0
01383 };
01384