* add p cc
[mascara-docs.git] / i386 / linux / linux-0.99 / drivers / block / genhd.c
blob1681d2b273d13dbc0aa40e104a91b856ea001534
1 /*
2 * Code extracted from
3 * linux/kernel/hd.c
5 * Copyright (C) 1991, 1992 Linus Torvalds
6 */
8 /*
9 * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
10 * in the early extended-partition checks and added DM partitions
13 #include <linux/config.h>
14 #include <linux/fs.h>
15 #include <linux/genhd.h>
16 #include <linux/kernel.h>
18 struct gendisk *gendisk_head = NULL;
20 static int current_minor = 0;
21 extern int *blk_size[];
22 extern void rd_load(void);
23 extern int ramdisk_size;
26 * Create devices for each logical partition in an extended partition.
27 * The logical partitions form a linked list, with each entry being
28 * a partition table with two entries. The first entry
29 * is the real data partition (with a start relative to the partition
30 * table start). The second is a pointer to the next logical partition
31 * (with a start relative to the entire extended partition).
32 * We do not create a Linux partition for the partition tables, but
33 * only for the actual data partitions.
36 static void extended_partition(struct gendisk *hd, int dev)
38 struct buffer_head *bh;
39 struct partition *p;
40 unsigned long first_sector, this_sector;
41 int mask = (1 << hd->minor_shift) - 1;
43 first_sector = hd->part[MINOR(dev)].start_sect;
44 this_sector = first_sector;
46 while (1) {
47 if ((current_minor & mask) >= (4 + hd->max_p))
48 return;
49 if (!(bh = bread(dev,0,1024)))
50 return;
52 * This block is from a device that we're about to stomp on.
53 * So make sure nobody thinks this block is usable.
55 bh->b_dirt=0;
56 bh->b_uptodate=0;
57 if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
58 p = (struct partition *) (0x1BE + bh->b_data);
60 * Process the first entry, which should be the real
61 * data partition.
63 if (p->sys_ind == EXTENDED_PARTITION ||
64 !(hd->part[current_minor].nr_sects = p->nr_sects))
65 goto done; /* shouldn't happen */
66 hd->part[current_minor].start_sect = this_sector + p->start_sect;
67 printk(" %s%c%d", hd->major_name,
68 'a'+(current_minor >> hd->minor_shift),
69 mask & current_minor);
70 current_minor++;
71 p++;
73 * Process the second entry, which should be a link
74 * to the next logical partition. Create a minor
75 * for this just long enough to get the next partition
76 * table. The minor will be reused for the real
77 * data partition.
79 if (p->sys_ind != EXTENDED_PARTITION ||
80 !(hd->part[current_minor].nr_sects = p->nr_sects))
81 goto done; /* no more logicals in this partition */
82 hd->part[current_minor].start_sect = first_sector + p->start_sect;
83 this_sector = first_sector + p->start_sect;
84 dev = ((hd->major) << 8) | current_minor;
85 brelse(bh);
86 } else
87 goto done;
89 done:
90 brelse(bh);
93 static void check_partition(struct gendisk *hd, unsigned int dev)
95 static int first_time = 1;
96 int i, minor = current_minor;
97 struct buffer_head *bh;
98 struct partition *p;
99 unsigned long first_sector;
100 int mask = (1 << hd->minor_shift) - 1;
102 if (first_time)
103 printk("Partition check:\n");
104 first_time = 0;
105 first_sector = hd->part[MINOR(dev)].start_sect;
106 if (!(bh = bread(dev,0,1024))) {
107 printk(" unable to read partition table of device %04x\n",dev);
108 return;
110 printk(" %s%c:", hd->major_name, 'a'+(minor >> hd->minor_shift));
111 current_minor += 4; /* first "extra" minor */
112 if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
113 p = (struct partition *) (0x1BE + bh->b_data);
114 for (i=1 ; i<=4 ; minor++,i++,p++) {
115 if (!(hd->part[minor].nr_sects = p->nr_sects))
116 continue;
117 hd->part[minor].start_sect = first_sector + p->start_sect;
118 printk(" %s%c%d", hd->major_name,'a'+(minor >> hd->minor_shift), i);
119 if ((current_minor & 0x3f) >= 60)
120 continue;
121 if (p->sys_ind == EXTENDED_PARTITION) {
122 printk(" <");
123 extended_partition(hd, (hd->major << 8) | minor);
124 printk(" >");
128 * check for Disk Manager partition table
130 if (*(unsigned short *) (bh->b_data+0xfc) == 0x55AA) {
131 p = (struct partition *) (0x1BE + bh->b_data);
132 for (i = 4 ; i < 16 ; i++, current_minor++) {
133 p--;
134 if ((current_minor & mask) >= mask-2)
135 break;
136 if (!(p->start_sect && p->nr_sects))
137 continue;
138 hd->part[current_minor].start_sect = p->start_sect;
139 hd->part[current_minor].nr_sects = p->nr_sects;
140 printk(" %s%c%d", hd->major_name,
141 'a'+(current_minor >> hd->minor_shift),
142 current_minor & mask);
145 } else
146 printk(" bad partition table");
147 printk("\n");
148 brelse(bh);
151 /* This function is used to re-read partition tables for removable disks.
152 Much of the cleanup from the old partition tables should have already been
153 done */
155 /* This function will re-read the partition tables for a given device,
156 and set things back up again. There are some important caveats,
157 however. You must ensure that no one is using the device, and no one
158 can start using the device while this function is being executed. */
160 void resetup_one_dev(struct gendisk *dev, int drive)
162 int i;
163 int start = drive<<dev->minor_shift;
164 int j = start + dev->max_p;
165 int major = dev->major << 8;
167 current_minor = 1+(drive<<dev->minor_shift);
168 check_partition(dev, major+(drive<<dev->minor_shift));
170 for (i=start ; i < j ; i++)
171 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
174 static void setup_dev(struct gendisk *dev)
176 int i;
177 int j = dev->max_nr * dev->max_p;
178 int major = dev->major << 8;
179 int drive;
182 for (i = 0 ; i < j; i++) {
183 dev->part[i].start_sect = 0;
184 dev->part[i].nr_sects = 0;
186 dev->init();
187 for (drive=0 ; drive<dev->nr_real ; drive++) {
188 current_minor = 1+(drive<<dev->minor_shift);
189 check_partition(dev, major+(drive<<dev->minor_shift));
191 for (i=0 ; i < j ; i++)
192 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
193 blk_size[dev->major] = dev->sizes;
196 /* This may be used only once, enforced by 'static int callable' */
197 asmlinkage int sys_setup(void * BIOS)
199 static int callable = 1;
200 struct gendisk *p;
201 int nr=0;
203 if (!callable)
204 return -1;
205 callable = 0;
207 for (p = gendisk_head ; p ; p=p->next) {
208 setup_dev(p);
209 nr += p->nr_real;
212 if (ramdisk_size)
213 rd_load();
214 mount_root();
215 return (0);