?? sysln97xend.c
字號:
/*
DESCRIPTION
This is the WRS-supplied configuration module for the VxWorks
ln97xEnd (lnPci) END driver. It performs the dynamic parameterization
of the ln97xEnd driver. This technique of 'just-in-time'
parameterization allows driver parameter values to be declared
as any other defined constants rather than as static strings.
*/
/* includes */
#if (defined (INCLUDE_LN_97X_END) && defined (INCLUDE_NETWORK) \
&& defined (INCLUDE_END))
#include "vxWorks.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "end.h"
#include "config.h"
#include "i2c_export.h"
#include "sysI2C.h"
#include "ln97xEnd.h"
#include "bsp8240.h"
/* defines */
/* AMD 7997x 10/100Base-TX Board type */
#define LN_TYPE_970 1 /* AMD 97c970 PCI Ethernet PCNet */
#define LN_TYPE_971 2 /* AMD 97c970 PCI Ethernet PCNet Fast */
#define LN_TYPE_972 3 /* AMD 97c970 PCI Ethernet PCNet Fast+ */
#define LN_TYPE_7990 4
#define LN97X_MAX_UNITS 8 /* number of board types */
/* LN970 driver user flags */
#define LN_USR_FLAGS_970 0
#define LN_USR_FLAGS_971 0
#define LN_USR_FLAGS_972 0
#define LN_USR_FLAGS_7990 0
/* PCI vendor/device Ids and rev mask */
#define LN97X_PCI_VENDOR_ID 0x1022 /* AMD */
#define LN97X_PCI_DEVICE_ID 0x2000 /* PCI device ID */
#define LN7990_PCI_DEVICE_ID 0x0000 /* PCI device ID */
#define LN970_PCI_REV_MASK 0x10 /* 79970 pci rev mask */
#define LN971_PCI_REV_MASK 0x20 /* 79971 pci rev mask */
#define LN972_PCI_REV_MASK 0x30 /* 79972 pci rev mask */
#define LN97X_CSR3_VALUE CSR3_DXSUFLO /* 0 csr3 value */
#define CSR3_DXSUFLO 0x0040 /* Disable Transmit Stop on Underflow */
/*
* default values if PCI_CFG_TYPE defined to be PCI_CFG_FORCE
* note: memory addresses must be aligned on MMU page boundaries
*/
#define LN97X_IO_ADR0 0xf400
#define LN97X_MEM_ADR0 0xfd000000
#define LN97X_INT_LVL0 0x04
#define LN97X_INT_VEC0 0x04
#define LN97X_IO_ADR1 0xf420
#define LN97X_MEM_ADR1 0xfd200000
#define LN97X_INT_LVL1 0x02
#define LN97X_INT_VEC1 0x02
#define LN97X_IO_ADR2 0xf440
#define LN97X_MEM_ADR2 0xfd300000
#define LN97X_INT_LVL2 0x01
#define LN97X_INT_VEC2 0x01
#define LN97X_IO_ADR3 0xf460
#define LN97X_MEM_ADR3 0xfd400000
#define LN97X_INT_LVL3 0x0
#define LN97X_INT_VEC3 0
#define LN97X_MAX_DEV 1
#define NET_END_USER_FLAGS LN_USR_FLAGS_972
#define NET_ADAPTER_VENDOR_ID LN97X_PCI_VENDOR_ID
#define NET_ADAPTER_DEVICE_ID LN97X_PCI_DEVICE_ID
#define LN_97X_LOAD_FUNC ln97xEndLoad
/* externs */
IMPORT END_OBJ* ln97xEndLoad (char *);
/* typedefs */
typedef struct ln97xPciRsrc /* LN97X_PCI_RSRC */
{
UINT32 iobaseCsr; /* Base Address Register 0 */
UINT32 membaseCsr; /* Base Address Register 1 */
char irq; /* Interrupt Request Level */
UINT32 irqvec; /* Interrupt Request vector */
UINT32 configType; /* type of configuration */
UINT32 boardType; /* type of LAN board this unit is */
UINT32 pciBus; /* PCI Bus number */
UINT32 pciDevice; /* PCI Device number */
UINT32 pciFunc; /* PCI Function number */
} LN97X_PCI_RSRC;
typedef struct boardResource /* LN97X_BRD_RSRC */
{
UINT32 type; /* type of the board */
UINT32 vendorId; /* Vendor ID */
UINT32 deviceId; /* Device ID */
UINT32 lnUsrFlags; /* LN driver user flags */
FUNCPTR mediaSelectFunc; /* media select routine */
} LN97X_BRD_RSRC;
/* locals */
LOCAL int ln97XUnits = 0;
LOCAL LN97X_PCI_RSRC * pRsrc; /* pointer board resources */
/*
* This array defines the board-specific PCI resources, the base address
* register configuration mode and the Ethernet adapter type. It's indexed
* using the device number returned from pciFindDevice().
*/
LOCAL LN97X_PCI_RSRC ln97xPciRsrcs [LN97X_MAX_DEV] =
{
{LN97X_IO_ADR0, LN97X_MEM_ADR0, LN97X_INT_LVL0, LN97X_INT_VEC0,
PCI_CFG_TYPE, LN_TYPE_970, 0, 0, 0}
};
/*
* This array defines board-specific vendor and device ids, flags to pass to
* the drive load routine and the function used to select the media.
*/
LOCAL LN97X_BRD_RSRC ln97xBrdRsrc [LN97X_MAX_UNITS] =
{
{LN_TYPE_970, LN97X_PCI_VENDOR_ID, LN97X_PCI_DEVICE_ID, LN_USR_FLAGS_970, NULL}
};
void findLan97xEnetInt(void);
/******************************************************************************
*
* sysLn97xEndLoad - load and create load string, for a ln97x (lnPci) device.
*
* This routine loads the lnPci device with initial parameters.
*
* RETURNS: pointer to END object or ERROR.
*
* SEE ALSO: ln97xEndLoad()
*/
END_OBJ * sysLn97xEndLoad
(
char * pParamStr, /* ptr to initialization parameter string */
void * unused /* unused optional argument */
)
{
/*
* The ln97xEnd driver END_LOAD_STRING should be:
* <unit>:<devMemAddr>:<devIoAddr>:<pciMemBase:<vecNum>:<intLvl>:<memAdrs>:
* <memSize>:<memWidth>:<csr3b>:<offset>:<flags>
*
* Note that ln97xEnd unit number is prepended in muxDevLoad, so we
* don't put it here!
*/
char * cp;
char paramStr [END_INIT_STR_MAX]; /* from end.h */
END_OBJ * pEnd;
static char ln97xParamTemplate[] =
"0x%x:0x%x:0x%x:%d:%d:-1:-1:-1:0x%x:%d:0x%x";
if (strlen (pParamStr) == 0)
{
/*
* muxDevLoad() calls us twice. If the string is
* zero length, then this is the first time through
* this routine, so we just return.
*/
pEnd = ln97xEndLoad (pParamStr);
}
else
{
/*
* On the second pass though here, we actually create
* the initialization parameter string on the fly.
* Note that we will be handed our unit number on the
* second pass through and we need to preserve that information.
* So we use the unit number handed from the input string.
*/
cp = strcpy (paramStr, pParamStr); /* cp points to paramStr */
/* Now, we advance cp, by finding the end the string */
cp += strlen (paramStr);
/* finish off the initialization parameter string */
sprintf (cp, ln97xParamTemplate,
/* device memory Io base */
(UINT) PCI_MEMIO2LOCAL (pRsrc->membaseCsr),
/* device Io base */
(UINT) PCI_IO2LOCAL (pRsrc->iobaseCsr),
(UINT) PCI_SLV_MEM_LOCAL, /* pciMemBase */
pRsrc->irqvec, /* interrupt IRQ vector */
pRsrc->irq, /* interrupt irq number */
LN97X_CSR3_VALUE, /* csr3 register value */
0, /* offset */
NET_END_USER_FLAGS /* flags */
);
if ((pEnd = ln97xEndLoad (paramStr)) == (END_OBJ *)ERROR)
{
printf ("Error: device failed ln97xEndLoad routine.\n");
}
}
return (pEnd);
}
/*******************************************************************************
*
* sysLan97xPciInit - prepare LAN adapter for LN97X initialization
*
* This routine finds out the PCI device, maps its memory and IO address.
* It must be done prior to initializing the LN970, sysLn97XInit(). Also
* must be done prior to MMU initialization, usrMmuInit().
*
* RETURNS: OK/ERROR
*/
STATUS sysLan97xPciInit (void)
{
UINT32 membaseCsr;
UINT32 iobaseCsr;
int pciBus;
int pciDevice;
int pciFunc;
int unit;
int found = 0;
/* for all the support lan devices find if some of them exist */
for (unit = 0; unit < LN97X_MAX_UNITS; unit++)
{
if (pciFindDevice (ln97xBrdRsrc [unit].vendorId,
ln97xBrdRsrc [unit].deviceId,
unit, &pciBus, &pciDevice, &pciFunc) == OK)
{
/* board detected */
/* for now, we're ignoring the possibility of duplicates */
found = TRUE;
/* load up the PCI device table */
pRsrc = ln97xPciRsrcs + ln97XUnits; /* get the pci entry */
pRsrc->pciBus = pciBus;
pRsrc->pciDevice = pciDevice;
pRsrc->pciFunc = pciFunc;
ln97XUnits++; /* number of units found */
}
}
if ((found != TRUE) || (pciDevice > PCI_MAX_DEV))
return (ERROR);
/* Now initialize all the units we found */
for (unit = 0; unit < ln97XUnits; unit++)
{
/* Fill in the resource entry */
pRsrc = ln97xPciRsrcs + unit;
if (pRsrc->configType == PCI_CFG_FORCE)
{
/* write the iobase, membase, and irq */
pciConfigOutLong (pRsrc->pciBus, pRsrc->pciDevice, pRsrc->pciFunc,
PCI_CFG_BASE_ADDRESS_0, pRsrc->iobaseCsr |
PCI_BASE_IO);
pciConfigOutLong (pRsrc->pciBus, pRsrc->pciDevice, pRsrc->pciFunc,
PCI_CFG_BASE_ADDRESS_1, pRsrc->membaseCsr);
}
/*
* get memory base address and IO base address
* Note: we read it in again, even if we just wrote it out because the
* device can change what we wrote
*/
pciConfigInLong (pRsrc->pciBus, pRsrc->pciDevice, pRsrc->pciFunc,
PCI_CFG_BASE_ADDRESS_0, &iobaseCsr);
pciConfigInLong (pRsrc->pciBus, pRsrc->pciDevice, pRsrc->pciFunc,
PCI_CFG_BASE_ADDRESS_1, &membaseCsr);
/*
* mask off registers. IO base needs to be masked off because bit0
* will always be set to 1
*/
membaseCsr &= PCI_MEMBASE_MASK;
iobaseCsr &= PCI_IOBASE_MASK;
/* over write the resource table with values read */
pRsrc->membaseCsr = membaseCsr;
pRsrc->iobaseCsr = iobaseCsr;
/******************************/
/* enable mapped memory and IO addresses */
/* AMD973's mem_map and the IO_map is not enable at the same time */
pciConfigOutWord (pRsrc->pciBus, pRsrc->pciDevice, pRsrc->pciFunc,
PCI_CFG_COMMAND, PCI_CMD_MEM_ENABLE | PCI_CMD_MASTER_ENABLE);
/* disable sleep mode */
pciConfigOutWord (pciBus, pciDevice, pciFunc, PCI_CFG_MODE,
SLEEP_MODE_DIS);
}
return (OK);
}
/*******************************************************************************
*
* sysLan97xIntEnable - enable Lan97x interrupts
*
* This routine enables ln7997x interrupts. This may involve operations on
* interrupt control hardware.
*
* RETURNS: OK or ERROR for invalid arguments.
*/
STATUS sysLan97xIntEnable
(
int level /* level number */
)
{
return (intEnable (level));
}
/*******************************************************************************
*
* sysLan97xIntDisable - disable ln970 interrupts
*
* This routine disables ln970 interrupts. This may involve operations on
* interrupt control hardware.
*
* RETURNS: OK or ERROR for invalid arguments.
*/
STATUS sysLan97xIntDisable
(
int level /* level number */
)
{
return (intDisable(level));
}
/*******************************************************************************
*
* sysLan97xEnetAddrGet - get Ethernet address
*
* This routine provides a target-specific interface for accessing a
* device Ethernet address.
*
* -- Specific to 971 ldt
*
* RETURNS: OK or ERROR if could not be obtained.
*/
STATUS sysLan97xEnetAddrGet
(
LN_97X_DRV_CTRL * pDrvCtrl, /* Driver control */
char * enetAdrs
)
{
UCHAR aprom [LN_97X_APROM_SIZE] = {0,1,2,3,4,5,6}; /* copy of address prom space */
UCHAR eeprom [6] = {0,1,2,3,4,5};
char *ioaddr;
UCHAR ix;
/* get IO address of unit */
ioaddr = (char *)(pDrvCtrl->devAdrs);
/* load aprom into an array */
for (ix=0; ix<32; ix++)
{
aprom [ix] = sysInByte((ULONG)(ioaddr+ ix));
}
/* check for 'w's at end of list */
if ((aprom [0xe] != 'W') || (aprom [0xf] != 'W'))
{
int retry;
if (I2C_Initialize(CPU_I2C_ADDR, I2C_INT_DISABLE, NULL)==I2C_SUCCESS)
{
retry = 3;
while (retry--)
{
if (I2C_do_transaction(I2C_INT_DISABLE, I2C_MASTER_RCV,
I2C_MAIN_CPU_ADD, SYSI2C_BOARD_CONF+0x20,
2, 6, aprom, I2C_STOP, 2, I2C_NO_RESTART)==I2C_SUCCESS)
{
bcopy (aprom, enetAdrs, 6);
return OK;
}
}
}
bcopy (eeprom, enetAdrs, 6);
}
else
bcopy (aprom, enetAdrs, 6);
return (OK);
}
void findLan97xEnetInt(void)
{
struct pciR26Device *p;
if (pciDeviceList != NULL)
{
p = pciDeviceList;
while(p)
{
if((p->pciBusNo == pRsrc->pciBus) && (p->pciDeviceNo == pRsrc->pciDevice) && (p->pciFunctionNo == pRsrc->pciFunc))
{
pRsrc->irq = p->iNum;
pRsrc->irqvec = p->iVec;
break;
}
else
{
p = p->next;
}
}
}
}
#endif/* defined (INCLUDE_LN_97X_END) && defined (INCLUDE_NETWORK) */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -