荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: georgehill (人生不定式), 信区: Linux
标  题: 终于搞定IBM45G(ide)硬盘!!(转寄)
发信站: BBS 荔园晨风站 (Thu Sep 14 22:56:12 2000), 站内信件

【 以下文字转载自 georgehill 的信箱 】
【 原文由 georgehill.bbs@smth.org 所发表 】
发信人: hzl (孤独的消防员), 信区: Linux
标  题: 终于搞定IBM45G(ide)硬盘!!(转寄)
发信站: BBS 水木清华站 (Thu Sep 14 14:11:57 2000) WWW-POST

在RH6.1(kernel2.2.12-20)下,无法正确安装IBM DTLA-307045硬盘。
这是该版本及以前版本的BUG所至,大于34G的硬盘将无法正确安装。
通过直接修改少许内核源代码即可解决。下面是PATCH代码
(原文见http://www.uwsg.indiana.edu/hypermail/linux/kernel/9910.2/0636.html
 我是根据代码手工进行修改的,重编内核后,一切搞定)
diff -u --recursive --new-file ../linux-2.2.12/drivers/block/genhd.c
./linux/drivers/block/genhd.c
--- ../linux-2.2.12/drivers/block/genhd.c Wed Aug 25 01:08:35 1999
+++ ./linux/drivers/block/genhd.c Wed Oct 20 21:35:40 1999
@@ -784,8 +784,11 @@
label = (struct sun_disklabel *) bh->b_data;
p = label->partitions;
if (be16_to_cpu(label->magic) != SUN_LABEL_MAGIC) {
+#if 0
+ /* There is no error here - it is just not a sunlabel. */
printk("Dev %s Sun disklabel: bad magic %04x\n",
kdevname(dev), be16_to_cpu(label->magic));
+#endif
brelse(bh);
return 0;
}
@@ -856,8 +859,11 @@
p = &label->partitions[0];
magic = label->magic_mushroom;
if(be32_to_cpu(magic) != SGI_LABEL_MAGIC) {
+#if 0
+ /* There is no error here - it is just not an sgilabel. */
printk("Dev %s SGI disklabel: bad magic %08x\n",
kdevname(dev), magic);
+#endif
brelse(bh);
return 0;
}
diff -u --recursive --new-file ../linux-2.2.12/drivers/block/ide-disk.c
./linux/drivers/block/ide-disk.c
--- ../linux-2.2.12/drivers/block/ide-disk.c Wed Mar 24 20:07:58 1999
+++ ./linux/drivers/block/ide-disk.c Wed Oct 20 22:07:30 1999
@@ -88,30 +88,35 @@
*/
static int lba_capacity_is_ok (struct hd_driveid *id)
{
- unsigned long lba_sects = id->lba_capacity;
- unsigned long chs_sects = id->cyls * id->heads * id->sectors;
- unsigned long _10_percent = chs_sects / 10;
+ unsigned long lba_sects, chs_sects, head, tail;

/*
- * very large drives (8GB+) may lie about the number of cylinders
- * This is a split test for drives 8 Gig and Bigger only.
+ * The ATA spec tells large drives to return
+ * C/H/S = 16383/16/63 independent of their size.
+ * Some drives can be jumpered to use 15 heads instead of 16.
*/
- if ((id->lba_capacity >= 16514064) && (id->cyls == 0x3fff) &&
- (id->heads == 16) && (id->sectors == 63)) {
- id->cyls = lba_sects / (16 * 63); /* correct cyls */
- return 1; /* lba_capacity is our only option */
- }
+ if (id->cyls == 16383 && id->sectors == 63 &&
+ (id->heads == 15 || id->heads == 16) &&
+ id->lba_capacity >= 16383*63*id->heads)
+ return 1;
+
+ lba_sects = id->lba_capacity;
+ chs_sects = id->cyls * id->heads * id->sectors;
+
/* perform a rough sanity check on lba_sects: within 10% is "okay" */
- if ((lba_sects - chs_sects) < _10_percent) {
- return 1; /* lba_capacity is good */
- }
+ if ((lba_sects - chs_sects) < chs_sects/10)
+ return 1;
+
/* some drives have the word order reversed */
- lba_sects = (lba_sects << 16) | (lba_sects >> 16);
- if ((lba_sects - chs_sects) < _10_percent) {
- id->lba_capacity = lba_sects; /* fix it */
+ head = ((lba_sects >> 16) & 0xffff);
+ tail = (lba_sects & 0xffff);
+ lba_sects = (head | (tail << 16));
+ if ((lba_sects - chs_sects) < chs_sects/10) {
+ id->lba_capacity = lba_sects;
return 1; /* lba_capacity is (now) good */
}
- return 0; /* lba_capacity value is bad */
+
+ return 0; /* lba_capacity value may be bad */
}

/*
@@ -446,7 +451,6 @@
/* Determine capacity, and use LBA if the drive properly supports it */
if (id != NULL && (id->capability & 2) && lba_capacity_is_ok(id)) {
if (id->lba_capacity >= capacity) {
- drive->cyl = id->lba_capacity / (drive->head * drive->sect);
capacity = id->lba_capacity;
drive->select.b.lba = 1;
}
@@ -721,9 +725,9 @@
if ((id->lba_capacity > 16514064) || (id->cyls == 0x3fff)) {
id->cyls = ((int)(id->lba_capacity/(id->heads * id->sectors)));
}
- drive->cyl = id->cur_cyls = id->cyls;
- drive->head = id->cur_heads = id->heads;
- drive->sect = id->cur_sectors = id->sectors;
+ drive->cyl = id->cyls;
+ drive->head = id->heads;
+ drive->sect = id->sectors;
}

/* calculate drive capacity, and select LBA if possible */
@@ -733,21 +737,19 @@
* if possible, give fdisk access to more of the drive,
* by correcting bios_cyls:
*/
- if ((capacity >= (drive->bios_cyl * drive->bios_sect * drive->bios_head))
&&
- (!drive->forced_geom) && drive->bios_sect && drive->bios_head) {
- drive->bios_cyl = (capacity / drive->bios_sect) / drive->bios_head;
-#ifdef DEBUG
- printk("Fixing Geometry :: CHS=%d/%d/%d to CHS=%d/%d/%d\n",
- drive->id->cur_cyls,
- drive->id->cur_heads,
- drive->id->cur_sectors,
- drive->bios_cyl,
- drive->bios_head,
- drive->bios_sect);
-#endif
- drive->id->cur_cyls = drive->bios_cyl;
- drive->id->cur_heads = drive->bios_head;
- drive->id->cur_sectors = drive->bios_sect;
+ if (!drive->forced_geom &&
+ capacity > drive->bios_cyl * drive->bios_sect * drive->bios_head) {
+ unsigned long cylsize;
+ cylsize = drive->bios_sect * drive->bios_head;
+ if (cylsize == 0 || capacity/cylsize > 65535) {
+ drive->bios_sect = 63;
+ drive->bios_head = 255;
+ cylsize = 63*255;
+ }
+ if (capacity/cylsize > 65535)
+ drive->bios_cyl = 65535;
+ else
+ drive->bios_cyl = capacity/cylsize;
}

#if 0 /* done instead for entire identify block in arch/ide.h stuff */
@@ -770,19 +772,6 @@
}
}
printk("\n");
-
- if (drive->select.b.lba) {
- if (*(int *)&id->cur_capacity0 < id->lba_capacity) {
-#ifdef DEBUG
- printk(" CurSects=%d, LBASects=%d, ",
- *(int *)&id->cur_capacity0, id->lba_capacity);
-#endif
- *(int *)&id->cur_capacity0 = id->lba_capacity;
-#ifdef DEBUG
- printk( "Fixed CurSects=%d\n", *(int *)&id->cur_capacity0);
-#endif
- }
- }

