* Copyright (c) 1988 University of Utah.
* Copyright (c) 1990 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* the Systems Programming Group of the University of Utah Computer
* %sccs.include.redist.c%
* from: Utah $Hdr: grf.c 1.32 92/01/21$
* @(#)grf.c 7.14 (Berkeley) %G%
* Graphics display driver for HP 300/400/700/800 machines.
* This is the hardware-independent portion of the driver.
* Hardware access is through the machine dependent grf switch routines.
#include <hp/dev/grfioctl.h>
#include <hp/dev/grfvar.h>
#include <hp/dev/grfreg.h>
#include <hp/hpux/hpux.h>
#include <miscfs/specfs/specdev.h>
struct grf_softc grf_softc
[NGRF
];
register struct grf_softc
*gp
= &grf_softc
[unit
];
if (unit
>= NGRF
|| (gp
->g_flags
& GF_ALIVE
) == 0)
if ((gp
->g_flags
& (GF_OPEN
|GF_EXCLUDE
)) == (GF_OPEN
|GF_EXCLUDE
))
* XXX: cannot handle both HPUX and BSD processes at the same time
if (curproc
->p_flag
& SHPUX
)
if (gp
->g_flags
& GF_BSDOPEN
)
gp
->g_flags
|= GF_HPUXOPEN
;
if (gp
->g_flags
& GF_HPUXOPEN
)
gp
->g_flags
|= GF_BSDOPEN
;
* XXX: always put in graphics mode.
if ((gp
->g_flags
& GF_OPEN
) == 0) {
register struct grf_softc
*gp
= &grf_softc
[GRFUNIT(dev
)];
grfioctl(dev
, cmd
, data
, flag
, p
)
register struct grf_softc
*gp
= &grf_softc
[GRFUNIT(dev
)];
return(hpuxgrfioctl(dev
, cmd
, data
, flag
, p
));
bcopy((caddr_t
)&gp
->g_display
, data
, sizeof(struct grfinfo
));
error
= grfmmap(dev
, (caddr_t
*)data
, p
);
error
= grfunmmap(dev
, *(caddr_t
*)data
, p
);
register struct grf_softc
*gp
;
struct proc
*p
= curproc
; /* XXX */
printf("grflock(%d): dev %x flags %x lockpid %x\n",
p
->p_pid
, gp
-grf_softc
, gp
->g_flags
,
gp
->g_lockp
? gp
->g_lockp
->p_pid
: -1);
printf(" lockpslot %d lockslot %d lock[lockslot] %d\n",
gp
->g_lock
->gl_lockslot
, gp
->g_lockpslot
,
gp
->g_lock
->gl_locks
[gp
->g_lockpslot
]);
gp
->g_lock
->gl_lockslot
= 0;
if (gp
->g_lock
->gl_locks
[gp
->g_lockpslot
] == 0) {
gp
->g_flags
|= GF_WANTED
;
if (error
= tsleep((caddr_t
)&gp
->g_flags
,
(PZERO
+1) | PCATCH
, devioc
, 0))
int slot
= grffindpid(gp
);
printf(" slot %d\n", slot
);
gp
->g_lockpslot
= gp
->g_lock
->gl_lockslot
= slot
;
gp
->g_lock
->gl_locks
[slot
] = 1;
register struct grf_softc
*gp
;
printf("grfunlock(%d): dev %x flags %x lockpid %d\n",
curproc
->p_pid
, gp
-grf_softc
, gp
->g_flags
,
gp
->g_lockp
? gp
->g_lockp
->p_pid
: -1);
if (gp
->g_lockp
!= curproc
)
printf(" lockpslot %d lockslot %d lock[lockslot] %d\n",
gp
->g_lock
->gl_lockslot
, gp
->g_lockpslot
,
gp
->g_lock
->gl_locks
[gp
->g_lockpslot
]);
gp
->g_lock
->gl_locks
[gp
->g_lockpslot
] = 0;
gp
->g_lockpslot
= gp
->g_lock
->gl_lockslot
= 0;
if (gp
->g_flags
& GF_WANTED
) {
wakeup((caddr_t
)&gp
->g_flags
);
gp
->g_flags
&= ~GF_WANTED
;
return(grfaddr(&grf_softc
[GRFUNIT(dev
)], off
));
hpuxgrfioctl(dev
, cmd
, data
, flag
, p
)
register struct grf_softc
*gp
= &grf_softc
[GRFUNIT(dev
)];
*(int *)data
= gp
->g_display
.gd_id
;
/* GCSTATIC is implied by our implementation */
/* map in control regs and frame buffer */
error
= grfmmap(dev
, (caddr_t
*)data
, p
);
error
= grfunmmap(dev
, *(caddr_t
*)data
, p
);
/* XXX: HP-UX uses GCUNMAP to get rid of GCSLOT memory */
error
= grflckunmmap(dev
, *(caddr_t
*)data
);
struct grf_slot
*sp
= (struct grf_slot
*)data
;
sp
->slot
= grffindpid(gp
);
error
= grflckmmap(dev
, (caddr_t
*)&sp
->addr
);
if (error
&& gp
->g_pid
) {
free((caddr_t
)gp
->g_pid
, M_DEVBUF
);
error
= EINVAL
; /* XXX */
* XXX: only used right now to map in rbox control registers
* Will be replaced in the future with a real IOMAP interface.
error
= iommap(dev
, (caddr_t
*)data
);
* It may not be worth kludging this (using p_devtmp) to
* make this work. It was an undocumented side-effect
* in HP-UX that the mapped address was the return value
* of the ioctl. The only thing I remember that counted
* on this behavior was the rbox X10 server.
u
.u_r
.r_val1
= *(int *)data
; /* XXX: this sux */
error
= iounmmap(dev
, *(caddr_t
*)data
);
struct grf_softc
*gp
= &grf_softc
[unit
];
* XXX: iteoff call relies on devices being in same order
* as ITEs and the fact that iteoff only uses the minor part
return((*gp
->g_sw
->gd_mode
)(gp
,
(dev
&GRFOVDEV
) ? GM_GRFOVON
: GM_GRFON
,
struct grf_softc
*gp
= &grf_softc
[unit
];
(void) grfunmmap(dev
, (caddr_t
)0, curproc
);
error
= (*gp
->g_sw
->gd_mode
)(gp
,
(dev
&GRFOVDEV
) ? GM_GRFOVOFF
: GM_GRFOFF
,
/* XXX: see comment for iteoff above */
register struct grfinfo
*gi
= &gp
->g_display
;
if (off
>= 0 && off
< gi
->gd_regsize
)
return(((u_int
)gi
->gd_regaddr
+ off
) >> PGSHIFT
);
if (off
>= gi
->gd_regsize
&& off
< gi
->gd_regsize
+gi
->gd_fbsize
) {
return(((u_int
)gi
->gd_fbaddr
+ off
) >> PGSHIFT
);
* Convert a BSD style minor devno to HPUX style.
* We cannot just create HPUX style nodes as they require 24 bits
* of minor device number and we only have 8.
* XXX: This may give the wrong result for remote stats of other
* machines where device 10 exists.
struct grf_softc
*gp
= &grf_softc
[unit
];
if (unit
>= NGRF
|| (gp
->g_flags
&GF_ALIVE
) == 0)
return(bsdtohpuxdev(dev
));
/* now construct minor number */
if (gp
->g_display
.gd_regaddr
!= (caddr_t
)GRFIADDR
) {
int sc
= patosc(gp
->g_display
.gd_regaddr
);
newdev
|= (sc
<< 16) | 0x200;
if (grfdebug
& GDB_DEVNO
)
printf("grfdevno: dev %x newdev %x\n", dev
, newdev
);
struct grf_softc
*gp
= &grf_softc
[GRFUNIT(dev
)];
printf("grfmmap(%d): addr %x\n", p
->p_pid
, *addrp
);
len
= gp
->g_display
.gd_regsize
+ gp
->g_display
.gd_fbsize
;
*addrp
= (caddr_t
)0x1000000; /* XXX */
vn
.v_type
= VCHR
; /* XXX */
vn
.v_specinfo
= &si
; /* XXX */
vn
.v_rdev
= dev
; /* XXX */
error
= vm_mmap(&p
->p_vmspace
->vm_map
, (vm_offset_t
*)addrp
,
(vm_size_t
)len
, VM_PROT_ALL
, flags
, (caddr_t
)&vn
, 0);
struct grf_softc
*gp
= &grf_softc
[GRFUNIT(dev
)];
printf("grfunmmap(%d): dev %x addr %x\n", p
->p_pid
, dev
, addr
);
return(EINVAL
); /* XXX: how do we deal with this? */
size
= round_page(gp
->g_display
.gd_regsize
+ gp
->g_display
.gd_fbsize
);
rv
= vm_deallocate(&p
->p_vmspace
->vm_map
, (vm_offset_t
)addr
, size
);
return(rv
== KERN_SUCCESS
? 0 : EINVAL
);
struct proc
*p
= curproc
; /* XXX */
struct grf_softc
*gp
= &grf_softc
[GRFUNIT(dev
)];
if (grfdebug
& (GDB_MMAP
|GDB_IOMAP
))
printf("iommap(%d): addr %x\n", p
->p_pid
, *addrp
);
if (grfdebug
& (GDB_MMAP
|GDB_IOMAP
))
printf("iounmmap(%d): id %d addr %x\n",
curproc
->p_pid
, unit
, addr
);
* Processes involved in framebuffer mapping via GCSLOT are recorded in
* an array of pids. The first element is used to record the last slot used
* (for faster lookups). The remaining elements record up to GRFMAXLCK-1
* process ids. Returns a slot number between 1 and GRFMAXLCK or 0 if no
malloc(GRFMAXLCK
* sizeof(short), M_DEVBUF
, M_WAITOK
);
bzero((caddr_t
)gp
->g_pid
, GRFMAXLCK
* sizeof(short));
ni
= limit
= gp
->g_pid
[0];
for (i
= 1, sp
= &gp
->g_pid
[1]; i
<= limit
; i
++, sp
++) {
printf("grffindpid(%d): slot %d of %d\n",
if (gp
->g_pid
== NULL
|| (limit
= gp
->g_pid
[0]) == 0)
for (i
= 1, sp
= &gp
->g_pid
[1]; i
<= limit
; i
++, sp
++) {
printf("grfrmpid(%d): slot %d of %d\n",
pid
, sp
-gp
->g_pid
, gp
->g_pid
[0]);
struct proc
*p
= curproc
; /* XXX */
if (grfdebug
& (GDB_MMAP
|GDB_LOCK
))
printf("grflckmmap(%d): addr %x\n",
if (grfdebug
& (GDB_MMAP
|GDB_LOCK
))
printf("grflckunmmap(%d): id %d addr %x\n",
curproc
->p_pid
, unit
, addr
);