⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 genhd.c.txt

📁 Linux块设备驱动分析与模拟实现
💻 TXT
字号:
  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)
 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                         return;
 51           /*
 52            * This block is from a device that we're about to stomp on.
 53            * So make sure nobody thinks this block is usable.
 54            */
 55                 bh->b_dirt=0;
 56                 bh->b_uptodate=0;
 57                 if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
 58                         p = (struct partition *) (0x1BE + bh->b_data);
 59                 /*
 60                  * Process the first entry, which should be the real
 61                  * data partition.
 62                  */
 63                         if (p->sys_ind == EXTENDED_PARTITION ||
 64                             !(hd->part[current_minor].nr_sects = p->nr_sects))
 65                                 goto done;  /* shouldn't happen */
 66                         hd->part[current_minor].start_sect = this_sector + p->start_sect;
 67                         printk(" %s%c%d", hd->major_name,
 68                                 'a'+(current_minor >> hd->minor_shift),
 69                                 mask & current_minor);
 70                         current_minor++;
 71                         p++;
 72                 /*
 73                  * Process the second entry, which should be a link
 74                  * to the next logical partition.  Create a minor
 75                  * for this just long enough to get the next partition
 76                  * table.  The minor will be reused for the real
 77                  * data partition.
 78                  */
 79                         if (p->sys_ind != EXTENDED_PARTITION ||
 80                             !(hd->part[current_minor].nr_sects = p->nr_sects))
 81                                 goto done;  /* no more logicals in this partition */
 82                         hd->part[current_minor].start_sect = first_sector + p->start_sect;
 83                         this_sector = first_sector + p->start_sect;
 84                         dev = ((hd->major) << 8) | current_minor;
 85                         brelse(bh);
 86                 } else
 87                         goto done;
 88         }
 89 done:
 90         brelse(bh);
 91 }
 92 
 93 static void check_partition(struct gendisk *hd, unsigned int dev)
 94 {
 95         static int first_time = 1;
 96         int i, minor = current_minor;
 97         struct buffer_head *bh;
 98         struct partition *p;
 99         unsigned long first_sector;
100         int mask = (1 << hd->minor_shift) - 1;
101 
102         if (first_time)
103                 printk("Partition check:\n");
104         first_time = 0;
105         first_sector = hd->part[MINOR(dev)].start_sect;
106         if (!(bh = bread(dev,0,1024))) {
107                 printk("  unable to read partition table of device %04x\n",dev);
108                 return;
109         }
110         printk("  %s%c:", hd->major_name, 'a'+(minor >> hd->minor_shift));
111         current_minor += 4;  /* first "extra" minor */
112         if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
113                 p = (struct partition *) (0x1BE + bh->b_data);
114                 for (i=1 ; i<=4 ; minor++,i++,p++) {
115                         if (!(hd->part[minor].nr_sects = p->nr_sects))
116                                 continue;
117                         hd->part[minor].start_sect = first_sector + p->start_sect;
118                         printk(" %s%c%d", hd->major_name,'a'+(minor >> hd->minor_shift), i);
119                         if ((current_minor & 0x3f) >= 60)
120                                 continue;
121                         if (p->sys_ind == EXTENDED_PARTITION) {
122                                 printk(" <");
123                                 extended_partition(hd, (hd->major << 8) | minor);
124                                 printk(" >");
125                         }
126                 }
127                 /*
128                  * check for Disk Manager partition table
129                  */
130                 if (*(unsigned short *) (bh->b_data+0xfc) == 0x55AA) {
131                         p = (struct partition *) (0x1BE + bh->b_data);
132                         for (i = 4 ; i < 16 ; i++, current_minor++) {
133                                 p--;
134                                 if ((current_minor & mask) >= mask-2)
135                                         break;
136                                 if (!(p->start_sect && p->nr_sects))
137                                         continue;
138                                 hd->part[current_minor].start_sect = p->start_sect;
139                                 hd->part[current_minor].nr_sects = p->nr_sects;
140                                 printk(" %s%c%d", hd->major_name,
141                                         'a'+(current_minor >> hd->minor_shift),
142                                         current_minor & mask);
143                         }
144                 }
145         } else
146                 printk(" bad partition table");
147         printk("\n");
148         brelse(bh);
149 }
150 
151 /* This function is used to re-read partition tables for removable disks.
152    Much of the cleanup from the old partition tables should have already been
153    done */
154 
155 /* This function will re-read the partition tables for a given device,
156 and set things back up again.  There are some important caveats,
157 however.  You must ensure that no one is using the device, and no one
158 can start using the device while this function is being executed. */
159 
160 void resetup_one_dev(struct gendisk *dev, int drive)
161 {
162         int i;
163         int start = drive<<dev->minor_shift;
164         int j = start + dev->max_p;
165         int major = dev->major << 8;
166 
167         current_minor = 1+(drive<<dev->minor_shift);
168         check_partition(dev, major+(drive<<dev->minor_shift));
169 
170         for (i=start ; i < j ; i++)
171                 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
172 }
173 
174 static void setup_dev(struct gendisk *dev)
175 {
176         int i;
177         int j = dev->max_nr * dev->max_p;
178         int major = dev->major << 8;
179         int drive;
180         
181 
182         for (i = 0 ; i < j; i++)  {
183                 dev->part[i].start_sect = 0;
184                 dev->part[i].nr_sects = 0;
185         }
186         dev->init();    
187         for (drive=0 ; drive<dev->nr_real ; drive++) {
188                 current_minor = 1+(drive<<dev->minor_shift);
189                 check_partition(dev, major+(drive<<dev->minor_shift));
190         }
191         for (i=0 ; i < j ; i++)
192                 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
193         blk_size[dev->major] = dev->sizes;
194 }
195         
196 /* This may be used only once, enforced by 'static int callable' */
197 asmlinkage int sys_setup(void * BIOS)
198 {
199         static int callable = 1;
200         struct gendisk *p;
201         int nr=0;
202 
203         if (!callable)
204                 return -1;
205         callable = 0;
206 
207         for (p = gendisk_head ; p ; p=p->next) {
208                 setup_dev(p);
209                 nr += p->nr_real;
210         }
211                 
212         if (ramdisk_size)
213                 rd_load();
214         mount_root();
215         return (0);
216 }
217 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -