xref: /netbsd-src/sys/arch/x68k/dev/grf.c (revision 2a399c6883d870daece976daec6ffa7bb7f934ce)
1 /*	$NetBSD: grf.c,v 1.6 1997/10/12 18:06:23 oki Exp $	*/
2 
3 /*
4  * Copyright (c) 1988 University of Utah.
5  * Copyright (c) 1990, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * the Systems Programming Group of the University of Utah Computer
10  * Science Department.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *	This product includes software developed by the University of
23  *	California, Berkeley and its contributors.
24  * 4. Neither the name of the University nor the names of its contributors
25  *    may be used to endorse or promote products derived from this software
26  *    without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38  * SUCH DAMAGE.
39  *
40  * from: Utah $Hdr: grf.c 1.36 93/08/13$
41  *
42  *	@(#)grf.c	8.4 (Berkeley) 1/12/94
43  */
44 
45 /*
46  * Graphics display driver for the X68K machines.
47  * This is the hardware-independent portion of the driver.
48  * Hardware access is through the machine dependent grf switch routines.
49  */
50 
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/device.h>
54 #include <sys/proc.h>
55 #include <sys/ioctl.h>
56 #include <sys/file.h>
57 #include <sys/malloc.h>
58 #include <sys/vnode.h>
59 #include <sys/mman.h>
60 #include <sys/poll.h>
61 #include <sys/conf.h>
62 
63 #include <x68k/dev/grfioctl.h>
64 #include <x68k/dev/grfvar.h>
65 #include <x68k/dev/itevar.h>
66 
67 #include <machine/cpu.h>
68 
69 #ifdef COMPAT_HPUX
70 #include <compat/hpux/hpux.h>
71 extern struct emul emul_hpux;
72 #endif
73 
74 #include <vm/vm.h>
75 #include <vm/vm_kern.h>
76 #include <vm/vm_page.h>
77 #include <vm/vm_pager.h>
78 
79 #include <miscfs/specfs/specdev.h>
80 
81 #include "ite.h"
82 #if NITE == 0
83 #define	iteon(u,f)
84 #define	iteoff(u,f)
85 #endif
86 
87 #ifdef DEBUG
88 int grfdebug = 0;
89 #define GDB_DEVNO	0x01
90 #define GDB_MMAP	0x02
91 #define GDB_IOMAP	0x04
92 #define GDB_LOCK	0x08
93 #endif
94 
95 struct cfdriver grf_cd;
96 
97 cdev_decl(grf);
98 int grfon __P((dev_t));
99 int grfoff __P((dev_t));
100 int grfaddr __P((struct grf_softc *, int));
101 int grfmap __P((dev_t, caddr_t *, struct proc *));
102 int grfunmap __P((dev_t, caddr_t, struct proc *));
103 
104 /*ARGSUSED*/
105 int
106 grfopen(dev, flags, mode, p)
107 	dev_t dev;
108 	int flags, mode;
109 	struct proc *p;
110 {
111 	int unit = GRFUNIT(dev);
112 	register struct grf_softc *gp = grf_cd.cd_devs[unit];
113 	int error = 0;
114 
115 	if (unit >= grf_cd.cd_ndevs || (gp->g_flags & GF_ALIVE) == 0)
116 		return(ENXIO);
117 	if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE))
118 		return(EBUSY);
119 #ifdef COMPAT_HPUX
120 	/*
121 	 * XXX: cannot handle both HPUX and BSD processes at the same time
122 	 */
123 	if (curproc->p_emul == &emul_hpux)
124 		if (gp->g_flags & GF_BSDOPEN)
125 			return(EBUSY);
126 		else
127 			gp->g_flags |= GF_HPUXOPEN;
128 	else
129 		if (gp->g_flags & GF_HPUXOPEN)
130 			return(EBUSY);
131 		else
132 			gp->g_flags |= GF_BSDOPEN;
133 #endif
134 	/*
135 	 * First open.
136 	 * XXX: always put in graphics mode.
137 	 */
138 	error = 0;
139 	if ((gp->g_flags & GF_OPEN) == 0) {
140 		gp->g_flags |= GF_OPEN;
141 		error = grfon(dev);
142 	}
143 	return(error);
144 }
145 
146 /*ARGSUSED*/
147 int
148 grfclose(dev, flags, mode, p)
149 	dev_t dev;
150 	int flags, mode;
151 	struct proc *p;
152 {
153 	register struct grf_softc *gp = grf_cd.cd_devs[GRFUNIT(dev)];
154 
155 	(void) grfoff(dev);
156 #ifdef COMPAT_HPUX
157 	(void) grfunlock(gp);
158 #endif
159 	gp->g_flags &= GF_ALIVE;
160 	return(0);
161 }
162 
163 /*ARGSUSED*/
164 int
165 grfioctl(dev, cmd, data, flag, p)
166 	dev_t dev;
167 	u_long cmd;
168 	caddr_t data;
169 	int flag;
170 	struct proc *p;
171 {
172 	int unit = GRFUNIT(dev);
173 	register struct grf_softc *gp = grf_cd.cd_devs[unit];
174 	int error;
175 
176 #ifdef COMPAT_HPUX
177 	if (p->p_emul == &emul_hpux)
178 		return(hpuxgrfioctl(dev, cmd, data, flag, p));
179 #endif
180 	error = 0;
181 	switch (cmd) {
182 
183 	case GRFIOCGINFO:
184 		bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo));
185 		break;
186 
187 	case GRFIOCON:
188 		error = grfon(dev);
189 		break;
190 
191 	case GRFIOCOFF:
192 		error = grfoff(dev);
193 		break;
194 
195 	case GRFIOCMAP:
196 		error = grfmap(dev, (caddr_t *)data, p);
197 		break;
198 
199 	case GRFIOCUNMAP:
200 		error = grfunmap(dev, *(caddr_t *)data, p);
201 		break;
202 
203 	case GRFSETVMODE:
204 		error = (*gp->g_sw->gd_mode)(gp, GM_GRFSETVMODE, data);
205 		if (error == 0)
206 			ite_reinit(unit);
207 		break;
208 
209 	default:
210 		error = EINVAL;
211 		break;
212 
213 	}
214 	return(error);
215 }
216 
217 /*ARGSUSED*/
218 int
219 grfpoll(dev, events, p)
220 	dev_t dev;
221 	int events;
222 	struct proc *p;
223 {
224 	int revents = 0;
225 
226 	if (events & (POLLOUT | POLLWRNORM))
227 		revents |= events & (POLLOUT | POLLWRNORM);
228 	return (revents);
229 }
230 
231 /*ARGSUSED*/
232 int
233 grfmmap(dev, off, prot)
234 	dev_t dev;
235 	int off, prot;
236 {
237 	return (grfaddr(grf_cd.cd_devs[GRFUNIT(dev)], off));
238 }
239 
240 int
241 grfon(dev)
242 	dev_t dev;
243 {
244 	int unit = GRFUNIT(dev);
245 	struct grf_softc *gp = grf_cd.cd_devs[unit];
246 
247 	/*
248 	 * XXX: iteoff call relies on devices being in same order
249 	 * as ITEs and the fact that iteoff only uses the minor part
250 	 * of the dev arg.
251 	 */
252 	iteoff(unit, 2);
253 	return((*gp->g_sw->gd_mode)(gp,
254 				    (dev&GRFOVDEV) ? GM_GRFOVON : GM_GRFON,
255 				    (caddr_t)0));
256 }
257 
258 int
259 grfoff(dev)
260 	dev_t dev;
261 {
262 	int unit = GRFUNIT(dev);
263 	struct grf_softc *gp = grf_cd.cd_devs[unit];
264 	int error;
265 
266 	(void) grfunmap(dev, (caddr_t)0, curproc);
267 	error = (*gp->g_sw->gd_mode)(gp,
268 				     (dev&GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF,
269 				     (caddr_t)0);
270 	/* XXX: see comment for iteoff above */
271 	iteon(unit, 2);
272 	return(error);
273 }
274 
275 int
276 grfaddr(gp, off)
277 	struct grf_softc *gp;
278 	register int off;
279 {
280 	register struct grfinfo *gi = &gp->g_display;
281 
282 	/* control registers */
283 	if (off >= 0 && off < gi->gd_regsize)
284 		return(((u_int)gi->gd_regaddr + off) >> PGSHIFT);
285 
286 	/* frame buffer */
287 	if (off >= gi->gd_regsize && off < gi->gd_regsize+gi->gd_fbsize) {
288 		off -= gi->gd_regsize;
289 		return(((u_int)gi->gd_fbaddr + off) >> PGSHIFT);
290 	}
291 	/* bogus */
292 	return(-1);
293 }
294 
295 /*
296  * HP-UX compatibility routines
297  */
298 #ifdef COMPAT_HPUX
299 
300 /*ARGSUSED*/
301 hpuxgrfioctl(dev, cmd, data, flag, p)
302 	dev_t dev;
303 	u_long cmd;
304 	caddr_t data;
305 	int flag;
306 	struct proc *p;
307 {
308 	register struct grf_softc *gp = grf_cd.cd_devs[GRFUNIT(dev)];
309 	int error;
310 
311 	error = 0;
312 	switch (cmd) {
313 
314 	case GCID:
315 		*(int *)data = gp->g_display.gd_id;
316 		break;
317 
318 	case GCON:
319 		error = grfon(dev);
320 		break;
321 
322 	case GCOFF:
323 		error = grfoff(dev);
324 		break;
325 
326 	case GCLOCK:
327 		error = grflock(gp, 1);
328 		break;
329 
330 	case GCUNLOCK:
331 		error = grfunlock(gp);
332 		break;
333 
334 	case GCAON:
335 	case GCAOFF:
336 		break;
337 
338 	/* GCSTATIC is implied by our implementation */
339 	case GCSTATIC_CMAP:
340 	case GCVARIABLE_CMAP:
341 		break;
342 
343 	/* map in control regs and frame buffer */
344 	case GCMAP:
345 		error = grfmap(dev, (caddr_t *)data, p);
346 		break;
347 
348 	case GCUNMAP:
349 		error = grfunmap(dev, *(caddr_t *)data, p);
350 		/* XXX: HP-UX uses GCUNMAP to get rid of GCSLOT memory */
351 		if (error)
352 			error = grflckunmmap(dev, *(caddr_t *)data);
353 		break;
354 
355 	case GCSLOT:
356 	{
357 		struct grf_slot *sp = (struct grf_slot *)data;
358 
359 		sp->slot = grffindpid(gp);
360 		if (sp->slot) {
361 			error = grflckmmap(dev, (caddr_t *)&sp->addr);
362 			if (error && gp->g_pid) {
363 				free((caddr_t)gp->g_pid, M_DEVBUF);
364 				gp->g_pid = NULL;
365 			}
366 		} else
367 			error = EINVAL;		/* XXX */
368 		break;
369 	}
370 
371 	case GCDESCRIBE:
372 		error = (*gp->g_sw->gd_mode)(gp, GM_DESCRIBE, data);
373 		break;
374 
375 	/*
376 	 * XXX: only used right now to map in rbox control registers
377 	 * Will be replaced in the future with a real IOMAP interface.
378 	 */
379 	case IOMAPMAP:
380 		error = iommap(dev, (caddr_t *)data);
381 #if 0
382 		/*
383 		 * It may not be worth kludging this (using p_devtmp) to
384 		 * make this work.  It was an undocumented side-effect
385 		 * in HP-UX that the mapped address was the return value
386 		 * of the ioctl.  The only thing I remember that counted
387 		 * on this behavior was the rbox X10 server.
388 		 */
389 		if (!error)
390 			u.u_r.r_val1 = *(int *)data;	/* XXX: this sux */
391 #endif
392 		break;
393 
394 	case IOMAPUNMAP:
395 		error = iounmmap(dev, *(caddr_t *)data);
396 		break;
397 
398 	default:
399 		error = EINVAL;
400 		break;
401 	}
402 	return(error);
403 }
404 
405 grflock(gp, block)
406 	register struct grf_softc *gp;
407 	int block;
408 {
409 	struct proc *p = curproc;		/* XXX */
410 	int error;
411 	extern char devioc[];
412 
413 #ifdef DEBUG
414 	if (grfdebug & GDB_LOCK)
415 		printf("grflock(%d): dev %x flags %x lockpid %x\n",
416 		       p->p_pid, gp-grf_softc, gp->g_flags,
417 		       gp->g_lockp ? gp->g_lockp->p_pid : -1);
418 #endif
419 	if (gp->g_pid) {
420 #ifdef DEBUG
421 		if (grfdebug & GDB_LOCK)
422 			printf(" lockpslot %d lockslot %d lock[lockslot] %d\n",
423 			       gp->g_lock->gl_lockslot, gp->g_lockpslot,
424 			       gp->g_lock->gl_locks[gp->g_lockpslot]);
425 #endif
426 		gp->g_lock->gl_lockslot = 0;
427 		if (gp->g_lock->gl_locks[gp->g_lockpslot] == 0) {
428 			gp->g_lockp = NULL;
429 			gp->g_lockpslot = 0;
430 		}
431 	}
432 	if (gp->g_lockp) {
433 		if (gp->g_lockp == p)
434 			return(EBUSY);
435 		if (!block)
436 			return(OEAGAIN);
437 		do {
438 			gp->g_flags |= GF_WANTED;
439 			if (error = tsleep((caddr_t)&gp->g_flags,
440 					   (PZERO+1) | PCATCH, devioc, 0))
441 				return (error);
442 		} while (gp->g_lockp);
443 	}
444 	gp->g_lockp = p;
445 	if (gp->g_pid) {
446 		int slot = grffindpid(gp);
447 
448 #ifdef DEBUG
449 		if (grfdebug & GDB_LOCK)
450 			printf("  slot %d\n", slot);
451 #endif
452 		gp->g_lockpslot = gp->g_lock->gl_lockslot = slot;
453 		gp->g_lock->gl_locks[slot] = 1;
454 	}
455 	return(0);
456 }
457 
458 grfunlock(gp)
459 	register struct grf_softc *gp;
460 {
461 #ifdef DEBUG
462 	if (grfdebug & GDB_LOCK)
463 		printf("grfunlock(%d): dev %x flags %x lockpid %d\n",
464 		       curproc->p_pid, gp-grf_softc, gp->g_flags,
465 		       gp->g_lockp ? gp->g_lockp->p_pid : -1);
466 #endif
467 	if (gp->g_lockp != curproc)
468 		return(EBUSY);
469 	if (gp->g_pid) {
470 #ifdef DEBUG
471 		if (grfdebug & GDB_LOCK)
472 			printf(" lockpslot %d lockslot %d lock[lockslot] %d\n",
473 			       gp->g_lock->gl_lockslot, gp->g_lockpslot,
474 			       gp->g_lock->gl_locks[gp->g_lockpslot]);
475 #endif
476 		gp->g_lock->gl_locks[gp->g_lockpslot] = 0;
477 		gp->g_lockpslot = gp->g_lock->gl_lockslot = 0;
478 	}
479 	if (gp->g_flags & GF_WANTED) {
480 		wakeup((caddr_t)&gp->g_flags);
481 		gp->g_flags &= ~GF_WANTED;
482 	}
483 	gp->g_lockp = NULL;
484 	return(0);
485 }
486 
487 /*
488  * Convert a BSD style minor devno to HPUX style.
489  * We cannot just create HPUX style nodes as they require 24 bits
490  * of minor device number and we only have 8.
491  * XXX: This may give the wrong result for remote stats of other
492  * machines where device 10 exists.
493  */
494 grfdevno(dev)
495 	dev_t dev;
496 {
497 	int unit = GRFUNIT(dev);
498 	struct grf_softc *gp = grf_cd.cd_devs[unit];
499 	int newdev;
500 
501 	if (unit >= grf_cd.cd_ndevs || (gp->g_flags&GF_ALIVE) == 0)
502 		return(bsdtohpuxdev(dev));
503 	/* magic major number */
504 	newdev = 12 << 24;
505 	/* now construct minor number */
506 	if (gp->g_display.gd_regaddr != (caddr_t)GRFIADDR) {
507 		int sc = patosc(gp->g_display.gd_regaddr);
508 		newdev |= (sc << 16) | 0x200;
509 	}
510 	if (dev & GRFIMDEV)
511 		newdev |= 0x02;
512 	else if (dev & GRFOVDEV)
513 		newdev |= 0x01;
514 #ifdef DEBUG
515 	if (grfdebug & GDB_DEVNO)
516 		printf("grfdevno: dev %x newdev %x\n", dev, newdev);
517 #endif
518 	return(newdev);
519 }
520 
521 #endif	/* COMPAT_HPUX */
522 
523 int
524 grfmap(dev, addrp, p)
525 	dev_t dev;
526 	caddr_t *addrp;
527 	struct proc *p;
528 {
529 	struct grf_softc *gp = grf_cd.cd_devs[GRFUNIT(dev)];
530 	int len, error;
531 	struct vnode vn;
532 	struct specinfo si;
533 	int flags;
534 
535 #ifdef DEBUG
536 	if (grfdebug & GDB_MMAP)
537 		printf("grfmap(%d): addr %p\n", p->p_pid, *addrp);
538 #endif
539 	len = gp->g_display.gd_regsize + gp->g_display.gd_fbsize;
540 	flags = MAP_SHARED;
541 	if (*addrp)
542 		flags |= MAP_FIXED;
543 	else
544 		*addrp = (caddr_t)0x1000000;	/* XXX */
545 	vn.v_type = VCHR;			/* XXX */
546 	vn.v_specinfo = &si;			/* XXX */
547 	vn.v_rdev = dev;			/* XXX */
548 	error = vm_mmap(&p->p_vmspace->vm_map, (vm_offset_t *)addrp,
549 			(vm_size_t)len, VM_PROT_ALL, VM_PROT_ALL,
550 			flags, (caddr_t)&vn, 0);
551 	if (error == 0)
552 		(void) (*gp->g_sw->gd_mode)(gp, GM_MAP, *addrp);
553 	return(error);
554 }
555 
556 int
557 grfunmap(dev, addr, p)
558 	dev_t dev;
559 	caddr_t addr;
560 	struct proc *p;
561 {
562 	struct grf_softc *gp = grf_cd.cd_devs[GRFUNIT(dev)];
563 	vm_size_t size;
564 	int rv;
565 
566 #ifdef DEBUG
567 	if (grfdebug & GDB_MMAP)
568 		printf("grfunmap(%d): dev %x addr %p\n", p->p_pid, dev, addr);
569 #endif
570 	if (addr == 0)
571 		return(EINVAL);		/* XXX: how do we deal with this? */
572 	(void) (*gp->g_sw->gd_mode)(gp, GM_UNMAP, 0);
573 	size = round_page(gp->g_display.gd_regsize + gp->g_display.gd_fbsize);
574 	rv = vm_deallocate(&p->p_vmspace->vm_map, (vm_offset_t)addr, size);
575 	return(rv == KERN_SUCCESS ? 0 : EINVAL);
576 }
577 
578 #ifdef COMPAT_HPUX
579 iommap(dev, addrp)
580 	dev_t dev;
581 	caddr_t *addrp;
582 {
583 
584 #ifdef DEBUG
585 	if (grfdebug & (GDB_MMAP|GDB_IOMAP))
586 		printf("iommap(%d): addr %x\n", curproc->p_pid, *addrp);
587 #endif
588 	return(EINVAL);
589 }
590 
591 iounmmap(dev, addr)
592 	dev_t dev;
593 	caddr_t addr;
594 {
595 	int unit = minor(dev);
596 
597 #ifdef DEBUG
598 	if (grfdebug & (GDB_MMAP|GDB_IOMAP))
599 		printf("iounmmap(%d): id %d addr %x\n",
600 		       curproc->p_pid, unit, addr);
601 #endif
602 	return(0);
603 }
604 
605 /*
606  * Processes involved in framebuffer mapping via GCSLOT are recorded in
607  * an array of pids.  The first element is used to record the last slot used
608  * (for faster lookups).  The remaining elements record up to GRFMAXLCK-1
609  * process ids.  Returns a slot number between 1 and GRFMAXLCK or 0 if no
610  * slot is available.
611  */
612 grffindpid(gp)
613 	struct grf_softc *gp;
614 {
615 	register short pid, *sp;
616 	register int i, limit;
617 	int ni;
618 
619 	if (gp->g_pid == NULL) {
620 		gp->g_pid = (short *)
621 			malloc(GRFMAXLCK * sizeof(short), M_DEVBUF, M_WAITOK);
622 		bzero((caddr_t)gp->g_pid, GRFMAXLCK * sizeof(short));
623 	}
624 	pid = curproc->p_pid;
625 	ni = limit = gp->g_pid[0];
626 	for (i = 1, sp = &gp->g_pid[1]; i <= limit; i++, sp++) {
627 		if (*sp == pid)
628 			goto done;
629 		if (*sp == 0)
630 			ni = i;
631 	}
632 	i = ni;
633 	if (i < limit) {
634 		gp->g_pid[i] = pid;
635 		goto done;
636 	}
637 	if (++i == GRFMAXLCK)
638 		return(0);
639 	gp->g_pid[0] = i;
640 	gp->g_pid[i] = pid;
641 done:
642 #ifdef DEBUG
643 	if (grfdebug & GDB_LOCK)
644 		printf("grffindpid(%d): slot %d of %d\n",
645 		       pid, i, gp->g_pid[0]);
646 #endif
647 	return(i);
648 }
649 
650 grfrmpid(gp)
651 	struct grf_softc *gp;
652 {
653 	register short pid, *sp;
654 	register int limit, i;
655 	int mi;
656 
657 	if (gp->g_pid == NULL || (limit = gp->g_pid[0]) == 0)
658 		return;
659 	pid = curproc->p_pid;
660 	limit = gp->g_pid[0];
661 	mi = 0;
662 	for (i = 1, sp = &gp->g_pid[1]; i <= limit; i++, sp++) {
663 		if (*sp == pid)
664 			*sp = 0;
665 		else if (*sp)
666 			mi = i;
667 	}
668 	i = mi;
669 	if (i < limit)
670 		gp->g_pid[0] = i;
671 #ifdef DEBUG
672 	if (grfdebug & GDB_LOCK)
673 		printf("grfrmpid(%d): slot %d of %d\n",
674 		       pid, sp-gp->g_pid, gp->g_pid[0]);
675 #endif
676 }
677 
678 grflckmmap(dev, addrp)
679 	dev_t dev;
680 	caddr_t *addrp;
681 {
682 #ifdef DEBUG
683 	struct proc *p = curproc;		/* XXX */
684 
685 	if (grfdebug & (GDB_MMAP|GDB_LOCK))
686 		printf("grflckmmap(%d): addr %x\n",
687 		       p->p_pid, *addrp);
688 #endif
689 	return(EINVAL);
690 }
691 
692 grflckunmmap(dev, addr)
693 	dev_t dev;
694 	caddr_t addr;
695 {
696 #ifdef DEBUG
697 	int unit = minor(dev);
698 
699 	if (grfdebug & (GDB_MMAP|GDB_LOCK))
700 		printf("grflckunmmap(%d): id %d addr %x\n",
701 		       curproc->p_pid, unit, addr);
702 #endif
703 	return(EINVAL);
704 }
705 #endif	/* COMPAT_HPUX */
706