xref: /csrg-svn/sys/hp/dev/grf.c (revision 41480)
1*41480Smckusick /*
2*41480Smckusick  * Copyright (c) 1988 University of Utah.
3*41480Smckusick  * Copyright (c) 1990 The Regents of the University of California.
4*41480Smckusick  * All rights reserved.
5*41480Smckusick  *
6*41480Smckusick  * This code is derived from software contributed to Berkeley by
7*41480Smckusick  * the Systems Programming Group of the University of Utah Computer
8*41480Smckusick  * Science Department.
9*41480Smckusick  *
10*41480Smckusick  * %sccs.include.redist.c%
11*41480Smckusick  *
12*41480Smckusick  * from: Utah $Hdr: grf.c 1.28 89/08/14$
13*41480Smckusick  *
14*41480Smckusick  *	@(#)grf.c	7.1 (Berkeley) 05/08/90
15*41480Smckusick  */
16*41480Smckusick 
17*41480Smckusick /*
18*41480Smckusick  * Graphics display driver for the HP300.
19*41480Smckusick  * This is the hardware-independent portion of the driver.
20*41480Smckusick  * Hardware access is through the grfdev routines below.
21*41480Smckusick  */
22*41480Smckusick 
23*41480Smckusick #include "grf.h"
24*41480Smckusick #if NGRF > 0
25*41480Smckusick 
26*41480Smckusick #include "param.h"
27*41480Smckusick #include "user.h"
28*41480Smckusick #include "proc.h"
29*41480Smckusick #include "ioctl.h"
30*41480Smckusick #include "file.h"
31*41480Smckusick #include "mapmem.h"
32*41480Smckusick #include "malloc.h"
33*41480Smckusick 
34*41480Smckusick #include "device.h"
35*41480Smckusick #include "grfioctl.h"
36*41480Smckusick #include "grfvar.h"
37*41480Smckusick 
38*41480Smckusick #include "machine/cpu.h"
39*41480Smckusick 
40*41480Smckusick #ifdef HPUXCOMPAT
41*41480Smckusick #include "../hpux/hpux.h"
42*41480Smckusick #endif
43*41480Smckusick 
44*41480Smckusick #include "ite.h"
45*41480Smckusick #if NITE == 0
46*41480Smckusick #define	iteon(u,f)
47*41480Smckusick #define	iteoff(u,f)
48*41480Smckusick #endif
49*41480Smckusick 
50*41480Smckusick int	grfprobe();
51*41480Smckusick int	tc_init(), tc_mode();
52*41480Smckusick int	gb_init(), gb_mode();
53*41480Smckusick int	rb_init(), rb_mode();
54*41480Smckusick int	dv_init(), dv_mode();
55*41480Smckusick 
56*41480Smckusick struct grfdev grfdev[] = {
57*41480Smckusick 	GID_TOPCAT,	GRFBOBCAT,	tc_init,	tc_mode,
58*41480Smckusick 	"topcat",
59*41480Smckusick 	GID_GATORBOX,	GRFGATOR,	gb_init,	gb_mode,
60*41480Smckusick 	"gatorbox",
61*41480Smckusick 	GID_RENAISSANCE,GRFRBOX,	rb_init,	rb_mode,
62*41480Smckusick 	"renaissance",
63*41480Smckusick 	GID_LRCATSEYE,	GRFCATSEYE,	tc_init,	tc_mode,
64*41480Smckusick 	"lo-res catseye",
65*41480Smckusick 	GID_HRCCATSEYE,	GRFCATSEYE,	tc_init,	tc_mode,
66*41480Smckusick 	"hi-res catseye",
67*41480Smckusick 	GID_HRMCATSEYE,	GRFCATSEYE,	tc_init,	tc_mode,
68*41480Smckusick 	"hi-res catseye",
69*41480Smckusick 	GID_DAVINCI,    GRFDAVINCI,	dv_init,	dv_mode,
70*41480Smckusick 	"davinci",
71*41480Smckusick };
72*41480Smckusick int	ngrfdev = sizeof(grfdev) / sizeof(grfdev[0]);
73*41480Smckusick 
74*41480Smckusick struct	driver grfdriver = { grfprobe, "grf" };
75*41480Smckusick struct	grf_softc grf_softc[NGRF];
76*41480Smckusick 
77*41480Smckusick #ifdef MAPMEM
78*41480Smckusick int grfexit();
79*41480Smckusick struct mapmemops grfops = { (int (*)())0, (int (*)())0, grfexit, grfexit };
80*41480Smckusick #ifdef HPUXCOMPAT
81*41480Smckusick struct mapmemops grflckops = { (int (*)())0, (int (*)())0, grfexit, grfexit };
82*41480Smckusick struct mapmemops grfiomops = { (int (*)())0, (int (*)())0, grfexit, grfexit };
83*41480Smckusick #endif
84*41480Smckusick #endif
85*41480Smckusick 
86*41480Smckusick #ifdef DEBUG
87*41480Smckusick int grfdebug = 0;
88*41480Smckusick #define GDB_DEVNO	0x01
89*41480Smckusick #define GDB_MMAP	0x02
90*41480Smckusick #define GDB_IOMAP	0x04
91*41480Smckusick #define GDB_LOCK	0x08
92*41480Smckusick #endif
93*41480Smckusick 
94*41480Smckusick /*
95*41480Smckusick  * XXX: called from ite console init routine.
96*41480Smckusick  * Does just what configure will do later but without printing anything.
97*41480Smckusick  */
98*41480Smckusick grfconfig()
99*41480Smckusick {
100*41480Smckusick 	register caddr_t addr;
101*41480Smckusick 	register struct hp_hw *hw;
102*41480Smckusick 	register struct hp_device *hd, *nhd;
103*41480Smckusick 
104*41480Smckusick 	for (hw = sc_table; hw->hw_type; hw++) {
105*41480Smckusick 	        if (hw->hw_type != BITMAP)
106*41480Smckusick 			continue;
107*41480Smckusick 		/*
108*41480Smckusick 		 * Found one, now match up with a logical unit number
109*41480Smckusick 		 */
110*41480Smckusick 		nhd = NULL;
111*41480Smckusick 		addr = hw->hw_addr;
112*41480Smckusick 		for (hd = hp_dinit; hd->hp_driver; hd++) {
113*41480Smckusick 			if (hd->hp_driver != &grfdriver || hd->hp_alive)
114*41480Smckusick 				continue;
115*41480Smckusick 			/*
116*41480Smckusick 			 * Wildcarded.  If first, remember as possible match.
117*41480Smckusick 			 */
118*41480Smckusick 			if (hd->hp_addr == NULL) {
119*41480Smckusick 				if (nhd == NULL)
120*41480Smckusick 					nhd = hd;
121*41480Smckusick 				continue;
122*41480Smckusick 			}
123*41480Smckusick 			/*
124*41480Smckusick 			 * Not wildcarded.
125*41480Smckusick 			 * If exact match done searching, else keep looking.
126*41480Smckusick 			 */
127*41480Smckusick 			if ((caddr_t)sctoaddr(hd->hp_addr) == addr) {
128*41480Smckusick 				nhd = hd;
129*41480Smckusick 				break;
130*41480Smckusick 			}
131*41480Smckusick 		}
132*41480Smckusick 		/*
133*41480Smckusick 		 * Found a match, initialize
134*41480Smckusick 		 */
135*41480Smckusick 		if (nhd && grfinit(addr, nhd->hp_unit)) {
136*41480Smckusick 			nhd->hp_addr = addr;
137*41480Smckusick 		}
138*41480Smckusick 	}
139*41480Smckusick }
140*41480Smckusick 
141*41480Smckusick /*
142*41480Smckusick  * Normal init routine called by configure() code
143*41480Smckusick  */
144*41480Smckusick grfprobe(hd)
145*41480Smckusick 	struct hp_device *hd;
146*41480Smckusick {
147*41480Smckusick 	struct grf_softc *gp = &grf_softc[hd->hp_unit];
148*41480Smckusick 
149*41480Smckusick 	if ((gp->g_flags & GF_ALIVE) == 0 &&
150*41480Smckusick 	    !grfinit(hd->hp_addr, hd->hp_unit))
151*41480Smckusick 		return(0);
152*41480Smckusick 	printf("grf%d: %d x %d ", hd->hp_unit,
153*41480Smckusick 	       gp->g_display.gd_dwidth, gp->g_display.gd_dheight);
154*41480Smckusick 	if (gp->g_display.gd_colors == 2)
155*41480Smckusick 		printf("monochrome");
156*41480Smckusick 	else
157*41480Smckusick 		printf("%d color", gp->g_display.gd_colors);
158*41480Smckusick 	printf(" %s display\n", grfdev[gp->g_type].gd_desc);
159*41480Smckusick 	return(1);
160*41480Smckusick }
161*41480Smckusick 
162*41480Smckusick grfinit(addr, unit)
163*41480Smckusick 	caddr_t addr;
164*41480Smckusick {
165*41480Smckusick 	struct grf_softc *gp = &grf_softc[unit];
166*41480Smckusick 	struct grfreg *gr;
167*41480Smckusick 	register struct grfdev *gd;
168*41480Smckusick 
169*41480Smckusick 	gr = (struct grfreg *) addr;
170*41480Smckusick 	if (gr->gr_id != GRFHWID)
171*41480Smckusick 		return(0);
172*41480Smckusick 	for (gd = grfdev; gd < &grfdev[ngrfdev]; gd++)
173*41480Smckusick 		if (gd->gd_hardid == gr->gr_id2)
174*41480Smckusick 			break;
175*41480Smckusick 	if (gd < &grfdev[ngrfdev] && (*gd->gd_init)(gp, addr)) {
176*41480Smckusick 		gp->g_display.gd_id = gd->gd_softid;
177*41480Smckusick 		gp->g_type = gd - grfdev;
178*41480Smckusick 		gp->g_flags = GF_ALIVE;
179*41480Smckusick 		return(1);
180*41480Smckusick 	}
181*41480Smckusick 	return(0);
182*41480Smckusick }
183*41480Smckusick 
184*41480Smckusick /*ARGSUSED*/
185*41480Smckusick grfopen(dev, flags)
186*41480Smckusick 	dev_t dev;
187*41480Smckusick {
188*41480Smckusick 	int unit = GRFUNIT(dev);
189*41480Smckusick 	register struct grf_softc *gp = &grf_softc[unit];
190*41480Smckusick 	int error = 0;
191*41480Smckusick 
192*41480Smckusick 	if (unit >= NGRF || (gp->g_flags & GF_ALIVE) == 0)
193*41480Smckusick 		return(ENXIO);
194*41480Smckusick 	if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE))
195*41480Smckusick 		return(EBUSY);
196*41480Smckusick #ifdef HPUXCOMPAT
197*41480Smckusick 	/*
198*41480Smckusick 	 * XXX: cannot handle both HPUX and BSD processes at the same time
199*41480Smckusick 	 */
200*41480Smckusick 	if (u.u_procp->p_flag & SHPUX)
201*41480Smckusick 		if (gp->g_flags & GF_BSDOPEN)
202*41480Smckusick 			return(EBUSY);
203*41480Smckusick 		else
204*41480Smckusick 			gp->g_flags |= GF_HPUXOPEN;
205*41480Smckusick 	else
206*41480Smckusick 		if (gp->g_flags & GF_HPUXOPEN)
207*41480Smckusick 			return(EBUSY);
208*41480Smckusick 		else
209*41480Smckusick 			gp->g_flags |= GF_BSDOPEN;
210*41480Smckusick #endif
211*41480Smckusick 	/*
212*41480Smckusick 	 * First open.
213*41480Smckusick 	 * XXX: always put in graphics mode.
214*41480Smckusick 	 */
215*41480Smckusick 	error = 0;
216*41480Smckusick 	if ((gp->g_flags & GF_OPEN) == 0) {
217*41480Smckusick 		gp->g_flags |= GF_OPEN;
218*41480Smckusick 		error = grfon(dev);
219*41480Smckusick 	}
220*41480Smckusick 	return(error);
221*41480Smckusick }
222*41480Smckusick 
223*41480Smckusick /*ARGSUSED*/
224*41480Smckusick grfclose(dev, flags)
225*41480Smckusick 	dev_t dev;
226*41480Smckusick {
227*41480Smckusick 	register struct grf_softc *gp = &grf_softc[GRFUNIT(dev)];
228*41480Smckusick 
229*41480Smckusick 	(void) grfoff(dev);
230*41480Smckusick 	(void) grfunlock(gp);
231*41480Smckusick 	gp->g_flags &= GF_ALIVE;
232*41480Smckusick 	return(0);
233*41480Smckusick }
234*41480Smckusick 
235*41480Smckusick /*ARGSUSED*/
236*41480Smckusick grfioctl(dev, cmd, data, flag)
237*41480Smckusick 	dev_t dev;
238*41480Smckusick 	caddr_t data;
239*41480Smckusick {
240*41480Smckusick 	register struct grf_softc *gp = &grf_softc[GRFUNIT(dev)];
241*41480Smckusick 	int error;
242*41480Smckusick 
243*41480Smckusick #ifdef HPUXCOMPAT
244*41480Smckusick 	if (u.u_procp->p_flag & SHPUX)
245*41480Smckusick 		return(hpuxgrfioctl(dev, cmd, data, flag));
246*41480Smckusick #endif
247*41480Smckusick 	error = 0;
248*41480Smckusick 	switch (cmd) {
249*41480Smckusick 
250*41480Smckusick 	/* XXX: compatibility hack */
251*41480Smckusick 	case OGRFIOCGINFO:
252*41480Smckusick 		bcopy((caddr_t)&gp->g_display, data, sizeof(struct ogrfinfo));
253*41480Smckusick 		break;
254*41480Smckusick 
255*41480Smckusick 	case GRFIOCGINFO:
256*41480Smckusick 		bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo));
257*41480Smckusick 		break;
258*41480Smckusick 
259*41480Smckusick 	case GRFIOCON:
260*41480Smckusick 		error = grfon(dev);
261*41480Smckusick 		break;
262*41480Smckusick 
263*41480Smckusick 	case GRFIOCOFF:
264*41480Smckusick 		error = grfoff(dev);
265*41480Smckusick 		break;
266*41480Smckusick 
267*41480Smckusick #ifdef MAPMEM
268*41480Smckusick 	case GRFIOCMAP:
269*41480Smckusick 		error = grfmmap(dev, (caddr_t *)data);
270*41480Smckusick 		break;
271*41480Smckusick 
272*41480Smckusick 	case GRFIOCUNMAP:
273*41480Smckusick 		error = grfunmmap(dev, *(caddr_t *)data);
274*41480Smckusick 		break;
275*41480Smckusick #endif
276*41480Smckusick 
277*41480Smckusick 	default:
278*41480Smckusick 		error = EINVAL;
279*41480Smckusick 		break;
280*41480Smckusick 
281*41480Smckusick 	}
282*41480Smckusick 	return(error);
283*41480Smckusick }
284*41480Smckusick 
285*41480Smckusick /*ARGSUSED*/
286*41480Smckusick grfselect(dev, rw)
287*41480Smckusick 	dev_t dev;
288*41480Smckusick {
289*41480Smckusick 	if (rw == FREAD)
290*41480Smckusick 		return(0);
291*41480Smckusick 	return(1);
292*41480Smckusick }
293*41480Smckusick 
294*41480Smckusick grflock(gp, block)
295*41480Smckusick 	register struct grf_softc *gp;
296*41480Smckusick 	int block;
297*41480Smckusick {
298*41480Smckusick #ifdef DEBUG
299*41480Smckusick 	if (grfdebug & GDB_LOCK)
300*41480Smckusick 		printf("grflock(%d): dev %x flags %x lockpid %x\n",
301*41480Smckusick 		       u.u_procp->p_pid, gp-grf_softc, gp->g_flags,
302*41480Smckusick 		       gp->g_lockp ? gp->g_lockp->p_pid : -1);
303*41480Smckusick #endif
304*41480Smckusick #ifdef HPUXCOMPAT
305*41480Smckusick 	if (gp->g_pid) {
306*41480Smckusick #ifdef DEBUG
307*41480Smckusick 		if (grfdebug & GDB_LOCK)
308*41480Smckusick 			printf("  lock[0] %d lockslot %d lock[lockslot] %d\n",
309*41480Smckusick 			       gp->g_locks[0], gp->g_lockpslot,
310*41480Smckusick 			       gp->g_locks[gp->g_lockpslot]);
311*41480Smckusick #endif
312*41480Smckusick 		gp->g_locks[0] = 0;
313*41480Smckusick 		if (gp->g_locks[gp->g_lockpslot] == 0) {
314*41480Smckusick 			gp->g_lockp = NULL;
315*41480Smckusick 			gp->g_lockpslot = 0;
316*41480Smckusick 		}
317*41480Smckusick 	}
318*41480Smckusick #endif
319*41480Smckusick 	if (gp->g_lockp) {
320*41480Smckusick 		if (gp->g_lockp == u.u_procp)
321*41480Smckusick 			return(EBUSY);
322*41480Smckusick 		if (!block)
323*41480Smckusick 			return(EAGAIN);
324*41480Smckusick 		do {
325*41480Smckusick 			gp->g_flags |= GF_WANTED;
326*41480Smckusick 			sleep((caddr_t)&gp->g_flags, PZERO+1);
327*41480Smckusick 		} while (gp->g_lockp);
328*41480Smckusick 	}
329*41480Smckusick 	gp->g_lockp = u.u_procp;
330*41480Smckusick #ifdef HPUXCOMPAT
331*41480Smckusick 	if (gp->g_pid) {
332*41480Smckusick 		int slot = grffindpid(gp);
333*41480Smckusick #ifdef DEBUG
334*41480Smckusick 		if (grfdebug & GDB_LOCK)
335*41480Smckusick 			printf("  slot %d\n", slot);
336*41480Smckusick #endif
337*41480Smckusick 		gp->g_lockpslot = gp->g_locks[0] = slot;
338*41480Smckusick 		gp->g_locks[slot] = 1;
339*41480Smckusick 	}
340*41480Smckusick #endif
341*41480Smckusick 	return(0);
342*41480Smckusick }
343*41480Smckusick 
344*41480Smckusick grfunlock(gp)
345*41480Smckusick 	register struct grf_softc *gp;
346*41480Smckusick {
347*41480Smckusick #ifdef DEBUG
348*41480Smckusick 	if (grfdebug & GDB_LOCK)
349*41480Smckusick 		printf("grfunlock(%d): dev %x flags %x lockpid %d\n",
350*41480Smckusick 		       u.u_procp->p_pid, gp-grf_softc, gp->g_flags,
351*41480Smckusick 		       gp->g_lockp ? gp->g_lockp->p_pid : -1);
352*41480Smckusick #endif
353*41480Smckusick 	if (gp->g_lockp != u.u_procp)
354*41480Smckusick 		return(EBUSY);
355*41480Smckusick #ifdef HPUXCOMPAT
356*41480Smckusick 	if (gp->g_pid) {
357*41480Smckusick #ifdef DEBUG
358*41480Smckusick 		if (grfdebug & GDB_LOCK)
359*41480Smckusick 			printf("  lock[0] %d lockslot %d lock[lockslot] %d\n",
360*41480Smckusick 			       gp->g_locks[0], gp->g_lockpslot,
361*41480Smckusick 			       gp->g_locks[gp->g_lockpslot]);
362*41480Smckusick #endif
363*41480Smckusick 		gp->g_locks[gp->g_lockpslot] = gp->g_locks[0] = 0;
364*41480Smckusick 		gp->g_lockpslot = 0;
365*41480Smckusick 	}
366*41480Smckusick #endif
367*41480Smckusick 	if (gp->g_flags & GF_WANTED) {
368*41480Smckusick 		wakeup((caddr_t)&gp->g_flags);
369*41480Smckusick 		gp->g_flags &= ~GF_WANTED;
370*41480Smckusick 	}
371*41480Smckusick 	gp->g_lockp = NULL;
372*41480Smckusick 	return(0);
373*41480Smckusick }
374*41480Smckusick 
375*41480Smckusick /*ARGSUSED*/
376*41480Smckusick grfmap(dev, off, prot)
377*41480Smckusick 	dev_t dev;
378*41480Smckusick {
379*41480Smckusick 	return(grfaddr(&grf_softc[GRFUNIT(dev)], off));
380*41480Smckusick }
381*41480Smckusick 
382*41480Smckusick #ifdef HPUXCOMPAT
383*41480Smckusick 
384*41480Smckusick /*ARGSUSED*/
385*41480Smckusick hpuxgrfioctl(dev, cmd, data, flag)
386*41480Smckusick 	dev_t dev;
387*41480Smckusick 	caddr_t data;
388*41480Smckusick {
389*41480Smckusick 	register struct grf_softc *gp = &grf_softc[GRFUNIT(dev)];
390*41480Smckusick 	int error;
391*41480Smckusick 
392*41480Smckusick 	error = 0;
393*41480Smckusick 	switch (cmd) {
394*41480Smckusick 
395*41480Smckusick 	case GCID:
396*41480Smckusick 		*(int *)data = gp->g_display.gd_id;
397*41480Smckusick 		break;
398*41480Smckusick 
399*41480Smckusick 	case GCON:
400*41480Smckusick 		error = grfon(dev);
401*41480Smckusick 		break;
402*41480Smckusick 
403*41480Smckusick 	case GCOFF:
404*41480Smckusick 		error = grfoff(dev);
405*41480Smckusick 		break;
406*41480Smckusick 
407*41480Smckusick 	case GCLOCK:
408*41480Smckusick 		error = grflock(gp, 1);
409*41480Smckusick 		break;
410*41480Smckusick 
411*41480Smckusick 	case GCUNLOCK:
412*41480Smckusick 		error = grfunlock(gp);
413*41480Smckusick 		break;
414*41480Smckusick 
415*41480Smckusick 	case GCAON:
416*41480Smckusick 	case GCAOFF:
417*41480Smckusick 		break;
418*41480Smckusick 
419*41480Smckusick 	/* GCSTATIC is implied by our implementation */
420*41480Smckusick 	case GCSTATIC_CMAP:
421*41480Smckusick 	case GCVARIABLE_CMAP:
422*41480Smckusick 		break;
423*41480Smckusick 
424*41480Smckusick #ifdef MAPMEM
425*41480Smckusick 	/* map in control regs and frame buffer */
426*41480Smckusick 	case GCMAP:
427*41480Smckusick 		error = grfmmap(dev, (caddr_t *)data);
428*41480Smckusick 		break;
429*41480Smckusick 
430*41480Smckusick 	case GCUNMAP:
431*41480Smckusick 		error = grfunmmap(dev, *(caddr_t *)data);
432*41480Smckusick 		/* XXX: HP-UX uses GCUNMAP to get rid of GCSLOT memory */
433*41480Smckusick 		if (error)
434*41480Smckusick 			error = grflckunmmap(dev, *(caddr_t *)data);
435*41480Smckusick 		break;
436*41480Smckusick 
437*41480Smckusick 	case GCSLOT:
438*41480Smckusick 	{
439*41480Smckusick 		struct grf_slot *sp = (struct grf_slot *)data;
440*41480Smckusick 
441*41480Smckusick 		sp->slot = grffindpid(gp);
442*41480Smckusick 		if (sp->slot)
443*41480Smckusick 			error = grflckmmap(dev, (caddr_t *)&sp->addr);
444*41480Smckusick 		else
445*41480Smckusick 			error = EINVAL;		/* XXX */
446*41480Smckusick 		break;
447*41480Smckusick 	}
448*41480Smckusick 
449*41480Smckusick 	/*
450*41480Smckusick 	 * XXX: only used right now to map in rbox control registers
451*41480Smckusick 	 * Will be replaced in the future with a real IOMAP interface.
452*41480Smckusick 	 */
453*41480Smckusick 	case IOMAPMAP:
454*41480Smckusick 		error = iommap(dev, (caddr_t *)data);
455*41480Smckusick 		if (!error)
456*41480Smckusick 			u.u_r.r_val1 = *(int *)data;	/* XXX: this sux */
457*41480Smckusick 		break;
458*41480Smckusick 
459*41480Smckusick 	case IOMAPUNMAP:
460*41480Smckusick 		error = iounmmap(dev, *(caddr_t *)data);
461*41480Smckusick 		break;
462*41480Smckusick #endif
463*41480Smckusick 
464*41480Smckusick 	default:
465*41480Smckusick 		error = EINVAL;
466*41480Smckusick 		break;
467*41480Smckusick 	}
468*41480Smckusick 	return(error);
469*41480Smckusick }
470*41480Smckusick 
471*41480Smckusick #endif
472*41480Smckusick 
473*41480Smckusick grfon(dev)
474*41480Smckusick 	dev_t dev;
475*41480Smckusick {
476*41480Smckusick 	int unit = GRFUNIT(dev);
477*41480Smckusick 	struct grf_softc *gp = &grf_softc[unit];
478*41480Smckusick 
479*41480Smckusick 	/*
480*41480Smckusick 	 * XXX: iteoff call relies on devices being in same order
481*41480Smckusick 	 * as ITEs and the fact that iteoff only uses the minor part
482*41480Smckusick 	 * of the dev arg.
483*41480Smckusick 	 */
484*41480Smckusick 	iteoff(unit, 3);
485*41480Smckusick 	return((*grfdev[gp->g_type].gd_mode)
486*41480Smckusick 			(gp, (dev&GRFOVDEV) ? GM_GRFOVON : GM_GRFON));
487*41480Smckusick }
488*41480Smckusick 
489*41480Smckusick grfoff(dev)
490*41480Smckusick 	dev_t dev;
491*41480Smckusick {
492*41480Smckusick 	int unit = GRFUNIT(dev);
493*41480Smckusick 	struct grf_softc *gp = &grf_softc[unit];
494*41480Smckusick 	int error;
495*41480Smckusick 
496*41480Smckusick #ifdef MAPMEM
497*41480Smckusick 	(void) grfunmmap(dev, (caddr_t)0);
498*41480Smckusick #endif
499*41480Smckusick 	error = (*grfdev[gp->g_type].gd_mode)
500*41480Smckusick 			(gp, (dev&GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF);
501*41480Smckusick 	/* XXX: see comment for iteoff above */
502*41480Smckusick 	iteon(unit, 2);
503*41480Smckusick 	return(error);
504*41480Smckusick }
505*41480Smckusick 
506*41480Smckusick grfaddr(gp, off)
507*41480Smckusick 	struct grf_softc *gp;
508*41480Smckusick 	register int off;
509*41480Smckusick {
510*41480Smckusick #ifdef MAPMEM
511*41480Smckusick 	register struct grfinfo *gi = &gp->g_display;
512*41480Smckusick 
513*41480Smckusick 	/* control registers */
514*41480Smckusick 	if (off >= 0 && off < gi->gd_regsize)
515*41480Smckusick 		return(((u_int)gi->gd_regaddr + off) >> PGSHIFT);
516*41480Smckusick 
517*41480Smckusick 	/* frame buffer */
518*41480Smckusick 	if (off >= gi->gd_regsize && off < gi->gd_regsize+gi->gd_fbsize) {
519*41480Smckusick 		off -= gi->gd_regsize;
520*41480Smckusick 		return(((u_int)gi->gd_fbaddr + off) >> PGSHIFT);
521*41480Smckusick 	}
522*41480Smckusick #endif
523*41480Smckusick 	/* bogus */
524*41480Smckusick 	return(-1);
525*41480Smckusick }
526*41480Smckusick 
527*41480Smckusick #ifdef HPUXCOMPAT
528*41480Smckusick /*
529*41480Smckusick  * Convert a BSD style minor devno to HPUX style.
530*41480Smckusick  * We cannot just create HPUX style nodes as they require 24 bits
531*41480Smckusick  * of minor device number and we only have 8.
532*41480Smckusick  * XXX: This may give the wrong result for remote stats of other
533*41480Smckusick  * machines where device 10 exists.
534*41480Smckusick  */
535*41480Smckusick grfdevno(dev)
536*41480Smckusick 	dev_t dev;
537*41480Smckusick {
538*41480Smckusick 	int unit = GRFUNIT(dev);
539*41480Smckusick 	struct grf_softc *gp = &grf_softc[unit];
540*41480Smckusick 	int newdev;
541*41480Smckusick 
542*41480Smckusick 	if (unit >= NGRF || (gp->g_flags&GF_ALIVE) == 0)
543*41480Smckusick 		return(bsdtohpuxdev(dev));
544*41480Smckusick 	/* magic major number */
545*41480Smckusick 	newdev = 12 << 24;
546*41480Smckusick 	/* now construct minor number */
547*41480Smckusick #if defined(HP360) || defined(HP370)
548*41480Smckusick 	if (gp->g_display.gd_regaddr == (caddr_t)DIOIIBASE)
549*41480Smckusick 		newdev |= 0x840200;
550*41480Smckusick 	else
551*41480Smckusick #endif
552*41480Smckusick 	if (gp->g_display.gd_regaddr != (caddr_t)GRFIADDR)
553*41480Smckusick 		newdev |= ((u_int)gp->g_display.gd_regaddr-EXTIOBASE) | 0x200;
554*41480Smckusick 	if (dev & GRFIMDEV)
555*41480Smckusick 		newdev |= 0x02;
556*41480Smckusick 	else if (dev & GRFOVDEV)
557*41480Smckusick 		newdev |= 0x01;
558*41480Smckusick #ifdef DEBUG
559*41480Smckusick 	if (grfdebug & GDB_DEVNO)
560*41480Smckusick 		printf("grfdevno: dev %x newdev %x\n", dev, newdev);
561*41480Smckusick #endif
562*41480Smckusick 	return(newdev);
563*41480Smckusick }
564*41480Smckusick #endif
565*41480Smckusick 
566*41480Smckusick #ifdef MAPMEM
567*41480Smckusick grfmapin(mp, off)
568*41480Smckusick 	struct mapmem *mp;
569*41480Smckusick {
570*41480Smckusick 	return(grfaddr(&grf_softc[GRFUNIT(mp->mm_id)], off));
571*41480Smckusick }
572*41480Smckusick 
573*41480Smckusick grfmmap(dev, addrp)
574*41480Smckusick 	dev_t dev;
575*41480Smckusick 	caddr_t *addrp;
576*41480Smckusick {
577*41480Smckusick 	struct grf_softc *gp = &grf_softc[GRFUNIT(dev)];
578*41480Smckusick 	register struct mapmem *mp;
579*41480Smckusick 	int len, grfmapin();
580*41480Smckusick 
581*41480Smckusick #ifdef DEBUG
582*41480Smckusick 	if (grfdebug & GDB_MMAP)
583*41480Smckusick 		printf("grfmmap(%d): addr %x\n", u.u_procp->p_pid, *addrp);
584*41480Smckusick #endif
585*41480Smckusick 	len = gp->g_display.gd_regsize + gp->g_display.gd_fbsize;
586*41480Smckusick 	mp = mmalloc(minor(dev), addrp, len, MM_RW|MM_CI|MM_NOCORE, &grfops);
587*41480Smckusick 	if (mp == MMNIL)
588*41480Smckusick 		return(u.u_error);
589*41480Smckusick 	if (!mmmapin(mp, grfmapin)) {
590*41480Smckusick 		mmfree(mp);
591*41480Smckusick 		return(u.u_error);
592*41480Smckusick 	}
593*41480Smckusick 	return(0);
594*41480Smckusick }
595*41480Smckusick 
596*41480Smckusick grfunmmap(dev, addr)
597*41480Smckusick 	dev_t dev;
598*41480Smckusick 	caddr_t addr;
599*41480Smckusick {
600*41480Smckusick 	register struct mapmem *mp, **mpp;
601*41480Smckusick 	int found, unit = minor(dev);
602*41480Smckusick 
603*41480Smckusick #ifdef DEBUG
604*41480Smckusick 	if (grfdebug & GDB_MMAP)
605*41480Smckusick 		printf("grfunmmap(%d): id %d addr %x\n",
606*41480Smckusick 		       u.u_procp->p_pid, unit, addr);
607*41480Smckusick #endif
608*41480Smckusick 	found = 0;
609*41480Smckusick 	mpp = &u.u_mmap;
610*41480Smckusick 	for (mp = *mpp; mp; mp = *mpp) {
611*41480Smckusick 		if (mp->mm_ops != &grfops || mp->mm_id != unit) {
612*41480Smckusick 			mpp = &mp->mm_next;
613*41480Smckusick 			continue;
614*41480Smckusick 		}
615*41480Smckusick 		if (addr &&
616*41480Smckusick 		    (addr < mp->mm_uva || addr >= mp->mm_uva+mp->mm_size)) {
617*41480Smckusick 			mpp = &mp->mm_next;
618*41480Smckusick 			continue;
619*41480Smckusick 		}
620*41480Smckusick 		grfexit(mp);
621*41480Smckusick 		found++;
622*41480Smckusick 	}
623*41480Smckusick 	return(found ? 0 : EINVAL);
624*41480Smckusick }
625*41480Smckusick 
626*41480Smckusick grfexit(mp)
627*41480Smckusick 	struct mapmem *mp;
628*41480Smckusick {
629*41480Smckusick 	struct grf_softc *gp = &grf_softc[GRFUNIT(mp->mm_id)];
630*41480Smckusick 
631*41480Smckusick #ifdef DEBUG
632*41480Smckusick 	if (grfdebug & GDB_MMAP)
633*41480Smckusick 		printf("grfexit(%d): id %d %x@%x\n",
634*41480Smckusick 		       u.u_procp->p_pid, mp->mm_id, mp->mm_size, mp->mm_uva);
635*41480Smckusick #endif
636*41480Smckusick 	(void) grfunlock(gp);
637*41480Smckusick #ifdef HPUXCOMPAT
638*41480Smckusick 	grfrmpid(gp);
639*41480Smckusick #endif
640*41480Smckusick 	mmmapout(mp);
641*41480Smckusick 	mmfree(mp);
642*41480Smckusick }
643*41480Smckusick 
644*41480Smckusick #ifdef HPUXCOMPAT
645*41480Smckusick iommap(dev, addrp)
646*41480Smckusick 	dev_t dev;
647*41480Smckusick 	caddr_t *addrp;
648*41480Smckusick {
649*41480Smckusick 	struct grf_softc *gp = &grf_softc[GRFUNIT(dev)];
650*41480Smckusick 	register struct mapmem *mp;
651*41480Smckusick 	int len, grfmapin();
652*41480Smckusick 
653*41480Smckusick #ifdef DEBUG
654*41480Smckusick 	if (grfdebug & (GDB_MMAP|GDB_IOMAP))
655*41480Smckusick 		printf("iommap(%d): addr %x\n", u.u_procp->p_pid, *addrp);
656*41480Smckusick #endif
657*41480Smckusick 	len = gp->g_display.gd_regsize;
658*41480Smckusick 	mp = mmalloc(minor(dev), addrp, len, MM_RW|MM_CI|MM_NOCORE, &grfiomops);
659*41480Smckusick 	if (mp == MMNIL)
660*41480Smckusick 		return(u.u_error);
661*41480Smckusick 	if (!mmmapin(mp, grfmapin)) {
662*41480Smckusick 		mmfree(mp);
663*41480Smckusick 		return(u.u_error);
664*41480Smckusick 	}
665*41480Smckusick 	return(0);
666*41480Smckusick }
667*41480Smckusick 
668*41480Smckusick iounmmap(dev, addr)
669*41480Smckusick 	dev_t dev;
670*41480Smckusick 	caddr_t addr;
671*41480Smckusick {
672*41480Smckusick 	struct grf_softc *gp = &grf_softc[GRFUNIT(dev)];
673*41480Smckusick 	register struct mapmem *mp, **mpp;
674*41480Smckusick 	int found, len, unit = minor(dev);
675*41480Smckusick 
676*41480Smckusick #ifdef DEBUG
677*41480Smckusick 	if (grfdebug & (GDB_MMAP|GDB_IOMAP))
678*41480Smckusick 		printf("iounmmap(%d): id %d addr %x\n",
679*41480Smckusick 		       u.u_procp->p_pid, unit, addr);
680*41480Smckusick #endif
681*41480Smckusick 	found = 0;
682*41480Smckusick 	len = gp->g_display.gd_regsize;
683*41480Smckusick 	mpp = &u.u_mmap;
684*41480Smckusick 	for (mp = *mpp; mp; mp = *mpp) {
685*41480Smckusick 		if (mp->mm_ops != &grfiomops || mp->mm_id != unit) {
686*41480Smckusick 			mpp = &mp->mm_next;
687*41480Smckusick 			continue;
688*41480Smckusick 		}
689*41480Smckusick 		if (addr &&
690*41480Smckusick 		    (addr < mp->mm_uva || addr >= mp->mm_uva+mp->mm_size ||
691*41480Smckusick 		    len != mp->mm_size)) {
692*41480Smckusick 			mpp = &mp->mm_next;
693*41480Smckusick 			continue;
694*41480Smckusick 		}
695*41480Smckusick 		grfexit(mp);
696*41480Smckusick 		found++;
697*41480Smckusick 	}
698*41480Smckusick 	return(found ? 0 : EINVAL);
699*41480Smckusick }
700*41480Smckusick 
701*41480Smckusick /*
702*41480Smckusick  * Processes involved in framebuffer mapping via GCSLOT are recorded in
703*41480Smckusick  * an array of pids.  The first element is used to record the last slot used
704*41480Smckusick  * (for faster lookups).  The remaining elements record up to GRFMAXLCK-1
705*41480Smckusick  * process ids.  Returns a slot number between 1 and GRFMAXLCK or 0 if no
706*41480Smckusick  * slot is available.
707*41480Smckusick  */
708*41480Smckusick grffindpid(gp)
709*41480Smckusick 	struct grf_softc *gp;
710*41480Smckusick {
711*41480Smckusick 	register short pid, *sp;
712*41480Smckusick 	register int i, limit;
713*41480Smckusick 	int ni;
714*41480Smckusick 
715*41480Smckusick 	if (gp->g_pid == NULL) {
716*41480Smckusick 		gp->g_pid = (short *)
717*41480Smckusick 			malloc(GRFMAXLCK * sizeof(short), M_DEVBUF, M_WAITOK);
718*41480Smckusick 		bzero((caddr_t)gp->g_pid, GRFMAXLCK * sizeof(short));
719*41480Smckusick 	}
720*41480Smckusick 	pid = u.u_procp->p_pid;
721*41480Smckusick 	ni = limit = gp->g_pid[0];
722*41480Smckusick 	for (i = 1, sp = &gp->g_pid[1]; i <= limit; i++, sp++) {
723*41480Smckusick 		if (*sp == pid)
724*41480Smckusick 			goto done;
725*41480Smckusick 		if (*sp == 0)
726*41480Smckusick 			ni = i;
727*41480Smckusick 	}
728*41480Smckusick 	i = ni;
729*41480Smckusick 	if (i < limit) {
730*41480Smckusick 		gp->g_pid[i] = pid;
731*41480Smckusick 		goto done;
732*41480Smckusick 	}
733*41480Smckusick 	if (++i == GRFMAXLCK)
734*41480Smckusick 		return(0);
735*41480Smckusick 	gp->g_pid[0] = i;
736*41480Smckusick 	gp->g_pid[i] = pid;
737*41480Smckusick done:
738*41480Smckusick #ifdef DEBUG
739*41480Smckusick 	if (grfdebug & GDB_LOCK)
740*41480Smckusick 		printf("grffindpid(%d): slot %d of %d\n",
741*41480Smckusick 		       pid, i, gp->g_pid[0]);
742*41480Smckusick #endif
743*41480Smckusick 	return(i);
744*41480Smckusick }
745*41480Smckusick 
746*41480Smckusick grfrmpid(gp)
747*41480Smckusick 	struct grf_softc *gp;
748*41480Smckusick {
749*41480Smckusick 	register short pid, *sp;
750*41480Smckusick 	register int limit, i;
751*41480Smckusick 	int mi;
752*41480Smckusick 
753*41480Smckusick 	if (gp->g_pid == NULL || (limit = gp->g_pid[0]) == 0)
754*41480Smckusick 		return;
755*41480Smckusick 	pid = u.u_procp->p_pid;
756*41480Smckusick 	limit = gp->g_pid[0];
757*41480Smckusick 	mi = 0;
758*41480Smckusick 	for (i = 1, sp = &gp->g_pid[1]; i <= limit; i++, sp++) {
759*41480Smckusick 		if (*sp == pid)
760*41480Smckusick 			*sp = 0;
761*41480Smckusick 		else if (*sp)
762*41480Smckusick 			mi = i;
763*41480Smckusick 	}
764*41480Smckusick 	i = mi;
765*41480Smckusick 	if (i < limit)
766*41480Smckusick 		gp->g_pid[0] = i;
767*41480Smckusick #ifdef DEBUG
768*41480Smckusick 	if (grfdebug & GDB_LOCK)
769*41480Smckusick 		printf("grfrmpid(%d): slot %d of %d\n",
770*41480Smckusick 		       pid, sp-gp->g_pid, gp->g_pid[0]);
771*41480Smckusick #endif
772*41480Smckusick }
773*41480Smckusick 
774*41480Smckusick /*ARGSUSED*/
775*41480Smckusick grflckmapin(mp, off)
776*41480Smckusick 	struct mapmem *mp;
777*41480Smckusick {
778*41480Smckusick 	u_int pa = kvtop((u_int)grf_softc[GRFUNIT(mp->mm_id)].g_locks);
779*41480Smckusick 
780*41480Smckusick #ifdef DEBUG
781*41480Smckusick 	if (grfdebug & GDB_LOCK)
782*41480Smckusick 		printf("grflckmapin(%d): va %x pa %x\n", u.u_procp->p_pid,
783*41480Smckusick 		       grf_softc[GRFUNIT(mp->mm_id)].g_locks, pa);
784*41480Smckusick #endif
785*41480Smckusick 	return(pa >> PGSHIFT);
786*41480Smckusick }
787*41480Smckusick 
788*41480Smckusick grflckmmap(dev, addrp)
789*41480Smckusick 	dev_t dev;
790*41480Smckusick 	caddr_t *addrp;
791*41480Smckusick {
792*41480Smckusick 	struct grf_softc *gp = &grf_softc[GRFUNIT(dev)];
793*41480Smckusick 	register struct mapmem *mp;
794*41480Smckusick 	int grflckmapin();
795*41480Smckusick 
796*41480Smckusick #ifdef DEBUG
797*41480Smckusick 	if (grfdebug & (GDB_MMAP|GDB_LOCK))
798*41480Smckusick 		printf("grflckmmap(%d): addr %x\n",
799*41480Smckusick 		       u.u_procp->p_pid, *addrp);
800*41480Smckusick #endif
801*41480Smckusick 	if (gp->g_locks == NULL) {
802*41480Smckusick 		gp->g_locks = (u_char *) cialloc(NBPG);
803*41480Smckusick 		if (gp->g_locks == NULL)
804*41480Smckusick 			return(ENOMEM);
805*41480Smckusick 	}
806*41480Smckusick 	mp = mmalloc(minor(dev), addrp, NBPG, MM_RW|MM_CI, &grflckops);
807*41480Smckusick 	if (mp == MMNIL)
808*41480Smckusick 		return(u.u_error);
809*41480Smckusick 	if (!mmmapin(mp, grflckmapin)) {
810*41480Smckusick 		mmfree(mp);
811*41480Smckusick 		return(u.u_error);
812*41480Smckusick 	}
813*41480Smckusick 	return(0);
814*41480Smckusick }
815*41480Smckusick 
816*41480Smckusick grflckunmmap(dev, addr)
817*41480Smckusick 	dev_t dev;
818*41480Smckusick 	caddr_t addr;
819*41480Smckusick {
820*41480Smckusick 	register struct mapmem *mp;
821*41480Smckusick 	int unit = minor(dev);
822*41480Smckusick 
823*41480Smckusick #ifdef DEBUG
824*41480Smckusick 	if (grfdebug & (GDB_MMAP|GDB_LOCK))
825*41480Smckusick 		printf("grflckunmmap(%d): id %d addr %x\n",
826*41480Smckusick 		       u.u_procp->p_pid, unit, addr);
827*41480Smckusick #endif
828*41480Smckusick 	for (mp = u.u_mmap; mp; mp = mp->mm_next)
829*41480Smckusick 		if (mp->mm_ops == &grflckops && mp->mm_id == unit &&
830*41480Smckusick 		    mp->mm_uva == addr) {
831*41480Smckusick 			grfexit(mp);
832*41480Smckusick 			return(0);
833*41480Smckusick 		}
834*41480Smckusick 	return(EINVAL);
835*41480Smckusick }
836*41480Smckusick #endif	/* HPUXCOMPAT */
837*41480Smckusick #endif	/* MAPMEM */
838*41480Smckusick #endif	/* NGRF > 0 */
839