kern_conf.c (129943) | kern_conf.c (130585) |
---|---|
1/*- 2 * Copyright (c) 1999-2002 Poul-Henning Kamp 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1999-2002 Poul-Henning Kamp 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/sys/kern/kern_conf.c 129943 2004-06-01 13:39:02Z phk $"); | 28__FBSDID("$FreeBSD: head/sys/kern/kern_conf.c 130585 2004-06-16 09:47:26Z phk $"); |
29 30#include <sys/param.h> 31#include <sys/kernel.h> 32#include <sys/systm.h> 33#include <sys/bio.h> 34#include <sys/lock.h> 35#include <sys/mutex.h> 36#include <sys/sysctl.h> 37#include <sys/module.h> 38#include <sys/malloc.h> 39#include <sys/conf.h> 40#include <sys/vnode.h> 41#include <sys/queue.h> 42#include <sys/poll.h> 43#include <sys/ctype.h> 44#include <sys/tty.h> 45#include <machine/stdarg.h> 46 | 29 30#include <sys/param.h> 31#include <sys/kernel.h> 32#include <sys/systm.h> 33#include <sys/bio.h> 34#include <sys/lock.h> 35#include <sys/mutex.h> 36#include <sys/sysctl.h> 37#include <sys/module.h> 38#include <sys/malloc.h> 39#include <sys/conf.h> 40#include <sys/vnode.h> 41#include <sys/queue.h> 42#include <sys/poll.h> 43#include <sys/ctype.h> 44#include <sys/tty.h> 45#include <machine/stdarg.h> 46 |
47static MALLOC_DEFINE(M_DEVT, "dev_t", "dev_t storage"); | 47static MALLOC_DEFINE(M_DEVT, "struct cdev *", "struct cdev *storage"); |
48 49/* Built at compile time from sys/conf/majors */ 50extern unsigned char reserved_majors[256]; 51 52/* 53 * This is the number of hash-buckets. Experiements with 'real-life' 54 * udev_t's show that a prime halfway between two powers of two works 55 * best. 56 */ 57#define DEVT_HASH 83 58 | 48 49/* Built at compile time from sys/conf/majors */ 50extern unsigned char reserved_majors[256]; 51 52/* 53 * This is the number of hash-buckets. Experiements with 'real-life' 54 * udev_t's show that a prime halfway between two powers of two works 55 * best. 56 */ 57#define DEVT_HASH 83 58 |
59/* The number of dev_t's we can create before malloc(9) kick in. */ | 59/* The number of struct cdev *'s we can create before malloc(9) kick in. */ |
60#define DEVT_STASH 50 61 62static struct cdev devt_stash[DEVT_STASH]; 63 64static LIST_HEAD(, cdev) dev_hash[DEVT_HASH]; 65 66static LIST_HEAD(, cdev) dev_free; 67 68static int free_devt; 69SYSCTL_INT(_debug, OID_AUTO, free_devt, CTLFLAG_RW, &free_devt, 0, ""); 70 71static struct mtx devmtx; | 60#define DEVT_STASH 50 61 62static struct cdev devt_stash[DEVT_STASH]; 63 64static LIST_HEAD(, cdev) dev_hash[DEVT_HASH]; 65 66static LIST_HEAD(, cdev) dev_free; 67 68static int free_devt; 69SYSCTL_INT(_debug, OID_AUTO, free_devt, CTLFLAG_RW, &free_devt, 0, ""); 70 71static struct mtx devmtx; |
72static void freedev(dev_t dev); | 72static void freedev(struct cdev *dev); |
73 74static void 75devlock(void) 76{ 77 if (!mtx_initialized(&devmtx)) | 73 74static void 75devlock(void) 76{ 77 if (!mtx_initialized(&devmtx)) |
78 mtx_init(&devmtx, "dev_t", NULL, MTX_DEF); | 78 mtx_init(&devmtx, "struct cdev *", NULL, MTX_DEF); |
79 mtx_lock(&devmtx); 80} 81 82static void 83devunlock(void) 84{ 85 mtx_unlock(&devmtx); 86} 87 88void | 79 mtx_lock(&devmtx); 80} 81 82static void 83devunlock(void) 84{ 85 mtx_unlock(&devmtx); 86} 87 88void |
89dev_ref(dev_t dev) | 89dev_ref(struct cdev *dev) |
90{ 91 devlock(); 92 dev->si_refcount++; 93 devunlock(); 94} 95 96void | 90{ 91 devlock(); 92 dev->si_refcount++; 93 devunlock(); 94} 95 96void |
97dev_rel(dev_t dev) | 97dev_rel(struct cdev *dev) |
98{ 99 devlock(); 100 dev->si_refcount--; 101 KASSERT(dev->si_refcount >= 0, 102 ("dev_rel(%s) gave negative count", devtoname(dev))); 103 if (dev->si_devsw == NULL && dev->si_refcount == 0) { 104 LIST_REMOVE(dev, si_list); 105 freedev(dev); --- 14 unchanged lines hidden (view full) --- 120{ 121 devlock(); 122 csw->d_refcount--; 123 KASSERT(csw->d_refcount >= 0, 124 ("cdevsw_vrel(%s) gave negative count", csw->d_name)); 125 devunlock(); 126} 127 | 98{ 99 devlock(); 100 dev->si_refcount--; 101 KASSERT(dev->si_refcount >= 0, 102 ("dev_rel(%s) gave negative count", devtoname(dev))); 103 if (dev->si_devsw == NULL && dev->si_refcount == 0) { 104 LIST_REMOVE(dev, si_list); 105 freedev(dev); --- 14 unchanged lines hidden (view full) --- 120{ 121 devlock(); 122 csw->d_refcount--; 123 KASSERT(csw->d_refcount >= 0, 124 ("cdevsw_vrel(%s) gave negative count", csw->d_name)); 125 devunlock(); 126} 127 |
128static dev_t makedev(int x, int y); | 128static struct cdev *makedev(int x, int y); |
129 130int 131nullop(void) 132{ 133 134 return (0); 135} 136 --- 58 unchanged lines hidden (view full) --- 195#define null_open (d_open_t *)nullop 196#define null_close (d_close_t *)nullop 197#define no_read (d_read_t *)enodev 198#define no_write (d_write_t *)enodev 199#define no_ioctl (d_ioctl_t *)enodev 200#define no_mmap (d_mmap_t *)enodev 201 202static int | 129 130int 131nullop(void) 132{ 133 134 return (0); 135} 136 --- 58 unchanged lines hidden (view full) --- 195#define null_open (d_open_t *)nullop 196#define null_close (d_close_t *)nullop 197#define no_read (d_read_t *)enodev 198#define no_write (d_write_t *)enodev 199#define no_ioctl (d_ioctl_t *)enodev 200#define no_mmap (d_mmap_t *)enodev 201 202static int |
203no_kqfilter(dev_t dev __unused, struct knote *kn __unused) | 203no_kqfilter(struct cdev *dev __unused, struct knote *kn __unused) |
204{ 205 206 return (1); 207} 208 209static void 210no_strategy(struct bio *bp) 211{ 212 213 biofinish(bp, NULL, ENODEV); 214} 215 216static int | 204{ 205 206 return (1); 207} 208 209static void 210no_strategy(struct bio *bp) 211{ 212 213 biofinish(bp, NULL, ENODEV); 214} 215 216static int |
217no_poll(dev_t dev __unused, int events, struct thread *td __unused) | 217no_poll(struct cdev *dev __unused, int events, struct thread *td __unused) |
218{ 219 /* 220 * Return true for read/write. If the user asked for something 221 * special, return POLLNVAL, so that clients have a way of 222 * determining reliably whether or not the extended 223 * functionality is present without hard-coding knowledge 224 * of specific filesystem implementations. 225 * Stay in sync with vop_nopoll(). 226 */ 227 if (events & ~POLLSTANDARD) 228 return (POLLNVAL); 229 230 return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)); 231} 232 233#define no_dump (dumper_t *)enodev 234 235struct cdevsw * | 218{ 219 /* 220 * Return true for read/write. If the user asked for something 221 * special, return POLLNVAL, so that clients have a way of 222 * determining reliably whether or not the extended 223 * functionality is present without hard-coding knowledge 224 * of specific filesystem implementations. 225 * Stay in sync with vop_nopoll(). 226 */ 227 if (events & ~POLLSTANDARD) 228 return (POLLNVAL); 229 230 return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)); 231} 232 233#define no_dump (dumper_t *)enodev 234 235struct cdevsw * |
236devsw(dev_t dev) | 236devsw(struct cdev *dev) |
237{ 238 if (dev->si_devsw != NULL) 239 return (dev->si_devsw); 240 return (&dead_cdevsw); 241} 242 243/* | 237{ 238 if (dev->si_devsw != NULL) 239 return (dev->si_devsw); 240 return (&dead_cdevsw); 241} 242 243/* |
244 * dev_t and u_dev_t primitives | 244 * struct cdev *and u_dev_t primitives |
245 */ 246 247int | 245 */ 246 247int |
248major(dev_t x) | 248major(struct cdev *x) |
249{ 250 if (x == NODEV) 251 return NOUDEV; 252 return((x->si_udev >> 8) & 0xff); 253} 254 255int | 249{ 250 if (x == NODEV) 251 return NOUDEV; 252 return((x->si_udev >> 8) & 0xff); 253} 254 255int |
256minor(dev_t x) | 256minor(struct cdev *x) |
257{ 258 if (x == NODEV) 259 return NOUDEV; 260 return(x->si_udev & 0xffff00ff); 261} 262 263int | 257{ 258 if (x == NODEV) 259 return NOUDEV; 260 return(x->si_udev & 0xffff00ff); 261} 262 263int |
264dev2unit(dev_t x) | 264dev2unit(struct cdev *x) |
265{ 266 int i; 267 268 if (x == NODEV) 269 return NOUDEV; 270 i = minor(x); 271 return ((i & 0xff) | (i >> 8)); 272} 273 274int 275unit2minor(int unit) 276{ 277 278 KASSERT(unit <= 0xffffff, ("Invalid unit (%d) in unit2minor", unit)); 279 return ((unit & 0xff) | ((unit << 8) & ~0xffff)); 280} 281 | 265{ 266 int i; 267 268 if (x == NODEV) 269 return NOUDEV; 270 i = minor(x); 271 return ((i & 0xff) | (i >> 8)); 272} 273 274int 275unit2minor(int unit) 276{ 277 278 KASSERT(unit <= 0xffffff, ("Invalid unit (%d) in unit2minor", unit)); 279 return ((unit & 0xff) | ((unit << 8) & ~0xffff)); 280} 281 |
282static dev_t | 282static struct cdev * |
283allocdev(void) 284{ 285 static int stashed; 286 struct cdev *si; 287 288 if (LIST_FIRST(&dev_free)) { 289 si = LIST_FIRST(&dev_free); 290 LIST_REMOVE(si, si_hash); --- 7 unchanged lines hidden (view full) --- 298 } 299 si->__si_namebuf[0] = '\0'; 300 si->si_name = si->__si_namebuf; 301 LIST_INIT(&si->si_children); 302 TAILQ_INIT(&si->si_snapshots); 303 return (si); 304} 305 | 283allocdev(void) 284{ 285 static int stashed; 286 struct cdev *si; 287 288 if (LIST_FIRST(&dev_free)) { 289 si = LIST_FIRST(&dev_free); 290 LIST_REMOVE(si, si_hash); --- 7 unchanged lines hidden (view full) --- 298 } 299 si->__si_namebuf[0] = '\0'; 300 si->si_name = si->__si_namebuf; 301 LIST_INIT(&si->si_children); 302 TAILQ_INIT(&si->si_snapshots); 303 return (si); 304} 305 |
306static dev_t | 306static struct cdev * |
307makedev(int x, int y) 308{ 309 struct cdev *si; 310 udev_t udev; 311 int hash; 312 313 if (x == umajor(NOUDEV) && y == uminor(NOUDEV)) 314 panic("makedev of NOUDEV"); --- 5 unchanged lines hidden (view full) --- 320 } 321 si = allocdev(); 322 si->si_udev = udev; 323 LIST_INSERT_HEAD(&dev_hash[hash], si, si_hash); 324 return (si); 325} 326 327static void | 307makedev(int x, int y) 308{ 309 struct cdev *si; 310 udev_t udev; 311 int hash; 312 313 if (x == umajor(NOUDEV) && y == uminor(NOUDEV)) 314 panic("makedev of NOUDEV"); --- 5 unchanged lines hidden (view full) --- 320 } 321 si = allocdev(); 322 si->si_udev = udev; 323 LIST_INSERT_HEAD(&dev_hash[hash], si, si_hash); 324 return (si); 325} 326 327static void |
328freedev(dev_t dev) | 328freedev(struct cdev *dev) |
329{ 330 331 if (dev->si_flags & SI_STASHED) { 332 bzero(dev, sizeof(*dev)); 333 dev->si_flags |= SI_STASHED; 334 LIST_INSERT_HEAD(&dev_free, dev, si_hash); 335 } else { 336 FREE(dev, M_DEVT); 337 } 338} 339 340udev_t | 329{ 330 331 if (dev->si_flags & SI_STASHED) { 332 bzero(dev, sizeof(*dev)); 333 dev->si_flags |= SI_STASHED; 334 LIST_INSERT_HEAD(&dev_free, dev, si_hash); 335 } else { 336 FREE(dev, M_DEVT); 337 } 338} 339 340udev_t |
341dev2udev(dev_t x) | 341dev2udev(struct cdev *x) |
342{ 343 if (x == NODEV) 344 return (NOUDEV); 345 return (x->si_udev); 346} 347 | 342{ 343 if (x == NODEV) 344 return (NOUDEV); 345 return (x->si_udev); 346} 347 |
348dev_t | 348struct cdev * |
349udev2dev(udev_t udev) 350{ 351 struct cdev *si; 352 int hash; 353 354 if (udev == NOUDEV) 355 return (NODEV); 356 hash = udev % DEVT_HASH; --- 105 unchanged lines hidden (view full) --- 462 devsw->d_name, "unreserved major device number", 463 devsw->d_maj); 464 reserved_majors[devsw->d_maj] = devsw->d_maj; 465 } 466 } 467 devunlock(); 468} 469 | 349udev2dev(udev_t udev) 350{ 351 struct cdev *si; 352 int hash; 353 354 if (udev == NOUDEV) 355 return (NODEV); 356 hash = udev % DEVT_HASH; --- 105 unchanged lines hidden (view full) --- 462 devsw->d_name, "unreserved major device number", 463 devsw->d_maj); 464 reserved_majors[devsw->d_maj] = devsw->d_maj; 465 } 466 } 467 devunlock(); 468} 469 |
470dev_t | 470struct cdev * |
471make_dev(struct cdevsw *devsw, int minornr, uid_t uid, gid_t gid, int perms, const char *fmt, ...) 472{ | 471make_dev(struct cdevsw *devsw, int minornr, uid_t uid, gid_t gid, int perms, const char *fmt, ...) 472{ |
473 dev_t dev; | 473 struct cdev *dev; |
474 va_list ap; 475 int i; 476 477 KASSERT((minornr & ~0xffff00ff) == 0, 478 ("Invalid minor (0x%x) in make_dev", minornr)); 479 480 if (!(devsw->d_flags & D_INIT)) 481 prep_cdevsw(devsw); --- 28 unchanged lines hidden (view full) --- 510 511 LIST_INSERT_HEAD(&devsw->d_devs, dev, si_list); 512 devfs_create(dev); 513 devunlock(); 514 return (dev); 515} 516 517int | 474 va_list ap; 475 int i; 476 477 KASSERT((minornr & ~0xffff00ff) == 0, 478 ("Invalid minor (0x%x) in make_dev", minornr)); 479 480 if (!(devsw->d_flags & D_INIT)) 481 prep_cdevsw(devsw); --- 28 unchanged lines hidden (view full) --- 510 511 LIST_INSERT_HEAD(&devsw->d_devs, dev, si_list); 512 devfs_create(dev); 513 devunlock(); 514 return (dev); 515} 516 517int |
518dev_named(dev_t pdev, const char *name) | 518dev_named(struct cdev *pdev, const char *name) |
519{ | 519{ |
520 dev_t cdev; | 520 struct cdev *cdev; |
521 522 if (strcmp(devtoname(pdev), name) == 0) 523 return (1); 524 LIST_FOREACH(cdev, &pdev->si_children, si_siblings) 525 if (strcmp(devtoname(cdev), name) == 0) 526 return (1); 527 return (0); 528} 529 530void | 521 522 if (strcmp(devtoname(pdev), name) == 0) 523 return (1); 524 LIST_FOREACH(cdev, &pdev->si_children, si_siblings) 525 if (strcmp(devtoname(cdev), name) == 0) 526 return (1); 527 return (0); 528} 529 530void |
531dev_depends(dev_t pdev, dev_t cdev) | 531dev_depends(struct cdev *pdev, struct cdev *cdev) |
532{ 533 534 devlock(); 535 cdev->si_parent = pdev; 536 cdev->si_flags |= SI_CHILD; 537 LIST_INSERT_HEAD(&pdev->si_children, cdev, si_siblings); 538 devunlock(); 539} 540 | 532{ 533 534 devlock(); 535 cdev->si_parent = pdev; 536 cdev->si_flags |= SI_CHILD; 537 LIST_INSERT_HEAD(&pdev->si_children, cdev, si_siblings); 538 devunlock(); 539} 540 |
541dev_t 542make_dev_alias(dev_t pdev, const char *fmt, ...) | 541struct cdev * 542make_dev_alias(struct cdev *pdev, const char *fmt, ...) |
543{ | 543{ |
544 dev_t dev; | 544 struct cdev *dev; |
545 va_list ap; 546 int i; 547 548 dev = allocdev(); 549 devlock(); 550 dev->si_flags |= SI_ALIAS; 551 dev->si_flags |= SI_NAMED; 552 va_start(ap, fmt); --- 6 unchanged lines hidden (view full) --- 559 560 devfs_create(dev); 561 devunlock(); 562 dev_depends(pdev, dev); 563 return (dev); 564} 565 566static void | 545 va_list ap; 546 int i; 547 548 dev = allocdev(); 549 devlock(); 550 dev->si_flags |= SI_ALIAS; 551 dev->si_flags |= SI_NAMED; 552 va_start(ap, fmt); --- 6 unchanged lines hidden (view full) --- 559 560 devfs_create(dev); 561 devunlock(); 562 dev_depends(pdev, dev); 563 return (dev); 564} 565 566static void |
567idestroy_dev(dev_t dev) | 567idestroy_dev(struct cdev *dev) |
568{ 569 if (!(dev->si_flags & SI_NAMED)) { 570 printf( "WARNING: Driver mistake: destroy_dev on %d/%d\n", 571 major(dev), minor(dev)); 572 panic("don't do that"); 573 } 574 575 devfs_destroy(dev); --- 16 unchanged lines hidden (view full) --- 592 LIST_REMOVE(dev, si_clone); 593 dev->si_flags &= ~SI_CLONELIST; 594 } 595 596 if (!(dev->si_flags & SI_ALIAS)) { 597 /* Remove from cdevsw list */ 598 LIST_REMOVE(dev, si_list); 599 | 568{ 569 if (!(dev->si_flags & SI_NAMED)) { 570 printf( "WARNING: Driver mistake: destroy_dev on %d/%d\n", 571 major(dev), minor(dev)); 572 panic("don't do that"); 573 } 574 575 devfs_destroy(dev); --- 16 unchanged lines hidden (view full) --- 592 LIST_REMOVE(dev, si_clone); 593 dev->si_flags &= ~SI_CLONELIST; 594 } 595 596 if (!(dev->si_flags & SI_ALIAS)) { 597 /* Remove from cdevsw list */ 598 LIST_REMOVE(dev, si_list); 599 |
600 /* If cdevsw has no dev_t's, clean it */ | 600 /* If cdevsw has no struct cdev *'s, clean it */ |
601 if (LIST_EMPTY(&dev->si_devsw->d_devs)) 602 fini_cdevsw(dev->si_devsw); 603 604 LIST_REMOVE(dev, si_hash); 605 } 606 dev->si_drv1 = 0; 607 dev->si_drv2 = 0; 608 dev->si_devsw = NULL; 609 bzero(&dev->__si_u, sizeof(dev->__si_u)); 610 dev->si_flags &= ~SI_ALIAS; 611 if (dev->si_refcount > 0) { 612 LIST_INSERT_HEAD(&dead_cdevsw.d_devs, dev, si_list); 613 } else { 614 freedev(dev); 615 } 616} 617 618void | 601 if (LIST_EMPTY(&dev->si_devsw->d_devs)) 602 fini_cdevsw(dev->si_devsw); 603 604 LIST_REMOVE(dev, si_hash); 605 } 606 dev->si_drv1 = 0; 607 dev->si_drv2 = 0; 608 dev->si_devsw = NULL; 609 bzero(&dev->__si_u, sizeof(dev->__si_u)); 610 dev->si_flags &= ~SI_ALIAS; 611 if (dev->si_refcount > 0) { 612 LIST_INSERT_HEAD(&dead_cdevsw.d_devs, dev, si_list); 613 } else { 614 freedev(dev); 615 } 616} 617 618void |
619destroy_dev(dev_t dev) | 619destroy_dev(struct cdev *dev) |
620{ 621 622 devlock(); 623 idestroy_dev(dev); 624 devunlock(); 625} 626 627const char * | 620{ 621 622 devlock(); 623 idestroy_dev(dev); 624 devunlock(); 625} 626 627const char * |
628devtoname(dev_t dev) | 628devtoname(struct cdev *dev) |
629{ 630 char *p; 631 int mynor; 632 633 if (dev->si_name[0] == '#' || dev->si_name[0] == '\0') { 634 p = dev->si_name; 635 if (devsw(dev)) 636 sprintf(p, "#%s/", devsw(dev)->d_name); --- 39 unchanged lines hidden (view full) --- 676/* 677 * Helper functions for cloning device drivers. 678 * 679 * The objective here is to make it unnecessary for the device drivers to 680 * use rman or similar to manage their unit number space. Due to the way 681 * we do "on-demand" devices, using rman or other "private" methods 682 * will be very tricky to lock down properly once we lock down this file. 683 * | 629{ 630 char *p; 631 int mynor; 632 633 if (dev->si_name[0] == '#' || dev->si_name[0] == '\0') { 634 p = dev->si_name; 635 if (devsw(dev)) 636 sprintf(p, "#%s/", devsw(dev)->d_name); --- 39 unchanged lines hidden (view full) --- 676/* 677 * Helper functions for cloning device drivers. 678 * 679 * The objective here is to make it unnecessary for the device drivers to 680 * use rman or similar to manage their unit number space. Due to the way 681 * we do "on-demand" devices, using rman or other "private" methods 682 * will be very tricky to lock down properly once we lock down this file. 683 * |
684 * Instead we give the drivers these routines which puts the dev_t's that | 684 * Instead we give the drivers these routines which puts the struct cdev *'s that |
685 * are to be managed on their own list, and gives the driver the ability 686 * to ask for the first free unit number or a given specified unit number. 687 * 688 * In addition these routines support paired devices (pty, nmdm and similar) 689 * by respecting a number of "flag" bits in the minor number. 690 * 691 */ 692 --- 5 unchanged lines hidden (view full) --- 698clone_setup(struct clonedevs **cdp) 699{ 700 701 *cdp = malloc(sizeof **cdp, M_DEVBUF, M_WAITOK | M_ZERO); 702 LIST_INIT(&(*cdp)->head); 703} 704 705int | 685 * are to be managed on their own list, and gives the driver the ability 686 * to ask for the first free unit number or a given specified unit number. 687 * 688 * In addition these routines support paired devices (pty, nmdm and similar) 689 * by respecting a number of "flag" bits in the minor number. 690 * 691 */ 692 --- 5 unchanged lines hidden (view full) --- 698clone_setup(struct clonedevs **cdp) 699{ 700 701 *cdp = malloc(sizeof **cdp, M_DEVBUF, M_WAITOK | M_ZERO); 702 LIST_INIT(&(*cdp)->head); 703} 704 705int |
706clone_create(struct clonedevs **cdp, struct cdevsw *csw, int *up, dev_t *dp, u_int extra) | 706clone_create(struct clonedevs **cdp, struct cdevsw *csw, int *up, struct cdev **dp, u_int extra) |
707{ 708 struct clonedevs *cd; | 707{ 708 struct clonedevs *cd; |
709 dev_t dev, dl, de; | 709 struct cdev *dev, *dl, *de; |
710 int unit, low, u; 711 712 KASSERT(*cdp != NULL, 713 ("clone_setup() not called in driver \"%s\"", csw->d_name)); 714 KASSERT(!(extra & CLONE_UNITMASK), 715 ("Illegal extra bits (0x%x) in clone_create", extra)); 716 KASSERT(*up <= CLONE_UNITMASK, 717 ("Too high unit (0x%x) in clone_create", *up)); --- 43 unchanged lines hidden (view full) --- 761 LIST_INSERT_HEAD(&cd->head, dev, si_clone); 762 dev->si_flags |= SI_CLONELIST; 763 *up = unit; 764 return (1); 765} 766 767/* 768 * Kill everything still on the list. The driver should already have | 710 int unit, low, u; 711 712 KASSERT(*cdp != NULL, 713 ("clone_setup() not called in driver \"%s\"", csw->d_name)); 714 KASSERT(!(extra & CLONE_UNITMASK), 715 ("Illegal extra bits (0x%x) in clone_create", extra)); 716 KASSERT(*up <= CLONE_UNITMASK, 717 ("Too high unit (0x%x) in clone_create", *up)); --- 43 unchanged lines hidden (view full) --- 761 LIST_INSERT_HEAD(&cd->head, dev, si_clone); 762 dev->si_flags |= SI_CLONELIST; 763 *up = unit; 764 return (1); 765} 766 767/* 768 * Kill everything still on the list. The driver should already have |
769 * disposed of any softc hung of the dev_t's at this time. | 769 * disposed of any softc hung of the struct cdev *'s at this time. |
770 */ 771void 772clone_cleanup(struct clonedevs **cdp) 773{ | 770 */ 771void 772clone_cleanup(struct clonedevs **cdp) 773{ |
774 dev_t dev, tdev; | 774 struct cdev *dev, *tdev; |
775 struct clonedevs *cd; 776 777 cd = *cdp; 778 if (cd == NULL) 779 return; 780 LIST_FOREACH_SAFE(dev, &cd->head, si_clone, tdev) { 781 KASSERT(dev->si_flags & SI_NAMED, 782 ("Driver has goofed in cloning underways udev %x", dev->si_udev)); 783 destroy_dev(dev); 784 } 785 free(cd, M_DEVBUF); 786 *cdp = NULL; 787} 788 789/* | 775 struct clonedevs *cd; 776 777 cd = *cdp; 778 if (cd == NULL) 779 return; 780 LIST_FOREACH_SAFE(dev, &cd->head, si_clone, tdev) { 781 KASSERT(dev->si_flags & SI_NAMED, 782 ("Driver has goofed in cloning underways udev %x", dev->si_udev)); 783 destroy_dev(dev); 784 } 785 free(cd, M_DEVBUF); 786 *cdp = NULL; 787} 788 789/* |
790 * Helper sysctl for devname(3). We're given a {u}dev_t and return | 790 * Helper sysctl for devname(3). We're given a {u}struct cdev *and return |
791 * the name, if any, registered by the device driver. 792 */ 793static int 794sysctl_devname(SYSCTL_HANDLER_ARGS) 795{ 796 int error; 797 udev_t ud; | 791 * the name, if any, registered by the device driver. 792 */ 793static int 794sysctl_devname(SYSCTL_HANDLER_ARGS) 795{ 796 int error; 797 udev_t ud; |
798 dev_t dev; | 798 struct cdev *dev; |
799 800 error = SYSCTL_IN(req, &ud, sizeof (ud)); 801 if (error) 802 return (error); 803 if (ud == NOUDEV) 804 return(EINVAL); 805 dev = udev2dev(ud); 806 if (dev == NODEV) 807 error = ENOENT; 808 else 809 error = SYSCTL_OUT(req, dev->si_name, strlen(dev->si_name) + 1); 810 return (error); 811} 812 813SYSCTL_PROC(_kern, OID_AUTO, devname, CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_ANYBODY, 814 NULL, 0, sysctl_devname, "", "devname(3) handler"); | 799 800 error = SYSCTL_IN(req, &ud, sizeof (ud)); 801 if (error) 802 return (error); 803 if (ud == NOUDEV) 804 return(EINVAL); 805 dev = udev2dev(ud); 806 if (dev == NODEV) 807 error = ENOENT; 808 else 809 error = SYSCTL_OUT(req, dev->si_name, strlen(dev->si_name) + 1); 810 return (error); 811} 812 813SYSCTL_PROC(_kern, OID_AUTO, devname, CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_ANYBODY, 814 NULL, 0, sysctl_devname, "", "devname(3) handler"); |