kernel/scsi: Fix sense information printing in bootverbose.
[dragonfly.git] / sys / kern / kern_conf.c
1 /*-
2  * Parts Copyright (c) 1995 Terrence R. Lambert
3  * Copyright (c) 1995 Julian R. Elischer
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed by Terrence R. Lambert.
17  * 4. The name Terrence R. Lambert may not be used to endorse or promote
18  *    products derived from this software without specific prior written
19  *    permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY Julian R. Elischer ``AS IS'' AND ANY
22  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * $FreeBSD: src/sys/kern/kern_conf.c,v 1.73.2.3 2003/03/10 02:18:25 imp Exp $
34  */
35
36 #include <sys/param.h>
37 #include <sys/kernel.h>
38 #include <sys/sysctl.h>
39 #include <sys/systm.h>
40 #include <sys/module.h>
41 #include <sys/conf.h>
42 #include <sys/vnode.h>
43 #include <sys/queue.h>
44 #include <sys/device.h>
45 #include <sys/disk.h>
46 #include <machine/stdarg.h>
47
48 #include <sys/sysref2.h>
49
50 #include <sys/devfs.h>
51
52 int dev_ref_debug = 0;
53 SYSCTL_INT(_debug, OID_AUTO, dev_refs, CTLFLAG_RW, &dev_ref_debug, 0,
54     "Toggle device reference debug output");
55
56 /*
57  * cdev_t and u_dev_t primitives.  Note that the major number is always
58  * extracted from si_umajor, not from si_devsw, because si_devsw is replaced
59  * when a device is destroyed.
60  */
61 int
62 major(cdev_t dev)
63 {
64         if (dev == NULL)
65                 return NOUDEV;
66         return(dev->si_umajor);
67 }
68
69 int
70 minor(cdev_t dev)
71 {
72         if (dev == NULL)
73                 return NOUDEV;
74         return(dev->si_uminor);
75 }
76
77 /*
78  * Compatibility function with old udev_t format to convert the
79  * non-consecutive minor space into a consecutive minor space.
80  */
81 int
82 lminor(cdev_t dev)
83 {
84         int y;
85
86         if (dev == NULL)
87                 return NOUDEV;
88         y = dev->si_uminor;
89         if (y & 0x0000ff00)
90                 return NOUDEV;
91         return ((y & 0xff) | (y >> 8));
92 }
93
94 /*
95  * Convert a device pointer to an old style device number.  Return NOUDEV
96  * if the device is invalid or if the device (maj,min) cannot be converted
97  * to an old style udev_t.
98  */
99 udev_t
100 dev2udev(cdev_t dev)
101 {
102         if (dev == NULL)
103                 return NOUDEV;
104
105         return (udev_t)dev->si_inode;
106 }
107
108 /*
109  * Convert a device number to a device pointer.  The device is referenced
110  * ad-hoc, meaning that the caller should call reference_dev() if it wishes
111  * to keep ahold of the returned structure long term.
112  *
113  * The returned device is associated with the currently installed cdevsw
114  * for the requested major number.  NULL is returned if the major number
115  * has not been registered.
116  */
117 cdev_t
118 udev2dev(udev_t x, int b)
119 {
120         if (x == NOUDEV || b != 0)
121                 return(NULL);
122
123         return devfs_find_device_by_udev(x);
124 }
125
126 int
127 dev_is_good(cdev_t dev)
128 {
129         if (dev != NULL && dev->si_ops != &dead_dev_ops)
130                 return(1);
131         return(0);
132 }
133
134 /*
135  * Various user device number extraction and conversion routines
136  */
137 int
138 uminor(udev_t dev)
139 {
140         if (dev == NOUDEV)
141                 return(-1);
142         return(dev & 0xffff00ff);
143 }
144
145 int
146 umajor(udev_t dev)
147 {
148         if (dev == NOUDEV)
149                 return(-1);
150         return((dev & 0xff00) >> 8);
151 }
152
153 udev_t
154 makeudev(int x, int y)
155 {
156         if ((x & 0xffffff00) || (y & 0x0000ff00))
157                 return NOUDEV;
158         return ((x << 8) | y);
159 }
160
161 /*
162  * Create an internal or external device.
163  *
164  * This routine creates and returns an unreferenced ad-hoc entry for the
165  * device which will remain intact until the device is destroyed.  If the
166  * caller intends to store the device pointer it must call reference_dev()
167  * to retain a real reference to the device.
168  *
169  * If an entry already exists, this function will set (or override)
170  * its cred requirements and name (XXX DEVFS interface).
171  */
172 cdev_t
173 make_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid,
174         int perms, const char *fmt, ...)
175 {
176         cdev_t  devfs_dev;
177         __va_list ap;
178
179         /*
180          * compile the cdevsw and install the device
181          */
182         compile_dev_ops(ops);
183
184         devfs_dev = devfs_new_cdev(ops, minor, NULL);
185         __va_start(ap, fmt);
186         kvsnrprintf(devfs_dev->si_name, sizeof(devfs_dev->si_name),
187                     32, fmt, ap);
188         __va_end(ap);
189
190         devfs_debug(DEVFS_DEBUG_INFO,
191                     "make_dev called for %s\n",
192                     devfs_dev->si_name);
193         devfs_create_dev(devfs_dev, uid, gid, perms);
194
195         return (devfs_dev);
196 }
197
198 /*
199  * make_dev_covering has equivalent functionality to make_dev, except that it
200  * also takes the dev_ops of the underlying device. Hence this function should
201  * only be used by systems and drivers which create devices covering others
202  */
203 cdev_t
204 make_dev_covering(struct dev_ops *ops, struct dev_ops *bops, int minor,
205             uid_t uid, gid_t gid, int perms, const char *fmt, ...)
206 {
207         cdev_t  devfs_dev;
208         __va_list ap;
209
210         /*
211          * compile the cdevsw and install the device
212          */
213         compile_dev_ops(ops);
214
215         devfs_dev = devfs_new_cdev(ops, minor, bops);
216         __va_start(ap, fmt);
217         kvsnrprintf(devfs_dev->si_name, sizeof(devfs_dev->si_name),
218                     32, fmt, ap);
219         __va_end(ap);
220
221         devfs_debug(DEVFS_DEBUG_INFO,
222                     "make_dev called for %s\n",
223                     devfs_dev->si_name);
224         devfs_create_dev(devfs_dev, uid, gid, perms);
225
226         return (devfs_dev);
227 }
228
229
230
231 cdev_t
232 make_only_devfs_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid,
233         int perms, const char *fmt, ...)
234 {
235         cdev_t  devfs_dev;
236         __va_list ap;
237
238         /*
239          * compile the cdevsw and install the device
240          */
241         compile_dev_ops(ops);
242         devfs_dev = devfs_new_cdev(ops, minor, NULL);
243
244         /*
245          * Set additional fields (XXX DEVFS interface goes here)
246          */
247         __va_start(ap, fmt);
248         kvsnrprintf(devfs_dev->si_name, sizeof(devfs_dev->si_name),
249                     32, fmt, ap);
250         __va_end(ap);
251
252         devfs_create_dev(devfs_dev, uid, gid, perms);
253
254         return (devfs_dev);
255 }
256
257 cdev_t
258 make_only_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid,
259         int perms, const char *fmt, ...)
260 {
261         cdev_t  devfs_dev;
262         __va_list ap;
263
264         /*
265          * compile the cdevsw and install the device
266          */
267         compile_dev_ops(ops);
268         devfs_dev = devfs_new_cdev(ops, minor, NULL);
269         devfs_dev->si_perms = perms;
270         devfs_dev->si_uid = uid;
271         devfs_dev->si_gid = gid;
272
273         /*
274          * Set additional fields (XXX DEVFS interface goes here)
275          */
276         __va_start(ap, fmt);
277         kvsnrprintf(devfs_dev->si_name, sizeof(devfs_dev->si_name),
278                     32, fmt, ap);
279         __va_end(ap);
280
281         reference_dev(devfs_dev);
282
283         return (devfs_dev);
284 }
285
286 cdev_t
287 make_only_dev_covering(struct dev_ops *ops, struct dev_ops *bops, int minor,
288         uid_t uid, gid_t gid, int perms, const char *fmt, ...)
289 {
290         cdev_t  devfs_dev;
291         __va_list ap;
292
293         /*
294          * compile the cdevsw and install the device
295          */
296         compile_dev_ops(ops);
297         devfs_dev = devfs_new_cdev(ops, minor, bops);
298         devfs_dev->si_perms = perms;
299         devfs_dev->si_uid = uid;
300         devfs_dev->si_gid = gid;
301
302         /*
303          * Set additional fields (XXX DEVFS interface goes here)
304          */
305         __va_start(ap, fmt);
306         kvsnrprintf(devfs_dev->si_name, sizeof(devfs_dev->si_name),
307                     32, fmt, ap);
308         __va_end(ap);
309
310         reference_dev(devfs_dev);
311
312         return (devfs_dev);
313 }
314
315 void
316 destroy_only_dev(cdev_t dev)
317 {
318         release_dev(dev);
319         release_dev(dev);
320         release_dev(dev);
321 }
322
323 /*
324  * destroy_dev() removes the adhoc association for a device and revectors
325  * its ops to &dead_dev_ops.
326  *
327  * This routine releases the reference count associated with the ADHOC
328  * entry, plus releases the reference count held by the caller.  What this
329  * means is that you should not call destroy_dev(make_dev(...)), because
330  * make_dev() does not bump the reference count (beyond what it needs to
331  * create the ad-hoc association).  Any procedure that intends to destroy
332  * a device must have its own reference to it first.
333  */
334 void
335 destroy_dev(cdev_t dev)
336 {
337         if (dev) {
338                 devfs_debug(DEVFS_DEBUG_DEBUG,
339                             "destroy_dev called for %s\n",
340                             dev->si_name);
341                 devfs_destroy_dev(dev);
342         }
343 }
344
345 /*
346  * Make sure all asynchronous disk and devfs related operations have
347  * completed.
348  *
349  * Typically called prior to mountroot to ensure that all disks have
350  * been completely probed and on module unload to ensure that ops
351  * structures have been dereferenced.
352  */
353 void
354 sync_devs(void)
355 {
356         disk_config(NULL);
357         devfs_config();
358         disk_config(NULL);
359         devfs_config();
360 }
361
362 int
363 make_dev_alias(cdev_t target, const char *fmt, ...)
364 {
365         __va_list ap;
366         char *name;
367
368         __va_start(ap, fmt);
369         kvasnrprintf(&name, PATH_MAX, 32, fmt, ap);
370         __va_end(ap);
371
372         devfs_make_alias(name, target);
373         kvasfree(&name);
374
375         return 0;
376 }
377
378 int
379 destroy_dev_alias(cdev_t target, const char *fmt, ...)
380 {
381         __va_list ap;
382         char *name;
383
384         __va_start(ap, fmt);
385         kvasnrprintf(&name, PATH_MAX, 32, fmt, ap);
386         __va_end(ap);
387
388         devfs_destroy_alias(name, target);
389         kvasfree(&name);
390
391         return 0;
392 }
393
394 extern struct dev_ops default_dev_ops;
395
396 cdev_t
397 make_autoclone_dev(struct dev_ops *ops, struct devfs_bitmap *bitmap,
398                 d_clone_t *nhandler, uid_t uid, gid_t gid, int perms, const char *fmt, ...)
399 {
400         __va_list ap;
401         cdev_t dev;
402         char *name;
403
404         __va_start(ap, fmt);
405         kvasnrprintf(&name, PATH_MAX, 32, fmt, ap);
406         __va_end(ap);
407
408         if (bitmap != NULL)
409                 devfs_clone_bitmap_init(bitmap);
410
411         devfs_clone_handler_add(name, nhandler);
412         dev = make_dev_covering(&default_dev_ops, ops, 0xffff00ff,
413                        uid, gid, perms, "%s", name);
414         kvasfree(&name);
415         return dev;
416 }
417
418 void
419 destroy_autoclone_dev(cdev_t dev, struct devfs_bitmap *bitmap)
420 {
421         if (dev == NULL)
422                 return;
423
424         devfs_clone_handler_del(dev->si_name);
425
426         if (bitmap != NULL)
427                 devfs_clone_bitmap_uninit(bitmap);
428
429         destroy_dev(dev);
430 }
431
432
433 /*
434  * Add a reference to a device.  Callers generally add their own references
435  * when they are going to store a device node in a variable for long periods
436  * of time, to prevent a disassociation from free()ing the node.
437  *
438  * Also note that a caller that intends to call destroy_dev() must first
439  * obtain a reference on the device.  The ad-hoc reference you get with
440  * make_dev() and friends is NOT sufficient to be able to call destroy_dev().
441  */
442 cdev_t
443 reference_dev(cdev_t dev)
444 {
445         //kprintf("reference_dev\n");
446
447         if (dev != NULL) {
448                 sysref_get(&dev->si_sysref);
449                 if (dev_ref_debug & 2) {
450                         kprintf("reference dev %p %s(minor=%08x) refs=%d\n",
451                             dev, devtoname(dev), dev->si_uminor,
452                             dev->si_sysref.refcnt);
453                 }
454         }
455         return(dev);
456 }
457
458 /*
459  * release a reference on a device.  The device will be terminated when the
460  * last reference has been released.
461  *
462  * NOTE: we must use si_umajor to figure out the original major number,
463  * because si_ops could already be pointing at dead_dev_ops.
464  */
465 void
466 release_dev(cdev_t dev)
467 {
468         //kprintf("release_dev\n");
469
470         if (dev == NULL)
471                 return;
472         sysref_put(&dev->si_sysref);
473 }
474
475 const char *
476 devtoname(cdev_t dev)
477 {
478         int mynor;
479         int len;
480         char *p;
481         const char *dname;
482
483         if (dev == NULL)
484                 return("#nodev");
485         if (dev->si_name[0] == '#' || dev->si_name[0] == '\0') {
486                 p = dev->si_name;
487                 len = sizeof(dev->si_name);
488                 if ((dname = dev_dname(dev)) != NULL)
489                         ksnprintf(p, len, "#%s/", dname);
490                 else
491                         ksnprintf(p, len, "#%d/", major(dev));
492                 len -= strlen(p);
493                 p += strlen(p);
494                 mynor = minor(dev);
495                 if (mynor < 0 || mynor > 255)
496                         ksnprintf(p, len, "%#x", (u_int)mynor);
497                 else
498                         ksnprintf(p, len, "%d", mynor);
499         }
500         return (dev->si_name);
501 }
502