OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [before_ORP/] [uclinux/] [uClinux-2.0.x/] [drivers/] [block/] [genhd.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 *  Code extracted from
3
 *  linux/kernel/hd.c
4
 *
5
 *  Copyright (C) 1991, 1992  Linus Torvalds
6
 *
7
 *
8
 *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
9
 *  in the early extended-partition checks and added DM partitions
10
 *
11
 *  Support for DiskManager v6.0x added by Mark Lord,
12
 *  with information provided by OnTrack.  This now works for linux fdisk
13
 *  and LILO, as well as loadlin and bootln.  Note that disks other than
14
 *  /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
15
 *
16
 *  More flexible handling of extended partitions - aeb, 950831
17
 *
18
 *  Check partition table on IDE disks for common CHS translations
19
 */
20
 
21
#include <linux/config.h>
22
#include <linux/fs.h>
23
#include <linux/genhd.h>
24
#include <linux/kernel.h>
25
#include <linux/major.h>
26
#include <linux/string.h>
27
#ifdef CONFIG_BLK_DEV_INITRD
28
#include <linux/blk.h>
29
#endif
30
 
31
#include <asm/system.h>
32
 
33
/*
34
 * Many architectures don't like unaligned accesses, which is
35
 * frequently the case with the nr_sects and start_sect partition
36
 * table entries.
37
 */
38
#include <asm/unaligned.h>
39
 
40
#define SYS_IND(p)      get_unaligned(&p->sys_ind)
41
#define NR_SECTS(p)     get_unaligned(&p->nr_sects)
42
#define START_SECT(p)   get_unaligned(&p->start_sect)
43
 
44
 
45
struct gendisk *gendisk_head = NULL;
46
 
47
static int current_minor = 0;
48
extern int *blk_size[];
49
extern void rd_load(void);
50
extern void initrd_load(void);
51
 
52
extern int chr_dev_init(void);
53
extern int blk_dev_init(void);
54
#ifdef CONFIG_BLK_DEV_DAC960
55
extern void DAC960_Initialize(void);
56
#endif
57
extern int scsi_dev_init(void);
58
extern int net_dev_init(void);
59
 
60
/*
61
 * disk_name() is used by genhd.c and md.c.
62
 * It formats the devicename of the indicated disk
63
 * into the supplied buffer, and returns a pointer
64
 * to that same buffer (for convenience).
65
 */
66
char *disk_name (struct gendisk *hd, int minor, char *buf)
67
{
68
        unsigned int part;
69
        const char *maj = hd->major_name;
70
        char unit = (minor >> hd->minor_shift) + 'a';
71
 
72
#ifdef CONFIG_BLK_DEV_IDE
73
        /*
74
         * IDE devices use multiple major numbers, but the drives
75
         * are named as:  {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
76
         * This requires special handling here.
77
         */
78
        switch (hd->major) {
79
                case IDE3_MAJOR:
80
                        unit += 2;
81
                case IDE2_MAJOR:
82
                        unit += 2;
83
                case IDE1_MAJOR:
84
                        unit += 2;
85
                case IDE0_MAJOR:
86
                        maj = "hd";
87
        }
88
#endif
89
        if (hd->major >= DAC960_MAJOR+0 && hd->major <= DAC960_MAJOR+7)
90
          {
91
            int controller = hd->major - DAC960_MAJOR;
92
            int partition = minor & ((1 << hd->minor_shift) - 1);
93
            if (partition == 0)
94
              sprintf(buf, "%s/c%dd%d",
95
                      maj, controller, minor >> hd->minor_shift);
96
            else sprintf(buf, "%s/c%dd%dp%d",
97
                         maj, controller, minor >> hd->minor_shift, partition);
98
            return buf;
99
          }
100
#if defined(CONFIG_BLK_CPQ_DA) || defined(CONFIG_BLK_CPQ_DA_MODULE)
101
        if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) {
102
                int ctlr = hd->major - COMPAQ_SMART2_MAJOR;
103
                int disk = minor >> hd->minor_shift;
104
                int part = minor & (( 1 << hd->minor_shift) - 1);
105
                if (part == 0)
106
                        sprintf(buf, "%s/c%dd%d", maj, ctlr, disk);
107
                else
108
                        sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, disk, part);
109
                return buf;
110
        }