drive->mult_count = 0;
if (id->max_multsect) {
diff -u --recursive --new-file ../linux-2.2.12/drivers/block/ide-proc.c
./linux/drivers/block/ide-proc.c
--- ../linux-2.2.12/drivers/block/ide-proc.c Wed May 6 23:42:53 1998
+++ ./linux/drivers/block/ide-proc.c Thu Oct 14 18:18:31 1999
@@ -516,8 +516,10 @@
char *out = page;
int len;

- out += sprintf(out,"physical %hi/%hi/%hi\n", drive->cyl, drive->head,
drive->sect);
- out += sprintf(out,"logical %hi/%hi/%hi\n", drive->bios_cyl,
drive->bios_head, drive->bios_sect);
+ out += sprintf(out,"physical %d/%d/%d\n",
+ drive->cyl, drive->head, drive->sect);
+ out += sprintf(out,"logical %d/%d/%d\n",
+ drive->bios_cyl, drive->bios_head, drive->bios_sect);
len = out - page;
PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
}
diff -u --recursive --new-file ../linux-2.2.12/drivers/net/8390.c
./linux/drivers/net/8390.c
--- ../linux-2.2.12/drivers/net/8390.c Thu May 13 00:23:32 1999
+++ ./linux/drivers/net/8390.c Thu Oct 14 14:49:27 1999
@@ -1089,7 +1089,9 @@
int start_page)
{
int e8390_base = dev->base_addr;
+#ifdef EI_LOCAL_NEEDED_FOR_EI_SHIFT
struct ei_device *ei_local = (struct ei_device *) dev->priv;
+#endif

outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD);

