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