diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/genhd.c | 141 | ||||
-rw-r--r-- | drivers/block/ide.c | 40 | ||||
-rw-r--r-- | drivers/block/ide.h | 2 | ||||
-rw-r--r-- | drivers/block/loop.c | 2 | ||||
-rw-r--r-- | drivers/block/md.c | 5 |
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; } |