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