111
#endif
112
        part = minor & ((1 << hd->minor_shift) - 1);
113
        if (part)
114
                sprintf(buf, "%s%c%d", maj, unit, part);
115
        else
116
                sprintf(buf, "%s%c", maj, unit);
117
        return buf;
118
}
119
 
120
static void add_partition (struct gendisk *hd, int minor, int start, int size)
121
{
122
        char buf[40];
123
        hd->part[minor].start_sect = start;
124
        hd->part[minor].nr_sects   = size;
125
        if (hd->major >= DAC960_MAJOR+0 && hd->major <= DAC960_MAJOR+7)
126
                printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
127
        else
128
#if defined(CONFIG_BLK_CPQ_DA) || defined(CONFIG_BLK_CPQ_DA_MODULE)
129
        if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7)
130
                printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
131
        else
132
#endif
133
                printk(" %s", disk_name(hd, minor, buf));
134
}
135
 
136
static inline int is_extended_partition(struct partition *p)
137
{
138
        return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||
139
                SYS_IND(p) == WIN98_EXTENDED_PARTITION ||
140
                SYS_IND(p) == LINUX_EXTENDED_PARTITION);
141
}
142
 
143
#ifdef CONFIG_MSDOS_PARTITION
144
/*
145
 * Create devices for each logical partition in an extended partition.
146
 * The logical partitions form a linked list, with each entry being
147
 * a partition table with two entries.  The first entry
148
 * is the real data partition (with a start relative to the partition
149
 * table start).  The second is a pointer to the next logical partition
150
 * (with a start relative to the entire extended partition).
151
 * We do not create a Linux partition for the partition tables, but
152
 * only for the actual data partitions.
153
 */
154
 
155
static void extended_partition(struct gendisk *hd, kdev_t dev)
156
{
157
        struct buffer_head *bh;
158
        struct partition *p;
159
        unsigned long first_sector, first_size, this_sector, this_size;
160
        int mask = (1 << hd->minor_shift) - 1;
161
        int i;
162
 
163
        first_sector = hd->part[MINOR(dev)].start_sect;
164
        first_size = hd->part[MINOR(dev)].nr_sects;
165
        this_sector = first_sector;
166
 
167
        while (1) {
168
                if ((current_minor & mask) == 0)
169
                        return;
170
                if (!(bh = bread(dev,0,1024)))
171
                        return;
172
          /*
173
           * This block is from a device that we're about to stomp on.
174
           * So make sure nobody thinks this block is usable.
175
           */
176
                bh->b_state = 0;
177
 
178
                if (*(unsigned short *) (bh->b_data+510) != 0xAA55)
179
                        goto done;
180
 
181
                p = (struct partition *) (0x1BE + bh->b_data);
182
 
183
                this_size = hd->part[MINOR(dev)].nr_sects;
184
 
185
                /*
186
                 * Usually, the first entry is the real data partition,
187
                 * the 2nd entry is the next extended partition, or empty,
188
                 * and the 3rd and 4th entries are unused.
189
                 * However, DRDOS sometimes has the extended partition as
190
                 * the first entry (when the data partition is empty),
191
                 * and OS/2 seems to use all four entries.
192
                 */
193
 
194
                /*
195
                 * First process the data partition(s)
196
                 */
197
                for (i=0; i<4; i++, p++) {
198
                    if (!NR_SECTS(p) || is_extended_partition(p))
199
                      continue;
200
 
201
                    /* Check the 3rd and 4th entries -
202
                       these sometimes contain random garbage */
203
                    if (i >= 2
204
                        && START_SECT(p) + NR_SECTS(p) > this_size
205
                        && (this_sector + START_SECT(p) < first_sector ||
206
                            this_sector + START_SECT(p) + NR_SECTS(p) >
207
                             first_sector + first_size))
208
                      continue;
209
 
210
                    add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p));
211
                    current_minor++;
212
                    if ((current_minor & mask) == 0)
213
                      goto done;
214
                }
