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