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 <sys/atom.h>
00118 #include <sys/heap.h>
00119 #include <sys/thread.h>
00120 #include <sys/event.h>
00121 #include <sys/timer.h>
00122 #include <sys/confnet.h>
00123
00124 #include <netinet/if_ether.h>
00125 #include <net/ether.h>
00126 #include <net/if_var.h>
00127
00128 #include <dev/irqreg.h>
00129 #include <dev/lanc111.h>
00130
00131 #include <stdlib.h>
00132 #include <string.h>
00133
00134 #ifdef NUTDEBUG
00135 #include <stdio.h>
00136 #endif
00137
00138 #ifndef NUT_THREAD_LANCRXSTACK
00139 #if defined(__GNUC__)
00140
00141
00142 #define NUT_THREAD_LANCRXSTACK 256
00143 #else
00144
00145 #define NUT_THREAD_LANCRXSTACK 384
00146 #endif
00147 #endif
00148
00149
00150
00151
00152 #ifndef LANC111_BASE_ADDR
00153 #define LANC111_BASE_ADDR 0xC000
00154 #endif
00155
00156 #ifndef LANC111_SIGNAL_IRQ
00157 #define LANC111_SIGNAL_IRQ INT5
00158 #endif
00159
00160 #ifdef LANC111_RESET_BIT
00161
00162 #if (LANC111_RESET_AVRPORT == AVRPORTB)
00163 #define LANC111_RESET_PORT PORTB
00164 #define LANC111_RESET_DDR DDRB
00165
00166 #elif (LANC111_RESET_AVRPORT == AVRPORTD)
00167 #define LANC111_RESET_PORT PORTD
00168 #define LANC111_RESET_DDR DDRD
00169
00170 #elif (LANC111_RESET_AVRPORT == AVRPORTE)
00171 #define LANC111_RESET_PORT PORTE
00172 #define LANC111_RESET_DDR DDRE
00173
00174 #elif (LANC111_RESET_AVRPORT == AVRPORTF)
00175 #define LANC111_RESET_PORT PORTF
00176 #define LANC111_RESET_DDR DDRF
00177
00178 #endif
00179
00180 #endif
00181
00182
00183
00184
00185 #if (LANC111_SIGNAL_IRQ == INT0)
00186 #define LANC111_SIGNAL sig_INTERRUPT0
00187 #define LANC111_SIGNAL_MODE() sbi(EICRA, ISC00); sbi(EICRA, ISC01)
00188
00189 #elif (LANC111_SIGNAL_IRQ == INT1)
00190 #define LANC111_SIGNAL sig_INTERRUPT1
00191 #define LANC111_SIGNAL_MODE() sbi(EICRA, ISC10); sbi(EICRA, ISC11)
00192
00193 #elif (LANC111_SIGNAL_IRQ == INT2)
00194 #define LANC111_SIGNAL sig_INTERRUPT2
00195 #define LANC111_SIGNAL_MODE() sbi(EICRA, ISC20); sbi(EICRA, ISC21)
00196
00197 #elif (LANC111_SIGNAL_IRQ == INT3)
00198 #define LANC111_SIGNAL sig_INTERRUPT3
00199 #define LANC111_SIGNAL_MODE() sbi(EICRA, ISC30); sbi(EICRA, ISC31)
00200
00201 #elif (LANC111_SIGNAL_IRQ == INT4)
00202 #define LANC111_SIGNAL sig_INTERRUPT4
00203 #define LANC111_SIGNAL_MODE() sbi(EICR, ISC40); sbi(EICR, ISC41)
00204
00205 #elif (LANC111_SIGNAL_IRQ == INT6)
00206 #define LANC111_SIGNAL sig_INTERRUPT6
00207 #define LANC111_SIGNAL_MODE() sbi(EICR, ISC60); sbi(EICR, ISC61)
00208
00209 #elif (LANC111_SIGNAL_IRQ == INT7)
00210 #define LANC111_SIGNAL sig_INTERRUPT7
00211 #define LANC111_SIGNAL_MODE() sbi(EICR, ISC70); sbi(EICR, ISC71)
00212
00213 #else
00214 #define LANC111_SIGNAL sig_INTERRUPT5
00215 #define LANC111_SIGNAL_MODE() sbi(EICR, ISC50); sbi(EICR, ISC51)
00216
00217 #endif
00218
00223
00227 #define NIC_BSR (LANC111_BASE_ADDR + 0x0E)
00228
00232 #define NIC_TCR (LANC111_BASE_ADDR + 0x00)
00233
00234 #define TCR_SWFDUP 0x8000
00235 #define TCR_EPH_LOOP 0x2000
00236 #define TCR_STP_SQET 0x1000
00237 #define TCR_FDUPLX 0x0800
00238 #define TCR_MON_CSN 0x0400
00239 #define TCR_NOCRC 0x0100
00240 #define TCR_PAD_EN 0x0080
00241 #define TCR_FORCOL 0x0004
00242 #define TCR_LOOP 0x0002
00243 #define TCR_TXENA 0x0001
00249 #define NIC_EPHSR (LANC111_BASE_ADDR + 0x02)
00250
00254 #define NIC_RCR (LANC111_BASE_ADDR + 0x04)
00255
00256 #define RCR_SOFT_RST 0x8000
00257 #define RCR_FILT_CAR 0x4000
00258 #define RCR_ABORT_ENB 0x2000
00259 #define RCR_STRIP_CRC 0x0200
00260 #define RCR_RXEN 0x0100
00261 #define RCR_ALMUL 0x0004
00262 #define RCR_PRMS 0x0002
00263 #define RCR_RX_ABORT 0x0001
00268 #define NIC_ECR (LANC111_BASE_ADDR + 0x06)
00269
00273 #define NIC_MIR (LANC111_BASE_ADDR + 0x08)
00274
00278 #define NIC_RPCR (LANC111_BASE_ADDR + 0x0A)
00279
00280 #define RPCR_SPEED 0x2000
00281 #define RPCR_DPLX 0x1000
00282 #define RPCR_ANEG 0x0800
00283 #define RPCR_LEDA_PAT 0x0000
00284 #define RPCR_LEDB_PAT 0x0010
00289 #define NIC_CR (LANC111_BASE_ADDR + 0x00)
00290
00291 #define CR_EPH_EN 0x8000
00296 #define NIC_BAR (LANC111_BASE_ADDR + 0x02)
00297
00301 #define NIC_IAR (LANC111_BASE_ADDR + 0x04)
00302
00306 #define NIC_GPR (LANC111_BASE_ADDR + 0x0A)
00307
00311 #define NIC_CTR (LANC111_BASE_ADDR + 0x0C)
00312
00313 #define CTR_RCV_BAD 0x4000
00314 #define CTR_AUTO_RELEASE 0x0800
00319 #define NIC_MMUCR (LANC111_BASE_ADDR + 0x00)
00320
00321 #define MMUCR_BUSY 0x0001
00322
00323 #define MMU_NOP 0
00324 #define MMU_ALO (1<<5)
00325 #define MMU_RST (2<<5)
00326 #define MMU_REM (3<<5)
00327 #define MMU_TOP (4<<5)
00328 #define MMU_PKT (5<<5)
00329 #define MMU_ENQ (6<<5)
00330 #define MMU_RTX (7<<5)
00331
00337 #define NIC_PNR (LANC111_BASE_ADDR + 0x02)
00338
00344 #define NIC_ARR (LANC111_BASE_ADDR + 0x03)
00345
00346 #define ARR_FAILED 0x80
00347
00351 #define NIC_FIFO (LANC111_BASE_ADDR + 0x04)
00352
00356 #define NIC_PTR (LANC111_BASE_ADDR + 0x06)
00357
00358 #define PTR_RCV 0x8000
00359 #define PTR_AUTO_INCR 0x4000
00360 #define PTR_READ 0x2000
00361 #define PTR_ETEN 0x1000
00362 #define PTR_NOT_EMPTY 0x0800
00367 #define NIC_DATA (LANC111_BASE_ADDR + 0x08)
00368
00372 #define NIC_IST (LANC111_BASE_ADDR + 0x0C)
00373
00377 #define NIC_ACK (LANC111_BASE_ADDR + 0x0C)
00378
00382 #define NIC_MSK (LANC111_BASE_ADDR + 0x0D)
00383
00384 #define INT_MD 0x80
00385 #define INT_ERCV 0x40
00386 #define INT_EPH 0x20
00387 #define INT_RX_OVRN 0x10
00388 #define INT_ALLOC 0x08
00389 #define INT_TX_EMPTY 0x04
00390 #define INT_TX 0x02
00391 #define INT_RCV 0x01
00396 #define NIC_MT (LANC111_BASE_ADDR + 0x00)
00397
00401 #define NIC_MGMT (LANC111_BASE_ADDR + 0x08)
00402
00403 #define MGMT_MDOE 0x08
00404 #define MGMT_MCLK 0x04
00405 #define MGMT_MDI 0x02
00406 #define MGMT_MDO 0x01
00411 #define NIC_REV (LANC111_BASE_ADDR + 0x0A)
00412
00416 #define NIC_ERCV (LANC111_BASE_ADDR + 0x0C)
00417
00421 #define NIC_PHYCR 0
00422
00423 #define PHYCR_RST 0x8000
00424 #define PHYCR_LPBK 0x4000
00425 #define PHYCR_SPEED 0x2000
00426 #define PHYCR_ANEG_EN 0x1000
00427 #define PHYCR_PDN 0x0800
00428 #define PHYCR_MII_DIS 0x0400
00429 #define PHYCR_ANEG_RST 0x0200
00430 #define PHYCR_DPLX 0x0100
00431 #define PHYCR_COLST 0x0080
00437 #define NIC_PHYSR 1
00438
00439 #define PHYSR_CAP_T4 0x8000
00440 #define PHYSR_CAP_TXF 0x4000
00441 #define PHYSR_CAP_TXH 0x2000
00442 #define PHYSR_CAP_TF 0x1000
00443 #define PHYSR_CAP_TH 0x0800
00444 #define PHYSR_CAP_SUPR 0x0040
00445 #define PHYSR_ANEG_ACK 0x0020
00446 #define PHYSR_REM_FLT 0x0010
00447 #define PHYSR_CAP_ANEG 0x0008
00448 #define PHYSR_LINK 0x0004
00449 #define PHYSR_JAB 0x0002
00450 #define PHYSR_EXREG 0x0001
00456 #define NIC_PHYID1 2
00457
00461 #define NIC_PHYID2 3
00462
00466 #define NIC_PHYANAD 4
00467
00468 #define PHYANAD_NP 0x8000
00469 #define PHYANAD_ACK 0x4000
00470 #define PHYANAD_RF 0x2000
00471 #define PHYANAD_T4 0x0200
00472 #define PHYANAD_TX_FDX 0x0100
00473 #define PHYANAD_TX_HDX 0x0080
00474 #define PHYANAD_10FDX 0x0040
00475 #define PHYANAD_10_HDX 0x0020
00476 #define PHYANAD_CSMA 0x0001
00481 #define NIC_PHYANRC 5
00482
00486 #define NIC_PHYCFR1 16
00487
00491 #define NIC_PHYCFR2 17
00492
00496 #define NIC_PHYSOR 18
00497
00498 #define PHYSOR_INT 0x8000
00499 #define PHYSOR_LNKFAIL 0x4000
00500 #define PHYSOR_LOSSSYNC 0x2000
00501 #define PHYSOR_CWRD 0x1000
00502 #define PHYSOR_SSD 0x0800
00503 #define PHYSOR_ESD 0x0400
00504 #define PHYSOR_RPOL 0x0200
00505 #define PHYSOR_JAB 0x0100
00506 #define PHYSOR_SPDDET 0x0080
00507 #define PHYSOR_DPLXDET 0x0040
00512 #define NIC_PHYMSK 19
00513
00514 #define PHYMSK_MINT 0x8000
00515 #define PHYMSK_MLNKFAIL 0x4000
00516 #define PHYMSK_MLOSSSYN 0x2000
00517 #define PHYMSK_MCWRD 0x1000
00518 #define PHYMSK_MSSD 0x0800
00519 #define PHYMSK_MESD 0x0400
00520 #define PHYMSK_MRPOL 0x0200
00521 #define PHYMSK_MJAB 0x0100
00522 #define PHYMSK_MSPDDT 0x0080
00523 #define PHYMSK_MDPLDT 0x0040
00527 #define MSBV(bit) (1 << ((bit) - 8))
00528
00529 #define nic_outlb(addr, val) (*(volatile uint8_t *)(addr) = (val))
00530 #define nic_outhb(addr, val) (*(volatile uint8_t *)((addr) + 1) = (val))
00531 #define nic_outwx(addr, val) (*(volatile uint16_t *)(addr) = (val))
00532 #define nic_outw(addr, val) { \
00533 *(volatile uint8_t *)(addr) = (uint8_t)(val); \
00534 *((volatile uint8_t *)(addr) + 1) = (uint8_t)((val) >> 8); \
00535 }
00536
00537 #define nic_inlb(addr) (*(volatile uint8_t *)(addr))
00538 #define nic_inhb(addr) (*(volatile uint8_t *)((addr) + 1))
00539 #define nic_inw(addr) (*(volatile uint16_t *)(addr))
00540
00541 #define nic_bs(bank) nic_outlb(NIC_BSR, bank)
00542
00547 struct _NICINFO {
00548 HANDLE volatile ni_rx_rdy;
00549 uint16_t ni_tx_cnt;
00550 uint32_t ni_rx_packets;
00551 uint32_t ni_tx_packets;
00552 uint32_t ni_interrupts;
00553 uint32_t ni_overruns;
00554 uint32_t ni_rx_frame_errors;
00555 uint32_t ni_rx_crc_errors;
00556 uint32_t ni_rx_missed_errors;
00557 uint8_t ni_mar[8];
00558 };
00559
00563 typedef struct _NICINFO NICINFO;
00564
00571
00572
00573 static HANDLE mutex;
00574 static HANDLE maq;
00575
00586 static uint8_t NicPhyRegSelect(uint8_t reg, uint8_t we)
00587 {
00588 uint8_t rs;
00589 uint8_t msk;
00590 uint8_t i;
00591
00592 nic_bs(3);
00593 rs = (nic_inlb(NIC_MGMT) & ~(MGMT_MCLK | MGMT_MDO)) | MGMT_MDOE;
00594
00595
00596 for (i = 0; i < 33; i++) {
00597 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00598 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00599 }
00600
00601
00602 nic_outlb(NIC_MGMT, rs);
00603 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00604 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00605 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00606
00607
00608 if (we) {
00609 nic_outlb(NIC_MGMT, rs);
00610 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00611 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00612 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00613 } else {
00614 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00615 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00616 nic_outlb(NIC_MGMT, rs);
00617 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00618 }
00619
00620
00621 for (i = 0; i < 5; i++) {
00622 nic_outlb(NIC_MGMT, rs);
00623 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00624 }
00625
00626
00627 for (msk = 0x10; msk; msk >>= 1) {
00628 if (reg & msk) {
00629 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00630 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00631 } else {
00632 nic_outlb(NIC_MGMT, rs);
00633 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00634 }
00635 }
00636 nic_outlb(NIC_MGMT, rs);
00637
00638 return rs;
00639 }
00640
00650 static uint16_t NicPhyRead(uint8_t reg)
00651 {
00652 uint16_t rc = 0;
00653 uint8_t rs;
00654 uint8_t i;
00655
00656
00657 rs = NicPhyRegSelect(reg, 0);
00658
00659
00660 rs &= ~MGMT_MDOE;
00661 nic_outlb(NIC_MGMT, rs);
00662 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00663
00664
00665 for (i = 0; i < 16; i++) {
00666 nic_outlb(NIC_MGMT, rs);
00667 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00668 rc <<= 1;
00669 rc |= (nic_inlb(NIC_MGMT) & MGMT_MDI) != 0;
00670 }
00671
00672
00673 nic_outlb(NIC_MGMT, rs);
00674
00675 return rc;
00676 }
00677
00686 static void NicPhyWrite(uint8_t reg, uint16_t val)
00687 {
00688 uint16_t msk;
00689 uint8_t rs;
00690
00691
00692 rs = NicPhyRegSelect(reg, 1);
00693
00694
00695 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00696 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00697 nic_outlb(NIC_MGMT, rs);
00698 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00699
00700
00701 for (msk = 0x8000; msk; msk >>= 1) {
00702 if (val & msk) {
00703 nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00704 nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00705 } else {
00706 nic_outlb(NIC_MGMT, rs);
00707 nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00708 }
00709 }
00710
00711
00712 nic_outlb(NIC_MGMT, rs & ~MGMT_MDOE);
00713 }
00714
00720 static int NicPhyConfig(void)
00721 {
00722 uint16_t phy_sor;
00723 uint16_t phy_sr;
00724 uint16_t phy_to;
00725 uint16_t mode;
00726
00727
00728
00729
00730
00731
00732
00733 NicPhyWrite(NIC_PHYCR, PHYCR_RST);
00734 for (phy_to = 0;; phy_to++) {
00735 NutSleep(63);
00736 if ((NicPhyRead(NIC_PHYCR) & PHYCR_RST) == 0)
00737 break;
00738 if (phy_to > 3)
00739 return -1;
00740 }
00741
00742
00743
00744 phy_sor = NicPhyRead(NIC_PHYSOR);
00745
00746
00747 NicPhyWrite(NIC_PHYMSK, PHYMSK_MLOSSSYN | PHYMSK_MCWRD | PHYMSK_MSSD |
00748 PHYMSK_MESD | PHYMSK_MRPOL | PHYMSK_MJAB | PHYMSK_MSPDDT | PHYMSK_MDPLDT);
00749
00750
00751 mode = RPCR_ANEG | RPCR_LEDA_PAT | RPCR_LEDB_PAT;
00752 nic_bs(0);
00753 nic_outw(NIC_RPCR, mode);
00754
00755 #ifdef NIC_FIXED
00756
00757 phy_sr = NicPhyRead(NIC_PHYCFR1);
00758 NicPhyWrite(NIC_PHYCFR1, phy_sr | 0x8000);
00759 NutSleep(63);
00760
00761
00762 NicPhyWrite(NIC_PHYCR, NIC_FIXED);
00763 nic_bs(0);
00764 nic_outw(NIC_RPCR, mode);
00765
00766
00767 phy_sr = NicPhyRead(NIC_PHYCFR1);
00768 NicPhyWrite(NIC_PHYCFR1, phy_sr & ~0x8000);
00769 phy_sr = NicPhyRead(NIC_PHYCFR1);
00770
00771 #else
00772
00773
00774
00775
00776
00777 NicPhyWrite(NIC_PHYANAD, PHYANAD_TX_FDX | PHYANAD_TX_HDX | PHYANAD_10FDX | PHYANAD_10_HDX | PHYANAD_CSMA);
00778 NutSleep(63);
00779 for (phy_to = 0, phy_sr = 0;; phy_to++) {
00780
00781 if (phy_to >= 1024)
00782 return -1;
00783
00784 if ((phy_to & 127) == 0 ) {
00785 NicPhyWrite(NIC_PHYCR, PHYCR_ANEG_EN | PHYCR_ANEG_RST);
00786
00787 NutSleep(63);
00788 }
00789
00790 phy_sr = NicPhyRead(NIC_PHYSR);
00791
00792 if (phy_sr & PHYSR_ANEG_ACK)
00793 break;
00794 NutSleep(63);
00795 }
00796
00797 #endif
00798
00799 return 0;
00800 }
00801
00812 static INLINE int NicMmuWait(uint16_t tmo)
00813 {
00814 while (tmo--) {
00815 if ((nic_inlb(NIC_MMUCR) & MMUCR_BUSY) == 0)
00816 break;
00817 NutDelay(1);
00818 }
00819 return tmo ? 0 : -1;
00820 }
00821
00827 static int NicReset(void)
00828 {
00829 #ifdef LANC111_RESET_BIT
00830 sbi(LANC111_RESET_DDR, LANC111_RESET_BIT);
00831 sbi(LANC111_RESET_PORT, LANC111_RESET_BIT);
00832 NutDelay(WAIT100);
00833 cbi(LANC111_RESET_PORT, LANC111_RESET_BIT);
00834 NutDelay(WAIT250);
00835 NutDelay(WAIT250);
00836 #endif
00837
00838
00839 nic_outlb(NIC_MSK, 0);
00840
00841
00842 nic_bs(0);
00843 nic_outw(NIC_RCR, RCR_SOFT_RST);
00844
00845
00846 nic_bs(1);
00847 nic_outw(NIC_CR, CR_EPH_EN);
00848
00849 NutDelay(10);
00850
00851
00852 nic_bs(0);
00853 nic_outw(NIC_RCR, 0);
00854 nic_outw(NIC_TCR, 0);
00855
00856
00857 nic_bs(1);
00858 nic_outw(NIC_CTR, CTR_AUTO_RELEASE);
00859
00860
00861 nic_bs(2);
00862 nic_outlb(NIC_MMUCR, MMU_RST);
00863 if (NicMmuWait(1000))
00864 return -1;
00865
00866 return 0;
00867 }
00868
00874 static void NicUpdateMCHardware(NICINFO * ni)
00875 {
00876 int i;
00877
00878
00879 nic_bs(3);
00880 for (i = 0; i < 7; i++) {
00881 nic_outlb(NIC_MT + i, ni->ni_mar[i]);
00882 }
00883 }
00884
00885
00886
00887
00888
00889
00890
00891
00892 static int NicStart(CONST uint8_t * mac, NICINFO * ni)
00893 {
00894 uint8_t i;
00895
00896 if (NicReset())
00897 return -1;
00898
00899
00900 nic_bs(3);
00901 nic_outlb(NIC_ERCV, 7);
00902 nic_bs(0);
00903 nic_outw(NIC_RCR, RCR_RXEN);
00904
00905
00906 nic_outw(NIC_TCR, TCR_PAD_EN | TCR_TXENA);
00907
00908
00909 if (NicPhyConfig())
00910 return -1;
00911
00912
00913
00914 nic_bs(1);
00915 for (i = 0; i < 6; i++)
00916 nic_outlb(NIC_IAR + i, mac[i]);
00917
00918
00919
00920 NicUpdateMCHardware(ni);
00921
00922
00923 nic_bs(2);
00924 nic_outlb(NIC_MSK, INT_ERCV | INT_RCV | INT_RX_OVRN);
00925
00926 return 0;
00927 }
00928
00929
00930
00931
00932 static void NicInterrupt(void *arg)
00933 {
00934 uint8_t isr;
00935 uint8_t imr;
00936 NICINFO *ni = (NICINFO *) ((NUTDEVICE *) arg)->dev_dcb;
00937
00938 ni->ni_interrupts++;
00939
00940
00941 nic_bs(2);
00942 imr = nic_inlb(NIC_MSK);
00943 nic_outlb(NIC_MSK, 0);
00944
00945
00946 isr = nic_inlb(NIC_IST);
00947
00948 isr &= imr;
00949
00950
00951
00952
00953
00954
00955 if (isr & INT_TX_EMPTY) {
00956 nic_outlb(NIC_ACK, INT_TX_EMPTY);
00957 imr &= ~INT_TX_EMPTY;
00958 }
00959
00960 else if (isr & INT_TX) {
00961
00962 nic_bs(0);
00963 nic_outw(NIC_TCR, nic_inlb(NIC_TCR) | TCR_TXENA);
00964 nic_bs(2);
00965 nic_outlb(NIC_ACK, INT_TX);
00966
00967 nic_outlb(NIC_MMUCR, MMU_PKT);
00968 }
00969
00970
00971
00972
00973
00974
00975 if (isr & INT_RX_OVRN) {
00976 nic_outlb(NIC_ACK, INT_RX_OVRN);
00977
00978 NutEventPostFromIrq(&ni->ni_rx_rdy);
00979 }
00980 if (isr & INT_ERCV) {
00981 nic_outlb(NIC_ACK, INT_ERCV);
00982 NutEventPostFromIrq(&ni->ni_rx_rdy);
00983 }
00984 if (isr & INT_RCV) {
00985 nic_outlb(NIC_ACK, INT_RCV);
00986 imr &= ~INT_RCV;
00987 NutEventPostFromIrq(&ni->ni_rx_rdy);
00988 }
00989
00990 if (isr & INT_ALLOC) {
00991 imr &= ~INT_ALLOC;
00992 NutEventPostFromIrq(&maq);
00993 }
00994
00995 nic_outlb(NIC_MSK, imr);
00996 }
00997
00998
00999
01000
01001 static void NicWrite(uint8_t * buf, uint16_t len)
01002 {
01003 register uint16_t l = len - 1;
01004 register uint8_t ih = (uint16_t) l >> 8;
01005 register uint8_t il = (uint8_t) l;
01006
01007 if (!len)
01008 return;
01009
01010 do {
01011 do {
01012 nic_outlb(NIC_DATA, *buf++);
01013 } while (il-- != 0);
01014 } while (ih-- != 0);
01015 }
01016
01017
01018
01019
01020 static void NicRead(uint8_t * buf, uint16_t len)
01021 {
01022 register uint16_t l = len - 1;
01023 register uint8_t ih = (uint16_t) l >> 8;
01024 register uint8_t il = (uint8_t) l;
01025
01026 if (!len)
01027 return;
01028
01029 do {
01030 do {
01031 *buf++ = nic_inlb(NIC_DATA);
01032 } while (il-- != 0);
01033 } while (ih-- != 0);
01034 }
01035
01046 static NETBUF *NicGetPacket(void)
01047 {
01048 NETBUF *nb = 0;
01049
01050 uint16_t fsw;
01051 uint16_t fbc;
01052
01053
01054
01055 nic_bs(2);
01056 if (nic_inw(NIC_FIFO) & 0x8000) {
01057 return 0;
01058 }
01059
01060
01061 nic_outw(NIC_PTR, PTR_READ | PTR_RCV | PTR_AUTO_INCR);
01062 _NOP();
01063 _NOP();
01064 _NOP();
01065 _NOP();
01066
01067
01068 fsw = nic_inw(NIC_DATA);
01069 fbc = nic_inw(NIC_DATA);
01070
01071
01072
01073 if (fsw & 0xAC00) {
01074 nb = (NETBUF *) 0xFFFF;
01075 }
01076
01077 else if (fbc < 66 || fbc > 1524) {
01078 nb = (NETBUF *) 0xFFFF;
01079 }
01080
01081 else {
01082
01083
01084
01085
01086 fbc -= 3;
01087 nb = NutNetBufAlloc(0, NBAF_DATALINK, fbc);
01088
01089
01090 if (nb)
01091 NicRead(nb->nb_dl.vp, fbc);
01092 }
01093
01094
01095 nic_outlb(NIC_MMUCR, MMU_TOP);
01096
01097 return nb;
01098 }
01099
01114 static int NicPutPacket(NETBUF * nb)
01115 {
01116 uint16_t sz;
01117 uint8_t odd = 0;
01118 uint8_t imsk;
01119
01120
01121
01122
01123
01124
01125
01126
01127 if ((sz = nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz) > ETHERMTU)
01128 return -1;
01129
01130
01131 imsk = nic_inlb(NIC_MSK);
01132 nic_outlb(NIC_MSK, 0);
01133
01134
01135 nic_bs(2);
01136 nic_outlb(NIC_MMUCR, MMU_ALO);
01137 if (NicMmuWait(100))
01138 return -1;
01139
01140
01141 nic_outlb(NIC_MSK, imsk | INT_ALLOC);
01142
01143
01144 sz += nb->nb_dl.sz;
01145 sz += 6;
01146 if (sz & 1) {
01147 sz++;
01148 odd++;
01149 }
01150
01151
01152 while ((nic_inlb(NIC_IST) & INT_ALLOC) == 0) {
01153 if (NutEventWait(&maq, 125)) {
01154 nic_outlb(NIC_MMUCR, MMU_RST);
01155 NicMmuWait(1000);
01156 nic_outlb(NIC_MMUCR, MMU_ALO);
01157 if (NicMmuWait(100) || (nic_inlb(NIC_IST) & INT_ALLOC) == 0) {
01158 if (NutEventWait(&maq, 125)) {
01159 return -1;
01160 }
01161 }
01162 }
01163 }
01164
01165
01166 imsk = nic_inlb(NIC_MSK);
01167 nic_outlb(NIC_MSK, 0);
01168
01169
01170 nic_outlb(NIC_PNR, nic_inhb(NIC_PNR));
01171
01172 nic_outw(NIC_PTR, 0x4000);
01173
01174
01175 nic_outlb(NIC_DATA, 0);
01176 nic_outlb(NIC_DATA, 0);
01177
01178
01179 nic_outw(NIC_DATA, sz);
01180
01181
01182 NicWrite(nb->nb_dl.vp, nb->nb_dl.sz);
01183 NicWrite(nb->nb_nw.vp, nb->nb_nw.sz);
01184 NicWrite(nb->nb_tp.vp, nb->nb_tp.sz);
01185 NicWrite(nb->nb_ap.vp, nb->nb_ap.sz);
01186
01187 if (odd)
01188 nic_outlb(NIC_DATA, 0);
01189
01190
01191 nic_outw(NIC_DATA, 0);
01192
01193
01194 if (NicMmuWait(100))
01195 return -1;
01196 nic_outlb(NIC_MMUCR, MMU_ENQ);
01197
01198
01199 imsk |= INT_TX | INT_TX_EMPTY;
01200 nic_outlb(NIC_MSK, imsk);
01201
01202 return 0;
01203 }
01204
01205
01210 THREAD(NicRxLanc, arg)
01211 {
01212 NUTDEVICE *dev;
01213 IFNET *ifn;
01214 NICINFO *ni;
01215 NETBUF *nb;
01216 uint8_t imsk;
01217
01218 dev = arg;
01219 ifn = (IFNET *) dev->dev_icb;
01220 ni = (NICINFO *) dev->dev_dcb;
01221
01222
01223
01224
01225
01226
01227 while (!ETHER_IS_UNICAST(ifn->if_mac)) {
01228 NutSleep(10);
01229 }
01230
01231
01232
01233
01234
01235
01236
01237 while (NicStart(ifn->if_mac, ni)) {
01238 NutSleep(1000);
01239 }
01240
01241 LANC111_SIGNAL_MODE();
01242 sbi(EIMSK, LANC111_SIGNAL_IRQ);
01243
01244 NutEventPost(&mutex);
01245
01246
01247 NutThreadSetPriority(9);
01248
01249 for (;;) {
01250
01251
01252
01253
01254
01255 NutEventWait(&ni->ni_rx_rdy, 2000);
01256
01257
01258
01259
01260
01261 imsk = nic_inlb(NIC_MSK);
01262 nic_outlb(NIC_MSK, 0);
01263 while ((nb = NicGetPacket()) != 0) {
01264 if (nb != (NETBUF *) 0xFFFF) {
01265 ni->ni_rx_packets++;
01266 (*ifn->if_recv) (dev, nb);
01267 }
01268 }
01269 nic_outlb(NIC_MSK, imsk | INT_RCV | INT_ERCV);
01270 }
01271 }
01272
01283 int LancOutput(NUTDEVICE * dev, NETBUF * nb)
01284 {
01285 static uint32_t mx_wait = 5000;
01286 int rc = -1;
01287 NICINFO *ni;
01288
01289
01290
01291
01292
01293 if (NutEventWait(&mutex, mx_wait) == 0) {
01294 ni = (NICINFO *) dev->dev_dcb;
01295
01296 if (NicPutPacket(nb) == 0) {
01297 ni->ni_tx_packets++;
01298 rc = 0;
01299
01300
01301 mx_wait = 5000;
01302 }
01303 NutEventPost(&mutex);
01304 }
01305
01306
01307
01308
01309 else {
01310 mx_wait = 500;
01311 }
01312 return rc;
01313 }
01314
01332 int LancInit(NUTDEVICE * dev)
01333 {
01334
01335 cbi(EIMSK, LANC111_SIGNAL_IRQ);
01336 memset(dev->dev_dcb, 0, sizeof(NICINFO));
01337
01338
01339 if (NutRegisterIrqHandler(&LANC111_SIGNAL, NicInterrupt, dev))
01340 return -1;
01341
01342
01343
01344
01345
01346
01347 NutThreadCreate("rxi5", NicRxLanc, dev, (NUT_THREAD_LANCRXSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
01348
01349
01350
01351 return 0;
01352 }
01353
01354 static int LancIOCtl(NUTDEVICE * dev, int req, void *conf)
01355 {
01356 int rc = 0;
01357 IFNET *nif = (IFNET *) dev->dev_icb;
01358 NICINFO *ni = (NICINFO *) dev->dev_dcb;
01359 uint32_t i;
01360 MCASTENTRY *mcast;
01361
01362 uint8_t mac[6];
01363
01364 switch (req) {
01365
01366 case SIOCSIFADDR:
01367
01368 memcpy(nif->if_mac, conf, sizeof(nif->if_mac));
01369 break;
01370
01371
01372 case SIOCADDMULTI:
01373 mac[0] = 0x01;
01374 mac[1] = 0x00;
01375 mac[2] = 0x5E;
01376 mac[3] = ((uint8_t *) conf)[1] & 0x7f;
01377 mac[4] = ((uint8_t *) conf)[2];
01378 mac[5] = ((uint8_t *) conf)[3];
01379
01380 mcast = malloc(sizeof(MCASTENTRY));
01381 if (mcast != NULL) {
01382
01383
01384
01385
01386
01387
01388 for (i = 0; i < 7; i++) {
01389 ni->ni_mar[i] = 0xFF;
01390 }
01391
01392
01393 memcpy(mcast->mca_ha, mac, 6);
01394 mcast->mca_ip = *((uint32_t *) conf);
01395 mcast->mca_next = nif->if_mcast;
01396 nif->if_mcast = mcast;
01397
01398
01399 NicUpdateMCHardware(ni);
01400 } else {
01401 rc = -1;
01402 }
01403 break;
01404
01405
01406 case SIOCDELMULTI:
01407
01408 rc = -1;
01409 break;
01410
01411 default:
01412 rc = -1;
01413 break;
01414 }
01415
01416 return rc;
01417 }
01418
01419 static NICINFO dcb_eth0;
01420
01426 static IFNET ifn_eth0 = {
01427 IFT_ETHER,
01428 0,
01429 {0, 0, 0, 0, 0, 0},
01430 0,
01431 0,
01432 0,
01433 ETHERMTU,
01434 0,
01435 0,
01436 0,
01437 NutEtherInput,
01438 LancOutput,
01439 NutEtherOutput,
01440 0
01441 };
01442
01452 NUTDEVICE devSmsc111 = {
01453 0,
01454 {'e', 't', 'h', '0', 0, 0, 0, 0, 0},
01455 IFTYP_NET,
01456 0,
01457 0,
01458 &ifn_eth0,
01459 &dcb_eth0,
01460 LancInit,
01461 LancIOCtl,
01462 0,
01463 0,
01464 0,
01465 0,
01466 0,
01467 0
01468 };
01469