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