<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=ks_c_5601-1987">
<META content="MSHTML 6.00.2600.0" name=GENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=#ffffff>
<DIV><FONT size=2>Hello...<BR> <BR>I copy FreeBSD's RTL8139C(not C+) driver
and paste to RTEMS.<BR>It's looks like working, but I can't say
positively.<BR>Anyone who want run RTEMS(in pc386 target) with RTL8139C(not C+)
network interface is, please help me.<BR>I attach code.<BR> <BR>PS.<BR>I
must use LonWorks PC104 card & IEEE1394 PC104 card in my SBC. So I have not
enough space in my SBC & must use RTL 8139C(not C+) network
interface(--).<BR> <BR>***** code start *****<BR> <BR>/*<BR> *
Copyright (c) 1997, 1998<BR> * Bill Paul <<A
href="mailto:wpaul@ctr.columbia.edu">wpaul@ctr.columbia.edu</A>>. All
rights reserved.<BR> *<BR> * Redistribution and use in source and
binary forms, with or without<BR> * modification, are permitted provided
that the following conditions<BR> * are met:<BR> * 1. Redistributions
of source code must retain the above copyright<BR> *
notice, this list of conditions and the following disclaimer.<BR> * 2.
Redistributions in binary form must reproduce the above
copyright<BR> * notice, this list of conditions and the
following disclaimer in the<BR> * documentation and/or
other materials provided with the distribution.<BR> * 3. All advertising
materials mentioning features or use of this
software<BR> * must display the following
acknowledgement:<BR> * This product includes software developed by Bill
Paul.<BR> * 4. Neither the name of the author nor the names of any
co-contributors<BR> * may be used to endorse or promote
products derived from this software<BR> * without
specific prior written permission.<BR> *<BR> * THIS SOFTWARE IS
PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND<BR> * ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE<BR> * IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE<BR> *
ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS
HEAD<BR> * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR<BR> * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF<BR> * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS<BR> * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN<BR> * CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE)<BR> * ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF<BR> * THE POSSIBILITY OF SUCH
DAMAGE.<BR> *<BR> * $FreeBSD: src/sys/pci/if_rl.c,v 1.38.2.10
2002/02/15 04:21:20 silby Exp $<BR> */<BR> <BR>/*<BR> * RealTek
8129/8139 PCI NIC driver<BR> *<BR> * Supports several extremely cheap
PCI 10/100 adapters based on<BR> * the RealTek chipset. Datasheets can be
obtained from<BR> * <A
href="http://www.realtek.com.tw">www.realtek.com.tw</A>.<BR> *<BR> *
Written by Bill Paul <<A
href="mailto:wpaul@ctr.columbia.edu">wpaul@ctr.columbia.edu</A>><BR> *
Electrical Engineering Department<BR> * Columbia University, New York
City<BR> */<BR> <BR>/*<BR> * The RealTek 8139 PCI NIC redefines
the meaning of 'low end.' This is<BR> * probably the worst PCI ethernet
controller ever made, with the possible<BR> * exception of the FEAST chip
made by SMC. The 8139 supports bus-master<BR> * DMA, but it has a terrible
interface that nullifies any performance<BR> * gains that bus-master DMA
usually offers.<BR> *<BR> * For transmission, the chip offers a series
of four TX descriptor<BR> * registers. Each transmit frame must be in a
contiguous buffer, aligned<BR> * on a longword (32-bit) boundary. This
means we almost always have to<BR> * do mbuf copies in order to transmit a
frame, except in the unlikely<BR> * case where a) the packet fits into a
single mbuf, and b) the packet<BR> * is 32-bit aligned within the mbuf's
data area. The presence of only<BR> * four descriptor registers means that
we can never have more than four<BR> * packets queued for transmission at
any one time.<BR> *<BR> * Reception is not much better. The driver has
to allocate a single large<BR> * buffer area (up to 64K in size) into which
the chip will DMA received<BR> * frames. Because we don't know where within
this region received packets<BR> * will begin or end, we have no choice but
to copy data from the buffer<BR> * area into mbufs in order to pass the
packets up to the higher protocol<BR> * levels.<BR> *<BR> * It's
impossible given this rotten design to really achieve decent<BR> *
performance at 100Mbps, unless you happen to have a 400Mhz PII or<BR> *
some equally overmuscled CPU to drive it.<BR> *<BR> * On the bright
side, the 8139 does have a built-in PHY, although<BR> * rather than using
an MDIO serial interface like most other NICs, the<BR> * PHY registers are
directly accessible through the 8139's register<BR> * space. The 8139
supports autonegotiation, as well as a 64-bit multicast<BR> *
filter.<BR> *<BR> * The 8129 chip is an older version of the 8139 that
uses an external PHY<BR> * chip. The 8129 has a serial MDIO interface for
accessing the MII where<BR> * the 8139 lets you directly access the
on-board PHY registers. We need<BR> * to select which interface to use
depending on the chip type.<BR> */<BR> <BR>/* <BR> * RTL8139C(not
C+) RTEMS driver<BR> * It's only TEST!!! <BR> * Bae daeho <<A
href="mailto:baedo@palgong.knu.ac.kr">baedo@palgong.knu.ac.kr</A>><BR> */<BR> <BR>#include
<bsp.h><BR> <BR>#include <pcibios.h><BR> <BR>#include
<stdio.h><BR>#include <assert.h><BR> <BR>#include
<rtems/error.h><BR>#include
<rtems/rtems_bsdnet.h><BR> <BR>#include
<sys/param.h><BR>#include <sys/mbuf.h><BR>#include
<sys/socket.h><BR>#include <sys/sockio.h><BR> <BR>#include
<net/if.h><BR> <BR>#include <netinet/in.h><BR>#include
<netinet/if_ether.h><BR> <BR>#include <irq.h><BR> <BR>/*
from NetBSD RTK8139 driver */<BR>#define PCI_VENDOR_ID_RTK
0x10EC<BR>#define PCI_DEVICE_ID_RTK_8139 0x8139<BR> <BR>#define RTK_IDR0
0x0000 /* ID register 0 (station addr) */<BR>#define RTK_IDR1 0x0001
/* Must use 32-bit accesses (?) */<BR>#define RTK_IDR2 0x0002<BR>#define
RTK_IDR3 0x0003<BR>#define RTK_IDR4 0x0004<BR>#define RTK_IDR5
0x0005<BR> /* 0006-0007 reserved */<BR>#define RTK_MAR0
0x0008 /* Multicast hash table */<BR>#define RTK_MAR1 0x0009<BR>#define
RTK_MAR2 0x000A<BR>#define RTK_MAR3 0x000B<BR>#define RTK_MAR4 0x000C<BR>#define
RTK_MAR5 0x000D<BR>#define RTK_MAR6 0x000E<BR>#define RTK_MAR7
0x000F<BR> <BR>#define RTK_TXSTAT0 0x0010 /* status of TX descriptor
0 */<BR>#define RTK_TXSTAT1 0x0014 /* status of TX descriptor 1
*/<BR>#define RTK_TXSTAT2 0x0018 /* status of TX descriptor 2
*/<BR>#define RTK_TXSTAT3 0x001C /* status of TX descriptor 3
*/<BR> <BR>#define RTK_TXADDR0 0x0020 /* address of TX descriptor 0
*/<BR>#define RTK_TXADDR1 0x0024 /* address of TX descriptor 1
*/<BR>#define RTK_TXADDR2 0x0028 /* address of TX descriptor 2
*/<BR>#define RTK_TXADDR3 0x002C /* address of TX descriptor 3
*/<BR> <BR>#define RTK_RXADDR 0x0030 /* RX ring start address
*/<BR>#define RTK_RX_EARLY_BYTES 0x0034 /* RX early byte count */<BR>#define
RTK_RX_EARLY_STAT 0x0036 /* RX early status */<BR>#define RTK_COMMAND
0x0037 /* command register */<BR>#define RTK_CURRXADDR 0x0038 /*
current address of packet read */<BR>#define RTK_CURRXBUF 0x003A /*
current RX buffer address */<BR>#define RTK_IMR 0x003C /* interrupt
mask register */<BR>#define RTK_ISR 0x003E /* interrupt status
register */<BR>#define RTK_TXCFG 0x0040 /* transmit config */<BR>#define
RTK_RXCFG 0x0044 /* receive config */<BR>#define RTK_TIMERCNT 0x0048
/* timer count register */<BR>#define RTK_MISSEDPKT 0x004C /* missed
packet counter */<BR>#define RTK_EECMD 0x0050 /* EEPROM command register
*/<BR>#define RTK_CFG0 0x0051 /* config register #0 */<BR>#define RTK_CFG1
0x0052 /* config register #1 */<BR> /* 0053-0057
reserved */<BR>#define RTK_MEDIASTAT 0x0058 /* media status register
(8139) */<BR> /* 0059-005A reserved */<BR>#define
RTK_MII 0x005A /* 8129 chip only */<BR>#define RTK_HALTCLK
0x005B<BR>#define RTK_MULTIINTR 0x005C /* multiple interrupt */<BR>#define
RTK_PCIREV 0x005E /* PCI revision value */<BR> /*
005F reserved */<BR>#define RTK_TXSTAT_ALL 0x0060 /* TX status of all
descriptors */<BR> <BR>/* Direct PHY access registers only available on
8139 */<BR>#define RTK_BMCR 0x0062 /* PHY basic mode control */<BR>#define
RTK_BMSR 0x0064 /* PHY basic mode status */<BR>#define RTK_ANAR
0x0066 /* PHY autoneg advert */<BR>#define RTK_LPAR 0x0068 /* PHY
link partner ability */<BR>#define RTK_ANER 0x006A /* PHY autoneg
expansion */<BR> <BR>#define RTK_DISCCNT 0x006C /* disconnect counter
*/<BR>#define RTK_FALSECAR 0x006E /* false carrier counter */<BR>#define
RTK_NWAYTST 0x0070 /* NWAY test register */<BR>#define RTK_RX_ER
0x0072 /* RX_ER counter */<BR>#define RTK_CSCFG 0x0074 /* CS
configuration register */<BR> </FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>/*<BR> * TX config register bits<BR> */<BR>#define
RTK_TXCFG_CLRABRT 0x00000001 /* retransmit aborted pkt */<BR>#define
RTK_TXCFG_MAXDMA 0x00000700 /* max DMA burst size */<BR>#define
RTK_TXCFG_CRCAPPEND 0x00010000 /* CRC append (0 = yes) */<BR>#define
RTK_TXCFG_LOOPBKTST 0x00060000 /* loopback test */<BR>#define
RTK_TXCFG_IFG 0x03000000 /* interframe gap */<BR> <BR>#define
RTK_TXDMA_16BYTES 0x00000000<BR>#define RTK_TXDMA_32BYTES 0x00000100<BR>#define
RTK_TXDMA_64BYTES 0x00000200<BR>#define RTK_TXDMA_128BYTES 0x00000300<BR>#define
RTK_TXDMA_256BYTES 0x00000400<BR>#define RTK_TXDMA_512BYTES
0x00000500<BR>#define RTK_TXDMA_1024BYTES 0x00000600<BR>#define
RTK_TXDMA_2048BYTES 0x00000700<BR> <BR>/*<BR> * Transmit descriptor
status register bits.<BR> */<BR>#define RTK_TXSTAT_LENMASK
0x00001FFF<BR>#define RTK_TXSTAT_OWN 0x00002000<BR>#define
RTK_TXSTAT_TX_UNDERRUN 0x00004000<BR>#define RTK_TXSTAT_TX_OK
0x00008000<BR>#define RTK_TXSTAT_EARLY_THRESH 0x003F0000<BR>#define
RTK_TXSTAT_COLLCNT 0x0F000000<BR>#define RTK_TXSTAT_CARR_HBEAT
0x10000000<BR>#define RTK_TXSTAT_OUTOFWIN 0x20000000<BR>#define
RTK_TXSTAT_TXABRT 0x40000000<BR>#define RTK_TXSTAT_CARRLOSS
0x80000000<BR> <BR>/*<BR> * Interrupt status register
bits.<BR> */<BR>#define RTK_ISR_RX_OK 0x0001<BR>#define
RTK_ISR_RX_ERR 0x0002<BR>#define RTK_ISR_TX_OK 0x0004<BR>#define
RTK_ISR_TX_ERR 0x0008<BR>#define RTK_ISR_RX_OVERRUN 0x0010<BR>#define
RTK_ISR_PKT_UNDERRUN 0x0020<BR>#define RTK_ISR_FIFO_OFLOW 0x0040 /* 8139 only
*/<BR>#define RTK_ISR_PCS_TIMEOUT 0x4000 /* 8129 only */<BR>#define
RTK_ISR_SYSTEM_ERR 0x8000<BR> <BR>#define RTK_INTRS
\<BR> (RTK_ISR_TX_OK|RTK_ISR_RX_OK|RTK_ISR_RX_ERR|RTK_ISR_TX_ERR|
\<BR> RTK_ISR_RX_OVERRUN|RTK_ISR_PKT_UNDERRUN|RTK_ISR_FIFO_OFLOW|
\<BR> RTK_ISR_PCS_TIMEOUT|RTK_ISR_SYSTEM_ERR)<BR> <BR>/*<BR> *
Media status register. (8139 only)<BR> */<BR>#define RTK_MEDIASTAT_RXPAUSE
0x01<BR>#define RTK_MEDIASTAT_TXPAUSE 0x02<BR>#define RTK_MEDIASTAT_LINK
0x04<BR>#define RTK_MEDIASTAT_SPEED10 0x08<BR>#define RTK_MEDIASTAT_RXFLOWCTL
0x40 /* duplex mode */<BR>#define RTK_MEDIASTAT_TXFLOWCTL 0x80 /* duplex mode
*/<BR> <BR>/*<BR> * Receive config register.<BR> */<BR>#define
RTK_RXCFG_RX_ALLPHYS 0x00000001 /* accept all nodes */<BR>#define
RTK_RXCFG_RX_INDIV 0x00000002 /* match filter */<BR>#define RTK_RXCFG_RX_MULTI
0x00000004 /* accept all multicast */<BR>#define RTK_RXCFG_RX_BROAD 0x00000008
/* accept all broadcast */<BR>#define RTK_RXCFG_RX_RUNT 0x00000010<BR>#define
RTK_RXCFG_RX_ERRPKT 0x00000020<BR>#define RTK_RXCFG_WRAP
0x00000080<BR>#define RTK_RXCFG_MAXDMA 0x00000700<BR>#define
RTK_RXCFG_BUFSZ 0x00001800<BR>#define RTK_RXCFG_FIFOTHRESH
0x0000E000<BR>#define RTK_RXCFG_EARLYTHRESH 0x07000000<BR> <BR>#define
RTK_RXDMA_16BYTES 0x00000000<BR>#define RTK_RXDMA_32BYTES 0x00000100<BR>#define
RTK_RXDMA_64BYTES 0x00000200<BR>#define RTK_RXDMA_128BYTES 0x00000300<BR>#define
RTK_RXDMA_256BYTES 0x00000400<BR>#define RTK_RXDMA_512BYTES
0x00000500<BR>#define RTK_RXDMA_1024BYTES 0x00000600<BR>#define
RTK_RXDMA_UNLIMITED 0x00000700<BR> <BR>#define RTK_RXBUF_8
0x00000000<BR>#define RTK_RXBUF_16 0x00000800<BR>#define
RTK_RXBUF_32 0x00001000<BR>#define RTK_RXBUF_64
0x00001800<BR> <BR>#define RTK_RXFIFO_16BYTES 0x00000000<BR>#define
RTK_RXFIFO_32BYTES 0x00002000<BR>#define RTK_RXFIFO_64BYTES
0x00004000<BR>#define RTK_RXFIFO_128BYTES 0x00006000<BR>#define
RTK_RXFIFO_256BYTES 0x00008000<BR>#define RTK_RXFIFO_512BYTES
0x0000A000<BR>#define RTK_RXFIFO_1024BYTES 0x0000C000<BR>#define
RTK_RXFIFO_NOTHRESH 0x0000E000<BR> <BR>/*<BR> * Bits in RX status
header (included with RX'ed packet<BR> * in ring
buffer).<BR> */<BR>#define RTK_RXSTAT_RXOK 0x00000001<BR>#define
RTK_RXSTAT_ALIGNERR 0x00000002<BR>#define RTK_RXSTAT_CRCERR
0x00000004<BR>#define RTK_RXSTAT_GIANT 0x00000008<BR>#define
RTK_RXSTAT_RUNT 0x00000010<BR>#define RTK_RXSTAT_BADSYM
0x00000020<BR>#define RTK_RXSTAT_BROAD 0x00002000<BR>#define RTK_RXSTAT_INDIV
0x00004000<BR>#define RTK_RXSTAT_MULTI 0x00008000<BR>#define RTK_RXSTAT_LENMASK
0xFFFF0000<BR> <BR>#define RTK_RXSTAT_UNFINISHED 0xFFF0 /* DMA still
in progress */<BR>/*<BR> * Command register.<BR> */<BR>#define
RTK_CMD_EMPTY_RXBUF 0x0001<BR>#define RTK_CMD_TX_ENB 0x0004<BR>#define
RTK_CMD_RX_ENB 0x0008<BR>#define RTK_CMD_RESET
0x0010<BR> <BR>/*<BR> * EEPROM control register<BR> */<BR>#define
RTK_EE_DATAOUT 0x01 /* Data out */<BR>#define RTK_EE_DATAIN 0x02 /*
Data in */<BR>#define RTK_EE_CLK 0x04 /* clock */<BR>#define
RTK_EE_SEL 0x08 /* chip select */<BR>#define RTK_EE_MODE
(0x40|0x80)<BR> <BR>#define RTK_EEMODE_OFF 0x00<BR>#define
RTK_EEMODE_AUTOLOAD 0x40<BR>#define RTK_EEMODE_PROGRAM 0x80<BR>#define
RTK_EEMODE_WRITECFG (0x80|0x40)<BR> <BR>/* 9346/9356 EEPROM commands
*/<BR>#define RTK_EEADDR_LEN0 6 /* 9346 */<BR>#define
RTK_EEADDR_LEN1 8 /* 9356 */<BR>#define RTK_EECMD_LEN
4<BR> <BR>#define RTK_EECMD_WRITE 0x5 /* 0101b */<BR>#define
RTK_EECMD_READ 0x6 /* 0110b */<BR>#define RTK_EECMD_ERASE 0x7 /*
0111b */<BR> <BR>#define RTK_EE_ID 0x00<BR>#define
RTK_EE_PCI_VID 0x01<BR>#define RTK_EE_PCI_DID 0x02<BR>/* Location of
station address inside EEPROM */<BR>#define RTK_EE_EADDR0 0x07<BR>#define
RTK_EE_EADDR1 0x08<BR>#define RTK_EE_EADDR2
0x09<BR> <BR>/*<BR> * MII register (8129 only)<BR> */<BR>#define
RTK_MII_CLK 0x01<BR>#define RTK_MII_DATAIN 0x02<BR>#define
RTK_MII_DATAOUT 0x04<BR>#define RTK_MII_DIR 0x80 /* 0 == input, 1 ==
output */<BR> <BR>/*<BR> * Config 0 register<BR> */<BR>#define
RTK_CFG0_ROM0 0x01<BR>#define RTK_CFG0_ROM1 0x02<BR>#define
RTK_CFG0_ROM2 0x04<BR>#define RTK_CFG0_PL0 0x08<BR>#define
RTK_CFG0_PL1 0x10<BR>#define RTK_CFG0_10MBPS 0x20 /* 10 Mbps
internal mode */<BR>#define RTK_CFG0_PCS 0x40<BR>#define
RTK_CFG0_SCR 0x80<BR> <BR>/*<BR> * Config 1
register<BR> */<BR>#define RTK_CFG1_PWRDWN 0x01<BR>#define
RTK_CFG1_SLEEP 0x02<BR>#define RTK_CFG1_IOMAP 0x04<BR>#define
RTK_CFG1_MEMMAP 0x08<BR>#define RTK_CFG1_RSVD 0x10<BR>#define
RTK_CFG1_DRVLOAD 0x20<BR>#define RTK_CFG1_LED0 0x40<BR>#define
RTK_CFG1_FULLDUPLEX 0x40 /* 8129 only */<BR>#define RTK_CFG1_LED1
0x80<BR> <BR>/*<BR> * The RealTek doesn't use a fragment-based
descriptor mechanism.<BR> * Instead, there are only four register sets,
each or which represents<BR> * one 'descriptor.' Basically, each TX
descriptor is just a contiguous<BR> * packet buffer (32-bit aligned!) and
we place the buffer addresses in<BR> * the registers so the chip knows
where they are.<BR> *<BR> * We can sort of kludge together the same
kind of buffer management<BR> * used in previous drivers, but we have to do
buffer copies almost all<BR> * the time, so it doesn't really buy us
much.<BR> *<BR> * For reception, there's just one large buffer where
the chip stores<BR> * all received
packets.<BR> */<BR> <BR>#define RTK_RX_BUF_SZ
RTK_RXBUF_64<BR>#define RTK_RXBUFLEN (1 << ((RTK_RX_BUF_SZ >>
11) + 13))<BR>#define RTK_TX_LIST_CNT 4<BR>#define RTK_RX_BUF_NUM
64 /* Yves: Rx buffer number */<BR>#define RTK_TX_EARLYTHRESH ((256 / 32)
<< 16)<BR>#define RTK_RX_FIFOTHRESH RTK_RXFIFO_256BYTES<BR>#define
RTK_RX_MAXDMA RTK_RXDMA_UNLIMITED<BR>#define RTK_TX_MAXDMA
RTK_TXDMA_2048BYTES<BR> <BR>#define RTK_RXCFG_CONFIG
(RTK_RX_FIFOTHRESH|RTK_RX_MAXDMA|RTK_RX_BUF_SZ)<BR>#define RTK_TXCFG_CONFIG
(RTK_TXCFG_IFG|RTK_TX_MAXDMA)<BR>#define RTK_TXCFG_CONFIG
RTK_TX_MAXDMA<BR> <BR>/*<BR> * PCI low memory base and low I/O base
register, and<BR> * other PCI registers.<BR> */<BR>#define
RTK_PCI_COMMAND 0x04<BR>#define RTK_PCI_LOIO 0x10<BR>#define
RTK_PCI_LOMEM 0x14<BR> <BR>#define RTK_PSTATE_MASK
0x0003<BR>#define RTK_PSTATE_D0 0x0000<BR>#define RTK_PSTATE_D1
0x0002<BR>#define RTK_PSTATE_D2 0x0002<BR>#define RTK_PSTATE_D3
0x0003<BR>#define RTK_PME_EN 0x0010<BR>#define RTK_PME_STATUS
0x8000<BR>#define RTK_PCI_REVISION_ID 0x08 /* Yves: 8 bits */<BR>#define
RTK_TIMEOUT 1000<BR>#define RTK_PCI_CAPID 0x50 /* 8 bits
*/<BR>#define RTK_PCI_PWRMGMTCAP 0x52 /* 16 bits */<BR>#define
RTK_PCI_PWRMGMTCTRL 0x54 /* 16 bits */<BR> <BR>struct rl_chain_data
{<BR> u_int16_t cur_rx;<BR> caddr_t
rl_rx_buf;<BR> <BR> struct mbuf
*rl_tx_chain[RTK_TX_LIST_CNT];<BR> u_int8_t
last_tx;<BR> u_int8_t cur_tx;<BR>};<BR> <BR>#define
RL_INC(x) (x = (x + 1) % RTK_TX_LIST_CNT)<BR>#define RL_CUR_TXADDR(x)
((x->rl_cdata.cur_tx * 4) + RTK_TXADDR0)<BR>#define RL_CUR_TXSTAT(x)
((x->rl_cdata.cur_tx * 4) + RTK_TXSTAT0)<BR>#define RL_CUR_TXMBUF(x)
(x->rl_cdata.rl_tx_chain[x->rl_cdata.cur_tx])<BR>#define RL_LAST_TXADDR(x)
((x->rl_cdata.last_tx * 4) + RTK_TXADDR0)<BR>#define RL_LAST_TXSTAT(x)
((x->rl_cdata.last_tx * 4) + RTK_TXSTAT0)<BR>#define RL_LAST_TXMBUF(x)
(x->rl_cdata.rl_tx_chain[x->rl_cdata.last_tx])<BR>#define
RL_MIN_FRAMELEN 60<BR>#define RL_TXTHRESH(x) ((x) <<
11)<BR>#define RL_TX_THRESH_INIT 96<BR>#define RL_ETHER_ALIGN 2<BR> <BR>/*
from BSD header */<BR>/* PCI config header registers for all devices
*/<BR>#define PCIR_DEVVENDOR 0x00<BR>#define PCIR_VENDOR 0x00<BR>#define
PCIR_DEVICE 0x02<BR>#define PCIR_COMMAND 0x04<BR>#define PCIM_CMD_PORTEN
0x0001<BR>#define PCIM_CMD_MEMEN 0x0002<BR>#define PCIM_CMD_BUSMASTEREN
0x0004<BR>#define PCIM_CMD_MWRICEN 0x0010<BR>#define PCIM_CMD_PERRESPEN
0x0040<BR>#define PCIM_CMD_SERRESPEN 0x0100<BR>#define PCIR_STATUS
0x06<BR>#define PCIM_STATUS_CAPPRESENT 0x0010<BR>#define PCIM_STATUS_66CAPABLE
0x0020<BR>#define PCIM_STATUS_BACKTOBACK 0x0080<BR>#define
PCIM_STATUS_PERRREPORT 0x0100<BR>#define PCIM_STATUS_SEL_FAST 0x0000<BR>#define
PCIM_STATUS_SEL_MEDIMUM 0x0200<BR>#define PCIM_STATUS_SEL_SLOW 0x0400<BR>#define
PCIM_STATUS_SEL_MASK 0x0600<BR>#define PCIM_STATUS_STABORT 0x0800<BR>#define
PCIM_STATUS_RTABORT 0x1000<BR>#define PCIM_STATUS_RMABORT 0x2000<BR>#define
PCIM_STATUS_SERR 0x4000<BR>#define PCIM_STATUS_PERR 0x8000<BR>#define PCIR_REVID
0x08<BR>#define PCIR_PROGIF 0x09<BR>#define PCIR_SUBCLASS 0x0a<BR>#define
PCIR_CLASS 0x0b<BR>#define PCIR_CACHELNSZ 0x0c<BR>#define PCIR_LATTIMER
0x0d<BR>#define PCIR_HEADERTYPE 0x0e<BR>#define PCIM_MFDEV 0x80<BR>#define
PCIR_BIST 0x0f<BR> <BR>/* from RTEMS NE2000 driver */<BR>#define
NRTKDRIVER 1<BR>#define phys_to_bus(address) ((unsigned int)
((address)))<BR>#define bus_to_phys(address) ((unsigned int)
((address)))<BR>#define delay_in_bus_cycles(cycle) Wait_X_ms( cycle/100
)<BR>#define CPU_CACHE_ALIGNMENT_FOR_BUFFER PG_SIZE<BR> <BR>#define
INTERRUPT_EVENT RTEMS_EVENT_1<BR>#define START_TRANSMIT_EVENT
RTEMS_EVENT_2<BR> <BR>struct rtk8139_softc {<BR> <BR>
struct arpcom arpcom;<BR> <BR>
rtems_irq_connect_data irqInfo;<BR> <BR> volatile unsigned char
*bufferBase;<BR> int
acceptBroadcast;<BR> rtems_id
rxDaemonTid;<BR> rtems_id txDaemonTid;<BR>
<BR> int
PendingTxCount;<BR>
int
TxSuspended;<BR> <BR> unsigned int port;<BR>
volatile unsigned int *base;<BR> int
rl_txthresh;<BR> <BR> struct rl_chain_data
rl_cdata;<BR> <BR> /*<BR> * Statistics<BR>
*/<BR> unsigned long rxInterrupts;<BR> unsigned long
rxNotFirst;<BR> unsigned long rxNotLast;<BR> unsigned long
rxGiant;<BR> unsigned long rxNonOctet;<BR> unsigned long
rxRunt;<BR> unsigned long rxBadCRC;<BR> unsigned long
rxOverrun;<BR> unsigned long rxCollision;<BR> <BR> unsigned
long txInterrupts;<BR> unsigned long txDeferred;<BR> unsigned long
txHeartbeat;<BR> unsigned long txLateCollision;<BR> unsigned long
txRetryLimit;<BR> unsigned long txUnderrun;<BR> unsigned long
txLostCarrier;<BR> unsigned long txRawWait;<BR>};<BR> <BR>static
struct rtk8139_softc rtk8139_softc[NRTKDRIVER];<BR> <BR>#define DELAY(x)
Wait_X_ms(x)<BR> <BR>static __inline void outl( unsigned short io_addr,
unsigned int out_data )<BR>{<BR> outport_long( io_addr, out_data
);<BR>}<BR> <BR>static __inline void outw( unsigned short io_addr, unsigned
short out_data )<BR>{<BR> outport_word( io_addr, out_data
);<BR>}<BR> <BR>void __inline outb( unsigned short io_addr, unsigned char
out_data )<BR>{<BR> outport_byte( io_addr, out_data
);<BR>}<BR> <BR>static __inline unsigned int inl( unsigned short io_addr
)<BR>{<BR> unsigned int in_data;<BR> inport_long( io_addr, in_data
);<BR> return in_data;<BR>}<BR> <BR>static __inline unsigned short
inw( unsigned short io_addr )<BR>{<BR> unsigned short in_data;<BR>
inport_word( io_addr, in_data );<BR> return
in_data;<BR>}<BR> <BR>static __inline unsigned char inb( unsigned short
io_addr )<BR>{<BR> unsigned char in_data;<BR> inport_byte( io_addr,
in_data );<BR> return in_data;<BR>}<BR> </FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>static int rl_encap(struct rtk8139_softc *sc, struct mbuf
*m_head) /* Only used in ~C+ mode */<BR>{<BR> struct mbuf
*m_new = NULL;<BR> <BR> MGETHDR(m_new, M_DONTWAIT,
MT_DATA);<BR> if (m_new == NULL) {<BR> printf("rk1 no memory for tx
list");<BR> return(1);<BR> }<BR> if (m_head->m_pkthdr.len
> MHLEN) {<BR> MCLGET(m_new, M_DONTWAIT);<BR> if
(!(m_new->m_flags & M_EXT)) {<BR>
m_freem(m_new);<BR> printf("rk1: no memory for tx
list");<BR> return(1);<BR>
}<BR> }<BR> m_copydata(m_head, 0, m_head->m_pkthdr.len, mtod(m_new,
caddr_t));<BR> m_new->m_pkthdr.len = m_new->m_len =
m_head->m_pkthdr.len;<BR> m_freem(m_head);<BR> m_head =
m_new;<BR> <BR> /* Pad frames to at least 60 bytes. */<BR> if
(m_head->m_pkthdr.len < RL_MIN_FRAMELEN) { /* Yves: Case length < 60
bytes */<BR> /*<BR> * Make security concious people happy:
zero out the<BR> * bytes in the pad area, since we don't know
what<BR> * this mbuf cluster buffer's previous user
might<BR> * have left in it.<BR> */<BR>
bzero(mtod(m_head, char *) +
m_head->m_pkthdr.len,<BR> RL_MIN_FRAMELEN
- m_head->m_pkthdr.len);<BR> m_head->m_pkthdr.len
+=<BR> (RL_MIN_FRAMELEN -
m_head->m_pkthdr.len);<BR> m_head->m_len =
m_head->m_pkthdr.len;<BR> }<BR> RL_CUR_TXMBUF(sc) = m_head;
/* Yves: Save pointer of buffer to sc
*/<BR> <BR> return(0);<BR>}<BR> <BR>static void<BR>rtk8139_start
(struct ifnet *ifp)<BR>{<BR> struct rtk8139_softc *sc =
ifp->if_softc;<BR> struct mbuf *m =
NULL;<BR> <BR> while(RL_CUR_TXMBUF(sc) ==
NULL)<BR> {<BR>
IF_DEQUEUE(&ifp->if_snd, m);<BR> if
(!m)<BR> break;<BR> <BR> if
(rl_encap(sc, m))<BR>
{<BR>
IF_PREPEND(&ifp->if_snd, m); /* Yves: Case encap fail
*/<BR> ifp->if_flags |=
IFF_OACTIVE;<BR>
break;<BR>
}<BR> <BR> outl(sc->port +
RL_CUR_TXADDR(sc), mtod(RL_CUR_TXMBUF(sc),
caddr_t));<BR> outl(sc->port +
RL_CUR_TXSTAT(sc), RL_TXTHRESH(sc->rl_txthresh) |
RL_CUR_TXMBUF(sc)->m_pkthdr.len);<BR>
RL_INC(sc->rl_cdata.cur_tx); /* Yves: Move current Tx index
*/<BR> }<BR> if (RL_CUR_TXMBUF(sc) !=
NULL) /* Tx buffer chain full
*/<BR> ifp->if_flags |=
IFF_OACTIVE;<BR> <BR> ifp->if_timer = 5;<BR>}<BR> <BR>static
void<BR>rtk8139_reset(struct rtk8139_softc *sc)<BR>{<BR> register int
i;<BR> outb(sc->port + RTK_COMMAND,
RTK_CMD_RESET);<BR> <BR> for(i = 0; i < RTK_TIMEOUT;
i++)<BR> {<BR> DELAY(10);<BR> if(!(inb(sc->port +
RTK_COMMAND) & RTK_CMD_RESET))<BR>
break;<BR> }<BR> if(i == RTK_TIMEOUT)<BR> printk("rtk8139 reset
never completed !!\n");<BR> return;<BR>}<BR> <BR>static rtems_isr
rtk8139_intr(rtems_vector_number v)<BR>{<BR> struct rtk8139_softc
*sc;<BR> struct ifnet *ifp;<BR> u_int16_t
status;<BR> <BR> sc =
&rtk8139_softc[0];<BR> ifp =
&sc->arpcom.ac_if;<BR> <BR> /* Disable interrupts.
*/<BR> outw(sc->port + RTK_IMR, 0x0000);<BR> <BR> for (;;)
{<BR> status = inw(sc->port + RTK_ISR);<BR> if
(status)<BR> outw(sc->port + RTK_ISR,
status);<BR> <BR> if ((status & RTK_INTRS) == 0)<BR>
break;<BR> <BR> if (status & RTK_ISR_RX_OK)<BR>
rtems_event_send (sc->rxDaemonTid, INTERRUPT_EVENT);<BR> <BR> if
(status & RTK_ISR_RX_ERR)<BR> rtems_event_send
(sc->rxDaemonTid, INTERRUPT_EVENT);<BR> <BR> if ((status &
RTK_ISR_TX_OK) || (status & RTK_ISR_TX_ERR))<BR>
rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT);<BR> <BR>
if (status & RTK_ISR_SYSTEM_ERR)<BR> {<BR>
rtk8139_reset(sc);<BR> rtk8139_init(sc);<BR>
}<BR> }<BR> <BR> /* Re-enable interrupts.
*/<BR> outw(sc->port + RTK_IMR, RTK_INTRS);<BR> <BR> if
(ifp->if_snd.ifq_head != NULL) /* Yves : Data in Tx buffer waiting for
transimission */<BR>
rtk8139_start(ifp);<BR> <BR> return;<BR>}<BR> <BR>static void
nopOn(const rtems_irq_connect_data* notUsed)<BR>{<BR> /*<BR> *
code should be moved from dec21140Enet_initialize_hardware<BR> * to
this location<BR> */<BR>}<BR> <BR>static int rtk8139IsOn(const
rtems_irq_connect_data* irq)<BR>{<BR> return BSP_irq_enabled_at_i8259s
(irq->name);<BR>}<BR> <BR>static int rl_var_init(struct rtk8139_softc
*sc)<BR>{<BR> int i;<BR> struct rl_chain_data
*cd;<BR> <BR> cd = &sc->rl_cdata;<BR> for (i = 0; i <
RTK_TX_LIST_CNT; i++) {<BR> cd->rl_tx_chain[i] = NULL;<BR>
outl(sc->port + RTK_TXADDR0 + (i * sizeof(u_int32_t)),
0x00000000);<BR> }<BR> sc->rl_cdata.cur_tx =
0;<BR> sc->rl_cdata.last_tx =
0;<BR> <BR> return(0);<BR>}<BR> <BR>/*<BR> * Initialize the
ethernet hardware<BR> */<BR>unsigned char rxbuffer[RTK_RXBUFLEN +
1518];<BR> <BR>static void<BR>rtk8139_initialize_hardware (struct
rtk8139_softc *sc)<BR>{<BR> rtems_status_code st;<BR> volatile
unsigned int *tbase;<BR> int i;<BR> volatile unsigned char *cp =
(volatile unsigned char *)rxbuffer; /* Please check this code : from
baedo*/<BR> u_int32_t rxcfg = 0;<BR> <BR> tbase =
sc->base;<BR> <BR> <BR> /*<BR> * Init RX
ring<BR> */<BR>/* cp = (volatile unsigned char
*)malloc(RTK_RXBUFLEN + 1518, 0, M_NOWAIT); */<BR> sc->bufferBase =
cp;<BR> sc->bufferBase += sizeof(u_int64_t);<BR>
sc->rl_cdata.rl_rx_buf = sc->bufferBase; /* It looks like a goose :
=.= */<BR> <BR> sc->irqInfo.hdl =
(rtems_irq_hdl)rtk8139_intr;<BR> sc->irqInfo.on =
nopOn;<BR> sc->irqInfo.off = nopOn;<BR> sc->irqInfo.isOn =
rtk8139IsOn;<BR> st = BSP_install_rtems_irq_handler
(&sc->irqInfo);<BR> if (!st)<BR> rtems_panic
("Can't attach rtk8139 interrupt handler for irq %d\n",
sc->irqInfo.name);<BR> <BR> rl_var_init(sc);<BR> <BR>
sc->rl_txthresh = RL_TX_THRESH_INIT;<BR> <BR>
rtk8139_reset(sc);<BR> <BR> outb(sc->port + RTK_COMMAND,
RTK_CMD_TX_ENB|RTK_CMD_RX_ENB);<BR> outl(sc->port + RTK_RXCFG,
RTK_RXCFG_CONFIG);<BR> outl(sc->port + RTK_TXCFG,
RTK_TXCFG_CONFIG);<BR> <BR> outl(sc->port + RTK_RXADDR, (unsigned
long)sc->bufferBase);<BR> <BR> rxcfg |=
RTK_RXCFG_RX_INDIV;<BR> rxcfg |= RTK_RXCFG_RX_BROAD;<BR> rxcfg |=
RTK_RXCFG_RX_MULTI;<BR> <BR> outl(sc->port + RTK_MISSEDPKT,
0);<BR> <BR> outl(sc->port + RTK_RXCFG, rxcfg);<BR>
outl(sc->port + RTK_MAR0, 0xFFFFFFFF);<BR> outl(sc->port + RTK_MAR0
+ 4, 0xFFFFFFFF);<BR> <BR> outw(sc->port + RTK_IMR,
RTK_INTRS);<BR> outb(sc->port + RTK_COMMAND,
RTK_CMD_TX_ENB|RTK_CMD_RX_ENB);<BR> outb(sc->port + RTK_CFG1,
RTK_CFG1_DRVLOAD|RTK_CFG1_FULLDUPLEX);<BR> <BR>
printk("rtk8139_initialize_hardware !!\n");<BR>
return;<BR>}<BR> <BR>static void<BR>rtk8139_hw_init(struct rtk8139_softc
*sc)<BR>{<BR> rtems_status_code st;<BR> volatile unsigned int
*tbase;<BR> int i;<BR> volatile unsigned char *cp = (volatile
unsigned char *)rxbuffer;<BR> u_int32_t rxcfg = 0;<BR> <BR>
tbase = sc->base;<BR> <BR> /*<BR> * Init RX
ring<BR> */<BR> sc->bufferBase = cp;<BR>
sc->bufferBase += sizeof(u_int64_t);<BR> sc->rl_cdata.rl_rx_buf =
sc->bufferBase; /* It looks like a goose : =.= */<BR> <BR>
rl_var_init(sc);<BR> <BR> sc->rl_txthresh
= RL_TX_THRESH_INIT;<BR> <BR> rtk8139_reset(sc);<BR> <BR>
outb(sc->port + RTK_COMMAND, RTK_CMD_TX_ENB|RTK_CMD_RX_ENB);<BR>
outl(sc->port + RTK_RXCFG, RTK_RXCFG_CONFIG);<BR> outl(sc->port +
RTK_TXCFG, RTK_TXCFG_CONFIG);<BR> <BR> outl(sc->port + RTK_RXADDR,
(unsigned long)sc->bufferBase);<BR> <BR> rxcfg |=
RTK_RXCFG_RX_INDIV;<BR> rxcfg |= RTK_RXCFG_RX_BROAD;<BR> rxcfg |=
RTK_RXCFG_RX_MULTI;<BR> <BR> outl(sc->port + RTK_MISSEDPKT,
0);<BR> <BR> outl(sc->port + RTK_RXCFG, rxcfg);<BR>
outl(sc->port + RTK_MAR0, 0xFFFFFFFF);<BR> outl(sc->port + RTK_MAR0
+ 4, 0xFFFFFFFF);<BR> <BR> outw(sc->port + RTK_IMR,
RTK_INTRS);<BR> outb(sc->port + RTK_COMMAND,
RTK_CMD_TX_ENB|RTK_CMD_RX_ENB);<BR> outb(sc->port + RTK_CFG1,
RTK_CFG1_DRVLOAD|RTK_CFG1_FULLDUPLEX);<BR> <BR>
return;<BR>}<BR> <BR>static void<BR>rtk8139_rxDaemon (void
*arg)<BR>{<BR> struct ether_header *eh;<BR> struct mbuf
*m;<BR> int total_len = 0;<BR> u_int32_t
rxstat;<BR> caddr_t rxbufpos;<BR> int wrap =
0;<BR> u_int16_t cur_rx;<BR> u_int16_t limit;<BR>
u_int16_t rx_bytes = 0, max_bytes;<BR> struct rtk8139_softc *sc =
(struct rtk8139_softc *)&rtk8139_softc[0];<BR> struct ifnet *ifp =
&sc->arpcom.ac_if;<BR> u_int32_t
value32;<BR> <BR> printk("rtk8139_rxDaemon !!\n");<BR>
<BR> cur_rx = inw(sc->port + RTK_CURRXADDR);<BR> printk("cur_rx
0x%x\n", cur_rx);<BR> value32 = inl(sc->port + RTK_RXADDR);<BR>
printk("RTK_RXADDR 0x%x\n", value32);<BR> <BR> while (1)<BR>
{<BR> rtems_event_set events;<BR> <BR>
/* Wait for the interrupt handler to tell us that there is
a<BR> packet ready to receive.
*/<BR> rtems_bsdnet_event_receive
(INTERRUPT_EVENT,<BR> RTEMS_WAIT |
RTEMS_EVENT_ANY,<BR> RTEMS_NO_TIMEOUT,<BR>
&events);<BR> <BR> cur_rx = (inw(sc->port + RTK_CURRXADDR) +
16) % RTK_RXBUFLEN;<BR> <BR> /* Do not try to read past this point.
*/<BR> limit = inw(sc->port + RTK_CURRXBUF) %
RTK_RXBUFLEN;<BR> <BR> if (limit < cur_rx)<BR>
max_bytes = (RTK_RXBUFLEN - cur_rx) + limit;<BR> else<BR>
max_bytes = limit - cur_rx;<BR> <BR> while((inb(sc->port +
RTK_COMMAND) & RTK_CMD_EMPTY_RXBUF) == 0) {<BR> rxbufpos =
sc->rl_cdata.rl_rx_buf + cur_rx;<BR> rxstat = *(u_int32_t
*)rxbufpos;<BR> <BR> /*<BR> * Here's a
totally undocumented fact for you. When the<BR> * RealTek chip
is in the process of copying a packet into<BR> * RAM for you,
the length will be 0xfff0. If you spot a<BR> * packet header
with this value, you need to stop. The<BR> * datasheet makes
absolutely no mention of this and<BR> * RealTek should be shot
for this.<BR> */<BR> if ((u_int16_t)(rxstat
>> 16) == RTK_RXSTAT_UNFINISHED)<BR>
break;<BR> <BR> if (!(rxstat & RTK_RXSTAT_RXOK))
{<BR> ifp->if_ierrors++;<BR>
rtk8139_hw_init(sc);<BR> break;<BR> /*
return; */<BR> }<BR> <BR> /* No errors; receive the
packet. */ <BR> total_len = rxstat >> 16;<BR>
rx_bytes += total_len + 4;<BR> <BR> /*<BR> *
XXX The RealTek chip includes the CRC with every<BR> *
received frame, and there's no way to turn this<BR> * behavior
off (at least, I can't find anything in<BR> * the manual
that explains how to do it) so we have<BR> * to trim off the
CRC manually.<BR> */<BR> total_len -=
ETHER_CRC_LEN;<BR> <BR> /*<BR> * Avoid trying
to read more bytes than we know<BR> * the chip has prepared
for us.<BR> */<BR>/*<BR> if (rx_bytes >
max_bytes)<BR> break; */ /* Please check this code :
from baedo*/<BR> <BR> rxbufpos =
sc->rl_cdata.rl_rx_buf +<BR> ((cur_rx + sizeof(u_int32_t))
% RTK_RXBUFLEN);<BR> <BR> if (rxbufpos ==
(sc->rl_cdata.rl_rx_buf + RTK_RXBUFLEN))<BR> rxbufpos =
sc->rl_cdata.rl_rx_buf;<BR> <BR> wrap =
(sc->rl_cdata.rl_rx_buf + RTK_RXBUFLEN) - rxbufpos;<BR> <BR>
if (total_len > wrap) {<BR> /*<BR>
* Fool m_devget() into thinking we want to copy<BR> *
the whole buffer so we don't end up fragmenting<BR> *
the data.<BR> */<BR> m =
m_devget(rxbufpos -
RL_ETHER_ALIGN,<BR> total_len +
RL_ETHER_ALIGN, 0, ifp, NULL);<BR> if (m == NULL)
{<BR> ifp->if_ierrors++;<BR>
printf("rk1: out of mbufs, tried to
"<BR> "copy %d bytes\n",
wrap);<BR> } else {<BR> m_adj(m,
RL_ETHER_ALIGN);<BR> m_copyback(m, wrap, total_len -
wrap,<BR>
sc->rl_cdata.rl_rx_buf);<BR> }<BR> cur_rx
= (total_len - wrap + ETHER_CRC_LEN);<BR> } else
{<BR> m = m_devget(rxbufpos -
RL_ETHER_ALIGN,<BR> total_len +
RL_ETHER_ALIGN, 0, ifp, NULL);<BR> if (m == NULL)
{<BR> ifp->if_ierrors++;<BR>
printf("rk1: out of mbufs, tried to
"<BR> "copy %d bytes\n",
total_len);<BR> } else<BR> m_adj(m,
RL_ETHER_ALIGN);<BR> cur_rx += total_len + 4 +
ETHER_CRC_LEN;<BR> }<BR> <BR>
/*<BR> * Round up to 32-bit boundary.<BR>
*/<BR> cur_rx = (cur_rx + 3) & ~3;<BR>
outw(sc->port + RTK_CURRXADDR, cur_rx - 16);<BR> <BR> if (m
== NULL)<BR> continue;<BR> <BR> eh = mtod(m,
struct ether_header *);<BR>
ifp->if_ipackets++;<BR> <BR> /* Remove header from mbuf and
pass it on. */<BR> m_adj(m, sizeof(struct
ether_header));<BR> ether_input(ifp, eh, m);<BR>
}<BR> <BR> }<BR>}<BR> <BR>/*<BR> * Driver transmit
daemon<BR> */<BR>void<BR>rtk8139_txDaemon (void *arg)<BR>{<BR> struct
rtk8139_softc *sc = (struct rtk8139_softc *)arg;<BR> struct ifnet *ifp =
&sc->arpcom.ac_if;<BR> u_int32_t txstat;<BR>
rtems_event_set events;<BR> <BR> for (;;) <BR> {<BR>
rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT,
RTEMS_NO_TIMEOUT, &events);<BR> <BR> /* Clear the timeout timer.
*/<BR> ifp->if_timer = 0;<BR> <BR> /*<BR> * Go
through our tx list and free mbufs for those<BR> * frames that have
been uploaded.<BR> */<BR> do {<BR> txstat =
inl(sc->port + RL_LAST_TXSTAT(sc));<BR> if (!(txstat &
(RTK_TXSTAT_TX_OK|<BR>
RTK_TXSTAT_TX_UNDERRUN|RTK_TXSTAT_TXABRT)))<BR>
break;<BR> <BR> ifp->if_collisions += (txstat &
RTK_TXSTAT_COLLCNT) >> 24; /* Yves: Add collision counter
*/<BR> <BR> if (RL_LAST_TXMBUF(sc) != NULL) { /* Yves: Free
Buffer */<BR> m_freem(RL_LAST_TXMBUF(sc)); /* Yves:
RL_LAST_TXMBUF(x)==>(x->rl_cdata.rl_tx_chain[x->rl_cdata.last_tx])
*/<BR> RL_LAST_TXMBUF(sc) = NULL;<BR>
}<BR> if (txstat & RTK_TXSTAT_TX_OK) /* Yves: Case Tx OK
*/<BR> ifp->if_opackets++;<BR> else
{ /* Yves: Case Tx ERR */<BR>
int oldthresh;<BR>
ifp->if_oerrors++;<BR> if ((txstat & RTK_TXSTAT_TXABRT)
||<BR> (txstat &
RTK_TXSTAT_OUTOFWIN))<BR> outl(sc->port + RTK_TXCFG,
RTK_TXCFG_CONFIG);<BR> oldthresh =
sc->rl_txthresh;<BR> /* error recovery
*/<BR> rtk8139_reset(sc);<BR>
rtk8139_init(sc);<BR> /*<BR> * If
there was a transmit underrun,<BR> * bump the TX
threshold.<BR> */<BR> if (txstat &
RTK_TXSTAT_TX_UNDERRUN)<BR> sc->rl_txthresh =
oldthresh + 32;<BR> printk("RTK8139 tx
underrun\n");<BR> break;<BR> }<BR>
RL_INC(sc->rl_cdata.last_tx);<BR> ifp->if_flags &=
~IFF_OACTIVE;<BR> } while (sc->rl_cdata.last_tx !=
sc->rl_cdata.cur_tx);<BR> <BR> ifp->if_timer =
(sc->rl_cdata.last_tx == sc->rl_cdata.cur_tx) ? 0 : 5;<BR> }<BR>}
<BR> <BR>static void<BR>rtk8139_init (void *arg)<BR>{<BR> struct
rtk8139_softc *sc = arg;<BR> struct ifnet *ifp =
&sc->arpcom.ac_if;<BR> <BR> if (sc->txDaemonTid == 0)
{<BR> <BR> rtk8139_initialize_hardware
(sc);<BR> <BR> sc->rxDaemonTid = rtems_bsdnet_newproc
("RLrx", 4096,<BR>
rtk8139_rxDaemon, sc);<BR> sc->txDaemonTid =
rtems_bsdnet_newproc ("RLtx",
4096,<BR> rtk8139_txDaemon,
sc);<BR> }<BR> else<BR>
rtk8139_hw_init(sc);<BR> /*<BR> * Tell the world that we're
running.<BR> */<BR> ifp->if_flags |= IFF_RUNNING;<BR>
ifp->if_flags &= ~IFF_OACTIVE;<BR>}<BR> <BR>/*<BR> * Stop the
device<BR> */<BR>static void<BR>rtk8139_stop (struct rtk8139_softc
*sc)<BR>{<BR> register int i;<BR> struct ifnet
*ifp;<BR> <BR> ifp =
&sc->arpcom.ac_if;<BR> ifp->if_timer =
0;<BR> <BR> outb(sc->port + RTK_COMMAND,
0x00);<BR> outw(sc->port + RTK_IMR,
0x0000);<BR> <BR> /*<BR> * Free the TX list buffers.<BR>
*/<BR> for (i = 0; i < RTK_TX_LIST_CNT; i++) <BR> {<BR> if
(sc->rl_cdata.rl_tx_chain[i] != NULL) {<BR>
m_freem(sc->rl_cdata.rl_tx_chain[i]);<BR>
sc->rl_cdata.rl_tx_chain[i] = NULL;<BR> outl(sc->port +
RTK_TXADDR0 + i, 0x00000000);<BR>
}<BR> }<BR> <BR> ifp->if_flags &= ~(IFF_RUNNING |
IFF_OACTIVE);<BR> <BR> printk("rtk8139_stop()\n");<BR> return;<BR>}<BR> </FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>/*<BR> * Show interface statistics<BR> */<BR>static
void<BR>rtk8139_stats (struct rtk8139_softc *sc)<BR>{<BR> printf
(" Rx Interrupts:%-8lu",
sc->rxInterrupts);<BR> printf (" Not
First:%-8lu", sc->rxNotFirst);<BR> printf
(" Not Last:%-8lu\n",
sc->rxNotLast);<BR> printf
("
Giant:%-8lu", sc->rxGiant);<BR> printf
("
Runt:%-8lu", sc->rxRunt);<BR> printf
(" Non-octet:%-8lu\n",
sc->rxNonOctet);<BR> printf
(" Bad
CRC:%-8lu", sc->rxBadCRC);<BR> printf
(" Overrun:%-8lu",
sc->rxOverrun);<BR> printf ("
Collision:%-8lu\n", sc->rxCollision);<BR> <BR> printf
(" Tx Interrupts:%-8lu",
sc->txInterrupts);<BR> printf
(" Deferred:%-8lu",
sc->txDeferred);<BR> printf (" Missed Hearbeat:%-8lu\n",
sc->txHeartbeat);<BR> printf
(" No Carrier:%-8lu",
sc->txLostCarrier);<BR> printf ("Retransmit Limit:%-8lu",
sc->txRetryLimit);<BR> printf (" Late Collision:%-8lu\n",
sc->txLateCollision);<BR> printf
(" Underrun:%-8lu",
sc->txUnderrun);<BR> printf (" Raw output wait:%-8lu\n",
sc->txRawWait);<BR>}<BR> <BR>/*<BR> * Driver ioctl
handler<BR> */<BR>static int<BR>rtk8139_ioctl (struct ifnet *ifp, int
command, caddr_t data)<BR>{<BR> struct rtk8139_softc *sc =
ifp->if_softc;<BR> int error = 0;<BR> <BR> switch (command)
{<BR> case SIOCGIFADDR:<BR> case SIOCSIFADDR:<BR> ether_ioctl
(ifp, command, data);<BR> break;<BR> <BR> case
SIOCSIFFLAGS:<BR> switch (ifp->if_flags & (IFF_UP | IFF_RUNNING))
{<BR> case IFF_RUNNING:<BR> rtk8139_stop (sc);<BR>
break;<BR> <BR> case IFF_UP:<BR> rtk8139_init
(sc);<BR> break;<BR> <BR> case IFF_UP |
IFF_RUNNING:<BR> rtk8139_stop (sc);<BR> rtk8139_init
(sc);<BR> break;<BR> <BR> default:<BR>
break;<BR> }<BR> break;<BR> <BR> case
SIO_RTEMS_SHOW_STATS:<BR> rtk8139_stats (sc);<BR> break;<BR>
<BR> /*<BR> * FIXME: All sorts of multicast commands need to be added
here!<BR> */<BR> default:<BR> error = EINVAL;<BR>
break;<BR> }<BR> <BR> return error;<BR>}<BR> <BR>/* Attach
an RTK 8139 driver to the system.
*/<BR> <BR>int<BR>rtems_rtk8139_driver_attach (struct rtems_bsdnet_ifconfig
*config)<BR>{<BR> struct rtk8139_softc *sc;<BR> struct ifnet
*ifp;<BR> int mtu;<BR> int i;<BR> int deviceID =
PCI_DEVICE_ID_RTK_8139; /* network card device ID */<BR> <BR> int
signature;<BR> u_int32_t value;<BR> char interrupt;<BR> int
diag;<BR> int addr_len;<BR> u_int16_t val;<BR> u_int8_t
val8;<BR> u_int32_t command;<BR> u_int8_t
eaddr[ETHER_ADDR_LEN];<BR> <BR> if (pcib_init() ==
PCIB_ERR_NOTPRESENT)<BR> rtems_panic("PCI BIOS not found
!!");<BR> <BR> diag = pcib_find_by_devid(PCI_VENDOR_ID_RTK, deviceID,
0, &signature);<BR> <BR> if(diag == PCIB_ERR_SUCCESS)<BR>
printk("RTK 8139 network card found !!\n");<BR> else<BR>
rtems_panic("RTK 8139 network card not found !!\n");<BR> <BR> for(i =
0; i < NRTKDRIVER; i++)<BR> {<BR> sc =
&rtk8139_softc[i];<BR> ifp = &sc->arpcom.ac_if;<BR>
if(ifp->if_softc == NULL)<BR> break; <BR> }<BR> if(i
>= NRTKDRIVER)<BR> {<BR> printk("Too many RTK
drivers.\n");<BR> return
0;<BR> }<BR> <BR> pcib_conf_read32(signature, RTK_PCI_CAPID,
&command);<BR> command &= 0x000000FF;<BR> printk("rtk8139
command 0x%x\n", command);<BR> <BR> if(command ==
0x01)<BR> {<BR> pcib_conf_read32(signature, RTK_PCI_PWRMGMTCTRL,
&command);<BR> command &= 0xFFFFFFFC;<BR>
pcib_conf_write32(signature, RTK_PCI_PWRMGMTCTRL,
command);<BR> }<BR> <BR> pcib_conf_read32(signature,
PCIR_COMMAND, &command);<BR> command |=
(PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);<BR> pcib_conf_write32(signature,
PCIR_COMMAND, command);<BR> pcib_conf_read32(signature, PCIR_COMMAND,
&command);<BR> <BR> pcib_conf_read8(signature, RTK_PCI_COMMAND,
&val8);<BR> val8 |= 0x03;<BR> pcib_conf_write8(signature,
RTK_PCI_COMMAND, val8);<BR> <BR> pcib_conf_read32(signature,
RTK_PCI_LOIO, &value);<BR> sc->port = value & 0xfff0; /*
Please check this code : from
baedo*/<BR> <BR> pcib_conf_read32(signature, RTK_PCI_LOMEM,
&value);<BR> sc->base = (unsigned int
*)value;<BR> <BR> pcib_conf_read8(signature, RTK_IMR,
&interrupt);<BR> sc->irqInfo.name =
(rtems_irq_symbolic_name)interrupt;<BR> <BR> /* check rtk 8139C+
*/<BR> pcib_conf_read8(signature, RTK_PCI_REVISION_ID,
&val8);<BR> <BR> printk("RTK 8139 port 0x%x mem base 0x%x irq %d
revision %d\n", sc->port, sc->base, sc->irqInfo.name,
val8);<BR> <BR> if(config->hardware_address)<BR> {<BR>
memcpy(sc->arpcom.ac_enaddr, config->hardware_address,
ETHER_ADDR_LEN);<BR> }<BR> else<BR> {<BR>
/*<BR> * Get station address.<BR> */<BR> eaddr[0]
= inb(sc->port + RTK_IDR0);<BR> eaddr[1] = inb(sc->port +
RTK_IDR1);<BR> eaddr[2] = inb(sc->port + RTK_IDR2);<BR> eaddr[3]
= inb(sc->port + RTK_IDR3);<BR> eaddr[4] = inb(sc->port +
RTK_IDR4);<BR> eaddr[5] = inb(sc->port + RTK_IDR5);<BR>
<BR> memcpy(sc->arpcom.ac_enaddr, eaddr, ETHER_ADDR_LEN);<BR>
<BR> printk("RTK 8139 mac addr 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", eaddr[0],
eaddr[1], eaddr[2], eaddr[3], eaddr[4],
eaddr[5]);<BR> }<BR> <BR> rtk8139_reset(sc);<BR> <BR> if
(config->mtu)<BR> mtu = config->mtu;<BR> else<BR> mtu =
ETHERMTU;<BR> <BR> sc->acceptBroadcast =
!config->ignore_broadcast;<BR> <BR> /*<BR> * Set up network
interface values<BR> */<BR> ifp->if_softc =
sc;<BR> ifp->if_unit = i + 1;<BR> ifp->if_name =
"rk";<BR> ifp->if_mtu = mtu;<BR> ifp->if_init =
rtk8139_init;<BR> ifp->if_ioctl =
rtk8139_ioctl;<BR> ifp->if_start =
rtk8139_start;<BR> ifp->if_output =
ether_output;<BR> ifp->if_flags = IFF_BROADCAST |
IFF_SIMPLEX;<BR> if (ifp->if_snd.ifq_maxlen ==
0)<BR> ifp->if_snd.ifq_maxlen = ifqmaxlen;<BR> <BR>
/*<BR> * Attach the interface<BR> */<BR> if_attach
(ifp);<BR> ether_ifattach (ifp);<BR> <BR> printk( "RTK 8139
driver has been attached\n" );<BR> return 1;<BR>}</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>***** code end *****</FONT></DIV>
<DIV><FONT size=2></FONT> </DIV></BODY></HTML>