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