2 * Copyright (c) 2009 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Alex Hornung <ahornung@gmail.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <machine/limits.h>
40 #include <vfs/devfs/devfs.h>
42 MALLOC_DECLARE(M_DEVFS);
44 static struct devfs_unit_hash *devfs_clone_hash_get(int, cdev_t);
45 static void devfs_clone_hash_put(struct devfs_unit_hash *);
46 static int devfs_clone_hash_add(struct devfs_unit_hash **, struct devfs_unit_hash *);
47 static struct devfs_unit_hash *devfs_clone_hash_del(struct devfs_unit_hash **, int);
50 * DEVFS clone hash functions
53 static struct devfs_unit_hash *
54 devfs_clone_hash_get(int unit_no, cdev_t dev)
56 struct devfs_unit_hash *hash = (struct devfs_unit_hash *)kmalloc(sizeof(struct devfs_unit_hash), M_DEVFS, M_WAITOK);
58 hash->unit_no = unit_no;
66 devfs_clone_hash_put(struct devfs_unit_hash *hash)
73 devfs_clone_hash_add(struct devfs_unit_hash **devfs_hash_array, struct devfs_unit_hash *hash)
75 struct devfs_unit_hash **hashp;
76 hashp = &devfs_hash_array[hash->unit_no &
79 if ((*hashp)->unit_no ==
82 hashp = &(*hashp)->next;
90 static struct devfs_unit_hash *
91 devfs_clone_hash_del(struct devfs_unit_hash **devfs_hash_array, int unit_no)
93 struct devfs_unit_hash **hashp;
94 struct devfs_unit_hash *hash;
95 hashp = &devfs_hash_array[unit_no &
98 while ((*hashp)->unit_no != unit_no) {
99 KKASSERT(*hashp != NULL);
100 hashp = &(*hashp)->next;
109 * DEVFS clone bitmap functions
112 devfs_clone_bitmap_init(struct devfs_bitmap *bitmap)
114 bitmap->bitmap = (unsigned long *)kmalloc(DEVFS_BITMAP_INITIAL_SIZE*sizeof(unsigned long), M_DEVFS, M_WAITOK);
115 bitmap->chunks = DEVFS_BITMAP_INITIAL_SIZE;
116 memset(bitmap->bitmap, ULONG_MAX, DEVFS_BITMAP_INITIAL_SIZE*sizeof(unsigned long));
121 devfs_clone_bitmap_uninit(struct devfs_bitmap *bitmap)
123 kfree(bitmap->bitmap, M_DEVFS);
128 devfs_clone_bitmap_resize(struct devfs_bitmap *bitmap, int newchunks)
130 int oldchunks = bitmap->chunks;
131 bitmap->chunks = newchunks+2;
132 bitmap->bitmap = (unsigned long *)krealloc(bitmap->bitmap, sizeof(unsigned long)*bitmap->chunks, M_DEVFS, M_WAITOK);
134 devfs_debug(DEVFS_DEBUG_DEBUG, "%d vs %d (oldchunks=%d)\n", bitmap->bitmap, bitmap->bitmap + oldchunks, oldchunks);
135 memset(bitmap->bitmap + oldchunks, ULONG_MAX, sizeof(unsigned long)*(bitmap->chunks - oldchunks));
140 devfs_clone_bitmap_fff(struct devfs_bitmap *bitmap)
142 unsigned long curbitmap;
144 int chunks = bitmap->chunks;
146 for (i = 0; i < chunks+1; i++) {
148 devfs_clone_bitmap_resize(bitmap, i);
149 curbitmap = bitmap->bitmap[i];
152 curbitmap &= (~curbitmap)+1;
153 for (bit = 1; curbitmap != 1; bit++)
154 curbitmap = (unsigned long)curbitmap >> 1;
156 return bit-1 + (i<<3) * sizeof(unsigned long);
160 /* Should never happen as we dynamically resize as needed */
166 devfs_clone_bitmap_chk(struct devfs_bitmap *bitmap, int unit)
168 int chunk = unit / (sizeof(unsigned long)<<3);
169 unit -= chunk<<3 * sizeof(unsigned long);
171 if (chunk >= bitmap->chunks)
174 return !((bitmap->bitmap[chunk]) & (1<<(unit)));
179 devfs_clone_bitmap_set(struct devfs_bitmap *bitmap, int unit)
181 int chunk = unit / (sizeof(unsigned long)<<3);
182 unit -= chunk<<3 * sizeof(unsigned long);
184 if (chunk >= bitmap->chunks) {
185 devfs_clone_bitmap_resize(bitmap, chunk);
188 bitmap->bitmap[chunk] ^= (1<<unit);
193 devfs_clone_bitmap_rst(struct devfs_bitmap *bitmap, int unit)
195 int chunk = unit / (sizeof(unsigned long)<<3);
196 unit -= chunk<<3 * sizeof(unsigned long);
198 if (chunk >= bitmap->chunks)
201 bitmap->bitmap[chunk] |= (1<<unit);
206 devfs_clone_bitmap_get(struct devfs_bitmap *bitmap, int limit)
209 unit = devfs_clone_bitmap_fff(bitmap);
210 KKASSERT(unit != -1);
212 if ((limit > 0) && (unit > limit))
215 devfs_clone_bitmap_set(bitmap, unit);
221 * DEVFS clone helper functions
225 devfs_clone_helper_init(struct devfs_clone_helper *helper)
227 devfs_clone_bitmap_init(&helper->DEVFS_CLONE_BITMAP(generic));
228 memset(&helper->DEVFS_CLONE_HASHLIST(generic), 0, DEVFS_UNIT_HSIZE*sizeof(void *));
233 devfs_clone_helper_uninit(struct devfs_clone_helper *helper)
235 devfs_clone_bitmap_uninit(&helper->DEVFS_CLONE_BITMAP(generic));
236 //XXX: free all elements in helper->DEVFS_HASHLIST(generic)
241 devfs_clone_helper_insert(struct devfs_clone_helper *helper, cdev_t dev)
243 struct devfs_unit_hash *hash;
248 unit_no = devfs_clone_bitmap_fff(&helper->DEVFS_CLONE_BITMAP(generic));
250 devfs_clone_bitmap_set(&helper->DEVFS_CLONE_BITMAP(generic), unit_no);
251 hash = devfs_clone_hash_get(unit_no, dev);
253 error = devfs_clone_hash_add(helper->DEVFS_CLONE_HASHLIST(generic), hash);
259 dev->si_uminor = unit_no;
265 devfs_clone_helper_remove(struct devfs_clone_helper *helper, int unit_no)
267 struct devfs_unit_hash *hash;
268 hash = devfs_clone_hash_del(helper->DEVFS_CLONE_HASHLIST(generic), unit_no);
269 devfs_clone_bitmap_rst(&helper->DEVFS_CLONE_BITMAP(generic), unit_no);
270 kfree(hash, M_DEVFS);