/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* bos720 src/bos/kernext/rcm/inc/rcm_mac.h 1.10.3.27 */ /* */ /* Licensed Materials - Property of IBM */ /* */ /* COPYRIGHT International Business Machines Corp. 1989,1999 */ /* All Rights Reserved */ /* */ /* US Government Users Restricted Rights - Use, duplication or */ /* disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /* */ /* IBM_PROLOG_END_TAG */ /* @(#)37 1.10.3.27 src/bos/kernext/rcm/inc/rcm_mac.h, rcm, bos720 12/3/99 15:28:53 */ #ifndef _H_RCM_MAC #define _H_RCM_MAC /*================================================================ INCLUDES ==============================================================*/ #include #include #include #ifdef _RCM #include #endif /* * This should be commented out for ship level code. */ /* #define CHECK_MP_LOCK_STATUS */ /*================================================================ MACROS ==============================================================*/ /* ------------------------------------------------------------- min and max */ #ifndef max #define max(a,b) (ushort) (((ushort) a < (ushort) b) ? b : a) #endif #ifndef min #define min(a,b) (ushort) (((ushort) a > (ushort) b) ? b : a) #endif /* ------------------------------------------------------------- SET_PDEV Sets the device pointer from the virtual terminal structure. */ #define SET_PDEV(pd,pdev) \ {pdev = pd->pGSC;} #ifdef CHECK_MP_LOCK_STATUS /* * Lock between processes on the same device. If we're not running on * an mp box, or if the device doesn't support mp, then all the * processes will be running on the same processor, and we can simply do * an i_disable. Otherwise, we use a simple lock. * TBD: Do we want to disable interrupts for the kind of time frames * that we can hold the device lock for?? */ # define LOCK_DEVICE(pdev, old_int) \ { \ if (__power_mp() && (pdev)->devHead.display->flags & GS_DD_SUPPORTS_MP) \ { \ assert(!lock_mine(&(pdev)->devHead.lock)); \ simple_lock(&(pdev)->devHead.lock); \ } \ else \ (old_int) = i_disable(INTMAX); \ } # define UNLOCK_DEVICE(pdev, old_int) \ { \ if (__power_mp() && (pdev)->devHead.display->flags & GS_DD_SUPPORTS_MP) \ { \ assert(lock_mine(&(pdev)->devHead.lock)); \ simple_unlock(&(pdev)->devHead.lock); \ } \ else \ i_enable(old_int); \ } /* * Lock between threads for the same process. If the device doesn't * support mp, then there can only ever be one thread, so we don't need * to do anything. */ # define LOCK_PROCESS(pdev) \ { \ if ((pdev)->devHead.display->flags & GS_DD_SUPPORTS_MP) \ { \ assert(!lock_mine(&(pdev)->devHead.lock)); \ simple_lock(&(pdev)->devHead.lock); \ } \ } # define UNLOCK_PROCESS(pdev) \ { \ if ((pdev)->devHead.display->flags & GS_DD_SUPPORTS_MP) \ { \ assert(lock_mine(&(pdev)->devHead.lock)); \ simple_unlock(&(pdev)->devHead.lock); \ } \ } /* * Provide a lock macro for device drivers which doesn't need to check * the GS_DD_SUPPORTS_MP flag. */ # define DD_LOCK_DEVICE(pdev) \ { \ assert(!lock_mine(&(pdev)->devHead.lock)); \ simple_lock(&(pdev)->devHead.lock); \ } # define DD_UNLOCK_DEVICE(pdev) \ { \ assert(lock_mine(&(pdev)->devHead.lock)); \ simple_unlock(&(pdev)->devHead.lock); \ } #else /* !CHECK_MP_LOCK_STATUS */ /* * Lock between processes on the same device. If we're not running on * an mp box, or if the device doesn't support mp, then all the * processes will be running on the same processor, and we can simply do * an i_disable. Otherwise, we use a simple lock. * TBD: Do we want to disable interrupts for the kind of time frames * that we can hold the device lock for?? */ # define LOCK_DEVICE(pdev, old_int) \ { \ if (__power_mp() && (pdev)->devHead.display->flags & GS_DD_SUPPORTS_MP) \ simple_lock(&(pdev)->devHead.lock); \ else \ (old_int) = i_disable(INTMAX); \ } # define UNLOCK_DEVICE(pdev, old_int) \ { \ if (__power_mp() && (pdev)->devHead.display->flags & GS_DD_SUPPORTS_MP) \ simple_unlock(&(pdev)->devHead.lock); \ else \ i_enable(old_int); \ } /* * Lock between threads for the same process. If the device doesn't * support mp, then there can only ever be one thread, so we don't need * to do anything. */ # define LOCK_PROCESS(pdev) \ { \ if ((pdev)->devHead.display->flags & GS_DD_SUPPORTS_MP) \ simple_lock(&(pdev)->devHead.lock); \ } # define UNLOCK_PROCESS(pdev) \ { \ if ((pdev)->devHead.display->flags & GS_DD_SUPPORTS_MP) \ simple_unlock(&(pdev)->devHead.lock); \ } /* * Provide a lock macro for device drivers which doesn't need to check * the GS_DD_SUPPORTS_MP flag. */ # define DD_LOCK_DEVICE(pdev) simple_lock(&(pdev)->devHead.lock); # define DD_UNLOCK_DEVICE(pdev) simple_unlock(&(pdev)->devHead.lock); #endif /* CHECK_MP_LOCK_STATUS */ /* ------------------------------------------------------------- FIND_COMPROC Determines if the calling process is a graphics process (by pid). If so, sets the variable "pcproc" to point to the RCM common proc structure. If not, it returns with NULL pointer. THE TID IS NOT CHECKED! Note: This can only be called from a funneled thread (for 32-bit) or with the common anchor lock held (for 64-bit). */ #ifdef __64BIT_KERNEL # define FIND_COMPROC(pcproc) \ { \ pid_t pid = getpid (); \ for (pcproc = apCom->pProcList; pcproc != NULL; \ pcproc = pcproc->pNext) \ { \ if (pcproc->pid == pid) \ { \ break; \ } \ } \ } #else # define FIND_COMPROC(pcproc) \ { \ ulong old_int; \ pid_t pid = getpid (); \ old_int = i_disable(INTMAX); \ for (pcproc = apCom->pProcList; pcproc != NULL; \ pcproc = pcproc->pNext) \ { \ if (pcproc->pid == pid) \ { \ break; \ } \ } \ i_enable(old_int); \ } #endif /* ------------------------------------------------------------- FIND_COMTHR Determines if the calling thread is a graphics thread. If so, sets the variable "pcthr" to point to the RCM common thread structure. If not, it returns with NULL pointer. Note: This can only be called from a funneled thread (for 32-bit) or with the common anchor lock held (for 64-bit). */ #ifdef __64BIT_KERNEL # define FIND_COMTHR(pcthr) \ { \ tid_t tid = thread_self (); \ for (pcthr = apCom->pThreadList; pcthr != NULL; \ pcthr = pcthr->pNext) \ { \ if (pcthr->tid == tid) \ { \ break; \ } \ } \ } #else # define FIND_COMTHR(pcthr) \ { \ ulong old_int; \ tid_t tid = thread_self (); \ old_int = i_disable(INTMAX); \ for (pcthr = apCom->pThreadList; pcthr != NULL; \ pcthr = pcthr->pNext) \ { \ if (pcthr->tid == tid) \ { \ break; \ } \ } \ i_enable(old_int); \ } #endif #ifdef CHECK_MP_LOCK_STATUS /* ------------------------------------------------------------- FIND_GP Determines if the calling process is a graphics process for the indicated device. If so, sets the variable "pproc" to point to the RCM proc structure. If not, it returns with NULL pointer. NOTE: FIND_GP_OPT can be called directly for better performance if the lock is already held. */ # define FIND_GP_OPT(pdev,pproc) \ { \ pid_t spid = getpid (); \ if ((pdev) != NULL) \ assert(!(pdev->devHead.display->flags & GS_DD_SUPPORTS_MP) || \ lock_mine(&(pdev)->devHead.lock)); \ pproc = NULL; \ if (pdev != NULL) \ for (pproc = pdev->devHead.pProc; pproc != NULL; \ pproc = pproc->procHead.pNext) \ { \ if (pproc->procHead.pid == spid) \ { \ break; \ } \ } \ } # define FIND_GP_OPT_NO_CHECK(pdev,pproc) \ { \ pid_t spid = getpid (); \ pproc = NULL; \ if (pdev != NULL) \ for (pproc = pdev->devHead.pProc; pproc != NULL; \ pproc = pproc->procHead.pNext) \ { \ if (pproc->procHead.pid == spid) \ { \ break; \ } \ } \ } # define FIND_GP(pdev,pproc) \ { \ int old_int; \ \ pproc = NULL; \ if ((pdev) != NULL) \ { \ /* \ * Note that for mp devices on mp machines, we'll get the lock; \ * for non-mp devices or up machines, we'll disable interrupts, \ * which is sufficient to lock out anyone who's trying to \ * change the list. \ */ \ assert(!(pdev->devHead.display->flags & GS_DD_SUPPORTS_MP) || \ !lock_mine(&(pdev)->devHead.lock)); \ LOCK_DEVICE( pdev, old_int ); \ \ FIND_GP_OPT_NO_CHECK( pdev, pproc ); \ \ UNLOCK_DEVICE( pdev, old_int ); \ } \ } #else /* !CHECK_MP_LOCK_STATUS */ /* ------------------------------------------------------------- FIND_GP Determines if the calling process is a graphics process for the indicated device. If so, sets the variable "pproc" to point to the RCM proc structure. If not, it returns with NULL pointer. NOTE: FIND_GP_OPT can be called directly for better performance if the lock is already held. */ # define FIND_GP_OPT(pdev,pproc) \ { \ pid_t spid = getpid (); \ pproc = NULL; \ if (pdev != NULL) \ for (pproc = pdev->devHead.pProc; pproc != NULL; \ pproc = pproc->procHead.pNext) \ { \ if (pproc->procHead.pid == spid) \ { \ break; \ } \ } \ } # define FIND_GP(pdev,pproc) \ { \ int old_int; \ \ pproc = NULL; \ if ((pdev) != NULL) \ { \ /* \ * Note that for mp devices on mp machines, we'll get the lock; \ * for non-mp devices or up machines, we'll disable interrupts, \ * which is sufficient to lock out anyone who's trying to \ * change the list. \ */ \ LOCK_DEVICE( pdev, old_int ); \ \ FIND_GP_OPT( pdev, pproc ); \ \ UNLOCK_DEVICE( pdev, old_int ); \ } \ } #endif /* CHECK_MP_LOCK_STATUS */ #ifndef __64BIT_KERNEL /* ------------------------------------------------------------- NOTE: FIND_GP_PID_TO_TID should not be called by a device driver which supports mp. */ #define FIND_GP_PID_TO_TID(PD,PID,TID) \ { \ ulong old_int; \ gscComProcPtr pcproc; \ \ (TID) = 0; \ if ((PD) && (PD)->pGSC && (PD)->pGSC->devHead.pCom) \ { \ old_int = i_disable(INTMAX); \ \ for (pcproc = (PD)->pGSC->devHead.pCom->pProcList; \ pcproc != NULL; \ pcproc = pcproc->pNext) \ { \ if (pcproc->pid == (PID)) \ { \ (TID) = pcproc->tid; \ break; \ } \ } \ \ i_enable(old_int); \ } \ } #endif #ifdef CHECK_MP_LOCK_STATUS /* ------------------------------------------------------------- FIND_GT Determines if the calling thread is a graphics thread for the indicated device. If so, sets the variable "pthread" to point to the RCM thread structure. If not, it returns with NULL pointer. NOTE: FIND_GT_OPT can be called directly for better performance if the lock is already held. */ # define FIND_GT_FROM_PROC_OPT(pproc, pthread) \ { \ tid_t stid = thread_self (); \ \ pthread = NULL; \ if ((pproc) != NULL) \ { \ assert(!((pproc)->procHead.pGSC->devHead.display->flags & \ GS_DD_SUPPORTS_MP) ||\ lock_mine(&(pproc)->procHead.pGSC->devHead.lock)); \ (pthread) = NULL; \ if ((pproc) != NULL) \ for ((pthread) = (pproc)->procHead.pThread; \ (pthread) != NULL; (pthread) = (pthread)->pNext) \ if ((pthread)->tid == stid) \ break; \ } \ } # define FIND_GT_FROM_PROC_OPT_NO_CHECK(pproc, pthread) \ { \ tid_t stid = thread_self (); \ \ (pthread) = NULL; \ if ((pproc) != NULL) \ for ((pthread) = (pproc)->procHead.pThread; \ (pthread) != NULL; (pthread) = (pthread)->pNext) \ if ((pthread)->tid == stid) \ break; \ } # define FIND_GT_OPT(pdev,pthread) \ { \ rcmProcPtr pproc; \ \ pthread = NULL; \ if ((pdev) != NULL) \ { \ assert(!((pdev)->devHead.display->flags & GS_DD_SUPPORTS_MP) || \ lock_mine(&(pdev)->devHead.lock)); \ (pthread) = NULL; \ FIND_GP_OPT_NO_CHECK(pdev, pproc); \ if (pproc) \ FIND_GT_FROM_PROC_OPT_NO_CHECK(pproc, pthread); \ } \ } # define FIND_GT_OPT_NO_CHECK(pdev,pthread) \ { \ rcmProcPtr pproc; \ \ (pthread) = NULL; \ FIND_GP_OPT_NO_CHECK(pdev, pproc); \ if (pproc) \ FIND_GT_FROM_PROC_OPT_NO_CHECK(pproc, pthread); \ } # define FIND_GT(pdev,pthread) \ { \ int old_int; \ \ pthread = NULL; \ if ((pdev) != NULL) \ { \ /* \ * Note that for mp devices on mp machines, we'll get the lock; \ * for non-mp devices or up machines, we'll disable interrupts, \ * which is sufficient to lock out anyone who's trying to \ * change the list. \ */ \ assert(!((pdev)->devHead.display->flags & GS_DD_SUPPORTS_MP) || \ !lock_mine(&(pdev)->devHead.lock)); \ LOCK_DEVICE( pdev, old_int ); \ \ FIND_GT_OPT_NO_CHECK( pdev, pthread ); \ \ UNLOCK_DEVICE( pdev, old_int ); \ } \ } # define FIND_GT_FROM_PROC(pproc,pthread) \ { \ int old_int; \ \ pthread = NULL; \ if ((pproc) != NULL) \ { \ assert(!((pproc)->procHead.pGSC->devHead.display->flags & \ GS_DD_SUPPORTS_MP) ||\ !lock_mine(&(pproc)->procHead.pGSC->devHead.lock)); \ LOCK_PROCESS( (pproc)->procHead.pGSC ); \ \ FIND_GT_FROM_PROC_OPT_NO_CHECK( pproc, pthread ); \ \ UNLOCK_PROCESS( (pproc)->procHead.pGSC ); \ } \ } /* ------------------------------------------------------------- FIND_RCX Finds the requested rcx in the list for a graphics process. If found, sets pointer to rcx, else sets pointer to NULL. NOTE: This needs to be called with the device lock held. */ # define FIND_RCX(pproc,match,prcx) \ { \ assert(!((pproc)->procHead.pGSC->devHead.display->flags & \ GS_DD_SUPPORTS_MP) ||\ lock_mine(&(pproc)->procHead.pGSC->devHead.lock)); \ for (prcx = pproc->procHead.pRcx; prcx != NULL; prcx = prcx->pNext) \ if (prcx == (struct _rcx *) match) break; \ } /* ------------------------------------------------------------- FIND_WG_OPT Serves the same purpose as FIND_WG except that it does not worry about synchronization with anyone changing the list. NOTE: It is the caller's responsibility to ensure synchronization with list changers. */ # define FIND_WG_OPT(pdev,match,pwg) \ { \ rcmWG *hash_top ; \ uint depth; \ \ DEPTH_INIT(depth); \ hash_top = (rcmWG *)(pdev->devHead.wg_hash_table-> \ entry[RCM_WG_HASH(match)].pWG) ; \ pwg = hash_top ; \ \ RCM_FIND_WG_TRACE(0, 0, 0, 0, 0) ; \ while (pwg != NULL) \ { \ DEPTH_INC(depth); \ \ if (pwg == (struct _rcmWG *) match) break; \ pwg = pwg->pNext ; \ } \ RCM_FIND_WG_TRACE(0, 1, depth, pdev->devHead.window_count,0); \ \ CHECK_FOR_LARGE_DEPTH(pdev, depth); \ \ if ((pwg) && (pwg)->flags & WG_DELETED) \ (pwg) = NULL; \ } /* ------------------------------------------------------------- FIND_WG Finds the requested window geometry in the list for a device. If found, sets pointer to wg, else sets pointer to NULL. NOTE: Device drivers which support MP should not use this macro - they should use FIND_WG_MP instead. Non-MP device drivers should use FIND_WG_OPT instead for situations where interrupts are already disabled. */ # ifdef __64BIT_KERNEL # define FIND_WG(pdev,match,pwg) FIND_WG_MP(pdev, match, pwg) # else # define FIND_WG(pdev,match,pwg) \ { \ int old_int; \ \ old_int = i_disable( INTMAX ); \ \ FIND_WG_OPT( pdev, match, pwg ); \ \ i_enable( old_int ) ; \ \ } # endif /* ------------------------------------------------------------- FIND_WG_MP Serves the same purpose as FIND_WG, but for device drivers that support MP. NOTE: This macro must be called with the device lock held. */ # ifdef __64BIT_KERNEL # define FIND_WG_MP(pdev,match,pwg) \ { \ assert(lock_mine(&(pdev)->devHead.lock)); \ FIND_WG_OPT(pdev,match,pwg); \ } # else # define FIND_WG_MP(pdev,match,pwg) \ { \ /* \ * For UP machines, the DD will have the device lock, but the \ * LOCK_DEVICE in create_win_geom will only disable interrupts. \ */ \ assert(lock_mine(&(pdev)->devHead.lock)); \ if (!(__power_mp())) \ { \ FIND_WG(pdev,match,pwg); \ } \ else \ { \ FIND_WG_OPT(pdev,match,pwg); \ } \ } # endif #else /* !CHECK_MP_LOCK_STATUS */ /* ------------------------------------------------------------- FIND_GT Determines if the calling thread is a graphics thread for the indicated device. If so, sets the variable "pthread" to point to the RCM thread structure. If not, it returns with NULL pointer. NOTE: FIND_GT_OPT can be called directly for better performance if the lock is already held. */ # define FIND_GT_FROM_PROC_OPT(pproc, pthread) \ { \ tid_t stid = thread_self (); \ \ (pthread) = NULL; \ if ((pproc) != NULL) \ for ((pthread) = (pproc)->procHead.pThread; \ (pthread) != NULL; (pthread) = (pthread)->pNext) \ if ((pthread)->tid == stid) \ break; \ } # define FIND_GT_OPT(pdev,pthread) \ { \ rcmProcPtr pproc; \ \ (pthread) = NULL; \ FIND_GP_OPT(pdev, pproc); \ if (pproc) \ FIND_GT_FROM_PROC_OPT(pproc, pthread); \ } # define FIND_GT(pdev,pthread) \ { \ int old_int; \ \ pthread = NULL; \ if ((pdev) != NULL) \ { \ /* \ * Note that for mp devices on mp machines, we'll get the lock; \ * for non-mp devices or up machines, we'll disable interrupts, \ * which is sufficient to lock out anyone who's trying to \ * change the list. \ */ \ LOCK_DEVICE( pdev, old_int ); \ \ FIND_GT_OPT( pdev, pthread ); \ \ UNLOCK_DEVICE( pdev, old_int ); \ } \ } # define FIND_GT_FROM_PROC(pproc,pthread) \ { \ int old_int; \ \ pthread = NULL; \ if ((pproc) != NULL) \ { \ LOCK_PROCESS( pproc->procHead.pGSC ); \ \ FIND_GT_FROM_PROC_OPT( pproc, pthread ); \ \ UNLOCK_PROCESS( pproc->procHead.pGSC ); \ } \ } /* ------------------------------------------------------------- FIND_RCX Finds the requested rcx in the list for a graphics process. If found, sets pointer to rcx, else sets pointer to NULL. NOTE: This needs to be called with the device lock held. */ # define FIND_RCX(pproc,match,prcx) \ { \ for (prcx = pproc->procHead.pRcx; prcx != NULL; prcx = prcx->pNext) \ if (prcx == (struct _rcx *) match) break; \ } /* ------------------------------------------------------------- FIND_WG_OPT Serves the same purpose as FIND_WG except that it does not worry about synchronization with anyone changing the list. NOTE: It is the caller's responsibility to ensure synchronization with list changers. */ # define FIND_WG_OPT(pdev,match,pwg) \ { \ rcmWG *hash_top ; \ uint depth; \ \ DEPTH_INIT(depth); \ hash_top = (rcmWG *)(pdev->devHead.wg_hash_table-> \ entry[RCM_WG_HASH(match)].pWG) ; \ pwg = hash_top ; \ \ RCM_FIND_WG_TRACE(0, 0, 0, 0, 0) ; \ while (pwg != NULL) \ { \ DEPTH_INC(depth); \ \ if (pwg == (struct _rcmWG *) match) break; \ pwg = pwg->pNext ; \ } \ RCM_FIND_WG_TRACE(0, 1, depth, pdev->devHead.window_count,0); \ \ CHECK_FOR_LARGE_DEPTH(pdev, depth); \ \ if ((pwg) && (pwg)->flags & WG_DELETED) \ (pwg) = NULL; \ } /* ------------------------------------------------------------- FIND_WG Finds the requested window geometry in the list for a device. If found, sets pointer to wg, else sets pointer to NULL. NOTE: Device drivers which support MP should not use this macro - they should use FIND_WG_MP instead. Non-MP device drivers should use FIND_WG_OPT instead for situations where interrupts are already disabled. */ # ifdef __64BIT_KERNEL # define FIND_WG(pdev,match,pwg) FIND_WG_MP(pdev, match, pwg) # else # define FIND_WG(pdev,match,pwg) \ { \ int old_int; \ \ old_int = i_disable( INTMAX ); \ \ FIND_WG_OPT( pdev, match, pwg ); \ \ i_enable( old_int ) ; \ \ } # endif /* ------------------------------------------------------------- FIND_WG_MP Serves the same purpose as FIND_WG, but for device drivers that support MP. NOTE: This macro must be called with the device lock held. */ # ifdef __64BIT_KERNEL # define FIND_WG_MP(pdev,match,pwg) FIND_WG_OPT(pdev,match,pwg); # else # define FIND_WG_MP(pdev,match,pwg) \ { \ /* \ * For UP machines, the DD will have the device lock, but the \ * LOCK_DEVICE in create_win_geom will only disable interrupts. \ */ \ if (!(__power_mp())) \ { \ FIND_WG(pdev,match,pwg); \ } \ else \ { \ FIND_WG_OPT(pdev,match,pwg); \ } \ } # endif #endif /* CHECK_MP_LOCK_STATUS */ /* ------------------------------------------------------------- FIND_GT_FROM_RCX Finds the thread which has the given rcx active. NB: To be reliable, this must be called with the domain guarded (or during a context switch). */ #define FIND_GT_FROM_RCX(prcx, pthread) \ (pthread) = (prcx)->pThread /* ------------------------------------------------------------- WG_DELETED Returns if the given window geometry has been requested to be deleted, but the delete has been deferred because there are still contexts bound to it. NB: For non-mp supporting device drivers, this should be called with interrupts disabled. For device drivers which support mp, this should be called either with the device lock held, or while running on the master processor with interrupts disabled. */ #define WG_IS_DELETED(pwg) \ ((pwg)->flags & WG_DELETED) /* ------------------------------------------------------------- GET_CURRENT_CONTEXT Returns the current context for the specified thread and domain. NB: This should be called with the device lock held, to ensure that the returned information is still relevant when it is used. It should also probably be called with the domain guarded. */ #define GET_CURRENT_CONTEXT(pThread, pDom) \ ((pThread)->pDomainCur[(pDom)->domain]) /* ------------------------------------------------------------- FIND_WA Finds the requested window attribute in the list for a process. If found, sets pointer to wa, else sets pointer to NULL. */ #define FIND_WA(pproc,match,pwa) \ { \ for (pwa = pproc->procHead.pWA; pwa != NULL; pwa = pwa->pNext) \ if (pwa == (struct _rcmWA *) match) break; \ } /* ------------------------------------------------------------- FIND_RCXP Finds the requested context part in the common list. If found, sets pointer to rcxp, else sets pointer to NULL. */ #define FIND_RCXP(match,prcxp) \ { \ for (prcxp = apCom->pRcxParts; prcxp != NULL; \ prcxp = prcxp->pNext) \ if (prcxp->glob_id == match) break; \ } /* ------------------------------------------------------------- FIND_RCXP_BY_HANDLE Finds the requested context part in the common list. If found, sets pointer to rcxp, else sets pointer to NULL. */ #define FIND_RCXP_BY_HANDLE(match,prcxp) \ { \ for (prcxp = apCom->pRcxParts; prcxp != NULL; \ prcxp = prcxp->pNext) \ if (prcxp == (struct _rcxp *) match) break; \ } /* ------------------------------------------------------------- FIND_RCXPH Finds the requested context part header in the list for the context. If found, sets pointer to rcxph, else sets pointer to NULL. */ #define FIND_RCXPH(prcx,match,prcxph) \ { \ for (prcxph = prcx->pRcxph; prcxph != NULL; \ prcxph = prcxph->pNext) \ if (prcxph == (struct _rcxph *) match) break; \ } /* ------------------------------------------------------------- * Macros to facilitate usage of the RCM_USR_BUFFER capability by device * drivers. * * THERE CAN BE A RACE CONDITION with X going away and invalidating * pdev->devHead.pusrbufhdr. * * Therefore, non-MP supporting device drivers must disable interrupts * around calls to these macros. * * MP-supporting device drivers must obtain the device lock around * calls to FIND_RCM_USR_BUFFER, VALIDATE_XXX_ADDR or UPDATE_XXXX_DISP_BUFF. * Note that this means these macros cannot be called at the interrupt * level. If the device driver needs to update from its interrupt * handler, it should call FIND_RCM_USR_BUFFER to obtain the ubuf ptr * sometime while running at the process level, provide the ubuf ptr to * the interrupt handler which can then call WRITE/READ_RCM_USR_BUFFER. * ------------------------------------------------------------- */ #define RCM_FIND_RCM_USR_BUFFER(pdevA, setA, startA, lengthA, ubufA) \ { \ ubufA = NULL; \ \ if ((unsigned) (setA) < RCM_MAX_USR_BUFFER && \ (pdevA)->devHead.pusrbufhdr != NULL ) \ { \ ubufA = ((pdevA)->devHead.pusrbufhdr)[setA]; \ \ while (ubufA != NULL) \ { \ if ((startA) >= ubufA->start && \ (startA) + (lengthA) <= ubufA->start + ubufA->length ) \ { \ break; \ } \ \ ubufA = ubufA->next; \ } \ } \ } #define RCM_WRITE_RCM_USR_BUFFER(ubufA, startA, lengthA, bufferA) \ xmemout (bufferA, startA, lengthA, &ubufA->xmemusr); #define RCM_READ_RCM_USR_BUFFER(ubufA, startA, lengthA, bufferA) \ xmemin (startA, bufferA, lengthA, &ubufA->xmemusr); /* ------------------------------------------------------------------------- Current Displayed Buffer specific macros for shared memory usage * -------------------------------------------------------------------------*/ #define RCM_VALIDATE_CDB_ADDR(pdev_p, new_addr_p, uaddr_p, rc_p) \ { \ usrbuf_t * shm_region ; \ \ rc_p = 0 ; \ \ uaddr_p.eaddr = new_addr_p ; \ uaddr_p.srval = (ulong)new_addr_p; \ \ if (uaddr_p.eaddr != NULL) \ { \ RCM_FIND_RCM_USR_BUFFER (pdev_p, gsc_SHM_CurrDispBuff, \ uaddr_p.eaddr, \ sizeof(uint), shm_region) ; \ \ if (shm_region == NULL) \ { \ uaddr_p.eaddr = NULL ; \ uaddr_p.srval = 0; \ rc_p = -1 ; \ } \ else \ rc_p = 1; \ } \ } /* ------------------------------------------------------------------------- MBX specific macros for shared memory usage * -------------------------------------------------------------------------*/ #define RCM_VALIDATE_MBX_ADDR(pdev_p, new_addr_p, uaddr_p, rc_p) \ { \ usrbuf_t * shm_region ; \ \ rc_p = 0 ; \ \ uaddr_p.eaddr = new_addr_p ; \ uaddr_p.srval = (ulong)new_addr_p ; \ \ if (uaddr_p.eaddr != NULL) \ { \ RCM_FIND_RCM_USR_BUFFER (pdev_p, gsc_SHM_MBX, \ uaddr_p.eaddr, \ sizeof(uint), shm_region) ; \ \ if (shm_region == NULL) \ { \ uaddr_p.eaddr = NULL ; \ uaddr_p.srval = 0 ; \ rc_p = -1 ; \ } \ else \ rc_p = 1; \ } \ } #define RCM_UPDATE_CURR_DISP_BUFF(pdev_p, uaddr_p, new_buff, rc_p) \ { \ usrbuf_t * shm_region ; \ \ RCM_FIND_RCM_USR_BUFFER (pdev_p, gsc_SHM_CurrDispBuff, \ uaddr_p.eaddr, sizeof(uint), shm_region) ; \ \ if (shm_region == NULL) \ rc_p = -1 ; \ else \ { \ rc_p = RCM_WRITE_RCM_USR_BUFFER (shm_region, uaddr_p.eaddr, \ sizeof(uint), new_buff) ; \ } \ } #define RCM_UPDATE_MULT_DISP_BUFF(pdev_p, uaddr_p, new_swap, rc_p) \ { \ usrbuf_t * shm_region ; \ \ RCM_FIND_RCM_USR_BUFFER (pdev_p, gsc_SHM_MBX, \ uaddr_p.eaddr, sizeof(uint), shm_region) ; \ \ if (shm_region == NULL) \ rc_p = -1 ; \ else \ { \ rc_p = RCM_WRITE_RCM_USR_BUFFER (shm_region, uaddr_p.eaddr, \ sizeof(uint), new_swap) ; \ } \ } /* Return codes for DD start_switch */ #define RCM_HEAVY_SWITCH 0 #define RCM_LIGHT_SWITCH 1 /* ------------------------------------------------------------- RCM_TRACE Produces a RCM trace record. */ /* use powers of 2 for speed */ #define TRACE_2POW 8 #define TRACE_MAX (1 << TRACE_2POW) #define TRACE_MASK (TRACE_MAX - 1) struct _trace_all { char id[8]; int tcount; /* debug trace count */ struct _trace { /* trace area */ long type; pid_t pid; long a,b; } trace[TRACE_MAX]; }; extern struct _trace_all trace_all; #ifndef RCM_TRACE_SWITCH /* * Define the in-memory trace capability. * * Interrupts are not held off. We accept the risk of clobbered trace * records for run time efficiency. (This trace is always active in the * released software.) * * No fatal error can occur if trace record generation is interrupted * another record is generated, and then the first is resumed, etc., * because 'indx' is generated from trcptr->tcount via masking out the * lower bits. * * This macro can be used in drivers, since a pointer to the global * rcm trace buffer is always passed in the DDmake-gp call. Driver * generated trace records will be interleaved in real time with * records generated by the RCM. */ #define RCM_TRACE_PTR(trcptr,mtype,mpid,ma,mb) \ { \ int indx; \ \ indx = (trcptr)->tcount & TRACE_MASK; \ (trcptr)->tcount++; \ (trcptr)->trace[indx].type = mtype; \ (trcptr)->trace[indx].pid = (pid_t) mpid; \ (trcptr)->trace[indx].a = (int) ma; \ (trcptr)->trace[indx].b = (int) mb; \ } /* * The following version is commonly used in the rcm. */ #define RCM_TRACE(mtype,mpid,ma,mb) \ RCM_TRACE_PTR (&trace_all,mtype,mpid,ma,mb) /* * This version is used by the callback trace function * provided to the rcm kernel. Normal trace pitches p4. */ #define RCMHK_TRACE(hk,p0,p1,p2,p3,p4) \ RCM_TRACE (p0, p1, p2, p3) #else /* * Use the system trace facility, instead of in-memory trace. */ #define RCM_TRACE_PTR(trcptr,p0,p1,p2,p3) \ TRCHKGT (HKWD_DISPLAY_RCM_D, p0, p1, p2, p3, 0); #define RCM_TRACE(p0,p1,p2,p3) \ RCM_TRACE_PTR (dummy,p0,p1,p2,p3) #define RCMHK_TRACE(hk,p0,p1,p2,p3,p4) \ TRCHKGT (hk, p0, p1, p2, p3, p4); #endif /* RCM_LOCK/RCM_UNLOCK Handles a lock and provides for nesting. Ignores signals. */ #define RCM_LOCK(L,S) { (S) = lock_mine(L); if (!(S)) simple_lock(L); } #define RCM_UNLOCK(L,S) { if (!(S)) simple_unlock(L); } /***************************************************************************** ***************************************************************************** RCM_ASSERT macro - First define the compile symbols that turn on the asserts ***************************************************************************** *****************************************************************************/ #ifdef DEBUG /* we want RCM_ASSERT_SWITCH defined when DEBUG is defined */ #ifndef RCM_ASSERT_SWITCH # define RCM_ASSERT_SWITCH #endif #endif #ifdef RCMDEBUG /* we want RCM_ASSERT_SWITCH defined when DEBUG is defined */ #ifndef RCM_ASSERT_SWITCH # define RCM_ASSERT_SWITCH #endif #endif /*---------------------------------------------------------------------------* RCM_ASSERT macro itself *---------------------------------------------------------------------------*/ #ifdef RCM_ASSERT_SWITCH # define RCM_ASSERT(cond, p1, p2, p3, p4, p5) \ { \ if(!(cond)) \ { \ printf("RCM_ASSERT[%s #%d]\n",__FILE__,__LINE__); \ brkpoint(0xD06D0D00, p1, p2, p3, p4, p5); \ } \ } /*---------------------------------------------------------------------------* assert and ASSERT macros are also redefined *---------------------------------------------------------------------------*/ #undef assert #define assert(p) \ { \ if(!(p)) \ { \ printf("[%s #%d]\n",__FILE__,__LINE__); \ panic("assert(p)"); \ } \ } #undef ASSERT #define ASSERT(p) assert(p) #else # define RCM_ASSERT(cond, p1, p2, p3, p4, p5) #endif #endif