Files
Arquivotheca.SunOS-4.1.4/usr.lib/libpixrect/pr/pr_make.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

238 lines
5.5 KiB
C

#ifndef lint
static char sccsid[] = "@(#)pr_make.c 1.1 94/10/31 SMI";
#endif
/*
* Copyright 1986, 1987 by Sun Microsystems, Inc.
*/
/*
* Pixrect make/unmake utilities
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sun/fbio.h>
#include <pixrect/pixrect.h>
#include <pixrect/pr_impl_make.h>
/* fake out _MAP_NEW if compiling on 3.x or whatever */
#ifndef _MAP_NEW
#define _MAP_NEW 0x80000000
#endif
#define GP_MAJOR 32
/* Round value up to specified granularity -- gran must be a power of two */
#undef roundup
#define roundup(val, gran) ((val) + (gran) - 1 & ~((gran) - 1))
#define ALLOC(type) ((type *) calloc(1, sizeof (type)))
extern char *calloc(), *valloc();
extern caddr_t mmap();
Pixrect *
pr_makefromfd(fd, size, depth, devdata, curdd,
mmapbytes, privdatabytes, mmapoffset)
int fd;
struct pr_size size;
int depth;
struct pr_devdata **devdata, **curdd;
int mmapbytes, privdatabytes, mmapoffset;
{
return pr_makefromfd_2(fd, size, depth, devdata, curdd,
privdatabytes, mmapbytes, mmapoffset, 0, 0);
}
Pixrect *
pr_makefromfd_2(fd, size, depth, devdata, curdd, privdatabytes,
mmapbytes, mmapoffset, mmapbytes2, mmapoffset2)
int fd;
struct pr_size size;
int depth;
struct pr_devdata **devdata, **curdd;
int privdatabytes, mmapbytes, mmapoffset, mmapbytes2, mmapoffset2;
{
Pixrect *pr = 0;
register struct pr_devdata *dd = 0;
struct stat statbuf;
struct fbinfo finfo;
int pagesize;
/*
* check args
* stat frame buffer to get device type
* allocate and initialize pixrect and private data
*/
if (fd < 0 || devdata == 0 || curdd == 0 ||
fstat(fd, &statbuf) < 0 ||
!(pr = ALLOC(Pixrect)) ||
!(pr->pr_data =
(caddr_t) calloc(1, (unsigned) privdatabytes)))
goto bad;
pr->pr_size = size;
pr->pr_depth = depth;
if (major(statbuf.st_rdev) == GP_MAJOR &&
ioctl(fd, FBIOGINFO, &finfo) >= 0)
statbuf.st_rdev = makedev(major(statbuf.st_rdev), finfo.fb_unit);
/* look for a devdata structure for this device */
for (dd = *devdata; dd; dd = dd->next)
if (dd->rdev == statbuf.st_rdev && dd->count++ > 0) {
*curdd = dd;
return pr;
}
/* didn't find devdata, make a new one */
if (!(dd = ALLOC(struct pr_devdata)))
goto bad;
/* caller will close fd, so dup it (dumb) */
if ((dd->fd = dup(fd)) < 0)
goto bad;
pagesize = getpagesize();
mmapbytes = roundup(mmapbytes, pagesize);
if (mmapoffset != roundup(mmapoffset, pagesize))
goto bad;
if (mmapbytes2) {
mmapbytes2 = roundup(mmapbytes2, pagesize);
if (mmapoffset2 != roundup(mmapoffset2, pagesize))
goto bad;
}
/* try new style mmap */
if ((dd->va = mmap((caddr_t) 0, dd->bytes = mmapbytes,
PROT_READ | PROT_WRITE, MAP_SHARED | _MAP_NEW,
dd->fd, mmapoffset)) != (caddr_t) -1) {
/* map second piece if any */
if (mmapbytes2 &&
(dd->va2 = mmap((caddr_t) 0, dd->bytes2 = mmapbytes2,
PROT_READ | PROT_WRITE, MAP_SHARED | _MAP_NEW,
dd->fd, mmapoffset2)) == (caddr_t) -1) {
(void) munmap(dd->va, dd->bytes);
goto bad;
}
}
/* new wave mmap failed, try old fashioned (valloc) method */
else {
caddr_t mapit();
/* prevent munmap on unmake (swap hole!) */
dd->bytes = 0;
/* valloc/map each piece */
if (!(dd->va = mapit(dd->fd, mmapbytes, mmapoffset)) ||
mmapbytes2 &&
!(dd->va2 = mapit(dd->fd, mmapbytes2, mmapoffset2)))
goto bad;
}
/* fill in new devdata and link into head of list */
dd->rdev = statbuf.st_rdev;
dd->count = 1;
dd->next = *devdata ? (*devdata)->next : 0;
*devdata = dd;
*curdd = dd;
return pr;
/* error occurred -- clean up */
bad:
if (pr) {
/* free pixrect and possibly pixrect data */
if (pr->pr_data)
free((char *) pr->pr_data);
free((char *) pr);
/* free devdata, close fd */
if (dd) {
if (dd->fd >= 0)
(void) close(dd->fd);
free((char *) dd);
}
}
*curdd = 0;
return 0;
}
static caddr_t
mapit(fd, bytes, offset)
int fd, bytes, offset;
{
register caddr_t p;
if (!(p = (caddr_t) valloc((unsigned) bytes)))
(void) fprintf(stderr,
"pr_open: out of swap space (needed %dK)\n",
(unsigned) bytes >> 10);
else if (mmap(p, bytes, PROT_READ | PROT_WRITE, MAP_SHARED,
fd, offset)) {
free((char *) p);
p = 0;
}
return p;
}
pr_unmakefromfd(fd, devdata)
int fd;
struct pr_devdata **devdata;
{
register struct pr_devdata *dd, *ddprev = 0;
struct fbinfo finfo;
struct stat statbuf;
/* get the device number */
if (fstat(fd, &statbuf) < 0)
return PIX_ERR;
if (major(statbuf.st_rdev) == GP_MAJOR &&
ioctl(fd, FBIOGINFO, &finfo) >= 0)
statbuf.st_rdev = makedev(major(statbuf.st_rdev), finfo.fb_unit);
/* look for the relevant devdata structure */
for (dd = *devdata; dd; ddprev = dd, dd = dd->next)
/* found matching device number? */
if (statbuf.st_rdev == dd->rdev) {
/*
* If the reference count goes to zero, we would
* like to unmap the frame buffer, close its fd,
* and release the virtual space.
*
* Unfortunately, we can't do that with the old
* VM system because the mmap call probably
* released the swap space for the region the
* frame buffer was mapped over.
*/
if (dd->bytes && --dd->count <= 0) {
(void) munmap(dd->va, dd->bytes);
if (dd->bytes2)
(void) munmap(dd->va2, dd->bytes2);
(void) close(dd->fd);
/* unlink devdata */
if (ddprev == 0)
*devdata = dd->next;
else
ddprev->next = dd->next;
free((char *) dd);
}
return 0;
}
/* couldn't find the devdata */
return PIX_ERR;
}