* 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
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* from: Utah $Hdr: grf.c 1.31 91/01/21$
* @(#)grf.c 7.8 (Berkeley) 5/7/91
* Graphics display driver for the HP300.
* This is the hardware-independent portion of the driver.
* Hardware access is through the grfdev routines below.
#include "../hpux/hpux.h"
int tc_init(), tc_mode();
int gb_init(), gb_mode();
int rb_init(), rb_mode();
int dv_init(), dv_mode();
struct grfdev grfdev
[] = {
GID_TOPCAT
, GRFBOBCAT
, tc_init
, tc_mode
,
GID_GATORBOX
, GRFGATOR
, gb_init
, gb_mode
,
GID_RENAISSANCE
,GRFRBOX
, rb_init
, rb_mode
,
GID_LRCATSEYE
, GRFCATSEYE
, tc_init
, tc_mode
,
GID_HRCCATSEYE
, GRFCATSEYE
, tc_init
, tc_mode
,
GID_HRMCATSEYE
, GRFCATSEYE
, tc_init
, tc_mode
,
GID_DAVINCI
, GRFDAVINCI
, dv_init
, dv_mode
,
int ngrfdev
= sizeof(grfdev
) / sizeof(grfdev
[0]);
struct driver grfdriver
= { grfprobe
, "grf" };
struct grf_softc grf_softc
[NGRF
];
* XXX: called from ite console init routine.
* Does just what configure will do later but without printing anything.
register struct hp_hw
*hw
;
register struct hp_device
*hd
, *nhd
;
for (hw
= sc_table
; hw
->hw_type
; hw
++) {
if (!HW_ISDEV(hw
, D_BITMAP
))
* Found one, now match up with a logical unit number
for (hd
= hp_dinit
; hd
->hp_driver
; hd
++) {
if (hd
->hp_driver
!= &grfdriver
|| hd
->hp_alive
)
* Wildcarded. If first, remember as possible match.
if (hd
->hp_addr
== NULL
) {
* If exact match done searching, else keep looking.
if (sctova(hd
->hp_addr
) == addr
) {
* Found a match, initialize
if (nhd
&& grfinit(addr
, nhd
->hp_unit
))
* Normal init routine called by configure() code
struct grf_softc
*gp
= &grf_softc
[hd
->hp_unit
];
if ((gp
->g_flags
& GF_ALIVE
) == 0 &&
!grfinit(hd
->hp_addr
, hd
->hp_unit
))
printf("grf%d: %d x %d ", hd
->hp_unit
,
gp
->g_display
.gd_dwidth
, gp
->g_display
.gd_dheight
);
if (gp
->g_display
.gd_colors
== 2)
printf("%d color", gp
->g_display
.gd_colors
);
printf(" %s display\n", grfdev
[gp
->g_type
].gd_desc
);
struct grf_softc
*gp
= &grf_softc
[unit
];
register struct grfdev
*gd
;
gr
= (struct grfreg
*) addr
;
if (gr
->gr_id
!= GRFHWID
)
for (gd
= grfdev
; gd
< &grfdev
[ngrfdev
]; gd
++)
if (gd
->gd_hardid
== gr
->gr_id2
)
if (gd
< &grfdev
[ngrfdev
] && (*gd
->gd_init
)(gp
, addr
)) {
gp
->g_display
.gd_id
= gd
->gd_softid
;
gp
->g_type
= gd
- grfdev
;
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
));
/* XXX: compatibility hack */
bcopy((caddr_t
)&gp
->g_display
, data
, sizeof(struct ogrfinfo
));
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((*grfdev
[gp
->g_type
].gd_mode
)
(gp
, (dev
&GRFOVDEV
) ? GM_GRFOVON
: GM_GRFON
));
struct grf_softc
*gp
= &grf_softc
[unit
];
(void) grfunmmap(dev
, (caddr_t
)0, curproc
);
error
= (*grfdev
[gp
->g_type
].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
) {
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
;
flags
= MAP_FILE
|MAP_SHARED
;
*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
);