root/drivers/block/genhd.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. minor_name
  2. add_partition
  3. extended_partition
  4. msdos_partition
  5. osf_partition
  6. check_partition
  7. resetup_one_dev
  8. setup_dev
  9. device_setup

   1 /*
   2  *  Code extracted from
   3  *  linux/kernel/hd.c
   4  *
   5  *  Copyright (C) 1991, 1992  Linus Torvalds
   6  */
   7 
   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
  11  */
  12 
  13 #include <linux/fs.h>
  14 #include <linux/genhd.h>
  15 #include <linux/kernel.h>
  16 #include <linux/major.h>
  17 
  18 struct gendisk *gendisk_head = NULL;
  19 
  20 static int current_minor = 0;
  21 extern int *blk_size[];
  22 extern void rd_load(void);
  23 extern int ramdisk_size;
  24 
  25 static char minor_name (struct gendisk *hd, int minor)
     /* [previous][next][first][last][top][bottom][index][help] */
  26 {
  27         char base_name = (hd->major == IDE1_MAJOR) ? 'c' : 'a';
  28         return base_name + (minor >> hd->minor_shift);
  29 }
  30 
  31 static void add_partition (struct gendisk *hd, int minor, int start, int size)
     /* [previous][next][first][last][top][bottom][index][help] */
  32 {
  33         hd->part[minor].start_sect = start;
  34         hd->part[minor].nr_sects   = size;
  35         printk(" %s%c%d", hd->major_name, minor_name(hd, minor),
  36                 minor & ((1 << hd->minor_shift) - 1));
  37 }
  38 
  39 #ifdef CONFIG_MSDOS_PARTITION
  40 /*
  41  * Create devices for each logical partition in an extended partition.
  42  * The logical partitions form a linked list, with each entry being
  43  * a partition table with two entries.  The first entry
  44  * is the real data partition (with a start relative to the partition
  45  * table start).  The second is a pointer to the next logical partition
  46  * (with a start relative to the entire extended partition).
  47  * We do not create a Linux partition for the partition tables, but
  48  * only for the actual data partitions.
  49  */
  50 
  51 static void extended_partition(struct gendisk *hd, int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  52 {
  53         struct buffer_head *bh;
  54         struct partition *p;
  55         unsigned long first_sector, this_sector;
  56         int mask = (1 << hd->minor_shift) - 1;
  57 
  58         first_sector = hd->part[MINOR(dev)].start_sect;
  59         this_sector = first_sector;
  60 
  61         while (1) {
  62                 if ((current_minor & mask) >= (4 + hd->max_p))
  63                         return;
  64                 if (!(bh = bread(dev,0,1024)))
  65                         return;
  66           /*
  67            * This block is from a device that we're about to stomp on.
  68            * So make sure nobody thinks this block is usable.
  69            */
  70                 bh->b_dirt = 0;
  71                 bh->b_uptodate = 0;
  72                 bh->b_req = 0;
  73                 if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
  74                         p = (struct partition *) (0x1BE + bh->b_data);
  75                 /*
  76                  * Process the first entry, which should be the real
  77                  * data partition.
  78                  */
  79                         if (p->sys_ind == EXTENDED_PARTITION || !p->nr_sects)
  80                                 goto done;  /* shouldn't happen */
  81                         add_partition(hd, current_minor, this_sector+p->start_sect, p->nr_sects);
  82                         current_minor++;
  83                         p++;
  84                 /*
  85                  * Process the second entry, which should be a link
  86                  * to the next logical partition.  Create a minor
  87                  * for this just long enough to get the next partition
  88                  * table.  The minor will be reused for the real
  89                  * data partition.
  90                  */
  91                         if (p->sys_ind != EXTENDED_PARTITION ||
  92                             !(hd->part[current_minor].nr_sects = p->nr_sects))
  93                                 goto done;  /* no more logicals in this partition */
  94                         hd->part[current_minor].start_sect = first_sector + p->start_sect;
  95                         hd->sizes[current_minor] = p->nr_sects >> (BLOCK_SIZE_BITS - 9);
  96                         this_sector = first_sector + p->start_sect;
  97                         dev = ((hd->major) << 8) | current_minor;
  98                         brelse(bh);
  99                 } else
 100                         goto done;
 101         }
 102 done:
 103         brelse(bh);
 104 }
 105 
 106 static int msdos_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
     /* [previous][next][first][last][top][bottom][index][help] */
 107 {
 108         int i, minor = current_minor;
 109         struct buffer_head *bh;
 110         struct partition *p;
 111         int mask = (1 << hd->minor_shift) - 1;
 112 
 113         if (!(bh = bread(dev,0,1024))) {
 114                 printk("unable to read partition table\n");
 115                 return -1;
 116         }
 117         if (*(unsigned short *) (bh->b_data+510) != 0xAA55) {
 118                 brelse(bh);
 119                 return 0;
 120         }
 121         current_minor += 4;  /* first "extra" minor (for extended partitions) */
 122         p = (struct partition *) (0x1BE + bh->b_data);
 123         for (i=1 ; i<=4 ; minor++,i++,p++) {
 124                 if (!p->nr_sects)
 125                         continue;
 126                 add_partition(hd, minor, first_sector+p->start_sect, p->nr_sects);
 127                 if ((current_minor & 0x3f) >= 60)
 128                         continue;
 129                 if (p->sys_ind == EXTENDED_PARTITION) {
 130                         printk(" <");
 131                         extended_partition(hd, (hd->major << 8) | minor);
 132                         printk(" >");
 133                 }
 134         }
 135         /*
 136          * check for Disk Manager partition table
 137          */
 138         if (*(unsigned short *) (bh->b_data+0xfc) == 0x55AA) {
 139                 p = (struct partition *) (0x1BE + bh->b_data);
 140                 for (i = 4 ; i < 16 ; i++, current_minor++) {
 141                         p--;
 142                         if ((current_minor & mask) >= mask-2)
 143                                 break;
 144                         if (!(p->start_sect && p->nr_sects))
 145                                 continue;
 146                         add_partition(hd, current_minor, p->start_sect, p->nr_sects);
 147                 }
 148         }
 149         printk("\n");
 150         brelse(bh);
 151         return 1;
 152 }
 153 
 154 #endif /* CONFIG_MSDOS_PARTITION */
 155 
 156 #ifdef CONFIG_OSF_PARTITION
 157 
 158 static int osf_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
     /* [previous][next][first][last][top][bottom][index][help] */
 159 {
 160         int i;
 161         struct buffer_head *bh;
 162         struct disklabel {
 163                 u32 d_magic;
 164                 u16 d_type,d_subtype;
 165                 u8 d_typename[16];
 166                 u8 d_packname[16];
 167                 u32 d_secsize;
 168                 u32 d_nsectors;
 169                 u32 d_ntracks;
 170                 u32 d_ncylinders;
 171                 u32 d_secpercyl;
 172                 u32 d_secprtunit;
 173                 u16 d_sparespertrack;
 174                 u16 d_sparespercyl;
 175                 u32 d_acylinders;
 176                 u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
 177                 u32 d_headswitch, d_trkseek, d_flags;
 178                 u32 d_drivedata[5];
 179                 u32 d_spare[5];
 180                 u32 d_magic2;
 181                 u16 d_checksum;
 182                 u16 d_npartitions;
 183                 u32 d_bbsize, d_sbsize;
 184                 struct d_partition {
 185                         u32 p_size;
 186                         u32 p_offset;
 187                         u32 p_fsize;
 188                         u8  p_fstype;
 189                         u8  p_frag;
 190                         u16 p_cpg;
 191                 } d_partitions[8];
 192         } * label;
 193         struct d_partition * partition;
 194 #define DISKLABELMAGIC (0x82564557UL)
 195 
 196         if (!(bh = bread(dev,0,1024))) {
 197                 printk("unable to read partition table\n");
 198                 return -1;
 199         }
 200         label = (struct disklabel *) (bh->b_data+64);
 201         partition = label->d_partitions;
 202         if (label->d_magic != DISKLABELMAGIC) {
 203                 printk("magic: %08x\n", label->d_magic);
 204                 brelse(bh);
 205                 return 0;
 206         }
 207         if (label->d_magic2 != DISKLABELMAGIC) {
 208                 printk("magic2: %08x\n", label->d_magic2);
 209                 brelse(bh);
 210                 return 0;
 211         }
 212         for (i = 0 ; i < label->d_npartitions; i++, partition++) {
 213                 if (partition->p_size)
 214                         add_partition(hd, current_minor,
 215                                 first_sector+partition->p_offset,
 216                                 partition->p_size);
 217                 current_minor++;
 218         }
 219         printk("\n");
 220         brelse(bh);
 221         return 1;
 222 }
 223 
 224 #endif /* CONFIG_OSF_PARTITION */
 225 
 226 static void check_partition(struct gendisk *hd, unsigned int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 227 {
 228         static int first_time = 1;
 229         unsigned long first_sector;
 230 
 231         if (first_time)
 232                 printk("Partition check:\n");
 233         first_time = 0;
 234         first_sector = hd->part[MINOR(dev)].start_sect;
 235 
 236         /*
 237          * This is a kludge to allow the partition check to be
 238          * skipped for specific drives (ie. IDE cd-rom drives)
 239          */
 240         if ((int)first_sector == -1) {
 241                 hd->part[MINOR(dev)].start_sect = 0;
 242                 return;
 243         }
 244 
 245         printk("  %s%c:", hd->major_name, minor_name(hd, MINOR(dev)));
 246 #ifdef CONFIG_MSDOS_PARTITION
 247         if (msdos_partition(hd, dev, first_sector))
 248                 return;
 249 #endif
 250 #ifdef CONFIG_OSF_PARTITION
 251         if (osf_partition(hd, dev, first_sector))
 252                 return;
 253 #endif
 254         printk("unknown partition table\n");
 255 }
 256 
 257 /* This function is used to re-read partition tables for removable disks.
 258    Much of the cleanup from the old partition tables should have already been
 259    done */
 260 
 261 /* This function will re-read the partition tables for a given device,
 262 and set things back up again.  There are some important caveats,
 263 however.  You must ensure that no one is using the device, and no one
 264 can start using the device while this function is being executed. */
 265 
 266 void resetup_one_dev(struct gendisk *dev, int drive)
     /* [previous][next][first][last][top][bottom][index][help] */
 267 {
 268         int i;
 269         int start = drive<<dev->minor_shift;
 270         int j = start + dev->max_p;
 271         int major = dev->major << 8;
 272 
 273         current_minor = 1+(drive<<dev->minor_shift);
 274         check_partition(dev, major+(drive<<dev->minor_shift));
 275 
 276         for (i=start ; i < j ; i++)
 277                 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
 278 }
 279 
 280 static void setup_dev(struct gendisk *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 281 {
 282         int i;
 283         int j = dev->max_nr * dev->max_p;
 284         int major = dev->major << 8;
 285         int drive;
 286         
 287 
 288         for (i = 0 ; i < j; i++)  {
 289                 dev->part[i].start_sect = 0;
 290                 dev->part[i].nr_sects = 0;
 291         }
 292         dev->init();    
 293         for (drive=0 ; drive<dev->nr_real ; drive++) {
 294                 current_minor = 1+(drive<<dev->minor_shift);
 295                 check_partition(dev, major+(drive<<dev->minor_shift));
 296         }
 297         for (i=0 ; i < j ; i++)
 298                 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
 299         blk_size[dev->major] = dev->sizes;
 300 }
 301         
 302 void device_setup(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 303 {
 304         struct gendisk *p;
 305         int nr=0;
 306 
 307         for (p = gendisk_head ; p ; p=p->next) {
 308                 setup_dev(p);
 309                 nr += p->nr_real;
 310         }
 311                 
 312         if (ramdisk_size)
 313                 rd_load();
 314 }

/* [previous][next][first][last][top][bottom][index][help] */