adopted from Mike Hibler at Utah
[unix-history] / usr / src / sys / hp / dev / grf.c
CommitLineData
60f56dfc
KM
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 *
96d5f73d 14 * @(#)grf.c 7.4 (Berkeley) %G%
60f56dfc
KM
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
50int grfprobe();
51int tc_init(), tc_mode();
52int gb_init(), gb_mode();
53int rb_init(), rb_mode();
54int dv_init(), dv_mode();
55
56struct 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};
72int ngrfdev = sizeof(grfdev) / sizeof(grfdev[0]);
73
74struct driver grfdriver = { grfprobe, "grf" };
75struct grf_softc grf_softc[NGRF];
76
77#ifdef MAPMEM
78int grfexit();
79struct mapmemops grfops = { (int (*)())0, (int (*)())0, grfexit, grfexit };
80#ifdef HPUXCOMPAT
81struct mapmemops grflckops = { (int (*)())0, (int (*)())0, grfexit, grfexit };
82struct mapmemops grfiomops = { (int (*)())0, (int (*)())0, grfexit, grfexit };
83#endif
84#endif
85
86#ifdef DEBUG
87int 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 */
98grfconfig()
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 */
144grfprobe(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
162grfinit(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*/
185grfopen(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*/
224grfclose(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*/
236grfioctl(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*/
286grfselect(dev, rw)
287 dev_t dev;
288{
289 if (rw == FREAD)
290 return(0);
291 return(1);
292}
293
294grflock(gp, block)
295 register struct grf_softc *gp;
296 int block;
297{
05d14dfb 298 struct proc *p = u.u_procp; /* XXX */
339a5f2c
KM
299 int error;
300 extern char devioc[];
301
60f56dfc
KM
302#ifdef DEBUG
303 if (grfdebug & GDB_LOCK)
304 printf("grflock(%d): dev %x flags %x lockpid %x\n",
05d14dfb 305 p->p_pid, gp-grf_softc, gp->g_flags,
60f56dfc
KM
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) {
05d14dfb 324 if (gp->g_lockp == p)
60f56dfc
KM
325 return(EBUSY);
326 if (!block)
327 return(EAGAIN);
328 do {
329 gp->g_flags |= GF_WANTED;
339a5f2c
KM
330 if (error = tsleep((caddr_t)&gp->g_flags,
331 (PZERO+1) | PCATCH, devioc, 0))
332 return (error);
60f56dfc
KM
333 } while (gp->g_lockp);
334 }
05d14dfb 335 gp->g_lockp = p;
60f56dfc
KM
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
350grfunlock(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*/
382grfmap(dev, off, prot)
383 dev_t dev;
384{
385 return(grfaddr(&grf_softc[GRFUNIT(dev)], off));
386}
387
388#ifdef HPUXCOMPAT
389
390/*ARGSUSED*/
391hpuxgrfioctl(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);
96d5f73d
MH
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 */
60f56dfc
KM
469 if (!error)
470 u.u_r.r_val1 = *(int *)data; /* XXX: this sux */
96d5f73d 471#endif
60f56dfc
KM
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
488grfon(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
504grfoff(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
521grfaddr(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 */
550grfdevno(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
582grfmapin(mp, off)
583 struct mapmem *mp;
584{
585 return(grfaddr(&grf_softc[GRFUNIT(mp->mm_id)], off));
586}
587
588grfmmap(dev, addrp)
589 dev_t dev;
590 caddr_t *addrp;
591{
05d14dfb 592 struct proc *p = u.u_procp; /* XXX */
60f56dfc 593 struct grf_softc *gp = &grf_softc[GRFUNIT(dev)];
05d14dfb 594 struct mapmem *mp;
96d5f73d 595 int len, error, grfmapin();
60f56dfc
KM
596
597#ifdef DEBUG
598 if (grfdebug & GDB_MMAP)
05d14dfb 599 printf("grfmmap(%d): addr %x\n", p->p_pid, *addrp);
60f56dfc
KM
600#endif
601 len = gp->g_display.gd_regsize + gp->g_display.gd_fbsize;
96d5f73d
MH
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);
60f56dfc
KM
608}
609
610grfunmmap(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 }
96d5f73d 634 (void) grfexit(mp);
60f56dfc
KM
635 found++;
636 }
637 return(found ? 0 : EINVAL);
638}
639
640grfexit(mp)
641 struct mapmem *mp;
642{
05d14dfb 643 struct proc *p = u.u_procp; /* XXX */
60f56dfc
KM
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",
05d14dfb 649 p->p_pid, mp->mm_id, mp->mm_size, mp->mm_uva);
60f56dfc
KM
650#endif
651 (void) grfunlock(gp);
652#ifdef HPUXCOMPAT
653 grfrmpid(gp);
654#endif
05d14dfb 655 mmmapout(p, mp);
96d5f73d 656 return(mmfree(p, mp));
60f56dfc
KM
657}
658
659#ifdef HPUXCOMPAT
660iommap(dev, addrp)
661 dev_t dev;
662 caddr_t *addrp;
663{
05d14dfb 664 struct proc *p = u.u_procp; /* XXX */
60f56dfc 665 struct grf_softc *gp = &grf_softc[GRFUNIT(dev)];
05d14dfb 666 struct mapmem *mp;
96d5f73d 667 int len, error, grfmapin();
60f56dfc
KM
668
669#ifdef DEBUG
670 if (grfdebug & (GDB_MMAP|GDB_IOMAP))
05d14dfb 671 printf("iommap(%d): addr %x\n", p->p_pid, *addrp);
60f56dfc
KM
672#endif
673 len = gp->g_display.gd_regsize;
96d5f73d
MH
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);
60f56dfc
KM
680}
681
682iounmmap(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 }
96d5f73d 709 (void) grfexit(mp);
60f56dfc
KM
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 */
722grffindpid(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;
751done:
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
760grfrmpid(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*/
789grflckmapin(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
802grflckmmap(dev, addrp)
803 dev_t dev;
804 caddr_t *addrp;
805{
05d14dfb 806 struct proc *p = u.u_procp; /* XXX */
60f56dfc 807 struct grf_softc *gp = &grf_softc[GRFUNIT(dev)];
05d14dfb 808 struct mapmem *mp;
96d5f73d 809 int error, grflckmapin();
60f56dfc
KM
810
811#ifdef DEBUG
812 if (grfdebug & (GDB_MMAP|GDB_LOCK))
813 printf("grflckmmap(%d): addr %x\n",
05d14dfb 814 p->p_pid, *addrp);
60f56dfc
KM
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 }
96d5f73d
MH
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);
60f56dfc
KM
827}
828
829grflckunmmap(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) {
96d5f73d 844 (void) grfexit(mp);
60f56dfc
KM
845 return(0);
846 }
847 return(EINVAL);
848}
849#endif /* HPUXCOMPAT */
850#endif /* MAPMEM */
851#endif /* NGRF > 0 */