sysEnd.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:35k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* sysEnd.c - System Enhanced network interface support library */
  2. /* Copyright 2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01e,05sep02,jb3  Merge in changes from w/ t2.1 ongiong development
  8. 01e,01aug02,jb  Removing Dec device support
  9. 01d,30jul02,jb  Removing debug code
  10. 01c,27jun02,jb  Fix warnings
  11. 01b,18jun02,jb  Changing size calculation to allow veloce driver to work
  12. 01a,05jun02,jb  initial version...
  13. */
  14. /*
  15. DESCRIPTION
  16. This file contains the board-specific routines for Ethernet adapter
  17. initialisation of Intel Pro 100+ based adapters.
  18. NOTE
  19. At the time of writing, this module has only been tested with the following
  20. Ethernet cards:
  21.     82559 controller: Intel PRO/100+ Management Adapter
  22.                       Intel InBusiness 10/100 PCI Network Adapter
  23. Refer to the BSP reference entry for any eventual limitations or
  24. problems related to the BSP.
  25. SEE ALSO: ifLib,
  26. .I "Intel 10/100 MBit Ethernet Family Software technical Reference Manual."
  27. */
  28. #include "vxWorks.h"
  29. #include "config.h"
  30. #include "cacheLib.h"
  31. #include "stdio.h"
  32. #ifdef INCLUDE_END
  33. #include "end.h"
  34. #include "netinet/if_ether.h"
  35. #include "drv/end/fei82557End.h"
  36. #include "ixp425Pci.h"
  37. #ifdef END_DEBUG
  38. #undef LOCAL
  39. #define LOCAL
  40. #endif
  41. /* defines */
  42. #define CSR_BASE_MSK 0x7f /* Mask Base Address Register */
  43. #define END_LD_STR_SIZE 80
  44. /* PCI memory base address register configuration mode */
  45. #define FORCE 0x00 /* overwrite membase address register */
  46. #define AUTO 0x01 /* read membase address register */
  47. /*
  48.  * Need to use automatic configuration mode using the resource assigning in
  49.  * pciAssignResources().
  50.  */
  51. #define PCI_REG_MOD AUTO /* define the register configuration mode */
  52. #define TYPE_ALLOC 1000
  53.     /*Everything tested & works fine with a delay of 1, but set to 3 in 
  54.       order to eliminate the possibility of any timing issues with temp. increase etc*/
  55. #define PCI_CONFIG_DELAY 3 
  56.      
  57. /*
  58.  * FEI cards in range 1001 -> 2000
  59.  */
  60. #define FEI_START TYPE_ALLOC + 1
  61. #define PRO100B FEI_START /* Intel EtherExpress PRO-100B PCI */
  62. #define INBUSINESS FEI_START + 1 /* Intel InBusiness 10/100 PCI */
  63. #define XX82559ER  FEI_START + 100 /* Arbitrary card with 82559ER */
  64. #define BOARD_TYPE_NB (NELEMENTS(boardResources))
  65. #ifdef INCLUDE_FEI82557END
  66. /*the following two are tunable parameters which specify the number of transmit and receive buffers
  67.   to be allocated for use by an fei (82559) driver. These must never be set below 2, otherwise the 
  68.   driver will assume a default of 32, and our calculations of how much memory to allocate for the 
  69.   driver will be in error*/
  70. #define FEI_N_RDFS         32
  71. #define FEI_N_TFDS         32
  72. /*
  73.  * FEI_RFD_MULTIPLIER is the multiplier that is applied to the number of RFDs requested
  74.  * to determine the number of "spares" available for loaning to the network
  75.  * stack. This value (4) was taken from the fei driver source code (its not
  76.  * available in the header, so if this changes in future versions of the driver
  77.  * this will break - if it is increased the driver will complain that we have not
  78.  * given it enough memory, if it is decreased everything will work but we will be 
  79.  * wasting SDRAM.
  80.  */
  81. #define FEI_RFD_MULTIPLIER 4
  82. #define FEI_N_RFD_LOAN     (FEI_N_RDFS * FEI_RFD_MULTIPLIER)
  83. /*
  84.  * Again  FEI_CL_OVERHEAD has been taken from the fei source code (not specified in header),
  85.  * so the caveats for the FEI_RFD_MULTIPLIER apply here too
  86.  */
  87. #define FEI_CL_OVERHEAD    4 /* prepended cluster header */
  88. #define FEI_CL_RFD_SIZE    (RFD_SIZE + FEI_CL_OVERHEAD)
  89. #define FEI_CFD_SIZE       CFD_SIZE
  90. /*This calculation is taken from the fei driver source, again, if this changes, the driver will 
  91.   either complain that it has not been allocated enough memory, or will work fine but we will
  92.   be wasting SDRAM*/
  93. #define FEI_TOTAL_SIZE     ((FEI_N_RDFS * FEI_CL_RFD_SIZE) + 
  94.                            (FEI_N_RFD_LOAN * FEI_CL_RFD_SIZE) + 
  95.                            (FEI_N_TFDS * (FEI_CFD_SIZE +sizeof(long))) + 4)
  96. /* EEPROM control bits */
  97. #define EE_SK           0x01            /* shift clock */
  98. #define EE_CS           0x02            /* chip select */
  99. #define EE_DI           0x04            /* chip data in */
  100. #define EE_DO           0x08            /* chip data out */
  101. #define EE_ENB         (0x4800 | EE_CS)
  102. /* EEPROM opcode */
  103. #define EE_CMD_WRITE    0x05            /* WRITE opcode, 101 */
  104. #define EE_CMD_READ     0x06            /* READ  opcode, 110 */
  105. #define EE_CMD_ERASE    0x07            /* ERASE opcode, 111 */
  106. #define EE_WRITE_0 0x4802
  107. #define EE_WRITE_1 0x4806
  108. /* EEPROM misc. defines */
  109. #define EE_CMD_BITS     3               /* number of opcode bits */
  110. #define EE_ADDR_BITS    6               /* number of address bits */
  111. #define EE_DATA_BITS    16              /* number of data bits */
  112. #define EE_SIZE         0x40            /* 0x40 words */
  113. #define EE_CHECKSUM     0xbaba          /* checksum */
  114. /* PC compatibility macros */
  115. #define FEI_MEMSIZE0            0x00001000
  116. #define FEI_INIT_STATE_MASK   (VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE | VM_STATE_MASK_BUFFERABLE)
  117. #define FEI_INIT_STATE        (VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT | VM_STATE_BUFFERABLE_NOT)
  118. #define UNKNOWN                 (-1)
  119. /* 82557/9 PCI specific definitions */
  120. /* Intel PRO-100B PCI specific definitions */
  121. #ifndef PRO100B_PCI_VENDOR_ID
  122. #define PRO100B_PCI_VENDOR_ID   0x8086  /* PCI vendor ID */
  123. #define PRO100B_PCI_DEVICE_ID   0x1229  /* PCI device ID */
  124. #endif    /* PRO100B_PCI_VENDOR_ID */
  125. /* Intel InBusiness 10/100 PCI specific definitions */
  126. #ifndef INBUSINESS_PCI_VENDOR_ID
  127. #define INBUSINESS_PCI_VENDOR_ID   PRO100B_PCI_VENDOR_ID  /* PCI vendor ID */
  128. #define INBUSINESS_PCI_DEVICE_ID   0x1030                 /* PCI device ID */
  129. #endif    /* INBUSINESS_PCI_VENDOR_ID */
  130. #define I82559ER_PCI_DEVICE_ID  0x1209
  131. #endif /* INCLUDE_FEI82557END */
  132. /* undef'ed PCI_IO_ADRS_OK here as IXP425 does not properly generate
  133.   read/writes to IO address space, the FEI NIC also maps its IO space to 
  134.   a memory space, and can work without IO transactions
  135. */
  136. #undef PCI_IO_ADRS_OK
  137. /* typedefs */
  138. typedef struct pciResource              /* PCI_RESOURCES */
  139.     {
  140.     UINT32      iobaseCsr;              /* Base Address Register 0 */
  141.     UINT32      membaseCsr;             /* Base Address Register 1 */
  142.     char        irq;                    /* Interrupt Request Level */
  143.     UINT32      irqvec;                 /* Interrupt Request vector */
  144.     UINT32      configType;             /* type of configuration */
  145.     void *      buf;                    /* any allocated buffer space */
  146.     UINT32      cpuToPciOffset;         /* Any offset from CPU to PCI address */
  147.     } PCI_RESOURCES;
  148. typedef struct boardResource /* BOARD_RESOURCES */
  149.     {
  150.     UINT32  type;                   /* type of the board */
  151.     UINT32  vendorId;               /* Vendor ID */
  152.     UINT32  deviceId;               /* Device ID */
  153.     UINT32  decUsrFlags;            /* DEC driver user flags */
  154.     } BOARD_RESOURCES;
  155. #ifdef INCLUDE_FEI82557END
  156. typedef struct feiResource              /* FEI_RESOURCE */
  157.     {
  158.     UINT32      membaseCsr;             /* Base Address Register 0 */
  159.     UINT32      iobaseCsr;              /* Base Address Register 1 */
  160.     UINT32      membaseFlash;           /* Base Address Register 2 */
  161.     char        irq;                    /* Interrupt Request Level */
  162.     UINT32      configType;             /* type of configuration */
  163.     UINT32      boardType;              /* type of LAN board this unit is */
  164.     UINT32      pciBus;                 /* PCI Bus number */
  165.     UINT32      pciDevice;              /* PCI Device number */
  166.     UINT32      pciFunc;                /* PCI Function number */
  167.     UINT16      eeprom[0x40];           /* Ethernet Address of this unit */
  168.     INT32       timeout;                /* timeout for the self-test */
  169.     INT32       str[6];                 /* storage for the self-test result */
  170.     volatile INT32 * pResults;          /* pointer to the self-test result */
  171.     UINT        memLength;              /* required memory size */
  172.     UINT        initialStateMask;       /* mask parameter to vmStateSet */
  173.     UINT        initialState;           /* state parameter to vmStateSet */
  174.     } FEI_RESOURCE;
  175. #endif
  176. /* locals */
  177. /*
  178.  * This array defines the board-specific PCI resources, the base address
  179.  * register configuration mode and the Ethernet adapter type. It's indexed
  180.  * using the device number returned from pciFindDevice().
  181.  *
  182.  * The mode is set as AUTO so this will be erased by the configuration read
  183.  * from the card that is effectively set by pciAssignResources(). See
  184.  * sysLanPciInit() for this.
  185.  */
  186. LOCAL PCI_RESOURCES pciResources [IXP425_PCI_MAX_DEV] =
  187.     {
  188.     {PCI_IO_ADR0, PCI_MEM_ADR0, PCI_INT_LVL0, PCI_INT_VEC0, PCI_REG_MOD, 0, 0},
  189.     {PCI_IO_ADR1, PCI_MEM_ADR1, PCI_INT_LVL1, PCI_INT_VEC1, PCI_REG_MOD, 0, 0},
  190.     {PCI_IO_ADR2, PCI_MEM_ADR2, PCI_INT_LVL2, PCI_INT_VEC2, PCI_REG_MOD, 0, 0},
  191.     {PCI_IO_ADR3, PCI_MEM_ADR3, PCI_INT_LVL3, PCI_INT_VEC3, PCI_REG_MOD, 0, 0}
  192.     };
  193. /*
  194.  * This array defines board-specific vendor and device ids, flags to pass to
  195.  * the drive load routine and the function used to select the media.
  196.  */
  197. LOCAL BOARD_RESOURCES boardResources [] =
  198.     {
  199. #ifdef INCLUDE_FEI82557END
  200.     {PRO100B, PRO100B_PCI_VENDOR_ID, PRO100B_PCI_DEVICE_ID, 0},
  201.     {INBUSINESS, INBUSINESS_PCI_VENDOR_ID, INBUSINESS_PCI_DEVICE_ID, 0},
  202.     {XX82559ER, PRO100B_PCI_VENDOR_ID, I82559ER_PCI_DEVICE_ID, 0},
  203. #endif /* INCLUDE_FEI82557END */
  204.     };
  205. /* END load strings */
  206. LOCAL char endLoadStr[IXP425_PCI_MAX_DEV][END_LD_STR_SIZE];
  207. /* Index of devices */
  208. LOCAL int       currentEndDevice        = 0;
  209. #ifdef INCLUDE_FEI82557END
  210. LOCAL UINT32 feiUnits;                  /* number of FEIs we found */
  211. LOCAL FEI_RESOURCE feiResources [IXP425_PCI_MAX_DEV] =
  212.     {
  213.     {UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN,
  214.      UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, {UNKNOWN}, UNKNOWN,
  215.      {UNKNOWN}, NULL, FEI_MEMSIZE0, FEI_INIT_STATE_MASK, FEI_INIT_STATE},
  216.     {UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN,
  217.      UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, {UNKNOWN}, UNKNOWN,
  218.      {UNKNOWN}, NULL, FEI_MEMSIZE0, FEI_INIT_STATE_MASK, FEI_INIT_STATE},
  219.     {UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN,
  220.      UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, {UNKNOWN}, UNKNOWN,
  221.      {UNKNOWN}, NULL, FEI_MEMSIZE0, FEI_INIT_STATE_MASK, FEI_INIT_STATE},
  222.     {UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN,
  223.      UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, {UNKNOWN}, UNKNOWN,
  224.      {UNKNOWN}, NULL, FEI_MEMSIZE0, FEI_INIT_STATE_MASK, FEI_INIT_STATE}
  225.     };
  226. LOCAL const char * phys[] =
  227.     {
  228.     "None", "i82553-A/B", "i82553-C", "i82503",
  229.     "DP83840", "80c240", "80c24", "i82555",
  230.     "unknown-8", "unknown-9", "DP83840A", "unknown-11",
  231.     "unknown-12", "unknown-13", "unknown-14", "unknown-15"
  232.     };
  233. enum phy_chips
  234.     {
  235.     NonSuchPhy=0, I82553AB, I82553C, I82503,
  236.     DP83840, S80C240, S80C24, I82555, DP83840A=10, UndefinedPhy
  237.     };
  238. LOCAL const char *connectors[] = {" RJ45", " BNC", " AUI", " MII"};
  239. #endif /* INCLUDE_FEI82557END */
  240. /* imports */
  241. /* End device table - should be IXP425_PCI_MAX_DEV+1 entries */
  242. IMPORT END_TBL_ENTRY endDevTbl[];
  243. #ifdef INCLUDE_FEI82557END
  244. /* FEI specific imports */
  245. IMPORT FUNCPTR  feiEndIntConnect;
  246. IMPORT FUNCPTR  feiEndIntDisconnect;
  247. IMPORT END_OBJ* fei82557EndLoad (char *, void *);
  248. IMPORT void sysFlashBoardDelay (void);
  249. /*extern void sysDelay(void);*/
  250. extern void sysMicroDelay(int microseconds);
  251. /* forward declarations */
  252. LOCAL UINT16    sys557eepromRead (int unit, int location);
  253. LOCAL UINT32    sys557mdioRead   (int unit, int phyId, int location);
  254. LOCAL UINT32    sys557mdioWrite  (int unit, int phyId, int location, int value);
  255. LOCAL int       sys557IntEnable  (int unit);
  256. LOCAL int       sys557IntDisable (int unit);
  257. LOCAL int       sys557IntAck     (int unit);
  258. UINT32 sys557EndPhysToPci ( int unit, UINT32 PhysAddr);
  259. UINT32 sys557EndPciToPhys ( int unit, UINT32 PhysAddr);
  260. #endif /* INCLUDE_FEI82557END */
  261. #define SWAP16(x) ((((x) << 8) | ((x) >> 8)) & 0xFFFF)
  262. #define SWAP32(x)               
  263.   (((x) << 24) |                
  264.   (((x) & 0x0000FF00) << 8) |   
  265.   (((x) & 0x00FF0000) >> 8) |   
  266.   (((unsigned int)(x)) >> 24))
  267. #ifdef PCI_IO_ADRS_OK
  268. #define sysPciOutWord(addr,data)   PCI_OUT_WORD((void*)(addr-IXP425_PHYS_PCI_IO_BASE),data)
  269. #define sysPciOutLong(addr,data)   PCI_OUT_LONG((void*)(addr-IXP425_PHYS_PCI_IO_BASE),data)
  270. #else
  271. #ifdef IXP425_PCI_ENABLE_BYTE_ROUTING
  272. #define sysPciOutWord(addr,data)   *(volatile UINT16*)((addr)) = SWAP16((UINT16)data)
  273. #define sysPciOutLong(addr,data)   *(volatile UINT32*)((addr)) = SWAP32((UINT32)data)
  274. #else
  275. #define sysPciOutWord(addr,data)   *((volatile UINT16*)((addr) & ~3)) = (UINT16)data
  276. #define sysPciOutLong(addr,data)   *(volatile UINT32*)((addr)) = (UINT32)data
  277. #endif
  278. #endif /*PCI_IO_ADRS_OK*/
  279. /*because we do not return read values as return codes in our
  280.   pci IO config library, we must define these as functions, not macros*/
  281. UINT16 sysInWord(ULONG addr)
  282. {
  283. #ifdef PCI_IO_ADRS_OK
  284.     UINT16 retval;
  285.     pciIOInWord((void*)(addr-IXP425_PHYS_PCI_IO_BASE), &retval);
  286.     return retval;
  287. #else
  288.     UINT32 val;
  289.     UINT16 retval;
  290.     if (addr & 3)
  291.     {
  292. addr=addr & ~3; /*round down to 32 bit align*/
  293. val = *((UINT32*)addr);
  294. #ifdef IXP425_PCI_ENABLE_BYTE_ROUTING
  295. val = SWAP32(val); 
  296. #endif
  297. retval = val >> 16;
  298. return retval;
  299.     }
  300.     else
  301.     {
  302. return *((UINT16*)addr);
  303.     }
  304. #endif /*PCI_IO_ADRS_OK*/
  305. }
  306. ULONG sysInLong(ULONG addr)
  307. {
  308. #ifdef PCI_IO_ADRS_OK
  309.     ULONG retval;
  310.     pciIOInLong((void*)(addr-IXP425_PHYS_PCI_IO_BASE), &retval);
  311.     return retval;
  312. #else
  313. #ifdef IXP425_PCI_ENABLE_BYTE_ROUTING
  314.     return SWAP32(*((ULONG*)addr));
  315. #else
  316.     return *((ULONG*)addr);
  317. #endif
  318. #endif
  319. }
  320. /*******************************************************************************
  321. *
  322. * sysLanPciInit - prepare LAN adapter for initialization
  323. *
  324. * This routine find out the PCI device, and map its memory and I/O address.
  325. * It will understand both DEC21x4x and FEI type cards.
  326. *
  327. * RETURNS: N/A
  328. */
  329. STATUS sysLanPciInit (void)
  330. {
  331.     PciDevice *         pDev;           /* Pci resources */
  332.     PCI_RESOURCES * pRsrc; /* dec resource */
  333.     UINT32 pciBus; /* PCI Bus number */
  334.     UINT32 pciDevice = 0; /* PCI Device number */
  335.     UINT32 pciFunc; /* PCI Function number */
  336.     unsigned int ix; /* counter */
  337.     int iy; /* counter */
  338.     int unit = 0; /* unit numbers */
  339.     UINT32 boardType = NONE; /* board type detected */
  340. #ifdef INCLUDE_FEI82557END
  341.     FEI_RESOURCE *      pFeiRes;        /* FEI specific info */
  342. #ifndef  IXP425_PCI_SIMPLE_MAPPING
  343.     void* feiMemBase=NULL;
  344. #endif
  345. #endif
  346.     /* Setup Interrupt Pointers */
  347.     feiEndIntConnect = (FUNCPTR) pciIntConnect;
  348.     feiEndIntDisconnect = (FUNCPTR) pciIntDisconnect;
  349.     /* Find the first empty entry in the endDevTable*/
  350.     while(endDevTbl[currentEndDevice].endLoadFunc != END_TBL_END)
  351.     {
  352. currentEndDevice++;
  353.     }
  354.     /*
  355.      * The following code tries to automatically detect and configure
  356.      * all instances of supported Ethernet cards.
  357.      */
  358.     for (ix = 0; ix < BOARD_TYPE_NB; ix++)
  359.         {
  360.         for (iy = 0; iy < IXP425_PCI_MAX_DEV; iy++)
  361.             {
  362.             if( (pDev = pciDeviceGet(boardResources[ix].vendorId,
  363.                    boardResources[ix].deviceId, iy) ) == NULL)
  364.                 break; /* skip to next vendor/product pair */
  365.             if( pDev->error == TRUE )
  366.                 {
  367.                 break;  /* Something wrong here */
  368.                 }
  369.             /* board detected */
  370.             boardType = boardResources[ix].type;
  371.             pciBus = pDev->bus;
  372.             pciDevice = pDev->device;
  373.             pciFunc = pDev->func;
  374.             /*
  375.              * Update the END device table
  376.              *
  377.              * pciDevice for PCI cards plugged in is in the range 5 to 8.
  378.              */
  379.             pRsrc = &(pciResources[pciDevice]);
  380.             /* We only do Auto Configuration */
  381.             /* get memory base address and I/O base address */
  382. #ifdef INCLUDE_FEI82557END
  383.             if ((boardType >= FEI_START) &&
  384.                  (boardType < (FEI_START + TYPE_ALLOC)))
  385.                 {
  386.                 pFeiRes = &feiResources [unit];
  387.                 pFeiRes->pciBus    = pciBus;
  388.                 pFeiRes->pciDevice = pciDevice;
  389.                 pFeiRes->pciFunc   = pciFunc;
  390.                 pFeiRes->membaseCsr = pDev->bar[0].address;
  391.                 /* Convert to CPU address */
  392.                 pFeiRes->membaseCsr += CPU_PCI_MEM_ADRS;
  393. #ifdef PCI_IO_ADRS_OK
  394.                 pFeiRes->iobaseCsr = pDev->bar[1].address;
  395.                 pFeiRes->iobaseCsr &= ~PCI_BASE_IO;
  396.                 pFeiRes->iobaseCsr += CPU_PCI_IO_ADRS;
  397. #else
  398.                 pFeiRes->iobaseCsr = pFeiRes->membaseCsr;
  399. #endif
  400.                 pFeiRes->membaseFlash = pDev->bar[2].address;
  401.                 pFeiRes->membaseFlash += CPU_PCI_MEM_ADRS;
  402.                 pFeiRes->irq = pDev->irq;
  403.  
  404.                 pFeiRes->configType = boardType;
  405.                 }
  406. #endif /* INCLUDE_FEI82557END */
  407.             /*
  408.              * Update the END device table & dynamically create the load
  409.              * string we need for this device
  410.              */
  411. #ifdef INCLUDE_FEI82557END
  412.             if ((boardType >= FEI_START) &&
  413.                 (boardType < (FEI_START + TYPE_ALLOC)))
  414.                 {
  415.                 pRsrc->buf = (void *)NONE;
  416. #ifndef  IXP425_PCI_SIMPLE_MAPPING
  417. /*allocate memory for FEI END device*/
  418. feiMemBase = cacheDmaMalloc(FEI_TOTAL_SIZE);
  419. if (feiMemBase == NULL)
  420. {
  421.     return ERROR;
  422. }
  423.                 sprintf (endLoadStr[currentEndDevice],
  424.                         "0x%x:0x%x:0x%x:0x%x:0x00:2", (UINT32)feiMemBase
  425. , (UINT32)FEI_TOTAL_SIZE, (UINT32)FEI_N_TFDS, (UINT32)FEI_N_RDFS);
  426. /* set up BAR in PCI controller so that the PCI device can access
  427.    the memory that has just been set up for it*/
  428. if(sysPciMappingAdd((UINT32)feiMemBase, FEI_TOTAL_SIZE)!=OK)
  429. {
  430.     printf("sysPciMappingAdd failed in sysLanPciInitn");
  431.     return ERROR;
  432. }
  433. #else
  434.                 sprintf (endLoadStr[currentEndDevice],
  435.                         "-1:0x00:0x20:0x20:0x00:2");
  436. #endif 
  437.                 endDevTbl[currentEndDevice].unit = unit++;
  438.                 endDevTbl[currentEndDevice].endLoadFunc = fei82557EndLoad;
  439.                 endDevTbl[currentEndDevice].endLoadString =
  440.                                                 endLoadStr[currentEndDevice];
  441.                 endDevTbl[currentEndDevice].endLoan = 1;
  442.                 currentEndDevice++;
  443.                 /* enable mapped I/O addresses */
  444.                 pciConfigOutWord (pciBus, pciDevice, pciFunc,
  445.                           PCI_CFG_COMMAND, PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE |
  446.                           PCI_CMD_MASTER_ENABLE);
  447.                 feiUnits++;
  448.                 }
  449. #endif /* INCLUDE_FEI82557END */
  450.             }
  451.         }
  452.     return OK;
  453.     }
  454. #ifdef INCLUDE_FEI82557END
  455. /*******************************************************************************
  456. *
  457. * sys557Init - prepare LAN adapter for 82557 initialization
  458. *
  459. * This routine is expected to perform any adapter-specific or target-specific
  460. * initialization that must be done prior to initializing the 82557.
  461. *
  462. * The 82557 driver calls this routine from the driver attach routine before
  463. * any other routines in this library.
  464. *
  465. * This routine returns the interrupt level the <pIntLvl> parameter.
  466. *
  467. * RETURNS: OK or ERROR if the adapter could not be prepared for initialization.
  468. */
  469. STATUS sys557Init
  470.     (
  471.     int unit, /* unit number */
  472.     FEI_BOARD_INFO * pBoard     /* board information for the end driver */
  473.     )
  474. {
  475.     volatile FEI_RESOURCE * pReso = &feiResources [unit];
  476.     UINT16 sum          = 0;
  477.     int ix;
  478.     int iy;
  479.     UINT16 value;
  480.     void * testbuf = 0; /* keep compiler quiet */
  481. #ifdef PCI_END_DEBUG
  482.     int errors;
  483.     UINT32 testrepeat = 1000;
  484. #endif
  485.     /*
  486.      * Locate the 82557 based adapter - PRO100B, INBUSINESS and XXX.
  487.      * Note that since the INBUSINESS adapter is based upon the PRO100B
  488.      * board type, it is initialised and driven like one.
  489.      */
  490.     
  491.     if (pReso->boardType != UNKNOWN) /* only setup once */
  492. {
  493. }
  494.     else
  495. {
  496. /* read the configuration in EEPROM */
  497. #ifdef PCI_END_DEBUG
  498.     printf("RFD_SIZE = 0x%xn",RFD_SIZE);
  499.     printf("CFD_SIZE    = 0x%xn",CFD_SIZE); 
  500.     printf("TOTAL FEI STORAGE: 0x%xn",FEI_TOTAL_SIZE);
  501.     errors=0;
  502.     for(ix=0;ix<testrepeat; ix++)
  503.     {
  504. value = sys557eepromRead (unit, 0);
  505. if(value != 0x0200)
  506. {
  507.     errors++;
  508. }
  509.     }
  510.     printf("Test of eeprom read resulted in %d errors from %d readsn",errors,testrepeat);
  511. #endif
  512.     for (ix = 0; ix < EE_SIZE; ix++)
  513.     {
  514.     value = sys557eepromRead (unit, ix);
  515.     pReso->eeprom[ix] = value;         
  516.     sum += value;
  517. #ifdef PCI_END_DEBUG
  518.     printf("%4.4x ", value);
  519.     if(ix % 4 ==0)
  520.     {
  521. printf("n");
  522.     }
  523. #endif
  524.     }
  525.   
  526. if (sum != EE_CHECKSUM)
  527. {
  528.             printf ("nfei%d: Invalid EEPROM checksum %#4.4xn", unit, sum);
  529. }
  530. /* DP83840 specific setup */
  531. if (((pReso->eeprom[6]>>8) & 0x3f) == DP83840)
  532.     {
  533.     int reg23 = sys557mdioRead (unit, pReso->eeprom[6] & 0x1f, 23);
  534.     sys557mdioWrite (unit, pReso->eeprom[6] & 0x1f, 23, reg23 | 0x0420);
  535.     }
  536. /* perform a system self-test. */
  537.         pReso->timeout = 16000; /* Timeout for self-test. */
  538. /*
  539.  * No specific area specified, so we assume that cacheDmaMalloc() will
  540.  * return a pointer to a suitable area. If the data cache is on,
  541.  * this will be page-aligned, but if the data cache is off, then we
  542.  * will just get whatever malloc returns.
  543.  */
  544. if (testbuf = cacheDmaMalloc (32), testbuf == 0)
  545.     {
  546.     printf("fei%d cacheDmaMalloc failedn", unit);
  547.     return ERROR;
  548.     }
  549. pReso->pResults = (volatile INT32 *)testbuf;
  550. /* The chip requires the results buffer to be 16-byte aligned. */
  551.         pReso->pResults    = (volatile INT32 *)
  552.      ((((int) pReso->pResults) + 0xf) & ~0xf);
  553. /* initialise results buffer */
  554. pReso->pResults[0] = 0;
  555. pReso->pResults[1] = -1;
  556. /* Issue the self-test command */
  557. if(sysPhysToPci((void*)pReso->pResults) == NULL)
  558. {
  559.     printf("pReso->pResults does not reside in an area that the PCI devices can accessn");
  560. }
  561. /*reset the chip*/
  562. sysPciOutLong (pReso->iobaseCsr + 0x8, 0x0);
  563. sysDelay();
  564. /*perform self test*/
  565. sysPciOutLong (pReso->iobaseCsr + 0x8, sysPhysToPci((void*)pReso->pResults) | 1);
  566. #ifdef PCI_END_DEBUG
  567. printf("Asked the PCI NIC to write result of self test to PCI ADDR:0x%xn",(UINT32)sysPhysToPci((void*)pReso->pResults));
  568. printf("AHB address of results: 0x%xn", (UINT32)pReso->pResults);
  569. #endif
  570. /* wait for results */
  571. do
  572.     {
  573.     sysDelay(); /* cause a delay of at least an I/O cycle */
  574.     }
  575. while ((pReso->pResults[1] == -1) && (--pReso->timeout >= 0));
  576. if (pReso->timeout < 0)
  577.         { /* Test optimized out. */
  578.     printf ("Self test failed, status %8.8x:n"
  579.     " Failure to initialize the 82557.n"
  580.     " Verify that the card is a bus-master capable slot.n",
  581.     pReso->pResults[1]);
  582. }
  583. else
  584.         {
  585. #ifdef PCI_END_DEBUG
  586.     printf ("General self-test: %s.n"
  587.     " Serial sub-system self-test: %s.n"
  588.     " Internal registers self-test: %s.n"
  589.     " ROM checksum self-test: %s (%#8.8x).n",
  590.     pReso->pResults[1] & 0x1000 ? "failed" : "passed",
  591.     pReso->pResults[1] & 0x0020 ? "failed" : "passed",
  592.     pReso->pResults[1] & 0x0008 ? "failed" : "passed",
  593.     pReso->pResults[1] & 0x0004 ? "failed" : "passed",
  594.     pReso->pResults[0]);
  595. #endif
  596.         }
  597.         pReso->boardType = PRO100B; /* note that it is now initialised */
  598.         /* Save results so we can refer to them again later */
  599.         pReso->str[0] = pReso->pResults[0];
  600.         pReso->str[1] = pReso->pResults[1];
  601.         cacheDmaFree (testbuf);
  602.         pReso->pResults = pReso->str;
  603. }
  604.     /* initialise the board information structure */
  605.     pBoard->vector   = IVEC_TO_INUM(pReso->irq);
  606.     pBoard->baseAddr   = pReso->iobaseCsr;
  607.     for (ix = 0, iy = 0; ix < 3; ix++)
  608. {
  609. pBoard->enetAddr[iy++] = pReso->eeprom[ix] & 0xff;
  610. pBoard->enetAddr[iy++] = (pReso->eeprom[ix] >> 8) & 0xff;
  611. }
  612.     pBoard->intEnable   = sys557IntEnable;
  613.     pBoard->intDisable   = sys557IntDisable;
  614.     pBoard->intAck   = sys557IntAck;
  615.     /* install address conversion routines for driver
  616.      The fei driver needs these to figure out what addresses it needs to 
  617.     tell the nic to write to (PCI addresses) in order to access the appropriate
  618.     areas of the AHB*/
  619.     pBoard->sysLocalToBus = sys557EndPhysToPci;
  620.     pBoard->sysBusToLocal = sys557EndPciToPhys;
  621. #ifdef FEI_10MB
  622.     pBoard->phySpeed   = NULL;
  623.     pBoard->phyDpx   = NULL;
  624. #endif
  625.     intEnable (pReso->irq);
  626.     return (OK);
  627.     }
  628. /*******************************************************************************
  629. *
  630. * sys557IntAck - acknowledge an 82557 interrupt
  631. *
  632. * This routine performs any 82557 interrupt acknowledge that may be
  633. * required.  This typically involves an operation to some interrupt
  634. * control hardware.
  635. *
  636. * This routine gets called from the 82557 driver's interrupt handler.
  637. *
  638. * This routine assumes that the PCI configuration information has already
  639. * been setup.
  640. *
  641. * RETURNS: OK, or ERROR if the interrupt could not be acknowledged.
  642. */
  643. LOCAL STATUS sys557IntAck
  644.     (
  645.     int unit /* unit number */
  646.     )
  647. {
  648.     FEI_RESOURCE * pReso = &feiResources [unit];
  649.     switch (pReso->boardType)
  650. {
  651. case PRO100B: /* handle PRO100B LAN Adapter */
  652.         case INBUSINESS:
  653.         case XX82559ER:
  654.     /* no addition work necessary for the PRO100B */
  655.     break;
  656. default:
  657.     return (ERROR);
  658. }
  659.     return (OK);
  660.     }
  661. /*******************************************************************************
  662. *
  663. * sys557IntEnable - enable 82557 interrupts
  664. *
  665. * This routine enables 82557 interrupts.  This may involve operations on
  666. * interrupt control hardware.
  667. *
  668. * The 82557 driver calls this routine throughout normal operation to terminate
  669. * critical sections of code.
  670. *
  671. * This routine assumes that the PCI configuration information has already
  672. * been setup.
  673. *
  674. * RETURNS: OK, or ERROR if interrupts could not be enabled.
  675. */
  676. LOCAL STATUS sys557IntEnable
  677.     (
  678.     int unit /* unit number */
  679.     )
  680. {
  681.     FEI_RESOURCE * pReso = &feiResources [unit];
  682.     switch (pReso->boardType)
  683. {
  684. case PRO100B: /* handle PRO100B LAN Adapter */
  685.         case INBUSINESS:
  686.         case XX82559ER:
  687.             intEnable (pReso->irq);
  688.     break;
  689. default:
  690.     return (ERROR);
  691. }
  692.     return (OK);
  693.     }
  694. /*******************************************************************************
  695. *
  696. * sys557IntDisable - disable 82557 interrupts
  697. *
  698. * This routine disables 82557 interrupts.  This may involve operations on
  699. * interrupt control hardware.
  700. *
  701. * The 82557 driver calls this routine throughout normal operation to enter
  702. * critical sections of code.
  703. *
  704. * This routine assumes that the PCI configuration information has already
  705. * been setup.
  706. *
  707. * RETURNS: OK, or ERROR if interrupts could not be disabled.
  708. */
  709. LOCAL STATUS sys557IntDisable
  710.     (
  711.     int unit /* unit number */
  712.     )
  713. {
  714.     FEI_RESOURCE * pReso = &feiResources [unit];
  715.     switch (pReso->boardType)
  716. {
  717. case PRO100B: /* handle PRO100B LAN Adapter */
  718.         case INBUSINESS:
  719.         case XX82559ER:
  720.             intDisable (pReso->irq); 
  721.     break;
  722. default:
  723.     return (ERROR);
  724. }
  725.     return (OK);
  726.     }
  727. /*******************************************************************************
  728. *
  729. * sys557eepromRead - read a word from the 82557 EEPROM
  730. *
  731. * RETURNS: the EEPROM data word read in.
  732. */
  733. LOCAL UINT16 sys557eepromRead
  734.     (
  735.     int unit, /* unit number */
  736.     int location /* address of word to be read */
  737.     )
  738. {
  739.     UINT32 iobase = feiResources[unit].iobaseCsr;
  740.     UINT16 retval = 0;
  741.     UINT16 dataval;
  742.     UINT32 eeaddr = iobase + SCB_EEPROM;
  743.     int cmdlen = 27;
  744.     int readcmd = EE_CMD_READ << 22;
  745.     readcmd = readcmd | (location << 16);
  746.     /*Enable EEPROM*/
  747.     sysPciOutWord(eeaddr, EE_ENB | EE_SK);
  748.     
  749.     do
  750.     {
  751. dataval = (readcmd & (1 << cmdlen)) ?  EE_WRITE_1 : EE_WRITE_0;
  752. sysPciOutWord(eeaddr, dataval);
  753. sysDelay();
  754. sysPciOutWord(eeaddr, dataval | EE_SK);
  755. sysDelay();
  756. dataval=sysInWord(eeaddr);
  757. retval = (retval << 1) | ((dataval & EE_DO) ? 1 : 0);
  758.  
  759.     } while(cmdlen-- > 0);
  760.     sysPciOutWord(eeaddr, EE_ENB);
  761.     sysPciOutWord(eeaddr, EE_ENB & ~EE_CS);
  762.     return retval;
  763.     
  764. #if 0
  765.     sysPciOutWord (iobase + SCB_EEPROM, EE_CS); /* enable EEPROM */
  766.     /* write the READ opcode */
  767.     for (ix = EE_CMD_BITS - 1; ix >= 0; ix--)
  768. {
  769.         dataval = (EE_CMD_READ & (1 << ix)) ? EE_DI : 0;
  770.         sysPciOutWord (iobase + SCB_EEPROM, EE_CS | dataval);
  771.         sysDelay (); /* delay for one I/O READ cycle */
  772.         sysPciOutWord (iobase + SCB_EEPROM, EE_CS | dataval | EE_SK);
  773.         sysDelay (); /* delay for one I/O READ cycle */
  774.         sysPciOutWord (iobase + SCB_EEPROM, EE_CS | dataval);
  775.         sysDelay (); /* delay for one I/O READ cycle */
  776.         }
  777.     /* write the location */
  778.     for (ix = EE_ADDR_BITS - 1; ix >= 0; ix--)
  779. {
  780.         dataval = (location & (1 << ix)) ? EE_DI : 0;
  781.         sysPciOutWord (iobase + SCB_EEPROM, EE_CS | dataval);
  782.         sysDelay (); /* delay for one I/O READ cycle */
  783.         sysPciOutWord (iobase + SCB_EEPROM, EE_CS | dataval | EE_SK);
  784.         sysDelay (); /* delay for one I/O READ cycle */
  785.         sysPciOutWord (iobase + SCB_EEPROM, EE_CS | dataval);
  786.         sysDelay (); /* delay for one I/O READ cycle */
  787. dummy = sysInWord (iobase + SCB_EEPROM);
  788.         }
  789.     if ((dummy & EE_DO) == 0) /* dummy read */
  790. ;
  791.     /* read the data */
  792.     for (ix = EE_DATA_BITS - 1; ix >= 0; ix--)
  793. {
  794.         sysPciOutWord (iobase + SCB_EEPROM, EE_CS | EE_SK);
  795.         sysDelay (); /* delay for one I/O READ cycle */
  796.         retval = (retval << 1) |
  797.          ((sysInWord (iobase + SCB_EEPROM) & EE_DO) ? 1 : 0);
  798.         sysPciOutWord (iobase + SCB_EEPROM, EE_CS);
  799.         sysDelay (); /* delay for one I/O READ cycle */
  800.         }
  801.     sysPciOutWord (iobase + SCB_EEPROM, 0x00); /* disable EEPROM */
  802.     return (retval);
  803. #endif
  804.     }
  805. /*******************************************************************************
  806. *
  807. * sys557mdioRead - read MDIO
  808. *
  809. * RETURNS: read value
  810. */
  811. LOCAL UINT32 sys557mdioRead
  812.     (
  813.     int unit, /* unit number */
  814.     int phyId, /* PHY ID */
  815.     int location /* location to read */
  816.     )
  817. {
  818.     UINT32 iobase = feiResources[unit].iobaseCsr;
  819.     int timeout   = 64*4; /* <64 usec. to complete, typ 27 ticks */
  820.     int val;
  821.     sysPciOutLong (iobase + SCB_MDI, 0x08000000 | (location<<16) | (phyId<<21));
  822.     do  {
  823.         sysDelay (); /* delay for one I/O READ cycle */
  824.         val = sysInLong (iobase + SCB_MDI);
  825.         if (--timeout < 0)
  826.             printf ("sys557mdioRead() timed out with val = %8.8x.n", val);
  827.         } while (! (val & 0x10000000));
  828.     return (val & 0xffff);
  829.     }
  830. /*******************************************************************************
  831. *
  832. * sys557mdioWrite - write MDIO
  833. *
  834. * RETURNS: write value
  835. */
  836. LOCAL UINT32 sys557mdioWrite
  837.     (
  838.     int unit, /* unit number */
  839.     int phyId, /* PHY ID */
  840.     int location, /* location to write */
  841.     int value /* value to write */
  842.     )
  843. {
  844.     UINT32 iobase = feiResources[unit].iobaseCsr;
  845.     int timeout   = 64*4; /* <64 usec. to complete, typ 27 ticks */
  846.     int val;
  847.     sysPciOutLong (iobase + SCB_MDI,
  848. 0x04000000 | (location<<16) | (phyId<<21) | value);
  849.     do  {
  850.         sysDelay (); /* delay for one I/O READ cycle */
  851.         val = sysInLong (iobase + SCB_MDI);
  852.         if (--timeout < 0)
  853.             printf ("sys557mdioWrite() timed out with val = %8.8x.n", val);
  854.         } while (! (val & 0x10000000));
  855.     return (val & 0xffff);
  856.     }
  857. /*******************************************************************************
  858. *
  859. * sys557Show - shows 82557 configuration
  860. *
  861. * This routine shows the (Intel Pro Express 100) configuration
  862. *
  863. * RETURNS: N/A
  864. */
  865. void sys557Show
  866.     (
  867.     int unit /* unit number */
  868.     )
  869. {
  870.     FEI_RESOURCE * pReso = &feiResources [unit];
  871.     UINT32 iobase       = pReso->iobaseCsr;
  872.     UCHAR etheraddr[6];
  873.     int ix;
  874.     int iy;
  875.     if (unit > IXP425_PCI_MAX_DEV)
  876. {
  877. printf ("Illegal unit number %dn", unit);
  878. return;
  879. }
  880.     if (pReso->boardType == UNKNOWN)
  881. {
  882. printf ("Unit %d not an FEI devicen", unit);
  883. return;
  884. }
  885.     for (ix = 0, iy = 0; ix < 3; ix++)
  886. {
  887.         etheraddr[iy++] = pReso->eeprom[ix];
  888.         etheraddr[iy++] = pReso->eeprom[ix] >> 8;
  889.         }
  890.     printf ("fei%d: Intel EtherExpress Pro 10/100 at %#8x ", unit, iobase);
  891.     for (ix = 0; ix < 5; ix++)
  892.      printf ("%2.2X:", etheraddr[ix]);
  893.     printf ("%2.2Xn", etheraddr[ix]);
  894.     printf ("CSR mem base address = %x, Flash mem base address = %xn",
  895.     pReso->membaseCsr, pReso->membaseFlash);
  896.     if (pReso->eeprom[3] & 0x03)
  897.         printf ("Receiver lock-up bug exists -- enabling work-around.n");
  898.     printf ("Board assembly %4.4x%2.2x-%3.3d, Physical connectors present:",
  899. pReso->eeprom[8], pReso->eeprom[9]>>8, pReso->eeprom[9] & 0xff);
  900.     for (ix = 0; ix < 4; ix++)
  901. if (pReso->eeprom[5] & (1 << ix))
  902.     printf ("%s", connectors [ix]);
  903.     printf ("nPrimary interface chip %s PHY #%d.n",
  904. phys[(pReso->eeprom[6]>>8)&15], pReso->eeprom[6] & 0x1f);
  905.     if (pReso->eeprom[7] & 0x0700)
  906. printf ("Secondary interface chip %s.n",
  907. phys[(pReso->eeprom[7]>>8)&7]);
  908. #if FALSE  /* we don't show PHY specific info at this time */
  909.     /* ToDo: Read and set PHY registers through MDIO port. */
  910.     for (ix = 0; ix < 2; ix++)
  911. printf ("MDIO register %d is %4.4x.n",
  912. ix, sys557mdioRead (unit, pReso->eeprom[6] & 0x1f, ix));
  913.     for (ix = 5; ix < 7; ix++)
  914. printf ("MDIO register %d is %4.4x.n",
  915. ix, sys557mdioRead (unit, pReso->eeprom[6] & 0x1f, ix));
  916.     printf ("MDIO register %d is %4.4x.n",
  917.     25, sys557mdioRead (unit, pReso->eeprom[6] & 0x1f, 25));
  918. #endif /* FALSE */
  919.     if (pReso->timeout < 0)
  920.         { /* Test optimized out. */
  921. printf ("Self test failed, status %8.8x:n"
  922.         " Failure to initialize the 82557.n"
  923.         " Verify that the card is a bus-master capable slot.n",
  924.         pReso->pResults[1]);
  925. }
  926.     else
  927.         {
  928. printf ("General self-test: %s.n"
  929.         " Serial sub-system self-test: %s.n"
  930.         " Internal registers self-test: %s.n"
  931.         " ROM checksum self-test: %s (%#8.8x).n",
  932.         pReso->pResults[1] & 0x1000 ? "failed" : "passed",
  933.         pReso->pResults[1] & 0x0020 ? "failed" : "passed",
  934.         pReso->pResults[1] & 0x0008 ? "failed" : "passed",
  935.         pReso->pResults[1] & 0x0004 ? "failed" : "passed",
  936.         pReso->pResults[0]);
  937.         }
  938.     }
  939. #endif /* INCLUDE_FEI82557END */
  940. /*******************************************************************************
  941. *
  942. * sysDelay - a small delay
  943. *
  944. */
  945. void sysDelay (void)
  946.     {
  947.     sysMicroDelay(PCI_CONFIG_DELAY); 
  948.     return;
  949.     }
  950. /******************************************************************************
  951. *
  952. * sys557EndPciToPhys - translate a Pci address to a physical address
  953. *
  954. * This function converts a Pci address to a physical address. This only works
  955. * for PCI Memory space.
  956. *
  957. * RETURNS: the physical adddress
  958. */
  959. UINT32 sys557EndPciToPhys
  960.     (
  961.     int unit,
  962.     UINT32      PciAddr /* PCI address */
  963.     )
  964.     {
  965.     return((UINT32)sysPciToPhys((void *)PciAddr));
  966.     }
  967. /******************************************************************************
  968. *
  969. * sys557EndPhysToPci - translate a physical address to a Pci address
  970. *
  971. * This function converts a physical address to a Pci address. This only works
  972. * for PCI Memory space.
  973. *
  974. * RETURNS: the Pci adddress
  975. */
  976. UINT32 sys557EndPhysToPci
  977.     (
  978.     int unit,
  979.     UINT32      PhysAddr        /* Physical address */
  980.     )
  981.     {
  982.     return ((UINT32)sysPhysToPci((void *)PhysAddr));
  983.     }
  984. #endif /* INCLUDE_END */