1568N/A/* Copyright (c) 1993, 2015, Oracle and/or its affiliates. All rights reserved.
830N/A *
830N/A * Permission is hereby granted, free of charge, to any person obtaining a
919N/A * copy of this software and associated documentation files (the "Software"),
919N/A * to deal in the Software without restriction, including without limitation
919N/A * the rights to use, copy, modify, merge, publish, distribute, sublicense,
919N/A * and/or sell copies of the Software, and to permit persons to whom the
919N/A * Software is furnished to do so, subject to the following conditions:
830N/A *
919N/A * The above copyright notice and this permission notice (including the next
919N/A * paragraph) shall be included in all copies or substantial portions of the
919N/A * Software.
830N/A *
919N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
919N/A * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
919N/A * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
919N/A * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
919N/A * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
919N/A * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
919N/A * DEALINGS IN THE SOFTWARE.
830N/A */
830N/A
830N/A
830N/A/*
830N/A * cmap_grab.c - the client side code for DGA colormap grabber
830N/A */
830N/A
830N/A
830N/A/*
830N/A *
830N/A * Shared colormap synchronization routines.
830N/A *
830N/A * Client side
830N/A *
830N/A *
830N/A * Functions:
830N/A *
830N/A * Dga_cmap
830N/A * dga_cm_grab(devfd, filesuffix)
830N/A * int devfd ;
830N/A * unsigned long filesuffix ;
830N/A *
830N/A * Grab a colormap. 'filesuffix' is the handle returned by
830N/A * XDgaGrabColormap. 'devfd' is the file descriptor of the frame buffer
830N/A * if any, -1 otherwise. If you specify -1, dga_cm_grab will open
830N/A * the frame buffer. The frame buffer fd may be inquired from
830N/A * the returned dga_cmap structure.
830N/A *
830N/A * Returns a pointer to a dga_cmap structure on success,
830N/A * NULL on failure.
830N/A *
830N/A *
830N/A * void
830N/A * dga_cm_ungrab(cginfo,cflag)
830N/A * Dga_cmap cginfo ;
830N/A * int cflag ;
830N/A *
830N/A * Release a colormap. All resources allocated by dga_cm_grab are
830N/A * freed. The application should call XDgaUnGrabColormap after calling
830N/A * dga_cm_ungrab() so that the server may free the colormap info page
830N/A * at the other end.
830N/A *
830N/A * if cflag is nonzero, the framebuffr fd described in the info page
830N/A * is also closed. The info page is invalid after this call and
830N/A * references to it will probably result in a SIGSEGV.
830N/A *
830N/A *
830N/A *
830N/A *
830N/A * void
830N/A * dga_cm_get(cginfo,index,count, red,green,blue)
830N/A * Dga_cmap cginfo ;
830N/A * int index, count ;
830N/A * u_char *red, *green, *blue ;
830N/A *
830N/A * Read colormap values and return them to the application.
830N/A *
830N/A *
830N/A * void
830N/A * dga_cm_put(cginfo,index,count, red,green,blue)
830N/A * Dga_cmap cginfo ;
830N/A * int index, count ;
830N/A * u_char *red, *green, *blue ;
830N/A *
830N/A * Write colormap to hardware if colormap is installed, otherwise
830N/A * save them in shared memory.
830N/A *
830N/A *
830N/A *
830N/A * void
830N/A * dga_cm_write(cginfo,index,count, red,green,blue, putfunc)
830N/A * Dga_cmap cginfo ;
830N/A * int index, count ;
830N/A * u_char *red, *green, *blue ;
830N/A * int (*putfunc)();
830N/A *
830N/A * Write colormap to hardware by calling the user supplied putfunc
830N/A * if colormap is installed, otherwise save them in shared memory.
830N/A *
830N/A ** void
830N/A * dga_cm_read(cginfo,index,count, red,green,blue)
830N/A * Dga_cmap cginfo ;
830N/A * int index, count ;
830N/A * u_char *red, *green, *blue ;
830N/A * int (*putfunc)();
830N/A *
830N/A * Read colormap values and return them to the application
830N/A *
830N/A * int
830N/A * dga_cm_get_devfd(cginfo)
830N/A * Dga_cmap cginfo;
830N/A *
830N/A * Return the fd of the device associated with cginfo
830N/A *
830N/A * void
830N/A * dga_cm_get_devinfo(cginfo)
830N/A * Dga_cmap cginfo;
830N/A *
830N/A * Returns pointer to the device specific info associated with
830N/A * cginfo. Used to communicate info bet server and client
830N/A *
830N/A * void
830N/A * dga_cm_set_client_infop(cginfo, client_info_ptr)
830N/A * Dga_cmap cginfo;
830N/A * void* client_info_ptr;
830N/A *
830N/A * Sets pointer to client specificr-data associated with cginfo.
830N/A *
830N/A * void *
830N/A * dga_cm_get_client_infop(cginfo)
830N/A * Dga_cmap cginfo;
830N/A *
830N/A * Returns the client specific data pointer associated with cginfo
830N/A
830N/A ****/
830N/A
830N/A
830N/A#include <stdio.h>
830N/A#include <stdlib.h>
830N/A#include <string.h>
830N/A#include <sys/types.h>
830N/A#include <fcntl.h>
830N/A#include <sys/mman.h>
830N/A#include <sys/ioctl.h>
830N/A#include <sys/time.h>
830N/A#include <errno.h>
830N/A#include <X11/Xlib.h>
830N/A
830N/A#ifdef SVR4
830N/A#include <sys/fbio.h>
830N/A#ifdef SUNWINDOWS /* see note later */
830N/A#include <sys/cms.h>
830N/A#include <sys/rect.h>
830N/A#include <sys/win_screen.h>
830N/A#include <sys/win_input.h>
830N/A#include <sys/win_ioctl.h>
830N/A#endif /* SUNWINDOWS */
830N/A#include <unistd.h>
830N/A#else
830N/A#include <sun/fbio.h>
830N/A#include <sunwindow/cms.h>
830N/A#include <sunwindow/rect.h>
830N/A#include <sunwindow/win_screen.h>
830N/A#include <sunwindow/win_input.h>
830N/A#include <sunwindow/win_ioctl.h>
830N/A#endif
830N/A
830N/A#ifndef FB_CLUTPOST
830N/Astruct fb_clut {
830N/A unsigned int flags; /* flags */
830N/A int index; /* CLUT id */
830N/A int offset; /* offset within the CLUT */
830N/A int count; /* nbr of entries to be posted */
830N/A unsigned char *red; /* pointer to red table */
830N/A unsigned char *green; /* pointer to green table */
830N/A unsigned char *blue; /* pointer to blue table */
830N/A};
830N/A
830N/A#ifdef SVR4
830N/A#define FB_CLUTPOST (('t' << 8) | 4)
830N/A#else
830N/A#define FB_CLUTPOST _IOW(t, 4, struct fb_clut)
830N/A#endif
830N/A#endif
830N/A
830N/A
830N/A#include "cmap_grab.h"
830N/A
830N/A
830N/A/* externs */
830N/A#if 0
830N/Aextern char *_SysErrorMsg[] ;
830N/A#endif
830N/A
830N/Aextern int _dga_winlockat(u_long cookie, int **lockp, int **unlockp);
830N/Aextern int _dga_winlockdt(int *lockp, int *unlockp);
830N/A
830N/A#define GRABFILE "/tmp/cm"
830N/A#define NDIGITS 8
830N/A
830N/A#define MINSHMEMSIZE (8*1024)
830N/A#define CG_PAGESZ (8*1024)
830N/A
830N/Astatic Dga_cmap errret() ;
830N/Astatic int sunwindows_open();
830N/Astatic void sunwindows_close();
830N/A
830N/Astatic Dga_cmap grabbed_list = NULL ;
830N/A
830N/Astatic int cleanup_lockpages();
830N/A
830N/A/*ARGSUSED*/
830N/ADga_cmap
830N/Adga_cm_grab(fd, filesuffix)
830N/Aint fd ;
830N/ADga_token filesuffix ;
830N/A{
830N/A Grabbedcmap *infop, tmp ;
830N/A _Dga_cmap cmap_grab ;
830N/A char fn[sizeof(GRABFILE)+NDIGITS+1];
830N/A char *lock, *unlock ;
830N/A int lockfd, /* lock device */
830N/A devfd, /* framebuffer */
830N/A infofd, /* shared memory file */
830N/A sunwindows_def_fd, /* /dev/winXX fd */
830N/A sunwindows_inst_fd ; /* /dev/winXX fd */
830N/A int locktype = 0 ; /* use /dev/winlock */
830N/A int cflag = 0 ; /* close devfd */
830N/A u_long cookie;
830N/A int cmaplen ;
830N/A int filelen ;
830N/A int ok;
830N/A struct fbtype fbd_type;
830N/A
830N/A#ifdef MT
830N/A mutex_lock(&dgaGlobalMutex);
830N/A#endif
830N/A /* first and foremost, is this a nested grab? */
830N/A for(cmap_grab = grabbed_list; cmap_grab != NULL;
830N/A cmap_grab = cmap_grab->cm_next) {
830N/A if (cmap_grab->cm_token == filesuffix) {
830N/A ++cmap_grab->cm_grab_count;
830N/A#ifdef MT
830N/A mutex_unlock(&dgaGlobalMutex);
830N/A#endif
830N/A return cmap_grab;
830N/A }
830N/A }
830N/A
830N/A if((cmap_grab = (_Dga_cmap)calloc(1,sizeof(struct dga_cmap))) == NULL ) {
830N/A#ifdef MT
830N/A mutex_unlock(&dgaGlobalMutex);
830N/A#endif
830N/A return errret("malloc failed", fn) ;
830N/A }
830N/A
830N/A cmap_grab->cm_infofd =
830N/A cmap_grab->cm_devfd =
830N/A cmap_grab->cm_lockfd =
830N/A cmap_grab->cm_sunwindows_def_fd =
830N/A cmap_grab->cm_sunwindows_inst_fd = -1 ;
830N/A cmap_grab->cm_grab_count = 1 ;
830N/A cmap_grab->cm_next = grabbed_list ;
830N/A grabbed_list = cmap_grab ;
830N/A
830N/A /* open the file. Read in enough data to find out long it is. */
830N/A
830N/A sprintf(fn, "%s%08x", GRABFILE, filesuffix) ;
830N/A
830N/A if ((infofd = open(fn,O_RDWR,0666))<0) {
830N/A cleanup_lockpages(cmap_grab,0,0,0) ;
830N/A#ifdef MT
830N/A mutex_unlock(&dgaGlobalMutex);
830N/A#endif
830N/A return errret("can't open info page, ", fn) ;
830N/A }
830N/A
830N/A if( read(infofd, &tmp, sizeof(tmp)) != sizeof(tmp) ) {
1568N/A (void) close(infofd) ;
830N/A cleanup_lockpages(cmap_grab,0,0,0) ;
830N/A#ifdef MT
830N/A mutex_unlock(&dgaGlobalMutex);
830N/A#endif
830N/A return errret("info page too short", fn) ;
830N/A }
830N/A
830N/A if( tmp.cm_magic != CMMAGIC ) {
1568N/A (void) close(infofd) ;
830N/A cleanup_lockpages(cmap_grab,0,0,0) ;
830N/A#ifdef MT
830N/A mutex_unlock(&dgaGlobalMutex);
830N/A#endif
830N/A return errret("invalid magic number", fn) ;
830N/A }
830N/A
830N/A cookie = tmp.cm_cookie;
830N/A cmaplen = tmp.cm_reallen ;
830N/A
830N/A filelen = tmp.cm_shadowofs + 3*cmaplen*sizeof(short) + 4*cmaplen;
830N/A
830N/A /* map the colormap info area */
830N/A
830N/A infop = (Grabbedcmap *)mmap(0,
830N/A filelen,
830N/A PROT_READ|PROT_WRITE,
830N/A MAP_SHARED,
830N/A infofd,
830N/A (off_t)0);
830N/A
830N/A /* we're all done with infofd now. If the info file becomes
830N/A * subject to growth later, we'll want to keep it open.
830N/A */
830N/A (void) close(infofd) ;
830N/A cmap_grab->cm_infofd = -1 ;
830N/A
830N/A if (infop == (Grabbedcmap *)-1) {
830N/A cleanup_lockpages(cmap_grab,0,filelen,0) ;
830N/A#ifdef MT
830N/A mutex_unlock(&dgaGlobalMutex);
830N/A#endif
830N/A return errret("can't map info page", fn) ;
830N/A }
830N/A cmap_grab->cm_info = (void *) infop ;
830N/A
830N/A
830N/A /* Open framebuffer if not provided by caller */
830N/A
830N/A if( fd == -1 ) {
830N/A devfd = open(infop->cm_devname, O_RDWR,0666) ;
830N/A if( devfd < 0 ) {
830N/A#ifdef DEBUG
830N/A fprintf(stderr, "wx_cm_grab: cannot open %s, %s\n",
830N/A infop->cm_devname, strerror(errno)) ;
830N/A#endif /* DEBUG */
830N/A cleanup_lockpages(cmap_grab,0,filelen,0) ;
830N/A#ifdef MT
830N/A mutex_unlock(&dgaGlobalMutex);
830N/A#endif
830N/A return NULL ;
830N/A }
830N/A cflag = 1 ;
830N/A } else
830N/A devfd = fd ;
830N/A
830N/A cmap_grab->cm_devfd = devfd ;
830N/A
830N/A locktype = infop->cm_version >= 1 ? infop->cm_locktype : CM_LOCKDEV ;
830N/A
830N/A switch( locktype ) {
830N/A case CM_LOCKDEV:
830N/A /* if lockdevice explicitly specified by server, we need to
830N/A * open it here, even if the calling routine has opened the
830N/A * framebuffer for us. Otherwise, we use the framebuffer device.
830N/A */
830N/A
830N/A if( infop->cm_lockdevname[0] != '\0' ) {
830N/A lockfd = open(infop->cm_lockdevname, O_RDWR,0666) ;
830N/A if( lockfd < 0 ) {
830N/A#ifdef DEBUG
830N/A fprintf(stderr, "wx_cm_grab: cannot open %s, %s\n",
830N/A infop->cm_lockdevname, strerror(errno)) ;
830N/A#endif /* DEBUG */
830N/A cleanup_lockpages(cmap_grab,cflag,filelen,locktype) ;
830N/A#ifdef MT
830N/A mutex_unlock(&dgaGlobalMutex);
830N/A#endif
830N/A return NULL ;
830N/A }
830N/A } else
830N/A lockfd = devfd ;
830N/A
830N/A cmap_grab->cm_lockfd = lockfd ;
830N/A
830N/A /* map the lock page */
830N/A lock = (char *)mmap(0,
830N/A CM_PAGESZ,
830N/A PROT_READ|PROT_WRITE,
830N/A MAP_SHARED,
830N/A lockfd, (off_t)cookie);
830N/A
830N/A if (lock == (char *)-1) {
830N/A cleanup_lockpages(cmap_grab,cflag,filelen,0) ;
830N/A#ifdef MT
830N/A mutex_unlock(&dgaGlobalMutex);
830N/A#endif
830N/A return errret("can't map lock page",tmp.cm_devname) ;
830N/A }
830N/A cmap_grab->cm_lockp = (u_int *) lock ;
830N/A
830N/A /* map the unlock page */
830N/A unlock = (char *) mmap(0,
830N/A CM_PAGESZ,
830N/A PROT_READ|PROT_WRITE,
830N/A MAP_SHARED,
830N/A lockfd,(off_t)cookie) ;
830N/A
830N/A if( unlock == (char *)-1 ) {
830N/A cleanup_lockpages(cmap_grab,cflag,filelen,0) ;
830N/A#ifdef MT
830N/A mutex_unlock(&dgaGlobalMutex);
830N/A#endif
830N/A return errret("can't map unlock page", tmp.cm_devname) ;
830N/A }
830N/A cmap_grab->cm_unlockp = (u_int *) unlock ;
830N/A break ;
830N/A case CM_WINLOCK:
830N/A if( _dga_winlockat(cookie, &lock, &unlock) != 0 ) {
830N/A cleanup_lockpages(cmap_grab,cflag,filelen,locktype) ;
830N/A#ifdef MT
830N/A mutex_unlock(&dgaGlobalMutex);
830N/A#endif
830N/A return errret("can't get lock pages", fn) ;
830N/A }
830N/A cmap_grab->cm_lockp = (u_int *) lock ;
830N/A cmap_grab->cm_unlockp = (u_int *) unlock ;
830N/A break ;
830N/A }
830N/A
830N/A /* fill in the misc stuff */
830N/A
830N/A sunwindows_def_fd = sunwindows_inst_fd = -1;
830N/A ok = 1;
830N/A if (infop->cm_default && (infop->cm_sunwindows_def_devname[0] != '\0')) {
830N/A if ((sunwindows_def_fd = sunwindows_open(
830N/A infop->cm_sunwindows_def_devname)) < 0)
830N/A ok = 0;
830N/A }
830N/A cmap_grab->cm_sunwindows_def_fd = sunwindows_def_fd ;
830N/A if (ok && (infop->cm_sunwindows_inst_devname[0] != '\0')) {
830N/A if ((sunwindows_inst_fd = sunwindows_open(
830N/A infop->cm_sunwindows_inst_devname)) < 0)
830N/A ok = 0;
830N/A }
830N/A cmap_grab->cm_sunwindows_inst_fd = sunwindows_inst_fd ;
830N/A
830N/A if(!ok) {
830N/A cleanup_lockpages(cmap_grab,cflag,filelen,locktype) ;
830N/A#ifdef MT
830N/A mutex_unlock(&dgaGlobalMutex);
830N/A#endif
830N/A return errret("/dev/winxx open failed", fn) ;
830N/A }
830N/A
830N/A cmap_grab->cm_token = filesuffix;
830N/A cmap_grab->cm_client = NULL ;
830N/A cmap_grab->c_chngcnt = -1 ; /* flag all changes as not seen */
830N/A cmap_grab->s_chngcnt_p = (u_int *) &(infop->cm_count);
830N/A cmap_grab->cm_lockcnt = 0 ;
830N/A cmap_grab->cm_use_new_ioctl = 1 ; /* try to use new ioctl */
830N/A
830N/A#ifdef MT
830N/A mutex_unlock(&dgaGlobalMutex);
830N/A#endif
830N/A return((Dga_cmap)cmap_grab);
830N/A}
830N/A
830N/A
830N/Astatic int
830N/Acleanup_lockpages(cginfo,cflag,filelen,locktype)
830N/A _Dga_cmap cginfo ;
830N/A int cflag, filelen, locktype ;
830N/A{
830N/A int error = 0 ;
830N/A _Dga_cmap p1, p2 ;
830N/A
830N/A if (cginfo->cm_sunwindows_def_fd >= 0)
830N/A sunwindows_close(cginfo->cm_sunwindows_def_fd);
830N/A if (cginfo->cm_sunwindows_inst_fd >= 0)
830N/A sunwindows_close(cginfo->cm_sunwindows_inst_fd);
830N/A switch( locktype ) {
830N/A case CM_LOCKDEV:
830N/A if( cginfo->cm_unlockp != NULL )
830N/A error |= munmap((char *)cginfo->cm_unlockp,CM_PAGESZ) < 0 ;
830N/A if( cginfo->cm_lockp != NULL )
830N/A error |= munmap((char *)cginfo->cm_lockp,CM_PAGESZ) < 0 ;
830N/A if( cginfo->cm_lockfd != -1 &&
830N/A cginfo->cm_lockfd != cginfo->cm_devfd )
830N/A error |= close(cginfo->cm_lockfd) ;
830N/A break ;
830N/A case CM_WINLOCK:
830N/A error |= _dga_winlockdt(cginfo->cm_lockp, cginfo->cm_unlockp) < 0 ;
830N/A break ;
830N/A }
830N/A if( cginfo->cm_info != NULL )
830N/A error |= munmap(cginfo->cm_info, filelen) < 0 ;
830N/A if( cginfo->cm_infofd != -1 )
830N/A error |= close(cginfo->cm_infofd) < 0 ;
830N/A if( cflag )
830N/A error |= close(cginfo->cm_devfd) < 0 ;
830N/A
830N/A for( p1 = grabbed_list, p2 = NULL ; p1 != NULL && p1 != cginfo;
830N/A p2 = p1, p1=p1->cm_next) ;
830N/A if( p1 == NULL ) /* not found?? */
830N/A error = 1 ;
830N/A else {
830N/A if( p2 == NULL )
830N/A grabbed_list = p1->cm_next ;
830N/A else
830N/A p2->cm_next = p1->cm_next ;
830N/A }
830N/A free(cginfo);
830N/A return error ? -1 : 0 ;
830N/A}
830N/A
830N/Avoid
830N/Adga_cm_ungrab(cginfoi, cflag)
830N/ADga_cmap cginfoi ;
830N/Aint cflag ;
830N/A{
830N/A _Dga_cmap cginfo = (struct dga_cmap *)cginfoi;
830N/A Grabbedcmap *infop = (Grabbedcmap *) cginfo->cm_info ;
830N/A int cmaplen, filelen ;
830N/A int locktype ;
830N/A
830N/A#ifdef MT
830N/A mutex_lock(&dgaGlobalMutex);
830N/A#endif
830N/A if( --cginfo->cm_grab_count > 0 ) {
830N/A#ifdef MT
830N/A mutex_unlock(&dgaGlobalMutex);
830N/A#endif
830N/A return;
830N/A }
830N/A
830N/A cmaplen = infop->cm_reallen ;
830N/A filelen = infop->cm_shadowofs + 3*cmaplen*sizeof(short) + 4*cmaplen ;
830N/A
830N/A cleanup_lockpages(cginfo,cflag,filelen,
830N/A infop->cm_version >= 1 ? infop->cm_locktype : CM_LOCKDEV ) ;
830N/A#ifdef MT
830N/A mutex_unlock(&dgaGlobalMutex);
830N/A#endif
830N/A}
830N/A
830N/Astatic Dga_cmap
830N/Aerrret(msg,file)
830N/Achar *msg, *file ;
830N/A{
830N/A#ifdef DEBUG
830N/A fprintf(stderr, "colormap-grab: %s: %s, %s\n",
830N/A msg, file, strerror(errno)) ;
830N/A#endif /* DEBUG */
830N/A return NULL ;
830N/A}
830N/A
830N/A
830N/A
830N/A/*
830N/A * Read colormap from shared memory.
830N/A * Shared memory should always be in sync
830N/A * with server's idea of this X11 colormap's
830N/A * contents.
830N/A */
830N/A
830N/Avoid
830N/Adga_cm_get(cginfoi,index,count, red,green,blue)
830N/ADga_cmap cginfoi ;
830N/Aint index, count ;
830N/Au_char *red, *green, *blue ;
830N/A{
830N/A _Dga_cmap cginfo = (struct dga_cmap *)cginfoi;
830N/A Grabbedcmap *infop = (Grabbedcmap *) cginfo->cm_info ;
830N/A
830N/A#ifdef MT
830N/A mutex_lock(&dgaGlobalMutex);
830N/A#endif
830N/A wx_cm_lock(cginfo) ;
830N/A
830N/A /* REMIND: Currently, we don't need to test for any changes in the
830N/A * shared memory page; but if we did, right here is where we'd do
830N/A * it. We compare infop->cm_count against cginfo->c_chngcnt and
830N/A * react if there was a difference. After handling the change,
830N/A * we'd copy infop->cm_count to cginfo->c_chngcnt.
830N/A */
830N/A
830N/A if( index+count > infop->cm_reallen )
830N/A count = infop->cm_reallen - index ;
830N/A
830N/A if( count > 0 ) {
830N/A
830N/A /* copy from shared memory */
830N/A short *shadow ;
830N/A short *ip ;
830N/A u_char *op ;
830N/A int n ;
830N/A
830N/A shadow = (short *) ( (u_char *)infop + infop->cm_shadowofs ) ;
830N/A shadow += index ;
830N/A for(n=count, op=red, ip=shadow ; --n >= 0 ; *op++ = *ip++>>8 ) ;
830N/A shadow += infop->cm_reallen ;
830N/A for(n=count, op=green, ip=shadow ; --n >= 0 ; *op++ = *ip++>>8 ) ;
830N/A shadow += infop->cm_reallen ;
830N/A for(n=count, op=blue, ip=shadow ; --n >= 0 ; *op++ = *ip++>>8 ) ;
830N/A }
830N/A wx_cm_unlock(cginfo) ;
830N/A#ifdef MT
830N/A mutex_unlock(&dgaGlobalMutex);
830N/A#endif
830N/A}
830N/A/* This is the new interface that will be publicly exposed */
830N/Avoid
830N/Adga_cm_read(cginfo,index,count, red,green,blue)
830N/ADga_cmap cginfo;
830N/Aint index, count ;
830N/Au_char *red, *green, *blue ;
830N/A{
830N/A dga_cm_get(cginfo,index,count, red,green,blue);
830N/A}
830N/A
830N/A
830N/A/* write colormap to shared memory, and to DACS if appropriate. */
830N/A
830N/Avoid
830N/Adga_cm_put(cginfoi,index,count, red,green,blue)
830N/ADga_cmap cginfoi ;
830N/Aint index, count ;
830N/Au_char *red, *green, *blue ;
830N/A{
830N/A _Dga_cmap cginfo = (struct dga_cmap *)cginfoi;
830N/A Grabbedcmap *infop = (Grabbedcmap *) cginfo->cm_info ;
830N/A short *shadow ;
830N/A u_char *ip ; /* in pointer */
830N/A short *op ; /* out pointer */
830N/A u_char *fp ; /* flag pointer */
830N/A int n ;
830N/A
830N/A#ifdef MT
830N/A mutex_lock(&dgaGlobalMutex);
830N/A#endif
830N/A wx_cm_lock(cginfo) ;
830N/A
830N/A if( index+count > infop->cm_reallen )
830N/A count = infop->cm_reallen - index ;
830N/A if( count > 0 ) {
830N/A if( index < infop->cm_start )
830N/A infop->cm_start = index ;
830N/A if( index + count > infop->cm_start + infop->cm_len )
830N/A infop->cm_len = index + count -infop->cm_start ;
830N/A
830N/A /* copy to shared memory shadow of grabbed color map */
830N/A /* "stutter" the 8-bit values into 16 bits */
830N/A
830N/A shadow = (short *) ( (u_char *)infop + infop->cm_shadowofs ) ;
830N/A shadow += index ;
830N/A for(n=count, ip=red, op=shadow ; --n >= 0 ; *op++, *ip++)
830N/A *op = *ip | (*ip << 8);
830N/A shadow += infop->cm_reallen ;
830N/A for(n=count, ip=green, op=shadow ; --n >= 0 ; *op++, *ip++)
830N/A *op = *ip | (*ip << 8);
830N/A shadow += infop->cm_reallen ;
830N/A for(n=count, ip=blue, op=shadow ; --n >= 0 ; *op++, *ip++)
830N/A *op = *ip | (*ip << 8);
830N/A fp = (u_char *)infop + infop->cm_shadowofs +
830N/A 3 * infop->cm_reallen * sizeof(short) + index ;
830N/A for(n=count ; --n >= 0 ; *fp++ = 1 ) ;
830N/A
830N/A if( infop->cm_installed ) {
830N/A#ifdef COMMENT
830N/A /* We no longer need the hw shadow cmap but have to keep
830N/A * the structures the same size and so we will just stop
830N/A * updating it
830N/A */
830N/A u_char *hwshadow;
830N/A
830N/A /* copy to shared memory shadow of hardware color map */
830N/A hwshadow = (u_char *)infop + infop->cm_shadowofs +
830N/A 3 * infop->cm_reallen * sizeof(short) +
830N/A infop->cm_reallen + index;
830N/A for (n=count, ip=red, fp=hwshadow; --n >= 0; *fp++ = *ip++);
830N/A hwshadow += infop->cm_reallen;
830N/A for (n=count, ip=green, fp=hwshadow; --n >= 0; *fp++ = *ip++);
830N/A hwshadow += infop->cm_reallen;
830N/A for (n=count, ip=blue, fp=hwshadow; --n >= 0; *fp++ = *ip++);
830N/A hwshadow -= index + 2 * infop->cm_reallen;
830N/A#endif
830N/A switch(infop->cm_load_method) {
830N/A
830N/A#ifdef SUNWINDOWS
830N/A /* Note from V4 on, SUnwindows include files, support no
830N/A * longer exist. I am commenting out the code instead of
830N/A * removing it only for completeness. After Mars, time to
830N/A * move away from sunwindows....
830N/A */
830N/A case SUNWINDOWS_IOCTL:
830N/A {
830N/A struct cmschange cmschange;
830N/A
830N/A if( cginfo->cm_sunwindows_def_fd >= 0 ) {
830N/A strcpy(cmschange.cc_cms.cms_name,
830N/A infop->cm_sunwindows_def_cmapname);
830N/A cmschange.cc_cms.cms_addr = 0;
830N/A cmschange.cc_cms.cms_size =
830N/A infop->cm_sunwindows_def_cmapsize;
830N/A cmschange.cc_map.cm_red = hwshadow;
830N/A cmschange.cc_map.cm_green =
830N/A hwshadow + infop->cm_reallen;
830N/A cmschange.cc_map.cm_blue =
830N/A hwshadow + 2 * infop->cm_reallen;
830N/A
830N/A /* HACK ALERT */
830N/A /* Adjust SUNWINDOWS cms segment 1st colr != last color */
830N/A if ((cmschange.cc_map.cm_red[0] ==
830N/A cmschange.cc_map.cm_red[cmschange.cc_cms.cms_size-1]) &&
830N/A (cmschange.cc_map.cm_green[0] ==
830N/A cmschange.cc_map.cm_green[cmschange.cc_cms.cms_size-1]) &&
830N/A (cmschange.cc_map.cm_blue[0] ==
830N/A cmschange.cc_map.cm_blue[cmschange.cc_cms.cms_size-1]))
830N/A {
830N/A if (cmschange.cc_map.cm_blue[0] > 0)
830N/A cmschange.cc_map.cm_blue[0]--;
830N/A else
830N/A cmschange.cc_map.cm_blue[0] = 1;
830N/A }
830N/A
830N/A ioctl(cginfo->cm_sunwindows_def_fd, WINSETCMS, &cmschange);
830N/A }
830N/A
830N/A if( cginfo->cm_sunwindows_inst_fd >= 0 )
830N/A {
830N/A strcpy(cmschange.cc_cms.cms_name,
830N/A infop->cm_sunwindows_inst_cmapname);
830N/A cmschange.cc_cms.cms_addr = 0;
830N/A cmschange.cc_cms.cms_size =
830N/A infop->cm_sunwindows_inst_cmapsize;
830N/A cmschange.cc_map.cm_red = hwshadow;
830N/A cmschange.cc_map.cm_green = hwshadow + infop->cm_reallen;
830N/A cmschange.cc_map.cm_blue =
830N/A hwshadow + 2 * infop->cm_reallen;
830N/A
830N/A /* HACK ALERT */
830N/A /* Adjust SUNWINDOWS cms segment 1st colr != last color */
830N/A if ((cmschange.cc_map.cm_red[0] ==
830N/A cmschange.cc_map.cm_red[cmschange.cc_cms.cms_size-1]) &&
830N/A (cmschange.cc_map.cm_green[0] ==
830N/A cmschange.cc_map.cm_green[cmschange.cc_cms.cms_size-1]) &&
830N/A (cmschange.cc_map.cm_blue[0] ==
830N/A cmschange.cc_map.cm_blue[cmschange.cc_cms.cms_size-1])) {
830N/A if (cmschange.cc_map.cm_blue[0] > 0)
830N/A cmschange.cc_map.cm_blue[0]--;
830N/A else
830N/A cmschange.cc_map.cm_blue[0] = 1;
830N/A }
830N/A
830N/A ioctl(cginfo->cm_sunwindows_inst_fd,WINSETCMS,&cmschange);
830N/A }
830N/A }
830N/A break;
830N/A#endif /* SUNWINDOWS */
830N/A case HW_DEVICE_DIRECT: /* could have device-specific
830N/A routines here; just fall
830N/A through to device ioctl
830N/A for now */
830N/A
830N/A case HW_DEVICE_IOCTL:
830N/A default:
830N/A#ifdef FBIOPUTCMAPI
830N/A if( cginfo->cm_use_new_ioctl) {
830N/A /* try new ioctl */
830N/A struct fbcmap_i cmap;
830N/A
830N/A cmap.flags = 0 ;
830N/A cmap.id = infop->cm_cmapnum ;
830N/A cmap.index = infop->cm_ioctlbits | index;
830N/A cmap.count = count;
830N/A cmap.red = red;
830N/A cmap.green = green;
830N/A cmap.blue = blue;
830N/A if( ioctl(cginfo->cm_devfd, FBIOPUTCMAPI, &cmap) == 0 )
830N/A break;
830N/A }
830N/A#endif /* FBIOPUTCMAPI */
830N/A
830N/A if( cginfo->cm_use_new_ioctl ) {
830N/A /* try FB_CLUTPOST ioctl */
830N/A struct fb_clut cmap;
830N/A
830N/A cmap.flags = 0 ;
830N/A cmap.index = infop->cm_cmapnum;
830N/A cmap.offset = index;
830N/A cmap.count = count;
830N/A cmap.red = red;
830N/A cmap.green = green;
830N/A cmap.blue = blue;
830N/A if( ioctl(cginfo->cm_devfd, FB_CLUTPOST, &cmap) == 0 )
830N/A break;
830N/A
830N/A cginfo->cm_use_new_ioctl = 0;
830N/A }
830N/A
830N/A if (cginfo->cm_use_new_ioctl == 0) {
830N/A struct fbcmap cmap;
830N/A
830N/A cmap.index = infop->cm_ioctlbits | index;
830N/A cmap.count = count;
830N/A cmap.red = red;
830N/A cmap.green = green;
830N/A cmap.blue = blue;
830N/A ioctl(cginfo->cm_devfd, FBIOPUTCMAP, &cmap);
830N/A }
830N/A break;
830N/A }
830N/A }
830N/A
830N/A /* We've changed the shared memory page, flag this fact to
830N/A * the server and to any other clients
830N/A */
830N/A cginfo->c_chngcnt = ++infop->cm_count ;
830N/A }
830N/A wx_cm_unlock(cginfo) ;
830N/A#ifdef MT
830N/A mutex_unlock(&dgaGlobalMutex);
830N/A#endif
830N/A}
830N/A
830N/A/* This is the interfce that will be publicly exposed */
830N/Avoid
830N/Adga_cm_write(cginfoi,index,count, red,green,blue, putfunc)
830N/ADga_cmap cginfoi ;
830N/Aint index, count ;
830N/Au_char *red, *green, *blue ;
830N/Avoid (*putfunc)();
830N/A{
830N/A _Dga_cmap cginfo = (struct dga_cmap *)cginfoi;
830N/A Grabbedcmap *infop = (Grabbedcmap *) cginfo->cm_info ;
830N/A short *shadow ;
830N/A u_char *ip ; /* in pointer */
830N/A short *op ; /* out pointer */
830N/A u_char *fp ; /* flag pointer */
830N/A int n ;
830N/A
830N/A#ifdef MT
830N/A mutex_lock(&dgaGlobalMutex);
830N/A#endif
830N/A wx_cm_lock(cginfo) ;
830N/A
830N/A if( index+count > infop->cm_reallen )
830N/A count = infop->cm_reallen - index ;
830N/A
830N/A if( count > 0 ) {
830N/A if( index < infop->cm_start )
830N/A infop->cm_start = index ;
830N/A
830N/A if( index + count > infop->cm_start + infop->cm_len )
830N/A infop->cm_len = index + count -infop->cm_start ;
830N/A
830N/A /* copy to shared memory shadow of grabbed color map */
830N/A /* "stutter" the 8-bit values into 16 bits */
830N/A
830N/A shadow = (short *) ( (u_char *)infop + infop->cm_shadowofs ) ;
830N/A shadow += index ;
830N/A for(n=count, ip=red, op=shadow ; --n >= 0 ; *op++, *ip++)
830N/A *op = *ip | (*ip << 8);
830N/A shadow += infop->cm_reallen ;
830N/A for(n=count, ip=green, op=shadow ; --n >= 0 ; *op++, *ip++)
830N/A *op = *ip | (*ip << 8);
830N/A shadow += infop->cm_reallen ;
830N/A for(n=count, ip=blue, op=shadow ; --n >= 0 ; *op++, *ip++)
830N/A *op = *ip | (*ip << 8);
830N/A fp = (u_char *)infop + infop->cm_shadowofs +
830N/A 3 * infop->cm_reallen * sizeof(short) + index ;
830N/A for(n=count ; --n >= 0 ; *fp++ = 1 ) ;
830N/A
830N/A if( infop->cm_installed ) {
830N/A#ifdef COMMENT
830N/A /* We dont need to update thie any more */
830N/A u_char *hwshadow;
830N/A
830N/A /* copy to shared memory shadow of hardware color map */
830N/A hwshadow = (u_char *)infop + infop->cm_shadowofs +
830N/A 3 * infop->cm_reallen * sizeof(short) +
830N/A infop->cm_reallen + index;
830N/A for (n=count, ip=red, fp=hwshadow; --n >= 0; *fp++ = *ip++);
830N/A hwshadow += infop->cm_reallen;
830N/A for (n=count, ip=green, fp=hwshadow; --n >= 0; *fp++ = *ip++);
830N/A hwshadow += infop->cm_reallen;
830N/A for (n=count, ip=blue, fp=hwshadow; --n >= 0; *fp++ = *ip++);
830N/A hwshadow -= index + 2 * infop->cm_reallen;
830N/A
830N/A for (n=count, ip=blue, fp=hwshadow; --n >= 0; *fp++ = *ip++);
830N/A hwshadow -= index + 2 * infop->cm_reallen;
830N/A#endif
830N/A /* Now call the user supplied function for actually
830N/A * posting the cmap
830N/A */
830N/A (*putfunc)( cginfo, index, count, red, green, blue);
830N/A }
830N/A
830N/A /* We've changed the shared memory page, flag this fact to
830N/A * the server and to any other clients
830N/A */
830N/A
830N/A cginfo->c_chngcnt = ++infop->cm_count ;
830N/A }
830N/A wx_cm_unlock(cginfo) ;
830N/A#ifdef MT
830N/A mutex_unlock(&dgaGlobalMutex);
830N/A#endif
830N/A}
830N/A
830N/A/* Interfaces that will be exposed to the public */
830N/Aint
830N/Adga_cm_devdfd(cginfoi)
830N/ADga_cmap cginfoi ;
830N/A{
830N/A
830N/A return (((struct dga_cmap *)cginfoi)->cm_devfd);
830N/A}
830N/A
830N/A/* This device info is shared between the server and client */
830N/Avoid *
830N/Adga_cm_devinfo(cginfoi)
830N/ADga_cmap cginfoi ;
830N/A{
830N/A _Dga_cmap cginfo = (struct dga_cmap *)cginfoi;
830N/A return ((void *)(((char *)cginfo->cm_info)
830N/A + CM_INFOP(cginfo)->device_offset));
830N/A
830N/A}
830N/A
830N/A/* Each client may store private info in the client info ptr */
830N/Avoid
830N/Adga_cm_set_client_infop(cginfoi, client_info_ptr)
830N/ADga_cmap cginfoi;
830N/Avoid* client_info_ptr;
830N/A{
830N/A _Dga_cmap cginfo = (struct dga_cmap *)cginfoi;
830N/A
830N/A cginfo->cm_client = client_info_ptr;
830N/A}
830N/A
830N/Avoid *
830N/Adga_cm_get_client_infop(cginfoi)
830N/ADga_cmap cginfoi;
830N/A{
830N/A _Dga_cmap cginfo = (struct dga_cmap *)cginfoi;
830N/A
830N/A return ((void *)cginfo->cm_client);
830N/A}
830N/A
830N/Astatic Cmap_Devlist *devlist = NULL;
830N/A
830N/Astatic int
830N/Asunwindows_open(devname)
830N/Achar *devname;
830N/A{
830N/A Cmap_Devlist *dlist = devlist;
830N/A int fd;
830N/A
830N/A while (dlist)
830N/A {
830N/A if (strcmp(devname, dlist->devname) == 0)
830N/A {
830N/A dlist->refcnt++;
830N/A return(dlist->fd);
830N/A }
830N/A dlist = dlist->next;
830N/A }
830N/A if ((fd = open(devname, O_RDWR, 0666)) < 0)
830N/A {
830N/A#ifdef DEBUG
830N/A fprintf(stderr, "colormap-grab: open failed %s, %s\n",
830N/A devname, strerror(errno)) ;
830N/A#endif /* DEBUG */
830N/A return(-1);
830N/A }
830N/A if((dlist = (Cmap_Devlist *)malloc(sizeof(Cmap_Devlist))) == NULL )
830N/A {
830N/A close(fd);
830N/A#ifdef DEBUG
830N/A fprintf(stderr, "colormap-grab: malloc failed %s, %s\n",
830N/A devname, strerror(errno)) ;
830N/A#endif /* DEBUG */
830N/A return(-1);
830N/A }
830N/A dlist->next = devlist;
830N/A devlist = dlist;
830N/A dlist->refcnt = 1;
830N/A dlist->fd = fd;
830N/A strcpy(dlist->devname, devname);
830N/A return(fd);
830N/A}
830N/A
830N/A
830N/Astatic void
830N/Asunwindows_close(fd)
830N/Aint fd;
830N/A{
830N/A Cmap_Devlist *dlist = devlist;
830N/A Cmap_Devlist **dlptr = &devlist;
830N/A
830N/A while (dlist)
830N/A {
830N/A if (fd == dlist->fd)
830N/A {
830N/A if (--dlist->refcnt == 0)
830N/A {
830N/A close(fd);
830N/A *dlptr = dlist->next;
830N/A free(dlist);
830N/A }
830N/A return;
830N/A }
830N/A dlptr = &dlist->next;
830N/A dlist = dlist->next;
830N/A }
830N/A}
830N/A
830N/A
830N/A
830N/A
830N/A
830N/A
830N/A/* /dev/winlock management code. This is a temporary hack so we can
830N/A * develop the new /dev/winlock interface. Hopefully, this will become
830N/A * part of the C library someday.
830N/A *
830N/A */
830N/A
830N/A
830N/A#include <sys/ioccom.h>
830N/A
830N/A /* structure for allocating lock contexts. The identification
830N/A * should be provided as the offset for mmap(2). The offset is
830N/A * the byte-offset relative to the start of the page returned
830N/A * by mmap(2).
830N/A */
830N/A
830N/Astruct winlockalloc {
830N/A u_long sy_key ; /* user-provided key, if any */
830N/A u_long sy_ident ; /* system-provided identification */
830N/A } ;
830N/A
830N/Astruct winlocktimeout {
830N/A u_long sy_ident ;
830N/A u_int sy_timeout ;
830N/A int sy_flags ;
830N/A } ;
830N/A
830N/A
830N/A#ifndef WINLOCKALLOC
830N/A#ifdef SVR4
830N/A#define WIOC ('L'<<8)
830N/A#define WINLOCKALLOC (WIOC|0)
830N/A#define WINLOCKFREE (WIOC|1)
830N/A#define WINLOCKSETTIMEOUT (WIOC|2)
830N/A#define WINLOCKGETTIMEOUT (WIOC|3)
830N/A#define WINLOCKDUMP (WIOC|4)
830N/A#else /* SVR4 */
830N/A#define WINLOCKALLOC _IOWR(L, 0, struct winlockalloc)
830N/A#define WINLOCKFREE _IOW(L, 1, u_long)
830N/A#define WINLOCKSETTIMEOUT _IOW(L, 2, struct winlocktimeout)
830N/A#define WINLOCKGETTIMEOUT _IOWR(L, 3, struct winlocktimeout)
830N/A#define WINLOCKDUMP _IO(L, 4)
830N/A#endif /* SVR4 */
830N/A#endif /* WINLOCKALLOC */
830N/A
830N/A
830N/A/* flag bits */
830N/A#define SY_NOTIMEOUT 0x1 /* This client never times out */
830N/A
830N/A
830N/Astatic char *lockdev_name = "/dev/winlock" ;
830N/Astatic char *alt_lockdev_name = "/dev/cgsix0" ;
830N/A
830N/Astatic int lock_fd = -1 ;
830N/Astatic u_long pagemask ;
830N/Astatic u_long pageoffset ;
830N/Astatic u_long pagesize ;
830N/A
830N/A
830N/A
830N/A /* return non-zero if fail */
830N/A
830N/Astatic int
830N/Ainit()
830N/A{
830N/A if( lock_fd == -1 ) {
830N/A if( (lock_fd = open(lockdev_name, O_RDWR, 0)) == -1 &&
830N/A (lock_fd = open(alt_lockdev_name, O_RDWR, 0)) == -1 )
830N/A return 1 ;
830N/A#ifdef SVR4
830N/A pagesize = sysconf(_SC_PAGESIZE);
830N/A#else
830N/A pagesize = getpagesize() ;
830N/A#endif
830N/A pageoffset = pagesize - 1 ;
830N/A pagemask = ~pageoffset ;
830N/A }
830N/A
830N/A return 0 ;
830N/A}
830N/A
830N/A
830N/Aint
830N/A_dga_winlockat(cookie, lockp, unlockp)
830N/A u_long cookie ;
830N/A int **lockp, **unlockp ;
830N/A{
830N/A u_long ofs ;
830N/A caddr_t ptr ;
830N/A
830N/A if( lock_fd == -1 && init() )
830N/A {
830N/A errno = EINVAL ;
830N/A return -1 ;
830N/A }
830N/A
830N/A ofs = cookie & pageoffset ;
830N/A cookie &= pagemask ;
830N/A
830N/A ptr = mmap(0, pagesize, PROT_READ|PROT_WRITE,
830N/A MAP_SHARED, lock_fd, (off_t)cookie) ;
830N/A if( (int)ptr == -1 )
830N/A {
830N/A errno = ENOSPC ;
830N/A return -1 ;
830N/A }
830N/A *lockp = (int *) (ptr+ofs) ;
830N/A
830N/A ptr = mmap(0, pagesize, PROT_READ|PROT_WRITE,
830N/A MAP_SHARED, lock_fd, (off_t)cookie) ;
830N/A if( (int)ptr == -1 )
830N/A {
830N/A (void) munmap((caddr_t)*lockp, pagesize) ;
830N/A errno = ENOSPC ;
830N/A return -1 ;
830N/A }
830N/A *unlockp = (int *) (ptr+ofs) ;
830N/A
830N/A return 0 ;
830N/A}
830N/A
830N/A
830N/A
830N/Aint
830N/A_dga_winlockdt(lockp, unlockp)
830N/A int *lockp, *unlockp ;
830N/A{
830N/A caddr_t ptr ;
830N/A
830N/A if( lock_fd == -1 && init() )
830N/A {
830N/A errno = EINVAL ;
830N/A return -1 ;
830N/A }
830N/A
830N/A ptr = (caddr_t) ((long)lockp & pagemask) ;
830N/A if( munmap(ptr, pagesize) )
830N/A perror("_dga_winlockdt: munmap:");
830N/A
830N/A ptr = (caddr_t) ((long)unlockp & pagemask) ;
830N/A if( munmap(ptr, pagesize) )
830N/A perror("_dga_winlockdt: munmap:");
830N/A
830N/A return 0 ;
830N/A}