215
                /*
216
                 * Next, process the (first) extended partition, if present.
217
                 * (So far, there seems to be no reason to make
218
                 *  extended_partition()  recursive and allow a tree
219
                 *  of extended partitions.)
220
                 * It should be a link to the next logical partition.
221
                 * Create a minor for this just long enough to get the next
222
                 * partition table.  The minor will be reused for the next
223
                 * data partition.
224
                 */
225
                p -= 4;
226
                for (i=0; i<4; i++, p++)
227
                  if(NR_SECTS(p) && is_extended_partition(p))
228
                    break;
229
                if (i == 4)
230
                  goto done;     /* nothing left to do */
231
 
232
                hd->part[current_minor].nr_sects = NR_SECTS(p);
233
                hd->part[current_minor].start_sect = first_sector + START_SECT(p);
234
                this_sector = first_sector + START_SECT(p);
235
                dev = MKDEV(hd->major, current_minor);
236
                brelse(bh);
237
        }
238
done:
239
        brelse(bh);
240
}
241
 
242
#ifdef CONFIG_BSD_DISKLABEL
243
/*
244
 * Create devices for BSD partitions listed in a disklabel, under a
245
 * dos-like partition. See extended_partition() for more information.
246
 */
247
static void bsd_disklabel_partition(struct gendisk *hd, kdev_t dev)
248
{
249
        struct buffer_head *bh;
250
        struct bsd_disklabel *l;
251
        struct bsd_partition *p;
252
        int mask = (1 << hd->minor_shift) - 1;
253
 
254
        if (!(bh = bread(dev,0,1024)))
255
                return;
256
        bh->b_state = 0;
257
        l = (struct bsd_disklabel *) (bh->b_data+512);
258
        if (l->d_magic != BSD_DISKMAGIC) {
259
                brelse(bh);
260
                return;
261
        }
262
 
263
        p = &l->d_partitions[0];
264
        while (p - &l->d_partitions[0] <= BSD_MAXPARTITIONS) {
265
                if ((current_minor & mask) >= (4 + hd->max_p))
266
                        break;
267
 
268
                if (p->p_fstype != BSD_FS_UNUSED) {
269
                        add_partition(hd, current_minor, p->p_offset, p->p_size);
270
                        current_minor++;
271
                }
272
                p++;
273
        }
274
        brelse(bh);
275
 
276
}
277
#endif
278
 
279
static int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
280
{
281
        int i, minor = current_minor;
282
        struct buffer_head *bh;
283
        struct partition *p;
284
        unsigned char *data;
285
        int mask = (1 << hd->minor_shift) - 1;
286
#ifdef CONFIG_BLK_DEV_IDE
287
        int tested_for_xlate = 0;
288
 
289
read_mbr:
290
#endif
291
        if (!(bh = bread(dev,0,1024))) {
292
                printk(" unable to read partition table\n");
293
                return -1;
294
        }
295
        data = bh->b_data;
296
        /* In some cases we modify the geometry    */
297
        /*  of the drive (below), so ensure that   */
298
        /*  nobody else tries to re-use this data. */
299
        bh->b_state = 0;
300
#ifdef CONFIG_BLK_DEV_IDE
301
check_table:
302
#endif
303
        if (*(unsigned short *)  (0x1fe + data) != 0xAA55) {
304
                brelse(bh);
305
                return 0;
306
        }
307
        p = (struct partition *) (0x1be + data);
308
 
309
#ifdef CONFIG_BLK_DEV_IDE
310
        if (!tested_for_xlate++) {      /* Do this only once per disk */
311
                /*
312
                 * Look for various forms of IDE disk geometry translation
313
                 */
314
                extern int ide_xlate_1024(kdev_t, int, const char *);
315
                unsigned int sig = *(unsigned short *)(data + 2);
316
                if (SYS_IND(p) == EZD_PARTITION) {
317
                        /*
318
                         * The remainder of the disk must be accessed using
319
                         * a translated geometry that reduces the number of
320
                         * apparent cylinders to less than 1024 if possible.
321
                         *
322
                         * ide_xlate_1024() will take care of the necessary
323
                         * adjustments to fool fdisk/LILO and partition check.
324
                         */
325
                        if (ide_xlate_1024(dev, -1, " [EZD]")) {
326
                                data += 512;
327
                                goto check_table;
328
                        }
329
                } else if (SYS_IND(p) == DM6_PARTITION) {
330
 
331
                        /*
332
                         * Everything on the disk is offset by 63 sectors,
333
                         * including a "new" MBR with its own partition table,
334
                         * and the remainder of the disk must be accessed using
335
                         * a translated geometry that reduces the number of
336
                         * apparent cylinders to less than 1024 if possible.
337
                         *
338
                         * ide_xlate_1024() will take care of the necessary
339
                         * adjustments to fool fdisk/LILO and partition check.
340
                         */
341
                        if (ide_xlate_1024(dev, 1, " [DM6:DDO]")) {
342
                                brelse(bh);
343
                                goto read_mbr;  /* start over with new MBR */
344
                        }
345
                } else if (sig <= 0x1ae && *(unsigned short *)(data + sig) == 0x55AA
346
                         && (1 & *(unsigned char *)(data + sig + 2)) )
347
                {
348
                        /*
349
                         * DM6 signature in MBR, courtesy of OnTrack
350
                         */
351
                        (void) ide_xlate_1024 (dev, 0, " [DM6:MBR]");
352
                } else if (SYS_IND(p) == DM6_AUX1PARTITION || SYS_IND(p) == DM6_AUX3PARTITION) {
353
                        /*
354
                         * DM6 on other than the first (boot) drive
355
                         */
356
                        (void) ide_xlate_1024(dev, 0, " [DM6:AUX]");
357
                } else {
358
                        /*
359
                         * Examine the partition table for common translations.
360
                         * This is necessary for drives for situations where
361
                         * the translated geometry is unavailable from the BIOS.
362
                         */
363
                        for (i = 0; i < 4 ; i++) {
364
                                struct partition *q = &p[i];
365
                                if (NR_SECTS(q)
366
                                   && (q->sector & 63) == 1
367
                                   && (q->end_sector & 63) == 63) {
368
                                        unsigned int heads = q->end_head + 1;
369
                                        if (heads == 32 || heads == 64 ||
370
                                            heads == 128 || heads == 240 ||
371
                                            heads == 255) {
372
 
373
                                                (void) ide_xlate_1024(dev, heads, " [PTBL]");
374
                                                break;
375
                                        }
376
                                }
377
                        }
378
                }
379
        }
380
#endif  /* CONFIG_BLK_DEV_IDE */
381
 
382
        current_minor += 4;  /* first "extra" minor (for extended partitions) */
383
        for (i=1 ; i<=4 ; minor++,i++,p++) {
384
                if (!NR_SECTS(p))
385
                        continue;
386
                add_partition(hd, minor, first_sector+START_SECT(p), NR_SECTS(p));
387
                if (is_extended_partition(p)) {
388
                        printk(" <");
389
                        /*
390
                         * If we are rereading the partition table, we need
391
                         * to set the size of the partition so that we will
392
                         * be able to bread the block containing the extended
393
                         * partition info.
394
                         */
395
                        hd->sizes[minor] = hd->part[minor].nr_sects
396
                                >> (BLOCK_SIZE_BITS - 9);
397
                        extended_partition(hd, MKDEV(hd->major, minor));
398
                        printk(" >");
399
                        /* prevent someone doing mkfs or mkswap on an
400
                           extended partition, but leave room for LILO */
401
                        if (hd->part[minor].nr_sects > 2)
402
                                hd->part[minor].nr_sects = 2;
403
                }
404
#ifdef CONFIG_BSD_DISKLABEL
405
                if (SYS_IND(p) == BSD_PARTITION) {
406
                        printk(" <");
407
                        bsd_disklabel_partition(hd, MKDEV(hd->major, minor));
408
                        printk(" >");
409
                }
410
#endif
411
        }
412
        /*
413
         *  Check for old-style Disk Manager partition table
414
         */
415
        if (*(unsigned short *) (data+0xfc) == 0x55AA) {
416
                p = (struct partition *) (0x1be + data);
417
                for (i = 4 ; i < 16 ; i++, current_minor++) {
418
                        p--;
419
                        if ((current_minor & mask) == 0)
420
                                break;
421
                        if (!(START_SECT(p) && NR_SECTS(p)))
422
                                continue;
423
                        add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
424
                }
425
        }
426
        printk("\n");
427
        brelse(bh);
428
        return 1;
429
}
430
 
