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