smUtilLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:16k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* smUtilLib.c - VxWorks shared memory utility library */
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01l,03may02,mas  cache flush and volatile fix (SPR 68334); bridge flush fix
  7.  (SPR 68844)
  8. 01k,24oct01,mas  fixed diab warnings (SPR 71120); doc update (SPR 71149)
  9. 01j,23nov99,tm    smUtilIntConnect() now returns OK for USER_1/2 (SPR 29548)
  10. 01i,17mar99,dat   added SM_INT_USER_1 and SM_INT_USER_2, spr 25804
  11. 01h,08feb96,dat   fixed smUtilSoftTas, SPR #5888, fixed some
  12.   compiler warnings.
  13. 01g,12oct94,ism   added philm's workaround for SPR#2578
  14. 01f,12feb93,jdi   fixed parameter comments in smUtilIntGen() to keep mangen
  15.   happy -- in case we ever publish this one.
  16. 01e,23jun92,elh   cleanup, documentation.
  17. 01d,02jun92,elh   the tree shuffle
  18.   -changed includes to have absolute path from h/
  19. 01c,27may92,elh   fixed bug in smUtilIntRoutine && smUtilPollTask.
  20. 01b,15may92,pme   added smUtilIntConnect, smUtilIntRoutine, smUtilPollTask.
  21. 01a,07feb92,elh   created.
  22. */
  23. /*
  24. DESCRIPTION
  25. This module is the shared memory utility library.  It contains the 
  26. routines needed of VxWorks by the shared memory libraries (smPktLib,
  27. smObjLib and smLib).  
  28. To fully support this library, a BSP and the associated architecture must have
  29. support for the following system calls: vxMemProbe(), sysClkRateGet(),
  30. sysProcNumGet(), sysBusTas(), sysBusIntGen(), sysBusToLocalAdrs(),
  31. sysMailboxConnect(), and sysMailboxEnable().
  32. INTERNAL
  33. SunOS is no longer supported.
  34. Refer to smLib for more information about the layering of shared 
  35. memory modules.
  36. SEE ALSO: if_sm, smPktLib, smLib, smObjLib
  37. */
  38. /* includes */
  39. #include "vxWorks.h"
  40. #include "smLib.h"
  41. #include "smUtilLib.h"
  42. #include "netinet/in.h"
  43. #include "iv.h"
  44. #include "vxLib.h"
  45. #include "taskLib.h"
  46. #include "cacheLib.h"
  47. #include "logLib.h"
  48. #include "intLib.h"
  49. #include "stdio.h"
  50. #include "stdlib.h"
  51. #include "sysLib.h"
  52. /* defines */
  53. #define DEFAULT_TAS_CHECKS 10 /* rechecks for soft tas */
  54. #define TAS_CONST 0x80
  55. /* globals */
  56. int  smUtilVerbose   = FALSE; /* verbose mode */
  57. int  smUtilTasChecks = DEFAULT_TAS_CHECKS;
  58. VOIDFUNCPTR smUtilTasClearRtn = NULL;
  59. FUNCPTR smUtilUser1Rtn = NULL; /* returns STATUS */
  60. FUNCPTR smUtilUser2Rtn = NULL; /* returns STATUS */
  61. /* number of times to recheck soft tas */
  62. /* list of shared memory event handling routines */
  63. SM_ROUTINE  smUtilNetRoutine = { NULL, 0};
  64. SM_ROUTINE  smUtilObjRoutine = { NULL, 0};
  65. /* poll task parameters */
  66. int      smUtilPollTaskStackSize   = 0x2000;       /* stack size */
  67. int      smUtilPollTaskOptions     = 0;            /* options */
  68. int      smUtilPollTaskPriority    = 254;          /* priority */
  69. /* locals */
  70. LOCAL int smUtilTasValue = 0; /* special soft tas value */
  71. LOCAL int   smUtilPollTaskID;               /* polling task id */
  72. /* forwards */
  73. LOCAL void  smUtilPollTask (void);
  74. /*****************************************************************************
  75. *
  76. * smUtilSoftTas - software emulation of test-and-set function
  77. *
  78. * This routine emulates an inidivisable hardware test-and-set function.
  79. * The lock specified by <lockLocalAdrs> is read to confirm that it is
  80. * initially zero.  The lock is then set to a special value used only by
  81. * this cpu, and is repeatedly re-read to check if any other processor
  82. * has attempted to obtain access to the lock.  If no such conflict is
  83. * detected, this routine returns TRUE.
  84. *
  85. * The number of checks made after setting the lock value may be changed
  86. * by setting the global variable, smUtilTasChecks.  The default number
  87. * is 10.
  88. *
  89. * All the above is performed with interrupts disabled on the local processor.
  90. *
  91. * RETURNS: TRUE if value successfully set (was previously not set), or
  92. * FALSE if value already set or another CPU stole lock.
  93. */
  94. BOOL smUtilSoftTas
  95.     (
  96.     volatile int * lockLocalAdrs /* local address of lock variable */
  97.     )
  98.     {
  99.     int value; /* value to place in lock variable */
  100.     int nChecks; /* number of times to re-check lock */
  101.     int count; /* running count of re-checks */
  102.     int oldLvl; /* previous interrupt level */
  103.     int tmp;                    /* temp storage */
  104.     if (smUtilTasValue == 0)
  105.         {
  106. smUtilTasValue =  htonl ((TAS_CONST + sysProcNumGet())<< 24);
  107.         }
  108.     value   = smUtilTasValue; /* special value to write */
  109.     nChecks = smUtilTasChecks; /* number of checks to do */
  110.     /* Lock out interrupts */
  111.     oldLvl = intLock ();
  112.     /* Test that lock variable is initially empty */
  113.     CACHE_PIPE_FLUSH ();                        /* CACHE FLUSH   [SPR 68334] */
  114.     tmp = *lockLocalAdrs;                       /* PCI bridge bug [SPR 68844]*/
  115.     if (*lockLocalAdrs != 0)
  116. {
  117. intUnlock (oldLvl);
  118. return (FALSE); /* someone else has lock */
  119. }
  120.     /* Set lock value */
  121.     *lockLocalAdrs = value;
  122.     /* preliminary read compensates for PCI bridge failure (SPR 68844) */
  123.     CACHE_PIPE_FLUSH ();                        /* CACHE FLUSH   [SPR 68334] */
  124.     count = *lockLocalAdrs;
  125.     /* Check that no one else is trying to take lock */
  126.     for (count = 0;  count < nChecks;  count++)
  127. {
  128. if (*lockLocalAdrs != value)
  129.     {
  130.     intUnlock (oldLvl);
  131.     return (FALSE); /* someone else stole lock */
  132.     }
  133. }
  134.     intUnlock (oldLvl);
  135.     return (TRUE); /* exclusive access obtained */
  136.     }
  137. /*****************************************************************************
  138. *
  139. * smUtilDelay - delay 
  140. *
  141. * This routine delays task execution by <ticks> number of system clock ticks.
  142. *
  143. * RETURNS: OK if successful, otherwise ERROR. 
  144. */
  145. STATUS smUtilDelay
  146.     (
  147.     char * pAddr, /* address [not used] */
  148.     int  ticks            /* number of ticks to delay */
  149.     )
  150.     {
  151.     /* appease the Diab gods (SPR 71120) */
  152.     if (pAddr == NULL)
  153.         ;
  154.     return (taskDelay (ticks));
  155.     }
  156. /*****************************************************************************
  157. *
  158. * smUtilMemProbe - probe memory
  159. *
  160. * This routine safely probes a location in memory.  
  161. *
  162. * RETURNS:
  163. * OK if the probe is successful, or ERROR if the probe caused a bus error or
  164. * an address misalignment.
  165. */
  166. STATUS smUtilMemProbe
  167.     (
  168.     char * pAddr,    /* address to be probed          */
  169.     int  op,    /* VX_READ or VX_WRITE           */
  170.     int  size,     /* 1, 2, or 4                    */
  171.     char * pVal      /* where to return value,        */
  172.                           /* or ptr to value to be written */
  173.     )
  174.     {
  175.     if (smUtilVerbose)
  176.         {
  177. printf ("smUtilMemProbe:op[%s] addr:[0x%x] size:[%d]n", 
  178. (op == VX_READ) ? "read" : "write", (UINT) pAddr, size);
  179.         }
  180.     return (vxMemProbe (pAddr, op, size, pVal));
  181.     }
  182. /*****************************************************************************
  183. *
  184. * smUtilRateGet - get the system clock rate
  185. *
  186. * This routine calls the BSP-specific routine sysClkRateGet() which returns
  187. * the local system clock rate in ticks per second.
  188. *
  189. * RETURNS: The number of ticks per second of the system clock.
  190. */
  191. int smUtilRateGet (void)
  192.     {
  193.     return (sysClkRateGet ());
  194.     }
  195. /*****************************************************************************
  196. *
  197. * smUtilProcNumGet - get the processor number
  198. *
  199. * This routine calls the BSP-specific routine sysProcNumGet() which returns
  200. * the number assigned to the local CPU.
  201. *
  202. * RETURNS: The processor number for this CPU board.
  203. */
  204. int smUtilProcNumGet (void)
  205.     {
  206.     return (sysProcNumGet ());
  207.     }
  208. /*****************************************************************************
  209. *
  210. * smUtilTas - shared memory hardware test-and-set function
  211. *
  212. * This routine calls the BSP-specific TAS routine sysBusTas() which performs
  213. * an atomic test-and-set (TAS) on the specified address <adrs>.
  214. *
  215. * RETURNS: TRUE if the value had not been set but is now, or
  216. * FALSE if the value was set already.
  217. */
  218. BOOL smUtilTas
  219.     (
  220.     char * adrs /* address to be tested and set */
  221.     )
  222.     {
  223.     return (sysBusTas (adrs));
  224.     }
  225. /*****************************************************************************
  226. *
  227. * smUtilTasClear - shared memory clear hardware test-and-set function
  228. *
  229. * This routine calls a TAS clear routine through the hook 'smUtilTasClearRtn'
  230. * if it is not NULL, else, it clears the address <adrs> itself.
  231. *
  232. * INTERNAL
  233. * The function pointer smUtilTasClearRtn is currently set by the BSPs
  234. * if a test-and-set clear routine is required of the board support package.
  235. * Ultimately, the desired solution is that each BSP will provide a
  236. * sysBusTasClear routine that can be called directly from smUtilTasClear().
  237. *
  238. * RETURNS: N/A
  239. */
  240. void smUtilTasClear
  241.     (
  242.     char * adrs /* address to be tested and set */
  243.     )
  244.     {
  245.     int         tmp;            /* temp storage */
  246.     if (smUtilTasClearRtn != NULL)
  247.         {
  248. (*smUtilTasClearRtn) (adrs);
  249.         }
  250.     else
  251.         {
  252. *adrs = 0;
  253.         CACHE_PIPE_FLUSH ();                    /* CACHE FLUSH   [SPR 68334] */
  254.         tmp = *adrs;                            /* BRIDGE FLUSH  [SPR 68334] */
  255.         }
  256.     }
  257. /*****************************************************************************
  258. *
  259. * smUtilIntGen - interrupt the destination cpu.
  260. *
  261. * smUtilIntGen() gets called by the shared memory libraries to interrupt a
  262. * CPU to notify it of an incoming packet or an event.  smUtilIntGen() provides
  263. * the following methods for interrupting the destination CPU:
  264. * mail box interrupts (SM_INT_MAILBOX), bus interrupts (SM_INT_BUS), user
  265. * defined procedure 1 (SM_INT_USER1), user defined procedure 2 (SM_INT_USER2),
  266. * and none (SM_INT_NONE).  Refer to smLib.h for the actual values.
  267. * RETURNS: OK if successful, otherwise ERROR.
  268. */
  269. STATUS smUtilIntGen
  270.     (
  271.     SM_CPU_DESC * pCpuDesc, /* local addr of destination */
  272. /* cpu descriptor */
  273.     int cpuNum  /* destination cpu number */
  274.     )
  275.     {
  276.     volatile int bogus; /* bogus space */
  277.     char *  pMailbox = NULL;/* mailbox */
  278.     int intType; /* interrupt type */
  279.     int intArg1;
  280.     int intArg2;
  281.     int intArg3;
  282.     /* appease the Diab gods (SPR 71120) */
  283.     if (cpuNum == 0)
  284.         ;
  285.     intType = ntohl (pCpuDesc->intType); /* byte swap */
  286.     /* polling needs no arguments */
  287.     if (intType == SM_INT_NONE)
  288.         {
  289.      return (OK); /* destination polling */
  290.         }
  291.     /* Bus interrupts use 2 arguments */
  292.     intArg1 = ntohl (pCpuDesc->intArg1);
  293.     intArg2 = ntohl (pCpuDesc->intArg2);
  294.     if (intType == SM_INT_BUS)
  295. {
  296. return (sysBusIntGen (intArg1, intArg2));
  297. }
  298.     /* all other methods use all 3 arguments */
  299.     intArg3 = ntohl (pCpuDesc->intArg3);
  300.     if ((intType >= SM_INT_MAILBOX_1) && (intType <= SM_INT_MAILBOX_R4))
  301. {
  302. /* For mailboxes, arg1 is addrSpaceId, arg2 is address */
  303. if (sysBusToLocalAdrs (intArg1, (char *) intArg2, &pMailbox) == ERROR)
  304.     {
  305.     if (smUtilVerbose)
  306.         {
  307. logMsg ("smUtilIntGen:unable to calculate mailbox [0x%x]n",
  308. intArg2, 0, 0, 0, 0, 0);
  309.         }
  310.     return (ERROR);
  311.     }
  312. }
  313.     switch (intType)
  314. {
  315.      case SM_INT_MAILBOX_1:
  316.     *pMailbox = (char) intArg3;
  317.             CACHE_PIPE_FLUSH ();                 /* CACHE FLUSH  [SPR 68334] */
  318.     bogus = *(volatile char *) pMailbox; /* BRIDGE FLUSH [SPR 68334] */
  319.     break;
  320.      case SM_INT_MAILBOX_2:
  321.     *(short *) pMailbox = (short) intArg3;
  322.             CACHE_PIPE_FLUSH ();                 /* CACHE FLUSH  [SPR 68334] */
  323.     bogus = *(volatile short *) pMailbox; /* BRIDGE FLUSH [SPR 68334]*/
  324.     break;
  325.       case SM_INT_MAILBOX_4:
  326.     *(long *) pMailbox = (long) intArg3;
  327.             CACHE_PIPE_FLUSH ();                 /* CACHE FLUSH  [SPR 68334] */
  328.     bogus = *(volatile long *) pMailbox; /* BRIDGE FLUSH [SPR 68334] */
  329.     break;
  330.      case SM_INT_MAILBOX_R1:
  331.     bogus = *(volatile char *) pMailbox;
  332.     break;
  333.      case SM_INT_MAILBOX_R2:
  334.     bogus = *(volatile short *) pMailbox;
  335.     break;
  336.      case SM_INT_MAILBOX_R4:
  337.     bogus = *(volatile long *) pMailbox;
  338.     break;
  339. case SM_INT_USER_1:
  340.     if (smUtilUser1Rtn != NULL)
  341.         {
  342. return (*smUtilUser1Rtn)(intArg1, intArg2, intArg3);
  343.         }
  344.     return ERROR;
  345. case SM_INT_USER_2:
  346.     if (smUtilUser2Rtn != NULL)
  347.         {
  348. return (*smUtilUser2Rtn)(intArg1, intArg2, intArg3);
  349.         }
  350.     return ERROR;
  351. default:
  352.     printf ("smUtilIntGen:Unknown intType [%x]n", intType);
  353.     return (ERROR); /* unknown interrupt type */
  354. }
  355.     return (OK);
  356.     }
  357. /*****************************************************************************
  358. *
  359. * smUtilIntConnect - connect the shared memory interrupts
  360. *
  361. * This routine connects up how this CPU (ie mailbox, bus or polling task) gets
  362. * notified of incoming shared memory packets or shared memory events.
  363. *
  364. * RETURNS: OK if successful, otherwise ERROR.
  365. */
  366. STATUS smUtilIntConnect
  367.     (
  368.     int priorityType, /* handler priority LOW or HIGH */
  369.     FUNCPTR routine, /* routine to connect */
  370.     int                 param,          /* unit number */
  371.     int                 intType,        /* interrupt method */
  372.     int                 intArg1,        /* interrupt argument #1 */
  373.     int                 intArg2,        /* interrupt argument #2 */
  374.     int                 intArg3         /* interrupt argument #3 */
  375.     )
  376.     {
  377.     STATUS              status = ERROR; /* return status */
  378.     /* appease the Diab gods (SPR 71120) */
  379.     if (intArg3 == 0)
  380.         ;
  381.     if (priorityType == LOW_PRIORITY)
  382. {
  383. smUtilNetRoutine.routine = routine;
  384. smUtilNetRoutine.param   = param;
  385. }
  386.     else
  387. {
  388. smUtilObjRoutine.routine = routine;
  389. smUtilObjRoutine.param   = param;
  390. }
  391.     switch (intType)
  392.         {
  393.         case SM_INT_BUS:                        /* bus interrupts */
  394.             if ((intConnect (INUM_TO_IVEC (intArg2), smUtilIntRoutine, 0)
  395.  != ERROR) && (sysIntEnable (intArg1) != ERROR))
  396. {
  397.                 status = OK;
  398. }
  399.             break;
  400.         case SM_INT_NONE:                       /* polling */
  401.            if ((taskIdVerify (smUtilPollTaskID) == OK)   ||
  402.                 ((smUtilPollTaskID =
  403.                  taskSpawn ("tsmPollTask", smUtilPollTaskPriority,
  404.                              smUtilPollTaskOptions, smUtilPollTaskStackSize,
  405.                              (FUNCPTR) smUtilPollTask, 0, 0, 0, 0, 0, 0, 0,
  406.                              0, 0, 0)) != ERROR))
  407.                 {
  408.              status = OK;
  409.                 }
  410.             break;
  411.         case SM_INT_MAILBOX_1:                  /* mailbox interrupts */
  412.         case SM_INT_MAILBOX_2:
  413.         case SM_INT_MAILBOX_4:
  414.         case SM_INT_MAILBOX_R1:
  415.         case SM_INT_MAILBOX_R2:
  416.         case SM_INT_MAILBOX_R4:
  417.             if ((sysMailboxConnect ((FUNCPTR) smUtilIntRoutine, 0) != ERROR) &&
  418.                 (sysMailboxEnable ((char *) intArg2) != ERROR))
  419.                 {
  420.                 status = OK;
  421.                 }
  422.             break;
  423.         case SM_INT_USER_1:
  424.         case SM_INT_USER_2:
  425.     /* No special action, user code does it all */
  426.     status = OK;
  427.     break;
  428.         default:
  429.             logMsg ("smUtilIntConnect:Unknown interrupt type %dn",
  430.                     intType, 0, 0, 0, 0, 0);
  431.             break;
  432.         }
  433.     return (status);
  434.     }
  435. /*****************************************************************************
  436. *
  437. * smUtilIntRoutine - generic shared memory interrupt handler
  438. *
  439. * This routine is connected to the shared memory interrupts. It calls
  440. * dedicated handlers for incoming shared memory packets or shared
  441. * memory objects events.
  442. *
  443. * RETURNS: N/A
  444. */
  445. void smUtilIntRoutine (void)
  446.     {
  447.     /* call each routine stored in the list */
  448.     if (smUtilObjRoutine.routine != NULL)
  449.         {
  450. (* smUtilObjRoutine.routine) (smUtilObjRoutine.param);
  451.         }
  452.     if (smUtilNetRoutine.routine != NULL)
  453.         {
  454. (* smUtilNetRoutine.routine) (smUtilNetRoutine.param);
  455.         }
  456.     }
  457. /*****************************************************************************
  458. *
  459. * smUtilPollTask - task level generic shared memory events handler
  460. *
  461. * This task handles the shared memory events.  It calls dedicated 
  462. * handlers for incomming shared memory packets or shared memory 
  463. * objects events.
  464. *
  465. * RETURNS: N/A
  466. */
  467. LOCAL void smUtilPollTask (void)
  468.     {
  469.     FOREVER
  470. {
  471. if (smUtilObjRoutine.routine != NULL)
  472.     {
  473.     (* smUtilObjRoutine.routine) (smUtilObjRoutine.param);
  474.     }
  475. if (smUtilNetRoutine.routine != NULL)
  476.     {
  477.     (* smUtilNetRoutine.routine) (smUtilNetRoutine.param);
  478.     }
  479. }
  480.     }