root/kernel/blk_drv/genhd.c

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

DEFINITIONS

This source file includes following definitions.
  1. extended_partition
  2. check_partition
  3. resetup_one_dev
  4. setup_dev
  5. sys_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/config.h>
  14 #include <linux/fs.h>
  15 #include <linux/genhd.h>
  16 #include <linux/kernel.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 /*
  26  * Create devices for each logical partition in an extended partition.
  27  * The logical partitions form a linked list, with each entry being
  28  * a partition table with two entries.  The first entry
  29  * is the real data partition (with a start relative to the partition
  30  * table start).  The second is a pointer to the next logical partition
  31  * (with a start relative to the entire extended partition).
  32  * We do not create a Linux partition for the partition tables, but
  33  * only for the actual data partitions.
  34  */
  35 
  36 static void extended_partition(struct gendisk *hd, int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  37 {
  38         struct buffer_head *bh;
  39         struct partition *p;
  40         unsigned long first_sector, this_sector;
  41         int mask = (1 << hd->minor_shift) - 1;
  42 
  43         first_sector = hd->part[MINOR(dev)].start_sect;
  44         this_sector = first_sector;
  45 
  46         while (1) {
  47                 if ((current_minor & mask) >= (4 + hd->max_p))
  48                         return;
  49                 if (!(bh = bread(dev,0,1024))) {
  50                         printk("Unable to read partition table of device %04x\n",dev);
  51                         return;
  52                 }
  53           /*
  54            * This block is from a device that we're about to stomp on.
  55            * So make sure nobody thinks this block is usable.
  56            */
  57                 bh->b_dirt=0;
  58                 bh->b_uptodate=0;
  59                 if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
  60                         p = 0x1BE + (void *)bh->b_data;
  61                 /*
  62                  * Process the first entry, which should be the real
  63                  * data partition.
  64                  */
  65                         if (p->sys_ind == EXTENDED_PARTITION ||
  66                             !(hd->part[current_minor].nr_sects = p->nr_sects))
  67                                 goto done;  /* shouldn't happen */
  68                         hd->part[current_minor].start_sect = this_sector + p->start_sect;
  69                         printk("  Logical part %d start %d size %d end %d\n\r", 
  70                                mask & current_minor, hd->part[current_minor].start_sect, 
  71                                hd->part[current_minor].nr_sects,
  72                                hd->part[current_minor].start_sect + 
  73                                hd->part[current_minor].nr_sects - 1);
  74                         current_minor++;
  75                         p++;
  76                 /*
  77                  * Process the second entry, which should be a link
  78                  * to the next logical partition.  Create a minor
  79                  * for this just long enough to get the next partition
  80                  * table.  The minor will be reused for the real
  81                  * data partition.
  82                  */
  83                         if (p->sys_ind != EXTENDED_PARTITION ||
  84                             !(hd->part[current_minor].nr_sects = p->nr_sects))
  85                                 goto done;  /* no more logicals in this partition */
  86                         hd->part[current_minor].start_sect = first_sector + p->start_sect;
  87                         this_sector = first_sector + p->start_sect;
  88                         dev = ((hd->major) << 8) | current_minor;
  89                         brelse(bh);
  90                 } else
  91                         goto done;
  92         }
  93 done:
  94         brelse(bh);
  95 }
  96 
  97 static void check_partition(struct gendisk *hd, unsigned int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  98 {
  99         int i, minor = current_minor;
 100         struct buffer_head *bh;
 101         struct partition *p;
 102         unsigned long first_sector;
 103         int mask = (1 << hd->minor_shift) - 1;
 104 
 105         first_sector = hd->part[MINOR(dev)].start_sect;
 106 
 107         if (!(bh = bread(dev,0,1024))) {
 108                 printk("Unable to read partition table of device %04x\n",dev);
 109                 return;
 110         }
 111         printk("%s%c :\n\r", hd->major_name, 'a'+(minor >> hd->minor_shift));
 112         current_minor += 4;  /* first "extra" minor */
 113         if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
 114                 p = 0x1BE + (void *)bh->b_data;
 115                 for (i=1 ; i<=4 ; minor++,i++,p++) {
 116                         if (!(hd->part[minor].nr_sects = p->nr_sects))
 117                                 continue;
 118                         hd->part[minor].start_sect = first_sector + p->start_sect;
 119                         printk(" part %d start %d size %d end %d \n\r", i, 
 120                                hd->part[minor].start_sect, hd->part[minor].nr_sects, 
 121                                hd->part[minor].start_sect + hd->part[minor].nr_sects - 1);
 122                         if ((current_minor & 0x3f) >= 60)
 123                                 continue;
 124                         if (p->sys_ind == EXTENDED_PARTITION) {
 125                                 extended_partition(hd, (hd->major << 8) | minor);
 126                         }
 127                 }
 128                 /*
 129                  * check for Disk Manager partition table
 130                  */
 131                 if (*(unsigned short *) (bh->b_data+0xfc) == 0x55AA) {
 132                         p = 0x1BE + (void *)bh->b_data;
 133                         for (i = 4 ; i < 16 ; i++, current_minor++) {
 134                                 p--;
 135                                 if ((current_minor & mask) >= mask-2)
 136                                         break;
 137                                 if (!(p->start_sect && p->nr_sects))
 138                                         continue;
 139                                 hd->part[current_minor].start_sect = p->start_sect;
 140                                 hd->part[current_minor].nr_sects = p->nr_sects;
 141                                 printk(" DM part %d start %d size %d end %d\n\r",
 142                                        current_minor & mask,
 143                                        hd->part[current_minor].start_sect, 
 144                                        hd->part[current_minor].nr_sects,
 145                                        hd->part[current_minor].start_sect + 
 146                                        hd->part[current_minor].nr_sects - 1);
 147                         }
 148                 }
 149         } else
 150                 printk("Bad partition table on dev %04x\n",dev);
 151         brelse(bh);
 152 }
 153 
 154 /* This function is used to re-read partition tables for removable disks.
 155    Much of the cleanup from the old partition tables should have already been
 156    done */
 157 
 158 /* This function will re-read the partition tables for a given device,
 159 and set things back up again.  There are some important caveats,
 160 however.  You must ensure that no one is using the device, and no one
 161 can start using the device while this function is being executed. */
 162 
 163 void resetup_one_dev(struct gendisk *dev, int drive)
     /* [previous][next][first][last][top][bottom][index][help] */
 164 {
 165         int i;
 166         int start = drive<<dev->minor_shift;
 167         int j = start + dev->max_p;
 168         int major = dev->major << 8;
 169 
 170         current_minor = 1+(drive<<dev->minor_shift);
 171         check_partition(dev, major+(drive<<dev->minor_shift));
 172 
 173         for (i=start ; i < j ; i++)
 174                 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
 175 }
 176 
 177 static void setup_dev(struct gendisk *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 178 {
 179         int i;
 180         int j = dev->max_nr * dev->max_p;
 181         int major = dev->major << 8;
 182         int drive;
 183         
 184 
 185         for (i = 0 ; i < j; i++)  {
 186                 dev->part[i].start_sect = 0;
 187                 dev->part[i].nr_sects = 0;
 188         }
 189         dev->init();    
 190         for (drive=0 ; drive<dev->nr_real ; drive++) {
 191                 current_minor = 1+(drive<<dev->minor_shift);
 192                 check_partition(dev, major+(drive<<dev->minor_shift));
 193         }
 194         for (i=0 ; i < j ; i++)
 195                 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
 196         blk_size[dev->major] = dev->sizes;
 197 }
 198         
 199 /* This may be used only once, enforced by 'static int callable' */
 200 int sys_setup(void * BIOS)
     /* [previous][next][first][last][top][bottom][index][help] */
 201 {
 202         static int callable = 1;
 203         struct gendisk *p;
 204         int nr=0;
 205 
 206         if (!callable)
 207                 return -1;
 208         callable = 0;
 209 
 210         for (p = gendisk_head ; p ; p=p->next) {
 211                 setup_dev(p);
 212                 nr += p->nr_real;
 213         }
 214                 
 215         if (nr)
 216                 printk("Partition table%s ok.\n\r",(nr>1)?"s":"");
 217 
 218         if (ramdisk_size)
 219                 rd_load();
 220         mount_root();
 221         return (0);
 222 }

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