Main Page   File List   File Members  

sysLib.c

Go to the documentation of this file.
00001 /* sysLib.c - Motorola MVME2100 board series system-dependent library */
00003 /* Copyright 1984-2000 Wind River Systems, Inc. */
00004 /* Copyright 1996-2000 Motorola, Inc. All Rights Reserved */
00005 
00006 /*
00007 modification history
00008 --------------------
00009 * #ifdef APS_BSP
00010 aps,06jul01,anj  APS mods.
00011 * #endif  APS_BSP 
00012 01u,14jul00,rcs  fixed path to pciConfigShow.c
00013 01t,15jun00,dmw  updated following WRS code review.
00014 01s,08feb00,rhk  Modified sysMemProbeBus to allow the vxMemProbe call
00015                  to work properly.
00016 01r,25jun99,srr  remove #ifdef INCLUDE_PCI_AUTOCONF around sysDynEnetFind.
00017 01q,24jun99,srr  reset the EPIC in sysToMonitor.
00018 01p,23jun99,srr  restored call to sysUniverseInit2 in sysProcNumSet.
00019 01o,21jun99,srr  added support for running PCI Auto Config in bootrom only.
00020 01n,04jun99,rhk  removed the "ifdef INCLUDE_END"s, changed dec214x to
00021                  dec21x40, removed the routine sysDec21x40EnetAddrGet, 
00022                  removed addition of SERIAL_INTERRUPT_BASE value from 
00023                  calculations of ivec and ilevel, moved the sysUniverseInit2
00024                  call from sysProcNumSet to sysHwInit2.
00025 01m,29apr99,rhk  changes to support the Tornado 2 environment and SENS.
00026 01l,28apr99,dmw  Removed trigraph in sysPhysMemTop and replaced dynamic
00027                  memory sizing with a real routine.
00028 01k,16apr99,rhk  changed PCI_xxx define names, changed page table window
00029                  sizes, changed VME LM define names.
00030 01j,08apr99,dmw  added VPD code.
00031 01i,05apr99,rhk  removed legacy code, moved the xxxSpd routines to 
00032                  sysSpeed.c.
00033 01h,12mar99,rhk  changes for Shared memory support, removed EIEIO_SYNC macro
00034                  and replaced with SYNC macro.
00035 01g,24feb99,rhk  added PCI autoconfiguration support, setup UNIVERSE for PCI
00036                  autoconfig and removed UNIV I legacy code.
00037 01f,17feb99,srr  Added SENS support.
00038 01e,17feb99,rhk  removed speed functions.
00039 01d,15feb99,rhk  removed last instances of IBC references.
00040 01c,12feb99,rhk  more legacy cleanup, setup for auxclk, used the MV2400
00041                  version of sysLib.c as a basis for mods.
00042 01b,08feb98,rhk  updated the page table entries (sysPhysMemDesc) for mv2100
00043                  and started removing legacy code.
00044 01a,11dec98,srr  created. (from ver 02h of mv2600/sysLib.c bsp)
00045 */
00046 
00047 /*
00048 DESCRIPTION
00049 This library provides board-specific routines.  The chip drivers included are:
00050 
00051     i8250Sio.c - Intel 8250 UART driver 
00052     ppcDecTimer.c - PowerPC decrementer timer library (system clock)
00053     byteNvRam.c - byte-oriented generic non-volatile RAM library
00054     pciConfigLib.c - PCI configuration library
00055     universe.c - Tundra Universe chip VME-to-PCI interface library
00056     kahluaEpic.c - Kahlua Interrupt Controller
00057     sysI2cDrv.c - Kahlua I2C interface driver
00058 
00059 INCLUDE FILES: sysLib.h
00060 
00061 SEE ALSO:
00062 .pG "Configuration"
00063 */
00064 
00065 /* includes */
00066 
00067 #include "vxWorks.h"
00068 #include "vme.h"
00069 #include "memLib.h"
00070 #include "cacheLib.h"
00071 #include "sysLib.h"
00072 #include "config.h"
00073 #include "string.h"
00074 #include "intLib.h"
00075 #include "esf.h"
00076 #include "excLib.h"
00077 #include "logLib.h"
00078 #include "taskLib.h"
00079 #include "vxLib.h"
00080 #include "tyLib.h"
00081 #include "drv/end/dec21x40End.h"
00082 #include "arch/ppc/archPpc.h"
00083 #include "arch/ppc/mmu603Lib.h"
00084 #include "arch/ppc/vxPpcLib.h"
00085 #include "arch/ppc/excPpcLib.h"
00086 #include "private/vmLibP.h"
00087 #include "drv/pci/pciConfigLib.h"
00088 #include "kahluaMemParam.h"
00089 #include "sysMotVpd.h"
00090 
00091 /* defines */
00092 
00093 #define ZERO    0
00094 
00095 
00096 /* globals */
00097 
00098 /*
00099  * sysBatDesc[] is used to initialize the block address translation (BAT)
00100  * registers within the PowerPC 603/604 MMU.  BAT hits take precedence
00101  * over Page Table Entry (PTE) hits and are faster.  Overlap of memory
00102  * coverage by BATs and PTEs is permitted in cases where either the IBATs
00103  * or the DBATs do not provide the necessary mapping (PTEs apply to both
00104  * instruction AND data space, without distinction).
00105  *
00106  * The primary means of memory control for VxWorks is the MMU PTE support
00107  * provided by vmLib and cacheLib.  Use of BAT registers will conflict
00108  * with vmLib support.  User's may use BAT registers for i/o mapping and
00109  * other purposes but are cautioned that conflicts with cacheing and mapping
00110  * through vmLib may arise.  Be aware that memory spaces mapped through a BAT
00111  * are not mapped by a PTE and any vmLib() or cacheLib() operations on such
00112  * areas will not be effective, nor will they report any error conditions.
00113  *
00114  * Note: BAT registers CANNOT be disabled - they are always active.
00115  * For example, setting them all to zero will yield four identical data
00116  * and instruction memory spaces starting at local address zero, each 128KB
00117  * in size, and each set as write-back and cache-enabled.  Hence, the BAT regs
00118  * MUST be configured carefully.
00119  *
00120  * With this in mind, it is recommended that the BAT registers be used
00121  * to map LARGE memory areas external to the processor if possible.
00122  * If not possible, map sections of high RAM and/or PROM space where
00123  * fine grained control of memory access is not needed.  This has the
00124  * beneficial effects of reducing PTE table size (8 bytes per 4k page)
00125  * and increasing the speed of access to the largest possible memory space.
00126  * Use the PTE table only for memory which needs fine grained (4KB pages)
00127  * control or which is too small to be mapped by the BAT regs.
00128  *
00129  * #ifndef APS_BSP
00130  * The BAT configuration for 4xx/6xx-based PPC boards is as follows:
00131  * All BATs point to PROM/FLASH memory so that end customer may configure
00132  * them as required.
00133  *
00134  * #endif  APS_BSP 
00135  * [Ref: PowerPC Programming Reference, 7-25, 7.4.1]
00136  * #ifdef APS_BSP
00137  *
00138  * The BAT configuration for APS mv2700 boards is as follows:
00139  *   BATs are set up to access 1Gb of uncached, guarded VME A32 space.
00140  * #endif APS_BSP
00141  */
00142 
00143 UINT32 sysBatDesc [2 * (_MMU_NUM_IBAT + _MMU_NUM_DBAT)] =
00144     {
00145 #ifndef APS_BSP
00146     /* I BAT 0 */
00147 
00148     ((ROM_BASE_ADRS & _MMU_UBAT_BEPI_MASK) | (_MMU_UBAT_BL_1M &
00149     ~(_MMU_UBAT_VS & _MMU_UBAT_VP))),
00150     ((ROM_BASE_ADRS & _MMU_LBAT_BRPN_MASK) | _MMU_LBAT_PP_RW |
00151 #else /* APS_BSP */
00152     ((VME_A32_MSTR_BAT0 & _MMU_UBAT_BEPI_MASK) | _MMU_UBAT_BL_256M |
00153     _MMU_UBAT_VS | _MMU_UBAT_VP),
00154     ((VME_A32_MSTR_BAT0 & _MMU_LBAT_BRPN_MASK) | _MMU_LBAT_PP_RW |
00155 #endif /* APS_BSP */
00156     _MMU_LBAT_CACHE_INHIBIT),
00157 
00158     /* I BAT 1 */
00159 #ifdef APS_BSP
00160     ((VME_A32_MSTR_BAT1 & _MMU_UBAT_BEPI_MASK) | _MMU_UBAT_BL_256M |
00161     _MMU_UBAT_VS | _MMU_UBAT_VP),
00162     ((VME_A32_MSTR_BAT1 & _MMU_LBAT_BRPN_MASK) | _MMU_LBAT_PP_RW |
00163     _MMU_LBAT_CACHE_INHIBIT),
00164 #endif /* APS_BSP */
00165 
00166 #ifndef APS_BSP
00167     0, 0,
00168 
00169 #endif /* APS_BSP */
00170     /* I BAT 2 */
00171 #ifdef APS_BSP
00172     ((VME_A32_MSTR_BAT2 & _MMU_UBAT_BEPI_MASK) | _MMU_UBAT_BL_256M |
00173     _MMU_UBAT_VS | _MMU_UBAT_VP),
00174     ((VME_A32_MSTR_BAT2 & _MMU_LBAT_BRPN_MASK) | _MMU_LBAT_PP_RW |
00175     _MMU_LBAT_CACHE_INHIBIT),
00176 #endif /* APS_BSP */
00177 
00178 #ifndef APS_BSP
00179     0, 0,
00180 
00181 #endif /* APS_BSP */
00182     /* I BAT 3 */
00183 #ifdef APS_BSP
00184     ((VME_A32_MSTR_BAT3 & _MMU_UBAT_BEPI_MASK) | _MMU_UBAT_BL_256M |
00185     _MMU_UBAT_VS | _MMU_UBAT_VP),
00186     ((VME_A32_MSTR_BAT3 & _MMU_LBAT_BRPN_MASK) | _MMU_LBAT_PP_RW |
00187     _MMU_LBAT_CACHE_INHIBIT),
00188 #endif /* APS_BSP */
00189 
00190 #ifndef APS_BSP
00191     0, 0,
00192 
00193 #endif /* APS_BSP */
00194     /* D BAT 0 */
00195 #ifdef APS_BSP
00196     ((VME_A32_MSTR_BAT0 & _MMU_UBAT_BEPI_MASK) | _MMU_UBAT_BL_256M |
00197     _MMU_UBAT_VS | _MMU_UBAT_VP),
00198     ((VME_A32_MSTR_BAT0 & _MMU_LBAT_BRPN_MASK) | _MMU_LBAT_PP_RW |
00199     _MMU_LBAT_CACHE_INHIBIT | _MMU_LBAT_GUARDED),
00200 #endif /* APS_BSP */
00201 
00202 #ifndef APS_BSP
00203     0, 0,
00204 
00205 #endif /* APS_BSP */
00206     /* D BAT 1 */
00207 #ifdef APS_BSP
00208     ((VME_A32_MSTR_BAT1 & _MMU_UBAT_BEPI_MASK) | _MMU_UBAT_BL_256M |
00209     _MMU_UBAT_VS | _MMU_UBAT_VP),
00210     ((VME_A32_MSTR_BAT1 & _MMU_LBAT_BRPN_MASK) | _MMU_LBAT_PP_RW |
00211     _MMU_LBAT_CACHE_INHIBIT | _MMU_LBAT_GUARDED),
00212 #endif /* APS_BSP */
00213 
00214 #ifndef APS_BSP
00215     0, 0,
00216 
00217 #endif /* APS_BSP */
00218     /* D BAT 2 */
00219 #ifdef APS_BSP
00220     ((VME_A32_MSTR_BAT2 & _MMU_UBAT_BEPI_MASK) | _MMU_UBAT_BL_256M |
00221     _MMU_UBAT_VS | _MMU_UBAT_VP),
00222     ((VME_A32_MSTR_BAT2 & _MMU_LBAT_BRPN_MASK) | _MMU_LBAT_PP_RW |
00223     _MMU_LBAT_CACHE_INHIBIT | _MMU_LBAT_GUARDED),
00224 #endif /* APS_BSP */
00225 
00226 #ifndef APS_BSP
00227     0, 0,
00228 
00229 #endif /* APS_BSP */
00230     /* D BAT 3 */
00231 #ifndef APS_BSP
00232 
00233     0, 0
00234 #else /* APS_BSP */
00235     ((VME_A32_MSTR_BAT3 & _MMU_UBAT_BEPI_MASK) | _MMU_UBAT_BL_256M |
00236     _MMU_UBAT_VS | _MMU_UBAT_VP),
00237     ((VME_A32_MSTR_BAT3 & _MMU_LBAT_BRPN_MASK) | _MMU_LBAT_PP_RW |
00238     _MMU_LBAT_CACHE_INHIBIT | _MMU_LBAT_GUARDED)
00239 #endif /* APS_BSP */
00240     };
00241 
00242 /*
00243  * sysPhysMemDesc[] is used to initialize the Page Table Entry (PTE) array
00244  * used by the MMU to translate addresses with single page (4k) granularity.
00245  * PTE memory space should not, in general, overlap BAT memory space but
00246  * may be allowed if only Data or Instruction access is mapped via BAT.
00247  *
00248  * Address translations for local RAM, memory mapped PCI bus, memory mapped
00249  * VME A16 space and local PROM/FLASH are set here.
00250  *
00251  * PTEs are held, strangely enough, in a Page Table.  Page Table sizes are
00252  * integer powers of two based on amount of memory to be mapped and a
00253  * minimum size of 64 kbytes.  The MINIMUM recommended Page Table sizes
00254  * for 32-bit PowerPCs are:
00255  *
00256  * Total mapped memory          Page Table size
00257  * -------------------          ---------------
00258  *        8 Meg                      64 K
00259  *       16 Meg                     128 K
00260  *       32 Meg                     256 K
00261  *       64 Meg                     512 K
00262  *      128 Meg                       1 Meg
00263  *      .                               .
00264  *      .                               .
00265  *      .                               .
00266  *
00267  * [Ref: chapter 7, PowerPC Microprocessor Family: The Programming Environments]
00268  *
00269  */
00270 
00271 PHYS_MEM_DESC sysPhysMemDesc [] =
00272     {
00273     {
00274     /* Vector Table and Interrupt Stack */
00275 
00276     (void *) LOCAL_MEM_LOCAL_ADRS,
00277     (void *) LOCAL_MEM_LOCAL_ADRS,
00278     RAM_LOW_ADRS,
00279     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE |
00280     VM_STATE_MASK_MEM_COHERENCY,
00281     VM_STATE_VALID      | VM_STATE_WRITABLE      | VM_STATE_CACHEABLE |
00282     VM_STATE_MEM_COHERENCY
00283     },
00284 
00285 
00286     {
00287     /* Local DRAM */
00288 
00289     (void *) RAM_LOW_ADRS,
00290     (void *) RAM_LOW_ADRS,
00291     LOCAL_MEM_SIZE -  RAM_LOW_ADRS,
00292     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE |
00293     VM_STATE_MASK_MEM_COHERENCY,
00294     VM_STATE_VALID      | VM_STATE_WRITABLE      | VM_STATE_CACHEABLE |
00295     VM_STATE_MEM_COHERENCY
00296     },
00297 
00298     /* Access to PCI ISA I/O space */
00299 
00300     {
00301     (void *) ISA_MSTR_IO_LOCAL,
00302     (void *) ISA_MSTR_IO_LOCAL,
00303     ISA_MSTR_IO_SIZE,
00304     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
00305     VM_STATE_VALID      | VM_STATE_WRITABLE      | VM_STATE_CACHEABLE_NOT
00306     },
00307 
00308     /* Access to PCI I/O space */
00309 
00310     {
00311     (void *) PCI_MSTR_IO_LOCAL,
00312     (void *) PCI_MSTR_IO_LOCAL,
00313     PCI_MSTR_IO_SIZE,
00314     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
00315     VM_STATE_VALID      | VM_STATE_WRITABLE      | VM_STATE_CACHEABLE_NOT
00316     },
00317 
00318     /* Access to PCI ISA memory space */
00319 
00320     {
00321     (void *) PCI_MSTR_MEMIO_LOCAL,
00322     (void *) PCI_MSTR_MEMIO_LOCAL,
00323     PCI_MSTR_MEMIO_SIZE,
00324     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
00325     VM_STATE_VALID      | VM_STATE_WRITABLE      | VM_STATE_CACHEABLE_NOT
00326     },
00327 
00328     /* Access to PCI memory space */
00329 
00330     {
00331     (void *) PCI_DYNAMIC_MEM_LOCAL,
00332     (void *) PCI_DYNAMIC_MEM_LOCAL,
00333     PCI_DYNAMIC_MEM_SIZE,
00334     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
00335     VM_STATE_VALID      | VM_STATE_WRITABLE      | VM_STATE_CACHEABLE_NOT
00336     },
00337 
00338 
00339 #ifndef APS_BSP
00340     {
00341     /* MODIFY A32 VME WINDOW HERE */
00342     (void *) VME_A32_MSTR_LOCAL,
00343     (void *) VME_A32_MSTR_LOCAL,
00344     VME_A32_MSTR_SIZE,
00345     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
00346     VM_STATE_VALID      | VM_STATE_WRITABLE      | VM_STATE_CACHEABLE_NOT
00347     },
00348 #else /* APS_BSP */
00349     /* VME_A32_MSTR_LOCAL entry removed, system uses sysBatDesc instead */
00350 #endif /* APS_BSP */
00351 
00352     {
00353     (void *) VME_A24_MSTR_LOCAL,
00354     (void *) VME_A24_MSTR_LOCAL,
00355     VME_A24_MSTR_SIZE,
00356 #ifndef APS_BSP
00357     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
00358     VM_STATE_VALID      | VM_STATE_WRITABLE      | VM_STATE_CACHEABLE_NOT
00359 #else /* APS_BSP */
00360     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE |
00361     VM_STATE_MASK_GUARDED,
00362     VM_STATE_VALID      | VM_STATE_WRITABLE      | VM_STATE_CACHEABLE_NOT |
00363     VM_STATE_GUARDED
00364 #endif /* APS_BSP */
00365     },
00366 
00367 #ifndef APS_BSP
00368     {
00369     /* Off-board VME LM/SIG/Semaphore Regs */
00370 
00371     (void *) VME_LM_MSTR_LOCAL,
00372     (void *) VME_LM_MSTR_LOCAL,
00373     VME_LM_MSTR_SIZE,
00374     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
00375     VM_STATE_VALID      | VM_STATE_WRITABLE      | VM_STATE_CACHEABLE_NOT
00376     },
00377 #else /* APS_BSP */
00378     /* A32 VME LM/SIG/Semaphore Regs removed */
00379 #endif /* APS_BSP */
00380 
00381     {
00382     /* Kahlua registers */
00383 
00384     (void *) KAHLUA_EUMB_BASE,
00385     (void *) KAHLUA_EUMB_BASE,
00386     KAHLUA_EUMB_SIZE,
00387     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
00388     VM_STATE_VALID      | VM_STATE_WRITABLE      | VM_STATE_CACHEABLE_NOT
00389     },
00390 
00391     {
00392 #ifndef APS_BSP
00393     (void *) VME_A16_MSTR_LOCAL,
00394     (void *) VME_A16_MSTR_LOCAL,
00395     VME_A16_MSTR_SIZE,
00396     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
00397     VM_STATE_VALID      | VM_STATE_WRITABLE      | VM_STATE_CACHEABLE_NOT
00398 #else /* APS_BSP */
00399     (void *) VME_A16_MSTR_LOCAL,
00400     (void *) VME_A16_MSTR_LOCAL,
00401     VME_A16_MSTR_SIZE,
00402     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE |
00403     VM_STATE_MASK_GUARDED,
00404     VM_STATE_VALID      | VM_STATE_WRITABLE      | VM_STATE_CACHEABLE_NOT |
00405     VM_STATE_GUARDED
00406 #endif /* APS_BSP */
00407     },
00408 
00409     {
00410     /* PCI interrupt acknowledge */
00411 
00412     (void *) PCI_MSTR_IACK_WNDW_ADRS,
00413     (void *) PCI_MSTR_IACK_WNDW_ADRS,
00414     PCI_MSTR_IACK_SIZE,
00415     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
00416     VM_STATE_VALID      | VM_STATE_WRITABLE      | VM_STATE_CACHEABLE_NOT
00417     },
00418 
00419 #ifdef CHRP_ADRS_MAP
00420     {
00421     /* PCI Configuration Address Register */
00422 
00423     (void *) PCI_MSTR_PRIMARY_CAR,
00424     (void *) PCI_MSTR_PRIMARY_CAR,
00425     PCI_MSTR_PRIMARY_CAR_SIZE,
00426     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
00427     VM_STATE_VALID      | VM_STATE_WRITABLE      | VM_STATE_CACHEABLE_NOT
00428     },
00429 
00430     {
00431     /* PCI Configuration Data Register */
00432 
00433     (void *) PCI_MSTR_PRIMARY_CDR,
00434     (void *) PCI_MSTR_PRIMARY_CDR,
00435     PCI_MSTR_PRIMARY_CDR_SIZE,
00436     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
00437     VM_STATE_VALID      | VM_STATE_WRITABLE      | VM_STATE_CACHEABLE_NOT
00438     },
00439 #endif
00440 
00441 #ifndef CHRP_ADRS_MAP /* if PReP address map */
00442     {
00443 
00444     /* map in direct access of PCI configuration space */
00445 
00446     (void *) PCI_MSTR_DIRECT_MAP_ADRS,
00447     (void *) PCI_MSTR_DIRECT_MAP_ADRS,
00448     PCI_MSTR_DIRECT_SIZE,
00449     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
00450     VM_STATE_VALID      | VM_STATE_WRITABLE      | VM_STATE_CACHEABLE_NOT
00451     },
00452 #endif
00453 
00454 #ifndef APS_BSP
00455 
00456     {
00457     (void *) FLASH_BASE_ADRS,
00458     (void *) FLASH_BASE_ADRS,
00459     FLASH_MEM_SIZE,
00460     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
00461     VM_STATE_VALID      | VM_STATE_WRITABLE  | VM_STATE_CACHEABLE_NOT
00462     },
00463 #else /* APS_BSP */
00464     /* Soldered Flash, Read-only (programmed from PPC-bug) */
00465 
00466     {
00467     (void *) FLASH1_BASE_ADRS,
00468     (void *) FLASH1_BASE_ADRS,
00469     FLASH1_MEM_SIZE,
00470     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
00471     VM_STATE_VALID      | VM_STATE_WRITABLE_NOT  | VM_STATE_CACHEABLE
00472     },
00473 #endif /* APS_BSP */
00474 
00475 #ifdef APS_BSP
00476     /* Socketed Flash, Read-only */
00477 
00478     {
00479     (void *) FLASH0_BASE_ADRS,
00480     (void *) FLASH0_BASE_ADRS,
00481     FLASH0_MEM_SIZE,
00482     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
00483     VM_STATE_VALID      | VM_STATE_WRITABLE_NOT  | VM_STATE_CACHEABLE_NOT
00484     },
00485 
00486     /* System I/O registers */
00487 
00488     {
00489     (void *) MV2100_SIO_BASE,
00490     (void *) MV2100_SIO_BASE,
00491     MV2100_SIO_SIZE,
00492     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
00493     VM_STATE_VALID      | VM_STATE_WRITABLE      | VM_STATE_CACHEABLE_NOT
00494     }
00495 #endif /* APS_BSP */
00496     };
00497 
00498 int sysPhysMemDescNumEnt = NELEMENTS (sysPhysMemDesc);
00499 
00500 int    sysBus      = VME_BUS;           /* system bus type */
00501 int    sysCpu      = CPU;               /* system CPU type (MC680x0) */
00502 char * sysBootLine = BOOT_LINE_ADRS;    /* address of boot line */
00503 char * sysExcMsg   = EXC_MSG_ADRS;      /* catastrophic message area */
00504 int    sysProcNum;                      /* processor number of this CPU */
00505 int    sysFlags;                        /* boot flags */
00506 char   sysBootHost [BOOT_FIELD_LEN];    /* name of host from which we booted */
00507 char   sysBootFile [BOOT_FIELD_LEN];    /* name of file from which we booted */
00508 UINT   sysVectorIRQ0  = INT_VEC_IRQ0;   /* vector for IRQ0 */
00509 BOOL   sysVmeEnable   = FALSE;          /* by default no VME */
00510 int    pciToVmeDev;                     /* PCI to VME Bridge Device */
00511 #ifdef APS_BSP
00512 LOCAL PART_ID a24memPartId = NULL;
00513 LOCAL ULONG a24memBase;
00514 LOCAL ULONG a24memBound;
00515 LOCAL ULONG a24adrOffset;       /* local address = VME address + offset */
00516 LOCAL ULONG a24vmeBound;
00517 #endif /* APS_BSP */
00518 
00519 /* last 5 nibbles are board specific, initialized in sysHwInit */
00520 
00521 unsigned char lnEnetAddr [6] = { 0x08, 0x00, 0x3e, 0x00, 0x00, 0x00 };
00522 unsigned char clearWd [1]  = { 0x00 };
00523 
00524 #if defined(INCLUDE_PMC_SPAN) && !defined(INCLUDE_PCI_AUTOCONF)
00525 /*
00526  * PMC Span (DEC21150 PCI-to-PCI Bridge) Configuration Parameter Array
00527  *
00528  * This array MUST contain the parameters in the order which they will
00529  * be set.
00530  */
00531 
00532 PMC_SPAN sysPmcSpanParm [] =
00533 {
00534   {PCI_CFG_COMMAND, 2,   P2P_PMC_DISABLE},
00535   {PCI_CFG_STATUS,  2,   P2P_CLR_STATUS >> 16},
00536   {PCI_CFG_BRIDGE_CONTROL, 2, P2P_SEC_BUS_RESET},
00537   {PCI_CFG_CACHE_LINE_SIZE, 2, P2P_CACHE_LINE_SIZE | P2P_PRIM_LATENCY},
00538   {PCI_CFG_PRIMARY_BUS,     1, PCI_PRIMARY_BUS},
00539   {PCI_CFG_SECONDARY_BUS,   1, PCI_SECONDARY_BUS},
00540   {PCI_CFG_SUBORDINATE_BUS, 1, PCI_SUBORD_BUS},
00541   {PCI_CFG_SEC_STATUS, 2,   P2P_CLR_STATUS >> 16},
00542   {PCI_CFG_IO_BASE, 2,   ((P2P_IO_BASE & 0x0000F000) >> 8) |
00543                          ((P2P_IO_BASE + P2P_IO_SIZE - 1) & 0x0000F000)},
00544   {PCI_CFG_MEM_BASE, 2,  ((P2P_NONPREF_MEM_BASE & 0xFFF00000) >> 16)},
00545   {PCI_CFG_MEM_LIMIT, 2, ((P2P_NONPREF_MEM_BASE + P2P_NONPREF_MEM_SIZE - 1) & \
00546                           0xFFF00000) >> 16},
00547   {PCI_CFG_PRE_MEM_BASE, 2, ((P2P_PREF_MEM_BASE & 0xFFF00000) >> 16)},
00548   {PCI_CFG_PRE_MEM_LIMIT, 2, ((P2P_PREF_MEM_BASE + P2P_PREF_MEM_SIZE - 1) & \
00549                               0xFFF00000) >> 16},
00550   {PCI_CFG_PRE_MEM_BASE_U,  4, P2P_PREF_HI32_BASE},  /* only < 4GB space */
00551   {PCI_CFG_PRE_MEM_LIMIT_U, 4, P2P_PREF_HI32_BASE},
00552   {PCI_CFG_IO_BASE_U,  2, ((P2P_IO_BASE & 0xFFFF0000) >> 16)},
00553   {PCI_CFG_IO_LIMIT_U, 2, ((P2P_IO_BASE + P2P_IO_SIZE - 1) & 0xFFFF0000) >> 16},
00554   {PCI_CFG_BRIDGE_CONTROL, 2, 0},
00555   {PCI_CFG_DEC21150_SEC_CLK,   2, P2P_CLK_ENABLE},
00556   {PCI_CFG_DEC21150_SERR_STAT, 1, (P2P_CLR_STATUS >> 16) & 0xFF},
00557   {PCI_CFG_STATUS,  2,  P2P_CLR_STATUS >> 16},
00558   {PCI_CFG_COMMAND, 2,  P2P_PMC_ENABLE}
00559 };
00560 
00561 #define NUM_PMC_SPAN_PARMS      (sizeof(sysPmcSpanParm) / sizeof(PMC_SPAN))
00562 #ifdef APS_BSP
00563 LOCAL STATUS sysPmcSpanConfig (int, int, int, PMC_SPAN *);
00564 #endif /* APS_BSP */
00565 #endif /* INCLUDE_PMC_SPAN) & !INCLUDE_PCI_AUTOCONF */
00566 
00567 /* locals */
00568 
00569 LOCAL char sysModelStr[80];
00570 LOCAL char wrongCpuMsg[] = WRONG_CPU_MSG; 
00571 
00572 /* forward declarations */
00573 
00574 void    sysSpuriousIntHandler(void);
00575 #ifndef APS_BSP
00576 void    sysCpuCheck (void);
00577 #else /* APS_BSP */
00578 LOCAL   void sysCpuCheck(void);
00579 #endif /* APS_BSP */
00580 char *  sysPhysMemTop (void);
00581 void sysDec21x40UpdateLoadStr (void);
00582 UCHAR   sysNvRead(ULONG);
00583 void    sysNvWrite(ULONG,UCHAR);
00584 void    sysBusTasClear (volatile char *);
00585 #ifndef APS_BSP
00586 #if defined(INCLUDE_PMC_SPAN) && !defined(INCLUDE_PCI_AUTOCONF)
00587 STATUS  sysPmcSpanConfig (int, int, int, PMC_SPAN *);
00588 #endif /* INCLUDE_PMC_SPAN & !INCLUDE_PCI_AUTOCONF */
00589 STATUS  sysBusProbe (char *, int, int, char *);
00590 IMPORT UINT sysHid1Get(void);
00591 #else /* APS_BSP */
00592 LOCAL   STATUS sysBusProbe(char *, int, int, char *);
00593 #endif /* APS_BSP */
00594 LOCAL   BOOL sysVmeVownTas(char *);
00595 LOCAL   BOOL sysVmeRmwTas(char *);
00596 #ifdef APS_BSP
00597 LOCAL   void sysVmeVownClear (volatile char *);
00598 #endif /* APS_BSP */
00599 void    sysDebugMsg(char * str, UINT32  recovery);
00600 #ifndef APS_BSP
00601 STATUS  sysAtuInit();                   /* initialize Kahlua ATU */
00602 UINT    sysGetBusSpd(void);             /* system bus speed (in megahertz) */
00603 UINT    sysGetBusSpdHertz(void);        /* system bus speed (in hertz) */
00604 UINT    sysGetMpuSpd(void);             /* processor speed (in megahertz) */
00605 UINT    sysGetMpuSpdHertz(void);        /* processor speed (in hertz) */
00606 UINT    sysGetPciSpd(void);             /* pci bus speed (in megahertz) */
00607 UINT    sysGetPciSpdHertz(void);        /* pci bus speed (in hertz) */
00608 #else /* APS_BSP */
00609 LOCAL   STATUS sysAtuInit();            /* initialize Kahlua ATU */
00610 UINT    sysGetBusSpd(void);             /* system bus speed (in hertz) */
00611 UINT    sysGetMpuSpd(void);             /* processor speed (in hertz) */
00612 UINT    sysGetPciSpd(void);             /* pci bus speed (in hertz) */
00613 #endif /* APS_BSP */
00614 
00615 /* externals */
00616 
00617 IMPORT UCHAR  sysInByte (ULONG);
00618 IMPORT void   sysOutByte (ULONG, UCHAR);
00619 IMPORT USHORT sysInWord (ULONG);
00620 IMPORT void   sysOutWord (ULONG, USHORT);
00621 IMPORT ULONG  sysInLong (ULONG);
00622 IMPORT void   sysOutLong (ULONG, ULONG);
00623 IMPORT UINT32 sysPciInLong (UINT32);
00624 IMPORT void   sysPciOutLong (UINT32, UINT32);
00625 IMPORT UINT32 sysPciConfigInLong (UINT32 *);
00626 IMPORT void   sysPciConfigOutLong (UINT32 *, UINT32);
00627 IMPORT UINT16 sysPciConfigInWord (UINT16 *);
00628 IMPORT void   sysPciConfigOutWord (UINT16 *, UINT16);
00629 #ifdef APS_BSP
00630 IMPORT UINT8  sysPciConfigInByte (UINT8 *);
00631 IMPORT void   sysPciConfigOutByte (UINT8 *, UINT8);
00632 #endif /* APS_BSP */
00633 IMPORT void   sysClkIntCIO (void);
00634 IMPORT STATUS sysMemProbeSup (int length, char * src, char * dest);
00635 IMPORT int    sysProbeExc();
00636 IMPORT VOIDFUNCPTR      smUtilTasClearRtn;
00637 IMPORT void   sysBusRmwEnable(UINT, UINT, UINT, char *);
00638 IMPORT void   sysBusRmwDisable(void);
00639 IMPORT UINT32 sysTimeBaseLGet (void);
00640 #ifdef APS_BSP
00641 IMPORT UINT   sysHid1Get(void);
00642 #endif /* APS_BSP */
00643 IMPORT UCHAR  sysProductStr[];
00644 IMPORT UINT32 sysMemParamConfig();
00645 #ifdef APS_BSP
00646 IMPORT int    excExcHandle(ESFPPC *pEsf);
00647 #endif /* APS_BSP */
00648 
00649 /* BSP DRIVERS */
00650 
00651 #include "pci/pciConfigLib.c"
00652 #include "./sysEnd.c"
00653 #include "sysSerial.c"
00654 #include "mem/byteNvRam.c"
00655 #include "sysMotVpd.c"
00656 #include "timer/ppcDecTimer.c"          /* PPC603 has on chip timers */
00657 
00658 #ifdef INCLUDE_SHOW_ROUTINES
00659 #include "pci/pciConfigShow.c"          /* display of PCI config space */
00660 #include "sysMotVpdShow.c"
00661 #endif
00662 
00663 #ifdef INCLUDE_SCSI
00664 #   include "sysScsi.c"                 /* sysScsiInit routine */
00665 #endif /* INCLUDE_SCSI */
00666 
00667 #include "universe.c"
00668 #include "kahluaEpic.c"
00669 
00670 #ifdef INCLUDE_AUXCLK
00671 #    include "kahluaAuxClk.c"
00672 #endif
00673 
00674 #ifdef INCLUDE_PCI_AUTOCONF
00675 #  include "pci/pciAutoConfigLib.c"
00676 #  include "./sysBusPci.c"
00677 #endif
00678 
00679 /* defines for sysBusTas() and sysBusTasClear() */
00680 
00681 #define VMEBUS_OWNER    (*UNIVERSE_MAST_CTL & LONGSWAP(MAST_CTL_VOWN_ACK))
00682 #define CPU_CLOCKS_PER_LOOP     10
00683 #define LOCK_TIMEOUT            10
00684 #define UNLOCK_TIMEOUT          10000
00685 
00686 #ifdef APS_BSP
00687 /* defines for sysA24MapRam() */
00688 #endif /* APS_BSP */
00689 
00690 #ifdef APS_BSP
00691 #define MEM_PART_OVERHEAD 64
00692 
00693 
00694 #endif /* APS_BSP */
00695 /******************************************************************************
00696 *
00697 * sysModel - return the model name of the CPU board
00698 *
00699 * This routine returns the model name of the CPU board.  The returned string
00700 * depends on the board model and CPU version being used, for example,
00701 * "Motorola MVME2600 - MPC 604e".
00702 *
00703 * RETURNS: A pointer to the string.
00704 */
00705 
00706 char * sysModel (void)
00707     {
00708     int    cpu;
00709     char cpuStr[80];
00710 
00711     /* Determine CPU type and build display string */
00712 
00713     cpu = CPU_TYPE;
00714     switch (cpu)
00715         {
00716         case CPU_TYPE_603EK:
00717             sprintf(cpuStr, "8240");
00718             break;
00719         default:
00720             sprintf (cpuStr, "60%d", cpu);
00721             break;
00722         }
00723 
00724     sprintf (sysModelStr, "Motorola MVME2100 - MPC %s", cpuStr);
00725 
00726     return (sysModelStr);
00727     }
00728 
00729 /*******************************************************************************
00730 *
00731 * sysBspRev - return the BSP version and revision number
00732 *
00733 * This routine returns a pointer to a BSP version and revision number, for
00734 * example, 1.1/0. BSP_REV is concatenated to BSP_VERSION and returned.
00735 *
00736 * RETURNS: A pointer to the BSP version/revision string.
00737 */
00738 
00739 char * sysBspRev (void)
00740     {
00741     return (BSP_VERSION BSP_REV);
00742     }
00743 
00753 void sysDecDelay
00754     (
00755     UINT usDelay
00756     )
00757     {
00758     UINT  oneUsDelta;
00759     UINT  valueCurrent, valuePrevious, valueDelta;
00760 
00761 
00762     /* if no delay count, exit */
00763 
00764     if (!usDelay) 
00765         return;
00766 
00767     /*
00768      * calculate delta of decrementer ticks for 1ms of elapsed time,
00769      * the bus clock (in megahertz) is used for 603/604 versions, the
00770      * decrementer counts down once every for bus clocks for the
00771      * 603/604 versions, and once every RTC tick for the 601, the RTC
00772      * tick for 601 is the period of 1ns
00773      */
00774 
00775     oneUsDelta = ((DEC_CLOCK_FREQ / 4) / 1000000);
00776 
00777     /*
00778      * snapshot current decrementer count, this count is used
00779      * as the starting point
00780      *
00781      * check for rollover, the decrementer counts down from
00782      * the maximum count (0xffffffff) to zero
00783      *
00784      * calculate delta of the decrementer counts and divide
00785      * down by the one MS divider, exit if count has been
00786      * met or exceeded
00787      */
00788 
00789     for (valuePrevious = vxDecGet();;) 
00790         {
00791         valueCurrent = vxDecGet();
00792         valueDelta = 0;
00793         if (valueCurrent > valuePrevious) 
00794             {
00795             valueDelta = (0xFFFFFFFF - valueCurrent) + valuePrevious;
00796             } 
00797         else 
00798             {
00799             if (valueCurrent < valuePrevious) 
00800                 {
00801                 valueDelta = valuePrevious - valueCurrent;
00802                 }
00803             }
00804 
00805         if ((valueDelta / oneUsDelta) >= usDelay) 
00806             break;
00807         }
00808     }
00809 
00810 /******************************************************************************
00811 *
00812 * sysHwInit - initialize the system hardware
00813 *
00814 * This routine initializes various features of the CPU board.  It is called
00815 * by usrInit() in usrConfig.c.  This routine sets up the control registers
00816 * and initializes various devices if they are present.
00817 *
00818 * NOTE: This routine should not be called directly by the user application.  It
00819 * cannot be used to initialize interrupt vectors.
00820 *
00821 * RETURNS: N/A
00822 */
00823 
00824 void sysHwInit (void)
00825     {
00826     int         pciBusNo;       /* PCI bus number */
00827     int         pciDevNo;       /* PCI device number */
00828     int         pciFuncNo;      /* PCI function number */
00829 
00830     /* Initialize the VPD information */
00831 
00832     (void) sysVpdInit ();
00833 
00834 
00835     /*
00836      *  Validate CPU type
00837      */
00838     sysCpuCheck();
00839 
00840     /*
00841      *  Initialize PCI driver library.
00842      */
00843     if (pciConfigLibInit (PCI_MECHANISM_1, PCI_MSTR_PRIMARY_CAR, 
00844         PCI_MSTR_PRIMARY_CDR, 0) != OK)
00845         {
00846         sysToMonitor (BOOT_NO_AUTOBOOT);
00847         }
00848 
00849 #ifdef INCLUDE_PCI_AUTOCONF
00850     /* Auto-Configure the PCI busses/devices. */
00851 
00852     /*
00853      * Test to determine if we need to configure the PCI busses with
00854      * sysPciAutoConfig().  If we are coming up from a ROM-based image
00855      * then we need to reconfigure.  If we have been booted from a ROM
00856      * image then we don't need to reconfigure since the bootrom will
00857      * already have reconfigured the PCI busses.  We must avoid
00858      * configuring the PCI busses twice on startup.
00859      */
00860 
00861     if ( !PCI_AUTOCONFIG_DONE )
00862         {
00863 
00864         /* in ROM boot phase, OK to continue and configure PCI busses.*/
00865 
00866         sysPciAutoConfig ();
00867         PCI_AUTOCONFIG_FLAG++;  /* Remember that PCI is configured */
00868 
00869         }
00870 #endif
00871 
00872     sysDec21x40UpdateLoadStr ();
00873 
00874     /*
00875      * Do the necessary setup for the UNIVERSE chip.
00876      * 
00877      * In all cases we need to get the Base Address for the UNIVERSE
00878      * registers in PCI space.
00879      * If PCI autoconfiguration is not enabled, then we need to manually
00880      * configure the UNIVERSE chip.
00881      */
00882 
00883     if (pciFindDevice ((PCI_ID_UNIVERSE & 0xFFFF),
00884                         (PCI_ID_UNIVERSE >> 16) & 0xFFFF, 0,
00885                         &pciBusNo, &pciDevNo, &pciFuncNo) != ERROR)
00886         {
00887         pciToVmeDev = UNIVERSE_II;
00888 
00889 #if !defined(INCLUDE_PCI_AUTOCONF)
00890         (void)pciDevConfig (pciBusNo, pciDevNo, pciFuncNo,
00891                             NULL,
00892                             PCI_MEM_UNIVERSE_ADRS,
00893                             (PCI_CMD_MASTER_ENABLE | PCI_CMD_MEM_ENABLE));
00894 #endif /* !defined(INCLUDE_PCI_AUTOCONF) */
00895 
00896         /* get the base address for the Universe registers */
00897 
00898         (void)pciConfigInLong(pciBusNo, pciDevNo, pciFuncNo,
00899                         PCI_CFG_BASE_ADDRESS_0,
00900                         &univBaseAdrs);
00901         if (univBaseAdrs & PCI_BAR_SPACE_IO)
00902             {
00903             univBaseAdrs = (ISA_MSTR_IO_LOCAL + (univBaseAdrs & 
00904                             PCI_IOBASE_MASK));
00905             }
00906         else
00907             {
00908             univBaseAdrs = (PCI_MSTR_MEMIO_LOCAL + (univBaseAdrs & 
00909                             PCI_MEMBASE_MASK));
00910             }
00911         }
00912 
00913 #if defined(INCLUDE_NETWORK) && !defined(INCLUDE_PCI_AUTOCONF)
00914 
00915     /*  Initialize the Standard PCI Header of the LANCE device if present */
00916 
00917     if ((pciFindDevice ((PCI_ID_PRI_LAN & 0xFFFF),
00918                             (PCI_ID_PRI_LAN >> 16) & 0xFFFF, 0,
00919                             &pciBusNo, &pciDevNo, &pciFuncNo) != ERROR))
00920             {
00921             (void)pciDevConfig (pciBusNo, pciDevNo, pciFuncNo,
00922                                 PCI_IO_LN_ADRS,
00923                                 NULL,
00924                                 (PCI_CMD_MASTER_ENABLE | PCI_CMD_IO_ENABLE));
00925             }
00926         else
00927             {
00928             sysToMonitor (BOOT_NO_AUTOBOOT);
00929             }
00930 #endif /* INCLUDE_NETWORK & !INCLUDE_PCI_AUTOCONF */
00931  
00932     /* initialize the address translation unit (ATU) */
00933  
00934     sysAtuInit();
00935 
00936     /* Initialize the EPIC. */
00937 
00938     sysEpicInit();
00939 
00940 #if defined(INCLUDE_PMC_SPAN) && !defined(INCLUDE_PCI_AUTOCONF)
00941 
00942     /*
00943      * Initialize and configure PMC Span (bridge) to secondary PCI bus.
00944      */
00945 
00946     if  (pciFindDevice ((PCI_ID_BR_DEC21150 & 0xFFFF),
00947                         (PCI_ID_BR_DEC21150 >> 16) & 0xFFFF, 0,
00948                         &pciBusNo, &pciDevNo, &pciFuncNo) != ERROR)
00949         {
00950         (void)sysPmcSpanConfig (pciBusNo, pciDevNo, pciFuncNo, sysPmcSpanParm);
00951         }
00952 #endif  /* INCLUDE_PMC_SPAN & !INCLUDE_PCI_AUTOCONF */
00953 
00954     /*
00955      *  The LANCE has a real driver associated with it, so
00956      *  no additional initialization is done here.  It's done
00957      *  at kernel init time.
00958      */
00959 
00960     /*
00961      *  Initialize the non-PCI Config Space registers of the
00962      *  Universe which doesn't have a true device driver.
00963      */
00964 
00965     sysUniverseInit();
00966  
00967 #ifdef  INCLUDE_VME_DMA
00968 
00969     /*  Initialize the VMEbus DMA driver */
00970 
00971     sysVmeDmaInit();
00972 
00973 #endif  /* INCLUDE_VME_DMA */
00974 
00975     /* set shared memory TAS Clear routine pointer */
00976 
00977     smUtilTasClearRtn = (VOIDFUNCPTR)sysBusTasClear;
00978 
00979     /* set pointer to bus probing hook */
00980 
00981     _func_vxMemProbeHook = (FUNCPTR)sysBusProbe;
00982 
00983     /* Initialize COM1 and COM2 serial channels */
00984 
00985     sysSerialHwInit();
00986 
00987     /* Extract the Ethernet address out of non-volatile RAM.
00988      * The Motorola convention for the Ethernet address is that they only
00989      * save the low 3 bytes in BBRAM.  The high three bytes are the
00990      * manufacturers code, and Motorola software knows its own.
00991      * The Motorola code is 0x08003Exxx.
00992      */
00993     sysNvRamGet ((char *)lnEnetAddr, 6, ((int) BB_ENET - NV_BOOT_OFFSET));
00994 
00995     /* Disable the watchdog timer */
00996 
00997     sysNvWrite ((ULONG)WD_TIMER, 0);
00998 
00999     /*
01000      * If mmu tables are used, this is where we would dynamically
01001      * update the entry describing main memory, using sysPhysMemTop().
01002      * We must call sysPhysMemTop () at sysHwInit() time to do
01003      * the memory autosizing if available.
01004      */
01005 
01006     sysPhysMemTop ();
01007 
01008 
01009 #ifdef INCLUDE_FEIEND /* DHT -SNS02-A Added */
01010         sys557PciInit();
01011 #endif
01012 
01013 #ifdef INCLUDE_GIGEND/* DHT -SNS02-A Added */
01014         sysGigPciInit();
01015 #endif  /* INCLUDE_GIGEND */
01016 
01017     /* Upon completion, clear the Board Fail LED */
01018 
01019     *(UINT8 *)MV2100_SYS_STAT_REG2 &= ~MV2100_BD_FAIL;
01020 
01021 
01022     }
01023 
01024 
01025 /*******************************************************************************
01026 *
01027 * sysPhysMemTop - get the address of the top of physical memory
01028 *
01029 * This routine returns the address of the first missing byte of memory,
01030 * which indicates the top of memory.
01031 *
01032 * Normally, the user specifies the amount of physical memory with the
01033 * macro LOCAL_MEM_SIZE in config.h.  BSPs that support run-time
01034 * memory sizing do so only if the macro LOCAL_MEM_AUTOSIZE is defined.
01035 * If not defined, then LOCAL_MEM_SIZE is assumed to be, and must be, the
01036 * true size of physical memory.
01037 *
01038 * NOTE: Do no adjust LOCAL_MEM_SIZE to reserve memory for application
01039 * use.  See sysMemTop() for more information on reserving memory.
01040 *
01041 * RETURNS: The address of the top of physical memory.
01042 *
01043 * SEE ALSO: sysMemTop()
01044 */
01045 
01046 char * sysPhysMemTop (void)
01047     {
01048 #ifdef LOCAL_MEM_AUTOSIZE
01049     sramConfigReg MemControlReg;
01050 #endif
01051     static char * sysPhysMemSize = NULL;        /* ptr to top of mem + 1 */
01052 
01053     if (sysPhysMemSize == NULL)
01054         {
01055 #ifdef LOCAL_MEM_AUTOSIZE
01056         /*
01057          * Do dynamic memory sizing.
01058          *
01059          * Since the memory controller interface has already been set to
01060          * control all memory, just read and interpret its DRAM Attributes
01061          * Register.
01062          */
01063 
01064         sysPhysMemSize = (char *)sysMemParamConfig(&MemControlReg);
01065 
01066         /* Adjust initial DRAM size to actual physical memory. */
01067 
01068         sysPhysMemDesc[1].len = (ULONG)sysPhysMemSize -
01069                                 (ULONG)sysPhysMemDesc[1].physicalAddr;
01070 
01071 #else /* not LOCAL_MEM_AUTOSIZE */
01072         /* Don't do auto-sizing, use defined constants. */
01073 
01074         sysPhysMemSize = (char *)(LOCAL_MEM_LOCAL_ADRS + LOCAL_MEM_SIZE);
01075 #endif /* LOCAL_MEM_AUTOSIZE */
01076         }
01077 
01078 
01079 
01080     return sysPhysMemSize;
01081     }
01082 
01083 
01084 /*******************************************************************************
01085 *
01086 * sysMemTop - get the address of the top of VxWorks memory
01087 *
01088 * This routine returns a pointer to the first byte of memory not
01089 * controlled or used by VxWorks.
01090 *
01091 * The user can reserve memory space by defining the macro USER_RESERVED_MEM
01092 * in config.h.  This routine returns the address of the reserved memory
01093 * area.  The value of USER_RESERVED_MEM is in bytes.
01094 *
01095 * RETURNS: The address of the top of VxWorks memory.
01096 */
01097 
01098 char * sysMemTop (void)
01099     {
01100     static char * memTop = NULL;
01101 
01102     if (memTop == NULL)
01103         {
01104         memTop = sysPhysMemTop () - USER_RESERVED_MEM;
01105 #ifdef LARGE_MEMORY_HACK
01106 /* DHT - Limit to 32M */
01107         if (    memTop>0x2000000)
01108                 memTop=0x2000000;
01109 #endif
01110         }
01111 
01112     return memTop;
01113     }
01114 
01115 
01116 /******************************************************************************
01117 *
01118 * sysToMonitor - transfer control to the ROM monitor
01119 *
01120 * This routine transfers control to the ROM monitor.  Normally, it is called
01121 * only by reboot()--which services ^X--and by bus errors at interrupt level.
01122 * However, in some circumstances, the user may wish to introduce a
01123 * <startType> to enable special boot ROM facilities.
01124 *
01125 * RETURNS: Does not return.
01126 */
01127 
01128 STATUS sysToMonitor
01129     (
01130     int startType       /* parameter passed to ROM to tell it how to boot */
01131     )
01132     {
01133     FUNCPTR pRom = (FUNCPTR) (ROM_TEXT_ADRS + 4); /* Warm reboot */
01134 
01135     cacheDisable (0);           /* Disable the Instruction Cache */
01136     cacheDisable (1);           /* Disable the Data Cache */
01137 
01138 #if     (CPU == PPC604)
01139     vxHid0Set (vxHid0Get () & ~_PPC_HID0_SIED); /* Enable Serial Instr Exec */
01140 #endif  /* (CPU == PPC604) */
01141 
01142     sysUniverseReset ();        /* reset Universe chip */
01143     sysSerialReset ();          /* reset serial devices */
01144 
01145     /* Clear the MSR */
01146 
01147     vxMsrSet (0);
01148 
01149     /* Reset the EPIC */
01150 
01151     sysPciOutLong((UINT32)EPIC_GLOBAL_CONFIG_REG, EPIC_GC_RESET);
01152 
01153     /* set the Board Fail LED */
01154 
01155     *(UINT8 *)MV2100_SYS_STAT_REG2 |= MV2100_BD_FAIL;
01156 
01157     (*pRom) (startType);
01158 
01159     return (OK);        /* in case we ever continue from ROM monitor */
01160     }
01161 
01162 
01163 #ifdef APS_BSP
01164 /******************************************************************************
01165 *
01166 * sysBusErrHandler - exception handler for VME Bus errors
01167 *
01168 * This routine is connected to the Machine Check Exception vector by
01169 * sysHwInit2(), and is responsible for resetting the machine status so
01170 * subsequent Bus Errors => PCI Recieved Target-Abort generate another
01171 * exception.  We also call the standard exception handler to suspend the
01172 * bad task and report the approximate location to the user.
01173 *
01174 * RETURNS: N/A
01175 */
01176 
01177 int sysBusErrHandler
01178     (
01179     ESFPPC *    pEsf            /* pointer to exception stack frame */
01180     )
01181     {
01182     UINT16 pciCfg = sysPciConfigInWord((UINT16 *)(CNFG_PCI_HOST_BRDG + KAHLUA_CFG_STATUS));
01183     if (pciCfg & (KAHLUA_PCI_RCV_MSTR_ABORT | KAHLUA_PCI_RCV_TGT_ABORT))
01184         {
01185         sysPciConfigOutWord((UINT16 *)(CNFG_PCI_HOST_BRDG + KAHLUA_CFG_STATUS), 
01186                             KAHLUA_PCI_RCV_MSTR_ABORT | KAHLUA_PCI_RCV_TGT_ABORT);
01187         excJobAdd(sysBusErrShow, 0, 0, 0, 0, 0, 0);
01188         }
01189     return excExcHandle(pEsf); /* Won't normally return */
01190     }
01191 
01192 #endif /* APS_BSP */
01193 
01194 /******************************************************************************
01195 *
01196 * sysHwInit2 - initialize additional system hardware
01197 *
01198 * This routine connects system interrupt vectors and configures any 
01199 * required features not configured by sysHwInit().
01200 *
01201 * RETURNS: N/A
01202 */
01203 
01204 void sysHwInit2 (void)
01205     {
01206     static BOOL configured = FALSE;
01207 
01208     /* Int connects for various devices */
01209 
01210     if (!configured)
01211         {
01212 
01213 #ifdef INCLUDE_AUXCLK
01214         sysAuxClkInit ();
01215         intConnect (INUM_TO_IVEC(TIMER0_INT_VEC), sysAuxClkInt, 0);
01216         intEnable (TIMER0_INT_LVL);
01217 #endif /* INCLUDE_AUXCLK */
01218 
01219         /* connect Vme to PCI interrupt */
01220 
01221         intConnect (INUM_TO_IVEC(UNIV_INT_VEC), sysUnivVmeIntr, 0);
01222 
01223         /* interrupts can only be turned on ultimately by the PIC int ctrlr */
01224 
01225         intEnable (UNIV_INT_LVL);
01226 
01227         /* initialize serial interrupts */
01228 
01229         sysSerialHwInit2();
01230 
01231 #ifdef APS_BSP
01232         /* Make VME Bus Errors generate a Machine Check exception */
01233         
01234         excVecSet((FUNCPTR *) _EXC_OFF_MACH, sysBusErrHandler);
01235         excVecSet((FUNCPTR *) _EXC_OFF_DATA, sysBusErrHandler);
01236 
01237         {
01238         UINT32 picr1;
01239         picr1 = sysPciConfigInLong((UINT32 *)(CNFG_PCI_HOST_BRDG + KAHLUA_CFG_PROC_IF_CFG1));
01240         picr1 |= KAHLUA_PIC1_MCP_EN;
01241         sysPciConfigOutLong((UINT32 *)(CNFG_PCI_HOST_BRDG + KAHLUA_CFG_PROC_IF_CFG1), picr1);
01242         }
01243 
01244         {
01245         UINT8 ErrEnR2;
01246         ErrEnR2 = sysPciConfigInByte((UINT8 *)(CNFG_PCI_HOST_BRDG + KAHLUA_CFG_ERROR_ENABLE2));
01247         ErrEnR2 |= KAHLUA_EE2_PCI_TARG_ABORT;
01248         sysPciConfigOutByte((UINT8 *)(CNFG_PCI_HOST_BRDG + KAHLUA_CFG_ERROR_ENABLE2), ErrEnR2);
01249         }
01250 
01251         sysPciConfigOutWord((UINT16 *)(CNFG_PCI_HOST_BRDG + KAHLUA_CFG_STATUS), 
01252                             KAHLUA_PCI_RCV_MSTR_ABORT | KAHLUA_PCI_RCV_TGT_ABORT);
01253 
01254         /* Enable Machine Check exceptions */
01255 
01256         vxMsrSet(vxMsrGet() | _PPC_MSR_ME);
01257         vxHid0Set(vxHid0Get() | _PPC_HID0_EMCP);
01258 
01259 #endif /* APS_BSP */
01260         configured = TRUE;
01261         }
01262 
01263 
01264     }
01265 
01266 
01267 /******************************************************************************
01268 *
01269 * sysProcNumGet - get the processor number
01270 *
01271 * This routine returns the processor number for the CPU board, which is
01272 * set with sysProcNumSet().
01273 *
01274 * RETURNS: The processor number for the CPU board.
01275 *
01276 * SEE ALSO: sysProcNumSet()
01277 */
01278 
01279 int sysProcNumGet (void)
01280     {
01281     return (sysProcNum);
01282     }
01283 
01284 
01285 /******************************************************************************
01286 *
01287 * sysProcNumSet - set the processor number
01288 *
01289 * This routine sets the processor number for the CPU board.  Processor numbers
01290 * should be unique on a single backplane.  It also maps local resources onto
01291 * the VMEbus.
01292 *
01293 * RETURNS: N/A
01294 *
01295 * SEE ALSO: sysProcNumGet()
01296 *
01297 */
01298 
01299 void sysProcNumSet
01300     (
01301     int         procNum                 /* processor number */
01302     )
01303     {
01304 
01305     /*
01306      *  Init global variable - this needs to be done before
01307      *  calling sysUniverseInit2() because it calls sysProcNumGet()
01308      *  via the MACRO definition.
01309      */
01310     sysProcNum = procNum;
01311 
01312     /*
01313      *  Set up the node's VME slave decoders.
01314      */
01315     sysUniverseInit2(procNum);
01316 
01317     }
01318 
01319 
01320 /* miscellaneous support routines */
01321 
01322 /******************************************************************************
01323 *
01324 * sysLocalToBusAdrs - convert a local address to a bus address
01325 *
01326 * This routine returns a VMEbus address as it would be seen on the bus.
01327 * The local address that is passed into this routine is the address of
01328 * the local resource as seen by the CPU.
01329 *
01330 * RETURNS: OK, or ERROR if the address space is unknown or the mapping is not
01331 * possible.
01332 *
01333 * #ifndef APS_BSP
01334 * SEE ALSO: sysBusToLocalAdrs()
01335 * #else APS_BSP
01336 * SEE ALSO: sysBusToLocalAdrs(), sysVmeMapShow()
01337 * #endif  APS_BSP 
01338 */
01339  
01340 STATUS sysLocalToBusAdrs
01341     (
01342     int         adrsSpace,      /* bus address space where busAdrs resides */
01343     char *      localAdrs,      /* local address to convert */ 
01344     char **     pBusAdrs        /* where to return bus address */ 
01345     )
01346     {
01347 
01348 #ifdef APS_BSP
01349     /* only cpu #0 maps memory to bus */
01350     if (sysProcNumGet () != 0)
01351         return ERROR;
01352 
01353 #endif /* APS_BSP */
01354     switch (adrsSpace)
01355         {
01356         case VME_AM_EXT_SUP_PGM:
01357         case VME_AM_EXT_SUP_DATA:
01358         case VME_AM_EXT_USR_PGM:
01359         case VME_AM_EXT_USR_DATA:
01360 #ifndef APS_BSP
01361             if ((VME_A32_SLV_SIZE != 0) &&
01362                 ((ULONG)localAdrs >= VME_A32_SLV_LOCAL) &&
01363 #else /* APS_BSP */
01364             if (((ULONG)localAdrs >= VME_A32_SLV_LOCAL) &&
01365 #endif /* APS_BSP */
01366                 ((ULONG)localAdrs < (VME_A32_SLV_LOCAL + VME_A32_SLV_SIZE)))
01367                 {
01368                 *pBusAdrs = localAdrs + (VME_A32_SLV_BUS - VME_A32_SLV_LOCAL);
01369                 return (OK);
01370                 }
01371 #ifndef APS_BSP
01372 
01373             else
01374 #endif /* APS_BSP */
01375                 return (ERROR);
01376 
01377         case VME_AM_STD_SUP_PGM:
01378         case VME_AM_STD_SUP_DATA:
01379         case VME_AM_STD_USR_PGM:
01380         case VME_AM_STD_USR_DATA:
01381 #ifndef APS_BSP
01382             if ((VME_A24_SLV_SIZE != 0) &&
01383                 ((ULONG)localAdrs >= VME_A24_SLV_LOCAL) &&
01384                 ((ULONG)localAdrs < (VME_A24_SLV_LOCAL + VME_A24_SLV_SIZE)))
01385 #else /* APS_BSP */
01386             if ((a24memPartId != 0) &&
01387                 ((ULONG)localAdrs >= a24memBase) &&
01388                 ((ULONG)localAdrs < a24memBound))
01389 #endif /* APS_BSP */
01390                 {
01391 #ifndef APS_BSP
01392                 *pBusAdrs = localAdrs + (VME_A24_SLV_BUS - VME_A24_SLV_LOCAL);
01393 #else /* APS_BSP */
01394                 *pBusAdrs = localAdrs - a24adrOffset;
01395 #endif /* APS_BSP */
01396                 return (OK);
01397                 }
01398 #ifndef APS_BSP
01399             else
01400 #endif /* APS_BSP */
01401                 return (ERROR);
01402 
01403 #ifndef APS_BSP
01404         case VME_AM_SUP_SHORT_IO:
01405         case VME_AM_USR_SHORT_IO:
01406             if ((VME_A16_SLV_SIZE != 0) &&
01407                 ((ULONG)localAdrs >= VME_A16_SLV_LOCAL) &&
01408                 ((ULONG)localAdrs < (VME_A16_SLV_LOCAL + VME_A16_SLV_SIZE)))
01409                 {
01410                 *pBusAdrs = localAdrs + (VME_A16_SLV_BUS - VME_A16_SLV_LOCAL);
01411                 return (OK);
01412                 }
01413             else
01414                 return (ERROR);
01415  
01416 #else /* APS_BSP */
01417 #if (VME_A16_SLV_SIZE != 0)
01418         case VME_AM_SUP_SHORT_IO:
01419         case VME_AM_USR_SHORT_IO:
01420             if (((ULONG)localAdrs >= VME_A16_SLV_LOCAL) &&
01421                 ((ULONG)localAdrs < (VME_A16_SLV_LOCAL + VME_A16_SLV_SIZE)))
01422                 {
01423                 *pBusAdrs = localAdrs + (VME_A16_SLV_BUS - VME_A16_SLV_LOCAL);
01424                 return (OK);
01425                 }
01426             return (ERROR);
01427 #endif /* VME_A16_SLV_SIZE */ 
01428 #endif /* APS_BSP */
01429         default:
01430             return (ERROR);
01431         }
01432     }
01433 
01434 /************************************************************************/
01435 /* DHT@SNS - Rewrote entire function */
01436 
01456 STATUS sysBusToLocalAdrs
01457     (
01458     int         adrsSpace,      /* bus address space where busAdrs resides */
01459     char *      busAdrs,        /* bus address to convert */
01460     char **     pLocalAdrs      /* where to return local address */
01461     )
01462     {
01463 
01464     unsigned int * univ_ctl[8];
01465     char * base, * bound;
01466     unsigned long offset, ctl;
01467     int i;
01468     unsigned long VAS;
01469 
01470 #define VAS_MASK LSI_CTL_USER2
01471 
01472     univ_ctl[0]=UNIVERSE_LSI0_CTL;
01473     univ_ctl[1]=UNIVERSE_LSI1_CTL;
01474     univ_ctl[2]=UNIVERSE_LSI2_CTL;
01475     univ_ctl[3]=UNIVERSE_LSI3_CTL;
01476     univ_ctl[4]=UNIVERSE_LSI4_CTL;
01477     univ_ctl[5]=UNIVERSE_LSI5_CTL;
01478     univ_ctl[6]=UNIVERSE_LSI6_CTL;
01479     univ_ctl[7]=UNIVERSE_LSI7_CTL;
01480     
01481 
01482     switch (adrsSpace)
01483         {
01484         case VME_AM_EXT_SUP_PGM:
01485         case VME_AM_EXT_USR_PGM:
01486         case VME_AM_EXT_SUP_DATA:
01487         case VME_AM_EXT_USR_DATA:
01488                 VAS=LSI_CTL_A32;
01489                 break;
01490         case VME_AM_STD_SUP_PGM:
01491         case VME_AM_STD_USR_PGM:
01492         case VME_AM_STD_SUP_DATA:
01493         case VME_AM_STD_USR_DATA:
01494                 VAS=LSI_CTL_A24;
01495                 break;
01496         case VME_AM_SUP_SHORT_IO:
01497         case VME_AM_USR_SHORT_IO:
01498                 VAS=LSI_CTL_A16;
01499                 break;
01500         default:
01501             return (ERROR);
01502         }
01503         for (i=0;i<8;i++)
01504         {
01505                 UNIV_IN_LONG(univ_ctl[i],&ctl);
01506                 if ((ctl&VAS_MASK)==VAS)
01507                 {
01508                         UNIV_IN_LONG(univ_ctl[i]+1,&base);
01509                         UNIV_IN_LONG(univ_ctl[i]+2,&bound);
01510                         UNIV_IN_LONG(univ_ctl[i]+3,&offset);
01511                         if (busAdrs >= (base+offset) && busAdrs < (bound+offset))
01512                         {
01513                                 *pLocalAdrs= busAdrs-offset;
01514                                 return OK;
01515                         }
01516                 }
01517         
01518         
01519         }
01520         return ERROR;
01521     }
01522 
01523 
01524 /*====*/
01525 /*******************************************************************************
01526 *
01527 * sysBusTas - test and set a specified location
01528 *
01529 * #ifndef APS_BSP
01530 * This routine performs a test-and-set (TAS) instruction on the specified
01531 * address.  To prevent deadlocks, interrupts are disabled during the
01532 * test-and-set operation.  The following table defines the method used to
01533 * insure an atomic operation.
01534 * #else APS_BSP
01535 * This routine performs an atomic test-and-set (TAS) instruction on 
01536 * the specified byte address.  One of three different methods is used
01537 * depending on where the TAS location is and the SM_OFF_BOARD macro.
01538 * sysVmeRmwTas is used for all off-board locations, and vxTas for
01539 * locations within vxWorks' SM_MEM boundaries as long as the
01540 * SM_OFF_BOARD macro is FALSE.sysVmeVownTas is used for all other
01541 * conditions.
01542 * #endif  APS_BSP
01543 *
01544 * #ifndef APS_BSP
01545 * .CS
01546 *               Master          Slave_1         Slave_2
01547 *#else  APS_BSP
01548 * RETURNS: TRUE if the value had not been set but is now
01549 *          FALSE if the value was already set.
01550 * #endif APS_BSP
01551 *
01552 *#ifndef APS_BSP
01553 * VME Chip      Don't Care      U1              U1
01554 *               ----------      ----            ----
01555 * Method        VOWN            VOWN            VOWN
01556 *
01557 * VME Chip      Don't Care      U1              U2
01558 *               ----------      ----            ----
01559 * Method        VOWN            VOWN            RMW
01560 *
01561 * VME Chip      U1 or           U2              U2
01562 *               U2+
01563 *               ----------      ----            ----
01564 * Method        VOWN+++         RMW             RMW
01565 *
01566 * VME Chip      U2++            U2              U2
01567 * PCI Bridge    or Raven3
01568 *               ----------      ----            ----
01569 * Method        lwarx/stwcx     RMW             RMW
01570 *
01571 *  +   = Refer to target.txt file for explanation of older boards
01572 *        with Universe II (U2).
01573 *  ++  = Refer to target.txt file for explanation of newer boards
01574 *        with Universe II (U2).
01575 *  +++ = The master's hardware does not preserve the atomic RMW.
01576 * ++++ = If SM_OFF_BOARD == TRUE,  the method used will be the same
01577 *        as if the master board is acting like a slave board; namely:
01578 *               RMW for UNIVERSE_II and VOWN for UNIVERSE_I
01579 * .CE
01580 *
01581 * NOTE: Although the address passed-in to sysBusTas() is defined as
01582 * "char *", vxTas() operates on the address as a "void *".
01583 * For PowerPC, this implies that the location tested-and-set is
01584 * actually a 32-bit entity.
01585 * 
01586 * RETURNS: TRUE if the value had not been set but is now, or
01587 * FALSE if the value was set already.
01588 *
01589 * #endif APS_BSP
01590 * SEE ALSO: vxTas(), sysBusTasClear()
01591 */
01592 #ifndef APS_BSP
01593 BOOL sysBusTas
01594     (
01595     char * adrs          /* address to be tested and set */
01596     )
01597     {
01598     /* Check for master node */
01599 
01600     if (sysProcNumGet() == 0)
01601         {
01602 #ifdef  ANY_BRDS_IN_CHASSIS_NOT_RMW
01603 
01604         /*
01605          * A slave board in the chassis cannot generate a VMEbus RMW,
01606          * and/or the master board cannot translate an incoming VMEbus
01607          * RMW into an atomic operation, and/or the master board cannot
01608          * generate a VMEbus RMW; therefore, the master must set
01609          * VOWN before doing a TAS.
01610          */
01611 
01612         return (sysVmeVownTas(adrs));
01613 
01614 #else
01615 #if     (SM_OFF_BOARD == FALSE)
01616         BOOL state = FALSE;  /* semaphore state */
01617         int  lockKey;        /* interrupt lock key */
01618 
01619         /* 
01620          * All slave boards in the chassis are generating a VMEbus RMW, and
01621          * the master board can translate an incoming VMEbus RMW into an
01622          * atomic operation; therefore, the master can simply call vxTas()
01623          * (lwarx/stwcx sequence) because the write portion of the RMW will
01624          * be detected.
01625          */
01626 
01627         /* lock interrupts so that vxTas() can execute without preemption */
01628 
01629         lockKey = intLock ();
01630 
01631         /* Perform TAS on local address */
01632 
01633         state =  vxTas ((UINT *)adrs);
01634         SYNC;
01635 
01636         intUnlock (lockKey);
01637 
01638         /* return TAS test result */
01639 
01640         return (state);
01641 
01642 #else
01643         /* The master board can generate a VMEbus RMW */
01644 
01645         return (sysVmeRmwTas(adrs));
01646 
01647 #endif  /* SM_OFF_BOARD */
01648 
01649 #endif  /* ANY_BRDS_IN_CHASSIS_NOT_RMW */
01650         }
01651     else        /* Slave node */
01652         {
01653         if (pciToVmeDev == UNIVERSE_II)
01654             {
01655             /* A board with the UNIVERSE_II can generate a VMEbus RMW */
01656 
01657             return (sysVmeRmwTas(adrs));
01658                 }
01659         else    /* UNIVERSE_I */
01660             {
01661             /*
01662              * A slave board with the UNIVERSE_I cannot generate a VMEbus
01663              * RMW; therefore, it must set VOWN before doing a TAS.
01664              */
01665 
01666             return (sysVmeVownTas(adrs));
01667 
01668             }
01669         }
01670 
01671     }
01672 
01673 #else /* APS_BSP */
01674 
01675 BOOL sysBusTas
01676     (
01677     char * adrs          /* address to be tested and set */
01678     )
01679     {
01680     if (IS_VME_ADDRESS(adrs))
01681         {
01682         return (sysVmeRmwTas(adrs));
01683         }
01684 
01685 #if (SM_OFF_BOARD == FALSE)
01686     else if ((adrs >= (char *) SM_MEM_ADRS) && 
01687              (adrs < (char *) SM_MEM_ADRS + SM_MEM_SIZE + SM_OBJ_MEM_SIZE))
01688         {
01689         /* use vxTas */
01690 
01691         BOOL state = FALSE;  /* semaphore state */
01692         int  lockKey;        /* interrupt lock key */
01693 
01694         /* lock interrupts so that vxTas() can execute without preemption */
01695 
01696         lockKey = intLock ();
01697 
01698         /* Perform TAS on local address */
01699 
01700         state =  vxTas ((UINT *)adrs);
01701         SYNC;
01702 
01703         intUnlock (lockKey);
01704 
01705         /* return TAS test result */
01706 
01707         return (state);
01708 
01709         }
01710 #endif /* (SM_OFF_BOARD == FALSE) */
01711 
01712     /* Got to grab the VMEbus first */
01713     return (sysVmeVownTas(adrs));
01714     }
01715 
01716 
01717 
01718 #endif /* APS_BSP */
01719 
01720 /******************************************************************************
01721 *
01722 * sysBusTasClear - clear a location set by sysBusTas()
01723 *
01724 * #ifndef APS_BSP
01725 * This routine clears the specified 32-bit location typically set
01726 * by sysBusTas().  The following table defines the method used to
01727 * insure an atomic operation.
01728 * #else APS_BSP
01729 * This routine clears the specified test-and-set location typically set
01730 * by sysBusTas().  One of three methods is used depending on where the
01731 * TAS location is and the SM_OFF_BOARD macro.
01732 * #endif APS_BSP
01733 *
01734 * #ifndef APS_BSP
01735 * .CS
01736 *               Master          Slave_1         Slave_2
01737 *
01738 * VME Chip      Don't Care      U1              U1
01739 *               ----------      ----            ----
01740 * Method        VOWN            VOWN            VOWN
01741 *
01742 * VME Chip      Don't Care      U1              U2
01743 *               ----------      ----            ----
01744 * Method        VOWN            VOWN            RMW
01745 *
01746 * VME Chip      U1 or           U2              U2
01747 *               U2+
01748 *               ----------      ----            ----
01749 * Method        VOWN+++         RMW             RMW
01750 *
01751 * VME Chip      U2++            U2              U2
01752 * PCI Bridge    or Raven3
01753 *               ------------    ------------    ------------
01754 * Method        simple clear    simple clear    simple clear
01755 *
01756 *
01757 *  +   = Refer to target.txt file for explaination of older boards
01758 *        with Universe II (U2).
01759 *  ++  = Refer to target.txt file for explaination of newer boards
01760 *        with Universe II (U2).
01761 *  +++ = The master's hardware does not preserve the atomic RMW.
01762 * ++++ = If SM_OFF_BOARD == TRUE,  no special/additional processing
01763 *        is required.
01764 * .CE
01765 *
01766 * #endif  APS_BSP
01767 * RETURNS: N/A
01768 *
01769 * SEE ALSO: sysBusTas()
01770 */
01771 #ifndef APS_BSP
01772 
01773 void sysBusTasClear
01774     (
01775     volatile char * adrs        /* Address of semaphore to be cleared */
01776     )
01777     {
01778 
01779 #ifdef  ANY_BRDS_IN_CHASSIS_NOT_RMW
01780 
01781     /*
01782      * A slave board in the chassis cannot generate a VMEbus RMW,
01783      * and/or the master board cannot translate an incoming VMEbus
01784      * RMW into an atomic operation; therefore, the master must set
01785      * VOWN before clearing a local TAS location.
01786      */
01787 
01788     BOOL state;
01789     int  lockKey;        /* interrupt lock key */
01790 
01791     /* Check for master node or slave node with UNIVERSE_I */
01792 
01793     if ((sysProcNumGet() == 0) ||
01794         (pciToVmeDev == UNIVERSE_I))
01795         {
01796 
01797         /*
01798          * Compute a 10 microsecond delay count
01799          *
01800          * NotTimeOut(loops) = timeout(usec)/clks/loop/CPU_SPEED(clks/usec)
01801          */
01802 
01803         int  NotTimeOut = ((MEMORY_BUS_SPEED/1000000) * UNLOCK_TIMEOUT)
01804                             / CPU_CLOCKS_PER_LOOP;
01805 
01806         /* do clearing with no interference */
01807 
01808         lockKey = intLock ();
01809 
01810         /* request ownership of the VMEbus */
01811 
01812         *UNIVERSE_MAST_CTL |= LONGSWAP(MAST_CTL_VOWN);
01813         SYNC;
01814 
01815         /* wait for the VME controller to give you the BUS */
01816 
01817         while (!VMEBUS_OWNER && NotTimeOut)
01818             {
01819             --NotTimeOut;
01820             }
01821 
01822         /* clear the location */
01823 
01824         *(UINT *)adrs = 0;
01825         SYNC;
01826 
01827         /* release the VME BUS */
01828 
01829         *UNIVERSE_MAST_CTL &= LONGSWAP(~MAST_CTL_VOWN);
01830 
01831         /* enable normal operation */
01832 
01833         intUnlock (lockKey);
01834         }
01835     else        /* Slave node == UNIVERSE_II */
01836         {
01837         /* Lock interrupts so that setting up SCG and issuing RMW are atomic */
01838 
01839         lockKey = intLock ();
01840 
01841         /* Enable RMW cycle */
01842 
01843         sysBusRmwEnable(VME_SCG_COMPARE_MASK,
01844                         VME_SCG_COMPARE_TO_CLEAR,
01845                         VME_SCG_SWAP_TO_CLEAR,
01846                         (char *)adrs);
01847 
01848         /* perform RMW to clear TAS location */
01849 
01850         state = *((UINT *)adrs);
01851         SYNC;
01852 
01853         /* Disable RMW cycle */
01854 
01855         sysBusRmwDisable();
01856 
01857         /* unlock the interrupt */
01858 
01859         intUnlock (lockKey);
01860         }
01861 #else
01862 #if     (SM_OFF_BOARD == FALSE)
01863     /*
01864      * All slave boards in the chassis can generate a VMEbus RMW, and
01865      * the master board can translate an incoming VMEbus RMW into an
01866      * atomic operation therefore, all boards can do a simple clear.
01867      */
01868 
01869     *(UINT *)adrs = 0;
01870     SYNC;
01871 
01872 #else   /* SM_OFF_BOARD == TRUE */
01873 
01874     /* Check for master node or slave node with UNIVERSE_I */
01875 
01876     if ((sysProcNumGet() == 0) ||
01877         (pciToVmeDev == UNIVERSE_I))
01878         {
01879         /*
01880          * Compute a 10 microsecond delay count
01881          *
01882          * NotTimeOut(loops) = timeout(usec)/clks/loop/CPU_SPEED(clks/usec)
01883          */
01884 
01885         int  NotTimeOut = ((MEMORY_BUS_SPEED/1000000) * UNLOCK_TIMEOUT)
01886                             / CPU_CLOCKS_PER_LOOP;
01887 
01888         /* do clearing with no interference */
01889 
01890         lockKey = intLock ();
01891 
01892         /* request ownership of the VMEbus */
01893 
01894         *UNIVERSE_MAST_CTL |= LONGSWAP(MAST_CTL_VOWN);
01895         SYNC;
01896 
01897         /* wait for the VME controller to give you the BUS */
01898 
01899         while (!VMEBUS_OWNER && NotTimeOut)
01900             {
01901             --NotTimeOut;
01902             }
01903 
01904         /* clear the location */
01905 
01906         *(UINT *)adrs = 0;
01907         SYNC;
01908 
01909         /* release the VME BUS */
01910 
01911         *UNIVERSE_MAST_CTL &= LONGSWAP(~MAST_CTL_VOWN);
01912 
01913         /* enable normal operation */
01914 
01915         intUnlock (lockKey);
01916         }
01917     else        /* Slave node == UNIVERSE_II */
01918         {
01919         /* Lock interrupts so that setting up SCG and issuing RMW are atomic */
01920 
01921         lockKey = intLock ();
01922 
01923         /* Enable RMW cycle */
01924 
01925         sysBusRmwEnable(VME_SCG_COMPARE_MASK,
01926                         VME_SCG_COMPARE_TO_CLEAR,
01927                         VME_SCG_SWAP_TO_CLEAR,
01928                         (char *)adrs);
01929 
01930         /* perform RMW to clear TAS location */
01931 
01932         state = *((UINT *)adrs);
01933         SYNC;
01934 
01935         /* Disable RMW cycle */
01936 
01937         sysBusRmwDisable();
01938 
01939         /* unlock the interrupt */
01940 
01941         intUnlock (lockKey);
01942         }
01943 
01944 #endif  /* SM_OFF_BOARD */
01945 #endif  /* ANY_BRDS_IN_CHASSIS_NOT_RMW */
01946     }
01947 
01948 
01949 
01950 #else /* APS_BSP */
01951 void sysBusTasClear
01952     (
01953     volatile char * adrs        /* Address of semaphore to be cleared */
01954     )
01955     {
01956     /* Check for an off-board location */
01957     
01958     if (IS_VME_ADDRESS(adrs))
01959         {
01960         /* Use a simple clear, 8 bits only */
01961         SYNC;
01962         *adrs = 0;
01963         }
01964 #if (SM_OFF_BOARD == FALSE)
01965     else if ((adrs >= (char *) SM_MEM_ADRS) && 
01966              (adrs < (char *) SM_MEM_ADRS + SM_MEM_SIZE + SM_OBJ_MEM_SIZE))
01967         {
01968         /* Use a simple clear, 32-bits */
01969         SYNC;
01970         *(UINT *)adrs = 0;
01971         }
01972 #endif
01973     else
01974         {
01975         /* Got to grab the VMEbus first */
01976         sysVmeVownClear(adrs);
01977         }
01978     }
01979 
01980 
01981 
01982 
01983 #endif /* APS_BSP */
01984 
01985 
01986 
01987 
01988 /*******************************************************************************
01989 *
01990 * sysVmeVownTas - test and set a location across the VMEbus
01991 *
01992 * This routine performs a test-and-set (TAS) instruction on the specified
01993 * address.  To prevent deadlocks, interrupts are disabled and the VMEbus is
01994 * locked during the test-and-set operation.  sysVmeVownTas can be used with
01995 * local or VME locations, but in both cases the atomicity of its operation
01996 * is maintained by retaining ownership of the VMEbus between two separate
01997 * test and set instructions.  This will not be atomic where a competing CPU
01998 * has a non-VMEbus route to the location, unless that CPU still claims the
01999 * VMEbus around its test-and-set operation like sysVmeVownTas does even
02000 * when the address is local to the mv2100 CPU.
02001 *
02002 * NOTE: Although the address passed in to sysBusTas() is defined as "char *",
02003 * the vxTas() argument is a "void *".  For PowerPC the location that is
02004 * tested-and-set using sysVmeVownTas is therefor a 32-bit entity.
02005 * 
02006 * RETURNS: TRUE if the value had not been set but is now
02007 * FALSE if the VMEbus cannot be locked or the value was already set.
02008 *
02009 * SEE ALSO: vxTas(), sysVmeVownTasClear(), sysVmeRmwTas()
02010 */
02011 
02012 #ifndef APS_BSP
02013 LOCAL BOOL sysVmeVownTas
02014     (
02015     char * adrs          /* address to be tested and set */
02016     )
02017     {
02018     BOOL state = FALSE;  /* semaphore state */
02019     int  lockKey;        /* interrupt lock key */
02020 
02021     /*
02022      * Compute a 10 microsecond delay count
02023      *
02024      * NotTimeOut(loops) = timeout(usec)/clks/loop/CPU_SPEED(clks/usec)
02025      */
02026 
02027     int  NotTimeOut = ((MEMORY_BUS_SPEED/1000000) * LOCK_TIMEOUT)
02028                         / CPU_CLOCKS_PER_LOOP;
02029 
02030     /* lock interrupts so there will be no TAS interference */
02031 
02032     lockKey = intLock ();
02033 
02034     /* Request ownership of the VMEbus */
02035 
02036     *UNIVERSE_MAST_CTL |= LONGSWAP(MAST_CTL_VOWN);
02037     SYNC;
02038 
02039     /* Wait for the VME controller to give you the BUS */
02040 
02041     while (!VMEBUS_OWNER && NotTimeOut)
02042         {
02043         --NotTimeOut;
02044         }
02045 
02046     /* perform the TAS */
02047 
02048     if (VMEBUS_OWNER)
02049         {
02050         state =  vxTas ((UINT *)adrs);
02051         SYNC;
02052         }
02053 
02054     /* release the VME BUS */
02055     
02056     *UNIVERSE_MAST_CTL &= LONGSWAP(~MAST_CTL_VOWN);
02057 
02058     /* unlock the interrupt */
02059 
02060     intUnlock (lockKey);
02061 
02062     /* return TAS test result */
02063 
02064     return (state);
02065 
02066     }
02067 #else /* APS_BSP */
02068 LOCAL BOOL sysVmeVownTas
02069     (
02070     char * adrs          /* address to be tested and set */
02071     )
02072     {
02073     BOOL state = FALSE;  /* semaphore state */
02074     int  lockKey;        /* interrupt lock key */
02075 
02076     /*
02077      * Compute a 10 microsecond delay count
02078      *
02079      * NotTimeOut(loops) = timeout(usec)/clks/loop/CPU_SPEED(clks/usec)
02080      */
02081 
02082     int  NotTimeOut = ((MEMORY_BUS_SPEED/1000000) * LOCK_TIMEOUT)
02083                         / CPU_CLOCKS_PER_LOOP;
02084 
02085     /* lock interrupts so there will be no TAS interference */
02086 
02087     lockKey = intLock ();
02088 
02089     /* Request ownership of the VMEbus */
02090 
02091     *UNIVERSE_MAST_CTL |= LONGSWAP(MAST_CTL_VOWN);
02092     SYNC;
02093 
02094     /* Wait for the VME controller to give you the BUS */
02095 
02096     while (!VMEBUS_OWNER && NotTimeOut)
02097         {
02098         --NotTimeOut;
02099         }
02100 
02101     /* perform the TAS */
02102 
02103     if (VMEBUS_OWNER)
02104         {
02105         state =  vxTas ((UINT *)adrs);
02106         SYNC;
02107         }
02108 
02109     /* release the VME BUS */
02110     
02111     *UNIVERSE_MAST_CTL &= LONGSWAP(~MAST_CTL_VOWN);
02112 
02113     /* unlock the interrupt */
02114 
02115     intUnlock (lockKey);
02116 
02117     /* return TAS test result */
02118 
02119     return (state);
02120 
02121     }
02122 
02123 
02124 #endif /* APS_BSP */
02125 
02126 #ifdef APS_BSP
02127 
02128 
02129 /*******************************************************************************
02130 *
02131 * sysVmeVownClear - clear a test-and-set location
02132 *
02133 * This routine clears a test-and-set (TAS) word at the specified address.
02134 * To prevent deadlocks, interrupts are disabled and the VMEbus is locked
02135 * during the clear operation.  sysVmeVownClr can be used with local or
02136 * VME locations, but is only actually needed for addresses local to the
02137 * mv2700 where a remote CPU is using sysVmeVownTas for its test-and-set
02138 * method.  This prevents the mv2700 clear from happening in between the
02139 * test and set cycles from the remote CPU.  Deadlock would occur if the
02140 * other CPU always did the write operation even when the test failed.
02141 *
02142 * NOTE: Although the address passed in to sysBusTas() is defined as "char *",
02143 * the vxTas() argument is a "void *".  For PowerPC the location that is
02144 * tested-and-set using sysVmeVownTas is therefor a 32-bit entity.
02145 * 
02146 * RETURNS: TRUE if the value had not been set but is now
02147 * FALSE if the VMEbus cannot be locked or the value was already set.
02148 *
02149 * SEE ALSO: vxTas(), sysVmeRmwTas
02150 */
02151 
02152 LOCAL void sysVmeVownClear
02153     (
02154     volatile char * adrs          /* address that was tested and set */
02155     )
02156     {
02157     int  lockKey;        /* interrupt lock key */
02158 
02159     /*
02160      * Compute a 10 microsecond delay count
02161      *
02162      * NotTimeOut(loops) = timeout(usec)/clks/loop/CPU_SPEED(clks/usec)
02163      */
02164 
02165     int  NotTimeOut = ((MEMORY_BUS_SPEED/1000000) * LOCK_TIMEOUT)
02166                         / CPU_CLOCKS_PER_LOOP;
02167 
02168     /* lock interrupts to prevent interference */
02169 
02170     lockKey = intLock ();
02171 
02172     /* Request ownership of the VMEbus */
02173 
02174     *UNIVERSE_MAST_CTL |= LONGSWAP(MAST_CTL_VOWN);
02175     SYNC;
02176 
02177     /* Wait for the VME controller to give you the BUS */
02178 
02179     while (!VMEBUS_OWNER && NotTimeOut)
02180         {
02181         --NotTimeOut;
02182         }
02183 
02184     /* clear the location anyway */
02185 
02186     SYNC;
02187     *(UINT *)adrs = 0;
02188 
02189     /* release the VME BUS */
02190 
02191     *UNIVERSE_MAST_CTL &= LONGSWAP(~MAST_CTL_VOWN);
02192 
02193     /* unlock the interrupt */
02194 
02195     intUnlock (lockKey);
02196 
02197     }
02198 #endif /* APS_BSP */
02199 
02200 
02201 
02202 /*******************************************************************************
02203 *
02204 * sysVmeRmwTas - test and set a location across the VMEbus utilizing RMW
02205 *
02206 * This routine performs a test-and-set (TAS) instruction on the specified
02207 * #ifndef APS_BSP
02208 * address.  To prevent deadlocks, interrupts are disabled and the VMEbus is
02209 * locked during the test-and-set operation.
02210 * #else APS_BSP 
02211 * address, which must be on a different VME board.  Interrupts are disabled 
02212 * during the test-and-set operation so the Universe II chip's Special Cycle 
02213 * Generator is only enabled for the RMW operation.  sysVmeRmwTas can only
02214 * test-and-set locations across the VMEbus, local addresses may be tested
02215 * but never set.
02216 * #endif  APS_BSP 
02217 *
02218 * #ifndef APS_BSP
02219 * NOTE: Although the address passed-in to sysBusTas() is defined as
02220 *       "char *", vxTas() operates on the address as a "void *".
02221 *       For PowerPC, this implies that the location tested-and-set is
02222 *       actually a 32-bit entity.
02223 * #else APS_BSP 
02224 * NOTE: Unlike the built-in vxTas() routine from vxWorks, this version
02225 * of sysVmeRmwTas provides full emulation of the MC680x0's TAS instruction
02226 * by only accessing the byte pointed to, and only altering the top bit of
02227 * that byte.  The two are compatible as long as the same 4-byte aligned
02228 * address is used.
02229 * #endif  APS_BSP 
02230 * 
02231 * RETURNS: TRUE if the value had not been set but is now
02232 * #ifndef APS_BSP
02233 *          FALSE if the VMEbus cannot be locked or the value was already set.
02234 * #else APS_BSP 
02235 * FALSE if the value was already set.
02236 * #endif APS_BSP 
02237 *
02238 * #ifndef APS_BSP
02239 * SEE ALSO: vxTas()
02240 * #else  APS_BSP 
02241 * SEE ALSO: vxTas(), sysVmeVownTas()
02242 * #endif  APS_BSP 
02243 */
02244 
02245 #ifndef APS_BSP
02246 LOCAL BOOL sysVmeRmwTas
02247     (
02248     char * adrs          /* address to be tested and set */
02249     )
02250     {
02251     BOOL state = FALSE;  /* semaphore state */
02252     int  lockKey;        /* interrupt lock key */
02253 
02254     /* A board with the UNIVERSE_II can generate a VMEbus RMW */
02255 
02256     /*
02257      * Lock interrupts so that setting up SCG and issuing RMW
02258      * are atomic
02259      */
02260 
02261     lockKey = intLock ();
02262 
02263     /* Enable RMW cycle */
02264 
02265     sysBusRmwEnable(VME_SCG_COMPARE_MASK,
02266                     VME_SCG_COMPARE_TO_SET,
02267                     VME_SCG_SWAP_TO_SET,
02268                     (char *)adrs);
02269 
02270     /* perform RMW to try and set TAS location */
02271 
02272     state = *((UINT *)adrs);
02273     SYNC;
02274 
02275     /* Disable RMW cycle */
02276 
02277     sysBusRmwDisable();
02278 
02279     /* unlock the interrupt */
02280 
02281     intUnlock (lockKey);
02282 
02283     /* return TAS test result */
02284 
02285     if (state)
02286         {
02287         return (FALSE);
02288         }
02289     else
02290         {
02291         return (TRUE);
02292         }
02293     }
02294 
02295 #else /* APS_BSP */
02296 LOCAL BOOL sysVmeRmwTas
02297     (
02298     char * adrs          /* address to be tested and set */
02299     )
02300     {
02301     BOOL state = FALSE;  /* semaphore state */
02302     int  lockKey;        /* interrupt lock key */
02303     ULONG mask = 0x80000000 >> ((ULONG) adrs & 0x3) * 8; /* bit to TAS */
02304 
02305     /* A board with the UNIVERSE_II can generate a VMEbus RMW */
02306 
02307     /*
02308      * Lock interrupts so that setting up SCG and issuing RMW
02309      * are atomic
02310      */
02311 
02312     lockKey = intLock ();
02313 
02314     /* Enable RMW cycle */
02315 
02316     sysBusRmwEnable (mask, 0x00000000, 0x80808080, adrs);
02317 
02318     /* perform RMW to try and set TAS location */
02319 
02320     state = *adrs;
02321     SYNC;
02322 
02323     /* Disable RMW cycle */
02324 
02325     sysBusRmwDisable();
02326 
02327     /* unlock the interrupt */
02328 
02329     intUnlock (lockKey);
02330 
02331     /* return TAS test result */
02332 
02333     return (state & 0x80) ? (FALSE) : (TRUE);
02334     }
02335 #endif /* APS_BSP */
02336 
02337 
02338 /******************************************************************************
02339 *
02340 * sysLanIntEnable - enable the LAN interrupt
02341 *
02342 * This routine enables interrupts at a specified level for the on-board LAN
02343 * chip.  The LANCE chip on this board is on the Peripheral Component
02344 * Interconnect (PCI) bus.  The LANCE chip asserts PCI IRQ0 which is routed
02345 * to the EPIC Serial Interrupt #1.
02346 *
02347 * RETURNS: OK, or ERROR if network support not included.
02348 *
02349 * SEE ALSO: sysLanIntDisable()
02350 */
02351 
02352 STATUS sysLanIntEnable
02353     (
02354     int intLevel                /* interrupt level to enable */
02355     )
02356     {
02357 #ifdef INCLUDE_NETWORK
02358     intEnable (intLevel);
02359     return (OK);
02360 #else
02361     return (ERROR);
02362 #endif /* INCLUDE_NETWORK */
02363     }
02364 
02365 
02366 /******************************************************************************
02367 *
02368 * sysLanIntDisable - disable the LAN interrupt
02369 *
02370 * This routine disables interrupts for the on-board LAN chip. 
02371 *
02372 * RETURNS: OK, or ERROR if network support not included.
02373 *
02374 * SEE ALSO: sysLanIntEnable()
02375 */
02376 
02377 STATUS sysLanIntDisable
02378     (
02379     int intLevel                /* interrupt level to enable */
02380     )
02381     {
02382 #ifdef INCLUDE_NETWORK
02383     /* 
02384      *  disable the Serial interrupt #1 for the MV2100
02385      */
02386 
02387     intDisable (intLevel);
02388 
02389     return (OK);
02390 #else
02391     return (ERROR);
02392 #endif /* INCLUDE_NETWORK */
02393     }
02394 
02395 
02396 /******************************************************************************
02397 *
02398 * sysSpuriousIntHandler - spurious interrupt handler
02399 *
02400 * This is the entry point for spurious interrupts.
02401 *
02402 * NOTE: This routine has no effect.
02403 *
02404 * This routine catches all spurious interrupts.  It does nothing at all.
02405 *
02406 * RETURNS: N/A.
02407 *
02408 * RETURNS: N/A
02409 *
02410 * NOMANUAL
02411 */
02412 
02413 void sysSpuriousIntHandler (void)
02414     {
02415     }
02416 
02417 
02418 /******************************************************************************
02419 *
02420 * sysNvRead - read one byte from NVRAM
02421 *
02422 * This routine reads a single byte from a specified offset in NVRAM.
02423 *
02424 * RETURNS: The byte from the specified NVRAM offset.
02425 */
02426 
02427 UCHAR sysNvRead
02428     (
02429     ULONG       offset  /* NVRAM offset to read the byte from */
02430     )
02431     {
02432     return (sysInByte (NVRAM_BASE + offset));
02433     }
02434 
02435 
02436 /******************************************************************************
02437 *
02438 * sysNvWrite - write one byte to NVRAM
02439 *
02440 * This routine writes a single byte to a specified offset in NVRAM.
02441 *
02442 * RETURNS: N/A
02443 */
02444 
02445 void sysNvWrite
02446     (
02447     ULONG       offset, /* NVRAM offset to write the byte to */
02448     UCHAR       data    /* datum byte */
02449     )
02450     {
02451     sysOutByte (NVRAM_BASE + offset, data);
02452     }
02453 
02454 
02455 /*******************************************************************************
02456 *
02457 * sysCpuCheck - confirm the CPU type
02458 *
02459 * This routine validates the cpu type.  If the wrong cpu type is discovered
02460 * a message is printed using the serial channel in polled mode.
02461 *
02462 * RETURNS: N/A.
02463 */
02464 
02465 #ifdef APS_BSP
02466 LOCAL
02467 #endif /* APS_BSP */
02468 void sysCpuCheck (void)
02469     {
02470     int msgSize;
02471     int msgIx;
02472     SIO_CHAN * pSioChan;        /* serial I/O channel */
02473 
02474     /* Check for a valid CPU type;  If one is found, just return */
02475 
02476     if  ((CPU_TYPE == CPU_TYPE_603) || (CPU_TYPE == CPU_TYPE_603E) ||
02477          (CPU_TYPE == CPU_TYPE_603P) || (CPU_TYPE == CPU_TYPE_603EK))
02478         {
02479         return;
02480         }
02481 
02482     /* Invalid CPU type; print error message and terminate */
02483 
02484     msgSize = strlen (wrongCpuMsg);
02485 
02486     sysSerialHwInit ();
02487 
02488     pSioChan = sysSerialChanGet (0);
02489 
02490     sioIoctl (pSioChan, SIO_MODE_SET, (void *) SIO_MODE_POLL);
02491 
02492     for (msgIx = 0; msgIx < msgSize; msgIx++)
02493         {
02494         while (sioPollOutput (pSioChan, wrongCpuMsg[msgIx]) == EAGAIN);
02495         }
02496 
02497     sysToMonitor (BOOT_NO_AUTOBOOT);
02498     }
02499 
02500 
02501 #if defined(INCLUDE_PMC_SPAN) && !defined(INCLUDE_PCI_AUTOCONF)
02502 /******************************************************************************
02503 *
02504 * sysPmcSpanConfig - configure the PMC Span (DEC21150 PCI-to-PCI Bridge)
02505 *
02506 * This routine configures the DEC21150 PCI-to-PCI Bridge on the PMC Span.
02507 *
02508 * RETURNS: OK or ERROR if pciConfigLib has not been initialized.
02509 */
02510 
02511 #ifdef APS_BSP
02512 LOCAL
02513 #endif /* APS_BSP */
02514 STATUS sysPmcSpanConfig
02515     (
02516     int         pciBusNo,       /* PCI bus number */
02517     int         pciDevNo,       /* PCI device number */
02518     int         pciFuncNo,      /* PCI function number */
02519     PMC_SPAN *  pmcSpan         /* pointer to PMC Span config array */
02520     )
02521     {
02522     STATUS      result = OK;
02523     FAST        i;
02524 
02525     /* Write all parameters in pcmSpan in the order given */
02526 
02527     for (i = 0; i < NUM_PMC_SPAN_PARMS && result == OK; ++i)
02528         {
02529         switch (pmcSpan[i].parmSize)
02530             {
02531             case 1:
02532                 result = pciConfigOutByte (pciBusNo, pciDevNo, pciFuncNo,
02533                                            pmcSpan[i].parmOffset,
02534                                            pmcSpan[i].parmValue);
02535                 break;
02536 
02537             case 2:
02538                 result = pciConfigOutWord (pciBusNo, pciDevNo, pciFuncNo,
02539                                            pmcSpan[i].parmOffset,
02540                                            pmcSpan[i].parmValue);
02541                 break;
02542 
02543             case 4:
02544                 result = pciConfigOutLong (pciBusNo, pciDevNo, pciFuncNo,
02545                                            pmcSpan[i].parmOffset,
02546                                            pmcSpan[i].parmValue);
02547                 break;
02548             }
02549         }
02550 
02551     return (result);
02552     }
02553 #endif /* INCLUDE_PMC_SPAN  & !defined(INCLUDE_PCI_AUTOCONF) */
02554 
02555 
02556 /******************************************************************************
02557 *
02558 * sysMemProbeTrap - trap handler for vxMemProbe exception
02559 *
02560 * This routine is called from the excConnectCode stub if sysMemProbeSup
02561 * generates an exception. By default, sysMemProbeSup returns OK.
02562 * This code changes the PC value to "sysProbeExc" (within the sysMemProbeSup
02563 * routine), and sysProbeExc sets the return value to ERROR.
02564 *
02565 * RETURNS: 0
02566 */
02567 
02568 static int sysMemProbeTrap
02569     (
02570     ESFPPC *    pEsf            /* pointer to exception stack frame */
02571     )
02572     {
02573     REG_SET *pRegSet = &pEsf->regSet;
02574 
02575     pRegSet->pc = (_RType)sysProbeExc;  /* sysProbeExc forces an ERROR return */
02576     return (0);
02577     }
02578 
02579 
02580 /******************************************************************************
02581 *
02582 * sysMemProbeBus - probe an address on a bus.
02583 *
02584 * This routine probes a specified address to see if it is readable or
02585 * writable, as specified by <mode>.  The address will be read or written as
02586 * 1, 2, or 4 bytes as specified by <length> (values other than 1, 2, or 4
02587 * yield unpredictable results).  If the probe is a VX_READ, the value read will
02588 * be copied to the location pointed to by <pVal>.  If the probe is a VX_WRITE,
02589 * the value written will be taken from the location pointed to by <pVal>.
02590 * In either case, <pVal> should point to a value of 1, 2, or 4 bytes, as
02591 * specified by <length>.
02592 *
02593 * This routine probes the specified address with interrupts disabled and
02594 * a special handler for Machine Check, Data Access and Alignment exceptions.
02595 *
02596 * RETURNS: OK if probe succeeded or ERROR if an exception occured.
02597 */
02598 
02599 static STATUS sysMemProbeBus
02600     (
02601     char   * adrs,      /* address to be probed */
02602     int      mode,      /* VX_READ or VX_WRITE */
02603     int      length,    /* 1, 2 or 4 byte probe */
02604     char   * pVal       /* address of value to write OR */
02605                         /* address of location to place value read */
02606     )
02607     {
02608     int      oldLevel;
02609     FUNCPTR  oldVec1;
02610     FUNCPTR  oldVec2;
02611     STATUS   status;
02612     UINT32   ppcHid0;   /* H/W Implementation Dependent reg (PPC60x) */
02613     UINT32   ppcMsr;    /* PPC Machine Status Reg */
02614     UINT16   temp;
02615 
02616     /* Probes performed with interrupts disabled */
02617 
02618     oldLevel = intLock ();
02619 
02620     /* Handle Machine Check Exceptions locally */
02621 
02622     oldVec1 = excVecGet ((FUNCPTR *) _EXC_OFF_MACH);
02623     excVecSet ((FUNCPTR *) _EXC_OFF_MACH, FUNCREF(sysMemProbeTrap)); 
02624 
02625     /*
02626      *  Handle Data Access Exceptions locally
02627      *
02628      *  Data Access Exceptions will occur when trying to probe addresses
02629      *  that have not been mapped by the MMU.
02630      */
02631 
02632     oldVec2 = excVecGet ((FUNCPTR *) _EXC_OFF_DATA);
02633     excVecSet ((FUNCPTR *) _EXC_OFF_DATA, FUNCREF(sysMemProbeTrap));
02634 
02635     /* Enable Machine Check Pin (EMCP) */
02636 
02637     ppcHid0 = vxHid0Get();
02638     vxHid0Set(ppcHid0 | _PPC_HID0_EMCP);
02639 
02640     /* Enable Machine Check exception */
02641 
02642     ppcMsr = vxMsrGet();
02643     vxMsrSet(ppcMsr | _PPC_MSR_ME);
02644 
02645     /* clear the PCI abort bits in the PCI status word */
02646 
02647     sysPciConfigOutWord((UINT16 *)(CNFG_PCI_HOST_BRDG + KAHLUA_CFG_STATUS),
02648                         (KAHLUA_PCI_RCV_MSTR_ABORT | KAHLUA_PCI_RCV_TGT_ABORT));
02649 
02650     /* do probe */
02651 
02652     if (mode == VX_READ)
02653         {
02654         status = sysMemProbeSup (length, adrs, pVal);
02655         SYNC;
02656         }
02657     else
02658         {
02659         status = sysMemProbeSup (length, pVal, adrs);
02660         SYNC;
02661         }
02662 
02663     /* check for valid address */
02664 
02665     temp = sysPciConfigInWord((UINT16 *)(CNFG_PCI_HOST_BRDG + 
02666                               KAHLUA_CFG_STATUS));
02667     if (temp & (KAHLUA_PCI_RCV_MSTR_ABORT | KAHLUA_PCI_RCV_TGT_ABORT))
02668         status = ERROR;
02669 
02670     /* clear the PCI status reg. bits */
02671 
02672     sysPciConfigOutWord((UINT16 *)(CNFG_PCI_HOST_BRDG + KAHLUA_CFG_STATUS), 
02673                         (KAHLUA_PCI_RCV_MSTR_ABORT | KAHLUA_PCI_RCV_TGT_ABORT));
02674 
02675     /* Disable Machine Check Exceptions */
02676 
02677     vxMsrSet(ppcMsr);
02678 
02679     /* Disable Machine Check Pin (EMCP) */
02680 
02681     vxHid0Set(ppcHid0);
02682 
02683     /* restore original vectors and unlock */
02684 
02685     excVecSet ((FUNCPTR *) _EXC_OFF_DATA, oldVec2);
02686 
02687     excVecSet ((FUNCPTR *) _EXC_OFF_MACH, oldVec1);
02688 
02689     intUnlock (oldLevel);
02690 
02691     return (status);
02692     }
02693 
02694 
02695 /******************************************************************************
02696 *
02697 * sysProbeErrClr - clear errors associated with probing an address on a bus.
02698 *
02699 * This routine clears the error flags and conditions in the DAR, DSISR, SRR0
02700 * and SRR1 PowerPC registers arising from probing addresses as well as the
02701 * PCI_CFG_STATUS registers and the Universe PCI_CSR and V_AMERR registers.
02702 *
02703 * RETURNS: N/A
02704 */
02705 
02706 void sysProbeErrClr (void)
02707     {
02708     UINT32  pciCsr;
02709 
02710     /* Get current status */
02711 
02712     pciCsr = sysPciInLong ((UINT32)(UNIVERSE_PCI_CSR));
02713 
02714     /* Clear PCI_CSR */
02715 
02716     sysPciOutLong ((UINT32)(UNIVERSE_PCI_CSR), pciCsr);
02717 
02718     /* Clear any VME address error */
02719 
02720     sysPciOutLong ((UINT32)UNIVERSE_V_AMERR, V_AMERR_V_STAT);
02721 
02722     /* Force write due to Write-Posting and get updated status */
02723 
02724     pciCsr = sysPciInLong ((UINT32)(UNIVERSE_PCI_CSR));
02725 
02726     /* Clear PowerPC Data Access Exception Registers */
02727 
02728     vxDarSet   (0);
02729     vxDsisrSet (0);
02730     vxSrr0Set  (0);
02731     vxSrr1Set  (0);
02732     }
02733 
02734 /******************************************************************************
02735 *
02736 * sysVmeProbe - probe a VME bus address
02737 *
02738 * This routine probes an address on the VME bus.  The PCI bridge chip
02739 * must have a special setup to enable generation of Master Abort cycles on
02740 * write probes and reception of Target Abort cycles on read probes.
02741 * The CPU must be configured to enable Machine Check exceptions.  In 
02742 * addition, if the probe is a write, the Universe must be configured to
02743 * disable Posted Writes.  All probing is done with interrupts disabled.
02744 *
02745 * NOTE: This routine assumes that the Universe Local Control registers are
02746 * dedicated to these VME address spaces:
02747 *
02748 * .CS
02749 * #ifndef APS_BSP
02750 *   LSI0 - LM/SIG (mailbox)
02751 * #endif  APS_BSP 
02752 *   LSI1 - A32
02753 *   LSI2 - A24
02754 *   LSI3 - A16
02755 * .CE
02756 *
02757 * RETURNS: OK or ERROR if address cannot be probed
02758 */
02759 
02760 #ifndef APS_BSP
02761 STATUS sysVmeProbe
02762 #else /* APS_BSP */
02763 LOCAL STATUS sysVmeProbe
02764 #endif /* APS_BSP */
02765     (
02766     char   * adrs,      /* address to be probed */
02767     int      mode,      /* VX_READ or VX_WRITE */
02768     int      length,    /* 1, 2 or 4 byte probe */
02769     char   * pVal       /* address of value to write OR */
02770                         /* address of location to place value read */
02771     )
02772     {
02773     STATUS status = ERROR;
02774     UINT32 lsiCtlReg;   /* adress of Local Control register in Universe */
02775     UINT32 pciSlv1Ctl;  /* Universe PCI Slave Image Control reg */
02776 
02777     /* Determine which Control register controls this address */
02778 
02779 #ifndef APS_BSP
02780     if ((VME_LM_MSTR_SIZE != 0) && ((UINT32)adrs >= VME_LM_MSTR_BUS) &&
02781         ((UINT32)adrs <= (VME_LM_MSTR_BUS + VME_LM_MSTR_SIZE)))
02782         lsiCtlReg = (UINT32)(UNIVERSE_LSI0_CTL);
02783     else
02784 #endif /* APS_BSP */
02785     if ((VME_A32_MSTR_SIZE != 0) && ((UINT32)adrs >= VME_A32_MSTR_LOCAL) &&
02786              ((UINT32)adrs <= (VME_A32_MSTR_LOCAL + VME_A32_MSTR_SIZE)))
02787         lsiCtlReg = (UINT32)(UNIVERSE_LSI1_CTL);
02788     else if ((VME_A24_MSTR_SIZE != 0) && ((UINT32)adrs >= VME_A24_MSTR_LOCAL) &&
02789              ((UINT32)adrs <= (VME_A24_MSTR_LOCAL + VME_A24_MSTR_SIZE)))
02790         lsiCtlReg = (UINT32)(UNIVERSE_LSI2_CTL);
02791     else if ((VME_A16_MSTR_SIZE != 0) && ((UINT32)adrs >= VME_A16_MSTR_LOCAL) &&
02792              ((UINT32)adrs <= (VME_A16_MSTR_LOCAL + VME_A16_MSTR_SIZE)))
02793         lsiCtlReg = (UINT32)(UNIVERSE_LSI3_CTL);
02794     else
02795         return (ERROR);
02796 
02797     /* If write probe, disable Posted Writes in Universe */
02798 
02799     pciSlv1Ctl = sysPciInLong (lsiCtlReg);
02800     if (mode == VX_WRITE)
02801         {
02802         sysPciOutLong (lsiCtlReg, (pciSlv1Ctl & ~LSI_CTL_WP));
02803         }
02804 
02805     /* Perform probe */
02806 
02807     status = sysMemProbeBus (adrs, mode, length, pVal);
02808 
02809     /* Restore Posted Writes by Universe if previously enabled */
02810 
02811     if ((mode == VX_WRITE) && (pciSlv1Ctl & LSI_CTL_WP))
02812         {
02813         sysPciOutLong (lsiCtlReg, pciSlv1Ctl);
02814         }
02815 
02816     return (status);
02817     }
02818 
02819 
02820 /******************************************************************************
02821 *
02822 * sysPciProbe - probe a PCI bus address
02823 *
02824 * This routine probes an address on the PCI bus.  The PCI bridge chip
02825 * must have a special setup to enable generation of Master Abort cycles on
02826 * write probes and reception of Target Abort cycles on read probes.
02827 * The CPU must be configured to enable Machine Check exceptions.  In 
02828 * addition, if the probe is a write, the Universe must be configured to
02829 * disable Posted Writes.  All probing is done with interrupts disabled.
02830 *
02831 * RETURNS: OK or ERROR if address cannot be probed
02832 */
02833 
02834 #ifndef APS_BSP
02835 STATUS sysPciProbe
02836 #else /* APS_BSP */
02837 LOCAL STATUS sysPciProbe
02838 #endif /* APS_BSP */
02839     (
02840     char   * adrs,      /* address to be probed */
02841     int      mode,      /* VX_READ or VX_WRITE */
02842     int      length,    /* 1, 2 or 4 byte probe */
02843     char   * pVal       /* address of value to write OR */
02844                         /* address of location to place value read */
02845     )
02846     {
02847     STATUS status = ERROR;
02848 
02849     /* Perform probe */
02850 
02851     status = sysMemProbeBus (adrs, mode, length, pVal);
02852 
02853     return (status);
02854     }
02855 
02856 
02857 /******************************************************************************
02858 *
02859 * sysBusProbe - probe a bus address based on bus type.
02860 *
02861 * This routine is a function hook into vxMemProbe.  It determines which bus,
02862 * VME, PCI or local is being probed based on the address to be probed.
02863 * If the VME bus is being probed, the sysVmeProbe() routine is called to do
02864 * the special VME probing.  If the PCI bus is being probed, the sysPciProbe()
02865 * routine is called to do the special PCI probing.  If the local bus is being
02866 * probed, the routine returns ERROR which indicates that the default local
02867 * bus probe in vxMemProbe() should be used.
02868 *
02869 * RETURNS: ERROR if local bus is being probed, OK if VME or PCI bus.
02870 */
02871 
02872 #ifndef APS_BSP
02873 STATUS  sysBusProbe
02874 #else /* APS_BSP */
02875 LOCAL STATUS sysBusProbe
02876 #endif /* APS_BSP */
02877     (
02878     char   * adrs,      /* address to be probed */
02879     int      mode,      /* VX_READ or VX_WRITE */
02880     int      length,    /* 1, 2 or 4 byte probe */
02881     char   * pVal       /* address of value to write OR */
02882                         /* address of location to place value read */
02883     )
02884     {
02885     STATUS status;
02886 
02887     /* Clear any existing errors/exceptions */
02888 
02889     sysProbeErrClr ();
02890 
02891     /* Handle VME bus in special manner */
02892 
02893     if (IS_VME_ADDRESS(adrs))
02894         status = sysVmeProbe (adrs, mode, length, pVal);
02895 
02896     /* Handle PCI bus in special manner */
02897 
02898     else if (IS_PCI_ADDRESS(adrs))
02899         status = sysPciProbe (adrs, mode, length, pVal);
02900 
02901     /* Handle local bus in architecture-specific manner */
02902 
02903     else
02904         status = vxMemArchProbe (adrs, mode, length, pVal);
02905 
02906     /* Clear any errors/exceptions before exiting */
02907 
02908     sysProbeErrClr ();
02909 
02910     return (status);
02911     }
02912 
02913 #ifndef APS_BSP
02914 /******************************************************************************
02915 *
02916 * sysUsDelay - delay at least the specified amount of time (in microseconds)
02917 *
02918 * This routine will delay for at least the specified amount of time using the
02919 * lower 32 bit "word" of the Time Base register as the timer.  The accuracy of
02920 * the delay increases as the requested delay increases due to a certain amount
02921 * of overhead.  As an example, a requested delay of 10 microseconds is
02922 * accurate within approximately twenty percent, and a requested delay of 100
02923 * microseconds is accurate within approximately two percent.
02924 *
02925 * NOTE:  This routine will not relinquish the CPU; it is meant to perform a
02926 * busy loop delay.  The minimum delay that this routine will provide is
02927 * approximately 10 microseconds.  The maximum delay is approximately the
02928 * size of UINT32; however, there is no roll-over compensation for the total
02929 * delay time, so it is necessary to back off two times the system tick rate
02930 * from the maximum.
02931 *
02932 * RETURNS: N/A
02933 */
02934 
02935 
02936 void sysUsDelay
02937     (
02938     UINT32      delay           /* length of time in microsec to delay */
02939     )
02940     {
02941     register UINT baselineTickCount;
02942     register UINT curTickCount;
02943     register UINT terminalTickCount;
02944     register int actualRollover = 0;
02945     register int calcRollover = 0;
02946     UINT ticksToWait;
02947     UINT requestedDelay;
02948     UINT oneUsDelay;
02949 
02950     /* Exit if no delay count */
02951 
02952     if ((requestedDelay = delay) == 0)
02953         return;
02954 
02955     /*
02956      * Get the Time Base Lower register tick count, this will be used
02957      * as the baseline.
02958      */
02959 
02960     baselineTickCount = sysTimeBaseLGet();
02961 
02962     /*
02963      * Calculate number of ticks equal to 1 microsecond
02964      *
02965      * The Time Base register and the Decrementer count at the same rate:
02966      * once per 4 System Bus cycles.
02967      *
02968      * e.g., 66666666 cycles     1 tick      1 second             16 tick
02969      *       ---------------  *  ------   *  --------          =  ----------
02970      *       second              4 cycles    1000000 microsec    microsec
02971      */
02972 
02973     oneUsDelay = ((DEC_CLOCK_FREQ / 4) / 1000000);
02974 
02975     /* Convert delay time into ticks */
02976 
02977     ticksToWait = requestedDelay * oneUsDelay;
02978 
02979     /* Compute when to stop */
02980 
02981     terminalTickCount = baselineTickCount + ticksToWait;
02982 
02983     /* Check for expected rollover */
02984 
02985     if (terminalTickCount < baselineTickCount)
02986         {
02987         calcRollover = 1;
02988         }
02989 
02990     do
02991         {
02992         /*
02993          * Get current Time Base Lower register count.
02994          * The Time Base counts UP from 0 to
02995          * all F's.
02996          */
02997 
02998         curTickCount = sysTimeBaseLGet();
02999 
03000         /* Check for actual rollover */
03001 
03002         if (curTickCount < baselineTickCount)
03003             {
03004             actualRollover = 1;
03005             }
03006 
03007         if (((curTickCount >= terminalTickCount)
03008             && (actualRollover == calcRollover)) ||
03009             ((curTickCount < terminalTickCount)
03010             && (actualRollover > calcRollover)))
03011             {
03012             /* Delay time met */
03013 
03014             break;
03015             }
03016 
03017         }
03018     while (TRUE); /* Breaks when delay time is met */
03019     }
03020 
03021 #endif /* APS_BSP */
03022 /******************************************************************************
03023 *
03024 * sysDebugMsg - print a debug string to the console in polled mode.
03025 *
03026 * This routine prints a message to the system console in polled mode and
03027 * optionally exits to the monitor.
03028 *
03029 * RETURNS: N/A
03030 *
03031 */
03032 
03033 void sysDebugMsg
03034     (
03035     char * str,
03036     UINT32  recovery
03037     )
03038     {
03039     int msgSize;
03040     int msgIx;
03041     SIO_CHAN * pSioChan;        /* serial I/O channel */
03042 
03043     msgSize = strlen (str);
03044 
03045     sysSerialHwInit ();
03046 
03047     pSioChan = sysSerialChanGet (0);
03048 
03049     sioIoctl (pSioChan, SIO_MODE_SET, (void *) SIO_MODE_POLL);
03050 
03051     for (msgIx = 0; msgIx < msgSize; msgIx++)
03052         {
03053         while (sioPollOutput (pSioChan, str[msgIx]) == EAGAIN);
03054         }
03055 
03056     /* follow caller's error recovery policy. */
03057 
03058 #ifdef DEBUGMSG_RECOVERY
03059     if (recovery == EXIT_TO_SYSTEM_MONITOR)
03060         sysToMonitor (BOOT_NO_AUTOBOOT);
03061 #endif
03062     }
03063 
03064 #if defined(INCLUDE_NETWORK)
03065 /*****************************************************************************
03066 * sysDynEnetFind - Find ethernet network device dynamically
03067 *
03068 * This function dynamically finds the ethernet network device.  The
03069 * encoded location is returned the 'pciLoc' output parameter if the
03070 * device is found.  The constraints of the search require that the
03071 * device found be on the PCI bus number which matches the 'bus' input
03072 * parameter.  In addition, if the 'unit' input parameter is zero, the
03073 * device/vendor ID must match the PCI_ID_PRI_LAN define.
03074 *
03075 * RETURNS: OK if ethernet device is found, ERROR otherwise
03076 */
03077 
03078 STATUS sysDynEnetFind
03079     (
03080     int       unit,             /* input: unit number */
03081     UINT      bus,              /* input: bus number on which to look */
03082     PCI_LOC * pciLoc            /* output: encoded location of device */
03083     )
03084     {
03085 
03086     UINT    findClass;
03087     UINT    pciBus;
03088     UINT    pciDevice;
03089     UINT    pciFunc;
03090     UINT    devVend;
03091     UINT    index = 0;
03092     STATUS  status = ERROR;
03093 
03094     findClass = (UINT)((PCI_CLASS_NETWORK_CTLR << 16)  |
03095                       (PCI_SUBCLASS_NET_ETHERNET << 8) |
03096                       (0 << 0) /* Prog I/F = 0 */
03097                       );
03098 
03099     while (pciFindClass(findClass, index,
03100            &pciBus, &pciDevice, &pciFunc) == OK)
03101         {
03102         if (pciBus == bus)
03103             {
03104             pciConfigInLong (pciBus, pciDevice, pciFunc,
03105                              PCI_CFG_VENDOR_ID, &devVend);
03106 
03107             if ( ((unit == 0) && (devVend == PCI_ID_PRI_LAN)) )
03108                 {
03109                 pciLoc->bus = pciBus;
03110                 pciLoc->device = pciDevice;
03111                 pciLoc->function = pciFunc;
03112                 status = OK;
03113                 break;
03114                 }
03115             }
03116         index++;
03117         }
03118     return (status);
03119     }
03120 #endif /* defined(INCLUDE_NETWORK) */
03121 
03122 #if defined(INCLUDE_PCI_AUTOCONF) && !defined(INCLUDE_END)
03123 /*****************************************************************************
03124 *
03125 * sysDynDcAttach - Dynamically attach ethernet driver
03126 *
03127 * This function dynamically attaches the network driver to the actual PCI
03128 * network hardware via a 'dcattach()' function call.  It works in
03129 * conjunction with the two macros: NETIF_USR_DECL and NETIF_USR_ENTRIES
03130 * defined in "config.h".  The presence of these two macros causes
03131 * usrNetIfAttach() to call this function 'sysDynDcAttach()' directly
03132 * instead of calling 'dcattach()' directly.  This function dynamically
03133 * determines the CPU memory address, interrupt vector and interrupt
03134 * level parameters (associated with the dummy arguments: dummmyDevAdrs,
03135 * dummyIvec, dummyIlevel) by using information read from the already
03136 * configured PCI configuration header for this device.  The "unit"
03137 * argument is used to discern between primary ethernet (unit == 0) and
03138 * secondary ethernet (unit == 1).  Only network devices which reside on
03139 * bus 0 are attached.  Also the primary/secondary specification of the
03140 * "unit" parameter causes this function to check the device/vendor field
03141 * of the PCI header.  Primary ethernet must match PCI_ID_PRI_LAN,
03142 * otherwise dcattach() is not called and FALSE is returned.
03143 *
03144 * RETURNS: OK if dcattach() succeeds, ERROR if PCI header not found or
03145 * if dcattach() fails.
03146 */
03147 
03148 STATUS sysDynDcAttach
03149     (
03150     int         unit,           /* unit number */
03151     ULONG       dummmyDevAdrs,  /* LANCE I/O address (dummy) */
03152     int         dummyIvec,      /* interrupt vector (dummy) */
03153     int         dummyIlevel,    /* interrupt level (dummy) */
03154     char *      memAdrs,        /* address of memory pool (-1 = malloc it) */
03155     ULONG       memSize,        /* only used if memory pool is NOT malloc()'d */
03156     int         memWidth,       /* byte-width of data (-1 = any width) */
03157     ULONG       pciMemBase,     /* main memory base as seen from PCI bus */
03158     int         dcOpMode        /* mode of operation */
03159     )
03160     {
03161     IMPORT int dcattach ();
03162 
03163     int     index = 0;
03164     UINT    bar0;
03165     char    *cpuPciAddr;
03166     STATUS  status = ERROR;
03167     UINT    devVend;
03168     int     ivec;
03169     int     ilevel;
03170     UCHAR   intLine;
03171     UINT    pciBus, pciDevice, pciFunc;
03172     PCI_LOC pciList;
03173 
03174     while (sysDynEnetFind ( unit, index, 0, &pciList ) == OK)
03175         {
03176         pciBus = pciList.bus;
03177         pciDevice = pciList.device;
03178         pciFunc = pciList.function;
03179 
03180         pciConfigInLong (pciBus, pciDevice, pciFunc,
03181                          PCI_CFG_VENDOR_ID, &devVend);
03182 
03183         PCI_AUTO_DEBUG_MSG("sysDynDcAttach: found NIC [%d %d %d] dev_vend[0x%08x]\n",
03184                 pciBus, pciDevice, pciFunc, devVend,0,0 );
03185 
03186         if ( (unit == 0) && (devVend == PCI_ID_PRI_LAN) )
03187             {
03188 
03189             /*
03190              * Dynamically compute PCI address to pass to dcattach().
03191              * It is computed from the already configured PCI header
03192              * base address 0.
03193              */
03194 
03195             pciConfigInLong(pciBus, pciDevice, pciFunc,
03196                             PCI_CFG_BASE_ADDRESS_0, &bar0);
03197 
03198             cpuPciAddr = (char *)((bar0 & 0xfffffffe) |
03199                                    ISA_MSTR_IO_LOCAL);
03200 
03201             /*
03202              * Dynamically compute interrupt vector 'ivec' and
03203              * interrupt level 'ilevel' from the already configured
03204              * "interrupt line" field of the PCI config header.
03205              */
03206 
03207             pciConfigInByte (pciBus, pciDevice, pciFunc,
03208                              PCI_CFG_DEV_INT_LINE, &intLine);
03209 
03210             ivec = (int)intLine;
03211             ilevel = (int)intLine;
03212 
03213             /* Do the dcattach() with the dynamiclly computed arguments. */
03214 
03215             PCI_AUTO_DEBUG_MSG("sysDynDcAttach: dc%d addr[0x%08x]\n", 
03216                                index,cpuPciAddr,0,0,0,0);
03217             PCI_AUTO_DEBUG_MSG("                irq[0x%08x], opmode[0x%08x]\n",
03218                                ilevel,dcOpMode,0,0,0,0);
03219 
03220             status = dcattach(index,cpuPciAddr,ivec,ilevel,memAdrs,
03221                               memSize,memWidth,pciMemBase,dcOpMode);
03222 
03223             if (status != OK)
03224                 {
03225                 break;
03226                 PCI_AUTO_DEBUG_MSG("sysDynDcAttach: attach dc%d failed\n",index,0,0,0,0,0 );
03227                 }
03228             }
03229         index++;
03230         }
03231     return(status);
03232     }
03233 #endif /* defined(INCLUDE_PCI_AUTOCONF) && !defined(INCLUDE_END) */
03234 
03235 /******************************************************************************
03236 *
03237 * sysAtuInit - initialize ATU
03238 *
03239 * This function's purpose is to initialize the address translation
03240 * unit for use by the operating system.
03241 *
03242 * RETURNS: Ok always
03243 */
03244 
03245 #ifndef APS_BSP
03246 STATUS sysAtuInit (void)
03247 #else /* APS_BSP */
03248 LOCAL STATUS sysAtuInit (void)
03249 #endif /* APS_BSP */
03250     {
03251     UINT32      value;
03252 
03253     /*
03254      * initialize the inbound translation window and enable it,
03255      * the inbound translation window permits PCI bus masters to access
03256      * system memory, the enable is nothing more than enabling PCI memory
03257      * accesses in host's bridge PCI command configuration register
03258      */
03259     sysPciOutLong( (UINT32)KAHLUA_ATU_ITWR, 0 );
03260 
03261     value = sysPciConfigInLong((UINT32 *)(CNFG_PCI_HOST_BRDG + 0x10));
03262     value = (value & 0x00000FFF) | LOCAL_MEM_LOCAL_ADRS;
03263     sysPciConfigOutLong((UINT32 *)(CNFG_PCI_HOST_BRDG + 0x10), value);
03264 
03265     value = sysPciConfigInWord((UINT16 *)(CNFG_PCI_HOST_BRDG + 0x04));
03266     value |= 0x0002;
03267     sysPciConfigOutWord((UINT16 *)(CNFG_PCI_HOST_BRDG + 0x04), value);
03268  
03269     return (OK);
03270     }
03271 
03272 #ifdef APS_BSP
03273 
03297 STATUS sysA24MapRam(unsigned long size) {
03298     void *a24memAlloc;
03299     
03300     if ((sysProcNumGet() != 0) ||
03301         (a24memPartId != NULL))
03302         return ERROR;
03303     
03304     if (size > 0x800000)
03305         size = 0x800000;                /* Maximum size is 8MB */
03306     else if (size < 0x010000)
03307         size = 0x010000;                /* Minimum size is 64KB */
03308     
03309     a24memAlloc = cacheDmaMalloc(size);
03310     if (a24memAlloc == NULL)
03311         return ERROR;
03312     
03313     a24memPartId = memPartCreate(a24memAlloc, size);
03314     if (a24memPartId == NULL)
03315         {
03316         cacheDmaFree(a24memAlloc);
03317         a24memAlloc = 0;
03318         return ERROR;
03319         }
03320     
03321     /* Got the memory, now set up the Universe chip. */
03322     a24memBase  = 0xffff0000 & (unsigned long) a24memAlloc;
03323     a24memBound = 0xffff0000 & ((unsigned long) a24memAlloc + size + 0x10000);
03324     /* a24vmeBase is the constant VME_A24_SLV_BUS */
03325     a24adrOffset = a24memBase - VME_A24_SLV_BUS;
03326     a24vmeBound  = a24memBound - a24adrOffset;
03327     
03328     UNIV_OUT_LONG(UNIVERSE_VSI2_BS, VME_A24_SLV_BUS);
03329     UNIV_OUT_LONG(UNIVERSE_VSI2_BD, a24vmeBound);
03330     UNIV_OUT_LONG(UNIVERSE_VSI2_TO, a24adrOffset);
03331     UNIV_OUT_LONG(UNIVERSE_VSI2_CTL, VAL_VSI2_CTL);
03332     
03333     return OK;
03334     }
03335 
03336 
03353 void *sysA24Malloc
03354     (
03355     unsigned long size  /* number of bytes to allocate */
03356     )
03357     {
03358     if (a24memPartId == NULL)
03359         {
03360         /* None allocated, get enough for this request */
03361         if (sysA24MapRam(size + MEM_PART_OVERHEAD) != OK)
03362             return NULL;
03363         }
03364     
03365     return(memPartAlloc(a24memPartId, size));
03366     }
03367 
03368 
03369 /*******************************************************************************
03370 *
03371 * sysA24Free - free a block of memory from the A24 partition
03372 *
03373 * This routine returns to the A24 partition a block of memory that was
03374 * previously allocated with sysA24Malloc().
03375 *
03376 * RETURNS: OK, or ERROR if the block is invalid.
03377 *
03378 * SEE ALSO: sysA24MapRam(), sysA24Malloc(), sysA24MemShow()
03379 */
03380 
03381 STATUS sysA24Free
03382     (
03383     char *pBlock        /* pointer to block of memory to free */
03384     )
03385     {
03386     if (a24memPartId == NULL)
03387         return ERROR;
03388     
03389     return(memPartFree(a24memPartId, pBlock));
03390     }
03391 
03392 
03403 void sysA24MemShow(void)
03404     {
03405         if (a24memPartId)
03406             {
03407             memPartShow(a24memPartId, 0);
03408             }
03409         else
03410             puts("\nNo A24 memory currently reserved");
03411     }
03412 
03413 
03427 STATUS sysVmeMapShow(void)
03428     {
03429     unsigned long base, bound, offset, ctl;
03430     
03431     printf("\nVMEbus access from CPU:\n");
03432     UNIV_IN_LONG(UNIVERSE_LSI1_BS, &base);
03433     UNIV_IN_LONG(UNIVERSE_LSI1_BD, &bound);
03434     UNIV_IN_LONG(UNIVERSE_LSI1_TO, &offset);
03435     printf("  CPU:\t0x%8.8lX - 0x%8.8lX  =>  A32: 0x%8.8lX - 0x%8.8lX\n",
03436            base, bound - 1, base + offset, bound + offset - 1);
03437 
03438     UNIV_IN_LONG(UNIVERSE_LSI2_BS, &base);
03439     UNIV_IN_LONG(UNIVERSE_LSI2_BD, &bound);
03440     UNIV_IN_LONG(UNIVERSE_LSI2_TO, &offset);
03441     printf("\t0x%8.8lX - 0x%8.8lX  =>  A24:   0x%6.6lX -   0x%6.6lX\n",
03442            base, bound - 1, (base + offset) & 0xffffff, 
03443            (bound + offset - 1) & 0xffffff);
03444 
03445     UNIV_IN_LONG(UNIVERSE_LSI3_BS, &base);
03446     UNIV_IN_LONG(UNIVERSE_LSI3_BD, &bound);
03447     UNIV_IN_LONG(UNIVERSE_LSI3_TO, &offset);
03448     printf("\t0x%8.8lX - 0x%8.8lX  =>  A16:     0x%4.4lX -     0x%4.4lX\n",
03449            base, bound - 1, (base + offset) & 0xffff, 
03450            (bound + offset - 1) & 0xffff);
03451 
03452     printf("\nCPU access from VMEbus:\n");
03453     UNIV_IN_LONG(UNIVERSE_VSI1_CTL, &ctl);
03454     if (ctl & VSI_CTL_EN)
03455         {
03456         UNIV_IN_LONG(UNIVERSE_VSI1_BS, &base);
03457 #if ((SM_OFF_BOARD == FALSE) && !defined(ANY_BRDS_IN_CHASSIS_NOT_RMW))
03458         UNIV_IN_LONG(UNIVERSE_VSI5_BD, &bound);
03459 #else
03460         UNIV_IN_LONG(UNIVERSE_VSI1_BD, &bound);
03461 #endif
03462         UNIV_IN_LONG(UNIVERSE_VSI1_TO, &offset);
03463         printf("  A32:\t0x%8.8lX - 0x%8.8lX  =>  CPU: 0x%8.8lX - 0x%8.8lX\n",
03464                 base, bound - 1, base + offset, bound + offset - 1);
03465         }
03466     else
03467         printf("  A32:\t           -             =>                  -\n");
03468     
03469     UNIV_IN_LONG(UNIVERSE_VSI2_CTL, &ctl);
03470     if (ctl & VSI_CTL_EN)
03471         {
03472         UNIV_IN_LONG(UNIVERSE_VSI2_BS, &base);
03473         UNIV_IN_LONG(UNIVERSE_VSI2_BD, &bound);
03474         UNIV_IN_LONG(UNIVERSE_VSI2_TO, &offset);
03475         printf("  A24:\t  0x%6.6lX -   0x%6.6lX  =>       0x%8.8lX - 0x%8.8lX\n",
03476                 base, bound - 1, base + offset, bound + offset - 1);
03477         }
03478     
03479     UNIV_IN_LONG(UNIVERSE_VRAI_CTL, &ctl);
03480     if (ctl & VRAI_CTL_EN)
03481         {
03482         UNIV_IN_LONG(UNIVERSE_VRAI_BS, &base);
03483         bound = base + VME_VRAI_SLV_SIZE;
03484         printf("  A24:\t  0x%6.6lX -   0x%6.6lX  =>       Universe-2 Registers\n",
03485                 base, bound - 1);
03486         }
03487     
03488     return OK;
03489     }
03490 #endif /* APS_BSP */
03491 static char identsysLib_c[]="@(#) $Name:  $ $Id: sysLib.c,v 1.4.2.1 2002/09/12 21:45:36 thompson Exp $";

Generated on Tue Sep 17 13:03:01 2002 for MV2100 by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002