File: /usr/src/linux/drivers/block/genhd.c
1 /*
2 * Code extracted from
3 * linux/kernel/hd.c
4 *
5 * Copyright (C) 1991-1998 Linus Torvalds
6 *
7 * devfs support - jj, rgooch, 980122
8 *
9 * Moved partition checking code to fs/partitions* - Russell King
10 * (linux@arm.uk.linux.org)
11 */
12
13 /*
14 * TODO: rip out the remaining init crap from this file --hch
15 */
16
17 #include <linux/config.h>
18 #include <linux/module.h>
19 #include <linux/fs.h>
20 #include <linux/genhd.h>
21 #include <linux/kernel.h>
22 #include <linux/blk.h>
23 #include <linux/init.h>
24 #include <linux/spinlock.h>
25
26
27 static rwlock_t gendisk_lock;
28
29 /*
30 * Global kernel list of partitioning information.
31 *
32 * XXX: you should _never_ access this directly.
33 * the only reason this is exported is source compatiblity.
34 */
35 /*static*/ struct gendisk *gendisk_head;
36
37 EXPORT_SYMBOL(gendisk_head);
38
39
40 /**
41 * add_gendisk - add partitioning information to kernel list
42 * @gp: per-device partitioning information
43 *
44 * This function registers the partitioning information in @gp
45 * with the kernel.
46 */
47 void
48 add_gendisk(struct gendisk *gp)
49 {
50 write_lock(&gendisk_lock);
51 gp->next = gendisk_head;
52 gendisk_head = gp;
53 write_unlock(&gendisk_lock);
54 }
55
56 EXPORT_SYMBOL(add_gendisk);
57
58
59 /**
60 * del_gendisk - remove partitioning information from kernel list
61 * @gp: per-device partitioning information
62 *
63 * This function unregisters the partitioning information in @gp
64 * with the kernel.
65 */
66 void
67 del_gendisk(struct gendisk *gp)
68 {
69 struct gendisk **gpp;
70
71 write_lock(&gendisk_lock);
72 for (gpp = &gendisk_head; *gpp; gpp = &((*gpp)->next))
73 if (*gpp == gp)
74 break;
75 if (*gpp)
76 *gpp = (*gpp)->next;
77 write_unlock(&gendisk_lock);
78 }
79
80 EXPORT_SYMBOL(del_gendisk);
81
82
83 /**
84 * get_gendisk - get partitioning information for a given device
85 * @dev: device to get partitioning information for
86 *
87 * This function gets the structure containing partitioning
88 * information for the given device @dev.
89 */
90 struct gendisk *
91 get_gendisk(kdev_t dev)
92 {
93 struct gendisk *gp = NULL;
94 int maj = MAJOR(dev);
95
96 read_lock(&gendisk_lock);
97 for (gp = gendisk_head; gp; gp = gp->next)
98 if (gp->major == maj)
99 break;
100 read_unlock(&gendisk_lock);
101
102 return gp;
103 }
104
105 EXPORT_SYMBOL(get_gendisk);
106
107
108 #ifdef CONFIG_PROC_FS
109 int
110 get_partition_list(char *page, char **start, off_t offset, int count)
111 {
112 struct gendisk *gp;
113 char buf[64];
114 int len, n;
115
116 len = sprintf(page, "major minor #blocks name\n\n");
117 read_lock(&gendisk_lock);
118 for (gp = gendisk_head; gp; gp = gp->next) {
119 for (n = 0; n < (gp->nr_real << gp->minor_shift); n++) {
120 if (gp->part[n].nr_sects == 0)
121 continue;
122
123 len += snprintf(page + len, 63,
124 "%4d %4d %10d %s\n",
125 gp->major, n, gp->sizes[n],
126 disk_name(gp, n, buf));
127 if (len < offset)
128 offset -= len, len = 0;
129 else if (len >= offset + count)
130 goto out;
131 }
132 }
133
134 out:
135 read_unlock(&gendisk_lock);
136 *start = page + offset;
137 len -= offset;
138 if (len < 0)
139 len = 0;
140 return len > count ? count : len;
141 }
142 #endif
143
144
145 extern int blk_dev_init(void);
146 #ifdef CONFIG_BLK_DEV_DAC960
147 extern void DAC960_Initialize(void);
148 #endif
149 #ifdef CONFIG_FUSION_BOOT
150 extern int fusion_init(void);
151 #endif
152 extern int net_dev_init(void);
153 extern void console_map_init(void);
154 extern int soc_probe(void);
155 extern int atmdev_init(void);
156 extern int i2o_init(void);
157 extern int cpqarray_init(void);
158
159 int __init device_init(void)
160 {
161 rwlock_init(&gendisk_lock);
162 blk_dev_init();
163 sti();
164 #ifdef CONFIG_I2O
165 i2o_init();
166 #endif
167 #ifdef CONFIG_BLK_DEV_DAC960
168 DAC960_Initialize();
169 #endif
170 #ifdef CONFIG_FUSION_BOOT
171 fusion_init();
172 #endif
173 #ifdef CONFIG_FC4_SOC
174 /* This has to be done before scsi_dev_init */
175 soc_probe();
176 #endif
177 #ifdef CONFIG_BLK_CPQ_DA
178 cpqarray_init();
179 #endif
180 #ifdef CONFIG_NET
181 net_dev_init();
182 #endif
183 #ifdef CONFIG_ATM
184 (void) atmdev_init();
185 #endif
186 #ifdef CONFIG_VT
187 console_map_init();
188 #endif
189 return 0;
190 }
191
192 __initcall(device_init);
193