sysLib.c
上传用户:yingyi0918
上传日期:2022-06-26
资源大小:214k
文件大小:60k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* sysLib.c - IDT 79PMC438 system-dependent routines */
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * This file has been developed or significantly modified by the
  6.  * MIPS Center of Excellence Dedicated Engineering Staff.
  7.  * This notice is as per the MIPS Center of Excellence Master Partner
  8.  * Agreement, do not remove this notice without checking first with
  9.  * WR/Platforms MIPS Center of Excellence engineering management.
  10.  */
  11. /*
  12. modification history
  13. --------------------
  14. 01a,02jun02,krao    adapted to  79PMC438 board
  15. */
  16. /*
  17. DESCRIPTION
  18. This library provides board-specific routines for the IDT79PMC438 board.
  19. INCLUDE FILES: sysLib.h
  20. SEE ALSO:
  21. .pG "Configuration"
  22. */
  23. /* includes */
  24. #include "vxWorks.h"
  25. #include "vxLib.h"
  26. #include "config.h"
  27. #include "version.h"
  28. #include "arch/mips/cacheMipsLib.h"
  29. #include "arch/mips/ivMips.h"
  30. #include "arch/mips/esfMips.h"
  31. #include "sysLib.h"
  32. #include "string.h"
  33. #include "intLib.h"
  34. #include "logLib.h"
  35. #include "rc32438.h"
  36. #include "sysI2CDrv.h"
  37. #ifdef BROADCOM_BSP
  38. #include "netinet/in.h"     /* for sysBindFix() */
  39. #include "sockLib.h"        /* for sysBindFix() */
  40. #include "symLib.h"
  41. #ifdef INCLUDE_PCI
  42. int sysPCIBridgeProbe(int instance,
  43.       int primary,
  44.       int secondary,
  45.       int subordinate);
  46. #endif
  47. #endif /*!BROADCOM_BSP */
  48. #ifdef INCLUDE_IDT_END
  49. #include "end.h"
  50. #include "netBufLib.h"
  51. #include "idt32438End.h"
  52. #endif
  53. /* externs */
  54. IMPORT void     sys557PciInit (void);
  55. IMPORT void     sysWbFlush ();
  56. IMPORT ULONG    taskSRInit ();
  57. IMPORT void     sysClearTlbEntry ();
  58. IMPORT int      sysCompareSet ();
  59. IMPORT int      sysCompareGet ();
  60. IMPORT int      sysPridGet ();
  61. IMPORT int      sysCountGet ();
  62. IMPORT int      sysCountSet ();
  63. IMPORT int      sysConfig1Get ();
  64. IMPORT void     sysPciBusErrEnable ();
  65. IMPORT void     sysPciBusErrDisable ();
  66. IMPORT void     sysRc32438ClkEnable ();
  67. IMPORT void     sysRc32438ClkDisable ();
  68.  
  69. IMPORT UINT8    ffsMsbTbl[];            /* Msb high interrupt hash table */
  70. IMPORT UINT8    ffsLsbTbl[];            /* Lsb high interrupt hash table */
  71. IMPORT int      printf (const char *, ...);
  72. IMPORT int      isprint (char);
  73. /* cache initialization */
  74. IMPORT STATUS   cache4kcLibInit(CACHE_MODE, CACHE_MODE, 
  75.                                 UINT32, UINT32, UINT32, UINT32);
  76. /*defines */
  77. #define WAIT(x) { volatile int iCount=0; while (++iCount < (x)) ; }
  78. /*
  79.  * Override max # PCI buses to optimize pciFindDevice
  80.  * and PCI auto-config.
  81.  */
  82.  
  83. /* Timer defines */ 
  84. #define TIMER_ENABLE  1
  85. #define TIMER_DISABLE 0
  86. /*typedef */
  87. typedef struct priotable
  88.     {
  89.     ULONG   intCause;       /* cause of interrupt   */
  90.     ULONG   bsrTableOffset; /* index to BSR table   */
  91.     ULONG   statusReg;      /* interrupt level  */
  92.     ULONG   pad;            /* pad for ease of use  */
  93.     } PRIO_TABLE;
  94. /*globals */
  95.  
  96. /*
  97.  * Interrupt demux routine for RC32438 internal devices - This must be
  98.  * defined here even though it's not global. It's used in the
  99.  * intPrioTable below.
  100.  */
  101.  
  102. LOCAL ULONG sysRc32438IntDemux (int arg);
  103. LOCAL ULONG sysRc32438GpioDemux (int arg);
  104. LOCAL BOOL  sysIsPciMapped (ULONG address);
  105. LOCAL void  sysClkInt ();    
  106. LOCAL ULONG sysTimerIsr (int arg); 
  107. /* GLOBAL - Timer handlers */
  108. FUNCPTR sysTimer0Routine             = NULL;
  109. FUNCPTR sysTimer1Routine             = NULL;
  110. FUNCPTR sysTimer2Routine             = NULL;
  111. FUNCPTR sysRefreshTimerRoutine       = NULL;
  112. FUNCPTR sysWatchdogTimerRoutine      = NULL;
  113. FUNCPTR sysUndecodedCPUWriteRoutine  = NULL;
  114. ULONG   sysSoftCompare            = 0;      /* last target compare reg value */
  115. /*
  116.  *       intPrioTable is a board dependant structure that aids in the
  117.  *       processing of the 8 Rc32438 interrupt conditions.
  118.  *       It is used by excLib to determine the pending interrupt and
  119.  *       to call the user attached handler.  The present search algorithm
  120.  *       relies on a one to one mapping of Rc32438 interrupt lines and
  121.  *       table entries. 
  122.  *
  123.  *       Each entry has 4 fields, the first (intCause) is the interrupt ID, 
  124.  *       second (bsrTableOffset) is the vector number, third is unused
  125.  *       last (pad) is the multiplex field.  When an interrupt is received
  126.  *       the handler maps the pending Rc32438 line to  its' corresponding
  127.  *       table entry (ie. Software interrupt 0 would map to the first entry
  128.  *       in the table).  At this point interrupts that are not pending are
  129.  *       enabled.  Next the multiplex field is read, if it is zero, field 
  130.  *       two is taken as the interrupt vector number in the BSR table, 
  131.  *       otherwise it is interpreted as a demultiplex function and called
  132.  *       with field 4 passed as it's parameter.  The job of the demultiplex
  133.  *       routine is to calculate the correct interrupt vector number and pass
  134.  *       it back to the handler.  The handler can then call the routine the
  135.  *       user has installed in the BSR table with intVecSet, or intConnect.
  136.  *
  137.  *       This table is critical to interrupt processing.  Do not alter
  138.  *       it's contents until you understand the consequences.  The routine
  139.  *       sysPrioUpdate can aid modification during runtime.
  140.  */
  141. PRIO_TABLE intPrioTable[8] =
  142.     {
  143.     {CAUSE_SW1,(ULONG) IV_SWTRAP0_VEC,     0x0100, 0},      /* sw trap 0      */
  144.     {CAUSE_SW2,(ULONG) IV_SWTRAP1_VEC,     0x0200, 0},      /* sw trap 1      */
  145.     {CAUSE_IP3,(ULONG) sysTimerIsr,        0x8000, 1},      /* IRQ0           */
  146.     {CAUSE_IP4,(ULONG) INT_VEC_GRP3,       0x0800, 0},      /* IRQ1           */
  147.     {CAUSE_IP5,(ULONG) INT_VEC_GRP4,       0x1000, 0},      /* IRQ2           */
  148.     {CAUSE_IP6,(ULONG) sysRc32438IntDemux, 0x2000, 1},      /* IRQ3           */
  149.     {CAUSE_IP7,(ULONG) sysRc32438GpioDemux,0x4000, 1},      /* IRQ4           */
  150.     {CAUSE_IP8,(ULONG) INT_VEC_GRP7,       0x0400, 0}       /* IRQ5           */
  151.     };
  152. /*
  153.  *  Since tying interrupt lines to the processor is board dependent sysHashOrder
  154.  *  is provided to select the prioritization of interrupt lines.  Setting the
  155.  *  #define INT_PRIO_MSB to TRUE prioritizes interrupts from 7-0, 7 being
  156.  *  highest priority, 0 being lowest.  Setting it to FALSE prioritizes
  157.  *  interrupts from 0-7.  See idt79pmc438.h for the definition of INT_PRIO_MSB.
  158.  */
  159. #if (INT_PRIO_MSB == TRUE)
  160.     UINT8 * sysHashOrder = ffsMsbTbl;   /* interrupt prio., 7 = high 0 = low */
  161. #else   /* INT_PRIO_MSB == TRUE */
  162.     UINT8 * sysHashOrder = ffsLsbTbl;   /* interrupt prio., 0 = high 7 = low */
  163. #endif  /* INT_PRIO_MSB == TRUE */
  164. /*locals */
  165. int sysMemTopDebug = 0;
  166. typedef struct dma_int_vect
  167.     {
  168.     void *  func;   /* pointer to interrupt service routine */
  169.     void *  param;  /* parameter passed to interrupt service routine */
  170.     } DMA_INT_VECT;
  171. LOCAL DMA_INT_VECT  dmaInterruptVectors [MAX_DMA_INTRS];
  172.                                                /* DMA interrupt vector table */
  173. volatile unsigned char *ptr;
  174. #if defined (AUTO_CACHE_DETECT)
  175.     LOCAL int cacheSize[] = { 64, 128, 256, 512, 1024, 2048, 4096, 0 };
  176.     LOCAL int cacheLineSize[] = { 0, 4, 8, 16, 32, 64, 128, 0 };
  177.     LOCAL int cacheAssoc[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  178. #endif
  179. LOCAL BOOL      sysAuxClkRunning        = FALSE; /* aux clock enabled flag    */
  180. LOCAL BOOL      sysAuxClkConnected      = FALSE; /* aux clock connect flag    */
  181. LOCAL int       sysAuxClkTicksPerSecond = 100  ; /* aux timer rate            */
  182. LOCAL int       sysAuxClkArg            = 0    ; /* aux clock int routine arg */
  183. LOCAL FUNCPTR   sysAuxClkRoutine        = NULL ; /* aux clock interpt routine */
  184. /* locals */
  185. LOCAL int   sysClkTicksPerSecond    = 100  ;    /* default sys timer rate     */
  186. LOCAL int   sysClkArg               = 0    ;    /* clock int routine arg      */
  187. LOCAL BOOL  sysClkConnected         = FALSE;    /* sys clock connect flag     */
  188. LOCAL BOOL  sysClkRunning           = FALSE;    /* sys clock enabled flag     */
  189. LOCAL int   sysClkProcessorTicks           ;    /* Rc32364 clock ticks        */
  190. LOCAL FUNCPTR   sysClkRoutine       = NULL ;    /* clock interrupt routine    */
  191. #ifdef  INCLUDE_TIMESTAMP
  192. LOCAL BOOL  sysTimestampRunning     = FALSE;    /* timestamp running flag     */
  193. #endif  /* INCLUDE_TIMESTAMP */ 
  194.  
  195. /*forward declarations */
  196. void           sysDmaIntrVectorSet (int, void (*fptr) (), void *);
  197. void           sysDmaIntrVectorClr (int);
  198. LOCAL   void   sysDmaIntVecTblInit (void);
  199. LOCAL   void   sysDmaIsr (int parm);
  200. LOCAL   void   sysAuxClkInt ();
  201. LOCAL   void   sysDeviceInterruptDisable (void);
  202.  
  203. /* includes (source file) */
  204. #include "sysDelay.c"           /* uSec delay routine */
  205. #include "sysI2CDrv.c"          /* I2C driver */
  206. #include "sysSerial.c"          /* serial driver */
  207. #include "sysMipsLib.c"         /* Mips common routines */
  208. #include "sysIo.c"              /* I/O routines: must be before PCI includes */
  209. #ifdef  INCLUDE_PCI             /* PCI modules */
  210. #define PCI_AUTO_STATIC_LIST 
  211. #include "pci/pciConfigLib.c"
  212. #include "pci/pciIntLib.c"
  213. #include "pci/pciAutoConfigLib.c"
  214. #include "sysPci.c"
  215. #endif  /* INCLUDE_PCI */
  216.  
  217. /*****************************************************************************
  218. *
  219. * sysModel - return the model name of the CPU board
  220. *
  221. * This routine returns the model name of the CPU board.
  222. *
  223. * RETURNS: A pointer to the string "IDT 79PMC438".
  224. */
  225. char *sysModel (void)
  226.     {
  227.     return ("IDT 79PMC438");
  228.     }
  229. /*******************************************************************************
  230. *
  231. * sysCPUSubsystemName - return the text name of the CPU board / system.
  232. *
  233. * This routine returns the model name of either the CPU CPCI board
  234. * or of the embedded-CPU system board.
  235. *
  236. * RETURNS: A pointer to a text string.
  237. */
  238. char cpu_subsystem_name[64] = ""; /* Initially NULL, set to proper text */
  239. char *sysCPUSubsystemName (void)
  240. {
  241.   /* Table of known platforms based on the IDTRC32438 CPU */
  242.   struct revid_s {
  243.     UINT8 revid;
  244.     char *id_text;
  245.   } platform_list[] = {
  246.     /* {rev_id_value, "Text description"} */
  247.     {0x00, "Modular IDT79PMC438"},
  248.     {0x0,  NULL}
  249.   };
  250.   if (!cpu_subsystem_name[0]) {
  251.     /* UINT8 revid=sysBoardRev(); ******* FIX THIS!!! *******/
  252.     UINT8 revid=0; /* Use this until fixed */
  253.     struct revid_s *platform = &platform_list[0];
  254.     while (platform->id_text != NULL) {
  255.       if (revid == platform->revid) {
  256. strcpy(cpu_subsystem_name,platform->id_text);
  257. break;
  258.       }
  259.       platform++;
  260.     }
  261.     if (!cpu_subsystem_name[0])
  262.       sprintf(cpu_subsystem_name,"Unknown IDTRC32438 (REVID=0x%02X)%c",revid,'');
  263.   }
  264.   return cpu_subsystem_name;
  265. }
  266. /****************************************************************************
  267. *
  268. * sysBspRev - return the bsp version with the revision eg 1.1/<x>
  269. *
  270. * This function returns a pointer to a bsp version with the revision.
  271. * for eg. 1.1/<x>. BSP_REV is concatanated to BSP_VERSION to form the
  272. * BSP identification string.
  273. *
  274. * RETURNS: A pointer to the BSP version/revision string.
  275. */
  276. char * sysBspRev (void)
  277.     {
  278.     return (BSP_VERSION BSP_REV);
  279.     }
  280.  
  281. /*****************************************************************************
  282. *
  283. * sysHwInit - initialize the CPU board hardware
  284. *
  285. * This routine initializes various features of the IDT pmc438.
  286. * It is called from usrInit() in usrConfig.c before interrupts
  287. * are enabled.
  288. * This routine initializes and turns off the timers.
  289. *
  290. * NOTE:
  291. * This routine should not be called directly by the user.
  292. * RETURNS: N/A
  293. */
  294. void sysHwInit (void)
  295.     {
  296.     int sr; /*status register */
  297.  
  298.     /* set default task status register for RC32438 */
  299.    
  300.     sr = RC32438_SR;
  301.     taskSRInit (sr);
  302.     /* init status register but leave interrupts disabled */
  303.     
  304.     intSRSet (sr & ~SR_IE);
  305.    
  306.     /* Initialize the I2C Interface */
  307.     
  308.     sysI2CInit (); 
  309.    
  310.     sysDeviceInterruptDisable ();   /* Disable device interrupts  */
  311.    
  312.     sysPciTlbInit();
  313. #ifdef INCLUDE_PCI
  314.     
  315.     sysPciHostBridgeInit ();       /* Configure the RC32438 PCI host bridge */
  316.           
  317.     /* Initialize PCI modules and perform automatic configuration
  318.      * of PCI memory space.
  319.      */
  320.     
  321.     pciConfigLibInit (PCI_MECHANISM_1, PMC438_PCI_CONFIG_ADDR,
  322.                       PMC438_PCI_CONFIG_DATA, NONE);
  323.                    
  324.     pciIntLibInit ();
  325.      
  326.    
  327.      
  328.     sysPciAutoConfig (); 
  329.     
  330.     pciConfigOutLong(0, 0, 0, PCI_CFG_BASE_ADDRESS_0, PCI_TO_CPU_MEM_BASE);
  331.     /* Always probe for bus1: DC-21150/HB4 PCI-PCI bridge */
  332. #ifdef HB_RESET_HACK
  333.     pciConfigOutByte(0,0x14,0,0x41,1); /* Reset the bridge */
  334. #endif
  335.     sysPCIBridgeProbe(0, 0, 1, 1);  
  336.     
  337. #endif /* INCLUDE_PCI */
  338.  
  339.    
  340.     /* Setup the serial device descriptors. */
  341.     
  342.     sysSerialHwInit ();
  343.     sysWbFlush ();                  /* Flush write buffers */
  344.     
  345.     
  346.      
  347.    
  348.     }
  349. /*****************************************************************************
  350. *
  351. * sysHwInit2 - additional system configuration and initialization
  352. *
  353. * This routine connects system interrupts and does any additional
  354. * configuration necessary.
  355. *
  356. * RETURNS: N/A
  357. *
  358. * NOMANUAL
  359. */
  360.   
  361. void sysHwInit2 (void)
  362.     {
  363.     
  364.     int parm = 0; /*temp variable */
  365.     /* connect sys clock and aux clock interrupts */
  366.    
  367.     (void) intConnect (INUM_TO_IVEC(TMR0_INT_NUM), sysClkInt, 0);  
  368.    
  369.     
  370.     /* Initialize DMA interrupts & connect sysDmaIsr */
  371.     
  372.     sysDmaIntVecTblInit ();
  373.    
  374.     intConnect (INUM_TO_IVEC(INT_VEC_GRP3), sysDmaIsr, (int)parm);
  375.     /* connect serial channel interrupts */
  376.  
  377.     sysSerialHwInit2 ();
  378.     
  379.  
  380.     sysWbFlush ();   /* Flush write buffers */
  381.     
  382.     /* Mask the timer and PCI interrupts */
  383.     
  384.     INTERRUPT.i2.imask &= ~INTR_MASK_TIMER0; 
  385.     GPIO.gpioilevel = 0x0;
  386.     GPIO.gpioistat  = 0x0; 
  387. #if 0 
  388.     *(volatile unsigned char *)(0xb060000b)&=((INTR_PCI_ABCD_MASK>>24)&0xFF);
  389.     *(volatile unsigned char *)(0xb0c00023)&=((INTR_PCI_ABCD_MASK>>24)&0xFF);
  390.     *(volatile unsigned char *)(0xb0c00027)&=((INTR_PCI_ABCD_MASK>>24)&0xFF);
  391. #endif
  392.     INTERRUPT.i6.imask &= ~INTR_PCI_ABCD_MASK;
  393.     }
  394.  
  395. /**************************************************************************
  396. *
  397. * sysRc32438IntDemux - Demultiplex the RC32438 interrupt
  398. *
  399. * The RC32438 ORs most of it's internal device interrupts into
  400. * a single interrupt request - INT3.
  401. *
  402. * This routine determines which internal RC32438 device is causing
  403. * the interrupt and returns the appropriate interrupt number so that
  404. * the ISR can be dispatched. It is used in the intPrioTable (above).
  405. *
  406. * NOTE: This routine runs in the interrupt context!
  407. *
  408. * RETURNS: Interrupt number for connected ISR
  409. */
  410. LOCAL ULONG sysRc32438IntDemux
  411.     (
  412.     int arg                     /* Argument from intPrioTable */
  413.     )
  414.     {
  415.     volatile UINT32 intrStatusVal;  /* Value of master interrupt pend reg */
  416.  
  417.  
  418.     intrStatusVal = INTERRUPT.i5.ipend; 
  419.  
  420.     if (intrStatusVal & UART1_GENERAL_INTR_MASK)
  421.         {
  422.         return COM2_INT_NUM;
  423.         }
  424.     else if (intrStatusVal & UART0_GENERAL_INTR_MASK)
  425.         {
  426.         return COM1_INT_NUM;
  427.         }
  428.     else if (intrStatusVal & INTR_MASK_ETH0_OVR ) 
  429.         {
  430.         return ETH_OVR_NUM0;
  431.         }
  432.     else if (intrStatusVal & INTR_MASK_ETH1_OVR ) 
  433.         {
  434.         return ETH_OVR_NUM1;
  435.         }
  436.     else
  437.         {
  438.         return HIGH_VEC;
  439.         }
  440.     }
  441. /**************************************************************************
  442. *
  443. * sysRc32438GpioDemux - Demultiplex the RC32438 GPIO interrupts
  444. *
  445. *  
  446. *
  447. * This routine determines which GPIO pin of RC32438  is causing
  448. * the interrupt and returns the appropriate interrupt number so that
  449. * the ISR can be dispatched. It is used in the intPrioTable (above).
  450. *
  451. * NOTE: This routine runs in the interrupt context!
  452. *
  453. * RETURNS: Interrupt number for connected ISR
  454. */
  455. LOCAL ULONG sysRc32438GpioDemux
  456.     (
  457.     int arg    /* Argument from intPrioTable */
  458.     )
  459.     {
  460.     volatile UINT32 intrStatusVal;   /* Value of master interrupt pend reg */
  461.      
  462.     intrStatusVal = INTERRUPT.i6.ipend;  
  463.     GPIO.gpioistat  = 0;
  464.     if (intrStatusVal & INTR_PCI_ABCD_MASK)
  465.         {
  466.         return INT_NUM_PCI_ABCD; 
  467.         }
  468.     else
  469.         {
  470.         return HIGH_VEC;
  471.         }
  472.     }    
  473. /***************************************************************************
  474. *
  475. * sysDeviceInterruptDisable - Disable device interrupts
  476. *
  477. * This routine disables devices interrupts. It is done as a safeguard
  478. * during cold boots, but is required on a warm boot.
  479. *
  480. * RETURNS: N/A
  481. *
  482. */
  483. LOCAL void sysDeviceInterruptDisable (void)
  484.     {
  485.   
  486.     volatile UINT32* auxTimerIMsk  = (UINT32*)(AUX_TIMER_INTR_MASK);
  487.  
  488.     /* Clear Ethernet Interface  */
  489.     sysOutLong(ETH_INTFC0,0);
  490.     sysOutLong(ETH_INTFC1,0);
  491.     
  492.     /* Clear DMA Controller Registers for ETH0 */
  493.    
  494.     sysOutLong (DMA2C,0);
  495.     sysOutLong (DMA3C,0);
  496.     sysOutLong (DMA2S,0);
  497.     sysOutLong (DMA3S,0);
  498.     sysOutLong (DMA2DPTR,0);
  499.     sysOutLong (DMA3DPTR,0);
  500.     sysOutLong (DMA2NDPTR,0);
  501.     sysOutLong (DMA3NDPTR,0);
  502.     sysOutLong (DMA4C,0);
  503.     sysOutLong (DMA5C,0);
  504.     sysOutLong (DMA4S,0);
  505.     sysOutLong (DMA5S,0);
  506.     sysOutLong (DMA4DPTR,0);
  507.     sysOutLong (DMA5DPTR,0);
  508.     sysOutLong (DMA4NDPTR,0);
  509.     sysOutLong (DMA5NDPTR,0);
  510.     
  511.     
  512.     /* Mask and clear RC32438 UART interrupts */
  513.     
  514.     INTERRUPT.i5.imask |= 0xFC000 ; 
  515.     /*Mask and clear Aux Timer interrupts */
  516.     
  517.     *auxTimerIMsk = (UINT32)0xffffffff; 
  518.     
  519.     /* Mask and clear RC32438 timer interrupts */
  520.     
  521.     TIMER.ct0.ctc = ( TIMER.ct0.ctc & ~0x20 ) ;
  522.     INTERRUPT.i2.imask |= 0x1F ;
  523.     
  524.     INTERRUPT.i6.imask |= 0xffffffff;
  525.     GPIO.gpioilevel = 0x0;
  526.     GPIO.gpioistat  = 0x0; 
  527.     }
  528. /*****************************************************************************
  529. *
  530. * sysPhysMemTop - get the address of the top of memory
  531. *
  532. * This routine returns the address of the first missing byte of memory, which
  533. * indicates the top of memory.
  534. *
  535. * NOTE: Do not adjust LOCAL_MEM_SIZE to reserve memory for application
  536. * use.  See sysMemTop() for more information on reserving memory.
  537. *
  538. * RETURNS: The address of the top of memory.
  539. */
  540. char *sysPhysMemTop (void)
  541.     {
  542.   
  543.     static char * memTop = NULL; /* Returned pointer to top of memory */
  544.  
  545.     if (memTop == NULL)
  546.         {
  547.         memTop = (char *)(LOCAL_MEM_LOCAL_ADRS + LOCAL_MEM_SIZE);
  548.         }
  549.     return (memTop);
  550.     }
  551. /*****************************************************************************
  552. *
  553. * sysMemTop - get the address of the top of logical memory
  554. *
  555. * This routine returns the address of the first unusable byte of memory.
  556. * VxWorks will not use any memory at or above this address.
  557. *
  558. * The user can reserve local memory from the board by declaring the
  559. * macro USER_RESERVED_MEM with the amount of memory to reserve. This
  560. * routine will return a pointer to the first byte of the reserved memory
  561. * area.
  562. *
  563. * RETURNS: The address of the top of usable memory.
  564. */
  565. char *sysMemTop (void)
  566.     {
  567.     static char * memTop = NULL; /* Returned pointer to top of memory */
  568.   
  569.     if (memTop == NULL)
  570.         {
  571.         memTop = sysPhysMemTop () - USER_RESERVED_MEM;
  572.         }
  573.     return (memTop);
  574.     }
  575. #ifndef BROADCOM_BSP
  576. /*****************************************************************************
  577. *
  578. * sysToMonitor - transfer control to the ROM monitor
  579. *
  580. * This routine transfers control to the ROM monitor.  Normally, it is called
  581. * only by reboot()--which services ^X--and bus errors at interrupt level.
  582. * However, in some circumstances, the user may wish to introduce a
  583. * <startType> to enable special boot ROM facilities.
  584. *
  585. * RETURNS: Does not return.
  586. */
  587. STATUS sysToMonitor
  588.     (
  589.     int startType    /* parameter passed to ROM to tell it how to boot */
  590.     )
  591.     {
  592.   
  593.     FUNCPTR pRom = (FUNCPTR) (ROM_TEXT_ADRS + 8);
  594.     sysWbFlush ();   /* Flush write buffers */
  595.     (*pRom) (startType);
  596.     return (OK);    /* in case we ever continue from rom monitor */
  597.     }
  598. #endif /*BROADCOM_BSP */
  599. /*****************************************************************************
  600. *
  601. * sysAutoAck - acknowledge the RC32438 interrupt condition 
  602. *
  603. * This routine acknowledges an RC32438 interrupt for a specified interrupt
  604. * vector.
  605. *
  606. * NOTE:
  607. * This routine must be provided on all RC32438 board support packages.
  608. * Most interrupts are automatically acknowledged in the interrupt service
  609. * routine.
  610. *
  611. * RETURNS: The result of the interrupt acknowledge cycle.
  612. */
  613. int sysAutoAck
  614.     (
  615.     int vecNum              /* vector num of interrupt that bugs us */
  616.     )
  617.     {
  618.     int result = OK;        /* Returned status */
  619.   
  620.     switch (vecNum)
  621.         {
  622.         case IV_TIMER_VEC:
  623.             sysCompareSet (0);
  624.             break;
  625.         case IV_SWTRAP0_VEC:        /* software trap 0 */
  626.             result = sysSw0Ack ();
  627.             break;
  628.         case IV_SWTRAP1_VEC:        /* software trap 1 */
  629.             result = sysSw1Ack ();
  630.             break;
  631.         default:
  632.             result = ERROR;
  633.             break;
  634.         }
  635.     sysWbFlush ();                  /* Flush write buffers */
  636.     return (result);
  637.     }
  638. /*****************************************************************************
  639. *
  640. * sysClkEnable - turn on system clock interrupts
  641. *
  642. * This routine enables system clock interrupts.
  643. *
  644. * RETURNS: N/A
  645. *
  646. * SEE ALSO: sysClkDisable(), sysClkRateSet()
  647. */
  648. void sysClkEnable (void)
  649.     {
  650.     /* start the timer */
  651.     int key;
  652.     volatile UINT32* tmr0ctrl      = (UINT32*)(CNTR_TMR0_CTRLREG);
  653.      
  654.     sysClkProcessorTicks = CPU_CLOCK_RATE /sysClkTicksPerSecond ;
  655.     key = intLock ();
  656.     sysCompareSet (0);
  657.     sysCountSet (1);
  658.     sysCompareSet (sysClkProcessorTicks);
  659.     
  660.     sysSoftCompare = sysClkProcessorTicks;
  661.     sysClkRunning = TRUE;  
  662.     *tmr0ctrl = (UINT32)TIMER_ENABLE ;
  663.     intUnlock (key);
  664.     }
  665. /*****************************************************************************
  666. *
  667. * sysClkRateGet - get the system clock rate
  668. *
  669. * This routine returns the interrupt rate of the system clock.
  670. *
  671. * RETURNS: The number of ticks per second of the system clock.
  672. *
  673. * SEE ALSO: sysClkRateSet()
  674. */
  675. int sysClkRateGet (void)
  676.     {
  677.     return (sysClkTicksPerSecond);
  678.     }
  679. /*****************************************************************************
  680. *
  681. * sysClkRateSet - set the system clock rate
  682. *
  683. * This routine sets the interrupt rate of the system clock.  It does not
  684. * enable system clock interrupts.  Normally, it is called by usrRoot() in
  685. * usrConfig.c.
  686. *
  687. * NOTE
  688. * The RC32364 internal timer is used to provide the system clock.
  689. *
  690. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be
  691. * set.
  692. *
  693. * SEE ALSO: sysClkDisable(), sysClkEnable(), sysClkRateGet()
  694. */
  695. STATUS sysClkRateSet
  696.     (
  697.     int ticksPerSecond  /* number of clock interrupts per second */
  698.     )
  699.     {
  700.     if (ticksPerSecond < SYS_CLK_RATE_MIN || ticksPerSecond > SYS_CLK_RATE_MAX)
  701.         return (ERROR);
  702.     sysClkTicksPerSecond = ticksPerSecond;
  703.     if (sysClkRunning)
  704.         {
  705.         sysClkDisable ();
  706.         sysClkEnable ();
  707.         }
  708.     return (OK);
  709.     }
  710. /*****************************************************************************
  711. *
  712. * sysClkInt - handle a system clock interrupt
  713. *
  714. * This routine handles a system clock interrupt.  It increments the value 
  715. * on the front panel display and calls the routine installed by
  716. * sysClkConnect().
  717. *
  718. * RETURNS: N/A
  719. */
  720. LOCAL void sysClkInt (void)
  721.     {
  722.     
  723.     volatile unsigned int *ptr;
  724.     ptr = (unsigned int *) CNTR_TMR0_CTRLREG;
  725.     TIMER.ct0.ctc = 0;
  726.  
  727.     sysCountSet(0);
  728.    
  729.     sysCompareSet(CPU_CLOCK_RATE /sysClkTicksPerSecond);
  730.   
  731.     *ptr = 0x1;
  732.     
  733. #if defined(PCI_INTA_HACK)
  734.      SOC_INTR_INVOKE();
  735. #endif
  736.      if (sysClkRoutine != NULL)
  737.         (*sysClkRoutine) (sysClkArg);
  738.  
  739.     }
  740. /*****************************************************************************
  741. *
  742. * sysClkConnect - connect a routine to the system clock interrupt
  743. *
  744. * This routine specifies the interrupt handler to be called at each system
  745. * clock interrupt.  It does not enable system clock interrupts.  Normally,
  746. * it is called from usrRoot() in usrConfig.c to connect usrClock() to the
  747. * system clock interrupt.  Other standard interrupt handlers are also set up
  748. * at this time.
  749. *
  750. * RETURN: OK, or ERROR if the routine cannot be connected to the interrupt.
  751. *
  752. * SEE ALSO: intConnect(), usrClock()
  753. */
  754. STATUS sysClkConnect
  755.     (
  756.     FUNCPTR routine,    /* routine called at each system clock interrupt */
  757.     int arg             /* argument with which to call routine           */
  758.     )
  759.     {
  760.     if (sysClkConnected == FALSE)
  761.         {
  762.         sysHwInit2 ();
  763.         sysClkConnected = TRUE;
  764.         }
  765.     sysClkRoutine   = routine;
  766.     sysClkArg       = arg;
  767.     return (OK);
  768.     }
  769. /*****************************************************************************
  770. *
  771. * sysClkDisable - turn off system clock interrupts
  772. *
  773. * This routine disables system clock interrupts.
  774. *
  775. * RETURNS: N/A
  776. *
  777. * SEE ALSO: sysClkEnable(), sysClkRateSet()
  778. */
  779. void sysClkDisable (void)
  780.     {
  781.     int key;
  782.     volatile UINT32* tmr0ctrl      = (UINT32*)(CNTR_TMR0_CTRLREG);
  783.   
  784.     /* we cannot disable interrupts so we do this instead... */
  785.     key = intLock ();
  786.     sysCompareSet (0);
  787.     sysCountSet (1);
  788.     sysClkProcessorTicks = CPU_CLOCK_RATE /sysClkTicksPerSecond;
  789.     sysCompareSet (sysClkProcessorTicks);
  790.     sysSoftCompare = sysClkProcessorTicks;
  791.     sysClkRunning = FALSE;
  792.     *tmr0ctrl = (UINT32)TIMER_DISABLE; 
  793.     intUnlock (key);
  794.     }
  795. /*****************************************************************************
  796. *
  797. * sysAuxClkInt - interrupt level processing for auxiliary clock
  798. *
  799. * This routine handles the auxiliary clock interrupt.  It is attached to the
  800. * clock interrupt vector by the routine sysAuxClkConnect().
  801. * The appropriate routine is called and the interrupt is acknowleged.
  802. *
  803. * RETURNS: N/A
  804. */
  805. LOCAL void sysAuxClkInt (void)
  806.     {
  807.      
  808.     if (sysAuxClkRoutine != NULL)
  809.         (*sysAuxClkRoutine) (sysAuxClkArg); /*call system clock routine */ 
  810.  
  811.     /* Mask and clear RC32438 timer interrupts */
  812.     
  813.     TIMER.ct1.ctc = ( TIMER.ct1.ctc & ~0x20 ) ;
  814.  
  815.     sysWbFlush ();                          /* Flush write buffers */   
  816.     
  817.     }
  818. /*****************************************************************************
  819. *
  820. * sysAuxClkConnect - connect a routine to the auxiliary clock interrupt
  821. *
  822. * This routine specifies the interrupt service routine to be called at each
  823. * auxiliary clock interrupt.  It does not enable auxiliary clock
  824. * interrupts.
  825. *
  826. * RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.
  827. *
  828. * SEE ALSO: intConnect(), sysAuxClkEnable()
  829. */
  830. STATUS sysAuxClkConnect
  831.     (
  832.     FUNCPTR routine,    /*routine called at each aux clock interrupt   */    
  833.     int     arg         /*argument to auxiliary clock interrupt routine*/ 
  834.     )
  835.     {
  836.     if (!sysAuxClkConnected)
  837.         {
  838.         sysAuxClkConnected = TRUE;
  839.         }
  840.     sysAuxClkRoutine = routine;
  841.     sysAuxClkArg = arg;
  842.     return (OK);
  843.     }
  844. /*****************************************************************************
  845. *
  846. * sysAuxClkDisable - turn off auxiliary clock interrupts
  847. *
  848. * This routine disables auxiliary clock interrupts.
  849. *
  850. * RETURNS: N/A
  851. *
  852. * SEE ALSO: sysAuxClkEnable()
  853. */
  854. void sysAuxClkDisable (void)
  855.     {
  856.     sysRc32438ClkDisable ();
  857.     sysAuxClkRunning = FALSE ;
  858.     }
  859. /*****************************************************************************
  860. *
  861. * sysAuxClkEnable - turn on auxiliary clock interrupts
  862. *
  863. * This routine enables auxiliary clock interrupts.
  864. *
  865. * RETURNS: N/A
  866. *
  867. * SEE ALSO: sysAuxClkConnect(), sysAuxClkDisable(), sysAuxClkRateSet()
  868. */
  869. void sysAuxClkEnable (void)
  870.     {
  871.     sysTimer1Routine = (FUNCPTR) sysAuxClkInt;
  872.     sysRc32438ClkEnable (sysAuxClkTicksPerSecond);
  873.     sysAuxClkRunning = TRUE ;
  874.     }
  875. /****************************************************************************
  876. *
  877. * sysAuxClkRateGet - get the auxiliary clock rate
  878. *
  879. * This routine returns the interrupt rate of the auxiliary clock.
  880. *
  881. * RETURNS: The number of ticks per second of the auxiliary clock.
  882. *
  883. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateSet()
  884. */
  885. int sysAuxClkRateGet (void)
  886.     {
  887.     return (sysAuxClkTicksPerSecond);
  888.     }
  889. /*******************************************************************************
  890. *
  891. * sysAuxClkRateSet - set the auxiliary clock rate
  892. *
  893. * This routine sets the interrupt rate of the auxiliary clock.
  894. * It does not enable auxiliary clock interrupts.
  895. *
  896. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be set.
  897. *
  898. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateGet()
  899. */
  900. STATUS sysAuxClkRateSet
  901.     (
  902.     int ticksPerSecond     /* number of clock interrupts per second*/ 
  903.     )
  904.     {
  905.     if ( ticksPerSecond < AUX_CLK_RATE_MIN || ticksPerSecond > AUX_CLK_RATE_MAX)
  906.         {
  907.         return (ERROR);
  908.         }
  909.     sysAuxClkTicksPerSecond = ticksPerSecond ;
  910.      
  911.     if ( sysAuxClkRunning )
  912.         {
  913.         sysAuxClkDisable ();
  914.         sysAuxClkEnable ();
  915.         }
  916.         
  917.     return (OK);
  918.     }
  919. /***************************************************************************
  920. *
  921. * sysCacheInit - initialize the RC32438 cache library
  922. *
  923. * Initializes the generic cache library to work with the IDTPMC438.
  924. *
  925. * RETURNS: OK or ERROR
  926. *
  927. * NOMANUAL
  928. */
  929.  
  930. LOCAL STATUS sysCacheInit
  931.     (
  932.     CACHE_MODE instMode,
  933.     CACHE_MODE dataMode
  934.     )
  935.     {
  936. #if defined (AUTO_CACHE_DETECT)
  937.     UINT32 config1 = sysConfig1Get();
  938.     int iCacheSize;
  939.     int iCacheLineSize;
  940.     int iCacheAssoc;
  941.     int dCacheSize;
  942.     int dCacheLineSize;
  943.     int dCacheAssoc;
  944.     
  945.     iCacheSize =
  946.     cacheSize[((config1 & IDT32438_CONFIG1_IS_MSK) >> IDT32438_CONFIG1_IS_SHF)];
  947.    
  948.     iCacheLineSize =
  949.     cacheLineSize[((config1 & IDT32438_CONFIG1_IL_MSK) 
  950.                  >> IDT32438_CONFIG1_IL_SHF)];
  951.    
  952.     iCacheAssoc =
  953.     cacheAssoc[((config1 & IDT32438_CONFIG1_IA_MSK) 
  954.               >> IDT32438_CONFIG1_IA_SHF)];
  955.    
  956.     iCacheSize *= (iCacheLineSize * iCacheAssoc);
  957.     dCacheSize =
  958.     cacheSize[((config1 & IDT32438_CONFIG1_DS_MSK) 
  959.              >> IDT32438_CONFIG1_DS_SHF)];
  960.    
  961.     dCacheLineSize =
  962.     cacheLineSize[((config1 & IDT32438_CONFIG1_DL_MSK)
  963.                  >> IDT32438_CONFIG1_DL_SHF)];
  964.    
  965.     dCacheAssoc =
  966.     cacheAssoc[((config1 & IDT32438_CONFIG1_DA_MSK) 
  967.               >> IDT32438_CONFIG1_DA_SHF)];
  968.    
  969.     dCacheSize *= (dCacheLineSize * dCacheAssoc);
  970.     return cache4kcLibInit(
  971.         instMode,       /* I-cache mode */
  972.         dataMode,       /* D-cache mode */
  973.         iCacheSize,
  974.         iCacheLineSize,
  975.         dCacheSize,
  976.         dCacheLineSize
  977.         );
  978. #else
  979.     return cache4kcLibInit(
  980.         instMode,       /* I-cache mode */
  981.         dataMode,       /* D-cache mode */
  982.         iCacheSize,
  983.         iCacheLineSize,
  984.         dCacheSize,
  985.         dCacheLineSize
  986.         );
  987. #endif
  988.     }
  989.     
  990. /******************************************************************************
  991. *
  992. * sysNvRamGet - get the contents of non-volatile RAM
  993. *
  994. * This routine copies the contents of non-volatile memory into a specified
  995. * string.  The string will be terminated with an EOS.
  996. *
  997. * RETURNS: OK, or ERROR if access is outside the non-volatile RAM range.
  998. *
  999. * SEE ALSO: sysNvRamSet()
  1000. */
  1001. STATUS sysNvRamGet
  1002.     (
  1003.     char *string,    /* where to copy non-volatile RAM           */
  1004.     int  strLen,     /* maximum number of bytes to copy          */
  1005.     int  offset      /* byte offset into non-volatile RAM        */
  1006.     )
  1007.     {
  1008.     int key;                    /* Saved status register for int lock */
  1009.     offset += NV_BOOT_OFFSET;   /* boot line begins at <offset> = 0 */
  1010.     if ((offset < 0) || (strLen < 0) || ((offset + strLen) > NV_RAM_SIZE))
  1011.         return (ERROR);
  1012.     /* Exclude preemption */
  1013.     key = intLock ();
  1014.     sysI2CStringRead (I2C_READ_WRITE_ADRS + offset, string, strLen);
  1015.     string [strLen] = EOS;
  1016.     intUnlock (key);
  1017.     return (OK);
  1018.     }
  1019. /*******************************************************************************
  1020. *
  1021. *
  1022. * sysNvRamSet - write to non-volatile RAM
  1023. *
  1024. * This routine copies a specified string into non-volatile RAM.
  1025. *
  1026. * RETURNS: OK, or ERROR if access is outside the non-volatile RAM range.
  1027. *
  1028. * SEE ALSO: sysNvRamGet()
  1029. */
  1030. STATUS sysNvRamSet
  1031.     (
  1032.     char * string,       /* string to be copied into non-volatile RAM */
  1033.     int    strLen,       /* maximum number of bytes to copy           */
  1034.     int    offset        /* byte offset into non-volatile RAM         */
  1035.     )
  1036.     {
  1037.     int key;                    /* Saved status register for int lock */
  1038.     offset += NV_BOOT_OFFSET;   /* Boot line begins at <offset> = 0 */
  1039.     if ((offset < 0) || (strLen < 0) || ((offset + strLen) > NV_RAM_SIZE))
  1040.         return (ERROR);
  1041.     /* Exclude preemption */
  1042.     key = intLock ();
  1043.     sysI2CStringWrite ((I2C_READ_WRITE_ADRS + offset), string, strLen);
  1044.     /* Allow preemption */
  1045.     intUnlock (key);
  1046.     return (OK);
  1047.     }
  1048.  
  1049. /******************************************************************
  1050. * sysDmaIntVecTblInit - Initialize the DMA interrupt vector table.
  1051. * Initialize the DMA interrupt vector table.
  1052. *
  1053. * RETURNS N/A
  1054. */
  1055. LOCAL void sysDmaIntVecTblInit ()
  1056.     {
  1057.     int     vect; /* interrupt vector */
  1058.     for (vect = 0; vect < MAX_DMA_INTRS; vect++)
  1059.         {
  1060.         dmaInterruptVectors[vect].func = (void *)0;
  1061.         dmaInterruptVectors[vect].param = (void *)0;
  1062.         }
  1063.     }
  1064. /*****************************************************************************
  1065. *
  1066. * sysDmaIntEnable - enable interrupts for a DMA channel
  1067. * This function enables DMA interrupts at the RC32438 interrupt
  1068. * controller for a single DMA channel. It does not alter the system
  1069. * status register mask or any DMA device registers.
  1070. *
  1071. * RETURNS: N/A
  1072. */
  1073. void sysDmaIntEnable
  1074.     (
  1075.     unsigned int   dmaChan  /* DMA channel number (0-15) */
  1076.     )
  1077.     {
  1078.     if (dmaChan < MAX_DMA_INTRS)
  1079.         INTERRUPT.i3.imask &= ~(1 << dmaChan);
  1080.     return;
  1081.     
  1082.     }
  1083. /******************************************************************
  1084. *
  1085. * sysDmaIntDisable - disable interrupts for a DMA channel
  1086. * This function disables DMA interrupts at the RC32438 interrupt
  1087. * controller for a single DMA channel. It does not alter the system
  1088. * status register mask or any DMA device registers.
  1089. *
  1090. * RETURNS: N/A
  1091. */
  1092. void sysDmaIntDisable
  1093.     (
  1094.     unsigned int    dmaChan  /* DMA channel number (0-15) */
  1095.     )
  1096.     {
  1097.     if (dmaChan < MAX_DMA_INTRS)
  1098.         INTERRUPT.i3.imask |= (1 << dmaChan);
  1099.     return;
  1100.     
  1101.     }
  1102. /******************************************************************
  1103. * sysDmaIntrVectorClr - Clear a DMA interrupt vector
  1104. * Clear the DMA interrupt vector table entry for this vector.
  1105. *
  1106. * RETURNS: N/A
  1107. */
  1108. void sysDmaIntrVectorClr
  1109.     (
  1110.     int         vect        /* interrupt vector */
  1111.     )
  1112.     {
  1113.     if (vect < 0 || vect >= MAX_DMA_INTRS)
  1114.         return;
  1115.     dmaInterruptVectors[vect].func = (void *) NULL;
  1116.     dmaInterruptVectors[vect].param = NULL;
  1117.     }
  1118. /******************************************************************
  1119. * sysDmaIntrVectorSet - Set a DMA interrupt vector
  1120. * Set the DMA interrupt vector table entry to the handler routine.
  1121. *
  1122. * RETURNS: N/A
  1123. */
  1124. void sysDmaIntrVectorSet
  1125.     (
  1126.     int         vect,       /* interrupt vector */
  1127.     void (*fptr) (),        /* function pointer */
  1128.     void *      param       /* parameter to be passed to the function */
  1129.     )
  1130.     {
  1131.     if (vect < 0 || vect >= MAX_DMA_INTRS)
  1132.         return;
  1133.     dmaInterruptVectors[vect].func = (void *) fptr;
  1134.     dmaInterruptVectors[vect].param = param;
  1135.     }
  1136. /******************************************************************
  1137. * sysDmaIsr - DMA interrupt service routine
  1138. * RC32438 has 12 DMA channels that share same interrupt line.  The DMA
  1139. * interrupt service routine demultiplexes this interrupt for the all
  1140. * the dma channels. The device driver using a dma channel, initializes
  1141. * a global list ( having maximum of 12 entries : dma channel 0 through
  1142. * 11) which is referenced by the dmaIsr function to call the
  1143. * appropriate interrupt handlers.
  1144. *
  1145. * RETURNS: N/A
  1146. */
  1147. LOCAL void sysDmaIsr
  1148.     (
  1149.     int parm                       /* parameter value */
  1150.     )
  1151.     {
  1152.     int         vect;       /* index into DMA interrupt vector array */
  1153.     UINT32      iPend;      /* interrupt pending register value */ 
  1154.     UINT32      mask;       /* bit mask */
  1155.     unsigned    (*func) ();
  1156.     /* Read the IPEND3 register */
  1157.    
  1158.     iPend = INTERRUPT.i3.ipend;
  1159.     mask = 1;
  1160.     for (vect = 0; (iPend != 0) && (vect < MAX_DMA_INTRS); vect++)
  1161.         {
  1162.         if (iPend & mask)
  1163.             {
  1164.             func = ((unsigned (*) ()) dmaInterruptVectors[vect].func);
  1165.             if (func != NULL)
  1166.                 {
  1167.                 (* func) (vect, dmaInterruptVectors[vect].param);
  1168.                 }
  1169.                 else
  1170.                 {
  1171.                 (void)logMsg("Uninit DMA int: %dn", vect, 2, 3, 4, 5, 6);
  1172.                 INTERRUPT.i3.imask |= mask;
  1173.                 }
  1174.             iPend &= ~mask;
  1175.             }
  1176.         mask = mask << 1;
  1177.         }
  1178.     }
  1179. /****************************************************************************
  1180. * FUNCTION : sysTimerIsr
  1181. *
  1182. * RC32438 has 5 timers that share same interrupt line.
  1183. * The timer interrupt service routine demultiplexes this interrupt for
  1184. * all the  timers. The timerIsr function calls the
  1185. * appropriate interrupt handlers. In order to maintain equal opportunity
  1186. * for all the timers, the timerIsr function services  all the timer 
  1187. * interrupts in an order to ensure fairness to the timer interrupts among
  1188. * the active timers.
  1189. *
  1190. * RETURNS: N/A
  1191. */
  1192. LOCAL ULONG sysTimerIsr
  1193.     (
  1194.     int parm                   /* parameter value */
  1195.     )
  1196.     {
  1197.     UINT32  ipend;             /*interrupt pending reg */
  1198.     UINT32  imask;             /*mask value */ 
  1199.  
  1200.  
  1201.      
  1202.     ipend = INTERRUPT.i2.ipend;
  1203.     imask = INTERRUPT.i2.imask;
  1204.     ipend &= ~imask;
  1205.     if (ipend & CNTR_TMR0_MASK)
  1206.         {
  1207.         return TMR0_INT_NUM;
  1208.         }
  1209.     if (ipend & CNTR_TMR1_MASK)
  1210.         {
  1211.         if (sysTimer1Routine != NULL)
  1212.             (*sysTimer1Routine) ();      
  1213.     TIMER.ct1.ctc &= ~CTC_TO;
  1214.         }
  1215.     if (ipend & CNTR_TMR2_MASK)
  1216.         {
  1217.         if (sysTimer2Routine != NULL)
  1218.             (*sysTimer2Routine) ();     
  1219.         TIMER.ct2.ctc = CTC_EN;
  1220.         }
  1221.     if (ipend & REFRESH_TIMER_MASK)
  1222.         {
  1223.         if (sysRefreshTimerRoutine != NULL)
  1224.             (*sysRefreshTimerRoutine) ();   
  1225.         TIMER.rtc = CTC_EN;
  1226.         }
  1227.     if (ipend & WDOG_TMR_TO_MASK)
  1228.         {
  1229.         if (sysWatchdogTimerRoutine != NULL)
  1230.             (*sysWatchdogTimerRoutine) ();  
  1231.         SYSINTEG.wtc &= ~WTC_TO;
  1232.         SYSINTEG.errcs &= ~ERRCS_WTO;
  1233.         }
  1234.     if (ipend & UNDEC_CPU_WR_MASK)
  1235.         {
  1236.         if (sysUndecodedCPUWriteRoutine!= NULL)
  1237.             (*sysUndecodedCPUWriteRoutine) ();  
  1238.         SYSINTEG.errcs &= ~ERRCS_UCW;
  1239.         }
  1240.      return (OK);
  1241.     }
  1242. /*******************************************************************************
  1243. *
  1244. * sysRc32438ClkEnable - enable the Rc32438 timer0 interrupt
  1245. *
  1246. * This routine enables the Rc32438 timer0 to give a periodic interrupt.
  1247. * The <ticksPerSecond> parameter specifies the number of interrupts to generate
  1248. * per second. 
  1249. *
  1250. *
  1251. * RETURNS: N/A
  1252. *
  1253. * SEE ALSO: sysRc32438ClkDisable()
  1254. *
  1255. * NOMANUAL
  1256. */
  1257. void sysRc32438ClkEnable
  1258.     (
  1259.     int ticksPerSecond   /*interrupt frequency */
  1260.     )
  1261.     {
  1262.     volatile UINT32* rc32438Timer1CntlReg ; /*timer control reg*/
  1263.     volatile UINT32* rc32438Timer1CntReg  ; /*timer count reg */
  1264.     volatile UINT32* rc32438Timer1CmpReg  ; /*timer compare reg */
  1265.     volatile UINT32* rc32438TimerMask     ; /*timer mask reg */
  1266.     volatile UINT32* rc32438TimerPend     ; /*timer pend reg */
  1267.     int      key                          ; /*temp variable */
  1268.     rc32438Timer1CntlReg = (UINT32*)AUX_TIMER_CNTL_REG  ;
  1269.     rc32438Timer1CntReg  = (UINT32*)AUX_TIMER_CNT_REG   ;
  1270.     rc32438Timer1CmpReg  = (UINT32*)AUX_TIMER_CMP_REG   ;
  1271.     rc32438TimerPend     = (UINT32*)AUX_TIMER_INTR_PEND ;
  1272.     rc32438TimerMask     = (UINT32*)AUX_TIMER_INTR_MASK ;
  1273.     key = intLock ();
  1274.     *rc32438Timer1CntlReg = (UINT32)0x0; /* Clear any pending interrupt */
  1275.     *rc32438Timer1CntReg = (UINT32)0x0;  /* Count is made Zero */
  1276.                                          /* Compare=BUSFREQ/ticks PerSecond */
  1277.     *rc32438Timer1CmpReg  = (UINT32)(AUX_CLOCK_FREQ / ticksPerSecond) ;
  1278.     *rc32438Timer1CntlReg = (UINT32)0x0; /* Clear any pending interrupt */
  1279.     *rc32438TimerMask    &= (UINT32)0xfffffffd;
  1280.                                          /* Enable Timer1 Interrupt */
  1281.     *rc32438Timer1CntlReg = (UINT32)0x1; /* Enable the Timer1       */
  1282.     intUnlock (key);
  1283.     }
  1284. /*****************************************************************************
  1285. *
  1286. * sysRc32438ClkDisable - disable the Rc32438 timer1 interrupt
  1287. *
  1288. * This routine disables the Rc32438 timer1 interrupt.
  1289. *
  1290. * RETURNS: N/A
  1291. *
  1292. * SEE ALSO: sysRc32438ClkEnable()
  1293. *
  1294. * NOMANUAL
  1295. */
  1296. void sysRc32438ClkDisable ()
  1297.     {
  1298.     UINT32* rc32438Timer1CntlReg ; /*timer control reg */
  1299.     UINT32* rc32438Timer1CntReg  ; /*timer count reg */
  1300.     UINT32* rc32438Timer1CmpReg  ; /*timer compare reg */
  1301.     UINT32* rc32438TimerMask     ; /*timer mask reg */
  1302.     UINT32* rc32438TimerPend     ; /*timer pend reg */
  1303.     int     key                  ; /*temp variable */
  1304.     rc32438Timer1CntlReg = (UINT32*)AUX_TIMER_CNTL_REG  ;
  1305.     rc32438Timer1CntReg  = (UINT32*)AUX_TIMER_CNT_REG   ;
  1306.     rc32438Timer1CmpReg  = (UINT32*)AUX_TIMER_CMP_REG   ;
  1307.     rc32438TimerPend     = (UINT32*)AUX_TIMER_INTR_PEND ;
  1308.     rc32438TimerMask     = (UINT32*)AUX_TIMER_INTR_MASK ;
  1309.     key = intLock ();
  1310.     *rc32438Timer1CntlReg = (UINT32)0x0;        /* Disable the Timer1 */
  1311.     *rc32438Timer1CntReg  = (UINT32)0x0;        /* Count is made Zero */
  1312.     *rc32438TimerMask     |= (UINT32)0xfffffffE;/* Disable Timer1 Interrupt */
  1313.     intUnlock (key);
  1314.     }
  1315. /**************************************************************************
  1316. *
  1317. * sysEnetReverse - Reverse bytes in ethernet address array
  1318. *
  1319. * This routine reverses the order of bytes in a 6-character array.
  1320. * This utility is required because the boot shell 'N' command and
  1321. * the ethernet driver expect the opposite byte order for ethernet
  1322. * addresses. Given an address 00:11:22:33:44:55, the boot shell
  1323. * expects to see it stored in an array as 55,44,33,22,11,00, but
  1324. * the ethernet driver expects to see it as 00,11,22,33,44,55.
  1325. *
  1326. * RETURNS: N/A
  1327. */
  1328. LOCAL void sysEnetReverse
  1329.     (
  1330.     uchar_t *inpAddr, /* Input address array */
  1331.     uchar_t *revAddr  /* Reversed output array */
  1332.     )
  1333.     {
  1334.     int idx;                    /* loop index */
  1335.     for (idx = 0; idx < ENET_SIZE; idx++)
  1336.         {
  1337.         revAddr[idx] = inpAddr[ENET_SIZE - idx - 1];
  1338.         }
  1339.     }
  1340. /**************************************************************************
  1341. *
  1342. * sysEnetAddrGet - Read ethernet address from NVRAM for boot shell.
  1343. *
  1344. * This routine reads the ethernet address saved in NVRAM and reverses
  1345. * the bytes read before returning the result. This interface
  1346. * accomodates the 'N' command in the boot shell. If an unknown unit
  1347. * number is passed, then an ethernet address of all zeros is returned.
  1348. *
  1349. * RETURNS: N/A
  1350. */
  1351. void sysEnetAddrGet
  1352.     (
  1353.     int unit,                   /* Unit number */
  1354.     uchar_t* retEnetAddr        /* Returned ethernet addr */
  1355.     )
  1356.     {                               
  1357.     uchar_t readEnetAddr [ENET_SIZE + 1]; /* read from NVRAM, natural order */
  1358.     
  1359.     if (unit == IDT_UNIT0)
  1360.         {
  1361.         sysNvRamGet ((char *) readEnetAddr, ENET_SIZE, NV_ENET_OFFSET0);
  1362.         sysEnetReverse (readEnetAddr, retEnetAddr);
  1363.         }
  1364.     else if (unit == IDT_UNIT1)
  1365.         {
  1366.         sysNvRamGet ((char *) readEnetAddr, ENET_SIZE, NV_ENET_OFFSET0);
  1367.         sysEnetReverse (readEnetAddr, retEnetAddr);
  1368.         retEnetAddr[5]= retEnetAddr[5] + 1;
  1369.         }    
  1370.     else
  1371.         {
  1372.         bfill ((char *) retEnetAddr, ENET_SIZE, 0);
  1373.         }
  1374.     }
  1375. /**************************************************************************
  1376. *
  1377. * sysEnetAddrSet - Write ethernet address to NVRAM for boot shell.
  1378. *
  1379. * This routine writes the passed ethernet address to NVRAM. For a
  1380. * given address 00:11:22:33:44:55, the parameter order would be
  1381. * sysEnetAddrSet(00,11,22,33,44,55). This interface accomodates the
  1382. * 'N' command in the boot shell.
  1383. *
  1384. * RETURNS: N/A
  1385. */
  1386. void sysEnetAddrSet
  1387.     (
  1388.      
  1389.     uchar_t    addr0,           /* Address offset 0 - first byte of address */
  1390.     uchar_t    addr1,           /* Address offset 1 */
  1391.     uchar_t    addr2,           /* Address offset 2 */
  1392.     uchar_t    addr3,           /* Address offset 3 */
  1393.     uchar_t    addr4,           /* Address offset 4 */
  1394.     uchar_t    addr5            /* Address offset 5 - last byte of address */
  1395.     )
  1396.     {
  1397.     char enetAddr [ENET_SIZE];
  1398.     enetAddr [0] = addr0;
  1399.     enetAddr [1] = addr1;
  1400.     enetAddr [2] = addr2;
  1401.     enetAddr [3] = addr3;
  1402.     enetAddr [4] = addr4;
  1403.     enetAddr [5] = addr5;
  1404.     
  1405.     
  1406.     sysNvRamSet ((char *) enetAddr, ENET_SIZE, NV_ENET_OFFSET0);
  1407.     
  1408.     }
  1409. /******************************************************************************
  1410. *
  1411. * sysidt32438EnetAddrGet - Retrieve ethernet address for ethernet driver.
  1412. *
  1413. * This routine returns a six-byte ethernet address for a given ethernet unit.
  1414. * The ethernet driver uses this routine to obtain the ethernet address if
  1415. * indicated by a user-flag in the LoadString (above) - or if the reading the
  1416. * ethernet address ROM is unsuccessful.
  1417. *
  1418. * RETURNS: OK
  1419. */
  1420. STATUS sysidt32438EnetAddrGet
  1421.     (
  1422.     int         unit,        /* unit number */
  1423.     char *      enetAddr     /*returned ethernet address */
  1424.     )
  1425.     {
  1426.    
  1427.     sysNvRamGet (enetAddr, ENET_SIZE, NV_ENET_OFFSET0);
  1428.     
  1429.     return (OK);
  1430.     }
  1431. /**************************************************************************
  1432. *
  1433. * sysEnetAddrInit - Initialize NVRAM with default ethernet address
  1434. *
  1435. * This routine checks the ethernet address stored in NVRAM. If the
  1436. * first three bytes are not set to the unused manufacturing code
  1437. * (ENET_DEFAULT, defined in config.h), then a default address
  1438. * is written into NVRAM which comprises the unused manufacturing code
  1439. * and 3 lower bytes of 0xff.
  1440. *
  1441. * RETURNS: N/A
  1442. */
  1443. void sysEnetAddrInit (void)
  1444.     {
  1445.     char defEnetAddr [ENET_SIZE] = /* Default ethernet address */
  1446.         {
  1447.         ((ENET_DEFAULT & 0x0000ff00) >> 8),
  1448.         ((ENET_DEFAULT & 0x00ff0000) >> 16),
  1449.         ((ENET_DEFAULT & 0xff000000) >> 24),
  1450.         0xff, 0xff, 0xff
  1451.         };
  1452.     char curEnetAddr [ENET_SIZE + 1]; /* Current ethernet address */
  1453.     /* Read current ethernet address */
  1454.     
  1455.     sysNvRamGet(curEnetAddr, ENET_SIZE, NV_ENET_OFFSET0);
  1456.     /* If first three bytes of current ethernet address are not
  1457.      * ENET_DEFAULT, then write default address.
  1458.      */
  1459.      
  1460.     if ((curEnetAddr[0] != defEnetAddr[0]) 
  1461.        ||  (curEnetAddr[1] != defEnetAddr[1])
  1462.        ||  (curEnetAddr[2] != defEnetAddr[2])
  1463.        )
  1464.        {
  1465.        sysNvRamSet (defEnetAddr, ENET_SIZE, NV_ENET_OFFSET0);
  1466.        }
  1467.     }
  1468.  
  1469. #ifdef  INCLUDE_TIMESTAMP
  1470. /*******************************************************************************
  1471. *
  1472. * sysTimestampConnect - connect a user routine to a timestamp timer interrupt
  1473. *
  1474. * This routine specifies the user interrupt routine to be called at each
  1475. * timestamp timer interrupt.
  1476. *
  1477. * RETURNS: ERROR, always.
  1478. */
  1479. STATUS sysTimestampConnect
  1480.     (
  1481.     FUNCPTR routine,    /* routine called at each timestamp timer interrupt */
  1482.     int arg             /* argument with which to call routine */
  1483.     )
  1484.     {
  1485.     return (ERROR);
  1486.     }
  1487. /*******************************************************************************
  1488. *
  1489. * sysTimestampEnable - enable a timestamp timer interrupt
  1490. *
  1491. * This routine enables timestamp timer interrupts and resets the counter.
  1492. *
  1493. * RETURNS: OK, always.
  1494. *
  1495. * SEE ALSO: sysTimestampDisable()
  1496. */
  1497. STATUS sysTimestampEnable (void)
  1498.    {
  1499.    if (sysTimestampRunning)
  1500.       {
  1501.       return (OK);
  1502.       }
  1503.    if (!sysClkRunning)
  1504.       return (ERROR);
  1505.    sysTimestampRunning = TRUE;
  1506.    return (OK);
  1507.    }
  1508. /*******************************************************************************
  1509. *
  1510. * sysTimestampDisable - disable a timestamp timer interrupt
  1511. *
  1512. * This routine disables timestamp timer interrupts.
  1513. *
  1514. * RETURNS: OK, always.
  1515. *
  1516. * SEE ALSO: sysTimestampEnable()
  1517. */
  1518. STATUS sysTimestampDisable (void)
  1519.     {
  1520.     if (sysTimestampRunning)
  1521.         sysTimestampRunning = FALSE;
  1522.     return (OK);
  1523.     }
  1524. /*******************************************************************************
  1525. *
  1526. * sysTimestampPeriod - get the period of a timestamp timer
  1527. *
  1528. * This routine gets the period of the timestamp timer, in ticks.  The
  1529. * period, or terminal count, is the number of ticks to which the timestamp
  1530. * timer counts before rolling over and restarting the counting process.
  1531. *
  1532. * RETURNS: The period of the timestamp timer in counter ticks.
  1533. */
  1534. UINT32 sysTimestampPeriod (void)
  1535.     {
  1536.     /*
  1537.      * The period of the timestamp depends on the clock rate of the on-chip
  1538.      * timer.
  1539.      */
  1540.     return (CPU_CLOCK_RATE/sysClkTicksPerSecond);
  1541.     }
  1542. /*******************************************************************************
  1543. *
  1544. * sysTimestampFreq - get a timestamp timer clock frequency
  1545. *
  1546. * This routine gets the frequency of the timer clock, in ticks per
  1547. * second.  The rate of the timestamp timer is set explicitly by the
  1548. * hardware and typically cannot be altered.
  1549. *
  1550. * RETURNS: The timestamp timer clock frequency, in ticks per second.
  1551. */
  1552. UINT32 sysTimestampFreq (void)
  1553.     {
  1554.     return (CPU_CLOCK_RATE);
  1555.     }
  1556. /*******************************************************************************
  1557. *
  1558. * sysTimestamp - get a timestamp timer tick count
  1559. *
  1560. * This routine returns the current value of the timestamp timer tick counter.
  1561. * The tick count can be converted to seconds by dividing it by the return of
  1562. * sysTimestampFreq().
  1563. *
  1564. * This routine should be called with interrupts locked.  If interrupts are
  1565. * not locked, sysTimestampLock() should be used instead.
  1566. *
  1567. * RETURNS: The current timestamp timer tick count.
  1568. *
  1569. * SEE ALSO: sysTimestampFreq(), sysTimestampLock()
  1570. */
  1571. UINT32 sysTimestamp (void)
  1572.     {
  1573.     return (sysCountGet() - (sysSoftCompare - sysClkProcessorTicks) + 1);
  1574.     }
  1575. /*******************************************************************************
  1576. *
  1577. * sysTimestampLock - lock interrupts and get the timestamp timer tick count
  1578. *
  1579. * This routine locks interrupts when the tick counter must be stopped
  1580. * in order to read it or when two independent counters must be read.
  1581. * It then returns the current value of the timestamp timer tick
  1582. * counter.
  1583. *
  1584. * The tick count can be converted to seconds by dividing it by the return of
  1585. * sysTimestampFreq().
  1586. *
  1587. * If interrupts are already locked, sysTimestamp() should be
  1588. * used instead.
  1589. *
  1590. * RETURNS: The current timestamp timer tick count.
  1591. *
  1592. * SEE ALSO: sysTimestampFreq(), sysTimestamp()
  1593. */
  1594. UINT32 sysTimestampLock (void)
  1595.     {
  1596.     return(sysCountGet() - (sysSoftCompare - sysClkProcessorTicks)+ 1);
  1597.     }
  1598. #endif  /* INCLUDE_TIMESTAMP */
  1599. #ifdef BROADCOM_BSP
  1600. /******************************************************************************
  1601. *
  1602. * sysBacktraceMips - perform a stack trace of the caller with symbols
  1603. *  by Curt McDowell - csm@broadcom.com 03-20-01
  1604. *
  1605. * NOTE:
  1606. * This routine is specific to MIPS and GCC stack frame generation.
  1607. * Each function generated by the compiler must begin with a decrement
  1608. * of the stack pointer, then in the next few instructions, must save
  1609. * the return address on the stack.
  1610. *
  1611. *   27bdffd0    addiu       $sp,$sp,-48
  1612. * ...
  1613. *   afbf0028    sw          $ra,40($sp)
  1614. * ...
  1615. */
  1616. /* Hack; some day fix to locate function start using symFindByValue */
  1617. #define SYSBT_MAX_FUNC_WORDS 4096
  1618. LOCAL void sysbt_addr2sym(char *symName, UINT addr)
  1619. {
  1620.     extern SYMTAB_ID sysSymTbl;
  1621.     UINT symVal;
  1622.     SYM_TYPE symType;
  1623.     int                 rc;
  1624. #if VX_VERSION==55
  1625.     char                **psymName;
  1626.     
  1627.     rc = symByValueFind(sysSymTbl,
  1628.        (UINT) addr,
  1629.        psymName, &symVal, &symType);
  1630.     if (rc != ERROR)
  1631.         strcpy(symName, *psymName);        
  1632. #else
  1633.     rc = symFindByValue(sysSymTbl,
  1634.        (UINT) addr,
  1635.        symName, &symVal, &symType);
  1636. #endif
  1637.     if (rc == ERROR)
  1638.         sprintf(symName, "0x%x", addr);
  1639.     else if (symVal < addr)
  1640. sprintf(symName + strlen(symName),
  1641. " + 0x%x", addr - symVal);
  1642.     else if (symVal > addr)
  1643. sprintf(symName + strlen(symName),
  1644. " - 0x%x", symVal - addr);
  1645. }
  1646. #define VALID_K0(addr) 
  1647. (IS_KSEG0(addr) && K0_TO_PHYS(addr) < K0_TO_PHYS(sysPhysMemTop()))
  1648. #define VALID_K1(addr) 
  1649. (IS_KSEG1(addr) && K1_TO_PHYS(addr) < K0_TO_PHYS(sysPhysMemTop()))
  1650. #define VALID_ADDR(addr) 
  1651. (VALID_K0(addr) || VALID_K1(addr))
  1652. #define VALID_TEXT_ADDR(addr) 
  1653. VALID_ADDR(addr) /* some day fix for text range */
  1654. #define VALID_STACK_ADDR(addr) 
  1655. VALID_ADDR(addr) /* some day fix for stack range */
  1656. void sysBacktraceMips(char *pfx, char *sfx, int direct)
  1657. {
  1658.     UINT *sp, *pc, *fn_start, *caller_sp, *ra;
  1659.     extern UINT *vxSpGet(), *vxPcGet(); /* sysALib.s */
  1660.     int limit, first = 1;
  1661.     char buf[2048], symName[128], *s;
  1662.     int ra_off, sp_off;
  1663.     extern void sysSerialPrintString(char *s);
  1664.     sp = vxSpGet();
  1665.     pc = vxPcGet();
  1666.     s = buf;
  1667.     strcpy(s, pfx);
  1668.     while (*s) s++;
  1669.     while (s < &buf[sizeof (buf) - 128]) {
  1670. fn_start = pc;
  1671. for (limit = 0; limit < SYSBT_MAX_FUNC_WORDS; limit++) {
  1672.     /* sw $ra,x($sp); x>=0 */
  1673.     if ((*--fn_start & 0xffff8000) == 0xafbf0000)
  1674. break;
  1675. }
  1676. if (limit == SYSBT_MAX_FUNC_WORDS)
  1677.     break;
  1678. ra_off = (*fn_start & 0x7fff);
  1679. for (limit = 0; limit < SYSBT_MAX_FUNC_WORDS; limit++) {
  1680.     /* addiu $sp,$sp,-x; x<0 */
  1681.     if ((*--fn_start & 0xffff8000) == 0x27bd8000)
  1682. break;
  1683. }
  1684. if (limit == SYSBT_MAX_FUNC_WORDS)
  1685.     break;
  1686. sp_off = (int) (*fn_start | 0xffff0000);
  1687. ra = (UINT *) sp[ra_off / 4];
  1688. caller_sp = sp - (sp_off / 4);
  1689. sysbt_addr2sym(symName, (UINT) pc);
  1690. if (! first)
  1691.     sprintf(s,
  1692.     "FUNC = 0x%x, PC = 0x%x (%s), SP = 0x%xn",
  1693.     (UINT) fn_start, (UINT) pc, symName, (UINT) sp);
  1694. while (*s) s++;
  1695. if (! VALID_TEXT_ADDR(ra)) {
  1696.     sprintf(s, "RA 0x%x out of rangen", (UINT) ra);
  1697.     while (*s) s++;
  1698.     break;
  1699. }
  1700. if (! VALID_STACK_ADDR(caller_sp)) {
  1701.     sprintf(s, "Caller SP 0x%x out of rangen", (UINT) caller_sp);
  1702.     while (*s) s++;
  1703.     break;
  1704. }
  1705. pc = ra;
  1706. sp = caller_sp;
  1707. first = 0;
  1708.     }
  1709.     strcpy(s, sfx);
  1710.     if (direct)
  1711. sysSerialPrintString(buf);  /* Atomically print giant string */
  1712.     else {
  1713. fputs(buf, stdout); /* Regular print giant string */
  1714. fflush(stdout);
  1715.     }
  1716. }
  1717. /*******************************************************************************
  1718. *
  1719. * sysToMonitor - transfer control to the ROM monitor
  1720. *
  1721. * This routine transfers control to the ROM monitor.  Normally, it is called
  1722. * only by reboot()--which services ^X--and bus errors at interrupt level.
  1723. * However, in some circumstances, the user may wish to introduce a
  1724. * <startType> to enable special boot ROM facilities.
  1725. *
  1726. * RETURNS: Does not return.
  1727. */
  1728. int sysToMonitorExcMessage = 0;
  1729. int sysToMonitorBacktrace = 1;
  1730. int sysToMonitorReboot = 1;
  1731. void (*sysToMonitorHook)(void);
  1732. STATUS sysToMonitor
  1733.     (
  1734.     int startType    /* parameter passed to ROM to tell it how to boot */
  1735.     )
  1736.     {
  1737.     if (sysToMonitorHook)
  1738.         (*sysToMonitorHook)();
  1739.     if (sysToMonitorBacktrace)
  1740.         sysBacktraceMips("n--- Stack Trace ---n", "", 1);
  1741.     if (sysToMonitorReboot) {
  1742.         FUNCPTR pRom = (FUNCPTR) (ROM_TEXT_ADRS + 8);
  1743.         intLock();
  1744.         sysWbFlush ();   /* Flush write buffers */
  1745.         (*pRom) (startType);
  1746.         return (OK);    /* in case we ever continue from rom monitor */
  1747.     }
  1748.     return (OK);
  1749.     }
  1750. /*******************************************************************************
  1751. *
  1752. * sysReboot - Reboots the system
  1753. *
  1754. *
  1755. * RETURNS: Does not return.
  1756. */
  1757. void sysReboot
  1758.     (
  1759.     void
  1760.     )
  1761. {
  1762.     sysToMonitor(0);
  1763. }
  1764. void
  1765. SYS_TOD_SET()
  1766. {
  1767. }
  1768. void
  1769. sysSerialPrintString()
  1770. {
  1771. }
  1772. /* Detect HHB4 / DC21150 PCI-PCI bridge chips, and configure bus if
  1773.  * found. Note that this code should be run whenever we find a PCI
  1774.  * class code of type bridge. After we have run this procedure for the
  1775.  * first bridge, we then need to traverse any sub-bridges. This code
  1776.  * deals with only one PCI-PCI bridge and it's IO space for
  1777.  * sub-devices. See mousse.h for more details as well as the PCI-PCI
  1778.  * bridge specification.
  1779.  */
  1780. #ifdef INCLUDE_PCI
  1781. int sysPCIBridgeProbe(int instance,
  1782.       int primary,
  1783.       int secondary,
  1784.       int subordinate)
  1785. {
  1786.     int BusNo, DevNo, FuncNo;
  1787.     unsigned int buses = 0;
  1788.     sysPciBusErrDisable();    
  1789.     /* Find DC21150 PCI-PCI bridge or
  1790.      * HINTCORP HB4 PCI-PCI Bridge
  1791.      */
  1792.     if ( (pciFindDevice(DC21150_VENDOR_ID,
  1793. DC21150_DEVICE_ID,
  1794. instance,
  1795. &BusNo, &DevNo, &FuncNo) != ERROR) ||
  1796.          (pciFindDevice(PERICOM_VENDOR_ID,
  1797.                         PERICOM_8150_DEV_ID,
  1798.                         instance,
  1799.                         &BusNo, &DevNo, &FuncNo) != ERROR) ||
  1800.  (pciFindDevice(HINT_HB4_VENDOR_ID,
  1801. HINT_HB4_DEVICE_ID,
  1802. instance,
  1803. &BusNo, &DevNo, &FuncNo) != ERROR)) {
  1804. /* Disable device */
  1805. pciConfigOutWord(BusNo,DevNo,FuncNo, PCI_CFG_COMMAND, 0x0000);
  1806. pciConfigOutWord(BusNo,DevNo,FuncNo, PCI_CFG_STATUS, 0xffff);
  1807. /* Reset secondary bus */
  1808. pciConfigOutWord(BusNo,DevNo,FuncNo,
  1809.  PCI_CFG_BRIDGE_CONTROL,
  1810.  0x0040);
  1811. /* Setup topology info */
  1812. buses = (buses & 0xff000000)
  1813.     | ((unsigned int)(primary)     <<  0)
  1814.     | ((unsigned int)(secondary)   <<  8)
  1815.     | ((unsigned int)(subordinate) << 16);
  1816. /*
  1817.  * linux, -We need to blast all three values with a single write.
  1818.  */
  1819. pciConfigOutLong(BusNo, DevNo, FuncNo,
  1820.  PCI_CFG_PRIMARY_BUS, buses);
  1821. /* Clear secondary status */
  1822. pciConfigOutWord(BusNo,DevNo,FuncNo,
  1823.  PCI_CFG_SEC_STATUS, 0xffff);
  1824. /* Setup memory address space mapping */
  1825. pciConfigOutWord(BusNo,DevNo,FuncNo,     
  1826.  PCI_CFG_MEM_BASE,
  1827.  ((P2P_NONPREF_MEM_BASE & 0xFFF00000) >> 16));
  1828. pciConfigOutWord(BusNo,DevNo,FuncNo,
  1829.  PCI_CFG_MEM_LIMIT,
  1830.  ((P2P_NONPREF_MEM_BASE +
  1831.    P2P_NONPREF_MEM_SIZE - 1) & 0xFFF00000) >> 16);
  1832. /* Clear bridge control */
  1833. pciConfigOutWord(BusNo,DevNo,FuncNo,
  1834.  PCI_CFG_BRIDGE_CONTROL,0x0000);
  1835. /* Enable PCI clocks on remote end */
  1836. pciConfigOutWord(BusNo,DevNo,FuncNo,
  1837.  PCI_CFG_DEC21150_SEC_CLK,
  1838.  P2P_CLK_ENABLE);
  1839. /* Clear status */
  1840. pciConfigOutByte(BusNo,DevNo,FuncNo,
  1841.  PCI_CFG_DEC21150_SERR_STAT, 0xff);
  1842. /* Clear status */
  1843. pciConfigOutWord(BusNo,DevNo,FuncNo,
  1844.  PCI_CFG_STATUS, 0xffff);
  1845. /* Re-enable config space */
  1846. pciConfigOutWord(BusNo,DevNo,FuncNo, PCI_CFG_COMMAND,
  1847.  P2P_PMC_ENABLE);
  1848.      
  1849. return OK;
  1850.     }    
  1851.     sysPciBusErrEnable();    
  1852.     return ERROR;
  1853. }
  1854. #endif
  1855. /*****************************************************************************
  1856. *
  1857. * Each time VxWorks is rebooted, it starts assigning system-assigned
  1858. * port numbers beginning at 1024.  Thus, if vxWorks is rebooted two or
  1859. * more times in succession, the same port number will be re-used.
  1860. *
  1861. * This behavior causes problems when vxWorks is being booted from a
  1862. * remote FTP server (particularly one running Solaris), because port
  1863. * 1024 goes into a TIME_WAIT state on the server and cannot be reused
  1864. * until it times out, typically in 2-4 minutes.
  1865. *
  1866. * This hack reduces the likelihood of this happening by "wasting"
  1867. * a different number of system-assigned port numbers for each boot.
  1868. */
  1869. void sysBindFix(void)
  1870. {
  1871.     UINT8 N;
  1872.     sysNvRamGet((char *) &N, 1, NV_OFF_BINDFIX);
  1873.     N -= 16;
  1874.     sysNvRamSet((char *) &N, 1, NV_OFF_BINDFIX);
  1875.     /* This is quite fast even when N=255 */
  1876.     while (N--) {
  1877. int s;
  1878. struct sockaddr_in saddr;
  1879. saddr.sin_addr.s_addr = htonl(INADDR_ANY);
  1880. saddr.sin_port = 0;
  1881. saddr.sin_family = AF_INET;
  1882. s = socket(AF_INET, SOCK_STREAM, 0);
  1883. bind(s, (struct sockaddr *) &saddr, sizeof(saddr));
  1884. close(s);
  1885.     }
  1886. }
  1887. #ifdef PCI_DECOUPLED
  1888. #define MAX_POLL_PCI_DECOUPLED  256
  1889. UINT32 sysMaxPciRpolls = 0;
  1890. UINT32 sysMaxPciWpolls = 0;
  1891. UINT32 sysMaxPciRpollsDist[256] = { 0 };
  1892. #ifdef INCLUDE_PCI
  1893. void
  1894. sysPciRWInit()
  1895. {
  1896.     PCI.pcidac  = PCIDAC_DEN;  /* Enable PCI decoupled accesses at */
  1897.                                /* initialization */
  1898.     for(sysMaxPciRpolls = 0;
  1899.         sysMaxPciRpolls < sizeof(sysMaxPciRpollsDist)/sizeof(UINT32);
  1900.         sysMaxPciRpolls++) {
  1901.             sysMaxPciRpollsDist[sysMaxPciRpolls] = 0;
  1902.         }
  1903.     sysMaxPciRpolls = 0;
  1904.     sysMaxPciWpolls = 0;
  1905. }
  1906. UINT32
  1907. sysPciRead(UINT32 *addr)
  1908. {
  1909.     volatile UINT32 data;
  1910.     UINT32 spl;
  1911.     UINT32 cpolls = 0;
  1912.     spl = intLock();
  1913.     data = *addr;
  1914.     while (((PCI.pcidas) & PCIDAS_D) == 0) {
  1915.         if (sysMaxPciRpolls < ++cpolls ) sysMaxPciRpolls = cpolls;
  1916.         if (((PCI.pcidas) & PCIDAS_E) != 0) break;
  1917.         if (cpolls > MAX_POLL_PCI_DECOUPLED) break;
  1918.     }
  1919.     if (cpolls < sizeof(sysMaxPciRpollsDist)/sizeof(UINT32)) {
  1920.         sysMaxPciRpollsDist[cpolls]++; 
  1921.     }
  1922.     data = PCI.pcidad;
  1923.     data = ((data & 0xFF000000) >> 24) |
  1924.            ((data & 0x00FF0000) >> 8) |
  1925.            ((data & 0x0000FF00) << 8) |
  1926.            ((data & 0x000000FF) << 24) ;
  1927.     PCI.pcidas &= (~(PCIDAS_D));
  1928.     intUnlock(spl);
  1929.     return(data);
  1930. }
  1931. void
  1932. sysPciWrite(UINT32 *addr, UINT32 data)
  1933. {
  1934.     UINT32 spl;
  1935.     UINT32 cpolls = 0;
  1936.     spl = intLock();
  1937.     while ((PCI.pcidas & PCIDAS_OFE) == 0) {
  1938.         if (sysMaxPciWpolls < ++cpolls ) sysMaxPciWpolls = cpolls;
  1939.         if (cpolls > MAX_POLL_PCI_DECOUPLED) break;
  1940.     }
  1941.     *addr = data;
  1942.     cpolls = 0;
  1943.     intUnlock(spl);
  1944. }
  1945. #endif
  1946. #endif /* PCI_DECOUPLED */
  1947. #endif /*BROADCOM_BSP */