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

VxWorks

开发平台:

C/C++

  1. /*
  2.     Copyright 2001, Broadcom Corporation
  3.     All Rights Reserved.
  4.     
  5.     This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
  6.     the contents of this file may not be disclosed to third parties, copied or
  7.     duplicated in any form, in whole or in part, without the prior written
  8.     permission of Broadcom Corporation.
  9. */
  10.  
  11. /* sysLib.c - BCM 4702 system-dependent routines */
  12. /*
  13. modification history
  14. --------------------
  15. 01e,24sep02,jmb   send XON to serial port.  
  16. 01d,06sep02,jmb   remove single PCI interrupt hack.  Use VxWorks shared PCI
  17.                   interrupt handler.  Scan for secondary PCI bridges.
  18. 01c,15aug02,jmb   pciIntConnect for single PCI interrupt
  19. 01b,14aug02,jmb   stubbed out sysBusTas for vxMemProbe
  20. 01a,30jul02,jmb   created from sysLib.c,v 1.33 for HNBU 4710 eval board.  Merged
  21.                   in code from Strata idtrp334 BSP.
  22. */
  23. /*
  24. DESCRIPTION
  25. This library provides board-specific routines.
  26. INCLUDE FILES: sysLib.h
  27. SEE ALSO:
  28. .pG "Configuration"
  29. */
  30. /* includes */
  31. #include "vxWorks.h"
  32. #include "vxLib.h"
  33. #include "config.h"
  34. #include "version.h"
  35. #include "ioLib.h"
  36. #include "tyLib.h"
  37. #include "sysLib.h"
  38. #include "dosFsLib.h"
  39. #include "string.h"
  40. #include "intLib.h"
  41. #include "muxLib.h"
  42. #include "ipProto.h"
  43. #include "ifLib.h"
  44. #include "tickLib.h"
  45. #include "cacheLib.h"
  46. #include "symLib.h"
  47. #include "rebootLib.h"
  48. #include "stdio.h"
  49. #include "hnbutypedefs.h"
  50. #include "sbconfig.h"
  51. #include "bcmenet47xx.h"
  52. #include "vxbsp.h"
  53. #include "sb2pci.h"
  54. #include "drv/pci/pciConfigLib.h"
  55. #include "vx_osl.h"
  56. #include "vxbsp.h"
  57. #include "sbextif.h"
  58. #include "m48t59y.h"
  59. #include "ds1743.h"
  60. #include "netinet/in.h"         /* for sysBindFix() */
  61. #include "sockLib.h"            /* for sysBindFix() */
  62. #include "mem/byteNvRam.c"
  63.  
  64. static bcmenetregs_t *timerregs = NULL;
  65. IMPORT void     sysWbFlush ();
  66. IMPORT ULONG    taskSRInit();
  67. IMPORT int      sysSetCompare ();
  68. IMPORT int      sysGetCompare ();
  69. IMPORT int      sysGetPrid ();
  70. IMPORT int      sysGetCount ();
  71. IMPORT int      sysSetCount ();
  72. IMPORT int      printf (const char *, ...);
  73. IMPORT int      isprint (char);
  74. IMPORT UCHAR    sysinbyte(ULONG address);
  75. IMPORT USHORT   sysinword(ULONG address);
  76. IMPORT ULONG    sysinlong( ULONG address);
  77. IMPORT void     sysoutlong(ULONG address, ULONG datavalue);
  78. IMPORT void     sysoutword(ULONG address, USHORT datavalue);
  79. IMPORT void     sysoutbyte(ULONG address, UCHAR data);
  80. IMPORT void     platform_init();
  81. IMPORT uint32   get_sb_extif_tpsflag();
  82. IMPORT UINT8    ffsMsbTbl[];            /* Msb high interrupt hash table */
  83. IMPORT UINT8    ffsLsbTbl[];            /* Lsb high interrupt hash table */
  84. IMPORT int              consoleFd;              /* klmod: fd of initial console device */
  85. IMPORT int     pciMaxBus;
  86. IMPORT STATUS usrBootLineCrack(char * bootString,BOOT_PARAMS *pParams);
  87. /* globals */
  88. int   sysCpu      = CPU;                /* system CPU type (MIPS_RC32364) */
  89. char *sysMemTopAdr= NULL;               /* top of memory */
  90. char *sysBootLine = BOOT_LINE_ADRS;     /* address of boot line */
  91. char *sysExcMsg   = EXC_MSG_ADRS;       /* catastrophic message area */
  92. int   sysProcNum;                       /* processor number of this CPU */
  93. int   sysFlags;                         /* boot flags */
  94. char  sysBootHost [BOOT_FIELD_LEN];     /* name of host from which we booted */
  95. char  sysBootFile [BOOT_FIELD_LEN];     /* name of file from which we booted */
  96. int   sysVectorIRQ0 =IV_IORQ0_VEC;      /* used by SAL for pci int connect */
  97. int   sysMemTopDebug = 0;
  98. ULONG sysSoftCompare = 0;               /* last target compare reg value */
  99. /*
  100. *  Since tying interrupt lines to the processor is board dependent sysHashOrder
  101. *  is provided to select the prioritization of interrupt lines.  Setting the
  102. *  #define INT_PRIO_MSB to TRUE prioritizes interrupts from 7-0, 7 being
  103. *  highest priority, 0 being lowest.  Setting it to FALSE prioritizes
  104. *  interrupts from 0-7.  See idts134.h for the definition of INT_PRIO_MSB.
  105. */
  106. #if INT_PRIO_MSB == TRUE
  107. UINT8 * sysHashOrder = ffsMsbTbl;       /* interrupt prio., 7 = high 0 = low */
  108. #else   /* INT_PRIO_MSB == TRUE */
  109. UINT8 * sysHashOrder = ffsLsbTbl;       /* interrupt prio., 0 = high 7 = low */
  110. #endif  /* INT_PRIO_MSB == TRUE */
  111. /* forward declarations */
  112. STATUS sysEnetAddrGet (char *dev, int unit, unsigned char *pMac);
  113. LOCAL void      sysClkInt ();
  114. LOCAL int       sysSw0Ack ();
  115. LOCAL int       sysSw1Ack ();
  116. typedef struct 
  117.     {
  118.     ULONG       intCause;               /* cause of interrupt   */
  119.     ULONG       bsrTableOffset;         /* index to BSR table   */
  120.     ULONG       statusReg;              /* interrupt level      */
  121.     ULONG       pad;                    /* pad for ease of use  */
  122.     } PRIO_TABLE;
  123. /*
  124. *       intPrioTable is a board dependant structure that aids in the
  125. *       processing of the 8 Rc32364 interrupt conditions.
  126. *       It is used by excLib to determine the pending interrupt and
  127. *       to call the user attached handler.  The present search algorithm
  128. *       relies on a one to one mapping of Rc32364 interrupt lines and
  129. *       table entries.
  130. *
  131. *       Each entry has 4 fields, the first (intCause) is the interrupt ID, 
  132. *       second (bsrTableOffset) is the vector number, third is unused
  133. *       last (pad) is the multiplex field.  When an interrupt is received
  134. *       the handler maps the pending Rc32364 line to  its' corresponding
  135. *       table entry (ie. Software interrupt 0 would map to the first entry
  136. *       in the table).  At this point interrupts that are not pending are
  137. *       enabled.  Next the multiplex field is read, if it is zero, field 
  138. *       two is taken as the interrupt vector number in the BSR table, 
  139. *       otherwise it is interpreted as a demultiplex function and called
  140. *       with field 4 passed as it's parameter.  The job of the demultiplex
  141. *       routine is to calculate the correct interrupt vector number and pass
  142. *       it back to the handler.  The handler can then call the routine the
  143. *       user has installed in the BSR table with intVecSet, or intConnect.
  144. *
  145. *       This table is critical to interrupt processing.  Do not alter
  146. *       it's contents until you understand the consequences.  The routine
  147. *       sysPrioUpdate can aid modification during runtime.
  148. */
  149. PRIO_TABLE intPrioTable[8] =
  150.     {
  151.     {CAUSE_SW1,(ULONG) IV_SWTRAP0_VEC, 0x0100, 0},      /* sw trap 0      */
  152.     {CAUSE_SW2,(ULONG) IV_SWTRAP1_VEC, 0x0200, 0},      /* sw trap 1      */
  153.     {CAUSE_IP3,(ULONG) INT_VEC_IORQ0 , 0x0400, 0},              
  154.     {CAUSE_IP4,(ULONG) INT_VEC_IORQ1 , 0x0800, 0},      
  155.     {CAUSE_IP5,(ULONG) INT_VEC_IORQ2 , 0x1000, 0},      
  156.     {CAUSE_IP6,(ULONG) INT_VEC_IORQ3 , 0x2000, 0},      
  157.     {CAUSE_IP7,(ULONG) INT_VEC_IORQ4 , 0x4000, 0},      
  158.     {CAUSE_IP8,(ULONG) INT_VEC_IORQ5 , 0x8000, 0}       
  159.     };
  160. typedef struct _systodfunctions
  161.     {
  162.     FUNCPTR init;
  163.     FUNCPTR get;
  164.     FUNCPTR set;
  165.     FUNCPTR getSecond;
  166.     FUNCPTR watchdogArm;
  167.     } SYSTODFUNCTIONS;
  168. SYSTODFUNCTIONS sysTodFuncs;
  169. int sysRevId;
  170. VOIDFUNCPTR bringupPrintRtn = NULL;
  171. /* select cache library */
  172. IMPORT STATUS cacheBcm47xxLibInit(CACHE_MODE,CACHE_MODE);
  173. FUNCPTR sysCacheLibInit = (FUNCPTR)cacheBcm47xxLibInit; 
  174. /* locals */
  175. LOCAL int   sysClkTicksPerSecond    = 100;      /* default sys timer rate    */
  176. LOCAL int   sysClkArg               = 0;        /* clock int routine arg     */
  177. LOCAL BOOL  sysClkConnected         = FALSE;    /* sys clock connect flag    */
  178. LOCAL BOOL  sysClkRunning           = FALSE;    /* sys clock enabled flag    */
  179. LOCAL int   sysClkProcessorTicks;               /* MIPS32 clock ticks        */
  180. LOCAL FUNCPTR   sysClkRoutine       = NULL ;    /* clock interrupt routine   */
  181. LOCAL char sysModelStr[200];
  182. /* Commenting out sysAuxClkRoutines and defines as its not supported. However
  183.    the auxiliary clock can be generated by using one of the three general 
  184.    purpose timers of Rc32134 */                                           
  185. LOCAL BOOL  sysAuxClkRunning        = FALSE;     /*sys aux clock enabled flag */
  186. LOCAL BOOL  sysAuxClkConnected      = FALSE;     /*sys aux clock connect flag */
  187. LOCAL int   sysAuxClkTicksPerSecond = 200;       /* default aux timer rate    */
  188. LOCAL int   sysAuxClkArg            = 0 ;        /*aux clock int routine arg  */
  189. LOCAL FUNCPTR   sysAuxClkRoutine    = NULL ;     /*aux clock interpt routine  */
  190. #ifdef INCLUDE_TIMESTAMP
  191. LOCAL BOOL  sysTimestampRunning     = FALSE;   /* timestamp running flag */
  192. #endif  /* INCLUDE_TIMESTAMP */
  193. #ifdef INCLUDE_NETWORK
  194. #ifdef INCLUDE_END
  195. #if (defined(INCLUDE_ET0_END) || defined(INCLUDE_ET1_END))
  196. #include "sysEtEnd.c"
  197. #endif /* INCLUDE_ET_END */
  198. #endif /* INCLUDE_END */
  199. #endif  /* INCLUDE_NETWORK */
  200. /*
  201.  * Tell if a buffer contains a valid ansiTime time zone specification
  202.  */
  203. int sysTimeZoneGood(char *tz)
  204. {
  205.     int                 i, colons = 0;
  206.     for (i = 0; i < 64; i++) {
  207.         if (tz[i] == 0 || tz[i] == 10 || tz[i] == 13) {
  208.             tz[i] = 0;
  209.             break;
  210.         }
  211.         if (tz[i] < 32 || (tz[i] & 0x80))
  212.             return 0;
  213.         if (tz[i] == ':')
  214.             colons++;
  215.     }
  216.     return (i < 64 && colons == 4);
  217. }
  218. /*******************************************************************************
  219. *
  220. * sysModel - return the model name of the CPU board
  221. *
  222. * This routine returns the model name of the CPU board.
  223. *
  224. * RETURNS: A pointer to the string "IDT S134".
  225. */
  226. char *sysModel (void)
  227.     {
  228.     strcpy (sysModelStr, "BCM4702 (MIPS32)n");
  229.     strcat (sysModelStr, "Board:  MBZn");
  230.     return (sysModelStr);
  231.     }
  232. /******************************************************************************
  233. *
  234. * sysBspRev - return the bsp version with the revision eg 1.1/<x>
  235. *
  236. * This function returns a pointer to a bsp version with the revision.
  237. * for eg. 1.1/<x>. BSP_REV is concatanated to BSP_VERSION to form the
  238. * BSP identification string.
  239. *
  240. * RETURNS: A pointer to the BSP version/revision string.
  241. */
  242. char * sysBspRev (void)
  243.     {
  244.     return (BSP_VERSION BSP_REV);
  245.     }
  246. /*****************************************************************************
  247. *
  248. * Each time VxWorks is rebooted, it starts assigning system-assigned
  249. * port numbers beginning at 1024.  Thus, if vxWorks is rebooted two or
  250. * more times in succession, the same port number will be re-used.
  251. *
  252. * This behavior causes problems when vxWorks is being booted from a
  253. * remote FTP server (particularly one running Solaris), because port
  254. * 1024 goes into a TIME_WAIT state on the server and cannot be reused
  255. * until it times out, typically in 2-4 minutes.
  256. *
  257. * This hack reduces the likelihood of this happening by "wasting"
  258. * a different number of system-assigned port numbers for each boot.
  259. */
  260. void sysBindFix(void)
  261. {
  262.     UINT8               N;
  263.     BPRINT("BFIX");
  264.     sysNvRamGet((char *) &N, 1, NV_OFF_BINDFIX);
  265.     N -= 16;
  266.     sysNvRamSet((char *) &N, 1, NV_OFF_BINDFIX);
  267.     /* This is quite fast even when N=255 */
  268.     while (N--) {
  269.         int s;
  270.         struct sockaddr_in saddr;
  271.         saddr.sin_addr.s_addr = htonl(INADDR_ANY);
  272.         saddr.sin_port = 0;
  273.         saddr.sin_family = AF_INET;
  274.         s = socket(AF_INET, SOCK_STREAM, 0);
  275.         bind(s, (struct sockaddr *) &saddr, sizeof(saddr));
  276.         close(s);
  277.     }
  278. }
  279. /*******************************************************************************
  280. *
  281. * sysHwInit - initialize the CPU board hardware
  282. *
  283. * This routine initializes various features of the IDT S364.
  284. * It is called from usrInit() in usrConfig.c.
  285. *
  286. * This routine initializes and turns off the timers.
  287. *
  288. * NOTE:
  289. * This routine should not be called directly by the user.
  290. * RETURNS: N/A
  291. */
  292. void sysHwInit (void)
  293.     {
  294.     int prid;
  295.     int sr;
  296.     char xonString[3];
  297.     prid = sysGetPrid ();       /* get the BCM47xx processor ID register */
  298.     
  299.     /* set default task status register for BCM47xx */
  300.     sr = BCM47XX_SR;
  301.     sysRevId = SYS_REVID_GET();
  302.     /* Initialize TOD functions */
  303.     switch(sysRevId) {
  304.         case BOARD_ID_MBZ_1:
  305.             sysTodFuncs.init = (FUNCPTR) m48_tod_init;
  306.             sysTodFuncs.get = (FUNCPTR) m48_tod_get;
  307.             sysTodFuncs.set = (FUNCPTR) m48_tod_set;
  308.             sysTodFuncs.getSecond =  (FUNCPTR) m48_tod_get_second;
  309.             sysTodFuncs.watchdogArm = (FUNCPTR) m48_watchdog_arm;
  310.             break;
  311.         /* case BOARD_ID_LM_1_32MB:*/
  312.         case BOARD_ID_MBZ_32MB:
  313.         case BOARD_ID_LM_1:
  314.         case BOARD_ID_MBZ_2:
  315.         case BOARD_ID_MBZ_5645_REF:
  316.         default:
  317.             sysTodFuncs.init = (FUNCPTR) ds1743_tod_init;
  318.             sysTodFuncs.get = (FUNCPTR) ds1743_tod_get;
  319.             sysTodFuncs.set = (FUNCPTR) ds1743_tod_set;
  320.             sysTodFuncs.getSecond = (FUNCPTR) ds1743_tod_get_second;
  321.             sysTodFuncs.watchdogArm = (FUNCPTR) NULL;
  322.             break;
  323.     }
  324.     /* init status register but leave interrupts disabled */
  325.     taskSRInit (sr);
  326.     intSRSet (sr & ~SR_IE);
  327.     BPRINT ("HWOK");
  328.     }
  329. /*******************************************************************************
  330. *
  331. * sharedInt0: checks to see which interrupts are connected to 0 and calls each
  332. * in turn.
  333. *
  334. *******************************************************************************/
  335. LOCAL void sharedInt0 (void)
  336. {
  337.     unsigned long index=0x40;
  338.     unsigned long intNum = IV_IORQ0_BIT6_VEC; 
  339.     FUNCPTR  intVec;
  340.     
  341.     if (!DEF_SBINTVEC) 
  342. return;
  343.     while(index) {       
  344. /* is interrupt enabled*/
  345. if(index & DEF_SBINTVEC) {
  346.     /* Get the interrupt vector */
  347.     intVec = intVecGet((FUNCPTR*)INUM_TO_IVEC(intNum--));
  348.     
  349.     /* if non null then call the interrupt handler */
  350.     if(intVec) (intVec)();
  351.     /* If ext/if interrupt then call an additional two possible handlers */
  352.     if(index & (1 << get_sb_extif_tpsflag())) {
  353.      intVec = intVecGet((FUNCPTR*)INUM_TO_IVEC(IV_EXT_ALT1_VEC));
  354.      if(intVec) (intVec)();
  355.      intVec = intVecGet((FUNCPTR*)INUM_TO_IVEC(IV_EXT_ALT2_VEC));
  356.      if(intVec) (intVec)();
  357. #ifdef INCLUDE_PCMCIA
  358. intVec = intVecGet((FUNCPTR*)INUM_TO_IVEC(IV_EXT_ALT3_VEC));
  359.      if(intVec) (intVec)();
  360.      intVec = intVecGet((FUNCPTR*)INUM_TO_IVEC(IV_EXT_ALT4_VEC));
  361.      if(intVec) (intVec)();
  362. #endif
  363.     }                
  364. }
  365. /* check next interrupt */ 
  366. index = index >> 1; 
  367.     }
  368. }
  369. /******************************************************************************
  370. *
  371. * sysHwInit2 - additional system configuration and initialization
  372. *
  373. * This routine connects system interrupts and does any additional
  374. * configuration necessary.
  375. *
  376. * RETURNS: N/A
  377. *
  378. * NOMANUAL
  379. */
  380. static void dummyISR(void) {
  381.     /* do nothing */
  382.     return;
  383. }
  384. void sysHwInit2 (void)
  385. {
  386.     int sr,i;
  387.     char xonString[3];
  388.     sr = intSRGet();
  389.     BPRINT ("PCI ");
  390. #ifdef INCLUDE_PCI
  391.     /* this routine is also responsible for resetting any devices that may
  392.        currently be in an active state and sets up the interrupt mappings */
  393.     pciConfigLibInit(0,0,0,0);
  394.     /*
  395.     * Probe for secondary bridge devices.  The 4702 supports 2 PCI devices
  396.     * connected directly to the host PCI bus.
  397.     * One or both of these devices may be PCI bridges to other buses.
  398.     * Bridges on secondary buses is not supported.
  399.     *
  400.     * Args to the bridge probe function are:
  401.     * (instance, primary busNo, secondary busNo, subordinate busNo)
  402.     * For 4702, the bus numbering is non-standard.  HNBU software has
  403.     * coopted bus number 0 for the silicon backplane, so PCI bus numbering
  404.     * starts at 1.
  405.     *
  406.     */
  407. #endif
  408.     BPRINT ("TOD ");
  409.     /* Start the Time of Day device */
  410.     sysTodInit ((void *) MBZ_NVRAM_ADDR);
  411.     BPRINT ("SER ");
  412.     /* Setup the serial device descriptors. */
  413.     sysSerialHwInit();
  414.     /*
  415.     *  Send XON character in case power-off noise from UART has
  416.     *  sent an XOFF
  417.     */
  418.     xonString[0] = (char) 0x11;
  419.     xonString[1] = 'n';
  420.     xonString[2] = '';
  421.     sysSerialPrintString(xonString);
  422.     /* Perform anything specific to this platform design */
  423.     platform_init(); 
  424.     pciMaxBus = 1;
  425.     /* 
  426.     * Look for a secondary PCI bridge.  If we find one, look for
  427.     * another.  This BSP only supports up to 2 secondary bridges
  428.     * on the host bridge.
  429.     */
  430.     if (sysPCIBridgeProbe (0, 1, 2, 2) == OK)
  431.         sysPCIBridgeProbe (1, 1, 3, 3);
  432.     /* Initialize PCI shared interrupt handler */
  433.     pciIntLibInit();
  434.     /*
  435.     **  External UART interrupt init.
  436.     **  BOARD_ID_MBZ_5645_REF uses internal UART.
  437.     */
  438.     if (SYS_REVID_GET() != BOARD_ID_MBZ_5645_REF) {
  439.         gpioIntInit();
  440.     }
  441.     /* connect dummy isr's to shared int vectors */
  442.     for(i=IV_IORQ0_VEC; i<IV_LAST_VEC; i++)
  443.   intConnect (INUM_TO_IVEC(i), dummyISR, i);
  444.     /* connect and enable timer int */
  445.     (void) intConnect (INUM_TO_IVEC(IV_RTIME_VEC), sysClkInt, 0);
  446.     sr |= INT_LVL_TIMER;   
  447.     /* Connect and enable "shared" mips int 0 handler */
  448.     (void) intConnect (INUM_TO_IVEC(IV_IORQ0_VEC), sharedInt0, 0);
  449.     sr |= INT_LVL_IORQ0;   
  450.     /* connect serial channel interrupts */
  451.     sysSerialHwInit2();         
  452.     
  453.     intSRSet(sr);    
  454. }
  455. /*******************************************************************************
  456. *
  457. * sysPhysMemTop - get the address of the top of memory
  458. *
  459. * This routine returns the address of the first missing byte of memory, which
  460. * indicates the top of memory.
  461. *
  462. * NOTE: Do not adjust LOCAL_MEM_SIZE to reserve memory for application
  463. * use.  See sysMemTop() for more information on reserving memory.
  464. *
  465. * RETURNS: The address of the top of memory.
  466. */
  467. char *sysPhysMemTop (void)
  468.     {
  469.   
  470.   static char * memTop = NULL;
  471.     if (memTop == NULL)
  472. {
  473. memTop = (char *)(LOCAL_MEM_LOCAL_ADRS +
  474.                 (((SYS_REVID_GET() != BOARD_ID_LM_1_32MB) &&
  475.                  (SYS_REVID_GET() != BOARD_ID_MBZ_32MB)) ?
  476.                     LOCAL_MEM_SIZE:LOCAL_MEM_SIZE_LM));
  477. }
  478.     return memTop;
  479.     }
  480. /*******************************************************************************
  481. *
  482. * sysMemTop - get the address of the top of logical memory
  483. *
  484. * This routine returns the address of the first unusable byte of memory.
  485. * VxWorks will not use any memory at or above this address.
  486. *
  487. * The user can reserve local memory from the board by declaring the
  488. * macro USER_RESERVED_MEM with the amount of memory to reserve. This
  489. * routine will return a pointer to the first byte of the reserved memory
  490. * area.
  491. *
  492. * RETURNS: The address of the top of usable memory.
  493. */
  494. char *sysMemTop (void)
  495. {
  496.     static char * memTop = NULL;
  497.     if (memTop == NULL)
  498. memTop = sysPhysMemTop () - USER_RESERVED_MEM;
  499.     return memTop;
  500. }
  501. #ifdef BROADCOM_BSP
  502. /******************************************************************************
  503. *
  504. * sysBacktraceMips - perform a stack trace of the caller with symbols
  505. *               by Curt McDowell - csm@broadcom.com 03-20-01
  506. *
  507. * NOTE:
  508. *
  509. * This routine is specific to MIPS and GCC stack frame generation.
  510. * Each function generated by the compiler must begin with a decrement
  511. * of the stack pointer, then in the next few instructions, must save
  512. * the return address on the stack.
  513. *
  514. *   27bdffd0    addiu       $sp,$sp,-48
  515. *               ...
  516. *   afbf0028    sw          $ra,40($sp)
  517. *               ...
  518. */
  519. /* Hack; some day fix to locate function start using symFindByValue */
  520. #define SYSBT_MAX_FUNC_WORDS    4096
  521. LOCAL void sysbt_addr2sym(char *symName, UINT addr)
  522. {
  523.     extern SYMTAB_ID sysSymTbl;
  524.     UINT symVal;
  525.     SYM_TYPE symType;
  526.     int                 rc;
  527. #if VX_VERSION==55
  528.     char                **psymName;
  529.     
  530.     rc = symByValueFind(sysSymTbl,
  531.        (UINT) addr,
  532.        psymName, &symVal, &symType);
  533.     if (rc != ERROR)
  534.         strcpy(symName, *psymName);        
  535. #else
  536.     rc = symFindByValue(sysSymTbl,
  537.        (UINT) addr,
  538.        symName, &symVal, &symType);
  539. #endif
  540.     if (rc == ERROR)
  541.         sprintf(symName, "0x%x", addr);
  542.     else if (symVal < addr)
  543. sprintf(symName + strlen(symName),
  544. " + 0x%x", addr - symVal);
  545.     else if (symVal > addr)
  546. sprintf(symName + strlen(symName),
  547. " - 0x%x", symVal - addr);
  548. }
  549. #define VALID_K0(addr) 
  550.         (IS_KSEG0(addr) && K0_TO_PHYS(addr) < K0_TO_PHYS(sysPhysMemTop()))
  551. #define VALID_K1(addr) 
  552.         (IS_KSEG1(addr) && K1_TO_PHYS(addr) < K0_TO_PHYS(sysPhysMemTop()))
  553. #define VALID_ADDR(addr) 
  554.         (VALID_K0(addr) || VALID_K1(addr))
  555. #define VALID_TEXT_ADDR(addr) 
  556.         VALID_ADDR(addr)        /* some day fix for text range */
  557. #define VALID_STACK_ADDR(addr) 
  558.         VALID_ADDR(addr)        /* some day fix for stack range */
  559. void sysBacktraceMips(char *pfx, char *sfx, int direct)
  560. {
  561.     UINT                *sp, *pc, *fn_start, *caller_sp, *ra;
  562.     extern UINT         *vxSpGet(), *vxPcGet();         /* sysALib.s */
  563.     int                 limit, first = 1;
  564.     char                buf[2048], symName[128], *s;
  565.     int                 ra_off, sp_off;
  566.     extern void         sysSerialPrintString(char *s);
  567.     sp = vxSpGet();
  568.     pc = vxPcGet();
  569.     s = buf;
  570.     strcpy(s, pfx);
  571.     while (*s) s++;
  572.     while (s < &buf[sizeof (buf) - 128]) {
  573.         fn_start = pc;
  574.         for (limit = 0; limit < SYSBT_MAX_FUNC_WORDS; limit++) {
  575.             /* sw $ra,x($sp); x>=0 */
  576.             if ((*--fn_start & 0xffff8000) == 0xafbf0000)
  577.                 break;
  578.         }
  579.         if (limit == SYSBT_MAX_FUNC_WORDS)
  580.             break;
  581.         ra_off = (*fn_start & 0x7fff);
  582.         for (limit = 0; limit < SYSBT_MAX_FUNC_WORDS; limit++) {
  583.             /* addiu $sp,$sp,-x; x<0 */
  584.             if ((*--fn_start & 0xffff8000) == 0x27bd8000)
  585.                 break;
  586.         }
  587.         if (limit == SYSBT_MAX_FUNC_WORDS)
  588.             break;
  589.         sp_off = (int) (*fn_start | 0xffff0000);
  590.         ra = (UINT *) sp[ra_off / 4];
  591.         caller_sp = sp - (sp_off / 4);
  592.         sysbt_addr2sym(symName, (UINT) pc);
  593.         if (! first)
  594.             sprintf(s,
  595.                     "FUNC = 0x%x, PC = 0x%x (%s), SP = 0x%xn",
  596.                     (UINT) fn_start, (UINT) pc, symName, (UINT) sp);
  597.         while (*s) s++;
  598.         if (! VALID_TEXT_ADDR(ra)) {
  599.             sprintf(s, "RA 0x%x out of rangen", (UINT) ra);
  600.             while (*s) s++;
  601.             break;
  602.         }
  603.         if (! VALID_STACK_ADDR(caller_sp)) {
  604.             sprintf(s, "Caller SP 0x%x out of rangen", (UINT) caller_sp);
  605.             while (*s) s++;
  606.             break;
  607.         }
  608.         pc = ra;
  609.         sp = caller_sp;
  610.         first = 0;
  611.     }
  612.     strcpy(s, sfx);
  613.     if (direct)
  614.         sysSerialPrintString(buf);      /* Atomically print giant string */
  615.     else {
  616.         fputs(buf, stdout);             /* Regular print giant string */
  617.         fflush(stdout);
  618.     }
  619. }
  620. #endif /* BROADCOM_BSP */
  621. /*******************************************************************************
  622. *
  623. * sysToMonitor - transfer control to the ROM monitor
  624. *
  625. * This routine transfers control to the ROM monitor.  Normally, it is called
  626. * only by reboot()--which services ^X--and bus errors at interrupt level.
  627. * However, in some circumstances, the user may wish to introduce a
  628. * <startType> to enable special boot ROM facilities.
  629. *
  630. * RETURNS: Does not return.
  631. */
  632. int sysToMonitorExcMessage = 0;
  633. int sysToMonitorBacktrace = 1;
  634. int sysToMonitorReboot = 1;
  635. void (*sysToMonitorHook)(void);
  636. STATUS sysToMonitor
  637.     (
  638.     int startType    /* parameter passed to ROM to tell it how to boot */
  639.     )
  640.     {
  641.     if (sysToMonitorHook)
  642.         (*sysToMonitorHook)();
  643.     if (sysToMonitorBacktrace)
  644.         sysBacktraceMips("n--- Stack Trace ---n", "", 1);
  645.     if (sysToMonitorReboot) {
  646.         FUNCPTR pRom = (FUNCPTR) (ROM_TEXT_ADRS + 8);
  647.         intLock();
  648.         /* no addition work necessary for the PRO100B */
  649.         (*pRom) (startType);
  650.     }
  651.     return (OK);    /* in case we ever continue from rom monitor */
  652.     }
  653. /******************************************************************************
  654. *
  655. * sysProcNumGet - get the processor number
  656. *
  657. * This routine returns the processor number for the CPU board, which is
  658. * set with sysProcNumSet().
  659. *
  660. * RETURNS: The processor number for the CPU board.
  661. *
  662. * SEE ALSO: sysProcNumSet()
  663. */
  664. int sysProcNumGet (void)
  665.     {
  666.     return (sysProcNum);
  667.     }
  668. /*******************************************************************************
  669. *
  670. * sysProcNumSet - set the processor number
  671. *
  672. * This routine sets the processor number for this board.  Processor numbers
  673. * should be unique on a single backplane.
  674. *
  675. * RETURNS: N/A
  676. *
  677. * SEE ALSO: sysProcNumGet()
  678. */
  679. void sysProcNumSet
  680.     (
  681.     int procNum
  682.     )
  683.     {
  684.     sysProcNum = procNum;
  685.     }
  686. /*
  687.  * Write characters to LCD display.
  688.  * Note that the bytes for the first character is the last address.
  689.  */
  690. void
  691. sysLedDsply(const char* msg)
  692. {
  693.     LED_REG(0) = msg[3];
  694.     LED_REG(1) = msg[2];
  695.     LED_REG(2) = msg[1];
  696.     LED_REG(3) = msg[0];
  697. }
  698. /*******************************************************************************
  699. *
  700. * sysBusEid - get the value of the error ID register
  701. *
  702. * This routine returns the contents of the bus error status register
  703. * (if one existed).
  704. *
  705. * NOTE:
  706. * This routine must be provided on all Rc32364 board support packages.
  707. *
  708. * RETURNS: 0, always.
  709. */
  710. USHORT sysBusEid (void)
  711.     {
  712.     return (0);
  713.     }
  714. /*******************************************************************************
  715. *
  716. * sysBusEar - get the access address of a bus error
  717. *
  718. * This routine returns the address of a bus error.
  719. *
  720. * NOTE:
  721. * This routine must be provided on all Rc32364 board support packages.
  722. * The IDT S134 cannot determine the address that caused
  723. * a bus error.  It is possible to determine the source of a read bus error
  724. * by interpreting the instruction stream that caused the bus error.
  725. *
  726. * RETURNS: -1, always.
  727. */
  728. ULONG sysBusEar (void)
  729.     {
  730.     return (-1);
  731.     }
  732. /*******************************************************************************
  733. *
  734. * sysAutoAck - acknowledge the RC32364 interrupt condition 
  735. *
  736. * This routine acknowledges an RC32364 interrupt for a specified interrupt
  737. * vector.
  738. *
  739. * NOTE:
  740. * This routine must be provided on all RC32364 board support packages.
  741. * Most interrupts are automatically acknowledged in the interrupt service
  742. * routine.
  743. *
  744. * RETURNS: The result of the interrupt acknowledge cycle.
  745. */
  746. int sysAutoAck
  747.     (
  748.     int vecNum          /* vector num of interrupt that bugs us */
  749.     )
  750.     {
  751.     int result;
  752.     result = 0;
  753.     switch (vecNum)
  754. {
  755. case IV_RTIME_VEC:
  756.     sysSetCompare (0);
  757.     break;
  758. case IV_SWTRAP0_VEC:            /* software trap 0 */
  759.     return(result = sysSw0Ack ());
  760.     break;
  761. case IV_SWTRAP1_VEC:            /* software trap 1 */
  762.     return(result = sysSw1Ack ());
  763.     break;
  764. default:
  765.     return (-1);
  766.     break;
  767. }
  768.     return (result);
  769.     }
  770. /*******************************************************************************
  771. *
  772. * sysSw0Gen - generate software interrupt 0
  773. *
  774. * This routine writes the RC32364 cause register to generate a software
  775. * interrupt.
  776. *
  777. * RETURNS: N/A
  778. */
  779. void sysSw0Gen (void)
  780.     {
  781.     unsigned causeReg;
  782.     causeReg = intCRGet ();
  783.     causeReg |= CAUSE_SW1;
  784.     intCRSet (causeReg);
  785.     }
  786. /*******************************************************************************
  787. *
  788. * sysSw1Gen - generate software interrupt 1
  789. *
  790. * This routine writes the RC32364 cause register to generate a software
  791. * interrupt.
  792. *
  793. * RETURNS: N/A
  794. */
  795. void sysSw1Gen (void)
  796.     {
  797.     unsigned causeReg;
  798.     causeReg = intCRGet ();
  799.     causeReg |= CAUSE_SW2;
  800.     intCRSet (causeReg);
  801.     }
  802. /*******************************************************************************
  803. *
  804. * sysSw0Ack - acknowledge software interrupt 0
  805. *
  806. * This routine writes the RC32364 cause register to acknowledge a software
  807. * interrupt.
  808. *
  809. * NOTE:
  810. * This routine is provided as a default interrupt service routine.
  811. *
  812. * RETURNS: N/A
  813. */
  814. LOCAL int sysSw0Ack (void)
  815.     {
  816.     unsigned causeReg;
  817.     causeReg = intCRGet ();
  818.     causeReg &= ~CAUSE_SW1;
  819.     intCRSet (causeReg);
  820.     return(OK);
  821.     }
  822. /*******************************************************************************
  823. *
  824. * sysSw1Ack - acknowledge software interrupt 1 
  825. *
  826. * This routine writes the RC32364 cause register to acknowledge a software
  827. * interrupt.
  828. *
  829. * NOTE:
  830. * This routine is provided as a default interrupt service routine.
  831. *
  832. * RETURNS: N/A
  833. */
  834. LOCAL int sysSw1Ack (void)
  835.     {
  836.     unsigned causeReg;
  837.     causeReg = intCRGet ();
  838.     causeReg &= ~CAUSE_SW2;
  839.     intCRSet (causeReg);
  840.     return(OK);
  841.     }
  842. /*****************************************************************************
  843. *
  844. * sysClkEnable - turn on system clock interrupts
  845. *
  846. * This routine enables system clock interrupts.
  847. *
  848. * RETURNS: N/A
  849. *
  850. * SEE ALSO: sysClkDisable(), sysClkRateSet()
  851. */
  852. void sysClkEnable (void)
  853.     {
  854.     /* start the timer */
  855.     int key;
  856.     
  857.     sysClkProcessorTicks = (get_sb_clock()/sysClkTicksPerSecond)/2;
  858.     key = intLock ();
  859.     sysSetCompare (0);
  860.     sysSetCount (1);
  861.     sysSetCompare (sysClkProcessorTicks);
  862.     sysSoftCompare = sysClkProcessorTicks;
  863.     sysClkRunning = TRUE;
  864.     intUnlock (key);
  865.     }
  866. /*****************************************************************************
  867. *
  868. * sysClkRateGet - get the system clock rate
  869. *
  870. * This routine returns the interrupt rate of the system clock.
  871. *
  872. * RETURNS: The number of ticks per second of the system clock.
  873. *
  874. * SEE ALSO: sysClkRateSet()
  875. */
  876. int sysClkRateGet (void)
  877.     {
  878.     return (sysClkTicksPerSecond);
  879.     }
  880. /*****************************************************************************
  881. *
  882. * sysClkRateSet - set the system clock rate
  883. *
  884. * This routine sets the interrupt rate of the system clock.  It does not
  885. * enable system clock interrupts.  Normally, it is called by usrRoot() in
  886. * usrConfig.c.
  887. *
  888. * NOTE
  889. * The RC32364 internal timer is used to provide the system clock.
  890. *
  891. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be
  892. * set.
  893. *
  894. * SEE ALSO: sysClkDisable(), sysClkEnable(), sysClkRateGet()
  895. */
  896. STATUS sysClkRateSet
  897.     (
  898.     int ticksPerSecond  /* number of clock interrupts per second */
  899.     )
  900.     {
  901.     if (ticksPerSecond < SYS_CLK_RATE_MIN || ticksPerSecond > SYS_CLK_RATE_MAX)
  902. return (ERROR);
  903.     sysClkTicksPerSecond = ticksPerSecond;
  904.     if (sysClkRunning)
  905. {
  906. sysClkDisable ();
  907. sysClkEnable ();
  908. }
  909.     return (OK);
  910.     }
  911. /*****************************************************************************
  912. *
  913. * sysClkInt - handle a system clock interrupt
  914. *
  915. * This routine handles a system clock interrupt.  
  916. *
  917. * RETURNS: N/A
  918. */
  919. LOCAL void sysClkInt (void)
  920.     {
  921.     int key;
  922.     ULONG delta;        /* time to when next interrupt should be */
  923.  
  924.     /* see sysClkDisable(). Clear interrupt and return. */
  925.     if (!sysClkRunning)
  926. {
  927. sysSetCompare (sysSoftCompare);
  928. return;
  929. }
  930.     key = intLock();
  931.     /* use unsigned arithmetic to compensate for wrap-around */
  932.     /* delta is how long ago the interrupt occured. */
  933.     delta = sysGetCount() - sysSoftCompare;
  934.     if (delta < (sysClkProcessorTicks - 200))
  935. {
  936.      /*
  937.       * case 1 (normal): we haven't missed the next interrupt.
  938.       *  The 200 above is an estimate of how far count will advance
  939.       *  between reading it above and setting the compare register
  940.       *  below (count should not pass the new compare value before
  941.       *  we've set the register).  sysClkProcessorTicks is on
  942.       *  the order of 500,000.
  943.       */
  944.      sysSoftCompare += sysClkProcessorTicks;
  945.      sysSetCompare (sysSoftCompare);
  946. }
  947.     else if (delta < (16 * sysClkProcessorTicks))
  948. {
  949.      /*
  950.       * case 2 (missed a couple): we've missed some interrupts,
  951.       *   don't set the compare register (so we'll take another
  952.       *   interrupt as soon as we return).
  953.       */
  954.      sysSoftCompare += sysClkProcessorTicks;
  955. }
  956.     else
  957. {
  958.      /*
  959.       * case 3 (missed a lot): set the next interrupt at
  960.       *   sysClkProcessorTicks past the current time.
  961.       */
  962.      sysSoftCompare = sysGetCount() + sysClkProcessorTicks;
  963.      sysSetCompare (sysSoftCompare);
  964. }
  965.     intUnlock (key);
  966.     if (sysClkRoutine != NULL)
  967. (*sysClkRoutine) (sysClkArg);
  968.     }
  969. /*****************************************************************************
  970. *
  971. * sysClkConnect - connect a routine to the system clock interrupt
  972. *
  973. * This routine specifies the interrupt handler to be called at each system
  974. * clock interrupt.  It does not enable system clock interrupts.  Normally,
  975. * it is called from usrRoot() in usrConfig.c to connect usrClock() to the
  976. * system clock interrupt.  Other standard interrupt handlers are also set up
  977. * at this time.
  978. *
  979. * RETURN: OK, or ERROR if the routine cannot be connected to the interrupt.
  980. *
  981. * SEE ALSO: intConnect(), usrClock()
  982. */
  983. STATUS sysClkConnect
  984.     (
  985.     FUNCPTR routine,    /* routine called at each system clock interrupt */
  986.     int arg             /* argument with which to call routine           */
  987.     )
  988.     {
  989.     if (sysClkConnected == FALSE)
  990. {
  991. sysHwInit2 ();
  992. sysClkConnected = TRUE;
  993. }
  994.     sysClkRoutine   = routine;
  995.     sysClkArg       = arg;
  996.     return (OK);
  997.     }
  998. /*****************************************************************************
  999. *
  1000. * sysClkDisable - turn off system clock interrupts
  1001. *
  1002. * This routine disables system clock interrupts.
  1003. *
  1004. * RETURNS: N/A
  1005. *
  1006. * SEE ALSO: sysClkEnable(), sysClkRateSet()
  1007. */
  1008. void sysClkDisable (void)
  1009.     {
  1010.     int key;
  1011.     
  1012.     /* we cannot disable interrupts so we do this instead... */
  1013.     key = intLock ();
  1014.     sysSetCompare (0);
  1015.     sysSetCount (1);
  1016.     sysClkProcessorTicks = 0xffffff00;
  1017.     sysSetCompare (sysClkProcessorTicks);
  1018.     sysSoftCompare = sysClkProcessorTicks;
  1019.     sysClkRunning = FALSE;
  1020.     intUnlock (key);
  1021.     }
  1022. /*******************************************************************************
  1023. *
  1024. * sysAuxClkInt - interrupt level processing for auxiliary clock
  1025. *
  1026. * This routine handles the auxiliary clock interrupt.  It is attached to the
  1027. * clock interrupt vector by the routine sysAuxClkConnect().
  1028. * The appropriate routine is called and the interrupt is acknowleged.
  1029. */
  1030. LOCAL void sysAuxClkInt (void)
  1031. {
  1032. uint32 intstatus;
  1033. intstatus = R_REG(&timerregs->intstatus) & I_TO;
  1034.     if (intstatus) {
  1035.         /* clear the timer interrupt */
  1036.      W_REG(&timerregs->intstatus, intstatus);
  1037.         
  1038.         if (sysAuxClkRoutine != NULL)
  1039.      (*sysAuxClkRoutine) (sysAuxClkArg);     
  1040.     }
  1041. }
  1042. /*******************************************************************************
  1043. *
  1044. * sysAuxClkConnect - connect a routine to the auxiliary clock interrupt
  1045. *
  1046. * This routine specifies the interrupt service routine to be called at each
  1047. * auxiliary clock interrupt.  It does not enable auxiliary clock
  1048. * interrupts.
  1049. *
  1050. * RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.
  1051. *
  1052. * SEE ALSO: intConnect(), sysAuxClkEnable()
  1053. */
  1054. STATUS sysAuxClkConnect
  1055.     (
  1056.     FUNCPTR routine,    /*routine called at each aux clock interrupt   */    
  1057.     int arg             /*argument to auxiliary clock interrupt routine*/ 
  1058.     )
  1059.     {
  1060.     if (!sysAuxClkConnected)
  1061. {
  1062. sysAuxClkConnected = TRUE;
  1063.     (void) intConnect (INUM_TO_IVEC(INT_VEC_IORQ3), sysAuxClkInt, 0);
  1064. }
  1065.     sysAuxClkRoutine = routine;
  1066.     sysAuxClkArg = arg;
  1067.     return (OK);
  1068.     }
  1069. /*******************************************************************************
  1070. *
  1071. * sysAuxClkDisable - turn off auxiliary clock interrupts
  1072. *
  1073. * This routine disables auxiliary clock interrupts.
  1074. *
  1075. * RETURNS: N/A
  1076. *
  1077. * SEE ALSO: sysAuxClkEnable()
  1078. */
  1079. void sysAuxClkDisable (void)
  1080.     {
  1081.         /* write a zero to disable the timer */
  1082.       W_REG( &timerregs->gptimer, 0);
  1083.       /* disable interrupts */
  1084.       W_REG( &timerregs->intmask, 0);
  1085.       
  1086.       sysAuxClkRunning = FALSE ;
  1087.     }
  1088. /*******************************************************************************
  1089. *
  1090. * sysAuxClkEnable - turn on auxiliary clock interrupts
  1091. *
  1092. * This routine enables auxiliary clock interrupts.
  1093. *
  1094. * RETURNS: N/A
  1095. *
  1096. * SEE ALSO: sysAuxClkConnect(), sysAuxClkDisable(), sysAuxClkRateSet()
  1097. */
  1098. void sysAuxClkEnable (void)
  1099.     {
  1100.     uint32 clock,core;
  1101.     sbconfig_t *sbregs;
  1102.     if (timerregs == NULL) {
  1103.         printf("No core was selected to provide a timern");
  1104.         printf("Use set_auxtimer(base_addr) to select a core.n");
  1105.         sysAuxClkRunning = FALSE ;
  1106.         return;
  1107.     }
  1108.     sbregs = (sbconfig_t*)((uint32)timerregs + SBCONFIGOFF);
  1109.     core = (sbregs->sbidhigh & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
  1110.     /* check if the core selected is the iLine core and set clock appropriately */
  1111.     if (core == SB_ILINE20) 
  1112.         clock = 64000000;
  1113.     else
  1114.         clock = get_sb_clock();
  1115.     /* write to the timer */
  1116.     W_REG( &timerregs->gptimer, get_sb_clock()/sysAuxClkTicksPerSecond);
  1117.     /* enable timer interrupt */
  1118.     W_REG( &timerregs->intmask, I_TO);
  1119.     sysAuxClkRunning = TRUE ;
  1120.     }
  1121. void set_auxtimer( uint32 base_addr )
  1122. {
  1123.     timerregs = (bcmenetregs_t *)base_addr;
  1124. }
  1125. void show_auxtimer( void ) {
  1126.     printf("Aux timer core base address is 0x%xn", (uint32)timerregs); 
  1127. }
  1128. /*******************************************************************************
  1129. *
  1130. * sysAuxClkRateGet - get the auxiliary clock rate
  1131. *
  1132. * This routine returns the interrupt rate of the auxiliary clock.
  1133. *
  1134. * RETURNS: The number of ticks per second of the auxiliary clock.
  1135. *
  1136. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateSet()
  1137. */
  1138. int sysAuxClkRateGet (void)
  1139.     {
  1140.     return (sysAuxClkTicksPerSecond);
  1141.     }
  1142. /*******************************************************************************
  1143. *
  1144. * sysAuxClkRateSet - set the auxiliary clock rate
  1145. *
  1146. * This routine sets the interrupt rate of the auxiliary clock.
  1147. * It does not enable auxiliary clock interrupts.
  1148. *
  1149. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be set.
  1150. *
  1151. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateGet()
  1152. */
  1153. STATUS sysAuxClkRateSet
  1154.     (
  1155.     int ticksPerSecond     /* number of clock interrupts per second*/ 
  1156.     )
  1157.     {
  1158.      if( ticksPerSecond < AUX_CLK_RATE_MIN || ticksPerSecond > AUX_CLK_RATE_MAX)
  1159.        {
  1160. return (ERROR);
  1161.        }
  1162.      sysAuxClkTicksPerSecond = ticksPerSecond ;
  1163.      
  1164.      if ( sysAuxClkRunning )
  1165. {
  1166.   sysAuxClkDisable();
  1167.   sysAuxClkEnable();
  1168. }
  1169.       return (OK);
  1170.     }
  1171. /*
  1172.  * Reboot system.
  1173.  */
  1174. void sysReboot(void)
  1175. {
  1176.     SYS_HARD_RESET();
  1177. }
  1178. #ifdef INCLUDE_TIMESTAMP
  1179.      /* Timestamp routines derived from srcdrvtimermipsR4kTimer.c */
  1180. /*******************************************************************************
  1181. *
  1182. * sysTimestampConnect - connect a user routine to a timestamp timer interrupt
  1183. *
  1184. * This routine specifies the user interrupt routine to be called at each
  1185. * timestamp timer interrupt.
  1186. *
  1187. * RETURNS: ERROR, always.
  1188. */
  1189. STATUS sysTimestampConnect
  1190.     (
  1191.     FUNCPTR routine,    /* routine called at each timestamp timer interrupt */
  1192.     int arg             /* argument with which to call routine */
  1193.     )
  1194.     {
  1195.     return (ERROR);
  1196.     }
  1197. /*******************************************************************************
  1198. *
  1199. * sysTimestampEnable - enable a timestamp timer interrupt
  1200. *
  1201. * This routine enables timestamp timer interrupts and resets the counter.
  1202. *
  1203. * RETURNS: OK, always.
  1204. *
  1205. * SEE ALSO: sysTimestampDisable()
  1206. */
  1207. STATUS sysTimestampEnable (void)
  1208.    {
  1209.    if (sysTimestampRunning)
  1210.       {
  1211.       return (OK);
  1212.       }
  1213.    if (!sysClkRunning)
  1214.       return (ERROR);
  1215.    sysTimestampRunning = TRUE;
  1216.    return (OK);
  1217.    }
  1218. /*******************************************************************************
  1219. *
  1220. * sysTimestampDisable - disable a timestamp timer interrupt
  1221. *
  1222. * This routine disables timestamp timer interrupts.
  1223. *
  1224. * RETURNS: OK, always.
  1225. *
  1226. * SEE ALSO: sysTimestampEnable()
  1227. */
  1228. STATUS sysTimestampDisable (void)
  1229.     {
  1230.     if (sysTimestampRunning)
  1231.         sysTimestampRunning = FALSE;
  1232.     return (OK);
  1233.     }
  1234. /*******************************************************************************
  1235. *
  1236. * sysTimestampPeriod - get the period of a timestamp timer
  1237. *
  1238. * This routine gets the period of the timestamp timer, in ticks.  The
  1239. * period, or terminal count, is the number of ticks to which the timestamp
  1240. * timer counts before rolling over and restarting the counting process.
  1241. *
  1242. * RETURNS: The period of the timestamp timer in counter ticks.
  1243. */
  1244. UINT32 sysTimestampPeriod (void)
  1245.     {
  1246.     /*
  1247.      * The period of the timestamp depends on the clock rate of the on-chip
  1248.      * timer.
  1249.      */
  1250.     return (get_sb_clock()/sysClkTicksPerSecond)/2;
  1251.     }
  1252. /*******************************************************************************
  1253. *
  1254. * sysTimestampFreq - get a timestamp timer clock frequency
  1255. *
  1256. * This routine gets the frequency of the timer clock, in ticks per
  1257. * second.  The rate of the timestamp timer is set explicitly by the
  1258. * hardware and typically cannot be altered.
  1259. *
  1260. * RETURNS: The timestamp timer clock frequency, in ticks per second.
  1261. */
  1262. UINT32 sysTimestampFreq (void)
  1263.     {
  1264.     return (get_sb_clock()/2);
  1265.     }
  1266. /*******************************************************************************
  1267. *
  1268. * sysTimestamp - get a timestamp timer tick count
  1269. *
  1270. * This routine returns the current value of the timestamp timer tick counter.
  1271. * The tick count can be converted to seconds by dividing it by the return of
  1272. * sysTimestampFreq().
  1273. *
  1274. * This routine should be called with interrupts locked.  If interrupts are
  1275. * not locked, sysTimestampLock() should be used instead.
  1276. *
  1277. * RETURNS: The current timestamp timer tick count.
  1278. *
  1279. * SEE ALSO: sysTimestampFreq(), sysTimestampLock()
  1280. */
  1281. UINT32 sysTimestamp (void)
  1282.     {
  1283.     return (sysGetCount() - (sysSoftCompare - sysClkProcessorTicks) + 1);
  1284.     }
  1285. /*******************************************************************************
  1286. *
  1287. * sysTimestampLock - lock interrupts and get the timestamp timer tick count
  1288. *
  1289. * This routine locks interrupts when the tick counter must be stopped
  1290. * in order to read it or when two independent counters must be read.
  1291. * It then returns the current value of the timestamp timer tick
  1292. * counter.
  1293. *
  1294. * The tick count can be converted to seconds by dividing it by the return of
  1295. * sysTimestampFreq().
  1296. *
  1297. * If interrupts are already locked, sysTimestamp() should be
  1298. * used instead.
  1299. *
  1300. * RETURNS: The current timestamp timer tick count.
  1301. *
  1302. * SEE ALSO: sysTimestampFreq(), sysTimestamp()
  1303. */
  1304. UINT32 sysTimestampLock (void)
  1305.     {
  1306.     return(sysGetCount() - (sysSoftCompare - sysClkProcessorTicks)+ 1);
  1307.     }
  1308. #endif  /* INCLUDE_TIMESTAMP */
  1309. /*******************************************************************************
  1310. *
  1311. * sysMaskVmeErr - mask the VMEbus error interrupt
  1312. *
  1313. * This routine is required for all RC32364 BSPs.  It has no effect on the
  1314. * S134.
  1315. *
  1316. * RETURNS: 0.
  1317. *
  1318. * NOMANUAL
  1319. */
  1320. UINT8 sysMaskVmeErr (void)
  1321.     {
  1322.     return (0);
  1323.     }
  1324. /*******************************************************************************
  1325. *
  1326. * sysUnmaskVmeErr - unmask the VMEbus error interrupt
  1327. *
  1328. * This routine is required for all RC32364 BSPs.  It has no effect on the
  1329. * S134.
  1330. *
  1331. * RETURNS: 0.
  1332. *
  1333. * NOMANUAL
  1334. */
  1335. UINT8 sysUnmaskVmeErr (void)
  1336.     {
  1337.     return (0);
  1338.     }
  1339. /******************************************************************************
  1340. *
  1341. * sysEnetAddrGet - read the ethernet address from NVRAM
  1342. *
  1343. * This routine returns the system ethernet address from flash.
  1344. * If more than one ethernet driver is installed, the ethernet address
  1345. * will be the unit number added to the system ethernet address (unit 0).
  1346. *
  1347. * RETURNS: OK if flash read successful and enet addr isn't garbage
  1348. *          ERROR if flash read fails or enet addr is all 0's or all f's
  1349. *
  1350. */
  1351. STATUS sysEnetAddrGet
  1352.     (
  1353.     char *dev,          /* name of device, e.g. "bc" */
  1354.     int unit,           /* unit number */
  1355.     unsigned char *pMac         /* where to write the mac address */
  1356.     )
  1357.     {
  1358.     int i;
  1359.     int allzeros;
  1360.     int allfs;
  1361.     if (dev == NULL)
  1362.         return (ERROR);
  1363.     if (strcmp ("phy", dev) == 0)
  1364.         {
  1365.         if (unit != 0 && unit != 1)
  1366.             return (ERROR);
  1367.         if (unit == 0) 
  1368.            * (int *) pMac = (sysIsLM() ? ET1_PHYADDR:ET0_PHYADDR);
  1369.         else
  1370.            * (int *) pMac = (sysIsLM() ? ET0_PHYADDR:ET1_PHYADDR);
  1371.         return (OK);
  1372.         }
  1373.     if (strcmp ("mdc", dev) == 0)
  1374.         {
  1375.         if (unit != 0 && unit != 1)
  1376.             return (ERROR);
  1377.         if (unit == 0)
  1378.            * (int *) pMac = ET0_MDCPORT;
  1379.         else
  1380.            * (int *) pMac = ET1_MDCPORT;
  1381.         return (OK);
  1382.         }
  1383.     if (sysNvRamGet(pMac, 6, NV_OFF_MACADDR) == ERROR)
  1384.         return (ERROR);
  1385.     /*
  1386.      * Check what we got from NVRAM.  If it looks fishy, return ERROR
  1387.      */
  1388.     allzeros = 1;
  1389.     allfs = 1;
  1390.     for (i = 0; i < 6; i++)
  1391.         {
  1392.         if (pMac[i] == '')
  1393.             {
  1394.             if (allzeros)
  1395.                 continue;
  1396.             else
  1397.                 goto goodmac;
  1398.             }
  1399.         else if (pMac[i] == (unsigned char) 0xff)
  1400.             {
  1401.             if (allfs)
  1402.                 continue;
  1403.             else
  1404.                 goto goodmac;
  1405.             }
  1406.         else
  1407.             goto goodmac;
  1408.         }
  1409.     return (ERROR);
  1410. goodmac:
  1411.     pMac[5] = pMac[5] + unit;
  1412.     return (OK);
  1413.     }
  1414. #ifndef INCLUDE_FLASH
  1415. /*
  1416. *  This call is here because the xmodem code calls flashFsSync().
  1417. *  flashFsSync() is normally defined in flashFsLib, but MBZ uses
  1418. *  the DOC, not a flash array.
  1419. */
  1420. STATUS flashFsSync(void)
  1421.     {
  1422.     return (OK);
  1423.     }
  1424. #endif /* INCLUDE_FLASH */
  1425. /* Detect HHB4 / DC21150 PCI-PCI bridge chips, and configure bus if
  1426.  * found. Note that this code should be run whenever we find a PCI
  1427.  * class code of type bridge. After we have run this procedure for the
  1428.  * first bridge, we then need to traverse any sub-bridges. This code
  1429.  * deals with only one PCI-PCI bridge and it's IO space for
  1430.  * sub-devices. See mousse.h for more details as well as the PCI-PCI
  1431.  * bridge specification.
  1432.  */
  1433. int sysPCIBridgeProbe(int instance,
  1434.                       int primary,
  1435.                       int secondary,
  1436.                       int subordinate)
  1437. {
  1438.     int BusNo, DevNo, FuncNo;
  1439.     unsigned int buses = 0;
  1440.     /* Find DC21150 PCI-PCI bridge or
  1441.      * HINTCORP HB4 PCI-PCI Bridge
  1442.      */
  1443.     if ( (pciFindDevice(DC21150_VENDOR_ID,
  1444.                         DC21150_DEVICE_ID,
  1445.                         instance,
  1446.                         &BusNo, &DevNo, &FuncNo) != ERROR) ||
  1447.          (pciFindDevice(PERICOM_VENDOR_ID,
  1448.                         PERICOM_8150_DEV_ID,
  1449.                         instance,
  1450.                         &BusNo, &DevNo, &FuncNo) != ERROR) ||
  1451.          (pciFindDevice(HINT_HB4_VENDOR_ID,
  1452.                         HINT_HB4_DEVICE_ID,
  1453.                         instance,
  1454.                         &BusNo, &DevNo, &FuncNo) != ERROR)) {
  1455.         pciMaxBus++;
  1456.         /* Disable device */
  1457.         pciConfigOutWord(BusNo,DevNo,FuncNo, PCI_CFG_COMMAND, 0x0000);
  1458.         pciConfigOutWord(BusNo,DevNo,FuncNo, PCI_CFG_STATUS, 0xffff);
  1459.         /* Reset secondary bus */
  1460.         pciConfigOutWord(BusNo,DevNo,FuncNo,
  1461.                          PCI_CFG_BRIDGE_CONTROL,
  1462.                          0x0040);
  1463.         /* Setup topology info */
  1464.         buses = (buses & 0xff000000)
  1465.             | ((unsigned int)(primary)     <<  0)
  1466.             | ((unsigned int)(secondary)   <<  8)
  1467.             | ((unsigned int)(subordinate) << 16);
  1468.         /*
  1469.          * We need to blast all three values with a single write.
  1470.          */
  1471.         pciConfigOutLong(BusNo, DevNo, FuncNo,
  1472.                          PCI_CFG_PRIMARY_BUS, buses);
  1473.         /* Clear secondary status */
  1474.         pciConfigOutWord(BusNo,DevNo,FuncNo,
  1475.                          PCI_CFG_SEC_STATUS, 0xffff);
  1476.         /* Setup memory address space mapping */
  1477.         pciConfigOutWord(BusNo,DevNo,FuncNo,
  1478.                          PCI_CFG_MEM_BASE,
  1479.                          ((P2P_NONPREF_MEM_BASE & 0xFFF00000) >> 16));
  1480.         pciConfigOutWord(BusNo,DevNo,FuncNo,
  1481.                          PCI_CFG_MEM_LIMIT,
  1482.                          ((P2P_NONPREF_MEM_BASE +
  1483.                            P2P_NONPREF_MEM_SIZE - 1) & 0xFFF00000) >> 16);
  1484.         /* Clear bridge control */
  1485.         pciConfigOutWord(BusNo,DevNo,FuncNo,
  1486.                          PCI_CFG_BRIDGE_CONTROL,0x0000);
  1487.         /* Enable PCI clocks on remote end */
  1488.         pciConfigOutWord(BusNo,DevNo,FuncNo,
  1489.                          PCI_CFG_DEC21150_SEC_CLK,
  1490.                          P2P_CLK_ENABLE);
  1491.         /* Clear status */
  1492.         pciConfigOutByte(BusNo,DevNo,FuncNo,
  1493.                          PCI_CFG_DEC21150_SERR_STAT, 0xff);
  1494.         /* Clear status */
  1495.         pciConfigOutWord(BusNo,DevNo,FuncNo,
  1496.                          PCI_CFG_STATUS, 0xffff);
  1497.         /* Re-enable config space */
  1498.         pciConfigOutWord(BusNo,DevNo,FuncNo, PCI_CFG_COMMAND,
  1499.                          P2P_PMC_ENABLE);
  1500.         return OK;
  1501.     }
  1502.     return ERROR;
  1503. }
  1504. /*
  1505. *  Stub required because we're using vxMemProbe
  1506. */
  1507. BOOL sysBusTas(char * address)
  1508.     {
  1509.     return(TRUE);
  1510.     }
  1511. UINT8 sysBoardRev()
  1512. {
  1513.     return (SYS_REVID_GET());
  1514. }
  1515. int sysTodGetSecond (void)
  1516.     {
  1517.     if (sysTodFuncs.getSecond == NULL)
  1518.         return -1;
  1519.     else
  1520.         return (sysTodFuncs.getSecond ());
  1521.     }
  1522. STATUS sysTodGet
  1523.     (
  1524.     int *pYear,
  1525.     int *pMonth,
  1526.     int *pDay,
  1527.     int *pHour,
  1528.     int *pMin,
  1529.     int *pSec 
  1530.     )
  1531.     {
  1532.     if (sysTodFuncs.get == NULL)
  1533.         return (ERROR);
  1534.     else
  1535.         return (sysTodFuncs.get (pYear, pMonth, pDay, pHour, pMin, pSec));
  1536.     }
  1537. STATUS sysTodSet
  1538.     (
  1539.     int year,
  1540.     int month,
  1541.     int day,
  1542.     int hour,
  1543.     int min,
  1544.     int sec 
  1545.     )
  1546.     {
  1547.     if (sysTodFuncs.set == NULL)
  1548.         return (ERROR);
  1549.     else
  1550.         return (sysTodFuncs.set (year, month, day, hour, min, sec));
  1551.     }
  1552. STATUS sysTodInit (UINT8 *addr)
  1553.     {
  1554.     if (sysTodFuncs.init == NULL)
  1555.         return (ERROR);
  1556.     else
  1557.         return (sysTodFuncs.init (addr));
  1558.     }
  1559. STATUS sysTodWatchdogArm
  1560.     (
  1561.     int usec
  1562.     )
  1563.     {
  1564.     if (sysTodFuncs.watchdogArm == NULL)
  1565.         return (ERROR);
  1566.     else
  1567.         return (sysTodFuncs.watchdogArm (usec));
  1568.     }
  1569. /*****************************************************************************
  1570. *
  1571. * sysSerialPrintStringNL - print string and add newline
  1572. *
  1573. * This routine should only be used as alternative to sysLedDsply, as
  1574. * part of the BPRINT() mechanism for debugging bootroms or board bringup.
  1575. *
  1576. * Returns:  N/A
  1577. */
  1578. void sysSerialPrintStringNL
  1579.     (
  1580.     char *s
  1581.     )
  1582.     {
  1583.     sysSerialPrintString (s);
  1584.     sysSerialPrintString ("nr");
  1585.     }
  1586. void sys47xxClocks(int *core, int *sb, int *pci)
  1587. {
  1588.     volatile int *p;
  1589.     p = (volatile int *)(KSEG1ADDR((BCM4710_REG_EXTIF + 0x44)));
  1590.     switch(*p) {
  1591.         case (CC_125_N) :   *core = 125; break;
  1592.         case (CC_DEF_N) :   *core = 100; break;
  1593.         default:            *core = 0; break;
  1594.     }
  1595.     p = (volatile int *)(KSEG1ADDR((BCM4710_REG_EXTIF + 0x48)));
  1596.     switch(*p) {
  1597.         case (CC_125_M) :   *sb = 125; break;
  1598.         case (CC_DEF_100) : *sb = 100; break;
  1599.         default:            *sb = 0; break;
  1600.     }
  1601.     p = (volatile int *)(KSEG1ADDR((BCM4710_REG_EXTIF + 0x4c)));
  1602.     switch(*p) {
  1603.         case (CC_DEF_33) :   *pci = 33; break;
  1604.         case (CC_125_M33) :   *pci = 33; break;
  1605.         case (CC_DEF_25) :   *pci = 25; break;
  1606.         case (CC_125_M25) :   *pci = 25; break;
  1607.         default:            *pci = 0; break;
  1608.     }
  1609. }
  1610. /* Line module specific */
  1611. int sysSlotIdGet();
  1612. int sysIsLM();
  1613. int
  1614. sysSlotIdGet()
  1615. {
  1616.     if (sysIsLM()) {
  1617.         return (SYS_SLOTID_GET() + 2);
  1618.     } else {
  1619.         return(2);
  1620.     }
  1621. }
  1622. int
  1623. sysIsLM()
  1624. {
  1625.     unsigned int id;
  1626.     id = SYS_REVID_GET();
  1627.     return(id == BOARD_ID_LM_1_32MB);
  1628. }