* 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 is only permitted until one year after the first shipment
* of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
* binary forms are permitted provided that: (1) source distributions retain
* this entire copyright notice and comment, and (2) distributions including
* binaries display the following acknowledgement: This product includes
* software developed by the University of California, Berkeley and its
* contributors'' in the documentation or other materials provided with the
* distribution and in all advertising materials mentioning features or use
* of this software. 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 AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* from: Utah $Hdr: grf.c 1.28 89/08/14$
* @(#)grf.c 7.4 (Berkeley) 6/22/90
* 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
];
struct mapmemops grfops
= { (int (*)())0, (int (*)())0, grfexit
, grfexit
};
struct mapmemops grflckops
= { (int (*)())0, (int (*)())0, grfexit
, grfexit
};
struct mapmemops grfiomops
= { (int (*)())0, (int (*)())0, grfexit
, grfexit
};
* 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
->hw_type
!= 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 ((caddr_t
)sctoaddr(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 (u
.u_procp
->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
)
register struct grf_softc
*gp
= &grf_softc
[GRFUNIT(dev
)];
if (u
.u_procp
->p_flag
& SHPUX
)
return(hpuxgrfioctl(dev
, cmd
, data
, flag
));
/* 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
);
error
= grfunmmap(dev
, *(caddr_t
*)data
);
register struct grf_softc
*gp
;
struct proc
*p
= u
.u_procp
; /* 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(" lock[0] %d lockslot %d lock[lockslot] %d\n",
gp
->g_locks
[0], gp
->g_lockpslot
,
gp
->g_locks
[gp
->g_lockpslot
]);
if (gp
->g_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_locks
[0] = slot
;
register struct grf_softc
*gp
;
printf("grfunlock(%d): dev %x flags %x lockpid %d\n",
u
.u_procp
->p_pid
, gp
-grf_softc
, gp
->g_flags
,
gp
->g_lockp
? gp
->g_lockp
->p_pid
: -1);
if (gp
->g_lockp
!= u
.u_procp
)
printf(" lock[0] %d lockslot %d lock[lockslot] %d\n",
gp
->g_locks
[0], gp
->g_lockpslot
,
gp
->g_locks
[gp
->g_lockpslot
]);
gp
->g_locks
[gp
->g_lockpslot
] = gp
->g_locks
[0] = 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
)
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
);
error
= grfunmmap(dev
, *(caddr_t
*)data
);
/* 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
);
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);
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 defined(HP360) || defined(HP370)
if (gp
->g_display
.gd_regaddr
== (caddr_t
)DIOIIBASE
)
if (gp
->g_display
.gd_regaddr
!= (caddr_t
)GRFIADDR
)
newdev
|= ((u_int
)gp
->g_display
.gd_regaddr
-EXTIOBASE
) | 0x200;
if (grfdebug
& GDB_DEVNO
)
printf("grfdevno: dev %x newdev %x\n", dev
, newdev
);
return(grfaddr(&grf_softc
[GRFUNIT(mp
->mm_id
)], off
));
struct proc
*p
= u
.u_procp
; /* XXX */
struct grf_softc
*gp
= &grf_softc
[GRFUNIT(dev
)];
int len
, error
, grfmapin();
printf("grfmmap(%d): addr %x\n", p
->p_pid
, *addrp
);
len
= gp
->g_display
.gd_regsize
+ gp
->g_display
.gd_fbsize
;
error
= mmalloc(p
, minor(dev
), addrp
, len
, MM_RW
|MM_CI
|MM_NOCORE
,
if (error
= mmmapin(p
, mp
, grfmapin
))
register struct mapmem
*mp
, **mpp
;
int found
, unit
= minor(dev
);
printf("grfunmmap(%d): id %d addr %x\n",
u
.u_procp
->p_pid
, unit
, addr
);
for (mp
= *mpp
; mp
; mp
= *mpp
) {
if (mp
->mm_ops
!= &grfops
|| mp
->mm_id
!= unit
) {
(addr
< mp
->mm_uva
|| addr
>= mp
->mm_uva
+mp
->mm_size
)) {
return(found
? 0 : EINVAL
);
struct proc
*p
= u
.u_procp
; /* XXX */
struct grf_softc
*gp
= &grf_softc
[GRFUNIT(mp
->mm_id
)];
printf("grfexit(%d): id %d %x@%x\n",
p
->p_pid
, mp
->mm_id
, mp
->mm_size
, mp
->mm_uva
);
struct proc
*p
= u
.u_procp
; /* XXX */
struct grf_softc
*gp
= &grf_softc
[GRFUNIT(dev
)];
int len
, error
, grfmapin();
if (grfdebug
& (GDB_MMAP
|GDB_IOMAP
))
printf("iommap(%d): addr %x\n", p
->p_pid
, *addrp
);
len
= gp
->g_display
.gd_regsize
;
error
= mmalloc(p
, minor(dev
), addrp
, len
, MM_RW
|MM_CI
|MM_NOCORE
,
if (error
= mmmapin(p
, mp
, grfmapin
))
struct grf_softc
*gp
= &grf_softc
[GRFUNIT(dev
)];
register struct mapmem
*mp
, **mpp
;
int found
, len
, unit
= minor(dev
);
if (grfdebug
& (GDB_MMAP
|GDB_IOMAP
))
printf("iounmmap(%d): id %d addr %x\n",
u
.u_procp
->p_pid
, unit
, addr
);
len
= gp
->g_display
.gd_regsize
;
for (mp
= *mpp
; mp
; mp
= *mpp
) {
if (mp
->mm_ops
!= &grfiomops
|| mp
->mm_id
!= unit
) {
(addr
< mp
->mm_uva
|| addr
>= mp
->mm_uva
+mp
->mm_size
||
return(found
? 0 : EINVAL
);
* 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]);
u_int pa
= kvtop((u_int
)grf_softc
[GRFUNIT(mp
->mm_id
)].g_locks
);
printf("grflckmapin(%d): va %x pa %x\n", u
.u_procp
->p_pid
,
grf_softc
[GRFUNIT(mp
->mm_id
)].g_locks
, pa
);
struct proc
*p
= u
.u_procp
; /* XXX */
struct grf_softc
*gp
= &grf_softc
[GRFUNIT(dev
)];
int error
, grflckmapin();
if (grfdebug
& (GDB_MMAP
|GDB_LOCK
))
printf("grflckmmap(%d): addr %x\n",
if (gp
->g_locks
== NULL
) {
gp
->g_locks
= (u_char
*) cialloc(NBPG
);
error
= mmalloc(p
, minor(dev
), addrp
, NBPG
, MM_RW
|MM_CI
,
if (error
= mmmapin(p
, mp
, grflckmapin
))
register struct mapmem
*mp
;
if (grfdebug
& (GDB_MMAP
|GDB_LOCK
))
printf("grflckunmmap(%d): id %d addr %x\n",
u
.u_procp
->p_pid
, unit
, addr
);
for (mp
= u
.u_mmap
; mp
; mp
= mp
->mm_next
)
if (mp
->mm_ops
== &grflckops
&& mp
->mm_id
== unit
&&