⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sysln97xend.c

📁 vxWorks下AMD973芯片的驱动源码
💻 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 + -