431
#endif /* CONFIG_MSDOS_PARTITION */
432
 
433
#ifdef CONFIG_OSF_PARTITION
434
 
435
static int osf_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
436
{
437
        int i;
438
        int mask = (1 << hd->minor_shift) - 1;
439
        struct buffer_head *bh;
440
        struct disklabel {
441
                u32 d_magic;
442
                u16 d_type,d_subtype;
443
                u8 d_typename[16];
444
                u8 d_packname[16];
445
                u32 d_secsize;
446
                u32 d_nsectors;
447
                u32 d_ntracks;
448
                u32 d_ncylinders;
449
                u32 d_secpercyl;
450
                u32 d_secprtunit;
451
                u16 d_sparespertrack;
452
                u16 d_sparespercyl;
453
                u32 d_acylinders;
454
                u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
455
                u32 d_headswitch, d_trkseek, d_flags;
456
                u32 d_drivedata[5];
457
                u32 d_spare[5];
458
                u32 d_magic2;
459
                u16 d_checksum;
460
                u16 d_npartitions;
461
                u32 d_bbsize, d_sbsize;
462
                struct d_partition {
463
                        u32 p_size;
464
                        u32 p_offset;
465
                        u32 p_fsize;
466
                        u8  p_fstype;
467
                        u8  p_frag;
468
                        u16 p_cpg;
469
                } d_partitions[8];
470
        } * label;
471
        struct d_partition * partition;
472
#define DISKLABELMAGIC (0x82564557UL)
473
 
474
        if (!(bh = bread(dev,0,1024))) {
475
                printk("unable to read partition table\n");
476
                return -1;
477
        }
478
        label = (struct disklabel *) (bh->b_data+64);
479
        partition = label->d_partitions;
480
        if (label->d_magic != DISKLABELMAGIC) {
481
                printk("magic: %08x\n", label->d_magic);
482
                brelse(bh);
483
                return 0;
484
        }
485
        if (label->d_magic2 != DISKLABELMAGIC) {
486
                printk("magic2: %08x\n", label->d_magic2);
487
                brelse(bh);
488
                return 0;
489
        }
490
        for (i = 0 ; i < label->d_npartitions; i++, partition++) {
491
                if ((current_minor & mask) == 0)
492
                        break;
493
                if (partition->p_size)
494
                        add_partition(hd, current_minor,
495
                                first_sector+partition->p_offset,
496
                                partition->p_size);
497
                current_minor++;
498
        }
499
        printk("\n");
500
        brelse(bh);
501
        return 1;
502
}
503
 
504
#endif /* CONFIG_OSF_PARTITION */
505
 
506
#ifdef CONFIG_SUN_PARTITION
507
 
