summaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-06-13 16:29:25 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-06-13 16:29:25 +0000
commitdb7d4daea91e105e3859cf461d7e53b9b77454b2 (patch)
tree9bb65b95440af09e8aca63abe56970dd3360cc57 /drivers/block
parent9c1c01ead627bdda9211c9abd5b758d6c687d8ac (diff)
Merge with Linux 2.2.8.
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/Config.in16
-rw-r--r--drivers/block/Makefile4
-rw-r--r--drivers/block/cmd646.c9
-rw-r--r--drivers/block/floppy.c48
-rw-r--r--drivers/block/genhd.c103
-rw-r--r--drivers/block/hd.c3
-rw-r--r--drivers/block/ide-cd.c80
-rw-r--r--drivers/block/ide-cd.h31
-rw-r--r--drivers/block/ide-disk.c31
-rw-r--r--drivers/block/ide-pmac.c66
-rw-r--r--drivers/block/ide-probe.c73
-rw-r--r--drivers/block/ide.c36
-rw-r--r--drivers/block/ide.h8
-rw-r--r--drivers/block/ide_modes.h2
-rw-r--r--drivers/block/ll_rw_blk.c7
-rw-r--r--drivers/block/nbd.c36
-rw-r--r--drivers/block/ns87415.c6
-rw-r--r--drivers/block/rd.c123
-rw-r--r--drivers/block/sl82c105.c4
-rw-r--r--drivers/block/swim3.c119
20 files changed, 574 insertions, 231 deletions
diff --git a/drivers/block/Config.in b/drivers/block/Config.in
index de2ca9c88..390aa708c 100644
--- a/drivers/block/Config.in
+++ b/drivers/block/Config.in
@@ -51,13 +51,15 @@ else
bool ' Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105
fi
fi
- if [ "$CONFIG_PMAC" = "y" ]; then
- define_bool CONFIG_BLK_DEV_IDE_PMAC y
- bool ' PowerMac IDE DMA support' CONFIG_BLK_DEV_IDEDMA_PMAC
- if [ "$CONFIG_BLK_DEV_IDEDMA_PMAC" = "y" ]; then
- define_bool CONFIG_BLK_DEV_IDEDMA y
- bool ' Use DMA by default' CONFIG_PMAC_IDEDMA_AUTO
- fi
+ if [ "$CONFIG_PMAC" = "y" -o "$CONFIG_ALL_PPC" = "y" ]; then
+ bool ' Builtin PowerMac IDE support' CONFIG_BLK_DEV_IDE_PMAC
+ if [ "$CONFIG_BLK_DEV_IDE_PMAC" != "n" ]; then
+ bool ' PowerMac IDE DMA support' CONFIG_BLK_DEV_IDEDMA_PMAC
+ if [ "$CONFIG_BLK_DEV_IDEDMA_PMAC" = "y" ]; then
+ define_bool CONFIG_BLK_DEV_IDEDMA y
+ bool ' Use DMA by default' CONFIG_PMAC_IDEDMA_AUTO
+ fi
+ fi
fi
bool ' Other IDE chipset support' CONFIG_IDE_CHIPSETS
if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 6d48ecb98..79f3a9547 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -220,6 +220,10 @@ endif
ifeq ($(CONFIG_BLK_DEV_PS2),y)
L_OBJS += ps2esdi.o
+else
+ ifeq ($(CONFIG_BLK_DEV_PS2),m)
+ M_OBJS += ps2esdi.o
+ endif
endif
ifeq ($(CONFIG_BLK_DEV_XD),y)
diff --git a/drivers/block/cmd646.c b/drivers/block/cmd646.c
index fe2eb10a2..57b593131 100644
--- a/drivers/block/cmd646.c
+++ b/drivers/block/cmd646.c
@@ -1,4 +1,4 @@
-/* $Id: cmd646.c,v 1.10 1998/08/03 15:28:42 davem Exp $
+/* $Id: cmd646.c,v 1.11 1998/12/13 08:36:54 davem Exp $
* cmd646.c: Enable interrupts at initialization time on Ultra/PCI machines.
* Note, this driver is not used at all on other systems because
* there the "BIOS" has done all of the following already.
@@ -219,8 +219,11 @@ __initfunc(void ide_init_cmd646 (ide_hwif_t *hwif))
hwif->chipset = ide_cmd646;
- /* Set a good latency timer value. */
- (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 240);
+ /* Set a good latency timer and cache line size value. */
+ (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
+#ifdef __sparc_v9__
+ (void) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x10);
+#endif
/* Setup interrupts. */
(void) pci_read_config_byte(dev, 0x71, &mrdmode);
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 4c18a79dd..2b3f38895 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -3594,7 +3594,7 @@ static void config_types(void)
/* read drive info out of physical CMOS */
drive=0;
if (!UDP->cmos)
- UDP->cmos= FLOPPY0_TYPE;
+ UDP->cmos = FLOPPY0_TYPE;
drive=1;
if (!UDP->cmos && FLOPPY1_TYPE)
UDP->cmos = FLOPPY1_TYPE;
@@ -3603,26 +3603,31 @@ static void config_types(void)
/* additional physical CMOS drive detection should go here */
for (drive=0; drive < N_DRIVE; drive++){
- if (UDP->cmos >= 16)
- UDP->cmos = 0;
- if (UDP->cmos >= 0 && UDP->cmos <= NUMBER(default_drive_params))
- memcpy((char *) UDP,
- (char *) (&default_drive_params[(int)UDP->cmos].params),
- sizeof(struct floppy_drive_params));
- if (UDP->cmos){
- if (first)
- printk(KERN_INFO "Floppy drive(s): ");
- else
- printk(", ");
- first=0;
- if (UDP->cmos > 0){
+ unsigned int type = UDP->cmos;
+ struct floppy_drive_params *params;
+ const char *name = NULL;
+ static char temparea[32];
+
+ if (type < NUMBER(default_drive_params)) {
+ params = &default_drive_params[type].params;
+ if (type) {
+ name = default_drive_params[type].name;
allowed_drive_mask |= 1 << drive;
- printk("fd%d is %s", drive,
- default_drive_params[(int)UDP->cmos].name);
- } else
- printk("fd%d is unknown type %d",drive,
- UDP->cmos);
+ }
+ } else {
+ params = &default_drive_params[0].params;
+ sprintf(temparea, "unknown type %d (usb?)", type);
+ name = temparea;
}
+ if (name) {
+ const char * prepend = ",";
+ if (first) {
+ prepend = KERN_INFO "Floppy drive(s):";
+ first = 0;
+ }
+ printk("%s fd%d is %s", prepend, drive, name);
+ }
+ *UDP = *params;
}
if (!first)
printk("\n");
@@ -4022,11 +4027,6 @@ __initfunc(static void set_cmos(int *ints, int dummy, int dummy2))
}
if (current_drive >= 4 && !FDC2)
FDC2 = 0x370;
- if (ints[2] <= 0 ||
- (ints[2] >= NUMBER(default_drive_params) && ints[2] != 16)){
- DPRINT("bad CMOS code %d\n", ints[2]);
- return;
- }
DP->cmos = ints[2];
DPRINT("setting CMOS code to %d\n", ints[2]);
}
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index edb8a41cc..729c59929 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -130,6 +130,14 @@ static inline int is_extended_partition(struct partition *p)
SYS_IND(p) == LINUX_EXTENDED_PARTITION);
}
+static int sector_partition_scale(kdev_t dev)
+{
+ if (hardsect_size[MAJOR(dev)] != NULL)
+ return (hardsect_size[MAJOR(dev)][MINOR(dev)]/512);
+ else
+ return (1);
+}
+
static unsigned int get_ptable_blocksize(kdev_t dev)
{
int ret = 1024;
@@ -149,6 +157,7 @@ static unsigned int get_ptable_blocksize(kdev_t dev)
* the natural blocksize for the device so that we don't have to try
* and read partial sectors. Anything smaller should be just fine.
*/
+
switch( blksize_size[MAJOR(dev)][MINOR(dev)] )
{
case 2048:
@@ -196,6 +205,7 @@ static void extended_partition(struct gendisk *hd, kdev_t dev)
struct partition *p;
unsigned long first_sector, first_size, this_sector, this_size;
int mask = (1 << hd->minor_shift) - 1;
+ int sector_size = sector_partition_scale(dev);
int i;
first_sector = hd->part[MINOR(dev)].start_sect;
@@ -233,22 +243,22 @@ static void extended_partition(struct gendisk *hd, kdev_t dev)
* First process the data partition(s)
*/
for (i=0; i<4; i++, p++) {
- if (!NR_SECTS(p) || is_extended_partition(p))
- continue;
-
- /* Check the 3rd and 4th entries -
- these sometimes contain random garbage */
- if (i >= 2
- && START_SECT(p) + NR_SECTS(p) > this_size
- && (this_sector + START_SECT(p) < first_sector ||
- this_sector + START_SECT(p) + NR_SECTS(p) >
- first_sector + first_size))
- continue;
-
- add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p));
- current_minor++;
- if ((current_minor & mask) == 0)
- goto done;
+ if (!NR_SECTS(p) || is_extended_partition(p))
+ continue;
+
+ /* Check the 3rd and 4th entries -
+ these sometimes contain random garbage */
+ if (i >= 2
+ && START_SECT(p) + NR_SECTS(p) > this_size
+ && (this_sector + START_SECT(p) < first_sector ||
+ this_sector + START_SECT(p) + NR_SECTS(p) >
+ first_sector + first_size))
+ continue;
+
+ add_partition(hd, current_minor, this_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size);
+ current_minor++;
+ if ((current_minor & mask) == 0)
+ goto done;
}
/*
* Next, process the (first) extended partition, if present.
@@ -262,20 +272,21 @@ static void extended_partition(struct gendisk *hd, kdev_t dev)
*/
p -= 4;
for (i=0; i<4; i++, p++)
- if(NR_SECTS(p) && is_extended_partition(p))
- break;
+ if(NR_SECTS(p) && is_extended_partition(p))
+ break;
if (i == 4)
- goto done; /* nothing left to do */
+ goto done; /* nothing left to do */
- hd->part[current_minor].nr_sects = NR_SECTS(p);
- hd->part[current_minor].start_sect = first_sector + START_SECT(p);
- this_sector = first_sector + START_SECT(p);
+ hd->part[current_minor].nr_sects = NR_SECTS(p) * sector_size; /* JSt */
+ hd->part[current_minor].start_sect = first_sector + START_SECT(p) * sector_size;
+ this_sector = first_sector + START_SECT(p) * sector_size;
dev = MKDEV(hd->major, current_minor);
brelse(bh);
}
done:
brelse(bh);
}
+
#ifdef CONFIG_SOLARIS_X86_PARTITION
static void
solaris_x86_partition(struct gendisk *hd, kdev_t dev, long offset) {
@@ -317,11 +328,13 @@ solaris_x86_partition(struct gendisk *hd, kdev_t dev, long offset) {
#endif
#ifdef CONFIG_BSD_DISKLABEL
-static void check_and_add_bsd_partition(struct gendisk *hd, struct bsd_partition *bsd_p)
+static void check_and_add_bsd_partition(struct gendisk *hd,
+ struct bsd_partition *bsd_p, kdev_t dev)
{
struct hd_struct *lin_p;
/* check relative position of partitions. */
- for (lin_p = hd->part + 1; lin_p - hd->part < current_minor; lin_p++) {
+ for (lin_p = hd->part + 1 + MINOR(dev);
+ lin_p - hd->part - MINOR(dev) < current_minor; lin_p++) {
/* no relationship -> try again */
if (lin_p->start_sect + lin_p->nr_sects <= bsd_p->p_offset
|| lin_p->start_sect >= bsd_p->p_offset + bsd_p->p_size)
@@ -383,7 +396,7 @@ static void bsd_disklabel_partition(struct gendisk *hd, kdev_t dev,
break;
if (p->p_fstype != BSD_FS_UNUSED)
- check_and_add_bsd_partition(hd, p);
+ check_and_add_bsd_partition(hd, p, dev);
}
brelse(bh);
@@ -436,6 +449,7 @@ static int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_s
struct partition *p;
unsigned char *data;
int mask = (1 << hd->minor_shift) - 1;
+ int sector_size = sector_partition_scale(dev);
#ifdef CONFIG_BSD_DISKLABEL
/* no bsd disklabel as a default */
kdev_t bsd_kdev = 0;
@@ -538,7 +552,7 @@ check_table:
for (i=1 ; i<=4 ; minor++,i++,p++) {
if (!NR_SECTS(p))
continue;
- add_partition(hd, minor, first_sector+START_SECT(p), NR_SECTS(p));
+ add_partition(hd, minor, first_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size);
if (is_extended_partition(p)) {
printk(" <");
/*
@@ -795,7 +809,7 @@ static int sgi_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sec
struct sgi_partition *p;
#define SGI_LABEL_MAGIC 0x0be5a941
- if(!(bh = bread(dev, 0, 1024))) {
+ if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) {
printk("Dev %s: unable to read partition table\n", kdevname(dev));
return -1;
}
@@ -863,12 +877,20 @@ amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
int nr_sects;
int blk;
int part, res;
+ int old_blocksize;
+ int blocksize;
- set_blocksize(dev,512);
+ old_blocksize = get_ptable_blocksize(dev);
+ if (hardsect_size[MAJOR(dev)] != NULL)
+ blocksize = hardsect_size[MAJOR(dev)][MINOR(dev)];
+ else
+ blocksize = 512;
+
+ set_blocksize(dev,blocksize);
res = 0;
for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) {
- if(!(bh = bread(dev,blk,512))) {
+ if(!(bh = bread(dev,blk,blocksize))) {
printk("Dev %s: unable to read RDB block %d\n",
kdevname(dev),blk);
goto rdb_done;
@@ -876,16 +898,25 @@ amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
if (*(u32 *)bh->b_data == htonl(IDNAME_RIGIDDISK)) {
rdb = (struct RigidDiskBlock *)bh->b_data;
if (checksum_block((u32 *)bh->b_data,htonl(rdb->rdb_SummedLongs) & 0x7F)) {
- printk("Dev %s: RDB in block %d has bad checksum\n",
- kdevname(dev),blk);
- brelse(bh);
- continue;
+ /* Try again with 0xdc..0xdf zeroed, Windows might have
+ * trashed it.
+ */
+ *(u32 *)(&bh->b_data[0xdc]) = 0;
+ if (checksum_block((u32 *)bh->b_data,
+ htonl(rdb->rdb_SummedLongs) & 0x7F)) {
+ brelse(bh);
+ printk("Dev %s: RDB in block %d has bad checksum\n",
+ kdevname(dev),blk);
+ continue;
+ }
+ printk("Warning: Trashed word at 0xd0 in block %d "
+ "ignored in checksum calculation\n",blk);
}
printk(" RDSK");
blk = htonl(rdb->rdb_PartitionList);
brelse(bh);
for (part = 1; blk > 0 && part <= 16; part++) {
- if (!(bh = bread(dev,blk,512))) {
+ if (!(bh = bread(dev,blk,blocksize))) {
printk("Dev %s: unable to read partition block %d\n",
kdevname(dev),blk);
goto rdb_done;
@@ -918,7 +949,7 @@ amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
}
rdb_done:
- set_blocksize(dev,BLOCK_SIZE);
+ set_blocksize(dev,old_blocksize);
return res;
}
#endif /* CONFIG_AMIGA_PARTITION */
@@ -1099,7 +1130,7 @@ static int atari_partition (struct gendisk *hd, kdev_t dev,
partsect = extensect = pi->st;
while (1)
{
- xbh = bread (dev, partsect / 2, 1024);
+ xbh = bread (dev, partsect / 2, get_ptable_blocksize(dev));
if (!xbh)
{
printk (" block %ld read failed\n", partsect);
diff --git a/drivers/block/hd.c b/drivers/block/hd.c
index 5674e3070..203c2d609 100644
--- a/drivers/block/hd.c
+++ b/drivers/block/hd.c
@@ -744,11 +744,12 @@ static void hd_geninit(struct gendisk *ignored)
*/
- if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
+ if ((cmos_disks = CMOS_READ(0x12)) & 0xf0) {
if (cmos_disks & 0x0f)
NR_HD = 2;
else
NR_HD = 1;
+ }
}
#endif /* __i386__ */
for (drive=0 ; drive < NR_HD ; drive++) {
diff --git a/drivers/block/ide-cd.c b/drivers/block/ide-cd.c
index 2e1f9ba76..7e07eda65 100644
--- a/drivers/block/ide-cd.c
+++ b/drivers/block/ide-cd.c
@@ -33,6 +33,7 @@
* boot
* -Integrate DVD-ROM support in driver. Thanks to Merete Gotsæd-Petersen
* of Pioneer Denmark for providing me with a drive for testing.
+ * -Implement Features and Profiles.
*
*
* ----------------------------------
@@ -230,9 +231,23 @@
* 4.52 Jan 19, 1999 -- Jens Axboe <axboe@image.dk>
* - Detect DVD-ROM/RAM drives
*
+ * 4.53 Feb 22, 1999 - Include other model Samsung and one Goldstar
+ * drive in transfer size limit.
+ * - Fix the I/O error when doing eject without a medium
+ * loaded on some drives.
+ * - CDROMREADMODE2 is now implemented through
+ * CDROMREADRAW, since many drives don't support
+ * MODE2 (even though ATAPI 2.6 says they must).
+ * - Added ignore parameter to ide-cd (as a module), eg
+ * insmod ide-cd ignore='hda hdb'
+ * Useful when using ide-cd in conjunction with
+ * ide-scsi. TODO: non-modular way of doing the
+ * same.
+ *
+ *
*************************************************************************/
-#define IDECD_VERSION "4.52"
+#define IDECD_VERSION "4.53"
#include <linux/module.h>
#include <linux/types.h>
@@ -252,7 +267,6 @@
#include "ide.h"
#include "ide-cd.h"
-
/****************************************************************************
* Generic packet command support and error handling routines.
*/
@@ -1527,6 +1541,10 @@ cdrom_lockdoor (ide_drive_t *drive, int lockflag,
CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;
stat = 0;
}
+
+ /* no medium, that's alright. */
+ if (stat != 0 && reqbuf->sense_key == NOT_READY && reqbuf->asc == 0x3a)
+ stat = 0;
if (stat == 0)
CDROM_STATE_FLAGS (drive)->door_locked = lockflag;
@@ -1806,7 +1824,6 @@ cdrom_mode_select (ide_drive_t *drive, int pageno, char *buf, int buflen,
return cdrom_queue_packet_command (drive, &pc);
}
-
/* ATAPI cdrom drives are free to select the speed you request or any slower
rate :-( Requesting too fast a speed will _not_ produce an error. */
static int
@@ -2092,22 +2109,17 @@ int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi,
if (cmd == CDROMREADMODE1) {
blocksize = CD_FRAMESIZE;
format = 2;
- } else if (cmd == CDROMREADMODE2) {
- blocksize = CD_FRAMESIZE_RAW0;
- format = 3;
- } else {
+ } else { /* for RAW and MODE2. */
blocksize = CD_FRAMESIZE_RAW;
format = 0;
}
- stat = verify_area (VERIFY_WRITE, (char *)arg, blocksize);
- if (stat) return stat;
+
+ copy_from_user_ret(&msf, (void *)arg, sizeof (msf), -EFAULT);
- copy_from_user (&msf, (void *)arg, sizeof (msf));
+ lba = msf_to_lba(msf.cdmsf_min0,
+ msf.cdmsf_sec0,
+ msf.cdmsf_frame0);
- lba = msf_to_lba (msf.cdmsf_min0,
- msf.cdmsf_sec0,
- msf.cdmsf_frame0);
-
/* Make sure the TOC is up to date. */
stat = cdrom_read_toc (drive, NULL);
if (stat) return stat;
@@ -2117,14 +2129,21 @@ int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi,
if (lba < 0 || lba >= toc->capacity)
return -EINVAL;
- buf = (char *) kmalloc (CD_FRAMESIZE_RAW, GFP_KERNEL);
+ buf = (char *) kmalloc (blocksize, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
stat = cdrom_read_block (drive, format, lba, 1, buf, blocksize,
NULL);
- if (stat == 0)
- copy_to_user ((char *)arg, buf, blocksize);
+
+ if (stat == 0) {
+ if (cmd == CDROMREADMODE2) {
+ /* For Mode2, skip the Sync, Header, and Subheader */
+ copy_to_user_ret((char *)arg, buf+16, CD_FRAMESIZE_RAW0, -EFAULT);
+ } else {
+ copy_to_user_ret((char *)arg, buf, blocksize, -EFAULT);
+ }
+ }
kfree (buf);
return stat;
@@ -2486,14 +2505,12 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
static
int ide_cdrom_reset (struct cdrom_device_info *cdi)
{
-
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
struct request req;
ide_init_drive_cmd (&req);
req.cmd = RESET_DRIVE_COMMAND;
return ide_do_drive_cmd (drive, &req, ide_wait);
-
}
@@ -2501,9 +2518,10 @@ static
int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ struct atapi_request_sense rq;
if (position) {
- int stat = cdrom_lockdoor (drive, 0, NULL);
+ int stat = cdrom_lockdoor (drive, 0, &rq);
if (stat) return stat;
}
@@ -2980,12 +2998,14 @@ int ide_cdrom_setup (ide_drive_t *drive)
CDROM_CONFIG_FLAGS (drive)->no_eject = 1;
CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 0;
- /* limit transfer size per interrupt. currently only one Samsung
- drive needs this. */
+ /* limit transfer size per interrupt. */
CDROM_CONFIG_FLAGS (drive)->limit_nframes = 0;
- if (drive->id != NULL)
- if (strcmp (drive->id->model, "SAMSUNG CD-ROM SCR-2432") == 0)
+ if (drive->id != NULL) {
+ if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2430"))
CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1;
+ else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2432"))
+ CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1;
+ }
#if ! STANDARD_ATAPI
/* by default Sanyo 3 CD changer support is turned off and
@@ -3155,7 +3175,13 @@ static ide_module_t ide_cdrom_module = {
NULL
};
+/* options */
+char *ignore = NULL;
+
#ifdef MODULE
+MODULE_PARM(ignore, "s");
+MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
+
int init_module (void)
{
return ide_cdrom_init();
@@ -3183,6 +3209,12 @@ int ide_cdrom_init (void)
MOD_INC_USE_COUNT;
while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, NULL, failed++)) != NULL) {
+ /* skip drives that we were told to ignore */
+ if (ignore != NULL)
+ if (strstr(ignore, drive->name)) {
+ printk("ide-cd: ignoring drive %s\n", drive->name);
+ continue;
+ }
info = (struct cdrom_info *) kmalloc (sizeof (struct cdrom_info), GFP_KERNEL);
if (info == NULL) {
printk ("%s: Can't allocate a cdrom structure\n", drive->name);
diff --git a/drivers/block/ide-cd.h b/drivers/block/ide-cd.h
index 289b656ba..553013b9d 100644
--- a/drivers/block/ide-cd.h
+++ b/drivers/block/ide-cd.h
@@ -85,6 +85,9 @@
#define MECHANISM_STATUS 0xbd
#define READ_CD 0xbe
+/* DVD Opcodes */
+#define DVD_GET_PERFORMANCE 0xac
+
/* Page codes for mode sense/set */
@@ -331,13 +334,13 @@ struct atapi_capabilities_page {
#if defined(__BIG_ENDIAN_BITFIELD)
__u8 reserved3 : 2;
- /* Drive can fake writes */
- __u8 test_write : 1;
- __u8 reserved3a : 1;
- /* Drive can write DVD-R discs */
- __u8 dvd_r_write : 1;
/* Drive can write DVD-RAM discs */
__u8 dvd_ram_write : 1;
+ /* Drive can write DVD-R discs */
+ __u8 dvd_r_write : 1;
+ __u8 reserved3a : 1;
+ /* Drive can fake writes */
+ __u8 test_write : 1;
/* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
__u8 cd_rw_write : 1; /* reserved in 1.2 */
/* Drive supports write to CD-R discs (orange book, part II) */
@@ -347,20 +350,20 @@ struct atapi_capabilities_page {
__u8 cd_r_write : 1; /* reserved in 1.2 */
/* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
__u8 cd_rw_write : 1; /* reserved in 1.2 */
- /* Drive can write DVD-RAM discs */
- __u8 dvd_ram_write : 1;
- /* Drive can write DVD-R discs */
- __u8 dvd_r_write : 1;
- __u8 reserved3a : 1;
/* Drive can fake writes */
__u8 test_write : 1;
+ __u8 reserved3a : 1;
+ /* Drive can write DVD-R discs */
+ __u8 dvd_r_write : 1;
+ /* Drive can write DVD-RAM discs */
+ __u8 dvd_ram_write : 1;
__u8 reserved3 : 2;
#else
#error "Please fix <asm/byteorder.h>"
#endif
#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 reserved4 : 4;
+ __u8 reserved4 : 1;
/* Drive can read multisession discs. */
__u8 multisession : 1;
/* Drive can read mode 2, form 2 data. */
@@ -562,7 +565,7 @@ struct cdrom_info {
/* Sector buffer. If a read request wants only the first part
of a cdrom block, we cache the rest of the block here,
- in the expectation that that data is going to be wanted soon.
+ in the expectation that the data is going to be wanted soon.
SECTOR_BUFFERED is the number of the first buffered sector,
and NSECTORS_BUFFERED is the number of sectors in the buffer.
Before the buffer is allocated, we should have
@@ -656,6 +659,7 @@ const struct {
{ PLAY_CD, "Play CD" },
{ MECHANISM_STATUS, "Mechanism Status" },
{ READ_CD, "Read CD" },
+ { DVD_GET_PERFORMANCE, "Get Performance" },
};
@@ -776,7 +780,8 @@ const struct {
{ 0x6400, "Illegal mode for this track or incompatible medium" },
- { 0xb900, "Play operation oborted (sic)" },
+ /* Following error is misspelled in ATAPI 2.6 */
+ { 0xb900, "Play operation oborted [sic]" },
{ 0xbf00, "Loss of streaming" },
};
diff --git a/drivers/block/ide-disk.c b/drivers/block/ide-disk.c
index f84ac8f14..14ad6269e 100644
--- a/drivers/block/ide-disk.c
+++ b/drivers/block/ide-disk.c
@@ -101,20 +101,6 @@ static int lba_capacity_is_ok (struct hd_driveid *id)
id->cyls = lba_sects / (16 * 63); /* correct cyls */
return 1; /* lba_capacity is our only option */
}
- /*
- * This is a split test for drives less than 8 Gig only.
- * Drives less than 8GB sometimes declare that they have 15 heads.
- * This is an accounting trick (0-15) == (1-16), just an initial
- * zero point difference.
- */
- if ((id->lba_capacity < 16514064) && (lba_sects > chs_sects) &&
- ((id->heads == 15) || (id->heads == 16)) && (id->sectors == 63)) {
- if (id->heads == 15)
- id->cyls = lba_sects / (15 * 63); /* correct cyls */
- if (id->heads == 16)
- id->cyls = lba_sects / (16 * 63); /* correct cyls */
- return 1; /* lba_capacity is our only option */
- }
/* 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 */
@@ -684,10 +670,15 @@ static void idedisk_setup (ide_drive_t *drive)
if (id == NULL)
return;
- /* check for removable disks (eg. SYQUEST), ignore 'WD' drives */
- if (id->config & (1<<7)) { /* removable disk ? */
+ /*
+ * CompactFlash cards and their brethern look just like hard drives
+ * to us, but they are removable and don't have a doorlock mechanism.
+ */
+ if (drive->removable && !drive_is_flashcard(drive)) {
+ /*
+ * Removable disks (eg. SYQUEST); ignore 'WD' drives
+ */
if (id->model[0] != 'W' || id->model[1] != 'D') {
- drive->removable = 1;
drive->doorlocking = 1;
}
}
@@ -818,12 +809,6 @@ int idedisk_init (void)
MOD_INC_USE_COUNT;
while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, NULL, failed++)) != NULL) {
-
- /* SunDisk drives: ignore "second" drive; can mess up non-Sun systems! FIXME */
- struct hd_driveid *id = drive->id;
- if (id && id->model[0] == 'S' && id->model[1] == 'u' && drive->select.b.unit)
- continue;
-
if (ide_register_subdriver (drive, &idedisk_driver, IDE_SUBDRIVER_VERSION)) {
printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);
continue;
diff --git a/drivers/block/ide-pmac.c b/drivers/block/ide-pmac.c
index f504cb9c2..d8d353d87 100644
--- a/drivers/block/ide-pmac.c
+++ b/drivers/block/ide-pmac.c
@@ -20,13 +20,19 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
+#include <linux/delay.h>
#include <asm/prom.h>
#include <asm/io.h>
#include <asm/dbdma.h>
#include <asm/ide.h>
#include <asm/mediabay.h>
#include <asm/feature.h>
+#ifdef CONFIG_PMAC_PBOOK
+#include <asm/adb.h>
+#include <asm/pmu.h>
+#endif
#include "ide.h"
+#include "ide_modes.h"
ide_ioreg_t pmac_ide_regbase[MAX_HWIFS];
int pmac_ide_irq[MAX_HWIFS];
@@ -41,6 +47,13 @@ static int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive);
static int pmac_ide_build_dmatable(ide_drive_t *drive, int wr);
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+#ifdef CONFIG_PMAC_PBOOK
+static int idepmac_notify(struct notifier_block *, unsigned long, void *);
+struct notifier_block idepmac_sleep_notifier = {
+ idepmac_notify
+};
+#endif /* CONFIG_PMAC_PBOOK */
+
/*
* N.B. this can't be an initfunc, because the media-bay task can
* call ide_[un]register at any time.
@@ -74,6 +87,23 @@ pmac_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)
}
}
+void pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
+{
+ ide_pio_data_t d;
+
+ if (_machine != _MACH_Pmac)
+ return;
+ pio = ide_get_best_pio_mode(drive, pio, 4, &d);
+ switch (pio) {
+ case 4:
+ out_le32((unsigned *)(IDE_DATA_REG + 0x200), 0x211025);
+ break;
+ default:
+ out_le32((unsigned *)(IDE_DATA_REG + 0x200), 0x2f8526);
+ break;
+ }
+}
+
__initfunc(void
pmac_ide_probe(void))
{
@@ -145,9 +175,10 @@ pmac_ide_probe(void))
pmac_ide_init_hwif_ports(hwif->io_ports, base, &hwif->irq);
hwif->chipset = ide_generic;
hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
+ hwif->tuneproc = pmac_ide_tuneproc;
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
- if (np->n_addrs >= 2 && np->n_intrs >= 2) {
+ if (np->n_addrs >= 2) {
/* has a DBDMA controller channel */
pmac_ide_setup_dma(np, hwif);
}
@@ -156,6 +187,10 @@ pmac_ide_probe(void))
++i;
}
pmac_ide_count = i;
+
+#ifdef CONFIG_PMAC_PBOOK
+ notifier_chain_register(&sleep_notifier_list, &idepmac_sleep_notifier);
+#endif /* CONFIG_PMAC_PBOOK */
}
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
@@ -311,5 +346,32 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
}
return 0;
}
-
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+
+#ifdef CONFIG_PMAC_PBOOK
+static int idepmac_notify(struct notifier_block *this,
+ unsigned long code, void *p)
+{
+ int i, timeout;
+
+ switch (code) {
+ case PBOOK_SLEEP:
+ /* do anything here?? */
+ break;
+ case PBOOK_WAKE:
+ /* wait for the controller(s) to become ready */
+ timeout = 5000;
+ for (i = 0; i < pmac_ide_count; ++i) {
+ unsigned long base = pmac_ide_regbase[i];
+ if (check_media_bay_by_base(base, MB_CD) == -EINVAL)
+ continue;
+ while ((inb(base + 0x70) & BUSY_STAT) && timeout) {
+ mdelay(1);
+ --timeout;
+ }
+ }
+ break;
+ }
+ return NOTIFY_DONE;
+}
+#endif /* CONFIG_PMAC_PBOOK */
diff --git a/drivers/block/ide-probe.c b/drivers/block/ide-probe.c
index 8e0c54dc1..1d13043e8 100644
--- a/drivers/block/ide-probe.c
+++ b/drivers/block/ide-probe.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/ide-probe.c Version 1.03 Dec 5, 1997
+ * linux/drivers/block/ide-probe.c Version 1.04 March 10, 1999
*
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
*/
@@ -17,6 +17,7 @@
* Version 1.02 increase WAIT_PIDENTIFY to avoid CD-ROM locking at boot
* by Andrea Arcangeli
* Version 1.03 fix for (hwif->chipset == ide_4drives)
+ * Version 1.04 fixed buggy treatments of known flash memory cards
*/
#undef REALLY_SLOW_IO /* most systems can safely undef this */
@@ -84,16 +85,6 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
drive->present = 1;
/*
- * Prevent long system lockup probing later for non-existant
- * slave drive if the hwif is actually a Kodak CompactFlash card.
- */
- if (!strcmp(id->model, "KODAK ATA_FLASH")) {
- ide_drive_t *mate = &HWIF(drive)->drives[1^drive->select.b.unit];
- mate->present = 0;
- mate->noprobe = 1;
- }
-
- /*
* Check for an ATAPI device
*/
if (cmd == WIN_PIDENTIFY) {
@@ -124,6 +115,10 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
case ide_tape:
printk ("TAPE");
break;
+ case ide_optical:
+ printk ("OPTICAL");
+ drive->removable = 1;
+ break;
default:
printk("UNKNOWN (type %d)", type);
break;
@@ -133,6 +128,20 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
return;
}
+ /*
+ * Not an ATAPI device: looks like a "regular" hard disk
+ */
+ if (id->config & (1<<7))
+ drive->removable = 1;
+ /*
+ * Prevent long system lockup probing later for non-existant
+ * slave drive if the hwif is actually a flash memory card of some variety:
+ */
+ if (drive_is_flashcard(drive)) {
+ ide_drive_t *mate = &HWIF(drive)->drives[1^drive->select.b.unit];
+ mate->present = 0;
+ mate->noprobe = 1;
+ }
drive->media = ide_disk;
printk("ATA DISK drive\n");
return;
@@ -720,17 +729,39 @@ static int hwif_init (ide_hwif_t *hwif)
}
if (register_blkdev (hwif->major, hwif->name, ide_fops)) {
printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", hwif->name, hwif->major);
- } else if (init_irq (hwif)) {
- printk("%s: UNABLE TO GET IRQ %d\n", hwif->name, hwif->irq);
- (void) unregister_blkdev (hwif->major, hwif->name);
- } else {
- init_gendisk(hwif);
- blk_dev[hwif->major].data = hwif;
- blk_dev[hwif->major].request_fn = rfn;
- blk_dev[hwif->major].queue = ide_get_queue;
- read_ahead[hwif->major] = 8; /* (4kB) */
- hwif->present = 1; /* success */
+ return (hwif->present = 0);
+ }
+
+ if (init_irq (hwif)) {
+ int i = hwif->irq;
+ /*
+ * It failed to initialise. Find the default IRQ for
+ * this port and try that.
+ */
+ if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET])))
+ {
+ printk("%s: Disabled unable to get IRQ %d.\n", hwif->name, i);
+ (void) unregister_blkdev (hwif->major, hwif->name);
+ return (hwif->present = 0);
+ }
+ if(init_irq (hwif))
+ {
+ printk("%s: probed IRQ %d and default IRQ %d failed.\n",
+ hwif->name, i, hwif->irq);
+ (void) unregister_blkdev (hwif->major, hwif->name);
+ return (hwif->present = 0);
+ }
+ printk("%s: probed IRQ %d failed, using default.\n",
+ hwif->name, hwif->irq);
}
+
+ init_gendisk(hwif);
+ blk_dev[hwif->major].data = hwif;
+ blk_dev[hwif->major].request_fn = rfn;
+ blk_dev[hwif->major].queue = ide_get_queue;
+ read_ahead[hwif->major] = 8; /* (4kB) */
+ hwif->present = 1; /* success */
+
#if (DEBUG_SPINLOCK > 0)
{
static int done = 0;
diff --git a/drivers/block/ide.c b/drivers/block/ide.c
index 456ca470f..2e703455d 100644
--- a/drivers/block/ide.c
+++ b/drivers/block/ide.c
@@ -254,6 +254,33 @@ static void init_ide_data (void)
}
/*
+ * CompactFlash cards and their brethern pretend to be removable hard disks, except:
+ * (1) they never have a slave unit, and
+ * (2) they don't have doorlock mechanisms.
+ * This test catches them, and is invoked elsewhere when setting appropriate config bits.
+ *
+ * FIXME: This treatment is probably applicable for *all* PCMCIA (PC CARD) devices,
+ * so in linux 2.3.x we should change this to just treat all PCMCIA drives this way,
+ * and get rid of the model-name tests below (too big of an interface change for 2.2.x).
+ * At that time, we might also consider parameterizing the timeouts and retries,
+ * since these are MUCH faster than mechanical drives. -M.Lord
+ */
+int drive_is_flashcard (ide_drive_t *drive)
+{
+ struct hd_driveid *id = drive->id;
+
+ if (drive->removable && id != NULL) {
+ if (!strncmp(id->model, "KODAK ATA_FLASH", 15) /* Kodak */
+ || !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */
+ || !strncmp(id->model, "SunDisk SDCFB", 13)) /* SunDisk */
+ {
+ return 1; /* yes, it is a flash memory card */
+ }
+ }
+ return 0; /* no, it is not a flash memory card */
+}
+
+/*
* ide_system_bus_speed() returns what we think is the system VESA/PCI
* bus speed (in MHz). This is used for calculating interface PIO timings.
* The default is 40 for known PCI systems, 50 otherwise.
@@ -786,7 +813,7 @@ void ide_error (ide_drive_t *drive, const char *msg, byte stat)
ide_end_drive_cmd(drive, stat, err);
return;
}
- if (stat & BUSY_STAT) { /* other bits are useless when BUSY */
+ if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */
rq->errors |= ERROR_RESET;
} else {
if (drive->media == ide_disk && (stat & ERR_STAT)) {
@@ -2068,6 +2095,12 @@ static int ide_ioctl (struct inode *inode, struct file *file,
(unsigned long *) &loc->start)) return -EFAULT;
return 0;
}
+ case BLKSSZGET:
+ /* Block size of media */
+ return put_user(blksize_size[HWIF(drive)->major]
+ [minor&PARTN_MASK],
+ (int *)arg);
+
case BLKFLSBUF:
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
fsync_dev(inode->i_rdev);
@@ -2957,6 +2990,7 @@ EXPORT_SYMBOL(ide_spin_wait_hwgroup);
/*
* Probe module
*/
+EXPORT_SYMBOL(drive_is_flashcard);
EXPORT_SYMBOL(ide_timer_expiry);
EXPORT_SYMBOL(ide_intr);
EXPORT_SYMBOL(ide_geninit);
diff --git a/drivers/block/ide.h b/drivers/block/ide.h
index 7c0b2555b..2ca3266ec 100644
--- a/drivers/block/ide.h
+++ b/drivers/block/ide.h
@@ -182,6 +182,7 @@ typedef unsigned char byte; /* used everywhere */
#define ide_scsi 0x21
#define ide_disk 0x20
+#define ide_optical 0x7
#define ide_cdrom 0x5
#define ide_tape 0x1
#define ide_floppy 0x0
@@ -677,6 +678,13 @@ void ide_stall_queue (ide_drive_t *drive, unsigned long timeout);
*/
struct request **ide_get_queue (kdev_t dev);
+/*
+ * CompactFlash cards and their brethern pretend to be removable hard disks,
+ * but they never have a slave unit, and they don't have doorlock mechanisms.
+ * This test catches them, and is invoked elsewhere when setting appropriate config bits.
+ */
+int drive_is_flashcard (ide_drive_t *drive);
+
int ide_spin_wait_hwgroup(ide_drive_t *drive, unsigned long *flags);
void ide_timer_expiry (unsigned long data);
void ide_intr (int irq, void *dev_id, struct pt_regs *regs);
diff --git a/drivers/block/ide_modes.h b/drivers/block/ide_modes.h
index 21679622c..49a4997e3 100644
--- a/drivers/block/ide_modes.h
+++ b/drivers/block/ide_modes.h
@@ -15,7 +15,7 @@
* breaking the fragile cmd640.c support.
*/
-#if defined(CONFIG_BLK_DEV_CMD640) || defined(CONFIG_IDE_CHIPSETS) || defined(CONFIG_BLK_DEV_OPTI621)
+#if defined(CONFIG_BLK_DEV_CMD640) || defined(CONFIG_IDE_CHIPSETS) || defined(CONFIG_BLK_DEV_OPTI621) || defined(CONFIG_BLK_DEV_IDE_PMAC)
/*
* Standard (generic) timings for PIO modes, from ATA2 specification.
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 695fcb361..bc2ed2cac 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -392,8 +392,10 @@ void make_request(int major,int rw, struct buffer_head * bh)
lock_buffer(bh);
- if (blk_size[major])
- if (blk_size[major][MINOR(bh->b_rdev)] < (sector + count)>>1) {
+ if (blk_size[major]) {
+ unsigned long maxsector = (blk_size[major][MINOR(bh->b_rdev)] << 1) + 1;
+
+ if (maxsector < count || maxsector - count < sector) {
bh->b_state &= (1 << BH_Lock);
/* This may well happen - the kernel calls bread()
without checking the size of the device, e.g.,
@@ -406,6 +408,7 @@ void make_request(int major,int rw, struct buffer_head * bh)
blk_size[major][MINOR(bh->b_rdev)]);
goto end_io;
}
+ }
rw_ahead = 0; /* normal case; gets changed below for READA/WRITEA */
switch (rw) {
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 8b316d116..ca4e93ed0 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -17,6 +17,7 @@
* 97-4-11 Making protocol independent of endianity etc.
* 97-9-13 Cosmetic changes
* 98-5-13 Attempt to make 64-bit-clean on 64-bit machines
+ * 99-1-11 Attempt to make 64-bit-clean on 32-bit machines <ankry@mif.pg.gda.pl>
*
* possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall
* why not: would need verify_area and friends, would share yet another
@@ -45,8 +46,9 @@
#define LO_MAGIC 0x68797548
static int nbd_blksizes[MAX_NBD];
+static int nbd_blksize_bits[MAX_NBD];
static int nbd_sizes[MAX_NBD];
-static int nbd_bytesizes[MAX_NBD];
+static u64 nbd_bytesizes[MAX_NBD];
static struct nbd_device nbd_dev[MAX_NBD];
@@ -149,7 +151,7 @@ void nbd_send_req(struct socket *sock, struct request *req)
DEBUG("NBD: sending control, ");
request.magic = htonl(NBD_REQUEST_MAGIC);
request.type = htonl(req->cmd);
- request.from = cpu_to_be64( (u64) req->sector * (u64) 512);
+ request.from = cpu_to_be64( (u64) req->sector << 9);
request.len = htonl(req->current_nr_sectors << 9);
memcpy(request.handle, &req, sizeof(req));
@@ -340,7 +342,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct nbd_device *lo;
- int dev, error;
+ int dev, error, temp;
/* Anyone capable of this syscall can do *real bad* things */
@@ -355,6 +357,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
lo = &nbd_dev[dev];
switch (cmd) {
case NBD_CLEAR_SOCK:
+ nbd_clear_que(lo);
if (lo->head || lo->tail) {
printk(KERN_ERR "nbd: Some requests are in progress -> can not turn off.\n");
return -EBUSY;
@@ -380,14 +383,25 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
}
return error;
case NBD_SET_BLKSIZE:
- if ((arg & 511) || (arg > PAGE_SIZE))
+ if ((arg & (arg-1)) || (arg < 512) || (arg > PAGE_SIZE))
return -EINVAL;
nbd_blksizes[dev] = arg;
- nbd_sizes[dev] = arg/nbd_blksizes[dev];
+ temp = arg >> 9;
+ nbd_blksize_bits[dev] = 9;
+ while (temp > 1) {
+ nbd_blksize_bits[dev]++;
+ temp >>= 1;
+ }
+ nbd_sizes[dev] = nbd_bytesizes[dev] >> nbd_blksize_bits[dev];
+ nbd_bytesizes[dev] = nbd_sizes[dev] << nbd_blksize_bits[dev];
return 0;
case NBD_SET_SIZE:
- nbd_bytesizes[dev] = arg;
- nbd_sizes[dev] = arg/nbd_blksizes[dev];
+ nbd_sizes[dev] = arg >> nbd_blksize_bits[dev];
+ nbd_bytesizes[dev] = nbd_sizes[dev] << nbd_blksize_bits[dev];
+ return 0;
+ case NBD_SET_SIZE_BLOCKS:
+ nbd_sizes[dev] = arg;
+ nbd_bytesizes[dev] = arg << nbd_blksize_bits[dev];
return 0;
case NBD_DO_IT:
if (!lo->file)
@@ -404,7 +418,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
return 0;
#endif
case BLKGETSIZE:
- return put_user(nbd_bytesizes[dev]/512, (long *) arg);
+ return put_user(nbd_bytesizes[dev] >> 9, (long *) arg);
}
return -EINVAL;
}
@@ -420,6 +434,7 @@ static int nbd_release(struct inode *inode, struct file *file)
if (dev >= MAX_NBD)
return -ENODEV;
fsync_dev(inode->i_rdev);
+ invalidate_buffers(inode->i_rdev);
lo = &nbd_dev[dev];
if (lo->refcnt <= 0)
printk(KERN_ALERT "nbd_release: refcount(%d) <= 0\n", lo->refcnt);
@@ -478,8 +493,9 @@ int nbd_init(void)
nbd_dev[i].magic = LO_MAGIC;
nbd_dev[i].flags = 0;
nbd_blksizes[i] = 1024;
- nbd_bytesizes[i] = 0x7fffffff;
- nbd_sizes[i] = nbd_bytesizes[i]/nbd_blksizes[i];
+ nbd_blksize_bits[i] = 10;
+ nbd_bytesizes[i] = 0x7ffffc00; /* 2GB */
+ nbd_sizes[i] = nbd_bytesizes[i] >> nbd_blksize_bits[i];
}
return 0;
}
diff --git a/drivers/block/ns87415.c b/drivers/block/ns87415.c
index dbce52137..3275c0171 100644
--- a/drivers/block/ns87415.c
+++ b/drivers/block/ns87415.c
@@ -95,6 +95,12 @@ __initfunc(void ide_init_ns87415 (ide_hwif_t *hwif))
byte stat;
#endif
+ /* Set a good latency timer and cache line size value. */
+ (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
+#ifdef __sparc_v9__
+ (void) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x10);
+#endif
+
/*
* We cannot probe for IRQ: both ports share common IRQ on INTA.
* Also, leave IRQ masked during drive probing, to prevent infinite
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index dd1933a47..13a4307a8 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -33,11 +33,13 @@
*
* Added initrd: Werner Almesberger & Hans Lermen, Feb '96
*
-* 4/25/96 : Made RAM disk size a parameter (default is now 4 MB)
+ * 4/25/96 : Made RAM disk size a parameter (default is now 4 MB)
* - Chad Page
*
* Add support for fs images split across >1 disk, Paul Gortmaker, Mar '98
*
+ * Make block size and block size shift for RAM disks a global macro
+ * and set blk_size for -ENOSPC, Werner Fink <werner@suse.de>, Apr '99
*/
#include <linux/config.h>
@@ -47,6 +49,7 @@
#include <linux/romfs_fs.h>
#include <linux/fs.h>
#include <linux/kernel.h>
+#include <linux/hdreg.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/mman.h>
@@ -70,6 +73,15 @@ extern void wait_for_keypress(void);
#define MAJOR_NR RAMDISK_MAJOR
#include <linux/blk.h>
+/*
+ * We use a block size of 512 bytes in comparision to BLOCK_SIZE
+ * defined in include/linux/blk.h. This because of the finer
+ * granularity for filling up a RAM disk.
+ */
+#define RDBLK_SIZE_BITS 9
+#define RDBLK_SIZE (1<<RDBLK_SIZE_BITS)
+
+
/* The RAM disk size is now a parameter */
#define NUM_RAMDISKS 16 /* This cannot be overridden (yet) */
@@ -89,8 +101,10 @@ static int initrd_users = 0;
/* Various static variables go here. Most are used only in the RAM disk code.
*/
-static int rd_length[NUM_RAMDISKS];
-static int rd_blocksizes[NUM_RAMDISKS];
+static unsigned long rd_length[NUM_RAMDISKS]; /* Size of RAM disks in bytes */
+static int rd_hardsec[NUM_RAMDISKS]; /* Size of real blocks in bytes */
+static int rd_blocksizes[NUM_RAMDISKS]; /* Size of 1024 byte blocks :) */
+static int rd_kbsize[NUM_RAMDISKS]; /* Size in blocks of 1024 bytes */
/*
* Parameters for the boot-loading of the RAM disk. These are set by
@@ -120,9 +134,12 @@ int initrd_below_start_ok = 0;
static void rd_request(void)
{
unsigned int minor;
- int offset, len;
+ unsigned long offset, len;
repeat:
+ if (!CURRENT)
+ return;
+
INIT_REQUEST;
minor = MINOR(CURRENT->rq_dev);
@@ -132,14 +149,20 @@ repeat:
goto repeat;
}
- offset = CURRENT->sector << 9;
- len = CURRENT->current_nr_sectors << 9;
+ offset = CURRENT->sector << RDBLK_SIZE_BITS;
+ len = CURRENT->current_nr_sectors << RDBLK_SIZE_BITS;
if ((offset + len) > rd_length[minor]) {
end_request(0);
goto repeat;
}
+ if ((CURRENT->cmd != READ) && (CURRENT->cmd != WRITE)) {
+ printk(KERN_INFO "RAMDISK: bad command: %d\n", CURRENT->cmd);
+ end_request(0);
+ goto repeat;
+ }
+
/*
* If we're reading, fill the buffer with 0's. This is okay since
* we're using protected buffers which should never get freed...
@@ -158,28 +181,31 @@ repeat:
static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
- int err;
-
+ unsigned int minor;
+
if (!inode || !inode->i_rdev)
return -EINVAL;
+ minor = MINOR(inode->i_rdev);
+
switch (cmd) {
case BLKFLSBUF:
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
invalidate_buffers(inode->i_rdev);
break;
+
case BLKGETSIZE: /* Return device size */
if (!arg) return -EINVAL;
- err = verify_area(VERIFY_WRITE, (long *) arg,
- sizeof(long));
- if (err)
- return err;
- put_user(rd_length[MINOR(inode->i_rdev)] / 512,
- (long *) arg);
- return 0;
-
+ return put_user(rd_length[minor] >> RDBLK_SIZE_BITS, (long *) arg);
+
+ case BLKSSZGET: /* Block size of media */
+ if (!arg) return -EINVAL;
+ return put_user(rd_blocksizes[minor], (int *)arg);
+
+ RO_IOCTLS(inode->i_rdev, arg);
+
default:
- break;
+ return -EINVAL;
};
return 0;
@@ -267,7 +293,7 @@ static struct file_operations fd_fops = {
rd_open, /* open */
NULL, /* flush */
rd_release, /* module needs to decrement use count */
- block_fsync /* fsync */
+ block_fsync /* fsync */
};
/* This is the registration and initialization section of the RAM disk driver */
@@ -283,11 +309,16 @@ __initfunc(int rd_init(void))
blk_dev[MAJOR_NR].request_fn = &rd_request;
for (i = 0; i < NUM_RAMDISKS; i++) {
- rd_length[i] = (rd_size * 1024);
- rd_blocksizes[i] = 1024;
+ /* rd_size is given in kB */
+ rd_length[i] = (rd_size << BLOCK_SIZE_BITS);
+ rd_hardsec[i] = RDBLK_SIZE;
+ rd_blocksizes[i] = BLOCK_SIZE;
+ rd_kbsize[i] = (rd_length[i] >> BLOCK_SIZE_BITS);
}
- blksize_size[MAJOR_NR] = rd_blocksizes;
+ hardsect_size[MAJOR_NR] = rd_hardsec; /* Size of the RAM disk blocks */
+ blksize_size[MAJOR_NR] = rd_blocksizes; /* Avoid set_blocksize() check */
+ blk_size[MAJOR_NR] = rd_kbsize; /* Size of the RAM disk in kB */
printk("RAM disk driver initialized: %d RAM disks of %dK size\n",
NUM_RAMDISKS, rd_size);
@@ -299,6 +330,9 @@ __initfunc(int rd_init(void))
#ifdef MODULE
+MODULE_PARM (rd_size, "1i");
+MODULE_PARM_DESC(rd_size, "Size of each RAM disk.");
+
int init_module(void)
{
int error = rd_init();
@@ -429,7 +463,7 @@ done:
/*
* This routine loads in the RAM disk image.
*/
-__initfunc(static void rd_load_image(kdev_t device,int offset))
+__initfunc(static void rd_load_image(kdev_t device, int offset, int unit))
{
struct inode inode, out_inode;
struct file infile, outfile;
@@ -442,7 +476,7 @@ __initfunc(static void rd_load_image(kdev_t device,int offset))
unsigned short devblocks = 0;
char rotator[4] = { '|' , '/' , '-' , '\\' };
- ram_device = MKDEV(MAJOR_NR, 0);
+ ram_device = MKDEV(MAJOR_NR, unit);
memset(&infile, 0, sizeof(infile));
memset(&inode, 0, sizeof(inode));
@@ -482,9 +516,9 @@ __initfunc(static void rd_load_image(kdev_t device,int offset))
goto done;
}
- if (nblocks > (rd_length[0] >> BLOCK_SIZE_BITS)) {
+ if (nblocks > (rd_length[unit] >> RDBLK_SIZE_BITS)) {
printk("RAMDISK: image too big! (%d/%d blocks)\n",
- nblocks, rd_length[0] >> BLOCK_SIZE_BITS);
+ nblocks, rd_length[unit] >> RDBLK_SIZE_BITS);
goto done;
}
@@ -540,7 +574,7 @@ __initfunc(static void rd_load_image(kdev_t device,int offset))
successful_load:
invalidate_buffers(device);
- ROOT_DEV = MKDEV(MAJOR_NR,0);
+ ROOT_DEV = MKDEV(MAJOR_NR, unit);
done:
if (infile.f_op->release)
@@ -549,12 +583,21 @@ done:
}
-__initfunc(void rd_load(void))
+__initfunc(static void rd_load_disk(int n))
{
+#ifdef CONFIG_BLK_DEV_INITRD
+ extern kdev_t real_root_dev;
+#endif
+
if (rd_doload == 0)
return;
-
- if (MAJOR(ROOT_DEV) != FLOPPY_MAJOR) return;
+
+ if (MAJOR(ROOT_DEV) != FLOPPY_MAJOR
+#ifdef CONFIG_BLK_DEV_INITRD
+ && MAJOR(real_root_dev) != FLOPPY_MAJOR
+#endif
+ )
+ return;
if (rd_prompt) {
#ifdef CONFIG_BLK_DEV_FD
@@ -565,15 +608,24 @@ __initfunc(void rd_load(void))
wait_for_keypress();
}
- rd_load_image(ROOT_DEV,rd_image_start);
+ rd_load_image(ROOT_DEV,rd_image_start, n);
}
+__initfunc(void rd_load(void))
+{
+ rd_load_disk(0);
+}
+
+__initfunc(void rd_load_secondary(void))
+{
+ rd_load_disk(1);
+}
#ifdef CONFIG_BLK_DEV_INITRD
__initfunc(void initrd_load(void))
{
- rd_load_image(MKDEV(MAJOR_NR, INITRD_MINOR),0);
+ rd_load_image(MKDEV(MAJOR_NR, INITRD_MINOR),0,0);
}
#endif
@@ -697,7 +749,14 @@ __initfunc(static int
crd_load(struct file * fp, struct file *outfp))
{
int result;
-
+
+ insize = 0; /* valid bytes in inbuf */
+ inptr = 0; /* index of next byte to be processed in inbuf */
+ outcnt = 0; /* bytes in output buffer */
+ exit_code = 0;
+ bytes_out = 0;
+ crc = (ulg)0xffffffffL; /* shift register contents */
+
crd_infp = fp;
crd_outfp = outfp;
inbuf = kmalloc(INBUFSIZ, GFP_KERNEL);
diff --git a/drivers/block/sl82c105.c b/drivers/block/sl82c105.c
index 6c1d12cb9..7fca7d5d9 100644
--- a/drivers/block/sl82c105.c
+++ b/drivers/block/sl82c105.c
@@ -1,3 +1,4 @@
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/timer.h>
@@ -19,7 +20,6 @@ void ide_init_sl82c105(ide_hwif_t *hwif)
struct pci_dev *dev = hwif->pci_dev;
unsigned short t16;
unsigned int t32;
-
pci_read_config_word(dev, PCI_COMMAND, &t16);
printk("SL82C105 command word: %x\n",t16);
t16 |= PCI_COMMAND_IO;
@@ -28,7 +28,9 @@ void ide_init_sl82c105(ide_hwif_t *hwif)
pci_read_config_dword(dev, 0x44, &t32);
printk("IDE timing: %08x, resetting to PIO0 timing\n",t32);
pci_write_config_dword(dev, 0x44, 0x03e4);
+#ifndef CONFIG_MBX
pci_read_config_dword(dev, 0x40, &t32);
printk("IDE control/status register: %08x\n",t32);
pci_write_config_dword(dev, 0x40, 0x10ff08a1);
+#endif /* CONFIG_MBX */
}
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index 247db08d6..246405aff 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -10,6 +10,12 @@
* 2 of the License, or (at your option) any later version.
*/
+/*
+ * TODO:
+ * handle 2 drives
+ * handle GCR disks
+ */
+
#include <linux/stddef.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -52,18 +58,18 @@ enum swim_state {
*/
struct swim3 {
REG(data);
- REG(usecs); /* counts down at 1MHz */
+ REG(timer); /* counts down at 1MHz */
REG(error);
REG(mode);
REG(select); /* controls CA0, CA1, CA2 and LSTRB signals */
- REG(reg5);
+ REG(setup);
REG(control); /* writing bits clears them */
REG(status); /* writing bits sets them in control */
REG(intr);
REG(nseek); /* # tracks to seek */
REG(ctrack); /* current track number */
REG(csect); /* current sector number */
- REG(ssize); /* sector size code?? */
+ REG(gap3); /* size of gap 3 in track format */
REG(sector); /* sector # to read or write */
REG(nsect); /* # sectors to read or write */
REG(intr_enable);
@@ -78,21 +84,46 @@ struct swim3 {
/* Bits in control register */
#define DO_SEEK 0x80
+#define FORMAT 0x40
#define SELECT 0x20
#define WRITE_SECTORS 0x10
-#define SCAN_TRACK 0x08
+#define DO_ACTION 0x08
+#define DRIVE2_ENABLE 0x04
#define DRIVE_ENABLE 0x02
#define INTR_ENABLE 0x01
/* Bits in status register */
+#define FIFO_1BYTE 0x80
+#define FIFO_2BYTE 0x40
+#define ERROR 0x20
#define DATA 0x08
+#define RDDATA 0x04
+#define INTR_PENDING 0x02
+#define MARK_BYTE 0x01
/* Bits in intr and intr_enable registers */
-#define ERROR 0x20
+#define ERROR_INTR 0x20
#define DATA_CHANGED 0x10
#define TRANSFER_DONE 0x08
#define SEEN_SECTOR 0x04
#define SEEK_DONE 0x02
+#define TIMER_DONE 0x01
+
+/* Bits in error register */
+#define ERR_DATA_CRC 0x80
+#define ERR_ADDR_CRC 0x40
+#define ERR_OVERRUN 0x04
+#define ERR_UNDERRUN 0x01
+
+/* Bits in setup register */
+#define S_SW_RESET 0x80
+#define S_GCR_WRITE 0x40
+#define S_IBM_DRIVE 0x20
+#define S_TEST_MODE 0x10
+#define S_FCLK_DIV2 0x08
+#define S_GCR 0x04
+#define S_COPY_PROT 0x02
+#define S_INV_WDATA 0x01
/* Select values for swim3_action */
#define SEEK_POSITIVE 0
@@ -100,14 +131,18 @@ struct swim3 {
#define STEP 1
#define MOTOR_ON 2
#define MOTOR_OFF 6
+#define INDEX 3
#define EJECT 7
+#define SETMFM 9
+#define SETGCR 13
/* Select values for swim3_select and swim3_readbit */
#define STEP_DIR 0
#define STEPPING 1
#define MOTOR_ON 2
-#define RELAX 3
+#define RELAX 3 /* also eject in progress */
#define READ_DATA_0 4
+#define TWOMEG_DRIVE 5
#define SINGLE_SIDED 6
#define DRIVE_PRESENT 7
#define DISK_IN 8
@@ -115,7 +150,25 @@ struct swim3 {
#define TRACK_ZERO 10
#define TACHO 11
#define READ_DATA_1 12
+#define MFM_MODE 13
#define SEEK_COMPLETE 14
+#define ONEMEG_MEDIA 15
+
+/* Definitions of values used in writing and formatting */
+#define DATA_ESCAPE 0x99
+#define GCR_SYNC_EXC 0x3f
+#define GCR_SYNC_CONV 0x80
+#define GCR_FIRST_MARK 0xd5
+#define GCR_SECOND_MARK 0xaa
+#define GCR_ADDR_MARK "\xd5\xaa\x00"
+#define GCR_DATA_MARK "\xd5\xaa\x0b"
+#define GCR_SLIP_BYTE "\x27\xaa"
+#define GCR_SELF_SYNC "\x3f\xbf\x1e\x34\x3c\x3f"
+
+#define DATA_99 "\x99\x99"
+#define MFM_ADDR_MARK "\x99\xa1\x99\xa1\x99\xa1\x99\xfe"
+#define MFM_INDEX_MARK "\x99\xc2\x99\xc2\x99\xc2\x99\xfc"
+#define MFM_GAP_LEN 12
struct floppy_state {
enum swim_state state;
@@ -153,7 +206,7 @@ static unsigned short write_preamble[] = {
0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, /* gap field */
0, 0, 0, 0, 0, 0, /* sync field */
0x99a1, 0x99a1, 0x99a1, 0x99fb, /* data address mark */
- 0x990f /* init CRC generator */
+ 0x990f /* no escape for 512 bytes */
};
static unsigned short write_postamble[] = {
@@ -217,11 +270,11 @@ static void swim3_action(struct floppy_state *fs, int action)
volatile struct swim3 *sw = fs->swim3;
swim3_select(fs, action);
- udelay(10);
- sw->select |= LSTRB; eieio();
- udelay(20);
- sw->select &= ~LSTRB; eieio();
- udelay(10);
+ udelay(1);
+ out_8(&sw->select, sw->select | LSTRB);
+ udelay(2);
+ out_8(&sw->select, sw->select & ~LSTRB);
+ udelay(1);
out_8(&sw->select, RELAX);
}
@@ -328,9 +381,9 @@ static inline void scan_track(struct floppy_state *fs)
swim3_select(fs, READ_DATA_0);
xx = sw->intr; /* clear SEEN_SECTOR bit */
- out_8(&sw->control_bis, SCAN_TRACK);
+ out_8(&sw->control_bis, DO_ACTION);
/* enable intr when track found */
- out_8(&sw->intr_enable, ERROR | SEEN_SECTOR);
+ out_8(&sw->intr_enable, ERROR_INTR | SEEN_SECTOR);
set_timeout(fs, HZ, scan_timeout); /* enable timeout */
}
@@ -349,7 +402,7 @@ static inline void seek_track(struct floppy_state *fs, int n)
swim3_select(fs, STEP);
out_8(&sw->control_bis, DO_SEEK);
/* enable intr when seek finished */
- out_8(&sw->intr_enable, ERROR | SEEK_DONE);
+ out_8(&sw->intr_enable, ERROR_INTR | SEEK_DONE);
set_timeout(fs, HZ/2, seek_timeout); /* enable timeout */
}
@@ -384,7 +437,7 @@ static inline void setup_transfer(struct floppy_state *fs)
swim3_select(fs, fs->head? READ_DATA_1: READ_DATA_0);
out_8(&sw->sector, fs->req_sector);
out_8(&sw->nsect, n);
- out_8(&sw->ssize, 0);
+ out_8(&sw->gap3, 0);
st_le32(&dr->cmdptr, virt_to_bus(cp));
if (CURRENT->cmd == WRITE) {
/* Set up 3 dma commands: write preamble, data, postamble */
@@ -400,9 +453,9 @@ static inline void setup_transfer(struct floppy_state *fs)
out_le16(&cp->command, DBDMA_STOP);
out_le32(&dr->control, (RUN << 16) | RUN);
out_8(&sw->control_bis,
- (CURRENT->cmd == WRITE? WRITE_SECTORS: 0) | SCAN_TRACK);
+ (CURRENT->cmd == WRITE? WRITE_SECTORS: 0) | DO_ACTION);
/* enable intr when transfer complete */
- out_8(&sw->intr_enable, ERROR | TRANSFER_DONE);
+ out_8(&sw->intr_enable, ERROR_INTR | TRANSFER_DONE);
set_timeout(fs, 2*HZ, xfer_timeout); /* enable timeout */
}
@@ -445,7 +498,7 @@ static void act(struct floppy_state *fs)
/* wait for SEEK_COMPLETE to become true */
swim3_select(fs, SEEK_COMPLETE);
udelay(10);
- out_8(&sw->intr_enable, ERROR | DATA_CHANGED);
+ out_8(&sw->intr_enable, ERROR_INTR | DATA_CHANGED);
in_8(&sw->intr); /* clear DATA_CHANGED */
if (in_8(&sw->status) & DATA) {
/* seek_complete is not yet true */
@@ -487,7 +540,7 @@ static void scan_timeout(unsigned long data)
volatile struct swim3 *sw = fs->swim3;
fs->timeout_pending = 0;
- out_8(&sw->control_bic, SCAN_TRACK);
+ out_8(&sw->control_bic, DO_ACTION);
out_8(&sw->select, RELAX);
out_8(&sw->intr_enable, 0);
fs->cur_cyl = -1;
@@ -537,7 +590,7 @@ static void xfer_timeout(unsigned long data)
fs->timeout_pending = 0;
st_le32(&dr->control, RUN << 16);
out_8(&sw->intr_enable, 0);
- out_8(&sw->control_bic, WRITE_SECTORS | SCAN_TRACK);
+ out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION);
out_8(&sw->select, RELAX);
if (CURRENT->cmd == WRITE)
++cp;
@@ -568,13 +621,13 @@ static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#if 0
printk("swim3 intr state=%d intr=%x err=%x\n", fs->state, intr, err);
#endif
- if ((intr & ERROR) && fs->state != do_transfer)
+ if ((intr & ERROR_INTR) && fs->state != do_transfer)
printk(KERN_ERR "swim3_interrupt, state=%d, cmd=%x, intr=%x, err=%x\n",
fs->state, CURRENT->cmd, intr, err);
switch (fs->state) {
case locating:
if (intr & SEEN_SECTOR) {
- out_8(&sw->control_bic, SCAN_TRACK);
+ out_8(&sw->control_bic, DO_ACTION);
out_8(&sw->select, RELAX);
out_8(&sw->intr_enable, 0);
del_timer(&fs->timeout);
@@ -622,13 +675,13 @@ static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
act(fs);
break;
case do_transfer:
- if ((intr & (ERROR | TRANSFER_DONE)) == 0)
+ if ((intr & (ERROR_INTR | TRANSFER_DONE)) == 0)
break;
dr = fs->dma;
cp = fs->dma_cmd;
st_le32(&dr->control, RUN << 16);
out_8(&sw->intr_enable, 0);
- out_8(&sw->control_bic, WRITE_SECTORS | SCAN_TRACK);
+ out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION);
out_8(&sw->select, RELAX);
del_timer(&fs->timeout);
fs->timeout_pending = 0;
@@ -636,7 +689,7 @@ static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++cp;
stat = ld_le16(&cp->xfer_status);
resid = ld_le16(&cp->res_count);
- if (intr & ERROR) {
+ if (intr & ERROR_INTR) {
n = fs->scount - 1 - resid / 512;
if (n > 0) {
CURRENT->sector += n;
@@ -800,6 +853,8 @@ static int floppy_open(struct inode *inode, struct file *filp)
if (devnum >= floppy_count)
return -ENODEV;
+ if (filp == 0)
+ return -EIO;
fs = &floppy_states[devnum];
sw = fs->swim3;
@@ -809,7 +864,7 @@ static int floppy_open(struct inode *inode, struct file *filp)
return -ENXIO;
out_8(&sw->mode, 0x95);
out_8(&sw->control_bic, 0xff);
- out_8(&sw->reg5, 0x28);
+ out_8(&sw->setup, S_IBM_DRIVE | S_FCLK_DIV2);
udelay(10);
out_8(&sw->intr_enable, 0);
out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE);
@@ -834,14 +889,14 @@ static int floppy_open(struct inode *inode, struct file *filp)
} else if (fs->ref_count == -1 || filp->f_flags & O_EXCL)
return -EBUSY;
- if (err == 0 && filp && (filp->f_flags & O_NDELAY) == 0
+ if (err == 0 && (filp->f_flags & O_NDELAY) == 0
&& (filp->f_mode & 3)) {
check_disk_change(inode->i_rdev);
if (fs->ejected)
err = -ENXIO;
}
- if (err == 0 && filp && (filp->f_flags & (O_WRONLY | O_RDWR))) {
+ if (err == 0 && (filp->f_mode & 2)) {
if (fs->write_prot < 0)
fs->write_prot = swim3_readbit(fs, WRITE_PROT);
if (fs->write_prot)
@@ -977,10 +1032,14 @@ static ssize_t floppy_write(struct file * filp, const char * buf,
if (devnum >= floppy_count)
return -ENODEV;
-
+ check_disk_change(inode->i_rdev);
fs = &floppy_states[devnum];
if (fs->ejected)
return -ENXIO;
+ if (fs->write_prot < 0)
+ fs->write_prot = swim3_readbit(fs, WRITE_PROT);
+ if (fs->write_prot)
+ return -EROFS;
return block_write(filp, buf, count, ppos);
}