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