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