xref: /original-bsd/sys/hp/dev/grf.c (revision 0edb85a7)
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.2 (Berkeley) 05/25/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 	int error;
299 	extern char devioc[];
300 
301 #ifdef DEBUG
302 	if (grfdebug & GDB_LOCK)
303 		printf("grflock(%d): dev %x flags %x lockpid %x\n",
304 		       u.u_procp->p_pid, gp-grf_softc, gp->g_flags,
305 		       gp->g_lockp ? gp->g_lockp->p_pid : -1);
306 #endif
307 #ifdef HPUXCOMPAT
308 	if (gp->g_pid) {
309 #ifdef DEBUG
310 		if (grfdebug & GDB_LOCK)
311 			printf("  lock[0] %d lockslot %d lock[lockslot] %d\n",
312 			       gp->g_locks[0], gp->g_lockpslot,
313 			       gp->g_locks[gp->g_lockpslot]);
314 #endif
315 		gp->g_locks[0] = 0;
316 		if (gp->g_locks[gp->g_lockpslot] == 0) {
317 			gp->g_lockp = NULL;
318 			gp->g_lockpslot = 0;
319 		}
320 	}
321 #endif
322 	if (gp->g_lockp) {
323 		if (gp->g_lockp == u.u_procp)
324 			return(EBUSY);
325 		if (!block)
326 			return(EAGAIN);
327 		do {
328 			gp->g_flags |= GF_WANTED;
329 			sleep((caddr_t)&gp->g_flags, PZERO+1);
330 
331 			if (error = tsleep((caddr_t)&gp->g_flags,
332 					   (PZERO+1) | PCATCH, devioc, 0))
333 				return (error);
334 
335 		} while (gp->g_lockp);
336 	}
337 	gp->g_lockp = u.u_procp;
338 #ifdef HPUXCOMPAT
339 	if (gp->g_pid) {
340 		int slot = grffindpid(gp);
341 #ifdef DEBUG
342 		if (grfdebug & GDB_LOCK)
343 			printf("  slot %d\n", slot);
344 #endif
345 		gp->g_lockpslot = gp->g_locks[0] = slot;
346 		gp->g_locks[slot] = 1;
347 	}
348 #endif
349 	return(0);
350 }
351 
352 grfunlock(gp)
353 	register struct grf_softc *gp;
354 {
355 #ifdef DEBUG
356 	if (grfdebug & GDB_LOCK)
357 		printf("grfunlock(%d): dev %x flags %x lockpid %d\n",
358 		       u.u_procp->p_pid, gp-grf_softc, gp->g_flags,
359 		       gp->g_lockp ? gp->g_lockp->p_pid : -1);
360 #endif
361 	if (gp->g_lockp != u.u_procp)
362 		return(EBUSY);
363 #ifdef HPUXCOMPAT
364 	if (gp->g_pid) {
365 #ifdef DEBUG
366 		if (grfdebug & GDB_LOCK)
367 			printf("  lock[0] %d lockslot %d lock[lockslot] %d\n",
368 			       gp->g_locks[0], gp->g_lockpslot,
369 			       gp->g_locks[gp->g_lockpslot]);
370 #endif
371 		gp->g_locks[gp->g_lockpslot] = gp->g_locks[0] = 0;
372 		gp->g_lockpslot = 0;
373 	}
374 #endif
375 	if (gp->g_flags & GF_WANTED) {
376 		wakeup((caddr_t)&gp->g_flags);
377 		gp->g_flags &= ~GF_WANTED;
378 	}
379 	gp->g_lockp = NULL;
380 	return(0);
381 }
382 
383 /*ARGSUSED*/
384 grfmap(dev, off, prot)
385 	dev_t dev;
386 {
387 	return(grfaddr(&grf_softc[GRFUNIT(dev)], off));
388 }
389 
390 #ifdef HPUXCOMPAT
391 
392 /*ARGSUSED*/
393 hpuxgrfioctl(dev, cmd, data, flag)
394 	dev_t dev;
395 	caddr_t data;
396 {
397 	register struct grf_softc *gp = &grf_softc[GRFUNIT(dev)];
398 	int error;
399 
400 	error = 0;
401 	switch (cmd) {
402 
403 	case GCID:
404 		*(int *)data = gp->g_display.gd_id;
405 		break;
406 
407 	case GCON:
408 		error = grfon(dev);
409 		break;
410 
411 	case GCOFF:
412 		error = grfoff(dev);
413 		break;
414 
415 	case GCLOCK:
416 		error = grflock(gp, 1);
417 		break;
418 
419 	case GCUNLOCK:
420 		error = grfunlock(gp);
421 		break;
422 
423 	case GCAON:
424 	case GCAOFF:
425 		break;
426 
427 	/* GCSTATIC is implied by our implementation */
428 	case GCSTATIC_CMAP:
429 	case GCVARIABLE_CMAP:
430 		break;
431 
432 #ifdef MAPMEM
433 	/* map in control regs and frame buffer */
434 	case GCMAP:
435 		error = grfmmap(dev, (caddr_t *)data);
436 		break;
437 
438 	case GCUNMAP:
439 		error = grfunmmap(dev, *(caddr_t *)data);
440 		/* XXX: HP-UX uses GCUNMAP to get rid of GCSLOT memory */
441 		if (error)
442 			error = grflckunmmap(dev, *(caddr_t *)data);
443 		break;
444 
445 	case GCSLOT:
446 	{
447 		struct grf_slot *sp = (struct grf_slot *)data;
448 
449 		sp->slot = grffindpid(gp);
450 		if (sp->slot)
451 			error = grflckmmap(dev, (caddr_t *)&sp->addr);
452 		else
453 			error = EINVAL;		/* XXX */
454 		break;
455 	}
456 
457 	/*
458 	 * XXX: only used right now to map in rbox control registers
459 	 * Will be replaced in the future with a real IOMAP interface.
460 	 */
461 	case IOMAPMAP:
462 		error = iommap(dev, (caddr_t *)data);
463 		if (!error)
464 			u.u_r.r_val1 = *(int *)data;	/* XXX: this sux */
465 		break;
466 
467 	case IOMAPUNMAP:
468 		error = iounmmap(dev, *(caddr_t *)data);
469 		break;
470 #endif
471 
472 	default:
473 		error = EINVAL;
474 		break;
475 	}
476 	return(error);
477 }
478 
479 #endif
480 
481 grfon(dev)
482 	dev_t dev;
483 {
484 	int unit = GRFUNIT(dev);
485 	struct grf_softc *gp = &grf_softc[unit];
486 
487 	/*
488 	 * XXX: iteoff call relies on devices being in same order
489 	 * as ITEs and the fact that iteoff only uses the minor part
490 	 * of the dev arg.
491 	 */
492 	iteoff(unit, 3);
493 	return((*grfdev[gp->g_type].gd_mode)
494 			(gp, (dev&GRFOVDEV) ? GM_GRFOVON : GM_GRFON));
495 }
496 
497 grfoff(dev)
498 	dev_t dev;
499 {
500 	int unit = GRFUNIT(dev);
501 	struct grf_softc *gp = &grf_softc[unit];
502 	int error;
503 
504 #ifdef MAPMEM
505 	(void) grfunmmap(dev, (caddr_t)0);
506 #endif
507 	error = (*grfdev[gp->g_type].gd_mode)
508 			(gp, (dev&GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF);
509 	/* XXX: see comment for iteoff above */
510 	iteon(unit, 2);
511 	return(error);
512 }
513 
514 grfaddr(gp, off)
515 	struct grf_softc *gp;
516 	register int off;
517 {
518 #ifdef MAPMEM
519 	register struct grfinfo *gi = &gp->g_display;
520 
521 	/* control registers */
522 	if (off >= 0 && off < gi->gd_regsize)
523 		return(((u_int)gi->gd_regaddr + off) >> PGSHIFT);
524 
525 	/* frame buffer */
526 	if (off >= gi->gd_regsize && off < gi->gd_regsize+gi->gd_fbsize) {
527 		off -= gi->gd_regsize;
528 		return(((u_int)gi->gd_fbaddr + off) >> PGSHIFT);
529 	}
530 #endif
531 	/* bogus */
532 	return(-1);
533 }
534 
535 #ifdef HPUXCOMPAT
536 /*
537  * Convert a BSD style minor devno to HPUX style.
538  * We cannot just create HPUX style nodes as they require 24 bits
539  * of minor device number and we only have 8.
540  * XXX: This may give the wrong result for remote stats of other
541  * machines where device 10 exists.
542  */
543 grfdevno(dev)
544 	dev_t dev;
545 {
546 	int unit = GRFUNIT(dev);
547 	struct grf_softc *gp = &grf_softc[unit];
548 	int newdev;
549 
550 	if (unit >= NGRF || (gp->g_flags&GF_ALIVE) == 0)
551 		return(bsdtohpuxdev(dev));
552 	/* magic major number */
553 	newdev = 12 << 24;
554 	/* now construct minor number */
555 #if defined(HP360) || defined(HP370)
556 	if (gp->g_display.gd_regaddr == (caddr_t)DIOIIBASE)
557 		newdev |= 0x840200;
558 	else
559 #endif
560 	if (gp->g_display.gd_regaddr != (caddr_t)GRFIADDR)
561 		newdev |= ((u_int)gp->g_display.gd_regaddr-EXTIOBASE) | 0x200;
562 	if (dev & GRFIMDEV)
563 		newdev |= 0x02;
564 	else if (dev & GRFOVDEV)
565 		newdev |= 0x01;
566 #ifdef DEBUG
567 	if (grfdebug & GDB_DEVNO)
568 		printf("grfdevno: dev %x newdev %x\n", dev, newdev);
569 #endif
570 	return(newdev);
571 }
572 #endif
573 
574 #ifdef MAPMEM
575 grfmapin(mp, off)
576 	struct mapmem *mp;
577 {
578 	return(grfaddr(&grf_softc[GRFUNIT(mp->mm_id)], off));
579 }
580 
581 grfmmap(dev, addrp)
582 	dev_t dev;
583 	caddr_t *addrp;
584 {
585 	struct grf_softc *gp = &grf_softc[GRFUNIT(dev)];
586 	register struct mapmem *mp;
587 	int len, grfmapin();
588 
589 #ifdef DEBUG
590 	if (grfdebug & GDB_MMAP)
591 		printf("grfmmap(%d): addr %x\n", u.u_procp->p_pid, *addrp);
592 #endif
593 	len = gp->g_display.gd_regsize + gp->g_display.gd_fbsize;
594 	mp = mmalloc(minor(dev), addrp, len, MM_RW|MM_CI|MM_NOCORE, &grfops);
595 	if (mp == MMNIL)
596 		return(u.u_error);
597 	if (!mmmapin(mp, grfmapin)) {
598 		mmfree(mp);
599 		return(u.u_error);
600 	}
601 	return(0);
602 }
603 
604 grfunmmap(dev, addr)
605 	dev_t dev;
606 	caddr_t addr;
607 {
608 	register struct mapmem *mp, **mpp;
609 	int found, unit = minor(dev);
610 
611 #ifdef DEBUG
612 	if (grfdebug & GDB_MMAP)
613 		printf("grfunmmap(%d): id %d addr %x\n",
614 		       u.u_procp->p_pid, unit, addr);
615 #endif
616 	found = 0;
617 	mpp = &u.u_mmap;
618 	for (mp = *mpp; mp; mp = *mpp) {
619 		if (mp->mm_ops != &grfops || mp->mm_id != unit) {
620 			mpp = &mp->mm_next;
621 			continue;
622 		}
623 		if (addr &&
624 		    (addr < mp->mm_uva || addr >= mp->mm_uva+mp->mm_size)) {
625 			mpp = &mp->mm_next;
626 			continue;
627 		}
628 		grfexit(mp);
629 		found++;
630 	}
631 	return(found ? 0 : EINVAL);
632 }
633 
634 grfexit(mp)
635 	struct mapmem *mp;
636 {
637 	struct grf_softc *gp = &grf_softc[GRFUNIT(mp->mm_id)];
638 
639 #ifdef DEBUG
640 	if (grfdebug & GDB_MMAP)
641 		printf("grfexit(%d): id %d %x@%x\n",
642 		       u.u_procp->p_pid, mp->mm_id, mp->mm_size, mp->mm_uva);
643 #endif
644 	(void) grfunlock(gp);
645 #ifdef HPUXCOMPAT
646 	grfrmpid(gp);
647 #endif
648 	mmmapout(mp);
649 	mmfree(mp);
650 }
651 
652 #ifdef HPUXCOMPAT
653 iommap(dev, addrp)
654 	dev_t dev;
655 	caddr_t *addrp;
656 {
657 	struct grf_softc *gp = &grf_softc[GRFUNIT(dev)];
658 	register struct mapmem *mp;
659 	int len, grfmapin();
660 
661 #ifdef DEBUG
662 	if (grfdebug & (GDB_MMAP|GDB_IOMAP))
663 		printf("iommap(%d): addr %x\n", u.u_procp->p_pid, *addrp);
664 #endif
665 	len = gp->g_display.gd_regsize;
666 	mp = mmalloc(minor(dev), addrp, len, MM_RW|MM_CI|MM_NOCORE, &grfiomops);
667 	if (mp == MMNIL)
668 		return(u.u_error);
669 	if (!mmmapin(mp, grfmapin)) {
670 		mmfree(mp);
671 		return(u.u_error);
672 	}
673 	return(0);
674 }
675 
676 iounmmap(dev, addr)
677 	dev_t dev;
678 	caddr_t addr;
679 {
680 	struct grf_softc *gp = &grf_softc[GRFUNIT(dev)];
681 	register struct mapmem *mp, **mpp;
682 	int found, len, unit = minor(dev);
683 
684 #ifdef DEBUG
685 	if (grfdebug & (GDB_MMAP|GDB_IOMAP))
686 		printf("iounmmap(%d): id %d addr %x\n",
687 		       u.u_procp->p_pid, unit, addr);
688 #endif
689 	found = 0;
690 	len = gp->g_display.gd_regsize;
691 	mpp = &u.u_mmap;
692 	for (mp = *mpp; mp; mp = *mpp) {
693 		if (mp->mm_ops != &grfiomops || mp->mm_id != unit) {
694 			mpp = &mp->mm_next;
695 			continue;
696 		}
697 		if (addr &&
698 		    (addr < mp->mm_uva || addr >= mp->mm_uva+mp->mm_size ||
699 		    len != mp->mm_size)) {
700 			mpp = &mp->mm_next;
701 			continue;
702 		}
703 		grfexit(mp);
704 		found++;
705 	}
706 	return(found ? 0 : EINVAL);
707 }
708 
709 /*
710  * Processes involved in framebuffer mapping via GCSLOT are recorded in
711  * an array of pids.  The first element is used to record the last slot used
712  * (for faster lookups).  The remaining elements record up to GRFMAXLCK-1
713  * process ids.  Returns a slot number between 1 and GRFMAXLCK or 0 if no
714  * slot is available.
715  */
716 grffindpid(gp)
717 	struct grf_softc *gp;
718 {
719 	register short pid, *sp;
720 	register int i, limit;
721 	int ni;
722 
723 	if (gp->g_pid == NULL) {
724 		gp->g_pid = (short *)
725 			malloc(GRFMAXLCK * sizeof(short), M_DEVBUF, M_WAITOK);
726 		bzero((caddr_t)gp->g_pid, GRFMAXLCK * sizeof(short));
727 	}
728 	pid = u.u_procp->p_pid;
729 	ni = limit = gp->g_pid[0];
730 	for (i = 1, sp = &gp->g_pid[1]; i <= limit; i++, sp++) {
731 		if (*sp == pid)
732 			goto done;
733 		if (*sp == 0)
734 			ni = i;
735 	}
736 	i = ni;
737 	if (i < limit) {
738 		gp->g_pid[i] = pid;
739 		goto done;
740 	}
741 	if (++i == GRFMAXLCK)
742 		return(0);
743 	gp->g_pid[0] = i;
744 	gp->g_pid[i] = pid;
745 done:
746 #ifdef DEBUG
747 	if (grfdebug & GDB_LOCK)
748 		printf("grffindpid(%d): slot %d of %d\n",
749 		       pid, i, gp->g_pid[0]);
750 #endif
751 	return(i);
752 }
753 
754 grfrmpid(gp)
755 	struct grf_softc *gp;
756 {
757 	register short pid, *sp;
758 	register int limit, i;
759 	int mi;
760 
761 	if (gp->g_pid == NULL || (limit = gp->g_pid[0]) == 0)
762 		return;
763 	pid = u.u_procp->p_pid;
764 	limit = gp->g_pid[0];
765 	mi = 0;
766 	for (i = 1, sp = &gp->g_pid[1]; i <= limit; i++, sp++) {
767 		if (*sp == pid)
768 			*sp = 0;
769 		else if (*sp)
770 			mi = i;
771 	}
772 	i = mi;
773 	if (i < limit)
774 		gp->g_pid[0] = i;
775 #ifdef DEBUG
776 	if (grfdebug & GDB_LOCK)
777 		printf("grfrmpid(%d): slot %d of %d\n",
778 		       pid, sp-gp->g_pid, gp->g_pid[0]);
779 #endif
780 }
781 
782 /*ARGSUSED*/
783 grflckmapin(mp, off)
784 	struct mapmem *mp;
785 {
786 	u_int pa = kvtop((u_int)grf_softc[GRFUNIT(mp->mm_id)].g_locks);
787 
788 #ifdef DEBUG
789 	if (grfdebug & GDB_LOCK)
790 		printf("grflckmapin(%d): va %x pa %x\n", u.u_procp->p_pid,
791 		       grf_softc[GRFUNIT(mp->mm_id)].g_locks, pa);
792 #endif
793 	return(pa >> PGSHIFT);
794 }
795 
796 grflckmmap(dev, addrp)
797 	dev_t dev;
798 	caddr_t *addrp;
799 {
800 	struct grf_softc *gp = &grf_softc[GRFUNIT(dev)];
801 	register struct mapmem *mp;
802 	int grflckmapin();
803 
804 #ifdef DEBUG
805 	if (grfdebug & (GDB_MMAP|GDB_LOCK))
806 		printf("grflckmmap(%d): addr %x\n",
807 		       u.u_procp->p_pid, *addrp);
808 #endif
809 	if (gp->g_locks == NULL) {
810 		gp->g_locks = (u_char *) cialloc(NBPG);
811 		if (gp->g_locks == NULL)
812 			return(ENOMEM);
813 	}
814 	mp = mmalloc(minor(dev), addrp, NBPG, MM_RW|MM_CI, &grflckops);
815 	if (mp == MMNIL)
816 		return(u.u_error);
817 	if (!mmmapin(mp, grflckmapin)) {
818 		mmfree(mp);
819 		return(u.u_error);
820 	}
821 	return(0);
822 }
823 
824 grflckunmmap(dev, addr)
825 	dev_t dev;
826 	caddr_t addr;
827 {
828 	register struct mapmem *mp;
829 	int unit = minor(dev);
830 
831 #ifdef DEBUG
832 	if (grfdebug & (GDB_MMAP|GDB_LOCK))
833 		printf("grflckunmmap(%d): id %d addr %x\n",
834 		       u.u_procp->p_pid, unit, addr);
835 #endif
836 	for (mp = u.u_mmap; mp; mp = mp->mm_next)
837 		if (mp->mm_ops == &grflckops && mp->mm_id == unit &&
838 		    mp->mm_uva == addr) {
839 			grfexit(mp);
840 			return(0);
841 		}
842 	return(EINVAL);
843 }
844 #endif	/* HPUXCOMPAT */
845 #endif	/* MAPMEM */
846 #endif	/* NGRF > 0 */
847