Annotation of Gnu-Mach/linux/dev/drivers/block/genhd.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.