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