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

VxWorks

开发平台:

C/C++

  1. /* pciLocalBus.c - PCI device configuration library */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01i,27oct01,dat  Adding warnings about obsolete drivers
  8. 01h,29oct96,wlf  doc: cleanup.
  9. 01g,20sep96,mas  fixed for loop bug (SPR 7213)
  10. 01f,14aug96,dat  changed PCI_READ macro to include address
  11. 01e,02aug96,dat  rewritten for improved PCI spec compliance (SPR 6594, 6490)
  12. 01d,24jul96,dds  SPR 6819: The pci configuration registers are swapped
  13.                  in the sysPciDevShow routine.
  14. 01c,23feb96,tpr  added #include "stdio.h" and removed ix in sysPciDevConfig().
  15. 01b,02fev95,vin  cleaned up.
  16. 01a,10nov94,vin  created.
  17. */
  18. /*
  19. DESCRIPTION
  20. This library provides routines which configure a device which is located 
  21. on the PCI bus. This library has designed with respect to the PCI LOCAL BUS
  22. SPECIFICATION REVISION 2.0. It should be noted that the PCI BUS is a little
  23. endian bus and any registers located on a PCI bus are little endian. So 
  24. Big endian software should take care of this fact when writing and reading
  25. registers located on a PCI bus.
  26. This driver is customizable through the macros PCI_ADDR(base,index),
  27. PCI_READ(base,index,addr), and PCI_WRITE(base,index,data).  These 3 macros
  28. can be redefined prior to #including this file into sysLib.c.  Their default
  29. definitions assume simple memory mapped device registers. See pciLocalBus.h
  30. for default definitions.
  31. PCI_ADDR(base,index) returns a local pointer to PCI_CFG space, given a
  32. PCI base address and a longword index.
  33. PCI_READ(base,index,addr) performs a 32 bit longword read from PCI
  34. configuration space, storing the result at <addr>.
  35. PCI_WRITE(base,index,data) performs a 32 bit longword write to PCI
  36. configuration space.
  37. The macro PSWAP(x) is always defined to perform the necessary byte
  38. re-ordering based on whether or not the cpu is little-endian.  If not
  39. then PSWAP is defined to be LONGSWAP.  If the cpu is little-endian, then
  40. PSWAP is defined as a no-op.  The macros PCI_READ() and PCI_WRITE()
  41. must include PSWAP as needed.  PSWAP is only valid for 32 bit
  42. data elements.  See pciLocalBus.h for macros that will isolate fields
  43. of less than 32 bits from the appropriate 32 bit value.
  44. INCLUDE FILES: pciLocalBus.h
  45. */
  46. /* include files */
  47. #include "vxWorks.h"
  48. #include "stdio.h"
  49. #include "drv/pci/pciLocalBus.h"
  50. /* pciLocalBus is being obsoleted. Please use pciConfigLib instead. */
  51. #warning "src/drv/pci/pciLocalBus.c is outdated. Please use pciConfigLib"
  52. /*******************************************************************************
  53. *
  54. * sysPciDevConfig - configure a device on a PCI bus
  55. *
  56. * This routine configures a device that is on a Peripheral Component
  57. * Interconnect (PCI) bus. It specifies the base address(es) in I/O space and
  58. * memory space.
  59. *
  60. * The `command' argument controls how the device is configured.  If 
  61. * the CSR_IO_EN bit is set in `command', then the device is enabled in the 
  62. * I/O address space at the address `devIoBaseAdrs'.  If the CSR_MEM_EN bit 
  63. * is set, the device is enabled in the memory address space at the address
  64. * `devMemBaseAdrs'.  In all cases, all command bits are eventually written
  65. * into the device command register.
  66. *
  67. * After configuration, this routine calls the optional device-specific routine
  68. * <devPciRoutine> with its two optional arguments.
  69. *
  70. * This routine does not try interpret the configuration information in any
  71. * way; therefore it is important to configure the device with valid
  72. * information.
  73. *
  74. * RETURNS: OK, or ERROR if <devPciRoutine> returns ERROR.
  75. */
  76. STATUS sysPciDevConfig
  77.     (
  78.     ULONG  devPciCnfgAdrs, /* device PCI config space addrs */
  79.     ULONG devIoBaseAdrs, /* device IO base address */
  80.     ULONG  devMemBaseAdrs, /* device memory base address */
  81.     ULONG command, /* command to load in command reg */
  82.     FUNCPTR devPciRoutine, /* device specific function */
  83.     ULONG devPciArg1, /* device specific function argument */
  84.     ULONG devPciArg2 /* device specific function argument */
  85.     )
  86.     {
  87.     int i;
  88.     ULONG temp;
  89.     /* enable i/o mapping ? */
  90.     if ((command & CSR_IO_EN) == CSR_IO_EN)
  91. {
  92. /* find i/o base addr reg */
  93. for (i = 0; i < PCI_NUM_BAR ; i++)
  94.     {
  95.     PCI_READ (devPciCnfgAdrs, PCI_IDX_BAR_0 + i, &temp);
  96.     if (temp & 0x01)
  97. {
  98. PCI_WRITE (devPciCnfgAdrs, PCI_IDX_BAR_0 + i,
  99.     devIoBaseAdrs | BASE_ADDR_REG_IO_SPACE);
  100. break;
  101. }
  102.     }
  103. /* if can't find one, then use bar 0 (for pre 2.1 boards) */
  104. if (i == PCI_NUM_BAR)
  105.     PCI_WRITE (devPciCnfgAdrs, PCI_IDX_BAR_0,
  106. devIoBaseAdrs | BASE_ADDR_REG_IO_SPACE);
  107. }
  108.     
  109.     /* enable memory mapping ? */
  110.     if ((command & CSR_MEM_EN) == CSR_MEM_EN)
  111. {
  112. /* find memory base addr reg */
  113. for (i = 0; i < PCI_NUM_BAR ; i++)
  114.     {
  115.     PCI_READ (devPciCnfgAdrs, PCI_IDX_BAR_0 + i, &temp);
  116.     if ((temp & 0x01) == 0)
  117. {
  118. PCI_WRITE (devPciCnfgAdrs, PCI_IDX_BAR_0 + i,
  119.     devMemBaseAdrs | BASE_ADDR_REG_MEM_4GIG);
  120. break;
  121. }
  122.     }
  123. /* if can't find one, then use bar 1 (for pre 2.1 boards) */
  124. if (i == PCI_NUM_BAR)
  125.     PCI_WRITE (devPciCnfgAdrs, PCI_IDX_BAR_1,
  126. devMemBaseAdrs | BASE_ADDR_REG_MEM_4GIG);
  127. }
  128.     /* give device all the command bits */
  129.     PCI_WRITE (devPciCnfgAdrs, PCI_IDX_ST_CMD, command);
  130.     /* call the device specific routine if routine is provided */
  131.     if (devPciRoutine != NULL)
  132. if ((*devPciRoutine) (devPciArg1, devPciArg2) != OK)
  133.     return (ERROR);
  134.     return (OK);
  135.     }
  136. #ifdef INCLUDE_SHOW_ROUTINES
  137. /*******************************************************************************
  138. *
  139. * sysPciDevShow - show a PCI device configuration header
  140. *
  141. * This routine displays the configuration header for the PCI device. 
  142. *
  143. * RETURNS: OK, always.
  144. *
  145. * SEE ALSO: 
  146. * .I "PCI Local Bus Specification 2.1"
  147. */
  148. STATUS sysPciDevShow
  149.     (
  150.     ULONG * pPciCnfgHdr /* pointer to PCI config hdr */
  151.     )
  152.     {
  153.     ULONG temp;
  154.     int ix = 0;
  155.     printf ("Pci Configuration Header Information:n");
  156.     PCI_READ (pPciCnfgHdr, PCI_IDX_DEV_VNDR, &temp);
  157.     printf ("PCI device Id       :t0x%04lxn", PCI_DEVICE_ID (temp));
  158.     printf ("PCI vendor Id       :t0x%04lxn", PCI_VENDOR_ID (temp));
  159.     PCI_READ (pPciCnfgHdr, PCI_IDX_CLS_REV, &temp);
  160.     printf ("PCI classCode       :t0x%06lxn", PCI_CLASS (temp));
  161.     printf ("PCI revisionId      :t0x%02lxn", PCI_REVISION (temp));
  162.     PCI_READ (pPciCnfgHdr, PCI_IDX_ST_CMD, &temp);
  163.     printf ("PCI status & cmnd   :t0x%08lxn", temp);
  164.     PCI_READ (pPciCnfgHdr, PCI_IDX_B_H_L_C, &temp);
  165.     printf ("PCI BIST            :t0x%02lxn", PCI_BIST (temp));
  166.     printf ("PCI header type     :t0x%02lxn", PCI_HDR (temp));
  167.     printf ("PCI latency timer   :t0x%02lxn", PCI_LAT_TMR (temp));
  168.     printf ("PCI cache line Size :t0x%02lxn", PCI_CACHE_LN_SZ (temp));
  169.     for (ix = 0; ix < PCI_NUM_BAR; ix ++)
  170. {
  171. PCI_READ (pPciCnfgHdr, PCI_IDX_BAR_0 + ix, &temp);
  172. printf ("PCI Base addr Reg %2d:t0x%08lxn", ix, temp);
  173. }
  174.     PCI_READ (pPciCnfgHdr, PCI_IDX_CIS_PTR, &temp);
  175.     printf ("PCI cardbus CIS Ptr :t0x%08lxn", temp);
  176.     
  177.     PCI_READ (pPciCnfgHdr, PCI_IDX_SUB_SVID, &temp);
  178.     printf ("PCI Subsystem Id    :t0x%04lxn", PCI_SUB_ID (temp));
  179.     printf ("PCI Vendor Sub Id   :t0x%04lxn", PCI_SUB_VDR_ID (temp));
  180.     PCI_READ (pPciCnfgHdr, PCI_IDX_EXP_ROM, &temp);
  181.     printf ("PCI exp rom addr    :t0x%08lxn", temp);
  182.     PCI_READ (pPciCnfgHdr, PCI_IDX_RES_1, &temp);
  183.     printf ("PCI reserved 1      :t0x%08lxn", temp);
  184.     PCI_READ (pPciCnfgHdr, PCI_IDX_RES_2, &temp);
  185.     printf ("PCI reserved 2      :t0x%08lxn", temp);
  186.     PCI_READ (pPciCnfgHdr, PCI_IDX_L_G_I_I, &temp);
  187.     printf ("PCI maximum latency :t0x%02lxn", PCI_MAX_LAT (temp));
  188.     printf ("PCI minimum Grant   :t0x%02lxn", PCI_MIN_GNT (temp));
  189.     printf ("PCI interrupt pin   :t0x%02lxn", PCI_INT_PIN (temp));
  190.     printf ("PCI interrupt line  :t0x%02lxn", PCI_INT_LINE (temp));
  191.     return (OK);
  192.     }
  193. #endif /*INCLUDE_SHOW_ROUTINES*/
  194. /*******************************************************************************
  195. *
  196. * sysPciDevProbe - probe a PCI bus for a specified device ID
  197. *
  198. * This routine scans a Peripheral Component Interconnect (PCI) bus for 
  199. * a device with a specified ID.
  200. *
  201. * This routine assumes that each PCI ID select (IDSEL) line is mapped to 
  202. * an address line, A10 through A31.  PCI_DEV_SEL is initially A10, and is
  203. * moved left with each pass through the loop.  If the selection bit hits a
  204. * fixed bit in the configuration address, then the entire range of valid
  205. * addresses has been scanned.
  206. *
  207. * If a multifunction card is found, then this routine searches all eight
  208. * possible functions for a match to the device ID.
  209. *
  210. * CAVEAT: This routine cannot cross a PCI-PCI bridge, and therefore does not
  211. * comply with the 
  212. * .I "PCI Local Bus Specification 2.1."
  213. *
  214. * RETURNS: OK, or ERROR if the device is not found.
  215. *
  216. * SEE ALSO:
  217. * .I "PCI Local Bus Specification 2.1."
  218. */
  219. STATUS sysPciDevProbe
  220.     (
  221.     ULONG pciCnfgBaseAdrs, /* PCI configuration base address */
  222.     ULONG pciVndrDevId, /* PCI vendor device ID */
  223.     ULONG * pPciDevCnfgAdrs /* PCI device config addr returned */
  224.     )
  225.     {
  226.     ULONG devIdSel;
  227.     int ix;
  228.     int iy;
  229.     int temp;
  230.     ULONG *  pConfigReg;
  231.     devIdSel = PCI_DEV_IDSEL;
  232.     
  233.     /* Scan while the selection bit is still visible */
  234.     for (ix = 0; ix < PCI_DEV_IDSEL_MAX ; ix++, devIdSel <<= 1)
  235. {
  236. /* generate base address by using address lines for select bits */
  237. pConfigReg = (ULONG *)(pciCnfgBaseAdrs | devIdSel);
  238. /* stop if selection bit no longer makes a difference */
  239. if ((ULONG)pConfigReg == pciCnfgBaseAdrs)
  240.     break;
  241. /* copy config address to user's variable */
  242. *pPciDevCnfgAdrs = (ULONG)pConfigReg;
  243. /* test function 0 for a match */
  244. PCI_READ (pConfigReg, PCI_IDX_DEV_VNDR, &temp);
  245. if (pciVndrDevId == temp)
  246.     return (OK);
  247. if (PCI_VENDOR_ID (temp) == INVALID_VENDOR_ID)
  248.     continue; /* an empty slot, try next slot */
  249. /* If a multi-function card, we check functions 1 thru 7 */
  250. PCI_READ (pConfigReg, PCI_IDX_B_H_L_C, &temp);
  251. if (PCI_MULTI_FUNC_HDR(temp))
  252.     {
  253.     for (iy=1; iy < 8; iy++)
  254. {
  255. pConfigReg += PCI_CNFG_HDR_LONGS; /* # of longs in hdr */
  256. *pPciDevCnfgAdrs = (ULONG)pConfigReg; /* copy to user's area */
  257. PCI_READ (pConfigReg, PCI_IDX_DEV_VNDR, &temp);
  258. if (pciVndrDevId == temp)
  259.     return (OK); /* match found in sub-function */
  260. }
  261.     }
  262. }
  263.     /* device not found on the primary PCI BUS */
  264.     return (ERROR);
  265.     }