508
static int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
509
{
510
        int i, csum;
511
        unsigned short *ush;
512
        struct buffer_head *bh;
513
        struct sun_disklabel {
514
                unsigned char info[128];   /* Informative text string */
515
                unsigned char spare[292];  /* Boot information etc. */
516
                unsigned short rspeed;     /* Disk rotational speed */
517
                unsigned short pcylcount;  /* Physical cylinder count */
518
                unsigned short sparecyl;   /* extra sects per cylinder */
519
                unsigned char spare2[4];   /* More magic... */
520
                unsigned short ilfact;     /* Interleave factor */
521
                unsigned short ncyl;       /* Data cylinder count */
522
                unsigned short nacyl;      /* Alt. cylinder count */
523
                unsigned short ntrks;      /* Tracks per cylinder */
524
                unsigned short nsect;      /* Sectors per track */
525
                unsigned char spare3[4];   /* Even more magic... */
526
                struct sun_partition {
527
                        __u32 start_cylinder;
528
                        __u32 num_sectors;
529
                } partitions[8];
530
                unsigned short magic;      /* Magic number */
531
                unsigned short csum;       /* Label xor'd checksum */
532
        } * label;
533
        struct sun_partition *p;
534
        int other_endian;
535
        unsigned long spc;
536
#define SUN_LABEL_MAGIC          0xDABE
537
#define SUN_LABEL_MAGIC_SWAPPED  0xBEDA
538
/* No need to optimize these macros since they are called only when reading
539
 * the partition table. This occurs only at each disk change. */
540
#define SWAP16(x)  (other_endian ? (((__u16)(x) & 0xFF) << 8) \
541
                                 | (((__u16)(x) & 0xFF00) >> 8) \
542
                                 : (__u16)(x))
543
#define SWAP32(x)  (other_endian ? (((__u32)(x) & 0xFF) << 24) \
544
                                 | (((__u32)(x) & 0xFF00) << 8) \
545
                                 | (((__u32)(x) & 0xFF0000) >> 8) \
546
                                 | (((__u32)(x) & 0xFF000000) >> 24) \
547
                                 : (__u32)(x))
548
 
549
        if(!(bh = bread(dev, 0, 1024))) {
550
                printk("Dev %s: unable to read partition table\n",
551
                       kdevname(dev));
552
                return -1;
553
        }
554
        label = (struct sun_disklabel *) bh->b_data;
555
        p = label->partitions;
556
        if (label->magic != SUN_LABEL_MAGIC && label->magic != SUN_LABEL_MAGIC_SWAPPED) {
557
                printk("Dev %s Sun disklabel: bad magic %04x\n",
558
                       kdevname(dev), label->magic);
559
                brelse(bh);
560
                return 0;
561
        }
562
        other_endian = (label->magic == SUN_LABEL_MAGIC_SWAPPED);
563
        /* Look at the checksum */
564
        ush = ((unsigned short *) (label+1)) - 1;
565
        for(csum = 0; ush >= ((unsigned short *) label);)
566
                csum ^= *ush--;
567
        if(csum) {
568
                printk("Dev %s Sun disklabel: Csum bad, label corrupted\n",
569
                       kdevname(dev));
570
                brelse(bh);
571
                return 0;
572
        }
573
        /* All Sun disks have 8 partition entries */
574
        spc = SWAP16(label->ntrks) * SWAP16(label->nsect);
575
        for(i=0; i < 8; i++, p++) {
576
                unsigned long st_sector;
577
 
578
                /* We register all partitions, even if zero size, so that
579
                 * the minor numbers end up ok as per SunOS interpretation.
580
                 */
581
                st_sector = first_sector + SWAP32(p->start_cylinder) * spc;
582
                add_partition(hd, current_minor, st_sector, SWAP32(p->num_sectors));
583
                current_minor++;
584
        }
585
        printk("\n");
586
        brelse(bh);
587
        return 1;
588
#undef SWAP16
589
#undef SWAP32
590
}
591
 
592
#endif /* CONFIG_SUN_PARTITION */
593
 
