summaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/genhd.c141
-rw-r--r--drivers/block/ide.c40
-rw-r--r--drivers/block/ide.h2
-rw-r--r--drivers/block/loop.c2
-rw-r--r--drivers/block/md.c5
5 files changed, 164 insertions, 26 deletions
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index ad0e79b1b..0217dcb52 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -380,7 +380,7 @@ check_table:
&& (q->sector & 63) == 1
&& (q->end_sector & 63) == 63) {
unsigned int heads = q->end_head + 1;
- if (heads == 32 || heads == 64 || heads == 128) {
+ if (heads == 32 || heads == 64 || heads == 128 || heads == 255) {
(void) ide_xlate_1024(dev, heads, " [PTBL]");
break;
@@ -740,6 +740,141 @@ rdb_done:
}
#endif /* CONFIG_AMIGA_PARTITION */
+#ifdef CONFIG_ATARI_PARTITION
+#include <asm/atari_rootsec.h>
+
+/* ++guenther: this should be settable by the user ("make config")?.
+ */
+#define ICD_PARTS
+
+static int atari_partition (struct gendisk *hd, kdev_t dev,
+ unsigned long first_sector)
+{
+ int minor = current_minor, m_lim = current_minor + hd->max_p;
+ struct buffer_head *bh;
+ struct rootsector *rs;
+ struct partition_info *pi;
+ ulong extensect;
+#ifdef ICD_PARTS
+ int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */
+#endif
+
+ bh = bread (dev, 0, get_ptable_blocksize(dev));
+ if (!bh)
+ {
+ printk (" unable to read block 0\n");
+ return -1;
+ }
+
+ rs = (struct rootsector *) bh->b_data;
+ pi = &rs->part[0];
+ printk (" AHDI");
+ for (; pi < &rs->part[4] && minor < m_lim; minor++, pi++)
+ {
+ if (pi->flg & 1)
+ /* active partition */
+ {
+ if (memcmp (pi->id, "XGM", 3) == 0)
+ /* extension partition */
+ {
+ struct rootsector *xrs;
+ struct buffer_head *xbh;
+ ulong partsect;
+
+#ifdef ICD_PARTS
+ part_fmt = 1;
+#endif
+ printk(" XGM<");
+ partsect = extensect = pi->st;
+ while (1)
+ {
+ xbh = bread (dev, partsect / 2, 1024);
+ if (!xbh)
+ {
+ printk (" block %ld read failed\n", partsect);
+ brelse(bh);
+ return 0;
+ }
+ if (partsect & 1)
+ xrs = (struct rootsector *) &xbh->b_data[512];
+ else
+ xrs = (struct rootsector *) &xbh->b_data[0];
+
+ /* ++roman: sanity check: bit 0 of flg field must be set */
+ if (!(xrs->part[0].flg & 1)) {
+ printk( "\nFirst sub-partition in extended partition is not valid!\n" );
+ break;
+ }
+
+ add_partition(hd, minor, partsect + xrs->part[0].st,
+ xrs->part[0].siz);
+
+ if (!(xrs->part[1].flg & 1)) {
+ /* end of linked partition list */
+ brelse( xbh );
+ break;
+ }
+ if (memcmp( xrs->part[1].id, "XGM", 3 ) != 0) {
+ printk( "\nID of extended partition is not XGM!\n" );
+ brelse( xbh );
+ break;
+ }
+
+ partsect = xrs->part[1].st + extensect;
+ brelse (xbh);
+ minor++;
+ if (minor >= m_lim) {
+ printk( "\nMaximum number of partitions reached!\n" );
+ break;
+ }
+ }
+ printk(" >");
+ }
+ else
+ {
+ /* we don't care about other id's */
+ add_partition (hd, minor, pi->st, pi->siz);
+ }
+ }
+ }
+#ifdef ICD_PARTS
+ if ( part_fmt!=1 ) /* no extended partitions -> test ICD-format */
+ {
+ pi = &rs->icdpart[0];
+ /* sanity check: no ICD format if first partition invalid */
+ if (memcmp (pi->id, "GEM", 3) == 0 ||
+ memcmp (pi->id, "BGM", 3) == 0 ||
+ memcmp (pi->id, "LNX", 3) == 0 ||
+ memcmp (pi->id, "SWP", 3) == 0 ||
+ memcmp (pi->id, "RAW", 3) == 0 )
+ {
+ printk(" ICD<");
+ for (; pi < &rs->icdpart[8] && minor < m_lim; minor++, pi++)
+ {
+ /* accept only GEM,BGM,RAW,LNX,SWP partitions */
+ if (pi->flg & 1 &&
+ (memcmp (pi->id, "GEM", 3) == 0 ||
+ memcmp (pi->id, "BGM", 3) == 0 ||
+ memcmp (pi->id, "LNX", 3) == 0 ||
+ memcmp (pi->id, "SWP", 3) == 0 ||
+ memcmp (pi->id, "RAW", 3) == 0) )
+ {
+ part_fmt = 2;
+ add_partition (hd, minor, pi->st, pi->siz);
+ }
+ }
+ printk(" >");
+ }
+ }
+#endif
+ brelse (bh);
+
+ printk ("\n");
+
+ return 1;
+}
+#endif /* CONFIG_ATARI_PARTITION */
+
static void check_partition(struct gendisk *hd, kdev_t dev)
{
static int first_time = 1;
@@ -777,6 +912,10 @@ static void check_partition(struct gendisk *hd, kdev_t dev)
if(amiga_partition(hd, dev, first_sector))
return;
#endif
+#ifdef CONFIG_ATARI_PARTITION
+ if(atari_partition(hd, dev, first_sector))
+ return;
+#endif
#ifdef CONFIG_SGI_PARTITION
if(sgi_partition(hd, dev, first_sector))
return;
diff --git a/drivers/block/ide.c b/drivers/block/ide.c
index 89759dd32..1b293c539 100644
--- a/drivers/block/ide.c
+++ b/drivers/block/ide.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/ide.c Version 6.02 Mar 11, 1997
+ * linux/drivers/block/ide.c Version 6.03 June 4, 1997
*
* Copyright (C) 1994-1997 Linus Torvalds & authors (see below)
*/
@@ -280,6 +280,7 @@
* support HDIO_GETGEO for floppies
* Version 6.02 fix ide_ack_intr() call
* check partition table on floppies
+ * Version 6.03 handle bad status bit sequencing in ide_wait_stat()
*
* Some additional driver compile-time options are in ide.h
*
@@ -1044,27 +1045,24 @@ int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeou
byte stat;
unsigned long flags;
-test:
- udelay(1); /* spec allows drive 400ns to change "BUSY" */
- if (OK_STAT((stat = GET_STAT()), good, bad))
- return 0; /* fast exit for most frequent case */
- if (!(stat & BUSY_STAT)) {
- ide_error(drive, "status error", stat);
- return 1;
- }
-
- save_flags(flags);
- ide_sti();
- timeout += jiffies;
- do {
- if (!((stat = GET_STAT()) & BUSY_STAT)) {
- restore_flags(flags);
- goto test;
+ udelay(1); /* spec allows drive 400ns to assert "BUSY" */
+ if ((stat = GET_STAT()) & BUSY_STAT) {
+ save_flags(flags);
+ ide_sti();
+ timeout += jiffies;
+ while ((stat = GET_STAT()) & BUSY_STAT) {
+ if (jiffies > timeout) {
+ restore_flags(flags);
+ ide_error(drive, "status timeout", stat);
+ return 1;
+ }
}
- } while (jiffies <= timeout);
-
- restore_flags(flags);
- ide_error(drive, "status timeout", GET_STAT());
+ restore_flags(flags);
+ }
+ udelay(1); /* allow status to settle, then read it again */
+ if (OK_STAT((stat = GET_STAT()), good, bad))
+ return 0;
+ ide_error(drive, "status error", stat);
return 1;
}
diff --git a/drivers/block/ide.h b/drivers/block/ide.h
index 241a571ca..95724e6e9 100644
--- a/drivers/block/ide.h
+++ b/drivers/block/ide.h
@@ -134,7 +134,7 @@ typedef unsigned char byte; /* used everywhere */
#define BAD_W_STAT (BAD_R_STAT | WRERR_STAT)
#define BAD_STAT (BAD_R_STAT | DRQ_STAT)
#define DRIVE_READY (READY_STAT | SEEK_STAT)
-#define DATA_READY (DRIVE_READY | DRQ_STAT)
+#define DATA_READY (DRQ_STAT)
/*
* Some more useful definitions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 212efece2..53fef9b74 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -318,7 +318,7 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg)
}
lo->lo_inode = inode;
- lo->lo_inode->i_count++;
+ atomic_inc(&lo->lo_inode->i_count);
lo->transfer = NULL;
figure_loop_size(lo);
MOD_INC_USE_COUNT;
diff --git a/drivers/block/md.c b/drivers/block/md.c
index 078e1e1ee..12cb6dcf0 100644
--- a/drivers/block/md.c
+++ b/drivers/block/md.c
@@ -202,9 +202,10 @@ static int do_md_stop (int minor, struct inode *inode)
{
int i;
- if (inode->i_count>1 || md_dev[minor].busy>1) /* ioctl : one open channel */
+ if (atomic_read(&inode->i_count)>1 || md_dev[minor].busy>1) /* ioctl : one open channel */
{
- printk ("STOP_MD md%x failed : i_count=%d, busy=%d\n", minor, inode->i_count, md_dev[minor].busy);
+ printk ("STOP_MD md%x failed : i_count=%d, busy=%d\n", minor,
+ atomic_read(&inode->i_count), md_dev[minor].busy);
return -EBUSY;
}