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

VxWorks

开发平台:

C/C++

  1. /* pciAutoConfigLib.c - PCI bus scan and resource allocation facility */
  2. /* Copyright 1997-2002 Wind River Systems, Inc. All Rights Reserved */
  3. /* Copyright 1997,1998,1999 Motorola, Inc. All Rights Reserved */
  4. /*
  5. modification history
  6. --------------------
  7. 01u,15may02,pmr  SPR 76759: do not assume 32-bit I/O space is supported.
  8. 01t,02nov01,tor  Remove (void *) on lvalue.
  9. 01s,09oct01,tor  Add pciAutoCfgCtl() & other config functions,
  10.   SPRs #24505, #24506, #31830, #27280, #67568
  11. 01r,10aug00,wef  Removed redundant call to pciAutoListCreate in
  12.           pciAutoConfig: SPR 33636, fix logMsg 31830 (merge from AE)
  13. 01q,04oct99,scb  Fix broken roll call, interrupt routing. SPRs 29158, 31254
  14. 01p,20jul99,tm   AddrAlign ret assign before base+align+alloc check (SPR 28243)
  15. 01o,10jun99,scb  Update to latest WRS version.
  16. 01n,08jun99,scb  Moved from T1 base to T2 base.
  17. 01m,13apr99,djs  Made FuncEnable, FuncDisable, RegConfig global (SPR 26484)
  18. 01l,12apr99,scb  added roll call capability
  19. 01k,05may99,tm   Moved bridge Prefetch detection/attribute set to probe phase
  20.                  Prefetch enable gated by parent bridge prefetch support
  21.                  Added pciAutoAddrAlign to handle address alignment/checking
  22.  BAR scanning now not stopped at first unimplemented BAR
  23. 01j,30mar99,dat  changed class to pciClass (SPR 25312)
  24. 01i,02mar99,tm   Fixed Prefetch bridge attrib (SPR 25396) / doc cleanup
  25. 01h,10feb99,tm   Prefetch bit is now gated correctly from BARs (SPR 25033)
  26. 01g,21jan99,tm   Fixed attribute inheritance mask (SPR 24605)
  27. 01f,18nov98,tm   Limit non-bus-0 I/O addresses to 16-bit decode (SPR 23428)
  28. 01e,23oct98,dat  fixed CSR accesses to not reset status.
  29. 01d,30jul98,tm   more code review revisions / Prefetchable Memory support added
  30. 01c,01jul98,tm   code review revisions / Raven-like host bridge init removed
  31.                    Cyclic interrupt routing for non-bus0 devices added
  32.    Corrected non-spec existence check (SPR 21934)
  33. 01b,20mar98,tm   adapted from pciAutoLib
  34. 01a,05Jan98,scb  written based on Motorola bug code
  35. */
  36. /*
  37. DESCRIPTION
  38. This library provides a facility for automated PCI device scanning and
  39. configuration on PCI-based systems.
  40. Modern PCI based systems incorporate many peripherals and may span multiple
  41. physical bus segments, and these bus segments may be connected via
  42. PCI-to-PCI Bridges.  Bridges are identified and properly numbered
  43. before a recursive scan identifies all resources on the bus implemented
  44. by the bridge.  Post-scan configuration of the subordinate bus number
  45. is performed.
  46. Resource requirements of each device are identified and allocated according
  47. to system resource pools that are specified by the BSP Developer.  Devices may
  48. be conditionally excluded, and interrupt routing information obtained via
  49. optional routines provided by the BSP Developer.
  50. GENERAL ALGORITHM
  51. The library must first be initialized by a call to pciAutoConfigLibInit().
  52. The return value, pCookie, must be passed to each subsequent call
  53. from the library.  Options can be set using the function pciAutoCfgCtl().
  54. The available options are described in the documentation for pciAutoCfgCtl().
  55. After initialization of the library and configuration of any
  56. options, autoconfiguration takes place in two phases.  In the first
  57. phase, all devices and subordinate busses in a given system are
  58. scanned and each device that is found causes an entry to be created
  59. in the 'Probelist' or list of devices found during the
  60. probe/configuration process.
  61. In the second phase each device that is on the Probelist is checked to see
  62. if it has been excluded from automatic configuration by the BSP developer.
  63. If a particular function has not been excluded, then it is first disabled.
  64. The Base Address Registers of the particular function are read to ascertain
  65. the resource requirements of the function.  Each resource requirement is
  66. checked against available resources in the applicable pool based on size
  67. and alignment constraints.
  68. After all functions on the Probelist have been processed, each function
  69. and it's appropriate Memory or I/O decoder(s) are enabled for operation.
  70. HOST BRIDGE DETECTION/CONFIGURATION
  71. Note that the PCI Host Bridge is automatically excluded from configuration
  72. by the autoconfig routines, as it is often already configured as part of
  73. the system bootstrap device configuration.
  74. PCI-PCI BRIDGE DETECTION/CONFIGURATION
  75. Busses are scanned by first writing the primary, secondary, and subordinate
  76. bus information into the bridge that implements the bus.  Specifically,
  77. the primary and secondary bus numbers are set to their corresponding value,
  78. and the subordinate bus number is set to 0xFF, because the final number of
  79. sub-busses is not known.  The subordinate bus number is later updated to
  80. indicate the highest numbered sub-bus that was scanned once the scan is
  81. complete.
  82. GENERIC DEVICE DETECTION/CONFIGURATION
  83. The autoconfiguration library creates a list of devices during the process
  84. of scanning all of the busses in a system.  Devices with vendor
  85. IDs of 0xFFFF and 0x0000 are skipped.  Once all busses have been
  86. scanned, all non-excluded devices are then disabled prior to configuration.
  87. Devices that are not excluded will have Resources allocated according
  88. to Base Address Registers that are implemented by the device and
  89. available space in the applicable resource pool.  PCI 'Natural' alignment
  90. constraints are adhered to when allocating resources from pools.
  91. Also initialized are the cache line size register and the latency
  92. timer.  Bus mastering is unconditionally enabled.
  93. If an interrupt assignment routine is registered, then the interrupt
  94. pin register of the PCI Configuration space is passed to this routine
  95. along with the bus, device, and function number of the device under
  96. consideration.
  97. There are two different schemes to determine when the BSP interrupt
  98. assignment routine is called by autoconfig.  The call is done either
  99. only for bus-0 devices or for all devices depending upon how the
  100. autoIntRouting is set by the BSP developer (see the section
  101. "INTERRUPT ROUTING ACROSS PCI-TO-PCI BRIDGES" below for more details).
  102. The interrupt level number returned by this routine is then written
  103. into the interrupt line register of the PCI Configuration Space for
  104. subsequent use by device drivers.  If no interrupt assignment routine
  105. is registered, 0xFF is written into the interrupt line register,
  106. specifying an unknown interrupt binding.
  107. Lastly, the functions are enabled with what resources were able to be
  108. provided from the applicable resource pools.
  109. RESOURCE ALLOCATION
  110. Resource pools include the 32-bit Prefetchable Memory pool,
  111. the 32-bit Non-prefetchable Memory ("MemIO") pool, the 32-bit I/O pool,
  112. and the 16-bit I/O allocation pool.  The allocation in each pool begins at
  113. the specified base address and progresses to higher numbered addresses.
  114. Each allocated address adheres to the PCI 'natural' alignment constraints
  115. of the given resource requirement specified in the Base Address Register.
  116. DATA STRUCTURES
  117. Data structures are either allocated statically or allocated
  118. dynamically, depending on the value of the build macro
  119. PCI_AUTO_STATIC_LIST, discussed below.  In either case, the
  120. structures are initialized by the call to pciAutoConfigLibInit().
  121. For ease of upgrading from the older method which used the PCI_SYSTEM
  122. structure, the option PCI_SYSTEM_STRUCT_COPY has been implemented.
  123. See the in the documentation for for pciAutoCfgCtl() for more information.
  124. PCI RESOURCE POOLS
  125. Resources used by pciAutoConfigLib can be divided into two groups.
  126. The first group of information is the Memory and I/O resources, that are
  127. available in the system and that autoconfig can use to allocate to functions.
  128. These resource pools consist of a base address and size.  The base address
  129. specified here should be the address relative to the PCI bus.  Each of these
  130. values in the PCI_SYSTEM data structure is described below:
  131. .IP "pciMem32" 16
  132. Specifies the 32-bit prefetchable memory pool base address.
  133. Normally, this is given by the BSP constant PCI_MEM_ADRS.
  134. It can be set with the pciAutoCfgCtl() command PCI_MEM32_LOC_SET.
  135. .IP "pciMem32Size" 16
  136. Specifies the 32-bit prefetchable memory pool size.
  137. Normally, this is given by the BSP constant PCI_MEM_SIZE.
  138. It can be set with the pciAutoCfgCtl() command PCI_MEM32_SIZE_SET.
  139. .IP "pciMemIo32" 16
  140. Specifies the 32-bit non-prefetchable memory pool base address.
  141. Normally, this is given by the BSP constant PCI_MEMIO_ADRS.
  142. It can be set with the pciAutoCfgCtl() command PCI_MEMIO32_LOC_SET.
  143. .IP "pciMemIo32Size" 16
  144. Specifies the 32-bit non-prefetchable memory pool size
  145. Normally, this is given by the BSP constant PCI_MEMIO_SIZE.
  146. It can be set with the pciAutoCfgCtl() command PCI_MEMIO32_SIZE_SET.
  147. .IP "pciIo32" 16
  148. Specifies the 32-bit I/O pool base address.
  149. Normally, this is given by the BSP constant PCI_IO_ADRS.
  150. It can be set with the pciAutoCfgCtl() command PCI_IO32_LOC_SET.
  151. .IP "pciIo32Size" 16
  152. Specifies the 32-bit I/O pool size.
  153. Normally, this is given by the BSP constant PCI_IO_SIZE.
  154. It can be set with the pciAutoCfgCtl() command PCI_IO32_SIZE_SET.
  155. .IP "pciIo16" 16
  156. Specifies the 16-bit I/O pool base address.
  157. Normally, this is given by the BSP constant PCI_ISA_IO_ADDR.
  158. It can be set with the pciAutoCfgCtl() command PCI_IO16_LOC_SET.
  159. .IP "pciIo16Size" 16
  160. Specifies the 16-bit I/O pool size.
  161. Normally, this is given by the BSP constant PCI_ISA_IO_SIZE.
  162. It can be set with the pciAutoCfgCtl() command PCI_IO16_SIZE_SET.
  163. .LP
  164. PREFETCH MEMORY ALLOCATION
  165. The pciMem32 pointer is assumed to point to a pool of prefetchable PCI
  166. memory.  If the size of this pool is non-zero, then prefetch memory will
  167. be allocated to devices that request it given that there is enough
  168. memory in the pool to satisfy the request, and the host bridge or
  169. PCI-to-PCI bridge that implements the bus that the device resides on is
  170. capable of handling prefetchable memory.  If a device requests it, and
  171. no prefetchable memory is available or the bridge implementing the bus
  172. does not handle prefetchable memory then the request will be attempted
  173. from the non-prefetchable memory pool.
  174. PCI-to-PCI bridges are queried as to whether they support prefetchable
  175. memory by writing a non-zero value to the prefetchable memory base
  176. address register and reading back a non-zero value.  A zero value would
  177. indicate the the bridge does not support prefetchable memory.
  178. BSP-SPECIFIC ROUTINES
  179. Several routines can be provided by the BSP Developer to customize
  180. the degree to which the system can be automatically configured.
  181. These routines are normally put into a file called sysBusPci.c in
  182. the BSP directory.  The trivial cases of each of these routines are
  183. shown in the USAGE section below to illustrate the API to the BSP
  184. Developer.
  185. DEVICE INCLUSION
  186. Specific devices other than bridges can be excluded from auto
  187. configuration and either not used or manually configured later.
  188. For more information, see the PCI_INCLUDE_FUNC_SET section in the
  189. documentation for pciAutoCfgCtl().
  190. INTERRUPT ASSIGNMENT
  191. Interrupt assignment can be specified by the BSP developer by
  192. specifying a routine for pciAutoConfigLib to call at the time each
  193. device or bridge is configured.  See the PCI_INT_ASSIGN_FUNC_SET
  194. section in the documentation for pciAutoCfgCtl() for more information.
  195. INTERRUPT ROUTING ACROSS PCI-TO-PCI BRIDGES
  196. PCI autoconfig allows use of two interrupt routing strategies for handling
  197. devices that reside across a PCI-to-PCI Bridge.  The BSP-specific interrupt
  198. assignment routine described in the above section is called for all devices
  199. that reside on bus 0.  For devices residing across a PCI-to-PCI bridge, one
  200. of two supported interrupt routing strategies may be selected by setting
  201. the PCI_AUTO_INT_ROUTE_SET command using pciAutoCfgCtl() to the boolean
  202. value TRUE or FALSE:
  203. .IP "TRUE" 12
  204. If automatic interrupt routing is set to TRUE, then autoconfig only
  205. calls the BSP interrupt routing routine for devices on bus number
  206. 0.  If a device resides on a higher numbered bus, then a cyclic
  207. algorithm is applied to the IRQs that are routed through the
  208. bridge.  The algorithm is based on computing a 'route offset' that
  209. is the device number modulo 4 for every bridge device that is
  210. traversed.  This offset is used with the device number and interrupt
  211. pin register of the device of interest to compute the contents of
  212. the interrupt line register.
  213. .IP "FALSE" 12
  214. If automatic interrupt routing is set to FALSE, then autoconfig
  215. calls the BSP interrupt assignment routine to do all interrupt
  216. routing regardless of the bus on which the device resides.  The
  217. return value represents the contents of the interrupt line register
  218. in all cases.
  219. BRIDGE CONFIGURATION
  220. The BSP developer may wish to perform configuration of bridges
  221. before and/or after the normal configuration of the bus they reside
  222. on.  Two routines can be specified for this purpose.
  223. The bridge pre-configuration pass initialization routine is provided
  224. so that the BSP Developer can initialize a bridge device prior to the
  225. configuration pass on the bus that the bridge implements.
  226. The bridge post-configuration pass initialization routine is provided
  227. so that the BSP Developer can initialize the bridge device after the bus
  228. that the bridge implements has been enumerated.
  229. These routines are configured by calling pciAutoCfgCtl() with the
  230. command PCI_BRIDGE_PRE_CONFIG_FUNC_SET and the command
  231. PCI_BRIDGE_POST_CONFIG_FUNC_SET, respectively.
  232. HOST BRIDGE CONFIGURATION
  233. The PCI Local Bus Specification, rev 2.1 does not specify the content or
  234. initialization requirements of the configuration space of PCI Host Bridges.
  235. Due to this fact, no host bridge specific assumptions are made by
  236. autoconfig and any PCI Host Bridge initialization that must be done before either
  237. scan or configuration of the bus must be done in the BSP.  Comments
  238. illustrating where this initialization could be called in relation to
  239. invoking the pciAutoConfig() routine are in the USAGE section below.
  240. LIBRARY CONFIGURATION MACROS
  241. The following four macros can be defined by the BSP Developer in config.h
  242. to govern the operation of the autoconfig library.
  243. .IP "PCI_AUTO_MAX_FUNCTIONS" 32
  244. Defines the maximum number of functions that can be stored in the probe list
  245. during the autoconfiguration pass.  The default value for this define is 32,
  246. but this may be overridden by defining PCI_AUTO_MAX_FUNCTIONS in config.h.
  247. .IP "PCI_AUTO_STATIC_LIST" 32
  248. If defined, then a statically allocated array of size PCI_AUTO_MAX_FUNCTION
  249. instances of the PCI_LOC structure will be instantiated.
  250. .IP "PCI_AUTO_RECLAIM_LIST" 32
  251. This define may only be used if PCI_AUTO_STATIC_LIST is not defined.  If
  252. defined, this allows the autoconfig routine to perform a free() operation
  253. on a dynamically allocated probe list.  Note that if PCI_AUTO_RECLAIM_LIST
  254. is defined and PCI_AUTO_STATIC_LIST is also, a compiler error will be
  255. generated.
  256. .LP
  257. USAGE
  258. The following code sample illustrates the usage of the PCI_SYSTEM structure
  259. and invocation of the autoconfig library.  Note that the example BSP-specific
  260. routines are merely stubs.  The code in each routine varies by BSP and
  261. application.
  262. .CS
  263. #include "pciAutoConfigLib.h"
  264. LOCAL PCI_SYSTEM sysParams;
  265. void sysPciAutoConfig (void)
  266.     {
  267.     void * pCookie;
  268.     /@ initialize the library @/
  269.     pCookie = pciAutoConfigLibInit(NULL);
  270.     /@ 32-bit Prefetchable Memory Space @/
  271.     pciAutoCfgCtl(pCookie, PCI_MEM32_LOC_SET, PCI_MEM_ADRS);
  272.     pciAutoCfgCtl(pCookie, PCI_MEM32_SIZE_SET, PCI_MEM_SIZE);
  273.     /@ 32-bit Non-prefetchable Memory Space @/
  274.     pciAutoCfgCtl(pCookie, PCI_MEMIO32_LOC_SET, PCI_MEMIO_ADRS);
  275.     pciAutoCfgCtl(pCookie, PCI_MEMIO32_SIZE_SET, PCI_MEMIO_SIZE);
  276.     /@ 16-bit ISA I/O Space @/
  277.     pciAutoCfgCtl(pCookie, PCI_IO16_LOC_SET, PCI_ISA_IO_ADRS);
  278.     pciAutoCfgCtl(pCookie, PCI_IO16_SIZE_SET, PCI_ISA_IO_SIZE);
  279.     /@ 32-bit PCI I/O Space @/
  280.     pciAutoCfgCtl(pCookie, PCI_IO32_LOC_SET, PCI_IO_ADRS);
  281.     pciAutoCfgCtl(pCookie, PCI_IO32_SIZE_SET, PCI_IO_SIZE);
  282.     /@ Configuration space parameters @/
  283.     pciAutoCfgCtl(pCookie, PCI_MAX_BUS_SET, 0);
  284.     pciAutoCfgCtl(pCookie, PCI_MAX_LAT_ALL_SET, PCI_LAT_TIMER);
  285.     pciAutoCfgCtl(pCookie, PCI_CACHE_SIZE_SET,
  286. ( _CACHE_ALIGN_SIZE / 4 ));
  287.     /@
  288.      * Interrupt routing strategy
  289.      * across PCI-to-PCI Bridges
  290.      @/
  291.     pciAutoCfgCtl(pCookie, PCI_AUTO_INT_ROUTE_SET, TRUE);
  292.     /@ Device inclusion and interrupt routing routines @/
  293.     pciAutoCfgCtl(pCookie, PCI_INCLUDE_FUNC_SET,
  294. sysPciAutoconfigInclude);
  295.     pciAutoCfgCtl(pCookie, PCI_INT_ASSIGN_FUNC_SET,
  296. sysPciAutoconfigIntrAssign);
  297.     /@
  298.      * PCI-to-PCI Bridge Pre-
  299.      * and Post-enumeration init
  300.      * routines
  301.      @/
  302.     pciAutoCfgCtl(pCookie, PCI_BRIDGE_PRE_CONFIG_FUNC_SET,
  303. sysPciAutoconfigPreEnumBridgeInit);
  304.     pciAutoCfgCtl(pCookie, PCI_BRIDGE_POST_CONFIG_FUNC_SET,
  305. sysPciAutoconfigPostEnumBridgeInit);
  306.     /@
  307.      * Perform any needed PCI Host Bridge
  308.      * Initialization that needs to be done
  309.      * before pciAutoConfig is invoked here
  310.      * utilizing the information in the
  311.      * newly-populated sysParams structure.
  312.      @/
  313.     pciAutoCfg (&sysParams);
  314.     /@
  315.      * Perform any needed post-enumeration
  316.      * PCI Host Bridge Initialization here.
  317.      * Information about the actual configuration
  318.      * from the scan and configuration passes
  319.      * can be obtained using the assorted
  320.      * PCI_*_GET commands to pciAutoCfgCtl().
  321.      @/
  322.     }
  323.     /@
  324.      * Local BSP-Specific routines
  325.      * supplied by BSP Developer
  326.      @/
  327. STATUS sysPciAutoconfigInclude
  328.     (
  329.     PCI_SYSTEM * pSys, /@ PCI_SYSTEM structure pointer @/
  330.     PCI_LOC * pLoc, /@ pointer to function in question @/
  331.     UINT devVend /@ deviceID/vendorID of device @/
  332.     )
  333.     {
  334.     return OK; /@ Autoconfigure all devices @/
  335.     }
  336. UCHAR sysPciAutoconfigIntrAssign
  337.     (
  338.     PCI_SYSTEM * pSys, /@ PCI_SYSTEM structure pointer @/
  339.     PCI_LOC * pLoc, /@ pointer to function in question @/
  340.     UCHAR pin /@ contents of PCI int pin register @/
  341.     )
  342.     {
  343.     return (UCHAR)0xff;
  344.     }
  345. void sysPciAutoconfigPreEnumBridgeInit
  346.     (
  347.     PCI_SYSTEM * pSys, /@ PCI_SYSTEM structure pointer @/
  348.     PCI_LOC * pLoc, /@ pointer to function in question @/
  349.     UINT devVend /@ deviceID/vendorID of device @/
  350.     )
  351.     {
  352.     return;
  353.     }
  354. void sysPciAutoconfigPostEnumBridgeInit
  355.     (
  356.     PCI_SYSTEM * pSys, /@ PCI_SYSTEM structure pointer @/
  357.     PCI_LOC * pLoc, /@ pointer to function in question @/
  358.     UINT devVend /@ deviceID/vendorID of device @/
  359.     )
  360.     {
  361.     return;
  362.     }
  363. .CE
  364. CONFIGURATION SPACE PARAMETERS
  365. The cache line size register specifies the cacheline size in longwords.
  366. This register is required when a device can generate a memory write and
  367. Invalidate bus cycle, or when a device provides cacheable memory to the system.
  368. Note that in the above example, the macro _CACHE_ALIGN_SIZE is utilized.  This
  369. macro is implemented for all supported architectures and is located in the
  370. <architecture>.h file in .../target/h/arch/<architecture>.  The value of the
  371. macro indicates the cache line size in bytes for the particular architecture.
  372. For example, the PowerPC architecture defines this macro to be 32, while
  373. the ARM 810 defines it to be 16.  The PCI cache line size field and
  374. the cacheSize element of the PCI_SYSTEM structure expect to see this quantity
  375. in longwords, so the byte value must be divided by 4.
  376. LIMITATIONS
  377. The current version of the autoconfig facility does not support 64-bit
  378. prefetchable memory behind PCI-to-PCI bridges, but it does support
  379. 32-bit prefetchable memory.
  380. The autoconfig code also depends upon the BSP Developer specifying resource
  381. pools that do not conflict with any resources that are being used by
  382. statically configured devices.
  383. INCLUDE FILES:
  384. pciAutoConfigLib.h
  385. SEE ALSO:
  386. .I "PCI Local Bus Specification, Revision 2.1, June 1, 1996"
  387. .I "PCI Local Bus PCI to PCI Bridge Architecture Specification, Revision 1.0,
  388. April 5, 1994"
  389. INTERNAL: SIMPLE TEXT-BASED DEBUG SUPPORT
  390. Note that the macro PCI_AUTO_DEBUG may be defined, and the macro
  391. PCI_AUTO_DEBUG_MSG utilized.  PCI_AUTO_DEBUG_MSG is identical to a function
  392. call to logMsg() in function in that it calls _func_logMsg() with the
  393. string and six parameters passed to it.  The macro also invokes taskDelay
  394. to allow the debug string to be sent with minimal interruption.
  395. Also note that the macro PCI_AUTO_DEBUG initializes a global variable
  396. pciAutoDebug to a non-zero value.  Display of debug messages may be turned
  397. on and off during runtime by manipulating this variable.  If the variable is
  398. set to zero, messages will not be displayed.
  399. INTERNAL: ATTRIBUTES
  400. Attributes are reserved for use by the autoconfiguration routines.  There
  401. is presently no user-level API at this time to access attributes for a
  402. particular device.  The BSP-specific device exclusion routine affects
  403. the attributes indirectly by specifying which devices are to be excluded
  404. from the scan and configuration process.
  405. Attributes are divided into device attributes and bridge attributes.  The first
  406. group below describes device attributes.
  407. .IP "PCI_AUTO_ATTR_DEV_EXCLUDE" 32
  408. Specifies that a device is to be excluded from the automatic scan
  409. and configuration process
  410. .IP "PCI_AUTO_ATTR_DEV_DISPLAY" 32
  411. Specifies that a device is a display device
  412. .IP "PCI_AUTO_ATTR_DEV_PREFETCH" 32
  413. Specifies that a device has requested Prefetchable PCI memory
  414. .LP
  415. The second group below describes Bridge attributes.
  416. .IP "PCI_AUTO_ATTR_BUS_PREFETCH" 32
  417. Specifies that the bridge device supports Prefetchable Memory behind the bridge
  418. .IP "PCI_AUTO_ATTR_BUS_PCI" 32
  419. Specifies that the bridge device is a PCI-to-PCI bridge and implements a PCI bus
  420. .IP "PCI_AUTO_ATTR_BUS_HOST" 32
  421. Specifies that the bridge device is a PCI Host bridge and implements a PCI bus
  422. .IP "PCI_AUTO_ATTR_BUS_ISA" 32
  423. Specifies that the bridge device is an ISA bridge implements an ISA bus
  424. .IP "PCI_AUTO_ATTR_BUS_4GB_IO" 32
  425. Specifies that the bridge device supports 32-bit I/O Addressing
  426. behind the bridge
  427. .LP
  428. INTERNAL: ATTRIBUTE INHERITANCE
  429. Devices that reside on a particular bus automatically inherit the attributes
  430. of the bridge (Host or PCI-to-PCI) that implements that bus.  This allows
  431. devices to take advantage of the fact that, for example, a PCI-to-PCI bridge
  432. implements full 32-bit PCI I/O.  Note that device attributes, such as the
  433. inclusion attribute, are not inherited.
  434. */
  435. /* includes */
  436. #include "vxWorks.h"
  437. #include "logLib.h"
  438. #include "taskLib.h"
  439. #include "string.h"
  440. #include "dllLib.h"
  441. #include "config.h"
  442. #include "errnoLib.h"
  443. #ifdef USE_PCI_SIMULATOR
  444. #include "stdio.h"
  445. #include "stdlib.h"
  446. #endif /* USE_PCI_SIMULATOR */
  447. #include "drv/pci/pciConfigLib.h"
  448. #include "drv/pci/pciAutoConfigLib.h"
  449. /* local defines */
  450. #define PCI_CMD_MASK 0xffff0000 /* mask to save status bits */
  451. #define NO_ALLOCATION  0xffffffff
  452. #define PCI_CONFIG_ABSENT_F 0xffff
  453. #define PCI_CONFIG_ABSENT_0 0x0000
  454. /* local configuration defines */
  455. #define PCI_AUTO_STATIC_LIST
  456. #undef PCI_AUTO_RECLAIM_LIST
  457. #ifndef PCI_AUTO_MAX_FUNCTIONS
  458. # define PCI_AUTO_MAX_FUNCTIONS 32
  459. #endif /* PCI_AUTO_MAX_FUNCTIONS */
  460. IMPORT FUNCPTR _func_logMsg;
  461. #define PCI_LOG_MSG(s, a, b, c, d, e, f) 
  462.     do { 
  463. if (_func_logMsg != NULL) 
  464.     { 
  465.     (*_func_logMsg)(s, a, b, c, d, e, f); 
  466.     } 
  467. else if ( ( pPciCfgOpts->pciConfigInit == TRUE ) && ( pPciCfgOpts->pciLogMsgFunc != NULL ) ) 
  468.     { 
  469.     (*(pPciCfgOpts->pciLogMsgFunc))(s,a,b,c,d,e,f); 
  470.     } 
  471.     } while (0)
  472. #define PCI_AUTO_DEBUG_MSG(s, a, b, c, d, e, f) 
  473.     do { 
  474.     if ( pciAutoDebug == TRUE ) 
  475.         { 
  476.         PCI_LOG_MSG (s, a, b, c, d, e, f); 
  477. if ( taskIdCurrent != NULL ) 
  478.             taskDelay(10); 
  479.         } 
  480.     } while (0)
  481. /* typedefs */
  482. typedef struct pciAutoConfigOpts
  483.     {
  484.     /* copy of pSystem from pciAutoConfig() interface */
  485.     UINT pciMem32; /* 32 bit prefetchable memory location */
  486.     UINT pciMem32Size; /* 32 bit prefetchable memory size */
  487.     UINT pciMemIo32; /* 32 bit non-prefetchable memory location */
  488.     UINT pciMemIo32Size; /* 32 bit non-prefetchable memory size */
  489.     UINT pciIo32; /* 32 bit io location */
  490.     UINT pciIo32Size; /* 32 bit io size */
  491.     UINT pciIo16; /* 16 bit io location */
  492.     UINT pciIo16Size; /* 16 bit io size */
  493.     int maxBus; /* Highest subbus number */
  494.     int cacheSize; /* cache line size */
  495.     UINT maxLatency; /* max latency */
  496.     BOOL autoIntRouting;        /* automatic routing strategy */
  497.     PCI_INCLUDE_FUNC includeRtn;
  498.     PCI_INT_ASSIGN_FUNC intAssignRtn;
  499.     PCI_BRIDGE_PRE_CONFIG_FUNC bridgePreConfigInit;
  500.     PCI_BRIDGE_POST_CONFIG_FUNC bridgePostConfigInit;
  501.     PCI_ROLL_CALL_FUNC pciRollcallRtn;
  502.     /* new stuff not available in the obsolete PCI_SYSTEM structure */
  503.     BOOL pciConfigInit; /* internal use only */
  504.     /* Fast Back TO Back Enable */
  505.     BOOL pciFBBEnable; /* Enabled for system */
  506.     BOOL pciFBBActive; /* implemented all cards & turned on */
  507.     /* memory allocation */
  508.     UINT32 pciMemBusMinRes; /* minimum to reserve per bus */
  509.     UINT32 pciMemBusExtraRes; /* extra to reserve per bus */
  510.     UINT32 pciMemMax; /* maximum total to reserve */
  511.     UINT32 pciMem32Used; /* total 32-bit mem actually used */
  512.     UINT32 pciMemIo32Used; /* total 32-bit IOmem used */
  513.     UINT32 pciIo32Used; /* total 32-bit IO space used */
  514.     UINT32 pciIo16Used; /* total 16-bit IO space used */
  515.     PCI_MEM_BUS_EXTRA_FUNC pciMemBusExtraFunc; /* per bus, function to calculate */
  516.     /* misc functions */
  517.     PCI_LOGMSG_FUNC pciLogMsgFunc; /* safe logMsg() func */
  518.     PCI_MAX_LAT_FUNC pciMaxLatFunc; /* MAX_LAT calc each device */
  519.     void * pciMaxLatPArg; /* user-supplied arg */
  520.     /* PCI_AUTO_MAX_FUNCTIONS */
  521.     PCI_LOC * pFuncList; /* user-supplied space */
  522.     int numFuncListEntries; /* number of entries available */
  523.     BOOL minimizeResources; /* sort resource requirements */
  524.     } PCI_AUTO_CONFIG_OPTS;
  525. /* globals */
  526. #ifdef PCI_AUTO_DEBUG
  527. BOOL pciAutoDebug = TRUE;
  528. #else
  529. BOOL pciAutoDebug = FALSE;
  530. #endif
  531. IMPORT int pciMaxBus;
  532. /* locals */
  533. LOCAL PCI_AUTO_CONFIG_OPTS pciAutoConfigOpts =
  534.     {
  535.     /* pSystem */
  536.     0, /* pciMem32 */
  537.     0, /* pciMem32Size */
  538.     0, /* pciMemIo32 */
  539.     0, /* pciMemIo32Size */
  540.     0, /* pciIo32 */
  541.     0, /* pciIo32Size */
  542.     0,  /* pciIo16 */
  543.     0, /* pciIo16Size */
  544.     0, /* maxBus */
  545.     0, /* cacheSize */
  546.     0, /* maxLatency */
  547.     FALSE, /* autoIntRouting */
  548.     NULL, /* includeRtn */
  549.     NULL, /* intAssignRtn */
  550.     NULL, /* bridgePreConfigInit */
  551.     NULL, /* bridgePostConfigInit */
  552.     NULL, /* pciRollCallRtn */
  553.     FALSE, /* is this structure valid? */
  554.     FALSE, /* Fast Back To Back enabled */
  555.     FALSE, /* Fast Back To Back active */
  556.     0, /* mem 32-bit min to reserve */
  557.     0, /* mem 32-bit extra to reserve */
  558.     0, /* max total 32-bit memory */
  559.     0, /* actual 32-bit mem used */
  560.     0, /* actual 32-bit IOmem used */
  561.     0, /* actual 32-bit IO space used */
  562.     0, /* actual 16-bit IO space used */
  563.     NULL, /* per bus func to calculate extra mem */
  564.     NULL, /* logMsg() function */
  565.     NULL, /* function to calc MAX_LAT */
  566.     NULL, /* pArg for pciMaxLatFunc() */
  567.     NULL, /* pFuncList */
  568.     0, /* number of entries available in pFuncList */
  569.     FALSE /* minimize resources */
  570.     };
  571. LOCAL PCI_AUTO_CONFIG_OPTS * pPciCfgOpts;
  572. #ifdef PCI_AUTO_STATIC_LIST
  573. LOCAL PCI_LOC pciAutoLocalFuncList[PCI_AUTO_MAX_FUNCTIONS];
  574. #endif
  575. LOCAL int lastPciListSize;
  576. LOCAL PCI_LOC *pLastPciList;
  577. LOCAL UCHAR pciAutoIntRoutingTable[4] = { (UCHAR) 0xff,
  578.                                       (UCHAR) 0xff,
  579.                                       (UCHAR) 0xff,
  580.                                       (UCHAR) 0xff
  581.                                     };
  582. /* forward declarations */
  583. LOCAL PCI_LOC * pciAutoListCreate ( PCI_AUTO_CONFIG_OPTS * pSystem, int *pListSize);
  584. LOCAL UINT pciAutoBusProbe ( PCI_AUTO_CONFIG_OPTS * pSystem, UINT priBus,
  585.     UINT secBus, PCI_LOC*  pPciLoc, PCI_LOC** ppPciList,
  586.     int * pListSize);
  587. LOCAL UINT pciAutoDevProbe ( PCI_AUTO_CONFIG_OPTS * pSystem, UINT bus,
  588.     UCHAR offset, UCHAR inheritAttrib, PCI_LOC **ppPciList, int * pListSize);
  589. LOCAL void pciAutoFuncConfigAll ( PCI_AUTO_CONFIG_OPTS * pSystem,
  590.     PCI_LOC *pPciList, UINT nSize);
  591. LOCAL UCHAR pciAutoIntAssign ( PCI_AUTO_CONFIG_OPTS * pSystem, PCI_LOC * pFunc);
  592. LOCAL void pciAutoDevConfig ( PCI_AUTO_CONFIG_OPTS * pSystem, UINT bus,
  593.     PCI_LOC **ppPciList, UINT *nSize);
  594. LOCAL void pciAutoFuncConfig ( PCI_AUTO_CONFIG_OPTS * pSystem, PCI_LOC * pPciFunc);
  595. LOCAL UINT pciAutoIoAlloc ( PCI_AUTO_CONFIG_OPTS * pPciSys, PCI_LOC *pPciFunc,
  596.     UINT *pAlloc, UINT nSize);
  597. LOCAL UINT pciAutoMemAlloc ( PCI_AUTO_CONFIG_OPTS * pPciSys, PCI_LOC * pPciFunc,
  598.     UINT * pAlloc, UINT size, UINT addrInfo);
  599. LOCAL void pciAutoBusConfig ( PCI_AUTO_CONFIG_OPTS * pSystem, PCI_LOC * pPciLoc,
  600.     PCI_LOC **ppPciList, UINT *nSize);
  601. LOCAL STATUS pciAutoCfgFunc ( void *pCookie );
  602. LOCAL STATUS pciAutoConfigFBBEnable ( PCI_AUTO_CONFIG_OPTS * pOpts );
  603. LOCAL STATUS pciAutoConfigFBBDisable ( PCI_AUTO_CONFIG_OPTS * pOpts );
  604. LOCAL STATUS pciFBBFuncClear ( UINT bus, UINT device, UINT function, void *pArg );
  605. LOCAL STATUS pciFBBFuncSet ( UINT bus, UINT device, UINT function, void *pArg );
  606. LOCAL STATUS pciFBBFuncCheck ( UINT bus, UINT device, UINT function, void *pArg );
  607. LOCAL void pciAutoConfigCopyback ( PCI_AUTO_CONFIG_OPTS * pOpts, PCI_SYSTEM * pSystem);
  608. #ifdef USE_PCI_SIMULATOR
  609. void pciAutoConfigListShow(PCI_LOC *pLoc, int num);
  610. #endif /* USE_PCI_SIMULATOR */
  611. /* subroutines */
  612. /**********************************************************************
  613. *
  614. * pciAutoConfigLibInit - initialize PCI autoconfig library.
  615. *
  616. * pciAutoConfigLib initialization function.
  617. *
  618. * ERRNO: not set
  619. *
  620. * RETURNS: A cookie for use by subsequent pciAutoConfigLib function
  621. * calls.
  622. *
  623. */
  624. void * pciAutoConfigLibInit
  625.     (
  626.     void * pArg /* reserved for future use */
  627.     )
  628.     {
  629.     pPciCfgOpts = &pciAutoConfigOpts;
  630.     pPciCfgOpts->pciConfigInit = TRUE;
  631.     return((void *)pPciCfgOpts);
  632.     }
  633. /******************************************************************************
  634. *
  635. * pciAutoCfg - Automatically configure all nonexcluded PCI headers.
  636. *
  637. * Top level function in the PCI configuration process.
  638. *
  639. * CALLING SEQUENCE:
  640. * .CS
  641. * pCookie = pciAutoConfigLibInit(NULL);
  642. * pciAutoCfgCtl(pCookie, COMMAND, VALUE);
  643. * ...
  644. * pciAutoCfgCtl(pCookie, COMMAND, VALUE);
  645. * pciAutoCfg(pCookie);
  646. * .CE
  647. *
  648. * For ease in converting from the old interface to the new one,
  649. * a pciAutoCfgCtl() command PCI_PSYSTEM_STRUCT_COPY has been
  650. * implemented.  This can be used just like any other pciAutoCfgCtl()
  651. * command, and it will initialize all the values in pSystem.  If
  652. * used, it should be the first call to pciAutoCfgCtl().
  653. *
  654. * For a description of the COMMANDs and VALUEs to pciAutoCfgCtl(), see
  655. * the pciAutoCfgCtl() documentation.
  656. *
  657. * For all nonexcluded PCI functions on all PCI bridges, this routine
  658. * will automatically configure the PCI configuration headers for PCI
  659. * devices and subbridges.  The fields that are programmed are:
  660. *
  661. * .IP 1. 4
  662. * Status register.
  663. * .IP 2. 4
  664. * Command Register.
  665. * .IP 3. 4
  666. * Latency timer.
  667. * .IP 4. 4
  668. * Cache Line size.
  669. * .IP 5. 4
  670. * Memory and/or I/O base address and limit registers.
  671. * .IP 6. 4
  672. * Primary, secondary, subordinate bus number (for PCI-PCI bridges).
  673. * .IP 7. 4
  674. * Expansion ROM disable.
  675. * .IP 8. 4
  676. * Interrupt Line.
  677. * .LP
  678. *
  679. * ALGORITHM:
  680. *
  681. * Probe PCI config space and create a list of available PCI functions.
  682. * Call device exclusion function, if registered, to exclude/include device.
  683. * Disable all devices before we initialize any.
  684. * Allocate and assign PCI space to each device.
  685. * Calculate and set interrupt line value.
  686. * Initialize and enable each device.
  687. *
  688. * RETURNS: N/A.
  689. *
  690. */
  691. STATUS pciAutoCfg
  692.     (
  693.     void *pCookie /* cookie returned by pciAutoConfigLibInit() */
  694.     )
  695.     {
  696.     PCI_AUTO_CONFIG_OPTS *pOpts;
  697.     pOpts = (PCI_AUTO_CONFIG_OPTS *)pCookie;
  698.     if ( pOpts->pciConfigInit != TRUE )
  699. {
  700. errnoSet(EINVAL);
  701. return(ERROR);
  702. }
  703.     pciAutoCfgFunc(pCookie);
  704.     /* check FBB Enable & activate if appropriate */
  705.     if ( pOpts->pciFBBEnable == TRUE )
  706. {
  707. if ( pciAutoConfigFBBEnable(pOpts) == OK )
  708.     {
  709.          pOpts->pciFBBActive = TRUE;
  710.     }
  711. else
  712.     {
  713.     PCI_AUTO_DEBUG_MSG("pciAutoCfg(): fast back-to-back NOT enabledn",
  714. 1,2,3,4,5,6);
  715.     }
  716. }
  717.     return(OK);
  718.     }
  719. /**********************************************************************
  720. *
  721. * pciAutoCfgCtl - set or get pciAutoConfigLib options.
  722. *
  723. * pciAutoCfgCtl() can be considered analogous to ioctl()
  724. * calls: the call takes arguments of (1) a pCookie, returned by
  725. * pciAutoConfigLibInit().  (2) A command,
  726. * macros for which are defined in pciAutoConfigLib.h.  And, (3)
  727. * an argument, the type of which depends on the specific command,
  728. * but will always fit in a pointer variable.  Currently, only
  729. * globally effective commands are implemented.
  730. *
  731. * The commands available are:
  732. *
  733. * .IP "PCI_FBB_ENABLE - BOOL * pArg"
  734. * .IP "PCI_FBB_DISABLE - void"
  735. * .IP "PCI_FBB_UPDATE - BOOL * pArg"
  736. * .IP "PCI_FBB_STATUS_GET - BOOL * pArg"
  737. * Enable and disable the functions which check Fast Back To Back
  738. * functionality.  PCI_FBB_UPDATE is for use with dynamic/HA
  739. * applications.  It will
  740. * first disable FBB on all functions, then enable FBB on all
  741. * functions, if appropriate.  In HA applications, it should be
  742. * called any time a card is
  743. * added or removed.  The BOOL pointed to by pArg for PCI_FBB_ENABLE
  744. * and PCI_FBB_UPDATE will be set to TRUE if all cards allow FBB
  745. * functionality and FALSE if either any card does not allow FBB
  746. * functionality or if FBB is disabled.  The BOOL pointed to by pArg
  747. * for PCI_FBB_STATUS_GET will be set to TRUE if PCI_FBB_ENABLE has
  748. * been called and FBB is enabled, even if FBB is not activated on any
  749. * card.  It will be set to FALSE otherwise.
  750. *
  751. * Note that in the current
  752. * implementation, FBB will be enabled or disabled on
  753. * the entire bus.  If any device anywhere on the bus cannot support
  754. * FBB, then it is not enabled, even if specific sub-busses
  755. * could support it.
  756. *
  757. * .IP "PCI_MAX_LATENCY_FUNC_SET - FUNCPTR * pArg"
  758. * This routine will be called for each function present on the bus
  759. * when discovery takes place.  The routine must accept four
  760. * arguments, specifying bus, device, function, and a user-supplied
  761. * argument of type void *.  See PCI_MAX_LATENCY_ARG_SET.  The routine
  762. * should return a UINT8 value, which will be put into the MAX_LAT
  763. * field of the header structure.  The user supplied routine must
  764. * return a valid value each time it is called.  There is no mechanism
  765. * for any ERROR condition, but a default value can be returned in
  766. * such a case.  Default = NULL.
  767. *
  768. * .IP "PCI_MAX_LATENCY_ARG_SET - void * pArg"
  769. * When the routine specified in PCI_MAX_LATENCY_FUNC_SET is called,
  770. * this will be passed to it as the fourth argument.
  771. *
  772. * .IP "PCI_MAX_LAT_ALL_SET - int pArg"
  773. * Specifies a constant max latency value for all cards, if no
  774. * function has been specified with PCI_MAX_LATENCY_FUNC_SET..
  775. *
  776. * .IP "PCI_MAX_LAT_ALL_GET - UINT * pArg"
  777. * Retrieves the value of max latency for all cards, if no function
  778. * has been specified with PCI_MAX_LATENCY_FUNC_SET.  Otherwise, the
  779. * integer pointed to by pArg is set to the
  780. * value 0xffffffff.
  781. *
  782. * .IP "PCI_MSG_LOG_SET - FUNCPTR * pArg"
  783. * The argument specifies a routine will be called to print warning or
  784. * error messages from pciAutoConfigLib if logMsg() has not been
  785. * initialized at the time pciAutoConfigLib is used.  The specified
  786. * routine must accept arguments in the same format as logMsg(), but
  787. * it does not necessarily need to print the actual message.  An
  788. * example of this routine is presented below, which
  789. * saves the message into a safe memory space and turns on an LED.
  790. * This command is useful for BSPs which call pciAutoCfg() before
  791. * message logging is enabled.  Note that after logMsg() is configured,
  792. * output will go to logMsg() even if this command has been called.
  793. * Default = NULL.
  794. *
  795. * .CS
  796. * /@ sample PCI_MSG_LOG_SET function @/
  797. * int pciLogMsg(char *fmt,int a1,int a2,int a3,int a4,int a5,int a6)
  798. *     {
  799. *     sysLedOn(4);
  800. *     return(sprintf(sysExcMsg,fmt,a1,a2,a3,a4,a5,a6));
  801. *     }
  802. * .CE
  803. *
  804. * .IP "PCI_MAX_BUS_GET - int * pArg"
  805. * During autoconfiguration, the library will maintain a counter with
  806. * the highest numbered bus.  This can be retrieved by
  807. * .CS
  808. * pciAutoCfgCtl(pCookie, PCI_MAX_BUS_GET, &maxBus)
  809. * .CE
  810. *
  811. * .IP "PCI_CACHE_SIZE_SET - int pArg"
  812. * Sets the pci cache line size to the specified value.  See
  813. * CONFIGURATION SPACE PARAMETERS in the pciAutoConfigLib
  814. * documentation for more details.
  815. *
  816. * .IP "PCI_CACHE_SIZE_GET - int * pArg"
  817. * Retrieves the value of the pci cache line size.
  818. *
  819. * .IP "PCI_AUTO_INT_ROUTE_SET - BOOL pArg"
  820. * Enables or disables automatic interrupt routing across bridges
  821. * during the autoconfig process.  See "INTERRUPT ROUTING ACROSS
  822. * PCI-TO-PCI BRIDGES" in the pciAutoConfigLib documentation for more
  823. * details.
  824. *
  825. * .IP "PCI_AUTO_INT_ROUTE_GET - BOOL * pArg"
  826. * Retrieves the status of automatic interrupt routing.
  827. *
  828. * .IP "PCI_MEM32_LOC_SET - UINT32 pArg"
  829. * Sets the base address of the PCI 32-bit memory space.  Normally,
  830. * this is given by the BSP constant PCI_MEM_ADRS.
  831. *
  832. * .IP "PCI_MEM32_SIZE_SET - UINT32 pArg"
  833. * Sets the maximum size to use for the PCI 32-bit memory space.
  834. * Normally, this is given by the BSP constant PCI_MEM_SIZE.
  835. *
  836. * .IP "PCI_MEM32_SIZE_GET - UINT32 * pArg"
  837. * After autoconfiguration has been completed, this retrieves
  838. * the actual amount of space which has been used for the
  839. * PCI 32-bit memory space.
  840. *
  841. * .IP "PCI_MEMIO32_LOC_SET - UINT32 pArg"
  842. * Sets the base address of the PCI 32-bit non-prefetch memory space.
  843. * Normally, this is given by the BSP constant PCI_MEMIO_ADRS.
  844. *
  845. * .IP "PCI_MEMIO32_SIZE_SET - UINT32 pArg"
  846. * Sets the maximum size to use for the PCI 32-bit non-prefetch memory
  847. * space.  Normally, this is given by the BSP constant
  848. * PCI_MEMIO_SIZE.
  849. *
  850. * .IP "PCI_MEMIO32_SIZE_GET - UINT32 * pArg"
  851. * After autoconfiguration has been completed, this retrieves
  852. * the actual amount of space which has been used for the PCI
  853. * 32-bit non-prefetch memory space.
  854. *
  855. * .IP "PCI_IO32_LOC_SET - UINT32 pArg"
  856. * Sets the base address of the PCI 32-bit I/O space.
  857. * Normally, this is given by the BSP constant PCI_IO_ADRS.
  858. *
  859. * .IP "PCI_IO32_SIZE_SET - UINT32 pArg"
  860. * Sets the maximum size to use for the PCI 32-bit I/O space.
  861. * Normally, this is given by the BSP constant PCI_IO_SIZE.
  862. *
  863. * .IP "PCI_IO32_SIZE_GET - UINT32 * pArg"
  864. * After autoconfiguration has been completed, this retrieves
  865. * the actual amount of space which has been used for the PCI
  866. * 32-bit I/O space.
  867. *
  868. * .IP "PCI_IO16_LOC_SET - UINT32 pArg"
  869. * Sets the base address of the PCI 16-bit I/O space.
  870. * Normally, this is given by the BSP constant PCI_ISA_IO_ADRS
  871. *
  872. * .IP "PCI_IO16_SIZE_SET - UINT32 pArg"
  873. * Sets the maximum size to use for the PCI 16-bit I/O space.
  874. * Normally, this is given by the BSP constant PCI_ISA_IO_SIZE
  875. *
  876. * .IP "PCI_IO16_SIZE_GET - UINT32 * pArg"
  877. * After autoconfiguration has been completed, this retrieves
  878. * the actual amount of space which has been used for the PCI
  879. * 16-bit I/O space.
  880. *
  881. * .IP "PCI_INCLUDE_FUNC_SET - FUNCPTR * pArg"
  882. * The device inclusion routine is specified by assigning a function
  883. * pointer with the PCI_INCLUDE_FUNC_SET pciAutoCfgCtl() command:
  884. * .CS
  885. * pciAutoCfgCtl(pSystem, PCI_INCLUDE_FUNC_SET,sysPciAutoconfigInclude);
  886. * .CE
  887. * This optional user-supplied routine takes as input both the
  888. * bus-device-function tuple, and a 32-bit quantity containing both
  889. * the PCI vendorID and deviceID of the function.  The function
  890. * prototype for this function is shown below:
  891. * .CS
  892. * STATUS sysPciAutoconfigInclude
  893. *     (
  894. *     PCI_SYSTEM *pSys,
  895. *     PCI_LOC *pLoc,
  896. *     UINT devVend
  897. *     );
  898. * .CE
  899. * This optional user-specified routine is called by PCI AutoConfig
  900. * for each and every function encountered in the scan phase.  The BSP
  901. * developer may use any combination of the input data to ascertain
  902. * whether a device is to be excluded from the autoconfig process.
  903. * The exclusion routine then returns ERROR if a device is to be
  904. * excluded, and OK if a device is to be included in the
  905. * autoconfiguration process.
  906. *
  907. * Note that PCI-to-PCI Bridges may not be excluded, regardless of the
  908. * value returned by the BSP device inclusion routine.  The return
  909. * value is ignored for PCI-to-PCI bridges.
  910. *
  911. * The Bridge device will be always be configured with proper primary,
  912. * secondary, and subordinate bus numbers in the device scanning phase
  913. * and proper I/O and Memory aperture settings in the configuration
  914. * phase of autoconfig regardless of the value returned by the BSP
  915. * device inclusion routine.
  916. *
  917. * .IP "PCI_INT_ASSIGN_FUNC_SET - FUNCPTR * pArg"
  918. * The interrupt assignment routine is specified by assigning a
  919. * function pointer with the PCI_INCLUDE_FUNC_SET pciAutoCfgCtl()
  920. * command:
  921. * .CS
  922. * pciAutoCfgCtl(pCookie, PCI_INT_ASSIGN_FUNC_SET, sysPciAutoconfigIntrAssign);
  923. * .CE
  924. * This optional user-specified routine takes as input both the
  925. * bus-device-function tuple, and an 8-bit quantity containing the
  926. * contents of the interrupt Pin register from the PCI configuration
  927. * header of the device under consideration.  The interrupt pin
  928. * register specifies which of the four PCI Interrupt request lines
  929. * available are connected.  The function prototype for this function
  930. * is shown below:
  931. * .CS
  932. * UCHAR sysPciAutoconfigIntrAssign
  933. *     (
  934. *     PCI_SYSTEM *pSys,
  935. *     PCI_LOC *pLoc,
  936. *     UCHAR pin
  937. *     );
  938. * .CE
  939. *
  940. * This routine may use any combination of these data to ascertain the
  941. * interrupt level.  This value is returned from the function, and
  942. * will be programmed into the interrupt line register of the
  943. * function's PCI configuration header.  In this manner, device drivers
  944. * may subsequently read this register in order to calculate the
  945. * appropriate interrupt vector which to attach an interrupt service
  946. * routine.
  947. *
  948. * .IP "PCI_BRIDGE_PRE_CONFIG_FUNC_SET - FUNCPTR * pArg"
  949. * The bridge pre-configuration pass initialization routine is
  950. * provided so that the BSP Developer can initialize a bridge device
  951. * prior to the configuration pass on the bus that the bridge
  952. * implements.  This routine is specified by calling pciAutoCfgCtl()
  953. * with the PCI_BRIDGE_PRE_CONFIG_FUNC_SET command:
  954. * .CS
  955. * pciAutoCfgCtl(pCookie, PCI_BRIDGE_PRE_CONFIG_FUNC_SET,
  956. *         sysPciAutoconfigPreEnumBridgeInit);
  957. * .CE
  958. * This optional user-specified routine takes as input both the
  959. * bus-device-function tuple, and a 32-bit quantity containing both
  960. * the PCI deviceID and vendorID of the device.  The function prototype
  961. * for this function is shown below:
  962. * .CS
  963. * STATUS sysPciAutoconfigPreEnumBridgeInit
  964. *     (
  965. *     PCI_SYSTEM *pSys,
  966. *     PCI_LOC *pLoc,
  967. *     UINT devVend
  968. *     );
  969. * .CE
  970. * This routine may use any combination of these input data to
  971. * ascertain any special initialization requirements of a particular
  972. * type of bridge at a specified geographic location.
  973. *
  974. * .IP "PCI_BRIDGE_POST_CONFIG_FUNC_SET - FUNCPTR * pArg"
  975. * The bridge post-configuration pass initialization routine is
  976. * provided so that the BSP Developer can initialize the bridge device
  977. * after the bus that the bridge implements has been enumerated.  This
  978. * routine is specified by calling pciAutoCfgCtl() with the
  979. * PCI_BRIDGE_POST_CONFIG_FUNC_SET command
  980. * .CS
  981. * pciAutoCfgCtl(pCookie, PCI_BRIDGE_POST_CONFIG_FUNC_SET,
  982. *         sysPciAutoconfigPostEnumBridgeInit);
  983. * .CE
  984. * This optional user-specified routine takes as input both the
  985. * bus-device-function tuple, and a 32-bit quantity containing both
  986. * the PCI deviceID and vendorID of the device.  The function prototype
  987. * for this function is shown below:
  988. * .CS
  989. * STATUS sysPciAutoconfigPostEnumBridgeInit
  990. *     (
  991. *     PCI_SYSTEM *pSys,
  992. *     PCI_LOC *pLoc,
  993. *     UINT devVend
  994. *     );
  995. * .CE
  996. * This routine may use any combination of these input data to
  997. * ascertain any special initialization requirements of a particular
  998. * type of bridge at a specified geographic location.
  999. *
  1000. * .IP "PCI_ROLLCALL_FUNC_SET - FUNCPTR * pArg"
  1001. * The specified routine will be configured as a roll call routine.
  1002. *
  1003. * If a roll call routine has been configured, before any
  1004. * configuration is actually done, the roll call routine is called
  1005. * repeatedly until it returns TRUE.  A return value of TRUE indicates
  1006. * that either (1) the specified number and type of devices named in
  1007. * the roll call list have been found during PCI bus enumeration or
  1008. * (2) the timeout has expired without finding all of the specified
  1009. * number and type of devices.  In either case, it is assumed that all
  1010. * of the PCI devices which are going to appear on the busses have
  1011. * appeared and we can proceed with PCI bus configuration.
  1012. *
  1013. * .IP "PCI_TEMP_SPACE_SET - char * pArg"
  1014. * This command is not currently implemented.  It allows the user to
  1015. * set aside memory for use during pciAutoConfigLib execution, e.g.
  1016. * memory set aside using USER_RESERVED_MEM.  After PCI configuration
  1017. * has been completed, the memory can be added to the system memory
  1018. * pool using memAddToPool().
  1019. *
  1020. * .IP "PCI_MINIMIZE_RESOURCES"
  1021. * This command is not currently implemented.  It specifies that
  1022. * pciAutoConfigLib minimize requirements for memory and I/O space.
  1023. *
  1024. * .IP "PCI_PSYSTEM_STRUCT_COPY - PCI_SYSTEM * pArg"
  1025. * This command has been added for ease of converting from the old
  1026. * interface to the new one.  This will set each value as specified in
  1027. * the pSystem structure.  If the PCI_SYSTEM structure has already
  1028. * been filled, the pciAutoConfig(pSystem) call can be changed
  1029. * to:
  1030. * .CS
  1031. * void *pCookie;
  1032. * pCookie = pciAutoConfigLibInit(NULL);
  1033. * pciAutoCfgCtl(pCookie, PCI_PSYSTEM_STRUCT_COPY, (void *)pSystem);
  1034. * pciAutoCfgFunc(pCookie);
  1035. * .CE
  1036. * The fields of the PCI_SYSTEM structure are defined below.  For more
  1037. * information about each one, see the paragraphs above and the
  1038. * documentation for pciAutoConfigLib.
  1039. * .IP "pciMem32" 16
  1040. * Specifies the 32-bit prefetchable memory pool base address. 
  1041. * .IP "pciMem32Size" 16
  1042. * Specifies the 32-bit prefetchable memory pool size.
  1043. * .IP "pciMemIo32" 16
  1044. * Specifies the 32-bit non-prefetchable memory pool base address.
  1045. * .IP "pciMemIo32Size" 16
  1046. * Specifies the 32-bit non-prefetchable memory pool size
  1047. * .IP "pciIo32" 16
  1048. * Specifies the 32-bit I/O pool base address. 
  1049. * .IP "pciIo32Size" 16
  1050. * Specifies the 32-bit I/O pool size. 
  1051. * .IP "pciIo16" 16
  1052. * Specifies the 16-bit I/O pool base address. 
  1053. * .IP "pciIo16Size" 16
  1054. * Specifies the 16-bit I/O pool size. 
  1055. * .IP "includeRtn" 16
  1056. * Specifies the device inclusion routine.
  1057. * .IP "intAssignRtn" 16
  1058. * Specifies the interrupt assignment routine.
  1059. * .IP "autoIntRouting" 16
  1060. * Can be set to TRUE to configure pciAutoConfig() only to
  1061. * call the BSP interrupt routing routine for devices on bus number 0.
  1062. * Setting autoIntRoutine to FALSE will configure pciAutoConfig()
  1063. * to call the BSP interrupt routing routine for every device
  1064. * regardless of the bos on which the device resides.
  1065. * .IP "bridgePreInit" 16
  1066. * Specifies the bridge initialization routine to call
  1067. * before initializing devices on the bus that the bridge
  1068. * implements.
  1069. * .IP "bridgePostInit" 16
  1070. * Specifies the bridge initialization routine to call
  1071. * after initializing devices on the bus that the bridge
  1072. * implements.
  1073. * ERRNO:
  1074. *      EINVAL if pCookie is not NULL or cmd is not recognized
  1075. *
  1076. * RETURNS: OK, or ERROR if the command or argument is invalid.
  1077. *
  1078. */
  1079. STATUS pciAutoCfgCtl
  1080.     (
  1081.     void *      pCookie,          /* system configuration information */
  1082.     int         cmd,              /* command word */
  1083.     void *      pArg              /* argument for the cmd */
  1084.     )
  1085.     {
  1086.     PCI_SYSTEM * pSystem;
  1087.     PCI_AUTO_CONFIG_OPTS * pOpts;
  1088.     if ( pCookie == NULL )
  1089.         {
  1090.         errnoSet(EINVAL);
  1091.         return(ERROR);
  1092.         }
  1093.     pOpts = (PCI_AUTO_CONFIG_OPTS *)pCookie;
  1094.     switch (cmd)
  1095.         {
  1096.     case PCI_PSYSTEM_STRUCT_COPY:
  1097.         /* copy from pSystem to pOpt */
  1098. if ( pArg == NULL )
  1099.     {
  1100.     errnoSet(EINVAL);
  1101.     return(ERROR);
  1102.     }
  1103. pSystem = (PCI_SYSTEM *)pArg;
  1104.         pOpts->pciMem32 = pSystem->pciMem32;
  1105.         pOpts->pciMem32Size = pSystem->pciMem32Size;
  1106.         pOpts->pciMemIo32 = pSystem->pciMemIo32;
  1107.         pOpts->pciMemIo32Size = pSystem->pciMemIo32Size;
  1108.         pOpts->pciIo32 = pSystem->pciIo32;
  1109.         pOpts->pciIo32Size = pSystem->pciIo32Size;
  1110.         pOpts->pciIo16 = pSystem->pciIo16;
  1111.         pOpts->pciIo16Size = pSystem->pciIo16Size;
  1112.         pOpts->maxBus = pSystem->maxBus;
  1113.         pOpts->cacheSize = pSystem->cacheSize;
  1114.         pOpts->maxLatency = pSystem->maxLatency;
  1115.         pOpts->autoIntRouting = pSystem->autoIntRouting;
  1116.         pOpts->includeRtn = pSystem->includeRtn;
  1117.         pOpts->intAssignRtn = (PCI_INT_ASSIGN_FUNC)pSystem->intAssignRtn;
  1118.         pOpts->bridgePreConfigInit = pSystem->bridgePreConfigInit;
  1119.         pOpts->bridgePostConfigInit = pSystem->bridgePostConfigInit;
  1120.         pOpts->pciRollcallRtn = pSystem->pciRollcallRtn;
  1121. break;
  1122.     case PCI_MINIMIZE_RESOURCES:
  1123. pOpts->minimizeResources = (BOOL)pArg;
  1124. break;
  1125.     case PCI_FBB_ENABLE:
  1126.      pOpts->pciFBBEnable = TRUE;
  1127.      pOpts->pciFBBActive = FALSE;
  1128. if ( pciAutoConfigFBBEnable(pOpts) == OK )
  1129.     {
  1130.          pOpts->pciFBBActive = TRUE;
  1131.     }
  1132. if ( pArg != NULL )
  1133.     {
  1134.     (*(BOOL *)pArg) = pOpts->pciFBBActive;
  1135.     }
  1136. break;
  1137.     case PCI_FBB_DISABLE:
  1138. if ( ( pOpts->pciFBBEnable == TRUE ) || ( pOpts->pciFBBActive == TRUE ) )
  1139.     {
  1140.     pciAutoConfigFBBDisable(pOpts);
  1141.          pOpts->pciFBBActive = FALSE;
  1142.     }
  1143.      pOpts->pciFBBEnable = FALSE;
  1144. break;
  1145.     case PCI_FBB_UPDATE:
  1146.      if ( ( pOpts->pciConfigInit == TRUE ) &&
  1147.      ( pOpts->pciFBBEnable == TRUE ) )
  1148.     {
  1149.          pOpts->pciFBBActive = pciAutoConfigFBBEnable(pOpts);
  1150.     }
  1151. if ( pArg != NULL )
  1152.     {
  1153.     (*(BOOL *)pArg) = pOpts->pciFBBActive;
  1154.     }
  1155. break;
  1156.     case PCI_FBB_STATUS_GET:
  1157.      (*(BOOL *)pArg) = pOpts->pciFBBEnable;
  1158. break;
  1159.     case PCI_MAX_LATENCY_FUNC_SET:
  1160.      pOpts->pciMaxLatFunc = (PCI_MAX_LAT_FUNC)pArg;
  1161. break;
  1162.     case PCI_MAX_LATENCY_ARG_SET:
  1163. pOpts->pciMaxLatPArg = pArg;
  1164. break;
  1165.     case PCI_MSG_LOG_SET:
  1166.      pOpts->pciLogMsgFunc = (FUNCPTR)pArg;
  1167. break;
  1168.     case PCI_MAX_BUS_SET:
  1169. pOpts->maxBus = (int)pArg;
  1170. break;
  1171.     case PCI_MAX_BUS_GET:
  1172. (*(int *)pArg) = pOpts->maxBus;
  1173. break;
  1174.     case PCI_CACHE_SIZE_SET:
  1175. pOpts->cacheSize = (int)pArg;
  1176. break;
  1177.     case PCI_CACHE_SIZE_GET:
  1178. *(int *)pArg = pOpts->cacheSize;
  1179. break;
  1180.     case PCI_MAX_LAT_ALL_SET:
  1181. pOpts->maxLatency = (UINT)pArg;
  1182. break;
  1183.     case PCI_MAX_LAT_ALL_GET:
  1184.      if ( pOpts->pciMaxLatFunc == NULL )
  1185.     *(UINT *)pArg = pOpts->maxLatency;
  1186. else
  1187.     *(UINT *)pArg = 0xffffffff;
  1188. break;
  1189.     case PCI_AUTO_INT_ROUTE_SET:
  1190. pOpts->autoIntRouting = (BOOL)pArg;
  1191. break;
  1192.     case PCI_AUTO_INT_ROUTE_GET:
  1193. *(BOOL *)pArg = pOpts->autoIntRouting;
  1194. break;
  1195.     case PCI_MEM32_LOC_SET:
  1196. pOpts->pciMem32 = (UINT)pArg;
  1197. break;
  1198.     case PCI_MEM32_SIZE_SET:
  1199. pOpts->pciMem32Size = (UINT)pArg;
  1200. break;
  1201.     case PCI_MEM32_SIZE_GET:
  1202.      (*(UINT32 *)pArg) = pOpts->pciMem32Used;
  1203. break;
  1204.     case PCI_MEMIO32_LOC_SET:
  1205. pOpts->pciMemIo32 = (UINT)pArg;
  1206. break;
  1207.     case PCI_MEMIO32_SIZE_SET:
  1208. pOpts->pciMemIo32Size = (UINT)pArg;
  1209. break;
  1210.     case PCI_MEMIO32_SIZE_GET:
  1211. *(UINT *)pArg = pOpts->pciMemIo32Used;
  1212. break;
  1213.     case PCI_IO32_LOC_SET:
  1214. pOpts->pciIo32 = (UINT)pArg;
  1215. break;
  1216.     case PCI_IO32_SIZE_SET:
  1217. pOpts->pciIo32Size = (UINT)pArg;
  1218. break;
  1219.     case PCI_IO32_SIZE_GET:
  1220. *(UINT *)pArg = pOpts->pciIo32Used;
  1221. break;
  1222.     case PCI_IO16_LOC_SET:
  1223. pOpts->pciIo16 = (UINT)pArg;
  1224. break;
  1225.     case PCI_IO16_SIZE_SET:
  1226. pOpts->pciIo16Size = (UINT)pArg;
  1227. break;
  1228.     case PCI_IO16_SIZE_GET:
  1229. *(UINT *)pArg = pOpts->pciIo16Used;
  1230. break;
  1231.     case PCI_INCLUDE_FUNC_SET:
  1232. pOpts->includeRtn = (PCI_INCLUDE_FUNC)pArg;
  1233. break;
  1234.     case PCI_INT_ASSIGN_FUNC_SET:
  1235. pOpts->intAssignRtn = (PCI_INT_ASSIGN_FUNC)pArg;
  1236. break;
  1237.     case PCI_BRIDGE_PRE_CONFIG_FUNC_SET:
  1238. pOpts->bridgePreConfigInit = (PCI_BRIDGE_PRE_CONFIG_FUNC)pArg;
  1239. break;
  1240.     case PCI_BRIDGE_POST_CONFIG_FUNC_SET:
  1241. pOpts->bridgePostConfigInit = (PCI_BRIDGE_POST_CONFIG_FUNC)pArg;
  1242. break;
  1243.     case PCI_ROLLCALL_FUNC_SET:
  1244. pOpts->pciRollcallRtn = (FUNCPTR)pArg;
  1245. break;
  1246.     case PCI_TEMP_SPACE_SET:
  1247. pOpts->pFuncList = ((PCI_MEM_PTR *)pArg)->pMem;
  1248. pOpts->numFuncListEntries = ((PCI_MEM_PTR *)pArg)->memSize / sizeof(PCI_LOC);
  1249. break;
  1250.     default:
  1251.         errnoSet(EINVAL);
  1252.         return(ERROR);
  1253.         }
  1254.     return(OK);
  1255.     }
  1256. #ifdef USE_PCI_SIMULATOR
  1257. void pciAutoConfigListShow(PCI_LOC *pLoc, int num)
  1258.     {
  1259.     while ( num >= 0 )
  1260. {
  1261. PCI_AUTO_DEBUG_MSG("[%d,%d,%d] bar%d 0x%08x in %s spacen",
  1262. pLoc->bus, pLoc->device, pLoc->function, 4,5,6);
  1263. pLoc++;
  1264. num--;
  1265. }
  1266.     }
  1267. #endif /* USE_PCI_SIMULATOR */
  1268. /****************************************************************
  1269. *
  1270. * pciAutoCfgFunc - the actual guts of pciAutoCfg().
  1271. *
  1272. * The functions pciAutoConfig() and pciAutoCfg() are both
  1273. * wrapper functions to go around this function.  The actual
  1274. * work is done by this function.
  1275. *
  1276. * ALGORITHM:
  1277. *
  1278. * Probe PCI config space and create a list of available PCI functions.
  1279. * Call device exclusion function, if registered, to exclude/include device.
  1280. * Disable all devices before we initialize any.
  1281. * Allocate and assign PCI space to each device.
  1282. * Calculate and set interrupt line value.
  1283. * Initialize and enable each device.
  1284. *
  1285. * RETURNS: OK, or ERROR if pCookie is not valid.
  1286. *
  1287. */
  1288. LOCAL STATUS pciAutoCfgFunc
  1289.     (
  1290.     void *pCookie /* cookie returned by pciAutoConfigLibInit() */
  1291.     )
  1292.     {
  1293.     PCI_AUTO_CONFIG_OPTS * pSystem; /* named for backward compatibility */
  1294.     PCI_LOC* pPciList; /* Pointer to PCI include list */
  1295.     int listSize; /* Size of PCI include list */
  1296.     BOOL rollcallSuccess; /* has pciRollcallRtn() succeeded? */
  1297.     /* Input parameter sanity checking */
  1298.     if (pCookie == NULL)
  1299. {
  1300. errnoSet(EINVAL);
  1301. return(ERROR);
  1302. }
  1303.     pSystem = (PCI_AUTO_CONFIG_OPTS *)pCookie;
  1304.     /*
  1305.      * If a roll-call routine has been configured, call the roll-call
  1306.      * routine repeatedly until it returns TRUE.  A return value
  1307.      * of TRUE indicates that either (1) the specified number and
  1308.      * type of devices named in the roll call list have been found
  1309.      * during PCI bus enumeration or (2) the timeout has expired
  1310.      * without finding all of the specified number and type of
  1311.      * devices.  In either case, we will assume that all of the PCI
  1312.      * devices which are going to appear on the busses have appeared
  1313.      * and we can proceed with PCI bus configuration.
  1314.      */
  1315.     if (pSystem->pciRollcallRtn != NULL)
  1316. {
  1317. rollcallSuccess = FALSE;
  1318. while ( ! rollcallSuccess )
  1319.     {
  1320.             /*
  1321.              * Probe all PCI busses dynamically creating a function list
  1322.              * of all functions found.  Excluded devices are skipped over.
  1323.              */
  1324.     pPciList = pciAutoListCreate (pSystem, &listSize);
  1325.     /* Perform roll call function, if we pass, exit the loop */
  1326.     if ( (*pSystem->pciRollcallRtn)() == OK )
  1327.         rollcallSuccess = TRUE;
  1328. #ifdef PCI_AUTO_RECLAIM_LIST
  1329.          free(pPciList);
  1330. #endif /* PCI_AUTO_RECLAIM_LIST */
  1331.     if ( rollcallSuccess == TRUE )
  1332. break;
  1333.     }
  1334.          }
  1335.     /*
  1336.      * Probe all PCI busses dynamically creating a function list
  1337.      * of all functions found.  Excluded devices are skipped over.
  1338.      */
  1339.     pPciList = pciAutoListCreate (pSystem, &listSize);
  1340.     pciAutoFuncConfigAll (pSystem, pPciList, listSize);
  1341.     lastPciListSize = listSize;
  1342.     pLastPciList = pPciList;
  1343.     /* If the function list is malloc'ed at runtime, then release it */
  1344. #if defined(PCI_AUTO_RECLAIM_LIST)
  1345. #   if defined(PCI_AUTO_STATIC_LIST)
  1346. #       error "Can't do PCI_AUTO_RECLAIM_LIST with PCI_AUTO_STATIC_LIST"
  1347. #   endif
  1348.     free(pPciList);
  1349.     lastPciListSize = 0;
  1350.     pLastPciList = NULL;
  1351. #endif
  1352.     return(OK);
  1353.     }
  1354. /******************************************************************************
  1355. *
  1356. * pciAutoListCreate - probe for all functions and make a PCI probe list.
  1357. *
  1358. * This routine creates a dynamic probelist containing all PCI functions
  1359. * located in the PCI configuration hierarchy.  In addition, it assigns
  1360. * base addresses for the 32-bit prefetchable memory allocation pool,
  1361. * the 32-bit non-prefetchable memory allocation pool, the 32-bit I/O
  1362. * allocation pool, and the 16-bit I/O allocation pool.  When I/O space
  1363. * or memory space is actually assigned (not in this routine), the space
  1364. * allocation will begin with the base address in each of these categories
  1365. * and proceed to higher numbered addresses.
  1366. *
  1367. * Note that 20-bit memory space is not currently handled as a special case.
  1368. *
  1369. * RETURNS: A pointer to a newly populated PCI device list.
  1370. */
  1371. LOCAL PCI_LOC * pciAutoListCreate
  1372.     (
  1373.     PCI_AUTO_CONFIG_OPTS * pSystem,     /* cookie returned by pciAutoConfigLibInit() */
  1374.     int *pListSize /* size of the PCI_LOC list */
  1375.     )
  1376.     {
  1377.     PCI_LOC  pciLoc; /* PCI bus/device/function structure */
  1378.     PCI_LOC *pPciList;
  1379.     PCI_LOC *pRetPciList;
  1380.     UCHAR    busAttr;
  1381.    /* Initialize the list pointer in preparation for probing */
  1382. #if defined(PCI_AUTO_STATIC_LIST)
  1383.     pPciList = pciAutoLocalFuncList;
  1384.     pRetPciList = pPciList;
  1385. #else
  1386.     pPciList = malloc(sizeof(PCI_LOC) *  PCI_AUTO_MAX_FUNCTIONS);
  1387.     if (pPciList == NULL)
  1388. {
  1389. return NULL;
  1390. }
  1391.     pRetPciList = pPciList;
  1392. #endif
  1393.     lastPciListSize = 0;
  1394.     *pListSize = 0;
  1395.     /* Begin the scanning process at [0,0,0] */
  1396.     pciLoc.bus = (UINT8)0;
  1397.     pciLoc.device = (UINT8)0;
  1398.     pciLoc.function = (UINT8)0;
  1399.     /*
  1400.      * Note that the host bridge is assumed to support prefetchable memory
  1401.      * (PCI_AUTO_ATTR_BUS_PREFETCH) and only assumed to support 32-bit I/O 
  1402.      * addressing (PCI_AUTO_ATTR_BUS_4GB_IO) if pciIo32Size is non-zero.
  1403.      */
  1404.     if (pSystem->pciIo32Size == 0)
  1405.         busAttr = PCI_AUTO_ATTR_BUS_PREFETCH;
  1406.     else
  1407.         busAttr = PCI_AUTO_ATTR_BUS_4GB_IO | PCI_AUTO_ATTR_BUS_PREFETCH;
  1408.     pciMaxBus = pciAutoDevProbe (pSystem, pciLoc.bus, (UCHAR)0,
  1409.                                  busAttr, &pPciList, pListSize);
  1410.  
  1411.     pSystem->maxBus = pciMaxBus;
  1412.     return (pRetPciList);
  1413.     }
  1414. /******************************************************************************
  1415. *
  1416. * pciAutoDevReset - Quiesce a PCI device and reset all writeable status bits.
  1417. *
  1418. * This routine turns 'off' a PCI device by disabling the Memory decoders, I/O
  1419. * decoders, and Bus Master capability.  The routine also resets all writeable
  1420. * status bits in the status word that follows the command word sequentially
  1421. * in PCI config space by performing a longword access.
  1422. *
  1423. * RETURNS: OK, always.
  1424. */
  1425. STATUS pciAutoDevReset
  1426.     (
  1427.     PCI_LOC * pPciLoc /* device to be reset */
  1428.     )
  1429.     {
  1430.     /* Disable the device and reset all writeable status bits */
  1431.     pciConfigOutLong (pPciLoc->bus, pPciLoc->device,
  1432.  pPciLoc->function,
  1433.  PCI_CFG_COMMAND, 0xffff0000);
  1434.     return OK;
  1435.     }
  1436. /******************************************************************************
  1437. *
  1438. * pciAutoBusNumberSet - Set the primary, secondary, and subordinate bus number.
  1439. *
  1440. * This routine sets the primary, secondary, and subordinate bus numbers for
  1441. * a device that implements the Type 1 PCI Configuration Space Header.
  1442. *
  1443. * This routine has external visibility to enable it to be used by BSP
  1444. * Developers for initialization of PCI Host Bridges that may implement
  1445. * registers similar to those found in the Type 1 Header.
  1446. *
  1447. * RETURNS: OK, always.
  1448. */
  1449. STATUS pciAutoBusNumberSet
  1450.     (
  1451.     PCI_LOC * pPciLoc, /* device affected */
  1452.     UINT primary, /* primary bus specification */
  1453.     UINT secondary, /* secondary bus specification */
  1454.     UINT subordinate /* subordinate bus specification */
  1455.      )
  1456.     {
  1457.     UINT workvar = 0; /* Working variable */
  1458.     workvar = (subordinate << 16) + (secondary << 8) + primary;
  1459.     /* longword write */
  1460.     pciConfigModifyLong (pPciLoc->bus,
  1461.  pPciLoc->device,
  1462.  pPciLoc->function,
  1463.  PCI_CFG_PRIMARY_BUS,
  1464.  0x00ffffff,
  1465.  workvar);
  1466.     return OK;
  1467.     }
  1468. /******************************************************************************
  1469. *
  1470. * pciAutoBusProbe - Configure a bridge and probe all devices behind it.
  1471. *
  1472. * This routine assigns an initial range of subordinate busses to a
  1473. * PCI bridge, searches for functions under this bridge, and then
  1474. * updates the range assignment to the correct value.  It calls
  1475. * pciAutoDevProbe() which in turn calls this function in a recursive
  1476. * manner.  In addition to actually programming the PCI-PCI bridge
  1477. * headers with correct bus numbers, the 'pciLoc' list of functions
  1478. * is extended as each new PCI function is found.
  1479. *
  1480. * RETURNS: The subordinate bus number.
  1481. */
  1482. LOCAL UINT pciAutoBusProbe
  1483.     (
  1484.     PCI_AUTO_CONFIG_OPTS * pSystem, /* PCI system information */
  1485.     UINT priBus, /* Primary PCI bus */
  1486.     UINT secBus, /* Secondary PCI bus */
  1487.     PCI_LOC*  pPciLoc, /* PCI address of this bridge */
  1488.     PCI_LOC** ppPciList, /* Pointer to next PCI location */
  1489. /* entry pointer */
  1490.     int * pListSize /* number of PCI_LOC entries    */
  1491.     )
  1492.     {
  1493.     UINT subBus = 0xff; /* Highest subordinate PCI bus */
  1494.     UCHAR offset = 0;   /* Interrupt routing offset for this bus*/
  1495.     /* Disable I/O, Mem, and upstream transactions / reset status bits */
  1496.     pciAutoDevReset (pPciLoc);
  1497.     /* Set the bus numbers, subordinate bus is 0xff */
  1498.     pciAutoBusNumberSet (pPciLoc, priBus, secBus, 0xff);
  1499.     PCI_AUTO_DEBUG_MSG("pciAutoBusProbe: using bridge [%d,%d,%d,0x%02x]n",
  1500. (pPciLoc->bus),
  1501. (pPciLoc->device),
  1502. (pPciLoc->function),
  1503. (pPciLoc->attribute),
  1504. 0,
  1505. 0
  1506. );
  1507.     /* Probe all devices on this bus */
  1508.     PCI_AUTO_DEBUG_MSG("pciAutoBusProbe: calling pciAutoDevProbe on bus [%d]n",
  1509.     secBus, 0, 0, 0, 0, 0);
  1510.     /*
  1511.      * Compute the route offset for this bridge: if this bridge is
  1512.      * on bus zero (primary bus = zero) then its contribution is null,
  1513.      * otherwise it depends on its location on the bus and on the
  1514.      * contribution of all of the upper Pci-To-Pci Bridges.
  1515.      */
  1516.     pPciLoc->offset += (priBus > 0) ? (pPciLoc->device % 4) : 0;
  1517.     offset = pPciLoc->offset;
  1518.     PCI_AUTO_DEBUG_MSG("pciAutoBusProbe: int route offset for bridge is [%d]n",
  1519.               offset, 0, 0, 0, 0, 0);
  1520.     subBus = pciAutoDevProbe (pSystem, secBus, offset, (pPciLoc->attribute),
  1521.     ppPciList, pListSize);
  1522.     /* Set the range assignment to cover the correct range of busses */
  1523.     PCI_AUTO_DEBUG_MSG("pciAutoBusProbe: post-config subordinate bus as [%d]n",
  1524.     subBus, 0, 0, 0, 0, 0);
  1525.     pciAutoBusNumberSet (pPciLoc, priBus, secBus, subBus);
  1526.     /* Return the highest subordinate bus */
  1527.     return subBus;
  1528.     }
  1529. /******************************************************************************
  1530. *
  1531. * pciAutoDevProbe - Probe all devices on a single PCI bus.
  1532. *
  1533. * This routine probes a single PCI bus and adds each detected PCI function
  1534. * to the function list.  In case a PCI-PCI bridge is found, pciAutoBusProbe()
  1535. * is called to probe that bus.  pciAutoBusProbe() in turn calls this function
  1536. * in a recursive manner until all busses have been probed.
  1537. *
  1538. * RETURNS: Highest subordinate bus number found during probing process.
  1539. */
  1540. LOCAL UINT pciAutoDevProbe
  1541.     (
  1542.     PCI_AUTO_CONFIG_OPTS * pSystem, /* PCI system info */
  1543.     UINT bus, /* current bus number to probe */
  1544.     UCHAR offset, /* bridge contrib to int vector xlation */
  1545.     UCHAR inheritAttrib, /* attributes inherited from bridge  */
  1546.     PCI_LOC **ppPciList, /* Pointer to next PCI location entry */
  1547.     int * pListSize /* Number of PCI_LOC's currently in list*/
  1548.     )
  1549.     {
  1550.     PCI_LOC pciLoc; /* PCI bus/device/function structure */
  1551.     UINT16 pciclass; /* PCI class/subclass contents */
  1552.     UINT dev_vend; /* Device/Vendor identifier */
  1553.     int device; /* Device location */
  1554.     int function; /* Function location */
  1555.     int subBus; /* Highest subordinate PCI bus */
  1556.     UCHAR btemp; /* Temporary holding area */
  1557.     UINT temp;
  1558.     /* Initialize variables */
  1559.     bzero ((char *)&pciLoc, sizeof (PCI_LOC));
  1560.     pciLoc.bus = bus;
  1561.     subBus = bus;
  1562.     /* if attributes indicate a host bus, then set equal to pciLoc.attrib */
  1563.     /* Locate each active function on the current bus */
  1564.     for (device = 0; device < PCI_MAX_DEV; device++)
  1565. {
  1566. pciLoc.device = device;
  1567. /* Check each function until an unused one is detected */
  1568. for (function = 0; function < PCI_MAX_FUNC; function++)
  1569.     {
  1570.     pciLoc.function = function;
  1571.     /* Check for a valid device/vendor number */
  1572.     pciConfigInLong (pciLoc.bus, pciLoc.device, pciLoc.function,
  1573.      PCI_CFG_VENDOR_ID, &dev_vend);
  1574.     /* If function 0 then check next dev else check next function */
  1575.     if ( ((dev_vend & 0x0000ffff) == PCI_CONFIG_ABSENT_F) ||
  1576.  ((dev_vend & 0x0000ffff) == PCI_CONFIG_ABSENT_0) )
  1577. {
  1578. if (function == 0)
  1579.     {
  1580.     break; /* non-existent device, goto next device */
  1581.     }
  1582. else
  1583.     {
  1584.     continue;  /* function empty, try the next function */
  1585.     }
  1586. }
  1587.             /* store the translation offset for the int routing */
  1588.             pciLoc.offset = offset;
  1589.     pciLoc.attribute = 0;
  1590.     /* Check to see if this function belongs to a PCI-PCI bridge */
  1591.     pciConfigInWord (pciLoc.bus, pciLoc.device, pciLoc.function,
  1592.                      PCI_CFG_SUBCLASS, &pciclass);
  1593.     /* Set Bridge device attributes for this device */
  1594.     switch(pciclass)
  1595. {
  1596. /* PCI Host Bridge */
  1597. case ((PCI_CLASS_BRIDGE_CTLR << 8) + PCI_SUBCLASS_HOST_PCI_BRIDGE):
  1598.     pciLoc.attribute |= ( PCI_AUTO_ATTR_DEV_EXCLUDE |
  1599.   PCI_AUTO_ATTR_BUS_HOST );
  1600.     break;
  1601. /* ISA Bridge */
  1602. case ((PCI_CLASS_BRIDGE_CTLR << 8) + PCI_SUBCLASS_ISA_BRIDGE):
  1603.     pciLoc.attribute |= PCI_AUTO_ATTR_BUS_ISA;
  1604.     break;
  1605. /* Display Device */
  1606. case (PCI_CLASS_DISPLAY_CTLR << 8):
  1607.     pciLoc.attribute |= PCI_AUTO_ATTR_DEV_DISPLAY;
  1608.     break;
  1609. /* PCI-to-PCI Bridge */
  1610. case ((PCI_CLASS_BRIDGE_CTLR << 8) + PCI_SUBCLASS_P2P_BRIDGE):
  1611.     /* Setup and probe this bridge device */
  1612.     pciLoc.attribute |= PCI_AUTO_ATTR_BUS_PCI;
  1613.     /*
  1614.      * Check for 32 bit I/O addressability,
  1615.      * but only if the parent bridge supports it
  1616.      */
  1617.     if (inheritAttrib & PCI_AUTO_ATTR_BUS_4GB_IO)
  1618. {
  1619. pciConfigInByte (pciLoc.bus,
  1620.  pciLoc.device,
  1621.  pciLoc.function,
  1622.  PCI_CFG_IO_BASE, &btemp);
  1623. if ((btemp & 0x0F) == 0x01)
  1624.     {
  1625.     pciConfigInByte (pciLoc.bus,
  1626.      pciLoc.device, pciLoc.function,
  1627.      PCI_CFG_IO_LIMIT, &btemp);
  1628.     if ((btemp & 0x0F) == 0x01)
  1629. {
  1630. pciLoc.attribute |= PCI_AUTO_ATTR_BUS_4GB_IO;
  1631. PCI_AUTO_DEBUG_MSG("pciAutoDevProbe: 4G I/O n",
  1632. 0, 0, 0, 0, 0, 0);
  1633. }
  1634.     }
  1635. }
  1636.     /* Disable prefetch */
  1637.     pciConfigModifyLong (pciLoc.bus,
  1638.  pciLoc.device,
  1639.  pciLoc.function,
  1640.  PCI_CFG_PRE_MEM_BASE,
  1641.  0xfff0fff0, 0x0000fff0);
  1642.     pciConfigOutLong (pciLoc.bus,
  1643.       pciLoc.device,
  1644.       pciLoc.function,
  1645.       PCI_CFG_PRE_MEM_LIMIT_U, 0);
  1646.     pciConfigOutLong (pciLoc.bus,
  1647.               pciLoc.device,
  1648.       pciLoc.function,
  1649.       PCI_CFG_PRE_MEM_BASE_U, 0xffffffff);
  1650.     /* Check for Prefetch memory support */
  1651.     if (inheritAttrib & PCI_AUTO_ATTR_BUS_PREFETCH)
  1652. {
  1653. pciConfigInLong  (pciLoc.bus,
  1654.   pciLoc.device,
  1655.   pciLoc.function,
  1656.   PCI_CFG_PRE_MEM_BASE, &temp);
  1657.  /* PF Registers return 0 if PF is not implemented */
  1658. if (temp != 0)
  1659.     {
  1660.     pciLoc.attribute |= PCI_AUTO_ATTR_BUS_PREFETCH;
  1661.     PCI_AUTO_DEBUG_MSG("pciAutoDevProbe: PF presentn",
  1662. 0, 0, 0, 0, 0, 0);
  1663.     }
  1664. }
  1665.     break;
  1666. default:
  1667.     /* Mask off all but bus attribute bits to inherit */
  1668.     inheritAttrib &=   ( PCI_AUTO_ATTR_BUS_4GB_IO |
  1669.  PCI_AUTO_ATTR_BUS_PREFETCH );
  1670.     /* devices inherit bus attributes from their bridge */
  1671.     pciLoc.attribute |= inheritAttrib;
  1672.     break;
  1673.     }
  1674.     /* Add this function to the PCI function list */
  1675.     if (*pListSize < PCI_AUTO_MAX_FUNCTIONS)
  1676. {
  1677. memcpy (*ppPciList, &pciLoc, sizeof (PCI_LOC));
  1678. (*ppPciList)++;
  1679. (*pListSize)++;
  1680. }
  1681.     /* If the device is a PCI-to-PCI bridge, then scan behind it */
  1682.     if (pciLoc.attribute & PCI_AUTO_ATTR_BUS_PCI)
  1683. {
  1684. PCI_AUTO_DEBUG_MSG("pciAutoDevProbe: scanning bus[%d]n",
  1685.     (subBus+1), 0, 0, 0, 0, 0 );
  1686. subBus = pciAutoBusProbe (pSystem, bus, subBus+1, &pciLoc,
  1687.     ppPciList, pListSize);
  1688. }
  1689.     /* Proceed to next device if this is a single function device */
  1690.     if (function == 0)
  1691. {
  1692. pciConfigInByte (pciLoc.bus, pciLoc.device, pciLoc.function,
  1693.  PCI_CFG_HEADER_TYPE, &btemp);
  1694. if ((btemp & PCI_HEADER_MULTI_FUNC) == 0)
  1695.     {
  1696.     break; /* No more functions - proceed to next PCI device */
  1697.     }
  1698. }
  1699.     }
  1700. }
  1701.     return (subBus);
  1702.     }
  1703. /******************************************************************************
  1704. *
  1705. * pciAutoFuncConfigAll - Configure all PCI functions contained in list.
  1706. *
  1707. * This routine initializes all PCI functions within the specified
  1708. * list.  This may be anything from a full list to a single entry.
  1709. *
  1710. * RETURNS: N/A.
  1711. */
  1712. LOCAL void pciAutoFuncConfigAll
  1713.     (
  1714.     PCI_AUTO_CONFIG_OPTS * pSystem, /* PCI system info */
  1715.     PCI_LOC *pPciList, /* input: Pointer to first function   */
  1716.     UINT nSize /* input: Number of functions to init */
  1717.     )
  1718.     {
  1719.     PCI_LOC *pPciFunc; /* Pointer to next function */
  1720.     UINT nLoop; /* Loop control variable    */
  1721.     UINT nEnd; /* End of function list     */
  1722.     /* Disable all devices before we initialize any */
  1723.     /* Allocate and assign PCI space to each device */
  1724.     pPciFunc = pPciList;
  1725.     nEnd = nSize;
  1726.     pciAutoDevConfig (pSystem, pPciList->bus, &pPciFunc, &nEnd);
  1727.     /* Enable each device on the device list */
  1728.     pPciFunc = pPciList;
  1729.     for (nLoop = 0; nLoop < nSize; nLoop++)
  1730.         {
  1731.         pciAutoFuncEnable ((PCI_SYSTEM *)pSystem, pPciFunc);
  1732.         pPciFunc++;
  1733.         }
  1734.     }
  1735. /******************************************************************************
  1736. *
  1737. * pciAutoFuncDisable - Disable a specific PCI function.
  1738. *
  1739. * This routine clears the I/O, mem, master, & ROM space enable bits
  1740. * for a single PCI function.
  1741. *
  1742. * The PCI spec says that devices should normally clear these by default after
  1743. * reset but in actual practice, some PCI devices do not fully comply.  This
  1744. * routine ensures that the devices have all been disabled before configuration
  1745. * is started.
  1746. *
  1747. * RETURNS: N/A.
  1748. *
  1749. */
  1750. void pciAutoFuncDisable
  1751.     (
  1752.     PCI_LOC *pPciFunc /* input: Pointer to PCI function struct */
  1753.     )
  1754.     {
  1755.     UCHAR cTemp; /* Temporary storage */
  1756.     UINT16 wTemp;
  1757.     if ((pPciFunc->attribute) & PCI_AUTO_ATTR_DEV_EXCLUDE)
  1758. {
  1759. return;
  1760. }
  1761.     PCI_AUTO_DEBUG_MSG("pciAutoFuncDisable: disable device [%d,%d,%d,0x%02x]n",
  1762.     (pPciFunc->bus),
  1763.     (pPciFunc->device),
  1764.     (pPciFunc->function),
  1765.     (pPciFunc->attribute),
  1766.     0,
  1767.     0
  1768.     );
  1769.     /* Disable Memory, I/O, and Bus Mastering, save status bits */
  1770.     wTemp = (PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE | PCI_CMD_MASTER_ENABLE );
  1771.     pciConfigModifyLong (pPciFunc->bus, pPciFunc->device, pPciFunc->function,
  1772.         PCI_CFG_COMMAND, (0xffff0000 | wTemp), 0x0);
  1773.     /* Disable header dependent fields */
  1774.     pciConfigInByte (pPciFunc->bus, pPciFunc->device, pPciFunc->function,
  1775.      PCI_CFG_HEADER_TYPE, &cTemp);
  1776.     cTemp &= PCI_HEADER_TYPE_MASK;
  1777.     switch (cTemp)
  1778. {
  1779. case PCI_HEADER_TYPE0: /* non PCI-PCI bridge */
  1780.     /*
  1781.      * Disable Expansion ROM address decode for the device.
  1782.      * Note that no mem space is allocated for the Expansion
  1783.      * ROM, so a re-enable later should NOT be done.
  1784.      */
  1785.     pciConfigModifyLong (pPciFunc->bus, pPciFunc->device,
  1786.  pPciFunc->function, PCI_CFG_EXPANSION_ROM,
  1787.  0x1, 0);
  1788.     break;
  1789. case PCI_HEADER_PCI_PCI: /* PCI-PCI bridge */
  1790.     pciConfigModifyLong (pPciFunc->bus, pPciFunc->device,
  1791.  pPciFunc->function, PCI_CFG_ROM_BASE,
  1792.  0x1, 0);
  1793.     break;
  1794. default:
  1795.     break;
  1796. }
  1797.     return;
  1798.     }
  1799. /******************************************************************************
  1800. *
  1801. * pciAutoFuncEnable - Perform final configuration and enable a function.
  1802. *
  1803. * Depending upon whether the device is included, this routine initializes
  1804. * a single PCI function as follows:
  1805. *
  1806. * Initialize the cache line size register
  1807. * Initialize the PCI-PCI bridge latency timers
  1808. * Enable the master PCI bit for non-display devices
  1809. * Set the interrupt line value with the value from the BSP.
  1810. *
  1811. * RETURNS: N/A.
  1812. *
  1813. */
  1814. void pciAutoFuncEnable
  1815.     (
  1816.     PCI_SYSTEM * pSys,   /* for backwards compatibility */
  1817.     PCI_LOC * pFunc       /* input: Pointer to PCI function structure */
  1818.     )
  1819.     {
  1820.     PCI_AUTO_CONFIG_OPTS * pSystem; /* PCI system info */
  1821.     UINT16 pciClass;   /* PCI class/subclass contents */
  1822.     UCHAR intLine = 0xff; /* Interrupt "Line" value           */
  1823.     UINT8 maxLatency;   /* MAX_LAT value for this function */
  1824.     /*
  1825.     * automatically call pciAutoConfigLibInit() for
  1826.     * backwards compatibility if pciAutoConfig() was
  1827.     * used.
  1828.     */
  1829.     if ( pPciCfgOpts->pciConfigInit == TRUE )
  1830.         pSystem = pPciCfgOpts;
  1831.     else
  1832. {
  1833. pSystem = pciAutoConfigLibInit(NULL);
  1834. pciAutoCfgCtl(pSystem, PCI_PSYSTEM_STRUCT_COPY, pSys);
  1835. }
  1836.     if ((pFunc->attribute) & PCI_AUTO_ATTR_DEV_EXCLUDE)
  1837.         {
  1838.         return;
  1839.         }
  1840.    PCI_AUTO_DEBUG_MSG("pciAutoFuncConfig: enable device [%d,%d,%d,0x%02x]n",
  1841. (pFunc->bus),
  1842. (pFunc->device),
  1843. (pFunc->function),
  1844. (pFunc->attribute),
  1845. 0,
  1846. 0
  1847. );
  1848.     /* Initialize the cache line size register */
  1849.     pciConfigOutByte (pFunc->bus, pFunc->device, pFunc->function,
  1850.     PCI_CFG_CACHE_LINE_SIZE, pSystem->cacheSize);
  1851.     /* Initialize the latency timer */
  1852.     /*
  1853.     *  If MAX_LAT function supplied by BSP, call it to calculate
  1854.     *  the value of MAX_LAT for each function individually.
  1855.     *  Otherwise, use the default value for all functions.
  1856.     */
  1857.     if ( ( pPciCfgOpts->pciConfigInit == TRUE ) &&
  1858.          ( pPciCfgOpts->pciMaxLatFunc != NULL ) )
  1859.         {
  1860.         /* find value by calling user-supplied function */
  1861.         maxLatency = (*pPciCfgOpts->pciMaxLatFunc)
  1862.                         (pFunc->bus,pFunc->device,pFunc->function,
  1863. pPciCfgOpts->pciMaxLatPArg);
  1864.         }
  1865.     else
  1866.         {
  1867.         /* use default value */
  1868.         maxLatency = pSystem->maxLatency;
  1869.         }
  1870.     pciConfigOutByte (pFunc->bus, pFunc->device, pFunc->function,
  1871.                       PCI_CFG_LATENCY_TIMER, maxLatency);
  1872.     /* Get the PCI class code */
  1873.     pciConfigInWord (pFunc->bus, pFunc->device, pFunc->function,
  1874.     PCI_CFG_SUBCLASS, &pciClass);
  1875.    /* Enable Bus Mastering (preserve status bits) */
  1876.     pciConfigModifyLong (pFunc->bus, pFunc->device, pFunc->function,
  1877.  PCI_CFG_COMMAND,
  1878.  (0xffff0000 | PCI_CMD_MASTER_ENABLE),
  1879.  PCI_CMD_MASTER_ENABLE);
  1880.     /*
  1881.      * If an interrupt assignment routine is registered, assign the
  1882.      * interrupt and record interrupt line in config header, else
  1883.      * write 0xff (default value) to the interrupt line reg
  1884.      */
  1885.     intLine = pciAutoIntAssign (pSystem, pFunc);
  1886.     pciConfigOutByte (pFunc->bus, pFunc->device, pFunc->function,
  1887.       PCI_CFG_DEV_INT_LINE, intLine);
  1888.     /* Reset all writeable status bits */
  1889.     pciConfigOutWord (pFunc->bus, pFunc->device, pFunc->function,
  1890.                       PCI_CFG_STATUS, (UINT16)0xFFFF);
  1891.     /* copy back to PCI_SYSTEM struct for backward compatibility */
  1892.     pciAutoConfigCopyback(pSystem, pSys);
  1893.     return;
  1894.     }
  1895. /******************************************************************************
  1896. *
  1897. * pciAutoIntAssign - Compute the interrupt number for a given PCI device.
  1898. *
  1899. * This routine computes the interrupt number for a PCI device identified
  1900. * by the parameter <pFunc>.
  1901. *
  1902. * The algorithm used is the following: if the device is on the PCI bus 0,
  1903. * then the bsp interrupt assign routine (if any) is called to get the
  1904. * actual IRQ number used.  In adddition, if the device is a Pci-To-Pci
  1905. * Bridge, then this routine populates a routing table that will be used
  1906. * later for all of the PCI devices on its every subourdinate buses.
  1907. * Conversely, if the device sits on any PCI bus other than bus 0, this
  1908. * routines only looks at that table.  The index used depends not
  1909. * only on the device's location on the bus, but also on the routing offset
  1910. * of the most immediate Pci-To-Pci Bridge.  This offset, in turn, is based
  1911. * on its location in the PCI hierarchy and was computed earlier by the
  1912. * PCI configuration process.  However, the user may skip this automatic
  1913. * interrupt assignment process by simply setting the variable autoIntRouting
  1914. * in the relevant PCI_SYSTEM structure to FALSE.  In this case the bsp
  1915. * interrupt assign routine will be called to get the IRQ number for the device.
  1916. *
  1917. * RETURNS: The interrupt number associated with the device.
  1918. */
  1919. LOCAL UCHAR pciAutoIntAssign
  1920.     (
  1921.     PCI_AUTO_CONFIG_OPTS * pSystem, /* PCI system info */
  1922.     PCI_LOC * pFunc       /* input: Pointer to PCI function structure */
  1923.     )
  1924.     {
  1925.     UCHAR retVal = 0xFF;
  1926.     UCHAR        intPin;        /* Interrupt "Pin" value            */
  1927.     pciConfigInByte (pFunc->bus, pFunc->device, pFunc->function,
  1928.                      PCI_CFG_DEV_INT_PIN, &intPin);
  1929.     /*
  1930.      * if the bsp provides interrupt routing for all PCI devices,
  1931.      * then there's no need of any computation whatsoever
  1932.      */
  1933.     if ((!(pSystem->autoIntRouting)) && (intPin != 0))
  1934.         {
  1935.         if ((pSystem->intAssignRtn) != NULL )
  1936.             {
  1937.             retVal = (pSystem->intAssignRtn) ((PCI_SYSTEM *)pSystem, pFunc, intPin);
  1938.             return (retVal);
  1939.             }
  1940.         }
  1941.     /* default interrupt routing: let's find out the IRQ for this device */
  1942.     switch (pFunc->bus)
  1943.         {
  1944.         case 0:
  1945.             if (((pSystem->intAssignRtn) != NULL) && (intPin != 0))
  1946.                 {
  1947.                 retVal = (pSystem->intAssignRtn) ((PCI_SYSTEM *)pSystem, pFunc, intPin);
  1948.                 }
  1949.             /*
  1950.              * if this is a P2P Bridge, then populate its interrupt
  1951.              * routing table.  This will be used later for all the devices
  1952.              * belonging to its every subourdinate bus
  1953.              */
  1954.             if (((pFunc->attribute) & PCI_AUTO_ATTR_BUS_PCI) > 0)
  1955.                 {
  1956.                 int i = 0;
  1957.                 for (i = 0; i < 4; i++)
  1958.                     {
  1959.                     if ((pSystem->intAssignRtn) != NULL )
  1960.                         {
  1961.                         pciAutoIntRoutingTable [i]  = (pSystem->intAssignRtn)
  1962.                                                       ((PCI_SYSTEM *)pSystem, pFunc, (i+1));
  1963.                         }
  1964.                     }
  1965.                 }
  1966.             break;
  1967.         default:
  1968.             retVal = pciAutoIntRoutingTable [(((pFunc->device) + (intPin - 1)
  1969.                                               + (pFunc->offset)) % 4)];
  1970.             break;
  1971.         }
  1972.     PCI_AUTO_DEBUG_MSG("pciAutoIntAssign: int for [%d,%d,%d] pin %d is [%d]n",
  1973.               pFunc->bus, pFunc->device, pFunc->function, intPin, retVal, 0);
  1974.     return retVal;
  1975.     }
  1976. /******************************************************************************
  1977. *
  1978. * pciAutoGetNextClass - find the next device of specific type from probe list.
  1979. *
  1980. * The function uses the probe list which was built during the probing
  1981. * process.  Using configuration accesses, it searches for the
  1982. * occurrence of the device subject to the 'class' and 'mask'
  1983. * restrictions outlined below.  Setting 'class' to zero and 'mask' to
  1984. * zero allows searching the entire set of devices found regardless of
  1985. * class.
  1986. *
  1987. * RETURNS: TRUE if a device was found, else FALSE.
  1988. *
  1989. */
  1990. STATUS pciAutoGetNextClass
  1991.     (
  1992.     PCI_SYSTEM *pSys, /* for backwards compatibility */
  1993.     PCI_LOC *pPciFunc,  /* output: Contains the BDF of the device found */
  1994.     UINT *index,        /* Zero-based device instance number */
  1995.     UINT pciClass,      /* class code field from the PCI header */
  1996.     UINT mask           /* mask is ANDed with the class field */
  1997.     )
  1998.     {
  1999.     PCI_AUTO_CONFIG_OPTS *pPciSystem;
  2000.     UINT i;
  2001.     UINT idx = *index;
  2002.     UINT classCode;
  2003.     UINT nSize;
  2004.     PCI_LOC *pciList;
  2005.     /*
  2006.     * automatically call pciAutoConfigLibInit() for
  2007.     * backwards compatibility if pciAutoConfig() was
  2008.     * used.
  2009.     */
  2010.     if ( pPciCfgOpts->pciConfigInit == TRUE )
  2011.         pPciSystem = pPciCfgOpts;
  2012.     else
  2013. {
  2014. pPciSystem = pciAutoConfigLibInit(NULL);
  2015. pciAutoCfgCtl(pPciSystem, PCI_PSYSTEM_STRUCT_COPY, pSys);
  2016. }
  2017.     nSize = (UINT)lastPciListSize;
  2018.     pciList = pLastPciList;
  2019.     PCI_AUTO_DEBUG_MSG("npciAutoGetNextClass: index[%d] listSiz[%d]n",
  2020. *index, nSize, 0, 0, 0, 0);
  2021.     PCI_AUTO_DEBUG_MSG("                     pciClass[0x%08x], mask[0x%08x]n",
  2022. pciClass, mask, 0, 0, 0, 0);
  2023.     if ((nSize <= idx) || (pciList == NULL))
  2024. {
  2025. /* copy back to PCI_SYSTEM struct for backward compatibility */
  2026. pciAutoConfigCopyback(pPciSystem, pSys);
  2027.         return (FALSE);             /* No more devices */
  2028. }
  2029.     for (i = idx; i < nSize; i++)
  2030.         {
  2031.         /* Grab the class code 24-bit field */
  2032.         pciConfigInLong ((UINT)pciList[i].bus, (UINT)pciList[i].device,
  2033.                          (UINT)pciList[i].function, (PCI_CFG_CLASS & 0xfc),
  2034.                          &classCode);
  2035.         classCode >>= 8;        /* Isolate class code in low order bits */
  2036.         if ((classCode & mask) == (pciClass & mask))
  2037.             {
  2038.             *index = i;
  2039.             *pPciFunc = pciList[i];
  2040.     /* copy back to PCI_SYSTEM struct for backward compat */
  2041.     pciAutoConfigCopyback(pPciSystem, pSys);
  2042.             return (TRUE);
  2043.             }
  2044.         }
  2045.     /* copy back to PCI_SYSTEM struct for backward compatibility */
  2046.     pciAutoConfigCopyback(pPciSystem, pSys);
  2047.     return (FALSE);
  2048.     }
  2049. /******************************************************************************
  2050. *
  2051. * pciAutoDevConfig - Allocate memory and I/O space to PCI function.
  2052. *
  2053. * This routine allocates memory and I/O space to functions on an
  2054. * individual PCI bus.
  2055. *
  2056. * LIMITATIONS:
  2057. *
  2058. * do not sort the include function list before this routine is
  2059. * called.  This routine requires each function in the list to be in the
  2060. * same order as the probe occurred.
  2061. *
  2062. * RETURNS: N/A.
  2063. */
  2064. LOCAL void pciAutoDevConfig
  2065.     (
  2066.     PCI_AUTO_CONFIG_OPTS * pSystem,  /* PCI system info */
  2067.     UINT bus, /* Current bus number    */
  2068.     PCI_LOC **ppPciList, /* Pointer to function list */
  2069.     UINT *nSize /* Number of remaining funcs */
  2070.     )
  2071.     {
  2072.     PCI_LOC *pPciFunc; /* Pointer to PCI function    */
  2073.     UINT nextBus; /* Bus where function is located   */
  2074.     UINT16 pciClass; /* Class field of function    */
  2075.     /* Process each function within the list */
  2076.     while (*nSize > 0)
  2077. {
  2078. /* Setup local variables */
  2079. pPciFunc = *ppPciList;
  2080. nextBus = pPciFunc->bus;
  2081. /* Decrease recursion depth if this function is on a parent bus */
  2082. if (nextBus < bus)
  2083.     {
  2084.     return;
  2085.     }
  2086. /* Allocate and assign space to functions on this bus */
  2087. pciAutoFuncConfig (pSystem, pPciFunc);
  2088. (*nSize)--;
  2089. (*ppPciList)++;
  2090. /* Increase recursion depth if this function is a PCI-PCI bridge */
  2091. pciConfigInWord (pPciFunc->bus, pPciFunc->device, pPciFunc->function,
  2092.  PCI_CFG_SUBCLASS, &pciClass);
  2093. switch (pciClass)
  2094.     {
  2095.     case (( PCI_CLASS_BRIDGE_CTLR << 8) + PCI_SUBCLASS_P2P_BRIDGE ):
  2096. /* PCI-PCI bridge functions increase recursion depth */
  2097. pciAutoBusConfig (pSystem, pPciFunc, ppPciList, nSize);
  2098. break;
  2099.     default:
  2100. /* Maintain current recursion depth */
  2101. break;
  2102.     }
  2103. }
  2104.     }
  2105. /******************************************************************************
  2106. *
  2107. * pciAutoFuncConfig - Assign memory and/or I/O space to single function.
  2108. *
  2109. * This routine allocates and assigns memory and/or I/O space to a
  2110. * single PCI function.  Allocations are made for each implemented
  2111. * base address register (BAR) in the PCI configuration header.
  2112. *
  2113. * RETURNS: N/A.
  2114. */
  2115. LOCAL void pciAutoFuncConfig
  2116.     (
  2117.     PCI_AUTO_CONFIG_OPTS * pSystem, /* cookie returned by pciAutoConfigLibInit() */
  2118.     PCI_LOC * pPciFunc /* input: "Include list" pointer to function */
  2119.     )
  2120.     {
  2121.     UINT baMax; /* Total number of base addresses    */
  2122.     UINT baI; /* Base address register index      */
  2123.     UINT baseAddr;      /* PCI Offset of base address        */
  2124.     UINT readVar;       /* Contents of base address register */
  2125.     UINT addrInfo;      /* PCI address type information      */
  2126.     UINT sizeMask;      /* LSbit for size calculation        */
  2127.     UCHAR headerType; /* Read from PCI config header      */
  2128.     UINT dev_vend;
  2129.     /* If there is a function, then consult the exclusion routine */
  2130.     if ( (pSystem->includeRtn) != NULL )
  2131. {
  2132. pciConfigInLong (pPciFunc->bus, pPciFunc->device, pPciFunc->function,
  2133.  PCI_CFG_VENDOR_ID, &dev_vend);
  2134. if ( ((pSystem->includeRtn) ((PCI_SYSTEM *)pSystem, pPciFunc, dev_vend)) == ERROR )
  2135.     {
  2136.     if ((pPciFunc->attribute & PCI_AUTO_ATTR_BUS_PCI) == 0)
  2137. {
  2138. pPciFunc->attribute |= PCI_AUTO_ATTR_DEV_EXCLUDE;
  2139. PCI_AUTO_DEBUG_MSG("pciAutoFuncConfig: exc [%d,%d,%d,0x%02x]n",
  2140. pPciFunc->bus, pPciFunc->device, pPciFunc->function,
  2141. pPciFunc->attribute,0,0);
  2142. return;
  2143. }
  2144.     }
  2145. }
  2146.     /* Disable the function */
  2147.     pciAutoFuncDisable (pPciFunc);
  2148.     /* Determine the number of base address registers present */
  2149.     pciConfigInByte (pPciFunc->bus, pPciFunc->device, pPciFunc->function,
  2150.  PCI_CFG_HEADER_TYPE, &headerType);
  2151.     headerType &= 0x7f;
  2152.     switch (headerType)
  2153. {
  2154. case PCI_HEADER_TYPE0:
  2155.     baMax = 6;
  2156.     break;
  2157. case PCI_HEADER_PCI_PCI:
  2158.     baMax = 2;
  2159.     break;
  2160. default:
  2161.     baMax = 0;
  2162.     break;
  2163. }
  2164.     /* Allocate Memory or I/O space for each implemented base addr register */
  2165.     for (baI = 0; baI < baMax; baI++)
  2166. {
  2167. /* Get the base address register contents */
  2168. baseAddr = PCI_CFG_BASE_ADDRESS_0 + (baI * 4);
  2169. pciConfigOutLong (pPciFunc->bus, pPciFunc->device, pPciFunc->function,
  2170.           baseAddr, 0xFFFFFFFF);
  2171. pciConfigInLong (pPciFunc->bus, pPciFunc->device, pPciFunc->function,
  2172.          baseAddr, &readVar);
  2173. /* Go to the next BAR when an unimplemented one (BAR==0) is found */
  2174. if (readVar == 0)
  2175.     {
  2176.     continue;
  2177.     }
  2178. /* Mask off all but space, memory type, and prefetchable bits */
  2179. addrInfo = readVar & PCI_BAR_ALL_MASK;
  2180. /* Check for type, setup mask variables (based on type) */
  2181. if ((addrInfo & PCI_BAR_SPACE_MASK) == PCI_BAR_SPACE_IO)
  2182.     {
  2183.     PCI_AUTO_DEBUG_MSG("pciAutoFuncConfig: IO Space found at BAR[%d]n",
  2184.     baI, 0, 0, 0, 0, 0);
  2185.     sizeMask = (1 << 2);
  2186.     }
  2187. else
  2188.     {
  2189.     PCI_AUTO_DEBUG_MSG("pciAutoFuncConfig: MemSpace found at BAR[%d]n",
  2190.     baI, 0, 0, 0, 0, 0);
  2191.     sizeMask = (1 << 4);
  2192.     }
  2193. /* Loop until we find a bit set or until we run out of bits */
  2194. for (; sizeMask; sizeMask <<= 1)
  2195.     {
  2196.     /* is this bit set? if not, keep looking */
  2197.     if (readVar & sizeMask)
  2198. {
  2199. baI += pciAutoRegConfig ((PCI_SYSTEM *)pSystem, pPciFunc, baseAddr, sizeMask,
  2200.     addrInfo);
  2201. break;
  2202. }
  2203.     }
  2204. }
  2205.     }
  2206. /******************************************************************************
  2207. *
  2208. * pciAutoRegConfig - Assign PCI space to a single PCI base address register.
  2209. *
  2210. * This routine allocates and assigns PCI space (either memory or I/O)
  2211. * to a single PCI base address register.
  2212. *
  2213. * RETURNS: Returns (1) if BAR supports mapping anywhere in 64-bit address space.
  2214. * Returns (0) otherwise.
  2215. */
  2216. UINT pciAutoRegConfig
  2217.     (
  2218.     PCI_SYSTEM *pSys, /* backwards compatibility */
  2219.     PCI_LOC *pPciFunc, /* Pointer to function in device list */
  2220.     UINT baseAddr, /* Offset of base PCI address */
  2221.     UINT nSize, /* Size and alignment requirements */
  2222.     UINT addrInfo /* PCI address type information */
  2223.     )
  2224.     {
  2225.     PCI_AUTO_CONFIG_OPTS * pSystem; /* Pointer to PCI System structure */
  2226.     UINT addr; /* Working address variable */
  2227.     UINT spaceEnable = 0; /* PCI space enable bit */
  2228.     UINT baseaddr_mask; /* Mask for base address register */
  2229.     UINT register64Bit; /* 64 bit register flag */
  2230.     /*
  2231.     * automatically call pciAutoConfigLibInit() for
  2232.     * backwards compatibility if pciAutoConfig() was
  2233.     * used.
  2234.     */
  2235.     if ( pPciCfgOpts->pciConfigInit == TRUE )
  2236.         pSystem = pPciCfgOpts;
  2237.     else
  2238. {
  2239. pSystem = pciAutoConfigLibInit(NULL);
  2240. pciAutoCfgCtl(pSystem, PCI_PSYSTEM_STRUCT_COPY, pSys);
  2241. }
  2242.     /* Select the appropriate PCI address space for this register */
  2243.     if ((addrInfo & PCI_BAR_SPACE_MASK) == PCI_BAR_SPACE_IO)
  2244. {
  2245. /* Configure this register for PCI I/O space */
  2246. spaceEnable = PCI_CMD_IO_ENABLE;
  2247. baseaddr_mask = 0xFFFFFFFC;
  2248. register64Bit = pciAutoIoAlloc (pSystem, pPciFunc, &addr, nSize);
  2249. }
  2250.     else
  2251. {
  2252. /* Configure this register for PCI memory space */
  2253. spaceEnable = PCI_CMD_MEM_ENABLE;
  2254. baseaddr_mask = 0xFFFFFFF0;
  2255. register64Bit = pciAutoMemAlloc (pSystem, pPciFunc, &addr, nSize,
  2256.   addrInfo);
  2257. }
  2258.     /*
  2259.      * Do not exceed the upper boundary! If this occurs, all we can
  2260.      * do here is return, as this is called early in the initialization
  2261.      * process, before I/O is available to print error messages.
  2262.      */
  2263.     if (addr != NO_ALLOCATION)
  2264. {
  2265. /* Program the base address register */
  2266. PCI_AUTO_DEBUG_MSG("pciAutoRegConfig:[0x%08x] written to BAR[0x%08x]n",
  2267. addr, baseAddr, 0, 0, 0, 0);
  2268. pciConfigModifyLong (pPciFunc->bus, pPciFunc->device,
  2269. pPciFunc->function, baseAddr,
  2270. baseaddr_mask, addr);
  2271. if (register64Bit)
  2272.     {
  2273.     /*
  2274.      * Write the base address for 64-bit addressable memory devices:
  2275.      * initialize the next base address register to zero, the PReP
  2276.      * address map does support physical addresses above 4GB (i.e.,
  2277.      * 32-bit address space)
  2278.      */
  2279.     pciConfigOutLong (pPciFunc->bus, pPciFunc->device,
  2280.     pPciFunc->function,
  2281.     baseAddr + 4, 0);
  2282.     }
  2283. /* Set the appropriate enable bit, preserve status bits */
  2284. pciConfigModifyLong (pPciFunc->bus, pPciFunc->device,
  2285.  pPciFunc->function, PCI_CFG_COMMAND,
  2286.  (0xffff0000 | spaceEnable), spaceEnable);
  2287. }
  2288.     /* copy back to PCI_SYSTEM struct for backward compatibility */
  2289.     pciAutoConfigCopyback(pSystem, pSys);
  2290.     return (register64Bit);
  2291.     }
  2292. /******************************************************************************
  2293. *
  2294. * pciAutoIoAlloc - Select appropriate I/O space for device.
  2295. *
  2296. * This routine determines which PCI I/O space (16-bit or 32-bit) to assign
  2297. * to a particular function.  Note that functions located on subordinate
  2298. * busses must be  assigned to the 16 bit PCI I/O space due to 16 bit
  2299. * decoder limitations of certain bridges and functions.  The PCI
  2300. * specification limits each I/O base address register to 256 bytes, so
  2301. * this size should not be a problem.
  2302. *
  2303. * RETURNS: 0, indicating I/O space not located anywhere in 64-bit space.
  2304. */
  2305. LOCAL UINT pciAutoIoAlloc
  2306.     (
  2307.     PCI_AUTO_CONFIG_OPTS * pPciSys, /* PCI system structure   */
  2308.     PCI_LOC *pPciFunc, /* input: Pointer to PCI function element     */
  2309.     UINT *pAlloc, /* output: Pointer to PCI space alloc pointer */
  2310.     UINT nSize /* requested size (power of 2) */
  2311.     )
  2312.     {
  2313.     UINT * pBase;
  2314.     UINT32 alignedBase;
  2315.     UINT32 sizeAdj;
  2316.     UINT * pAvail = NULL;
  2317.     STATUS retStat = ERROR;
  2318.     /* Assign this register to PCI I/O space */
  2319.     if ((pPciFunc->bus == 0) &&
  2320.         ((pPciFunc->attribute & PCI_AUTO_ATTR_BUS_4GB_IO) != 0))
  2321. {
  2322. PCI_AUTO_DEBUG_MSG("pciAutoIoAlloc: 32-bit I/On", 0, 0, 0, 0, 0, 0);
  2323. pBase = &(pPciSys->pciIo32);
  2324. pAvail = &(pPciSys->pciIo32Size);
  2325. }
  2326.     else
  2327. {
  2328. PCI_AUTO_DEBUG_MSG("pciAutoIoAlloc: 16-bit I/On", 0, 0, 0, 0, 0, 0);
  2329. pBase = &(pPciSys->pciIo16);
  2330. pAvail = &(pPciSys->pciIo16Size);
  2331. }
  2332.     /* Adjust for alignment */
  2333.     if (*pAvail > 0)
  2334. {
  2335. retStat = pciAutoAddrAlign (*pBase,
  2336.     (*pBase + *pAvail),
  2337.     nSize,
  2338.     &alignedBase);
  2339. }
  2340.     /* If the space is exhausted, then return an invalid pointer */
  2341.     if (retStat == ERROR)
  2342. {
  2343.         PCI_LOG_MSG("Warning: PCI I/O allocation failedn",
  2344.  0, 0, 0, 0, 0, 0);
  2345. *pAlloc = NO_ALLOCATION;
  2346. return 0;
  2347. }
  2348.     PCI_AUTO_DEBUG_MSG("pciAutoIoAlloc: Pre/Post alloc: n",
  2349.  0, 0, 0, 0, 0, 0);
  2350.     PCI_AUTO_DEBUG_MSG("  Pre: pBase[0x%08x], pAvail[0x%08x]n",
  2351.     (int)(*pBase), (int)(*pAvail), 0, 0, 0, 0);
  2352.     *pAlloc  = alignedBase;
  2353.     sizeAdj = (alignedBase - *pBase) + nSize;
  2354.     *pBase  += sizeAdj;
  2355.     *pAvail -= sizeAdj;
  2356.     /* update size used in option struct */
  2357.     if ((pPciFunc->bus == 0) &&
  2358.         ((pPciFunc->attribute & PCI_AUTO_ATTR_BUS_4GB_IO) != 0))
  2359. {
  2360. pPciSys->pciIo32Used += sizeAdj;
  2361. }
  2362.     else
  2363. {
  2364. pPciSys->pciIo16Used += sizeAdj;
  2365. }
  2366.     PCI_AUTO_DEBUG_MSG("  Post: pBase[0x%08x], pAvail[0x%08x]n",
  2367.     (int)(*pBase), (int)(*pAvail), 0, 0, 0, 0);
  2368.     return 0; /* can't have 64 bit i/o addresses */
  2369.     }
  2370. /******************************************************************************
  2371. *
  2372. * pciAutoMemAlloc - Select appropriate memory space for device.
  2373. *
  2374. * This routine determines which PCI memory space pool to use for assignment
  2375. * to a particular function.  Note that functions located on subordinate
  2376. * busses must be  assigned to the 32 bit PCI memory space due to 32 bit
  2377. * requirements of functions using more than 1MB memory space.
  2378. *
  2379. * LIMITATIONS:
  2380. *
  2381. * Does not support 64-bit Memory space
  2382. *
  2383. * RETURNS: Returns 1 if 64-bit addressable memory space.
  2384. * Returns zero (0) otherwise.
  2385. */
  2386. LOCAL UINT pciAutoMemAlloc
  2387.     (
  2388.     PCI_AUTO_CONFIG_OPTS * pPciSys, /* PCI system structure */
  2389.     PCI_LOC * pPciFunc,  /* Pointer to PCI function element     */
  2390.     UINT * pAlloc,    /* Pointer to PCI space alloc pointer */
  2391.     UINT size, /* space requested (power of 2)  */
  2392.     UINT addrInfo /* PCI address type information       */
  2393.     )
  2394.     {
  2395.     UINT register64Bit = 0; /* 64 bit register flag */
  2396.     UINT * pBase;
  2397.     UINT * pAvail;
  2398.     UINT32 alignedBase;
  2399.     UINT32 sizeAdj;
  2400.     STATUS retStat = ERROR;
  2401.     UINT32 * pUpdate;
  2402.     /* Process address attribute info */
  2403.     switch (addrInfo & (UINT)PCI_BAR_MEM_TYPE_MASK )
  2404. {
  2405. case PCI_BAR_MEM_BELOW_1MB:
  2406.     break;
  2407. case PCI_BAR_MEM_ADDR64:
  2408.     /*
  2409.      * Check for a 64-bit addressable memory device, currently
  2410.      * the PReP address map does not support physical addresses
  2411.      * above 4Gb (i.e., 32-bits), so the configuration process
  2412.      * will initialize the upper base register to zero (i.e.,
  2413.      * the safe thing to do), so for right now we'll skip the
  2414.      * next base address register which belongs to the 64-bit
  2415.      * pair of 32-bit base address registers.
  2416.      */
  2417.     register64Bit = 1;
  2418.     break;
  2419. case PCI_BAR_MEM_ADDR32:
  2420.     break;
  2421. case PCI_BAR_MEM_RESERVED:
  2422.     /* fall through */
  2423. default:
  2424.     *pAlloc = NO_ALLOCATION;
  2425.     return 0;
  2426. }
  2427.     if ( (addrInfo & PCI_BAR_MEM_PREFETCH) &&
  2428.   ((pPciFunc->attribute) & PCI_AUTO_ATTR_BUS_PREFETCH) )
  2429. {
  2430. PCI_AUTO_DEBUG_MSG("pciAutoMemAlloc: PF Mem requested"
  2431. "n", 0, 0, 0, 0, 0, 0);
  2432. pBase = &(pPciSys->pciMem32);
  2433. pAvail = &(pPciSys->pciMem32Size);
  2434. pUpdate = &(pPciSys->pciMem32Used);
  2435. if (*pAvail > 0)
  2436.     {
  2437.     retStat = pciAutoAddrAlign (*pBase,
  2438. (*pBase + *pAvail),
  2439. size,
  2440. &alignedBase);
  2441.     }
  2442. if (retStat == ERROR)
  2443.     {
  2444.     /* If no PF memory available, then try conventional */
  2445.     PCI_AUTO_DEBUG_MSG("pciAutoMemAlloc: No PF Mem available"
  2446.     "Trying MemIOn", 0, 0, 0, 0, 0, 0);
  2447.     pBase = &(pPciSys->pciMemIo32);
  2448.     pAvail = &(pPciSys->pciMemIo32Size);
  2449.     pUpdate = &(pPciSys->pciMemIo32Used);
  2450.     if (*pAvail > 0)
  2451. {
  2452. retStat = pciAutoAddrAlign (*pBase,
  2453.     (*pBase + *pAvail),
  2454.     size,
  2455.     &alignedBase);
  2456. }
  2457.     if (retStat == ERROR)
  2458. {
  2459. PCI_LOG_MSG("Warning: PCI PF Mem alloc failedn",
  2460.  0, 0, 0, 0, 0, 0);
  2461. *pAlloc = NO_ALLOCATION;
  2462. return 0;
  2463. }
  2464.     }
  2465. }
  2466.     else
  2467. {
  2468. /* Use 32-bit Non-Prefetch Memory */
  2469. pBase = &(pPciSys->pciMemIo32);
  2470. pAvail = &(pPciSys->pciMemIo32Size);
  2471. pUpdate = &(pPciSys->pciMemIo32Used);
  2472. if (*pAvail > 0)
  2473.     {
  2474.     retStat = pciAutoAddrAlign (*pBase,
  2475. (*pBase + *pAvail),
  2476. size,
  2477. &alignedBase);
  2478.     }
  2479. if (retStat == ERROR)
  2480.     {
  2481.     PCI_LOG_MSG("Warning: PCI Memory allocation failedn",
  2482.  0, 0, 0, 0, 0, 0);
  2483.     *pAlloc = NO_ALLOCATION;
  2484.     return 0;
  2485.     }
  2486. }
  2487.     PCI_AUTO_DEBUG_MSG("pciAutoMemAlloc: n", 0, 0, 0, 0, 0, 0);
  2488.     PCI_AUTO_DEBUG_MSG("  Pre: pBase[0x%08x], pAvail[0x%08x]n",
  2489.     (int)(*pBase), (int)(*pAvail), 0, 0, 0, 0);
  2490.     *pAlloc  = alignedBase;
  2491.     sizeAdj = (alignedBase - *pBase) + size;
  2492.     *pBase  += sizeAdj;
  2493.     *pAvail -= sizeAdj;
  2494.     /* update size used in option struct */
  2495.     *pUpdate += sizeAdj;
  2496.     PCI_AUTO_DEBUG_MSG("  Post: pBase[0x%08x], pAvail[0x%08x]n",
  2497.     (int)(*pBase), (int)(*pAvail), 0, 0, 0, 0);
  2498.     return register64Bit;
  2499.     }
  2500. /******************************************************************************
  2501. *
  2502. * pciAutoBusConfig - Set mem and I/O registers for a single PCI-PCI bridge.
  2503. *
  2504. * This routine sets up memory and I/O base/limit registers for
  2505. * an individual PCI-PCI bridge.
  2506. *
  2507. * PCI/PCI bridges require that memory space assigned to functions
  2508. * on the secondary bus reside in one common block defined by a memory
  2509. * base register and a memory limit register, and I/O space assigned to
  2510. * functions on the secondary bus must reside in one common block defined
  2511. * by an I/O base register and an I/O limit register.  This effectively
  2512. * prevents the use of 32 bit PCI I/O space on subordinate (non-zero)
  2513. * busses due to the 16 bit decoder limitations of certain bridges and
  2514. * functions.
  2515. *
  2516. * Note that functions which use 20 bit memory decoders must be placed
  2517. * on bus zero, or this code will have to be modified to impose a 20 bit
  2518. * restriction on all subordinate busses (since some PCI devices allocate
  2519. * huge memory spaces, a 1MB total restriction is unacceptable).
  2520. *
  2521. * Also note that this code does not provide prefetchable memory support
  2522. * at this time.
  2523. *
  2524. * Warning: do not sort the include function list before this routine is
  2525. * called.  This routine requires each function in the list to be in the
  2526. * same order as the probe occurred.
  2527. *
  2528. * RETURNS: N/A.
  2529. */
  2530. LOCAL void pciAutoBusConfig
  2531.     (
  2532.     PCI_AUTO_CONFIG_OPTS * pSystem, /* PCI system info */
  2533.     PCI_LOC * pPciLoc, /* PCI address of this bridge */
  2534.     PCI_LOC **ppPciList, /* Pointer to function list pointer */
  2535.     UINT *nSize /* Number of remaining functions */
  2536.     )
  2537.     {
  2538.     UCHAR bus; /* Bus number for current bus */
  2539.     UINT8 maxLatency; /* MAX_LAT value */
  2540.     UINT dev_vend;
  2541.     UINT32 debugTmp;
  2542.     UINT32 debugTmp2;
  2543.     UINT32 debugTmp3;
  2544.     UINT32 alignedBase;
  2545.     /* If it exists, call the user-defined pre-config pass bridge init */
  2546.     if ((pSystem->bridgePreConfigInit) != NULL )
  2547. {
  2548. pciConfigInLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2549.  PCI_CFG_VENDOR_ID, &dev_vend);
  2550. (pSystem->bridgePreConfigInit) ((PCI_SYSTEM *)pSystem, pPciLoc, dev_vend);
  2551. }
  2552.     /* Clear the secondary status bits */
  2553.     pciConfigModifyLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2554.                          PCI_CFG_IO_BASE, 0xffff0000, 0xffff0000);
  2555.     /* If Prefetch supported, then pre-configure 32-bit PF Memory Base Addr */
  2556.     if ( (pPciLoc->attribute & PCI_AUTO_ATTR_BUS_PREFETCH)
  2557. && (pSystem->pciMem32Size > 0) )
  2558. {
  2559. PCI_AUTO_DEBUG_MSG("pciAutoBusConfig: Configuring prefetch aperturen",
  2560. 0, 0, 0, 0, 0, 0);
  2561. pciAutoAddrAlign(pSystem->pciMem32,
  2562.  (pSystem->pciMem32 + pSystem->pciMem32Size),
  2563.  0x100000,
  2564.  &alignedBase);
  2565. PCI_AUTO_DEBUG_MSG("PF Mem Base orig[0x%08x] new[0x%08x] adj[0x%08x]n",
  2566.     (pSystem->pciMem32),
  2567.     alignedBase,
  2568.     (alignedBase - (pSystem->pciMem32)),
  2569.     0,
  2570.     0,
  2571.     0
  2572.     );
  2573. (pSystem->pciMem32Used) += (alignedBase - (pSystem->pciMem32));
  2574. (pSystem->pciMem32Size) -= (alignedBase - (pSystem->pciMem32));
  2575. (pSystem->pciMem32) = alignedBase;
  2576. /* 64-bit Prefetch memory not supported at this time */
  2577. pciConfigOutLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2578.   PCI_CFG_PRE_MEM_BASE_U, 0);
  2579. pciConfigModifyLong (pPciLoc->bus,pPciLoc->device,pPciLoc->function,
  2580.      PCI_CFG_PRE_MEM_BASE, 0x0000fff0,
  2581.      (pSystem->pciMem32 >> (20-4))
  2582.      );
  2583. pciConfigInLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2584. PCI_CFG_PRE_MEM_BASE,
  2585. &debugTmp2);
  2586. debugTmp = ((debugTmp2 & 0x0000fff0) << 16);
  2587. PCI_AUTO_DEBUG_MSG("pciAutoBusConfig: PF Mem Base [0x%08x]n",
  2588. debugTmp, 0, 0, 0, 0, 0);
  2589. }
  2590.     /* Pre-configure 16-bit I/O Base Address */
  2591.     if ((pSystem->pciIo16Size) > 0)
  2592. {
  2593. pciAutoAddrAlign(pSystem->pciIo16,
  2594.  (pSystem->pciIo16 + pSystem->pciIo16Size),
  2595.  0x1000,
  2596.  &alignedBase);
  2597. PCI_AUTO_DEBUG_MSG("I/O 16 Base orig[0x%08x] new[0x%08x] adj[0x%08x]n",
  2598.     (pSystem->pciIo16),
  2599.     alignedBase,
  2600.     (alignedBase - (pSystem->pciIo16)),
  2601.     0,
  2602.     0,
  2603.     0
  2604.     );
  2605. (pSystem->pciIo16Used) += (alignedBase - (pSystem->pciIo16));
  2606. (pSystem->pciIo16Size) -= (alignedBase - (pSystem->pciIo16));
  2607. (pSystem->pciIo16) = alignedBase;
  2608. pciConfigModifyLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2609.      PCI_CFG_IO_BASE, 0x000000f0,
  2610.      (pSystem->pciIo16 >> (12-4))
  2611.      );
  2612. pciConfigModifyLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2613.      PCI_CFG_IO_BASE_U, 0x0000ffff,
  2614.      (pSystem->pciIo16 >> 16)
  2615.      );
  2616. pciConfigInLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2617. PCI_CFG_IO_BASE,
  2618. &debugTmp);
  2619. pciConfigInLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2620. PCI_CFG_IO_BASE_U,
  2621. &debugTmp2);
  2622. debugTmp3 = (((debugTmp & (UINT32)0xf0) << (12-4)) & 0x0000ffff);
  2623.         debugTmp = debugTmp3 | ((debugTmp2 << 16) & 0xffff0000);
  2624. PCI_AUTO_DEBUG_MSG("pciAutoBusConfig: IO16 Base Address [0x%08x]n",
  2625. debugTmp, 0, 0, 0, 0, 0);
  2626. }
  2627.     /* Pre-configure 32-bit Non-prefetchable Memory Base Address */
  2628.     if ((pSystem->pciMemIo32Size) > 0)
  2629. {
  2630. pciAutoAddrAlign(pSystem->pciMemIo32,
  2631.  (pSystem->pciMemIo32 + pSystem->pciMemIo32Size),
  2632.  0x100000,
  2633.  &alignedBase);
  2634. PCI_AUTO_DEBUG_MSG("Memory Base orig[0x%08x] new[0x%08x] adj[0x%08x]n",
  2635.     (pSystem->pciMemIo32),
  2636.     alignedBase,
  2637.     (alignedBase - (pSystem->pciMemIo32)),
  2638.     0,
  2639.     0,
  2640.     0
  2641.     );
  2642. (pSystem->pciMemIo32Used) += (alignedBase - (pSystem->pciMemIo32));
  2643. (pSystem->pciMemIo32Size) -= (alignedBase - (pSystem->pciMemIo32));
  2644. (pSystem->pciMemIo32) = alignedBase;
  2645. pciConfigModifyLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2646.      PCI_CFG_MEM_BASE, 0x0000fff0,
  2647.      (pSystem->pciMemIo32 >> (20-4))
  2648.      );
  2649. pciConfigInLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2650. PCI_CFG_MEM_BASE,
  2651. &debugTmp2);
  2652. debugTmp = ((debugTmp2 & 0x0000fff0) << 16);
  2653. PCI_AUTO_DEBUG_MSG("pciAutoBusConfig: Mem Base Address [0x%08x]n",
  2654. debugTmp, 0, 0, 0, 0, 0);
  2655. }
  2656.     /* Configure devices on the bus implemented by this bridge */
  2657.     pciConfigInByte (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2658.      PCI_CFG_SECONDARY_BUS, &bus);
  2659.     pciAutoDevConfig (pSystem, bus, ppPciList, nSize);
  2660.     /* Post-configure 32-bit I/O Limit Address */
  2661.     if ((pSystem->pciIo16Size) > 0)
  2662. {
  2663. pciAutoAddrAlign(pSystem->pciIo16,
  2664.  (pSystem->pciIo16 + pSystem->pciIo16Size),
  2665.  0x1000,
  2666.  &alignedBase);
  2667. PCI_AUTO_DEBUG_MSG("I/O 16 Lim orig[0x%08x] new[0x%08x] adj[0x%08x]n",
  2668.     (pSystem->pciIo16),
  2669.     alignedBase,
  2670.     (alignedBase - (pSystem->pciIo16)),
  2671.     0,
  2672.     0,
  2673.     0
  2674.     );
  2675. (pSystem->pciIo16Used) += (alignedBase - (pSystem->pciIo16));
  2676. (pSystem->pciIo16Size) -= (alignedBase - (pSystem->pciIo16));
  2677. (pSystem->pciIo16) = alignedBase;
  2678. pciConfigModifyLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2679.      PCI_CFG_IO_BASE, 0x0000f000,
  2680.      (pSystem->pciIo16 - 1)
  2681.      );
  2682. pciConfigModifyLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2683.      PCI_CFG_IO_BASE_U, 0xffff0000,
  2684.      (pSystem->pciIo16 - 1)
  2685.      );
  2686. pciConfigInLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2687. PCI_CFG_IO_BASE,
  2688. &debugTmp);
  2689. pciConfigInLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2690. PCI_CFG_IO_BASE_U,
  2691. &debugTmp2);
  2692. debugTmp3 = ((debugTmp & (UINT32)0xf000) & 0x0000ffff);
  2693.         debugTmp = debugTmp3 | (debugTmp2 & 0xffff0000);
  2694. debugTmp |= 0x00000FFF;
  2695. PCI_AUTO_DEBUG_MSG("pciAutoBusConfig: IO Limit [0x%08x]n",
  2696. debugTmp, 0, 0, 0, 0, 0);
  2697. }
  2698.     /* Post-configure 32-bit Non-prefetchable Memory Limit Address */
  2699.     if ((pSystem->pciMemIo32Size) > 0)
  2700. {
  2701. pciAutoAddrAlign(pSystem->pciMemIo32,
  2702.  (pSystem->pciMemIo32 + pSystem->pciMemIo32Size),
  2703.  0x100000,
  2704.  &alignedBase);
  2705. PCI_AUTO_DEBUG_MSG("MemIo Lim orig[0x%08x] new[0x%08x] adj[0x%08x]n",
  2706.     (pSystem->pciMemIo32),
  2707.     alignedBase,
  2708.     (alignedBase - (pSystem->pciMemIo32)),
  2709.     0,
  2710.     0,
  2711.     0
  2712.     );
  2713. (pSystem->pciMemIo32Used) += (alignedBase - (pSystem->pciMemIo32));
  2714. (pSystem->pciMemIo32Size) -= (alignedBase - (pSystem->pciMemIo32));
  2715. (pSystem->pciMemIo32) = alignedBase;
  2716. pciConfigModifyLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2717.      PCI_CFG_MEM_BASE, 0xfff00000,
  2718.      (pSystem->pciMemIo32 - 1)
  2719.      );
  2720. pciConfigInLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2721. PCI_CFG_MEM_BASE,
  2722. &debugTmp2);
  2723. debugTmp = (debugTmp2 & 0xfff00000);
  2724. debugTmp |= 0x000FFFFF;
  2725. PCI_AUTO_DEBUG_MSG("pciAutoBusConfig: MemIo Limit [0x%08x]n",
  2726. debugTmp, 0, 0, 0, 0, 0);
  2727. }
  2728.     /* Post-configure 32-bit Prefetchable Memory Address */
  2729.     if ( (pPciLoc->attribute & PCI_AUTO_ATTR_BUS_PREFETCH) &&
  2730.          ((pSystem->pciMem32Size) > 0) )
  2731. {
  2732. pciAutoAddrAlign(pSystem->pciMem32,
  2733.  (pSystem->pciMem32 + pSystem->pciMem32Size),
  2734.  0x100000,
  2735.  &alignedBase);
  2736. PCI_AUTO_DEBUG_MSG("PF Lim orig[0x%08x] new[0x%08x] adj[0x%08x]n",
  2737.     (pSystem->pciMem32),
  2738.     alignedBase,
  2739.     (alignedBase - (pSystem->pciMem32)),
  2740.     0,
  2741.     0,
  2742.     0
  2743.     );
  2744. (pSystem->pciMem32Used) += (alignedBase - (pSystem->pciMem32));
  2745. (pSystem->pciMem32Size) -= (alignedBase - (pSystem->pciMem32));
  2746. (pSystem->pciMem32) = alignedBase;
  2747. /* 64-bit Prefetchable memory not supported at this time */
  2748. pciConfigOutLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2749.   PCI_CFG_PRE_MEM_LIMIT_U, 0);
  2750. pciConfigModifyLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2751.      PCI_CFG_PRE_MEM_BASE, 0xfff00000,
  2752.      (pSystem->pciMem32 - 1)
  2753.      );
  2754. pciConfigInLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2755. PCI_CFG_PRE_MEM_BASE,
  2756. &debugTmp2);
  2757. debugTmp = (debugTmp2 & 0xfff00000);
  2758. debugTmp |= 0x000FFFFF;
  2759. PCI_AUTO_DEBUG_MSG("pciAutoBusConfig: PF Mem Limit [0x%08x]n",
  2760. debugTmp, 0, 0, 0, 0, 0);
  2761. }
  2762.     if ((pSystem->bridgePostConfigInit) != NULL )
  2763. {
  2764. pciConfigInLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2765.  PCI_CFG_VENDOR_ID, &dev_vend);
  2766. (pSystem->bridgePostConfigInit) ((PCI_SYSTEM *)pSystem, pPciLoc, dev_vend);
  2767. }
  2768.     /* Initialize primary and secondary PCI-PCI bridge latency timers */
  2769.     /*
  2770.     *  If MAX_LAT function supplied by BSP, call it to calculate
  2771.     *  the value of MAX_LAT for each function individually.
  2772.     *  Otherwise, use the default value for all functions.
  2773.     */
  2774.     if ( ( pPciCfgOpts->pciConfigInit == TRUE ) &&
  2775.          ( pPciCfgOpts->pciMaxLatFunc != NULL ) )
  2776.         {
  2777.         /* find value by calling user-supplied function */
  2778.         maxLatency = (*pPciCfgOpts->pciMaxLatFunc)
  2779.                         (pPciLoc->bus,pPciLoc->device,pPciLoc->function,
  2780. pPciCfgOpts->pciMaxLatPArg);
  2781.         }
  2782.     else
  2783.         {
  2784.         /* use default value */
  2785.         maxLatency = pSystem->maxLatency;
  2786.         }
  2787.     /* actually set MAX_LAT for this function */
  2788.     pciConfigOutByte (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2789.                       PCI_CFG_SEC_LATENCY, maxLatency);
  2790.     /* Clear status bits turn on downstream and upstream (master) mem,IO */
  2791.     pciConfigOutLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function,
  2792.                       PCI_CFG_COMMAND,
  2793.       (UINT32)(0xffff0000 | PCI_CMD_IO_ENABLE |
  2794.       PCI_CMD_MEM_ENABLE | PCI_CMD_MASTER_ENABLE)
  2795.       );
  2796.     }
  2797. /*******************************************************************************
  2798. *
  2799. * pciAutoAddrAlign - Align a PCI address and check boundary conditions.
  2800. *
  2801. * RETURNS: OK, or ERROR if available memory has been exceeded.
  2802. *
  2803. */
  2804. STATUS pciAutoAddrAlign
  2805.     (
  2806.     UINT32 base, /* base of available memory */
  2807.     UINT32 limit, /* last addr of available memory */
  2808.     UINT32 reqSize, /* required size */
  2809.     UINT32 *pAlignedBase /* output: aligned address put here */
  2810.     )
  2811.     {
  2812.     UINT32 sizeMask;
  2813.     UINT32 alignAdjust;
  2814.     /* make the size mask */
  2815.     sizeMask = reqSize - 1;
  2816.     PCI_AUTO_DEBUG_MSG("pciAutoAddrAlign: sizemask[%08x]n",sizeMask,0,0,0,0,0);
  2817.     /* see if the address needs to be adjusted */
  2818.     if ((base & sizeMask) > 0)
  2819.         {
  2820.         alignAdjust = reqSize - (base & sizeMask);
  2821. PCI_AUTO_DEBUG_MSG ("pciAutoAddrAlign: adjustment [%08x]n",alignAdjust,
  2822.     0,0,0,0,0);
  2823.         }
  2824.     else
  2825.         {
  2826. PCI_AUTO_DEBUG_MSG("pciAutoAddrAlign: already alignedn",0,0,0,0,0,0);
  2827.         alignAdjust = 0;
  2828.         }
  2829.     /* see if the aligned base exceeds the resource boundary */
  2830.     if ( ((base + alignAdjust) < base) ||
  2831.  ((base + alignAdjust) > limit) )
  2832.         {
  2833.         PCI_AUTO_DEBUG_MSG ("pciAutoAddrAlign: base + adjustment [%08x]"
  2834.     " exceeds limit [%08x]n", (base + alignAdjust),
  2835.     limit,
  2836.     0,0,0,0);
  2837.         return ERROR;
  2838.         }
  2839.     *pAlignedBase = base + alignAdjust;
  2840.     /* see if the aligned base+size exceeds the resource boundary */
  2841.     if ( ((base + alignAdjust + reqSize) < base) ||
  2842.          ((base + alignAdjust + reqSize) > limit) )
  2843.         {
  2844.         PCI_AUTO_DEBUG_MSG ("pciAutoAddrAlign: base + adjustment + req [%08x]"
  2845.     " exceeds limit [%08x]n",
  2846.     (base + alignAdjust + reqSize),limit,0,0,0,0);
  2847.         return ERROR;
  2848.         }
  2849.     PCI_AUTO_DEBUG_MSG ("pciAutoAddrAlign: new aligned base [%08x]n",
  2850. (base + alignAdjust),0,0,0,0,0);
  2851.     return OK;
  2852.     }
  2853. /**********************************************************************
  2854. *
  2855. * pciFBBFuncSet - enable Fast Back To Back on specified function.
  2856. *
  2857. * pciFBBFuncSet() turns on FBB on the specified function.  This function
  2858. * is intended for use with pciConfigForeachFunc().
  2859. *
  2860. * If the device fails to return a valid status word, then
  2861. * return ERROR without modifying FBB enable.
  2862. *
  2863. * ERRNO: not set
  2864. *
  2865. * RETURNS: OK, or ERROR if fast back to back is not supported.
  2866. */
  2867. LOCAL STATUS pciFBBFuncSet
  2868.     (
  2869.     UINT bus, /* bus */
  2870.     UINT device, /* device */
  2871.     UINT function, /* function */
  2872.     void * pArg /* not used */
  2873.     )
  2874.     {
  2875.     UINT16 pciStatus; /* PCI status register */
  2876.     /* check if this device supports Fast Back To Back */
  2877.     pciConfigInWord (bus, device, function, PCI_CFG_STATUS, &pciStatus);
  2878.     if ( ! ( pciStatus & PCI_STATUS_FAST_BB ) )
  2879. return(ERROR);
  2880.     /* turn FBB on */
  2881.     pciConfigModifyLong (bus, device, function, PCI_CFG_COMMAND,
  2882.       (PCI_CMD_MASK | PCI_CMD_FBTB_ENABLE),
  2883. PCI_CMD_FBTB_ENABLE);
  2884.     return(OK);
  2885.     }
  2886. /**********************************************************************
  2887. *
  2888. * pciFBBFuncCheck - check Fast Back To Back on specified function.
  2889. *
  2890. * pciFBBFuncCheck() checks whether the function supports FBB
  2891. *
  2892. * If the device fails to return a valid status word, then
  2893. * return ERROR without modifying FBB enable.
  2894. *
  2895. * ERRNO: not set
  2896. *
  2897. * RETURNS: OK, or ERROR if fast back to back is not supported.
  2898. *
  2899. */
  2900. LOCAL STATUS pciFBBFuncCheck
  2901.     (
  2902.     UINT bus, /* bus */
  2903.     UINT device, /* device */
  2904.     UINT function, /* function */
  2905.     void * pArg /* not used */
  2906.     )
  2907.     {
  2908.     UINT16 pciStatus; /* PCI status register */
  2909.     /* check if this device supports Fast Back To Back */
  2910.     pciConfigInWord (bus, device, function, PCI_CFG_STATUS, &pciStatus);
  2911.     if ( ! ( pciStatus & PCI_STATUS_FAST_BB ) )
  2912. return(ERROR);
  2913.     return(OK);
  2914.     }
  2915. /**********************************************************************
  2916. *
  2917. * pciFBBFuncClear - disable Fast Back To Back on specified function.
  2918. *
  2919. * pciFBBFuncClear() turns off FBB on the specified function.
  2920. *
  2921. * ERRNO: not set
  2922. *
  2923. * RETURNS: OK, always.
  2924. *
  2925. */
  2926. LOCAL STATUS pciFBBFuncClear
  2927.     (
  2928.     UINT bus, /* bus */
  2929.     UINT device, /* device */
  2930.     UINT function, /* function */
  2931.     void * pArg /* not used */
  2932.     )
  2933.     {
  2934.     UINT16 pciStatus; /* PCI status register */
  2935.     /* check if this device supports Fast Back To Back */
  2936.     pciConfigInWord (bus, device, function, PCI_CFG_STATUS, &pciStatus);
  2937.     if ( pciStatus & PCI_STATUS_FAST_BB )
  2938. {
  2939. /* turn FBB off */
  2940. pciConfigModifyLong (bus, device, function, PCI_CFG_COMMAND,
  2941.     (PCI_CMD_MASK | PCI_CMD_FBTB_ENABLE), 0);
  2942. }
  2943.     return(OK);
  2944.     }
  2945. /**********************************************************************
  2946. *
  2947. * pciAutoConfigFBBEnable - enable Fast Back To Back.
  2948. *
  2949. * pciAutoConfigFBBEnable() discovers the functions present
  2950. * and verifies that each of them can support FBB.  At any time,
  2951. * if it finds a device which cannot handle FBB, it returns ERROR.
  2952. * If all listed devices do support FBB, then it makes a second
  2953. * pass through the list, and enables FBB on all listed functions.
  2954. *
  2955. * If any device fails to return a valid status word, then
  2956. * pciAutoConfigFBBEnable() will immediately return ERROR without
  2957. * modifying FBB enable on any cards which have already been enabled
  2958. * and without finishing the list.
  2959. *
  2960. * ERRNO:
  2961. *      EINVAL if FBB is not enabled
  2962. *
  2963. * RETURNS: OK, or ERROR if fast back to back has not been enabled.
  2964. *
  2965. */
  2966. LOCAL STATUS pciAutoConfigFBBEnable
  2967.     (
  2968.     PCI_AUTO_CONFIG_OPTS * pOpts /* system configuration information */
  2969.     )
  2970.     {
  2971.     STATUS status;
  2972.     if ( pOpts->pciFBBEnable != TRUE )
  2973.         {
  2974.         errnoSet(EINVAL);
  2975.         return(ERROR);
  2976.         }
  2977.     /* discover devices and check for FBB implemented */
  2978.     status = pciFBBFuncCheck(0,0,0,NULL);
  2979.     if ( status != OK )
  2980. return(ERROR);
  2981.     status = pciConfigForeachFunc(0, TRUE, (PCI_FOREACH_FUNC)pciFBBFuncCheck, NULL);
  2982.     if ( status != OK )
  2983. return(ERROR);
  2984.     /* all are FBB aware, so enable devices */
  2985.     status = pciFBBFuncSet(0,0,0,NULL);
  2986.     if ( status != OK )
  2987. return(status);
  2988.     status = pciConfigForeachFunc(0, TRUE, (PCI_FOREACH_FUNC)pciFBBFuncSet, NULL);
  2989.     return(status);
  2990.     }
  2991. /**********************************************************************
  2992. *
  2993. * pciAutoConfigFBBDisable - disable Fast Back To Back.
  2994. *
  2995. * pciAutoConfigFBBDisable() goes through the list of PCI functions
  2996. * and disables FBB on all listed functions.
  2997. *
  2998. * If any device fails to return a valid status word, then
  2999. * pciAutoConfigFBBDisable() will continue disabling FBB on the
  3000. * remaining functions, but will return ERROR after finishing.
  3001. *
  3002. * ERRNO: Not set
  3003. *
  3004. * RETURNS: OK, or ERROR if fast back to back was not previously enabled.
  3005. *
  3006. */
  3007. LOCAL STATUS pciAutoConfigFBBDisable
  3008.     (
  3009.     PCI_AUTO_CONFIG_OPTS * pOpts /* system configuration information */
  3010.     )
  3011.     {
  3012.     STATUS status;
  3013.     if ( pOpts->pciFBBEnable != TRUE )
  3014.         {
  3015.         return(ERROR);
  3016.         }
  3017.     pOpts->pciFBBEnable = FALSE;
  3018.     /* discover devices and disable FBB */
  3019.     status = pciConfigForeachFunc(0, TRUE, (PCI_FOREACH_FUNC)pciFBBFuncClear, NULL);
  3020.     return(status);
  3021.     }
  3022. /* backward compatibility functions */
  3023. /**********************************************************************
  3024. *
  3025. * pciAutoConfigCopyback - copy data back to the pSystem struct.
  3026. *
  3027. * pciAutoConfigLib backwards compatibility function.
  3028. *
  3029. * The old interface for pciAutoConfigLib allowed the user to
  3030. * look at the values of pSystem after pciAutoConfig() had
  3031. * run.  This let them look at various values and determine
  3032. * system behavior based on how they changed.  The new interface
  3033. * does not have this behavior.
  3034. *
  3035. * To insure backwards compatibility, every time any of the functions
  3036. * visible to the user is called, when the function completes, it
  3037. * copies information back to the pSystem structure by calling
  3038. * this routine.
  3039. *
  3040. * ERRNO: not set
  3041. *
  3042. * RETURNS: N/A.
  3043. *
  3044. */
  3045. LOCAL void pciAutoConfigCopyback
  3046.     (
  3047.     PCI_AUTO_CONFIG_OPTS * pOpts, /* system configuration info */
  3048.     PCI_SYSTEM * pSystem /* PCI_SYSTEM to copy into */
  3049.     )
  3050.     {
  3051.     if ( pSystem == (PCI_SYSTEM *)pOpts )
  3052. return;
  3053.     pSystem->pciMem32 = pOpts->pciMem32;
  3054.     pSystem->pciMem32Size = pOpts->pciMem32Size;
  3055.     pSystem->pciMemIo32 = pOpts->pciMemIo32;
  3056.     pSystem->pciMemIo32Size = pOpts->pciMemIo32Size;
  3057.     pSystem->pciIo32 = pOpts->pciIo32;
  3058.     pSystem->pciIo32Size = pOpts->pciIo32Size;
  3059.     pSystem->pciIo16 = pOpts->pciIo16;
  3060.     pSystem->pciIo16Size = pOpts->pciIo16Size;
  3061.     pSystem->maxBus = pOpts->maxBus;
  3062.     pSystem->cacheSize = pOpts->cacheSize;
  3063.     pSystem->maxLatency = pOpts->maxLatency;
  3064.     pSystem->autoIntRouting = pOpts->autoIntRouting;
  3065.     pSystem->includeRtn = pOpts->includeRtn;
  3066.     pSystem->bridgePreConfigInit = pOpts->bridgePreConfigInit;
  3067.     pSystem->bridgePostConfigInit = pOpts->bridgePostConfigInit;
  3068.     pSystem->pciRollcallRtn = pOpts->pciRollcallRtn;
  3069.     pSystem->intAssignRtn = (void *)pOpts->intAssignRtn;
  3070.     }
  3071. /******************************************************************************
  3072. *
  3073. * pciAutoConfig - Automatically configure all nonexcluded PCI headers.  Obsolete.
  3074. *
  3075. * This routine is obsolete.  It is included for backward compatibility only.
  3076. * It is recommended that you use the pciAutoCfg() interface instead of
  3077. * this one.
  3078. *
  3079. * Top level function in the PCI configuration process.
  3080. *
  3081. * For all nonexcluded PCI functions on all PCI bridges, this routine
  3082. * will automatically configure the PCI configuration headers for PCI
  3083. * devices and subbridges.  The fields that are programmed are:
  3084. *
  3085. * .IP 1. 4
  3086. * Status register.
  3087. * .IP 2. 4
  3088. * Command Register.
  3089. * .IP 3. 4
  3090. * Latency timer.
  3091. * .IP 4. 4
  3092. * Cache Line size.
  3093. * .IP 5. 4
  3094. * Memory and/or I/O base address and limit registers.
  3095. * .IP 6. 4
  3096. * Primary, secondary, subordinate bus number (for PCI-PCI bridges).
  3097. * .IP 7. 4
  3098. * Expansion ROM disable.
  3099. * .IP 8. 4
  3100. * Interrupt Line.
  3101. * .LP
  3102. *
  3103. * ALGORITHM:
  3104. *
  3105. * Probe PCI config space and create a list of available PCI functions.
  3106. * Call device exclusion function, if registered, to exclude/include device.
  3107. * Disable all devices before we initialize any.
  3108. * Allocate and assign PCI space to each device.
  3109. * Calculate and set interrupt line value.
  3110. * Initialize and enable each device.
  3111. *
  3112. * RETURNS: N/A.
  3113. *
  3114. */
  3115. void pciAutoConfig
  3116.     (
  3117.     PCI_SYSTEM * pSystem /* PCI system to configure */
  3118.     )
  3119.     {
  3120.     PCI_AUTO_CONFIG_OPTS *pCookie;
  3121.     pCookie = pciAutoConfigLibInit(NULL);
  3122.     pciAutoCfgCtl(pCookie, PCI_PSYSTEM_STRUCT_COPY, (void *)pSystem);
  3123.     pciAutoCfgFunc(pCookie);
  3124.     pciAutoConfigCopyback(pCookie, pSystem);
  3125.     }