594
#ifdef CONFIG_AMIGA_PARTITION
595
#include <asm/byteorder.h>
596
#include <linux/affs_hardblocks.h>
597
 
598
static __inline__ __u32
599
checksum_block(__u32 *m, int size)
600
{
601
        __u32 sum = 0;
602
 
603
        while (size--)
604
                sum += htonl(*m++);
605
        return sum;
606
}
607
 
608
static int
609
amiga_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
610
{
611
        struct buffer_head      *bh;
612
        struct RigidDiskBlock   *rdb;
613
        struct PartitionBlock   *pb;
614
        int                      start_sect;
615
        int                      nr_sects;
616
        int                      blk;
617
        int                      part, res;
618
 
619
        set_blocksize(dev,512);
620
        res = 0;
621
 
622
        for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) {
623
                if(!(bh = bread(dev,blk,512))) {
624
                        printk("Dev %d: unable to read RDB block %d\n",dev,blk);
625
                        goto rdb_done;
626
                }
627
                if (*(__u32 *)bh->b_data == htonl(IDNAME_RIGIDDISK)) {
628
                        rdb = (struct RigidDiskBlock *)bh->b_data;
629
                        if (checksum_block((__u32 *)bh->b_data,htonl(rdb->rdb_SummedLongs) & 0x7F)) {
630
                                printk("Dev %d: RDB in block %d has bad checksum\n",dev,blk);
631
                                brelse(bh);
632
                                continue;
633
                        }
634
                        printk(" RDSK");
635
                        blk = htonl(rdb->rdb_PartitionList);
636
                        brelse(bh);
637
                        for (part = 1; blk > 0 && part <= 16; part++) {
638
                                if (!(bh = bread(dev,blk,512))) {
639
                                        printk("Dev %d: unable to read partition block %d\n",
640
                                                       dev,blk);
641
                                        goto rdb_done;
642
                                }
643
                                pb  = (struct PartitionBlock *)bh->b_data;
644
                                blk = htonl(pb->pb_Next);
645
                                if (pb->pb_ID == htonl(IDNAME_PARTITION) && checksum_block(
646
                                    (__u32 *)pb,htonl(pb->pb_SummedLongs) & 0x7F) == 0 ) {
647
 
648
                                        /* Tell Kernel about it */
649
 
650
                                        if (!(nr_sects = (htonl(pb->pb_Environment[10]) + 1 -
651
                                                          htonl(pb->pb_Environment[9])) *
652
                                                         htonl(pb->pb_Environment[3]) *
653
                                                         htonl(pb->pb_Environment[5]))) {
654
                                                continue;
655
                                        }
656
                                        start_sect = htonl(pb->pb_Environment[9]) *
657
                                                     htonl(pb->pb_Environment[3]) *
658
                                                     htonl(pb->pb_Environment[5]);
659
                                        add_partition(hd,current_minor,start_sect,nr_sects);
660
                                        current_minor++;
661
                                        res = 1;
662
                                }
663
                                brelse(bh);
664
                        }
665
                        printk("\n");
666
                        break;
667
                }
668
        }
669
 
670
rdb_done:
671
        set_blocksize(dev,BLOCK_SIZE);
672
        return res;
673
}
674
#endif /* CONFIG_AMIGA_PARTITION */
675
 
