www.pudn.com > vxworks0108.rar > dec21143.c
/*
modification history
--------------------
2003-4-14,deng xindong dxd-2000@163.net
*/
#include "type.h"
#include "config.h"
#include "vxWorks.h"
#include "ivppc.h"
#include "vg4.h"
#include "pciConfigLib.h"
#include "pciIntLib.h"
#include "pciAutoConfigLib.h"
#include "lwip/debug.h"
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/ip.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include "arch/cc.h"
#include "netif/arp.h"
#include "decif.h"
#define PCI_VENDOR_ID_DEC 0x1011
#define PCI_DEVICE_ID_DEC_21143 0x0019
#define NUM_RX_DESC 32
#define NUM_TX_DESC 32
#define DE_RX_RING_SIZE 64
#define DE_TX_RING_SIZE 64
#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
static int csr0 = 0x01A00000 | 0x8000;
const struct eth_addr ethbroadcast = {0x0,0x20,0xce,0xc5,0x43,0x1d};
struct DEC21143if {
struct eth_addr *ethaddr;
unsigned tx_head;
unsigned tx_tail;
unsigned rx_tail;
struct de_desc *rx_ring;
struct de_desc *tx_ring;
u32_t iobaseCsr; /* Base Address Register 0 */
u32_t membaseCsr; /* Base Address Register 1 */
char irq; /* Interrupt Request Level */
u32_t irqvec; /* Interrupt Request vector */
u32_t configType; /* type of configuration */
u32_t boardType; /* type of LAN board this unit is */
u32_t pciBus; /* PCI Bus number */
u32_t pciDevice; /* PCI Device number */
u32_t pciFunc; /* PCI Function number */
/* Add whatever per-interface state that is needed here. */
};
enum {
/* NIC registers */
BusMode = 0x00, /* bus mode register */
TxPoll = 0x08, /* transmit poll demand */
RxPoll = 0x10, /* receive poll demand */
RxRingAddr = 0x18, /* receive list base address */
TxRingAddr = 0x20, /* transmit list base address */
MacStatus = 0x28, /* status register */
MacMode = 0x30, /* operation mode register */
IntrMask = 0x38, /* interrupt mask register */
RxMissed = 0x40, /* missed frame counter */
ROMCmd = 0x48, /* Ethernet ROM register */
CSR11 = 0x58, /* full-duplex register */
SIAStatus = 0x60, /* SIA status register */
CSR13 = 0x68,
CSR14 = 0x70,
CSR15 = 0x78,
PCIPM = 0x40,
/* BusMode bits */
CmdReset = (1 << 0),
CacheAlign16 = 0x00008000,
BurstLen4 = 0x00000400,
/* Rx/TxPoll bits */
NormalTxPoll = (1 << 0),
NormalRxPoll = (1 << 0),
/* Tx/Rx descriptor status bits */
DescOwn = (1 << 31),
RxError = (1 << 15),
RxErrLong = (1 << 7),
RxErrCRC = (1 << 1),
RxErrFIFO = (1 << 0),
RxErrRunt = (1 << 11),
RxErrFrame = (1 << 14),
RingEnd = (1 << 25),
FirstFrag = (1 << 29),
LastFrag = (1 << 30),
TxError = (1 << 15),
TxFIFOUnder = (1 << 1),
TxLinkFail = (1 << 2) | (1 << 10) | (1 << 11),
TxMaxCol = (1 << 8),
TxOWC = (1 << 9),
TxJabber = (1 << 14),
SetupFrame = (1 << 27),
TxSwInt = (1 << 31),
/* MacStatus bits */
IntrOK = (1 << 16),
IntrErr = (1 << 15),
RxIntr = (1 << 6),
RxEmpty = (1 << 7),
TxIntr = (1 << 0),
TxEmpty = (1 << 2),
PciErr = (1 << 13),
TxState = (1 << 22) | (1 << 21) | (1 << 20),
RxState = (1 << 19) | (1 << 18) | (1 << 17),
LinkFail = (1 << 12),
LinkPass = (1 << 4),
RxStopped = (1 << 8),
TxStopped = (1 << 1),
/* MacMode bits */
TxEnable = (1 << 13),
RxEnable = (1 << 1),
RxTx = TxEnable | RxEnable,
FullDuplex = (1 << 9),
AcceptAllMulticast = (1 << 7),
AcceptAllPhys = (1 << 6),
BOCnt = (1 << 5),
MacModeClear = (1<<12) | (1<<11) | (1<<10) | (1<<8) | (1<<3) |
RxTx | BOCnt | AcceptAllPhys | AcceptAllMulticast,
/* ROMCmd bits */
EE_SHIFT_CLK = 0x02, /* EEPROM shift clock. */
EE_CS = 0x01, /* EEPROM chip select. */
EE_DATA_WRITE = 0x04, /* Data from the Tulip to EEPROM. */
EE_WRITE_0 = 0x01,
EE_WRITE_1 = 0x05,
EE_DATA_READ = 0x08, /* Data from the EEPROM chip. */
EE_ENB = (0x4800 | EE_CS),
/* The EEPROM commands include the alway-set leading bit. */
EE_READ_CMD = 6,
/* RxMissed bits */
RxMissedOver = (1 << 16),
RxMissedMask = 0xffff,
/* SROM-related bits */
SROMC0InfoLeaf = 27,
MediaBlockMask = 0x3f,
MediaCustomCSRs = (1 << 6),
/* PCIPM bits */
PM_Sleep = (1 << 31),
PM_Snooze = (1 << 30),
PM_Mask = PM_Sleep | PM_Snooze,
/* SIAStatus bits */
NWayState = (1 << 14) | (1 << 13) | (1 << 12),
NWayRestart = (1 << 12),
NonselPortActive = (1 << 9),
LinkFailStatus = (1 << 2),
NetCxnErr = (1 << 1),
};
static const u32_t de_intr_mask =
IntrOK | IntrErr | RxIntr | RxEmpty | TxIntr | TxEmpty |
LinkPass | LinkFail | PciErr;
static const u32_t de_bus_mode = /*0x02e000f8;*/ CacheAlign16 | BurstLen4;
static const u32_t de_MacStatus = 0x66f0; /* status register */
static const u32_t de_MacMode = 0x03e04432; /* operation mode register */
static const u32_t de_IntrMask =0xc5a0fff3;
static struct de_desc rx_ring[NUM_RX_DESC];
static struct de_desc tx_ring[NUM_TX_DESC];
#define dr32(reg) readl(de->membaseCsr + (reg))
#define dw32(reg,val) writel(de->membaseCsr + (reg),(val))
#define mdelay sysMsDelay
void dec_recv_packet(struct netif *netif);
err_t dec_send_packet(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr);
int dec_pci_init(struct DEC21143if *deif);
static void de_interrupt (struct DEC21143if *de);
static int de_is_running (struct DEC21143if *de);
static void de_reset_mac (struct DEC21143if *de);
unsigned long cpu_to_le32(unsigned long x)
{
return (((x & 0x000000ffU) << 24) |
((x & 0x0000ff00U) << 8) |
((x & 0x00ff0000U) >> 8) |
((x & 0xff000000U) >> 24));
}
static unsigned short tulip_read_eeprom(int regs, int location, int addr_len)
{
int i;
unsigned short retval = 0;
unsigned int ee_addr = (unsigned int)(regs + ROMCmd);
int read_cmd = location | (EE_READ_CMD << addr_len);
writel(ee_addr,EE_ENB & ~EE_CS);
writel(ee_addr,EE_ENB);
/* Shift the read command bits out. */
for (i = 4 + addr_len; i >= 0; i--) {
short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
writel(ee_addr,EE_ENB | dataval);
readl(ee_addr);
writel(ee_addr,EE_ENB | dataval | EE_SHIFT_CLK);
readl(ee_addr);
retval = (retval << 1) | ((readl(ee_addr) & EE_DATA_READ) ? 1 : 0);
}
writel(ee_addr,EE_ENB);
readl(ee_addr);
for (i = 16; i > 0; i--) {
writel(ee_addr,EE_ENB | EE_SHIFT_CLK);
readl(ee_addr);
retval = (retval << 1) | ((readl(ee_addr) & EE_DATA_READ) ? 1 : 0);
writel(ee_addr,EE_ENB);
readl(ee_addr);
}
/* Terminate the EEPROM access. */
writel( ee_addr,EE_ENB & ~EE_CS);
return (((retval<<8)&0xff00) | ((retval>>8)&0xff) );
}
static void de_reset_mac (struct DEC21143if *de)
{
u32_t tmp;
u32_t status;
/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
if (dr32(BusMode) == 0xffffffff)
{
printf("dec busy\n");
}
dw32 (BusMode, CmdReset);
mdelay (1);
dw32 (BusMode, de_bus_mode);
mdelay (1);
for (tmp = 0; tmp < 5; tmp++) {
dr32 (BusMode);
mdelay (1);
}
mdelay (1);
status = dr32(MacStatus);
if (status & (RxState | TxState))
{
printf("dec busy\n");
}
if (status == 0xffffffff)
{
printf("no dec \n");
}
printf("dec reset\n");
}
static void de_adapter_wake (struct DEC21143if *de)
{
u32_t pmctl;
pciConfigInLong(de->pciBus, de->pciDevice, de->pciFunc, PCIPM, &pmctl);
if (pmctl & PM_Mask) {
pmctl &= ~PM_Mask;
pciConfigOutLong(de->pciBus, de->pciDevice, de->pciFunc, PCIPM, pmctl);
}
}
static void de_stop_rxtx (struct DEC21143if *de)
{
u32_t macmode;
unsigned int work = 1000;
macmode = dr32(MacMode);
if (macmode & RxTx) {
dw32(MacMode, macmode & ~RxTx);
dr32(MacMode);
}
while (--work > 0) {
if (!de_is_running(de))
return;
}
printf("timeout expired stopping DMA\n");
}
static void de_set_rx_mode (struct DEC21143if *de)
{
u32_t macmode;
macmode = dr32(MacMode) & ~(AcceptAllMulticast | AcceptAllPhys);
macmode |= AcceptAllMulticast | AcceptAllPhys;
if (macmode != dr32(MacMode))
dw32(MacMode, macmode);
}
static void de_start_rxtx (struct DEC21143if *de)
{
u32_t macmode;
macmode = dr32(MacMode);
if ((macmode & RxTx) != RxTx) {
dw32(MacMode, macmode | RxTx);
dr32(MacMode);
}
}
static void de_stop_hw (struct DEC21143if *de)
{
mdelay(5);
dw32(IntrMask, 0);
de_stop_rxtx(de);
dw32(MacStatus, dr32(MacStatus));
mdelay(10);
de->rx_tail = 0;
de->tx_head = de->tx_tail = 0;
}
static int de_is_running (struct DEC21143if *de)
{
return (dr32(MacStatus) & (RxState | TxState)) ? 1 : 0;
}
static void de_set_media (struct DEC21143if *de)
{
u32_t macmode = dr32(MacMode);
if (de_is_running(de))
{
printf("dec21143 is running\n");
return ;
}
dw32(CSR13, 0); /* Reset phy */
/* must delay 10ms before writing to other registers,
* especially CSR6
*/
mdelay(10);
macmode |= FullDuplex;
if (macmode != dr32(MacMode))
dw32(MacMode, macmode);
}
static int de_init_hw (struct netif *netif)
{
struct DEC21143if *de;
unsigned int macmode;
de = (struct DEC21143if *)netif->state;
de_adapter_wake(de);
macmode = dr32(MacMode) & ~MacModeClear;
de_reset_mac(de);
de_set_media(de); /* reset phy */
dw32(RxRingAddr, (int)rx_ring);
dw32(TxRingAddr, (int)tx_ring);
intConnect(INUM_TO_IVEC(de->irqvec),(VOIDFUNCPTR)de_interrupt,(int)de);
dw32(MacMode, RxTx | macmode);
dr32(RxMissed); /* self-clearing */
printf("de_intr_mask=%x ",de_intr_mask);
dw32(IntrMask, de_intr_mask);
de_start_rxtx(de);
printf("BusMode= %x ", dr32(BusMode));
printf("TxPoll= %x ", dr32(TxPoll));
printf("RxPoll= %x ", dr32(RxPoll));
printf("RxRingAddr= %x ", dr32(RxRingAddr));
printf("TxRingAddr= %x ", dr32(TxRingAddr));
printf("MacStatus= %x ", dr32(MacStatus));
printf("MacMode= %x ", dr32(MacMode));
printf("IntrMask= %x ", dr32(IntrMask));
printf("RxMissed= %x ", dr32(RxMissed));
printf("ROMCmd= %x ", dr32(ROMCmd));
printf("CSR11= %x ", dr32(CSR11));
printf("SIAStatus= %x ", dr32(SIAStatus));
printf("CSR13= %x ", dr32(CSR13));
printf("CSR14= %x ", dr32(CSR14));
printf("CSR15= %x ", dr32(CSR15));
printf("de_init_hw ok\n");
intEnable(de->irqvec);
return 0;
}
static void de_rx (struct DEC21143if *de)
{
printf("de_receive\n");
}
static void de_tx (struct DEC21143if *de)
{
printf("de_tricve\n");
}
static void de_interrupt (struct DEC21143if *de)
{
u32_t status;
printf("de_int\n");
status = dr32(MacStatus);
if ((!(status & (IntrOK|IntrErr))) || (status == 0xFFFF))
{
dw32(MacStatus, status);
printf("status=%x,error\n",status);
return ;
}
dw32(MacStatus, status);
if (status & (RxIntr | RxEmpty)) {
de_rx(de);
if (status & RxEmpty)
dw32(RxPoll, NormalRxPoll);
}
if (status & (TxIntr | TxEmpty))
de_tx(de);
if (status & PciErr) {
u16_t pci_status;
pciConfigInWord(de->pciBus, de->pciDevice, de->pciFunc, PCI_CFG_STATUS, &pci_status);
pciConfigOutWord(de->pciBus, de->pciDevice, de->pciFunc, PCI_CFG_STATUS, pci_status);
printf("PCI bus error, status=%08x, PCI status=%04x\n",
status, pci_status);
}
}
static int de_refill_rx (struct DEC21143if *de)
{
unsigned i;
for (i = 0; i < DE_RX_RING_SIZE; i++) {
de->rx_ring[i].status = cpu_to_le32(DescOwn);
if (i == (DE_RX_RING_SIZE - 1))
de->rx_ring[i].length =
cpu_to_le32(RingEnd | PKT_BUF_SZ);
else
de->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ);
de->rx_ring[i].buffer1 = 0;
de->rx_ring[i].buffer2 = 0;
}
return 0;
}
static int de_init_rings (struct DEC21143if *de)
{
memset(de->tx_ring, 0, sizeof(struct de_desc) * DE_TX_RING_SIZE);
de->tx_ring[DE_TX_RING_SIZE - 1].length = cpu_to_le32(RingEnd);
de->rx_tail = 0;
de->tx_head = de->tx_tail = 0;
return de_refill_rx (de);
}
/*-----------------------------------------------------------------------------------*/
/*
* ethernetif_init():
*
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
* WARNING: must close all interrupts during init!!!!
/*-----------------------------------------------------------------------------------*/
void dec_init(struct netif *netif)
{
struct DEC21143if *dec21143if;
dec21143if = mem_malloc(sizeof(struct DEC21143if));
netif->state = dec21143if;
netif->name[0] = 'd';
netif->name[1] = 'e';
netif->output = dec_send_packet;
if(dec_pci_init(dec21143if) == OK)
{
printf("dec_pci_init ok\n");
}
de_init_hw(netif);
arp_init();
}
static err_t low_level_send(struct DEC21143if *de,struct pbuf *p)
{
}
static struct pbuf * low_level_receive(struct DEC21143if *de)
{
}
/**
* Send a packet to the RTK8019as from a series of pbuf buffers.
*/
err_t dec_send_packet(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr)
{
struct DEC21143if *dec21143if;
struct pbuf *q;
struct eth_hdr *ethhdr;
struct eth_addr *dest, mcastaddr;
struct ip_addr *queryaddr;
err_t err = 0;
u8_t i;
dec21143if = netif->state;
/* Make room for Ethernet header. */
if(pbuf_header(p, 14) != 0) {
/* The pbuf_header() call shouldn't fail, but we allocate an extra
pbuf just in case. */
q = pbuf_alloc(PBUF_LINK, 14, PBUF_RAM);
if(q == NULL) {
return ERR_MEM;
}
pbuf_chain(q, p);
p = q;
}
/* Construct Ethernet header. Start with looking up deciding which
MAC address to use as a destination address. Broadcasts and
multicasts are special, all other addresses are looked up in the
ARP table. */
queryaddr = ipaddr;
if(ip_addr_isany(ipaddr) || ip_addr_isbroadcast(ipaddr, &(netif->netmask))) {
dest = (struct eth_addr *)ðbroadcast;
}
else if(ip_addr_ismulticast(ipaddr)) {
/* Hash IP multicast address to MAC address. */
mcastaddr.addr[0] = 0x01;
mcastaddr.addr[1] = 0x0;
mcastaddr.addr[2] = 0x5e;
mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
mcastaddr.addr[4] = ip4_addr3(ipaddr);
mcastaddr.addr[5] = ip4_addr4(ipaddr);
dest = &mcastaddr;
} else {
if(ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
/* Use destination IP address if the destination is on the same
subnet as we are. */
queryaddr = ipaddr;
} else {
/* Otherwise we use the default router as the address to send
the Ethernet frame to. */
queryaddr = &(netif->gw);
}
dest = arp_lookup(queryaddr);
}
/* If the arp_lookup() didn't find an address, we send out an ARP
query for the IP address. */
if(dest == NULL) {
q = arp_query(netif, dec21143if->ethaddr, queryaddr);
if(q != NULL) {
low_level_send(dec21143if, q);
pbuf_free(q);
return err;
}
return ERR_MEM;
}
ethhdr = p->payload;
for(i = 0; i < 6; i++) {
ethhdr->dest.addr[i] = dest->addr[i];
ethhdr->src.addr[i] = dec21143if->ethaddr->addr[i];
}
ethhdr->type = htons(ETHTYPE_IP);
return low_level_send(dec21143if, p);
}
/**
* Read a packet, clearing overflows.
*/
void dec_recv_packet(struct netif *netif)
{
struct DEC21143if *dec21143if;
struct eth_hdr *ethhdr;
struct pbuf *p = NULL;
dec21143if = netif->state;
p = low_level_receive(dec21143if);
if(p == NULL) {
return;
}
ethhdr = p->payload;
switch(htons(ethhdr->type)) {
case ETHTYPE_IP:
arp_ip_input(netif, p);
pbuf_header(p, -14);
netif->input(p, netif);
break;
case ETHTYPE_ARP:
p = arp_arp_input(netif, dec21143if->ethaddr, p);
if(p != NULL) {
low_level_send(dec21143if, p);
pbuf_free(p);
}
break;
default:
pbuf_free(p);
break;
}
}
int dec_pci_init(struct DEC21143if *deif)
{
u32_t pciBus; /* PCI Bus number */
u32_t pciDevice; /* PCI Device number */
u32_t pciFunc; /* PCI Function number */
u32_t membaseCsr; /* Base Address Register 1 */
u32_t iobaseCsr; /* Base Address Register 0 */
char irq; /* Interrupt Request Level */
int i;
unsigned char temp[600];
int sa_offset=0;
if (pciFindDevice (PCI_VENDOR_ID_DEC,PCI_DEVICE_ID_DEC_21143,
0, &pciBus, &pciDevice, &pciFunc) == ERROR)
{
return ERROR;
}
deif->pciBus = pciBus;
deif->pciDevice = pciDevice;
deif->pciFunc = pciFunc;
/* get memory base address and IO base address */
pciConfigInLong (deif->pciBus, deif->pciDevice, deif->pciFunc,
PCI_CFG_BASE_ADDRESS_0, &iobaseCsr);
pciConfigInLong (deif->pciBus, deif->pciDevice, deif->pciFunc,
PCI_CFG_BASE_ADDRESS_1, &membaseCsr);
pciConfigInByte (deif->pciBus, deif->pciDevice, deif->pciFunc,
PCI_CFG_DEV_INT_LINE, &irq);
membaseCsr &= PCI_MEMBASE_MASK;
iobaseCsr &= PCI_IOBASE_MASK ;
/* overwrite the resource table with read value */
deif->membaseCsr = membaseCsr ;
deif->iobaseCsr = iobaseCsr ;
deif->irq = irq;
deif->irqvec = IVEC_TO_INUM(irq);
pciConfigOutWord (pciBus, pciDevice, pciFunc, PCI_CFG_COMMAND,
PCI_CMD_MEM_ENABLE |
PCI_CMD_MASTER_ENABLE);
pciConfigOutByte (pciBus, pciDevice, pciFunc, PCI_CFG_MODE, SLEEP_MODE_DIS);
pciConfigOutByte (pciBus, pciDevice, pciFunc, PCI_CFG_LATENCY_TIMER, 0x30);
temp[0] = tulip_read_eeprom(deif->membaseCsr, 0xff, 8) & 0x40000 ? 8 : 6;
printf("ee_addr_size=%08x\n",temp[0]);
printf("deif->membaseCsr=%08x ",deif->membaseCsr);
printf("deif->iobaseCsr=%08x ",deif->iobaseCsr);
printf("deif->irq=%d ",deif->irq);
for(i=0; i<256; i++)
{
((u16_t*)temp)[i] = tulip_read_eeprom(deif->membaseCsr, i,6);
}
for (i = 0; i < 8; i ++)
if (temp[i] != temp[16+i])
sa_offset = 20;
/* ethbroadcast = *(struct eth_addr*)&temp[sa_offset];*/
printf("dec %x:%x:%x:%x:%x:%x\n",ethbroadcast.addr[0],ethbroadcast.addr[1],ethbroadcast.addr[2],ethbroadcast.addr[3],ethbroadcast.addr[4],ethbroadcast.addr[5]);
return (OK);
}