diff -u --recursive --new-file ../linux-2.2.12/drivers/net/8390.h
./linux/drivers/net/8390.h
--- ../linux-2.2.12/drivers/net/8390.h Mon Dec 28 20:04:21 1998
+++ ./linux/drivers/net/8390.h Wed Oct 20 22:19:04 1999
@@ -215,6 +215,7 @@
#if defined(CONFIG_MAC) || defined(CONFIG_AMIGA_PCMCIA) || \
defined(CONFIG_ARIADNE2) || defined(CONFIG_ARIADNE2_MODULE)
#define EI_SHIFT(x) (ei_local->reg_offset[x])
+#define EI_LOCAL_NEEDED_FOR_EI_SHIFT
#else
#define EI_SHIFT(x) (x)
#endif
diff -u --recursive --new-file ../linux-2.2.12/fs/devices.c ./linux/fs/devices
.c
--- ../linux-2.2.12/fs/devices.c Wed Dec 23 20:39:49 1998
+++ ./linux/fs/devices.c Fri Feb 19 23:46:56 1999
@@ -228,7 +228,7 @@
*/
int blkdev_open(struct inode * inode, struct file * filp)
{
- int ret = -ENODEV;
+ int ret = -ENXIO;
filp->f_op = get_blkfops(MAJOR(inode->i_rdev));
if (filp->f_op != NULL){
ret = 0;
diff -u --recursive --new-file ../linux-2.2.12/fs/namei.c ./linux/fs/namei.c
--- ../linux-2.2.12/fs/namei.c Thu May 13 00:23:36 1999
+++ ./linux/fs/namei.c Sun Oct 3 18:48:00 1999
@@ -555,6 +555,8 @@
* on removing (or moving) the same entry: the
* parent lock will serialize them, but the
* other process will be too late..
+ *
+ * Note that check_parent will fail for mount points.
*/
#define check_parent(dir, dentry) \
((dir) == (dentry)->d_parent && !list_empty(&dentry->d_hash))
@@ -974,6 +976,10 @@

error = -ENOENT;
if (!dentry->d_inode)
+ goto exit_dput;
+
+ error = -EBUSY;
+ if (dentry->d_covers != dentry)
goto exit_dput;

dir = dget(dentry->d_parent);
diff -u --recursive --new-file ../linux-2.2.12/include/linux/genhd.h
./linux/include/linux/genhd.h
--- ../linux-2.2.12/include/linux/genhd.h Wed Aug 25 01:08:49 1999
+++ ./linux/include/linux/genhd.h Wed Oct 20 22:18:01 1999
@@ -42,7 +42,7 @@
#endif

#define DM6_PARTITION 0x54 /* has DDO: use xlated geom & offset */
-#define EZD_PARTITION 0x55 /* EZ-DRIVE: same as DM6 (we think) */
+#define EZD_PARTITION 0x55 /* EZ-DRIVE: remap sector 1 to 0 */
#define DM6_AUX1PARTITION 0x51 /* no DDO: use xlated geom */
#define DM6_AUX3PARTITION 0x53 /* no DDO: use xlated geom */

diff -u --recursive --new-file ../linux-2.2.12/ipc/sem.c ./linux/ipc/sem.c
--- ../linux-2.2.12/ipc/sem.c Sun Jan 10 04:16:44 1999
+++ ./linux/ipc/sem.c Thu Oct 14 15:10:49 1999
@@ -694,7 +694,7 @@
interruptible_sleep_on(&queue.sleeper);

/*
- * If queue.status == 1 we where woken up and
+ * If queue.status == 1 we were woken up and
* have to retry else we simply return.
* If an interrupt occurred we have to clean up the
* queue


--
※ 来源:·BBS 水木清华站 smth.org·[FROM: 202.115.192.9]
--
※ 转载:·BBS 荔园晨风站 bbs.szu.edu.cn·[FROM: 192.168.1.115]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店