1.\" Copyright (c) 1999 Chris Costello 2.\" All rights reserved. 3.\" 4.\" Redistribution and use in source and binary forms, with or without 5.\" modification, are permitted provided that the following conditions 6.\" are met: 7.\" 1. Redistributions of source code must retain the above copyright 8.\" notice, this list of conditions and the following disclaimer. 9.\" 2. Redistributions in binary form must reproduce the above copyright 10.\" notice, this list of conditions and the following disclaimer in the 11.\" documentation and/or other materials provided with the distribution. 12.\" 13.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23.\" SUCH DAMAGE. 24.\" 25.\" $FreeBSD$ 26.\" 27.Dd March 2, 2016 28.Dt MAKE_DEV 9 29.Os 30.Sh NAME 31.Nm make_dev , 32.Nm make_dev_cred , 33.Nm make_dev_credf , 34.Nm make_dev_p , 35.Nm make_dev_s , 36.Nm make_dev_alias , 37.Nm make_dev_alias_p , 38.Nm destroy_dev , 39.Nm destroy_dev_sched , 40.Nm destroy_dev_sched_cb , 41.Nm destroy_dev_drain , 42.Nm dev_depends 43.Nd manage 44.Vt cdev Ns 's 45and DEVFS registration for devices 46.Sh SYNOPSIS 47.In sys/param.h 48.In sys/conf.h 49.Ft void 50.Fn make_dev_args_init "struct make_dev_args *args" 51.Ft int 52.Fn make_dev_s "struct make_dev_args *args" "struct cdev **cdev" "const char *fmt" ... 53.Ft int 54.Fn make_dev_alias_p "int flags" "struct cdev **cdev" "struct cdev *pdev" "const char *fmt" ... 55.Ft void 56.Fn destroy_dev "struct cdev *dev" 57.Ft void 58.Fn destroy_dev_sched "struct cdev *dev" 59.Ft void 60.Fn destroy_dev_sched_cb "struct cdev *dev" "void (*cb)(void *)" "void *arg" 61.Ft void 62.Fn destroy_dev_drain "struct cdevsw *csw" 63.Ft void 64.Fn dev_depends "struct cdev *pdev" "struct cdev *cdev" 65.Pp 66LEGACY INTERFACES 67.Ft struct cdev * 68.Fn make_dev "struct cdevsw *cdevsw" "int unit" "uid_t uid" "gid_t gid" "int perms" "const char *fmt" ... 69.Ft struct cdev * 70.Fn make_dev_cred "struct cdevsw *cdevsw" "int unit" "struct ucred *cr" "uid_t uid" "gid_t gid" "int perms" "const char *fmt" ... 71.Ft struct cdev * 72.Fn make_dev_credf "int flags" "struct cdevsw *cdevsw" "int unit" "struct ucred *cr" "uid_t uid" "gid_t gid" "int perms" "const char *fmt" ... 73.Ft int 74.Fn make_dev_p "int flags" "struct cdev **cdev" "struct cdevsw *devsw" "struct ucred *cr" "uid_t uid" "gid_t gid" "int mode" "const char *fmt" ... 75.Ft struct cdev * 76.Fn make_dev_alias "struct cdev *pdev" "const char *fmt" ... 77.Sh DESCRIPTION 78The 79.Fn make_dev_s 80function creates a 81.Fa cdev 82structure for a new device, which is returned into the 83.Fa cdev 84argument. 85It also notifies 86.Xr devfs 5 87of the presence of the new device, that causes corresponding nodes 88to be created. 89Besides this, a 90.Xr devctl 4 91notification is sent. 92The function takes the structure 93.Va struct make_dev_args args , 94which specifies the parameters for the device creation: 95.Pp 96.Bd -literal -offset indent -compact 97struct make_dev_args { 98 size_t mda_size; 99 int mda_flags; 100 struct cdevsw *mda_devsw; 101 struct ucred *mda_cr; 102 uid_t mda_uid; 103 gid_t mda_gid; 104 int mda_mode; 105 int mda_unit; 106 void *mda_si_drv1; 107 void *mda_si_drv2; 108}; 109.Ed 110Before use and filling with the desired values, the structure must be 111initialized by the 112.Fn make_dev_args_init 113function, which ensures that future kernel interface expansion does 114not affect driver source code or binary interface. 115.Pp 116The created device will be owned by 117.Va args.mda_uid , 118with the group ownership as 119.Va args.mda_gid . 120The name is the expansion of 121.Va fmt 122and following arguments as 123.Xr printf 9 124would print it. 125The name determines its path under 126.Pa /dev 127or other 128.Xr devfs 5 129mount point and may contain slash 130.Ql / 131characters to denote subdirectories. 132The permissions of the file specified in 133.Va args.mda_mode 134are defined in 135.In sys/stat.h : 136.Pp 137.Bd -literal -offset indent -compact 138#define S_IRWXU 0000700 /* RWX mask for owner */ 139#define S_IRUSR 0000400 /* R for owner */ 140#define S_IWUSR 0000200 /* W for owner */ 141#define S_IXUSR 0000100 /* X for owner */ 142 143#define S_IRWXG 0000070 /* RWX mask for group */ 144#define S_IRGRP 0000040 /* R for group */ 145#define S_IWGRP 0000020 /* W for group */ 146#define S_IXGRP 0000010 /* X for group */ 147 148#define S_IRWXO 0000007 /* RWX mask for other */ 149#define S_IROTH 0000004 /* R for other */ 150#define S_IWOTH 0000002 /* W for other */ 151#define S_IXOTH 0000001 /* X for other */ 152 153#define S_ISUID 0004000 /* set user id on execution */ 154#define S_ISGID 0002000 /* set group id on execution */ 155#define S_ISVTX 0001000 /* sticky bit */ 156#ifndef _POSIX_SOURCE 157#define S_ISTXT 0001000 158#endif 159.Ed 160.Pp 161The 162.Va args.mda_cr 163argument specifies credentials that will be stored in the 164.Fa si_cred 165member of the initialized 166.Fa struct cdev . 167.Pp 168The 169.Va args.mda_flags 170argument alters the operation of 171.Fn make_dev_s. 172The following values are currently accepted: 173.Pp 174.Bl -tag -width "It Dv MAKEDEV_CHECKNAME" -compact -offset indent 175.It Dv MAKEDEV_REF 176reference the created device 177.It Dv MAKEDEV_NOWAIT 178do not sleep, the call may fail 179.It Dv MAKEDEV_WAITOK 180allow the function to sleep to satisfy malloc 181.It Dv MAKEDEV_ETERNAL 182created device will be never destroyed 183.It Dv MAKEDEV_CHECKNAME 184return an error if the device name is invalid or already exists 185.El 186.Pp 187Only 188.Dv MAKEDEV_NOWAIT , 189.Dv MAKEDEV_WAITOK 190and 191.Dv MAKEDEV_CHECKNAME 192values are accepted for the 193.Fn make_dev_alias_p 194function. 195.Pp 196The 197.Dv MAKEDEV_WAITOK 198flag is assumed if none of 199.Dv MAKEDEV_WAITOK , 200.Dv MAKEDEV_NOWAIT 201is specified. 202.Pp 203The 204.Xr dev_clone 9 205event handler shall specify 206.Dv MAKEDEV_REF 207flag when creating a device in response to lookup, to avoid race where 208the device created is destroyed immediately after 209.Xr devfs_lookup 9 210drops his reference to cdev. 211.Pp 212The 213.Dv MAKEDEV_ETERNAL 214flag allows the kernel to not acquire some locks when translating system 215calls into the cdevsw methods calls. 216It is responsibility of the driver author to make sure that 217.Fn destroy_dev 218is never called on the returned cdev. 219For the convenience, use the 220.Dv MAKEDEV_ETERNAL_KLD 221flag for the code that can be compiled into kernel or loaded 222(and unloaded) as loadable module. 223.Pp 224A panic will occur if the 225.Dv MAKEDEV_CHECKNAME 226flag is not specified 227and the device name is invalid or already exists. 228.Pp 229The 230.Fn make_dev_p 231use of the form 232.Bd -literal -offset indent 233struct cdev *dev; 234int res; 235res = make_dev_p(flags, &dev, cdevsw, cred, uid, gid, perms, name); 236.Ed 237is equivalent to the code 238.Bd -literal -offset indent 239struct cdev *dev; 240struct make_dev_args args; 241int res; 242 243make_dev_args_init(&args); 244args.mda_flags = flags; 245args.mda_devsw = cdevsw; 246args.mda_cred = cred; 247args.mda_uid = uid; 248args.mda_gid = gid; 249args.mda_mode = perms; 250res = make_dev_s(&args, &dev, name); 251.Ed 252.Pp 253Similarly, the 254.Fn make_dev_credf 255function call is equivalent to 256.Bd -literal -offset indent 257 (void) make_dev_s(&args, &dev, name); 258.Ed 259In other words, 260.Fn make_dev_credf 261does not allow the caller to obtain the return value, and in 262kernels compiled with the 263.Va INVARIANTS 264options, the function asserts that the device creation succeeded. 265.Pp 266The 267.Fn make_dev_cred 268function is equivalent to the call 269.Bd -literal -offset indent 270make_dev_credf(0, cdevsw, unit, cr, uid, gid, perms, fmt, ...); 271.Ed 272.Pp 273The 274.Fn make_dev 275function call is the same as 276.Bd -literal -offset indent 277make_dev_credf(0, cdevsw, unit, NULL, uid, gid, perms, fmt, ...); 278.Ed 279.Pp 280The 281.Fn make_dev_alias_p 282function takes the returned 283.Ft cdev 284from 285.Fn make_dev 286and makes another (aliased) name for this device. 287It is an error to call 288.Fn make_dev_alias_p 289prior to calling 290.Fn make_dev . 291.Pp 292The 293.Fn make_dev_alias 294function is similar to 295.Fn make_dev_alias 296but it returns the resulting aliasing 297.Ft *cdev 298and may not return an error. 299.Pp 300The 301.Fa cdev 302returned by 303.Fn make_dev_s 304and 305.Fn make_dev_alias_p 306has two fields, 307.Fa si_drv1 308and 309.Fa si_drv2 , 310that are available to store state. 311Both fields are of type 312.Ft void * , 313and can be initialized simultaneously with the 314.Va cdev 315allocation by filling 316.Va args.mda_si_drv1 317and 318.Va args.mda_si_drv2 319members of the 320.Fn make_dev_s 321argument structure, or filled after the 322.Va cdev 323is allocated, if using legacy interfaces. 324In the latter case, the driver should handle the race of 325accessing uninitialized 326.Va si_drv1 327and 328.Va si_drv2 329itself. 330These are designed to replace the 331.Fa unit 332argument to 333.Fn make_dev , 334which can be obtained with 335.Fn dev2unit . 336.Pp 337The 338.Fn destroy_dev 339function takes the returned 340.Fa cdev 341from 342.Fn make_dev 343and destroys the registration for that device. 344The notification is sent to 345.Xr devctl 4 346about the destruction event. 347Do not call 348.Fn destroy_dev 349on devices that were created with 350.Fn make_dev_alias . 351.Pp 352The 353.Fn dev_depends 354function establishes a parent-child relationship between two devices. 355The net effect is that a 356.Fn destroy_dev 357of the parent device will also result in the destruction of the 358child device(s), 359if any exist. 360A device may simultaneously be a parent and a child, 361so it is possible to build a complete hierarchy. 362.Pp 363The 364.Fn destroy_dev_sched_cb 365function schedules execution of the 366.Fn destroy_dev 367for the specified 368.Fa cdev 369in the safe context. 370After 371.Fn destroy_dev 372is finished, and if the supplied 373.Fa cb 374is not 375.Dv NULL , 376the callback 377.Fa cb 378is called, with argument 379.Fa arg . 380The 381.Fn destroy_dev_sched 382function is the same as 383.Bd -literal -offset indent 384destroy_dev_sched_cb(cdev, NULL, NULL); 385.Ed 386.Pp 387The 388.Fn d_close 389driver method cannot call 390.Fn destroy_dev 391directly. 392Doing so causes deadlock when 393.Fn destroy_dev 394waits for all threads to leave the driver methods. 395Also, because 396.Fn destroy_dev 397sleeps, no non-sleepable locks may be held over the call. 398The 399.Fn destroy_dev_sched 400family of functions overcome these issues. 401.Pp 402The device driver may call the 403.Fn destroy_dev_drain 404function to wait until all devices that have supplied 405.Fa csw 406as cdevsw, are destroyed. 407This is useful when driver knows that 408.Fn destroy_dev_sched 409is called for all instantiated devices, but need to postpone module 410unload until 411.Fn destroy_dev 412is actually finished for all of them. 413.Sh RETURN VALUES 414If successful, 415.Fn make_dev_s 416and 417.Fn make_dev_p 418will return 0, otherwise they will return an error. 419If successful, 420.Fn make_dev_credf 421will return a valid 422.Fa cdev 423pointer, otherwise it will return 424.Dv NULL . 425.Sh ERRORS 426The 427.Fn make_dev_s , 428.Fn make_dev_p 429and 430.Fn make_dev_alias_p 431calls will fail and the device will be not registered if: 432.Bl -tag -width Er 433.It Bq Er ENOMEM 434The 435.Dv MAKEDEV_NOWAIT 436flag was specified and a memory allocation request could not be satisfied. 437.It Bq Er ENAMETOOLONG 438The 439.Dv MAKEDEV_CHECKNAME 440flag was specified and the provided device name is longer than 441.Dv SPECNAMELEN . 442.It Bq Er EINVAL 443The 444.Dv MAKEDEV_CHECKNAME 445flag was specified and the provided device name is empty, contains a 446.Qq \&. 447or 448.Qq .. 449path component or ends with 450.Ql / . 451.It Bq Er EINVAL 452The 453.Dv MAKEDEV_CHECKNAME 454flag was specified and the provided device name contains invalid characters. 455.It Bq Er EEXIST 456The 457.Dv MAKEDEV_CHECKNAME 458flag was specified and the provided device name already exists. 459.El 460.Sh SEE ALSO 461.Xr devctl 4 , 462.Xr devfs 5 , 463.Xr dev_clone 9 464.Sh HISTORY 465The 466.Fn make_dev 467and 468.Fn destroy_dev 469functions first appeared in 470.Fx 4.0 . 471The function 472.Fn make_dev_alias 473first appeared in 474.Fx 4.1 . 475The function 476.Fn dev_depends 477first appeared in 478.Fx 5.0 . 479The functions 480.Fn make_dev_credf , 481.Fn destroy_dev_sched , 482.Fn destroy_dev_sched_cb 483first appeared in 484.Fx 7.0 . 485The function 486.Fn make_dev_p 487first appeared in 488.Fx 8.2 . 489The function 490.Fn make_dev_s 491first appeared in 492.Fx 11.0 . 493