676
static void check_partition(struct gendisk *hd, kdev_t dev)
677
{
678
        static int first_time = 1;
679
        unsigned long first_sector;
680
        char buf[40];
681
 
682
        if (first_time)
683
                printk("Partition check:\n");
684
        first_time = 0;
685
        first_sector = hd->part[MINOR(dev)].start_sect;
686
 
687
        /*
688
         * This is a kludge to allow the partition check to be
689
         * skipped for specific drives (e.g. IDE cd-rom drives)
690
         */
691
        if ((int)first_sector == -1) {
692
                hd->part[MINOR(dev)].start_sect = 0;
693
                return;
694
        }
695
 
696
        printk(" %s:", disk_name(hd, MINOR(dev), buf));
697
#ifdef CONFIG_MSDOS_PARTITION
698
        if (msdos_partition(hd, dev, first_sector))
699
                return;
700
#endif
701
#ifdef CONFIG_OSF_PARTITION
702
        if (osf_partition(hd, dev, first_sector))
703
                return;
704
#endif
705
#ifdef CONFIG_SUN_PARTITION
706
        if(sun_partition(hd, dev, first_sector))
707
                return;
708
#endif
709
#ifdef CONFIG_AMIGA_PARTITION
710
        if(amiga_partition(hd, dev, first_sector))
711
                return;
712
#endif
713
        printk(" unknown partition table\n");
714
}
715
 
716
/* This function is used to re-read partition tables for removable disks.
717
   Much of the cleanup from the old partition tables should have already been
718
   done */
719
 
720
/* This function will re-read the partition tables for a given device,
721
and set things back up again.  There are some important caveats,
722
however.  You must ensure that no one is using the device, and no one
723
can start using the device while this function is being executed. */
724
 
725
void resetup_one_dev(struct gendisk *dev, int drive)
726
{
727
        int i;
728
        int first_minor = drive << dev->minor_shift;
729
        int end_minor   = first_minor + dev->max_p;
730
 
731
        blk_size[dev->major] = NULL;
732
        current_minor = 1 + first_minor;
733
        check_partition(dev, MKDEV(dev->major, first_minor));
734
 
735
        /*
736
         * We need to set the sizes array before we will be able to access
737
         * any of the partitions on this device.
738
         */
739
        if (dev->sizes != NULL) {       /* optional safeguard in ll_rw_blk.c */
740
                for (i = first_minor; i < end_minor; i++)
741
                        dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
742
                blk_size[dev->major] = dev->sizes;
743
        }
744
}
745
 
746
static void setup_dev(struct gendisk *dev)
747
{
748
        int i, drive;
749
        int end_minor   = dev->max_nr * dev->max_p;
750
 
751
        blk_size[dev->major] = NULL;
752
        for (i = 0 ; i < end_minor; i++) {
753
                dev->part[i].start_sect = 0;
754
                dev->part[i].nr_sects = 0;
755
        }
756
        dev->init(dev);
757
        for (drive = 0 ; drive < dev->nr_real ; drive++) {
758
                int first_minor = drive << dev->minor_shift;
759
                current_minor = 1 + first_minor;
760
                check_partition(dev, MKDEV(dev->major, first_minor));
761
        }
762
        if (dev->sizes != NULL) {       /* optional safeguard in ll_rw_blk.c */
763
                for (i = 0; i < end_minor; i++)
764
                        dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
765
                blk_size[dev->major] = dev->sizes;
766
        }
767
}
768
 
769
void device_setup(void)
770
{
771
        extern void console_map_init(void);
772
        extern void cpqarray_init(void);
773
        struct gendisk *p;
774
        int nr=0;
775
 
776
        chr_dev_init();
777
        blk_dev_init();
778
        sti();
779
#ifdef CONFIG_BLK_DEV_DAC960
780
        DAC960_Initialize();
781
#endif
782
#ifdef CONFIG_SCSI
783
        scsi_dev_init();
784
#endif
785
#ifdef CONFIG_BLK_CPQ_DA
786
        cpqarray_init();
787
#endif
788
#ifdef CONFIG_INET
789
        net_dev_init();
790
#endif
791
#ifdef CONFIG_CONSOLE
792
        console_map_init();
793
#endif
794
 
795
        for (p = gendisk_head ; p ; p=p->next) {
796
                setup_dev(p);
797
                nr += p->nr_real;
798
        }
799
#ifdef CONFIG_BLK_DEV_RAM
800
#ifdef CONFIG_BLK_DEV_INITRD
801
        if (initrd_start && mount_initrd) initrd_load();
802
        else
803
#endif
804
        rd_load();
805
#endif
806
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.