summaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-08-25 09:12:35 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-08-25 09:12:35 +0000
commitc7fc24dc4420057f103afe8fc64524ebc25c5d37 (patch)
tree3682407a599b8f9f03fc096298134cafba1c9b2f /drivers/block
parent1d793fade8b063fde3cf275bf1a5c2d381292cd9 (diff)
o Merge with Linux 2.1.116.
o New Newport console code. o New G364 console code.
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/Config.in39
-rw-r--r--drivers/block/Makefile95
-rw-r--r--drivers/block/README.fd6
-rw-r--r--drivers/block/acsi.c6
-rw-r--r--drivers/block/amiflop.c4
-rw-r--r--drivers/block/ataflop.c216
-rw-r--r--drivers/block/cmd646.c236
-rw-r--r--drivers/block/floppy.c57
-rw-r--r--drivers/block/genhd.c48
-rw-r--r--drivers/block/hd.c14
-rw-r--r--drivers/block/ht6560b.c6
-rw-r--r--drivers/block/ide-cd.c32
-rw-r--r--drivers/block/ide-cd.h4
-rw-r--r--drivers/block/ide-disk.c2
-rw-r--r--drivers/block/ide-dma.c2
-rw-r--r--drivers/block/ide-floppy.c14
-rw-r--r--drivers/block/ide-pci.c32
-rw-r--r--drivers/block/ide-probe.c23
-rw-r--r--drivers/block/ide.c213
-rw-r--r--drivers/block/ide.h13
-rw-r--r--drivers/block/ll_rw_blk.c83
-rw-r--r--drivers/block/loop.c254
-rw-r--r--drivers/block/md.c154
-rw-r--r--drivers/block/nbd.c35
-rw-r--r--drivers/block/ns87415.c13
-rw-r--r--drivers/block/paride/Config.in4
-rw-r--r--drivers/block/paride/Makefile33
-rw-r--r--drivers/block/paride/aten.c20
-rw-r--r--drivers/block/paride/bpck.c30
-rw-r--r--drivers/block/paride/comm.c20
-rw-r--r--drivers/block/paride/dstr.c20
-rw-r--r--drivers/block/paride/epat.c20
-rw-r--r--drivers/block/paride/epia.c24
-rw-r--r--drivers/block/paride/fit2.c161
-rw-r--r--drivers/block/paride/fit3.c221
-rw-r--r--drivers/block/paride/frpw.c94
-rw-r--r--drivers/block/paride/kbic.c24
-rw-r--r--drivers/block/paride/ktti.c138
-rw-r--r--drivers/block/paride/mkd30
-rw-r--r--drivers/block/paride/on20.c20
-rw-r--r--drivers/block/paride/on26.c20
-rw-r--r--drivers/block/paride/paride.c57
-rw-r--r--drivers/block/paride/paride.h17
-rw-r--r--drivers/block/paride/pcd.c91
-rw-r--r--drivers/block/paride/pd.c186
-rw-r--r--drivers/block/paride/pf.c127
-rw-r--r--drivers/block/paride/pg.c691
-rw-r--r--drivers/block/paride/pseudo.h41
-rw-r--r--drivers/block/paride/pt.c45
-rw-r--r--drivers/block/paride/setup.h23
-rw-r--r--drivers/block/raid0.c2
-rw-r--r--drivers/block/raid1.c6
-rw-r--r--drivers/block/raid5.c12
-rw-r--r--drivers/block/rd.c63
-rw-r--r--drivers/block/sl82c105.c6
-rw-r--r--drivers/block/swim3.c103
-rw-r--r--drivers/block/trm290.c2
-rw-r--r--drivers/block/xd.c8
58 files changed, 3016 insertions, 944 deletions
diff --git a/drivers/block/Config.in b/drivers/block/Config.in
index dffd31d91..86208ba98 100644
--- a/drivers/block/Config.in
+++ b/drivers/block/Config.in
@@ -2,13 +2,20 @@
# Block device driver configuration
#
mainmenu_option next_comment
-comment 'Floppy, IDE, and other block devices'
+comment 'Block devices'
+
+tristate 'Normal PC floppy disk support' CONFIG_BLK_DEV_FD
+if [ "$CONFIG_AMIGA" = "y" ]; then
+ tristate 'Amiga floppy support' CONFIG_AMIGA_FLOPPY
+fi
+if [ "$CONFIG_ATARI" = "y" ]; then
+ tristate 'Atari floppy support' CONFIG_ATARI_FLOPPY
+fi
-tristate 'Normal floppy disk support' CONFIG_BLK_DEV_FD
tristate 'Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support' CONFIG_BLK_DEV_IDE
comment 'Please see Documentation/ide.txt for help/info on IDE drives'
if [ "$CONFIG_BLK_DEV_IDE" = "n" ]; then
- bool 'Old harddisk (MFM/RLL/IDE) driver' CONFIG_BLK_DEV_HD_ONLY
+ bool 'Old hard disk (MFM/RLL/IDE) driver' CONFIG_BLK_DEV_HD_ONLY
else
bool ' Use old disk-only driver on primary interface' CONFIG_BLK_DEV_HD_IDE
dep_tristate ' Include IDE/ATA-2 DISK support' CONFIG_BLK_DEV_IDEDISK $CONFIG_BLK_DEV_IDE
@@ -16,7 +23,7 @@ else
dep_tristate ' Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE $CONFIG_BLK_DEV_IDE
dep_tristate ' Include IDE/ATAPI FLOPPY support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_BLK_DEV_IDE
dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE
- if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then
+ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
bool ' CMD640 chipset bugfix/support' CONFIG_BLK_DEV_CMD640
if [ "$CONFIG_BLK_DEV_CMD640" = "y" ]; then
bool ' CMD640 enhanced support' CONFIG_BLK_DEV_CMD640_ENHANCED
@@ -26,6 +33,9 @@ else
bool ' Generic PCI IDE chipset support' CONFIG_BLK_DEV_IDEPCI
if [ "$CONFIG_BLK_DEV_IDEPCI" = "y" ]; then
bool ' Generic PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA
+ if [ "$CONFIG_BLK_DEV_IDEDMA" = "y" ]; then
+ bool ' Use DMA by default when available' CONFIG_IDEDMA_AUTO
+ fi
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
bool ' OPTi 82C621 chipset enhanced support (EXPERIMENTAL)' CONFIG_BLK_DEV_OPTI621
if [ "$CONFIG_BLK_DEV_IDEDMA" = "y" ]; then
@@ -34,7 +44,7 @@ else
fi
fi
fi
- if [ "$CONFIG_CHRP" = "y" ]; then
+ if [ "$CONFIG_PPC" = "y" ]; then
bool ' WInbond SL82c105 support' CONFIG_BLK_DEV_SL82C105
fi
fi
@@ -48,19 +58,32 @@ else
bool ' QDI QD6580 support' CONFIG_BLK_DEV_QD6580
bool ' UMC-8672 support' CONFIG_BLK_DEV_UMC8672
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then
bool ' PROMISE DC4030 support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC4030
+ fi
fi
fi
fi
fi
if [ "$CONFIG_MCA" = "y" ]; then
- bool 'PS/2 ESDI harddisk support' CONFIG_BLK_DEV_PS2
+ bool 'PS/2 ESDI hard disk support' CONFIG_BLK_DEV_PS2
+fi
+if [ "$CONFIG_ZORRO" = "y" ]; then
+ tristate 'Amiga Zorro II ramdisk support' CONFIG_AMIGA_Z2RAM
+fi
+if [ "$CONFIG_ATARI" = "y" ]; then
+ tristate 'Atari ACSI support' CONFIG_ATARI_ACSI
+ if [ "$CONFIG_ATARI_ACSI" != "n" ]; then
+ comment 'Some devices (e.g. CD jukebox) support multiple LUNs'
+ bool 'Probe all LUNs on each ACSI device' CONFIG_ACSI_MULTI_LUN
+ dep_tristate 'Atari SLM laser printer support' CONFIG_ATARI_SLM $CONFIG_ATARI_ACSI
+ fi
fi
comment 'Additional Block Devices'
tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
-#tristate 'Network block device support' CONFIG_BLK_DEV_NBD
+tristate 'Network block device support' CONFIG_BLK_DEV_NBD
bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD
if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then
tristate ' Linear (append) mode' CONFIG_MD_LINEAR
@@ -75,7 +98,7 @@ tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then
bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD
fi
-tristate 'XT harddisk support' CONFIG_BLK_DEV_XD
+tristate 'XT hard disk support' CONFIG_BLK_DEV_XD
# PARIDE doesn't need PARPORT, but if PARPORT is configured as a module,
# PARIDE must also be a module. The bogus CONFIG_PARIDE_PARPORT option
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 3fd1526e4..f3543db2e 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -38,6 +38,22 @@ else
endif
endif
+ifeq ($(CONFIG_AMIGA_FLOPPY),y)
+ L_OBJS += amiflop.o
+else
+ ifeq ($(CONFIG_AMIGA_FLOPPY),m)
+ M_OBJS += amiflop.o
+ endif
+endif
+
+ifeq ($(CONFIG_ATARI_FLOPPY),y)
+ L_OBJS += ataflop.o
+else
+ ifeq ($(CONFIG_ATARI_FLOPPY),m)
+ M_OBJS += ataflop.o
+ endif
+endif
+
ifeq ($(CONFIG_ATARI_ACSI),y)
LX_OBJS += acsi.o
else
@@ -82,87 +98,86 @@ ifeq ($(CONFIG_BLK_DEV_HD),y)
L_OBJS += hd.o
endif
-ifeq ($(CONFIG_BLK_DEV_IDE),y)
- LX_OBJS += ide.o
- ifeq ($(CONFIG_PROC_FS),y)
- L_OBJS += ide-proc.o
- endif
- L_OBJS += ide-probe.o
-else
- ifeq ($(CONFIG_BLK_DEV_IDE),m)
- MIX_OBJS += ide.o
- ifeq ($(CONFIG_PROC_FS),y)
- M_OBJS += ide-proc.o
- endif
- M_OBJS += ide-mod.o
- MX_OBJS += ide-probe.o
- endif
-endif
-
ifeq ($(CONFIG_BLK_DEV_RZ1000),y)
-L_OBJS += rz1000.o
+IDE_OBJS += rz1000.o
endif
ifeq ($(CONFIG_BLK_DEV_CMD640),y)
-L_OBJS += cmd640.o
+IDE_OBJS += cmd640.o
endif
ifeq ($(CONFIG_BLK_DEV_IDEPCI),y)
-L_OBJS += ide-pci.o
+IDE_OBJS += ide-pci.o
endif
ifeq ($(CONFIG_BLK_DEV_IDEDMA),y)
-L_OBJS += ide-dma.o
-endif
-
-ifeq ($(CONFIG_BLK_DEV_PS2),y)
-L_OBJS += ps2esdi.o
+IDE_OBJS += ide-dma.o
endif
ifeq ($(CONFIG_BLK_DEV_DTC2278),y)
-L_OBJS += dtc2278.o
+IDE_OBJS += dtc2278.o
endif
ifeq ($(CONFIG_BLK_DEV_HT6560B),y)
-L_OBJS += ht6560b.o
+IDE_OBJS += ht6560b.o
endif
ifeq ($(CONFIG_BLK_DEV_QD6580),y)
-L_OBJS += qd6580.o
+IDE_OBJS += qd6580.o
endif
ifeq ($(CONFIG_BLK_DEV_UMC8672),y)
-L_OBJS += umc8672.o
+IDE_OBJS += umc8672.o
endif
ifeq ($(CONFIG_BLK_DEV_ALI14XX),y)
-L_OBJS += ali14xx.o
+IDE_OBJS += ali14xx.o
endif
ifeq ($(CONFIG_BLK_DEV_PDC4030),y)
-L_OBJS += pdc4030.o
+IDE_OBJS += pdc4030.o
endif
ifeq ($(CONFIG_BLK_DEV_TRM290),y)
-L_OBJS += trm290.o
+IDE_OBJS += trm290.o
endif
ifeq ($(CONFIG_BLK_DEV_OPTI621),y)
-L_OBJS += opti621.o
+IDE_OBJS += opti621.o
endif
ifeq ($(CONFIG_BLK_DEV_NS87415),y)
-L_OBJS += ns87415.o
+IDE_OBJS += ns87415.o
endif
ifeq ($(CONFIG_BLK_DEV_CMD646),y)
-L_OBJS += cmd646.o
+IDE_OBJS += cmd646.o
endif
ifeq ($(CONFIG_BLK_DEV_SL82C105),y)
-L_OBJS += sl82c105.o
+IDE_OBJS += sl82c105.o
+endif
+
+### if CONFIG_BLK_DEV_IDE is n, IDE_OBJS will be ignored
+
+ifeq ($(CONFIG_PROC_FS),y)
+IDE_OBJS += ide-proc.o
+endif
+
+###Collect
+
+ifeq ($(CONFIG_BLK_DEV_IDE),y)
+ LX_OBJS += ide.o
+ L_OBJS += ide-probe.o $(IDE_OBJS)
+else
+ ifeq ($(CONFIG_BLK_DEV_IDE),m)
+ MIX_OBJS += ide.o $(IDE_OBJS)
+ M_OBJS += ide-mod.o ide-probe.o
+ endif
endif
+############
+
ifeq ($(CONFIG_BLK_DEV_IDEDISK),y)
L_OBJS += ide-disk.o
else
@@ -195,6 +210,10 @@ else
endif
endif
+ifeq ($(CONFIG_BLK_DEV_PS2),y)
+L_OBJS += ps2esdi.o
+endif
+
ifeq ($(CONFIG_BLK_DEV_XD),y)
L_OBJS += xd.o
else
@@ -259,5 +278,5 @@ endif
include $(TOPDIR)/Rules.make
-ide-mod.o: ide.o ide-proc.o
- $(LD) $(LD_RFLAG) -r -o $@ ide.o ide-proc.o
+ide-mod.o: ide.o $(IDE_OBJS)
+ $(LD) $(LD_RFLAG) -r -o $@ ide.o $(IDE_OBJS)
diff --git a/drivers/block/README.fd b/drivers/block/README.fd
index e34fa9f86..b750c89cf 100644
--- a/drivers/block/README.fd
+++ b/drivers/block/README.fd
@@ -7,8 +7,8 @@ FAQ list:
at http://poboxes.com/Alain.Knaff/floppy/FAQ.html
-Lilo config options (Thinkpad users, read this)
-===============================================
+LILO configuration options (Thinkpad users, read this)
+======================================================
The floppy driver is configured using the 'floppy=' option in
lilo. This option can be typed at the boot prompt, or entered in the
@@ -104,7 +104,7 @@ isn't, use the old method using environment variables.
floppy=nofifo
Disables the FIFO entirely. This is needed if you get "Bus
- master arbitration error" messages from your ethernet card (or
+ master arbitration error" messages from your Ethernet card (or
from other devices) while accessing the floppy.
floppy=fifo
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index 432276973..3594eb189 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -39,7 +39,7 @@
* knows the PREVENT/ALLOW MEDIUM REMOVAL command, the door should
* be locked and unlocked when mounting the first or unmounting the
* last filesystem on the device. The code is untested, because I
- * don't have a removable harddisk.
+ * don't have a removable hard disk.
*
*/
@@ -147,7 +147,7 @@ struct acsi_info_struct {
#define TYPE_NO_LUN 0x7f
/* The data returned by MODE SENSE differ between the old Atari
- * harddisks and SCSI disks connected to ACSI. In the following, both
+ * hard disks and SCSI disks connected to ACSI. In the following, both
* formats are defined and some macros to operate on them potably.
*/
@@ -1851,7 +1851,7 @@ void cleanup_module(void)
if (unregister_blkdev( MAJOR_NR, "ad" ) != 0)
printk( KERN_ERR "acsi: cleanup_module failed\n");
-
+
for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next))
if (*gdp == &acsi_gendisk)
break;
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 4cdcc28a3..afee4899e 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -68,11 +68,11 @@
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/amifdreg.h>
+#include <linux/amifd.h>
#include <asm/setup.h>
#include <asm/uaccess.h>
-#include <asm/amifdreg.h>
-#include <asm/amifd.h>
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#include <asm/irq.h>
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 7a92f74a2..640ddfd3a 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -344,16 +344,10 @@ static unsigned int changed_floppies = 0xff, fake_change = 0;
} while(0)
#define START_TIMEOUT() \
- do { \
- del_timer( &timeout_timer ); \
- timeout_timer.expires = jiffies + FLOPPY_TIMEOUT; \
- add_timer( &timeout_timer ); \
- } while(0)
+ mod_timer(&timeout_timer, jiffies + FLOPPY_TIMEOUT)
#define STOP_TIMEOUT() \
- do { \
- del_timer( &timeout_timer ); \
- } while(0)
+ del_timer(&timeout_timer)
/*
@@ -1409,27 +1403,25 @@ static int check_floppy_change (kdev_t dev)
static int floppy_revalidate (kdev_t dev)
{
- int drive = MINOR(dev) & 3;
-
- if (test_bit (drive, &changed_floppies) || test_bit (drive, &fake_change)
- || unit[drive].disktype == 0)
- {
- if (UD.flags & FTD_MSG)
- printk (KERN_ERR "floppy: clear format %p!\n", UDT);
- BufferDrive = -1;
- clear_bit (drive, &fake_change);
- clear_bit (drive, &changed_floppies);
- /*
- * MSch: clearing geometry makes sense only for autoprobe formats,
- * for 'permanent user-defined' parameter: restore default_params[]
- * here if flagged valid!
- */
- if (default_params[drive].blocks == 0)
- UDT = 0;
- else
- UDT = &default_params[drive];
- }
- return 0;
+ int drive = MINOR(dev) & 3;
+
+ if (test_bit(drive, &changed_floppies) ||
+ test_bit(drive, &fake_change) ||
+ unit[drive].disktype == 0) {
+ if (UD.flags & FTD_MSG)
+ printk(KERN_ERR "floppy: clear format %p!\n", UDT);
+ BufferDrive = -1;
+ clear_bit(drive, &fake_change);
+ clear_bit(drive, &changed_floppies);
+ /* MSch: clearing geometry makes sense only for autoprobe
+ formats, for 'permanent user-defined' parameter:
+ restore default_params[] here if flagged valid! */
+ if (default_params[drive].blocks == 0)
+ UDT = 0;
+ else
+ UDT = &default_params[drive];
+ }
+ return 0;
}
static __inline__ void copy_buffer(void *from, void *to)
@@ -1566,14 +1558,13 @@ void do_fd_request(void)
}
-static int
-invalidate_drive (kdev_t rdev)
+static int invalidate_drive(kdev_t rdev)
{
- /* invalidate the buffer track to force a reread */
- BufferDrive = -1;
- set_bit (MINOR(rdev) & 3, &fake_change);
- check_disk_change (rdev);
- return 0;
+ /* invalidate the buffer track to force a reread */
+ BufferDrive = -1;
+ set_bit(MINOR(rdev) & 3, &fake_change);
+ check_disk_change(rdev);
+ return 0;
}
static int fd_ioctl(struct inode *inode, struct file *filp,
@@ -1728,30 +1719,30 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
/* no matching disk type found above - setting user_params */
if (cmd == FDDEFPRM) {
- /* set permanent type */
- dtp = &default_params[drive];
+ /* set permanent type */
+ dtp = &default_params[drive];
} else
- /* set user type (reset by disk change!) */
- dtp = &user_params[drive];
+ /* set user type (reset by disk change!) */
+ dtp = &user_params[drive];
dtp->name = "user format";
dtp->blocks = setprm.size;
dtp->spt = setprm.sect;
if (setprm.sect > 14)
- dtp->fdc_speed = 3;
+ dtp->fdc_speed = 3;
else
- dtp->fdc_speed = 0;
+ dtp->fdc_speed = 0;
dtp->stretch = setprm.stretch;
if (UD.flags & FTD_MSG)
- printk (KERN_INFO "floppy%d: blk %d spt %d str %d!\n",
- drive, dtp->blocks, dtp->spt, dtp->stretch);
+ printk (KERN_INFO "floppy%d: blk %d spt %d str %d!\n",
+ drive, dtp->blocks, dtp->spt, dtp->stretch);
/* sanity check */
- if (!dtp || setprm.track != dtp->blocks/dtp->spt/2
- || setprm.head != 2) {
+ if (!dtp || setprm.track != dtp->blocks/dtp->spt/2 ||
+ setprm.head != 2) {
redo_fd_request();
- return -EINVAL;
+ return -EINVAL;
}
UDT = dtp;
@@ -1782,7 +1773,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
return invalidate_drive (device);
case FDFMTEND:
case FDFLUSH:
- return invalidate_drive (drive);
+ return invalidate_drive(device);
}
return -EINVAL;
}
@@ -1925,70 +1916,68 @@ __initfunc(static void config_types( void ))
static int floppy_open( struct inode *inode, struct file *filp )
{
- int drive, type;
- int old_dev;
-
- if (!filp)
- {
- DPRINT (("Weird, open called with filp=0\n"));
- return -EIO;
- }
-
- drive = MINOR (inode->i_rdev) & 3;
- type = MINOR(inode->i_rdev) >> 2;
- DPRINT(("fd_open: type=%d\n",type));
- if (drive >= FD_MAX_UNITS || type > NUM_DISK_MINORS)
- return -ENXIO;
-
- old_dev = fd_device[drive];
-
- if (fd_ref[drive])
- if (old_dev != inode->i_rdev)
- return -EBUSY;
-
- if (fd_ref[drive] == -1 || (fd_ref[drive] && filp->f_flags & O_EXCL))
- return -EBUSY;
-
- if (filp->f_flags & O_EXCL)
- fd_ref[drive] = -1;
- else
- fd_ref[drive]++;
-
- fd_device[drive] = inode->i_rdev;
-
- if (old_dev && old_dev != inode->i_rdev)
- invalidate_buffers(old_dev);
-
- /* Allow ioctls if we have write-permissions even if read-only open */
- if (filp->f_mode & 2 || permission (inode, 2) == 0)
- filp->f_mode |= IOCTL_MODE_BIT;
- if (filp->f_mode & 2)
- filp->f_mode |= OPEN_WRITE_BIT;
-
- MOD_INC_USE_COUNT;
-
- if (filp->f_flags & O_NDELAY)
- return 0;
-
- if (filp->f_mode & 3) {
- check_disk_change( inode->i_rdev );
- if (filp->f_mode & 2) {
- if (UD.wpstat) {
- floppy_release(inode, filp);
- return -EROFS;
- }
- }
- }
+ int drive, type;
+ int old_dev;
+
+ if (!filp) {
+ DPRINT (("Weird, open called with filp=0\n"));
+ return -EIO;
+ }
+
+ drive = MINOR(inode->i_rdev) & 3;
+ type = MINOR(inode->i_rdev) >> 2;
+ DPRINT(("fd_open: type=%d\n",type));
+ if (drive >= FD_MAX_UNITS || type > NUM_DISK_MINORS)
+ return -ENXIO;
+
+ old_dev = fd_device[drive];
- return 0;
+ if (fd_ref[drive] && old_dev != MINOR(inode->i_rdev))
+ return -EBUSY;
+
+ if (fd_ref[drive] == -1 || (fd_ref[drive] && filp->f_flags & O_EXCL))
+ return -EBUSY;
+
+ MOD_INC_USE_COUNT;
+
+ if (filp->f_flags & O_EXCL)
+ fd_ref[drive] = -1;
+ else
+ fd_ref[drive]++;
+
+ fd_device[drive] = MINOR(inode->i_rdev);
+
+ if (old_dev && old_dev != MINOR(inode->i_rdev))
+ invalidate_buffers(MKDEV(FLOPPY_MAJOR, old_dev));
+
+ /* Allow ioctls if we have write-permissions even if read-only open */
+ if (filp->f_mode & 2 || permission (inode, 2) == 0)
+ filp->f_mode |= IOCTL_MODE_BIT;
+ if (filp->f_mode & 2)
+ filp->f_mode |= OPEN_WRITE_BIT;
+
+ if (filp->f_flags & O_NDELAY)
+ return 0;
+
+ if (filp->f_mode & 3) {
+ check_disk_change(inode->i_rdev);
+ if (filp->f_mode & 2) {
+ if (UD.wpstat) {
+ floppy_release(inode, filp);
+ return -EROFS;
+ }
+ }
+ }
+
+ return 0;
}
static int floppy_release( struct inode * inode, struct file * filp )
{
- int drive;
+ int drive;
- drive = inode->i_rdev & 3;
+ drive = MINOR(inode->i_rdev) & 3;
/*
* If filp is NULL, we're being called from blkdev_release
@@ -1999,16 +1988,15 @@ static int floppy_release( struct inode * inode, struct file * filp )
if (filp && (filp->f_mode & (2 | OPEN_WRITE_BIT)))
block_fsync (filp, filp->f_dentry);
- if (fd_ref[drive] < 0)
- fd_ref[drive] = 0;
- else if (!fd_ref[drive]--)
- {
- printk(KERN_ERR "floppy_release with fd_ref == 0");
- fd_ref[drive] = 0;
- }
+ if (fd_ref[drive] < 0)
+ fd_ref[drive] = 0;
+ else if (!fd_ref[drive]--) {
+ printk(KERN_ERR "floppy_release with fd_ref == 0");
+ fd_ref[drive] = 0;
+ }
- MOD_DEC_USE_COUNT;
- return 0;
+ MOD_DEC_USE_COUNT;
+ return 0;
}
static struct file_operations floppy_fops = {
diff --git a/drivers/block/cmd646.c b/drivers/block/cmd646.c
index aa9248cbd..fe2eb10a2 100644
--- a/drivers/block/cmd646.c
+++ b/drivers/block/cmd646.c
@@ -1,20 +1,248 @@
-/* $Id: cmd646.c,v 1.1 1998/03/15 13:29:10 ecd Exp $
- * cmd646.c: Enable interrupts at initialization time on Ultra/PCI machines
+/* $Id: cmd646.c,v 1.10 1998/08/03 15:28:42 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.
+ * Due to massive hardware bugs, UltraDMA is only supported
+ * on the 646U2 and not on the 646U.
*
* Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
+ * Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com)
*/
+#include <linux/types.h>
#include <linux/pci.h>
+#include <linux/delay.h>
+#include <asm/io.h>
#include "ide.h"
+static int cmd646_config_drive_for_dma(ide_drive_t *drive)
+{
+ struct hd_driveid *id = drive->id;
+ ide_hwif_t *hwif = HWIF(drive);
+
+ /* Even if the drive is not _currently_ in a DMA
+ * mode, we succeed, and we'll enable it manually
+ * below in cmd646_dma_onoff.
+ *
+ * This is done for disks only, CDROMs and other
+ * IDE devices are just too quirky.
+ */
+ if((id != NULL) &&
+ ((id->capability & 1) != 0) &&
+ hwif->autodma &&
+ (drive->media == ide_disk)) {
+ if(id->field_valid & 0x0004) {
+ if(id->dma_ultra & 0x0007)
+ return hwif->dmaproc(ide_dma_on, drive);
+ }
+ if(id->field_valid & 0x0002)
+ if((id->dma_mword & 0x0004) || (id->dma_1word & 0x0004))
+ return hwif->dmaproc(ide_dma_on, drive);
+ }
+ return hwif->dmaproc(ide_dma_off_quietly, drive);
+}
+
+/* This is fun. -DaveM */
+#define IDE_SETXFER 0x03
+#define IDE_SETFEATURE 0xef
+#define IDE_DMA2_ENABLE 0x22
+#define IDE_DMA1_ENABLE 0x21
+#define IDE_DMA0_ENABLE 0x20
+#define IDE_UDMA2_ENABLE 0x42
+#define IDE_UDMA1_ENABLE 0x41
+#define IDE_UDMA0_ENABLE 0x40
+
+static __inline__ unsigned char dma2_bits_to_command(unsigned char bits)
+{
+ if(bits & 0x04)
+ return IDE_DMA2_ENABLE;
+ if(bits & 0x02)
+ return IDE_DMA1_ENABLE;
+ return IDE_DMA0_ENABLE;
+}
+
+static __inline__ unsigned char udma2_bits_to_command(unsigned char bits)
+{
+ if(bits & 0x04)
+ return IDE_UDMA2_ENABLE;
+ if(bits & 0x02)
+ return IDE_UDMA1_ENABLE;
+ return IDE_UDMA0_ENABLE;
+}
+
+static __inline__ int wait_for_ready(ide_drive_t *drive)
+{
+ int timeout = 100;
+ byte stat;
+
+ while(--timeout) {
+ stat = GET_STAT();
+
+ printk("STAT(%2x) ", stat);
+ if(!(stat & BUSY_STAT)) {
+ if((stat & READY_STAT) || (stat & ERR_STAT))
+ break;
+ }
+ udelay(100);
+ }
+ if((stat & ERR_STAT) || timeout <= 0)
+ return 1;
+ return 0;
+}
+
+static void cmd646_do_setfeature(ide_drive_t *drive, byte command)
+{
+ unsigned long flags;
+ byte old_select;
+
+ save_flags(flags);
+ cli();
+ printk("SELECT ");
+ old_select = IN_BYTE(IDE_SELECT_REG);
+ OUT_BYTE(drive->select.all, IDE_SELECT_REG);
+ printk("SETXFER ");
+ OUT_BYTE(IDE_SETXFER, IDE_FEATURE_REG);
+ printk("CMND ");
+ OUT_BYTE(command, IDE_NSECTOR_REG);
+ printk("wait ");
+ if(wait_for_ready(drive))
+ goto out;
+ printk("SETFEATURE ");
+ OUT_BYTE(IDE_SETFEATURE, IDE_COMMAND_REG);
+ printk("wait ");
+ (void) wait_for_ready(drive);
+out:
+ OUT_BYTE(old_select, IDE_SELECT_REG);
+ restore_flags(flags);
+}
+
+static void cmd646_dma2_enable(ide_drive_t *drive, unsigned long dma_base)
+{
+ byte unit = (drive->select.b.unit & 0x01);
+ byte bits = (drive->id->dma_mword | drive->id->dma_1word) & 0x07;
+
+ printk("CMD646: MDMA enable [");
+ if((((drive->id->dma_mword & 0x0007) << 8) !=
+ (drive->id->dma_mword & 0x0700)))
+ cmd646_do_setfeature(drive, dma2_bits_to_command(bits));
+ printk("DMA_CAP ");
+ outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
+ printk("DONE]\n");
+}
+
+static void cmd646_udma_enable(ide_drive_t *drive, unsigned long dma_base)
+{
+ byte unit = (drive->select.b.unit & 0x01);
+ byte udma_ctrl, bits = drive->id->dma_ultra & 0x07;
+ byte udma_timing_bits;
+
+ printk("CMD646: UDMA enable [");
+ if(((drive->id->dma_ultra & 0x0007) << 8) !=
+ (drive->id->dma_ultra & 0x0700))
+ cmd646_do_setfeature(drive, udma2_bits_to_command(bits));
+
+ /* Enable DMA and UltraDMA */
+ printk("DMA_CAP ");
+ outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
+
+ udma_ctrl = inb(dma_base + 3);
+
+ /* Put this channel into UDMA mode. */
+ printk("UDMA_CTRL ");
+ udma_ctrl |= (1 << unit);
+
+ /* Set UDMA2 usable timings. */
+ if(bits & 0x04)
+ udma_timing_bits = 0x10;
+ else if(bits & 0x02)
+ udma_timing_bits = 0x20;
+ else
+ udma_timing_bits = 0x30;
+ udma_ctrl &= ~(0x30 << (unit * 2));
+ udma_ctrl |= (udma_timing_bits << (unit * 2));
+
+ outb(udma_ctrl, dma_base+3);
+ printk("DONE]\n");
+}
+
+static int cmd646_dma_onoff(ide_drive_t *drive, int enable)
+{
+ if(enable) {
+ ide_hwif_t *hwif = HWIF(drive);
+ unsigned long dma_base = hwif->dma_base;
+ struct hd_driveid *id = drive->id;
+ unsigned int class_rev;
+
+ /* UltraDMA only supported on PCI646U and PCI646U2,
+ * which correspond to revisions 0x03 and 0x05 respectively.
+ * Actually, although the CMD tech support people won't
+ * tell me the details, the 0x03 revision cannot support
+ * UDMA correctly without hardware modifications, and even
+ * then it only works with Quantum disks due to some
+ * hold time assumptions in the 646U part which are fixed
+ * in the 646U2.
+ * So we only do UltraDMA on revision 0x05 chipsets.
+ */
+ pci_read_config_dword(hwif->pci_dev,
+ PCI_CLASS_REVISION,
+ &class_rev);
+ class_rev &= 0xff;
+ if((class_rev == 0x05) &&
+ (id->field_valid & 0x0004) &&
+ (id->dma_ultra & 0x07)) {
+ /* UltraDMA modes. */
+ cmd646_udma_enable(drive, dma_base);
+ } else {
+ /* Normal MultiWord DMA modes. */
+ cmd646_dma2_enable(drive, dma_base);
+ }
+ }
+ drive->using_dma = enable;
+ return 0;
+}
+
+static int cmd646_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
+{
+ if(func == ide_dma_check)
+ return cmd646_config_drive_for_dma(drive);
+ else if(func == ide_dma_on || func == ide_dma_off || func == ide_dma_off_quietly)
+ return cmd646_dma_onoff(drive, (func == ide_dma_on));
+
+ /* Other cases are done by generic IDE-DMA code. */
+ return ide_dmaproc(func, drive);
+}
+
__initfunc(void ide_init_cmd646 (ide_hwif_t *hwif))
{
-#ifdef __sparc_v9__
struct pci_dev *dev = hwif->pci_dev;
unsigned char mrdmode;
+ hwif->chipset = ide_cmd646;
+
+ /* Set a good latency timer value. */
+ (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 240);
+
+ /* Setup interrupts. */
(void) pci_read_config_byte(dev, 0x71, &mrdmode);
mrdmode &= ~(0x30);
(void) pci_write_config_byte(dev, 0x71, mrdmode);
-#endif
+
+ /* Use MEMORY READ LINE for reads.
+ * NOTE: Although not mentioned in the PCI0646U specs,
+ * these bits are write only and won't be read
+ * back as set or not. The PCI0646U2 specs clarify
+ * this point.
+ */
+ (void) pci_write_config_byte(dev, 0x71, mrdmode | 0x02);
+
+ /* Set reasonable active/recovery/address-setup values. */
+ (void) pci_write_config_byte(dev, 0x53, 0x40);
+ (void) pci_write_config_byte(dev, 0x54, 0x3f);
+ (void) pci_write_config_byte(dev, 0x55, 0x40);
+ (void) pci_write_config_byte(dev, 0x56, 0x3f);
+ (void) pci_write_config_byte(dev, 0x57, 0x5c);
+ (void) pci_write_config_byte(dev, 0x58, 0x3f);
+ (void) pci_write_config_byte(dev, 0x5b, 0x3f);
+
+ hwif->dmaproc = &cmd646_dmaproc;
}
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index df3dcc2ec..b8ca2ed8e 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1993, 1994 Alain Knaff
+ * Copyright (C) 1998 Alan Cox
*/
/*
* 02.12.91 - Changed to static variables to indicate need for reset
@@ -95,7 +96,11 @@
* 1995/10/18 -- Ralf Baechle -- Portability cleanup; move machine dependent
* features to asm/floppy.h.
*/
-
+
+/*
+ * 1998/06/07 -- Alan Cox -- Merged the 2.0.34 fixes for resource allocation
+ * failures.
+ */
#define FLOPPY_SANITY_CHECK
#undef FLOPPY_SILENT_DCL_CLEAR
@@ -114,9 +119,11 @@ static int print_unex=1;
* motor of these drives causes system hangs on some PCI computers. drive
* 0 is the low bit (0x1), and drive 7 is the high bit (0x80). Bits are on if
* a drive is allowed. */
+
static int FLOPPY_IRQ=6;
static int FLOPPY_DMA=2;
static int allowed_drive_mask = 0x33;
+static int irqdma_allocated = 0;
#include <linux/sched.h>
@@ -694,7 +701,7 @@ static int disk_change(int drive)
DPRINT("checking disk change line for drive %d\n",drive);
DPRINT("jiffies=%ld\n", jiffies);
DPRINT("disk change line=%x\n",fd_inb(FD_DIR)&0x80);
- DPRINT("flags=%x\n",UDRS->flags);
+ DPRINT("flags=%lx\n",UDRS->flags);
}
#endif
if (UDP->flags & FD_BROKEN_DCL)
@@ -759,6 +766,11 @@ static int set_dor(int fdc, char mask, char data)
UDRS->select_date = jiffies;
}
}
+ /*
+ * We should propogate failures to grab the resources back
+ * nicely from here. Actually we ought to rewrite the fd
+ * driver some day too.
+ */
if (newdor & FLOPPY_MOTOR_MASK)
floppy_grab_irq_and_dma();
if (olddor & FLOPPY_MOTOR_MASK)
@@ -818,10 +830,11 @@ static int lock_fdc(int drive, int interruptible)
unsigned long flags;
if (!usage_count){
- printk("trying to lock fdc while usage count=0\n");
+ printk(KERN_ERR "Trying to lock fdc while usage count=0\n");
return -1;
}
- floppy_grab_irq_and_dma();
+ if(floppy_grab_irq_and_dma()==-1)
+ return -EBUSY;
INT_OFF;
while (fdc_busy && NO_SIGNAL)
interruptible_sleep_on(&fdc_wait);
@@ -3950,7 +3963,7 @@ __initfunc(static void set_cmos(int *ints, int dummy, int dummy2))
int current_drive=0;
if (ints[0] != 2){
- DPRINT("wrong number of parameter for cmos\n");
+ DPRINT("wrong number of parameters for CMOS\n");
return;
}
current_drive = ints[1];
@@ -3962,11 +3975,11 @@ __initfunc(static void set_cmos(int *ints, int dummy, int dummy2))
FDC2 = 0x370;
if (ints[2] <= 0 ||
(ints[2] >= NUMBER(default_drive_params) && ints[2] != 16)){
- DPRINT("bad cmos code %d\n", ints[2]);
+ DPRINT("bad CMOS code %d\n", ints[2]);
return;
}
DP->cmos = ints[2];
- DPRINT("setting cmos code to %d\n", ints[2]);
+ DPRINT("setting CMOS code to %d\n", ints[2]);
}
static struct param_table {
@@ -4210,8 +4223,12 @@ static int floppy_grab_irq_and_dma(void)
for (fdc = 0; fdc < N_FDC; fdc++)
if (FDCS->address != -1)
fd_outb(FDCS->dor, FD_DOR);
+ /*
+ * The driver will try and free resources and relies on us
+ * to know if they were allocated or not.
+ */
fdc = 0;
- fd_enable_irq(FLOPPY_IRQ);
+ irqdma_allocated = 1;
return 0;
}
@@ -4233,11 +4250,13 @@ static void floppy_release_irq_and_dma(void)
return;
}
INT_ON;
- fd_disable_dma(FLOPPY_DMA);
- fd_free_dma(FLOPPY_DMA);
- fd_disable_irq(FLOPPY_IRQ);
- fd_free_irq(FLOPPY_IRQ);
-
+ if(irqdma_allocated)
+ {
+ fd_disable_dma(FLOPPY_DMA);
+ fd_free_dma(FLOPPY_DMA);
+ fd_free_irq(FLOPPY_IRQ);
+ irqdma_allocated=0;
+ }
set_dor(0, ~0, 8);
#if N_FDC > 1
set_dor(1, ~8, 0);
@@ -4388,10 +4407,12 @@ void floppy_eject(void)
int dummy;
if(have_no_fdc)
return;
- floppy_grab_irq_and_dma();
- lock_fdc(MAXTIMEOUT,0);
- dummy=fd_eject(0);
- process_fd_request();
- floppy_release_irq_and_dma();
+ if(floppy_grab_irq_and_dma()==0)
+ {
+ lock_fdc(MAXTIMEOUT,0);
+ dummy=fd_eject(0);
+ process_fd_request();
+ floppy_release_irq_and_dma();
+ }
}
#endif
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index f7b839848..040d922ef 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -414,7 +414,8 @@ check_table:
* This is necessary for drives for situations where
* the translated geometry is unavailable from the BIOS.
*/
- for (i = 0; i < 4 ; i++) {
+ int xlate_done = 0;
+ for (i = 0; i < 4 && !xlate_done; i++) {
struct partition *q = &p[i];
if (NR_SECTS(q)
&& (q->sector & 63) == 1
@@ -423,10 +424,16 @@ check_table:
if (heads == 32 || heads == 64 || heads == 128 || heads == 255) {
(void) ide_xlate_1024(dev, heads, " [PTBL]");
- break;
+ xlate_done = 1;
}
}
}
+ if (!xlate_done) {
+ /*
+ * Default translation is equivalent of "BIOS LBA":
+ */
+ ide_xlate_1024(dev, -2, " [LBA]");
+ }
}
}
#endif /* CONFIG_BLK_DEV_IDE */
@@ -1068,7 +1075,7 @@ static void check_partition(struct gendisk *hd, kdev_t dev)
/*
* This is a kludge to allow the partition check to be
- * skipped for specific drives (e.g. IDE cd-rom drives)
+ * skipped for specific drives (e.g. IDE CD-ROM drives)
*/
if ((int)first_sector == -1) {
hd->part[MINOR(dev)].start_sect = 0;
@@ -1169,8 +1176,10 @@ __initfunc(void device_setup(void))
#ifdef CONFIG_MD_BOOT
extern void md_setup_drive(void) __init;
#endif
+#ifdef CONFIG_FC4_SOC
+ extern int soc_probe(void);
+#endif
struct gendisk *p;
- int nr=0;
#ifdef CONFIG_PARPORT
parport_init();
@@ -1178,6 +1187,10 @@ __initfunc(void device_setup(void))
chr_dev_init();
blk_dev_init();
sti();
+#ifdef CONFIG_FC4_SOC
+ /* This has to be done before scsi_dev_init */
+ soc_probe();
+#endif
#ifdef CONFIG_SCSI
scsi_dev_init();
#endif
@@ -1188,10 +1201,9 @@ __initfunc(void device_setup(void))
console_map_init();
#endif
- for (p = gendisk_head ; p ; p=p->next) {
+ for (p = gendisk_head ; p ; p=p->next)
setup_dev(p);
- nr += p->nr_real;
- }
+
#ifdef CONFIG_BLK_DEV_RAM
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start && mount_initrd) initrd_load();
@@ -1203,3 +1215,25 @@ __initfunc(void device_setup(void))
md_setup_drive();
#endif
}
+
+#ifdef CONFIG_PROC_FS
+int get_partition_list(char * page)
+{
+ struct gendisk *p;
+ char buf[8];
+ int n, len;
+
+ len = sprintf(page, "major minor #blocks name\n\n");
+ for (p = gendisk_head; p; p = p->next) {
+ for (n=0; n < (p->nr_real << p->minor_shift); n++) {
+ if (p->part[n].nr_sects && len < PAGE_SIZE - 80) {
+ len += sprintf(page+len,
+ "%4d %4d %10d %s\n",
+ p->major, n, p->sizes[n],
+ disk_name(p, n, buf));
+ }
+ }
+ }
+ return len;
+}
+#endif
diff --git a/drivers/block/hd.c b/drivers/block/hd.c
index 52bb33ede..bd92e85e6 100644
--- a/drivers/block/hd.c
+++ b/drivers/block/hd.c
@@ -73,6 +73,8 @@ static struct wait_queue * busy_wait = NULL;
static int reset = 0;
static int hd_error = 0;
+#define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0)
+
/*
* This struct defines the HD's and their types.
*/
@@ -688,10 +690,10 @@ static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
/*
- * This is the harddisk IRQ description. The SA_INTERRUPT in sa_flags
- * means we run the IRQ-handler with interrupts disabled: this is bad for
+ * This is the hard disk IRQ description. The SA_INTERRUPT in sa_flags
+ * means we run the IRQ-handler with interrupts disabled: this is bad for
* interrupt latency, but anything else has led to problems on some
- * machines...
+ * machines.
*
* We enable interrupts in some of the routines after making sure it's
* safe.
@@ -758,7 +760,7 @@ static void hd_geninit(struct gendisk *ignored)
}
if (NR_HD) {
if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) {
- printk("hd: unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
+ printk("hd: unable to get IRQ%d for the hard disk driver\n",HD_IRQ);
NR_HD = 0;
} else {
request_region(HD_DATA, 8, "hd");
@@ -788,7 +790,7 @@ static struct file_operations hd_fops = {
__initfunc(int hd_init(void))
{
if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
- printk("hd: unable to get major %d for harddisk\n",MAJOR_NR);
+ printk("hd: unable to get major %d for hard disk\n",MAJOR_NR);
return -1;
}
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
@@ -802,7 +804,7 @@ __initfunc(int hd_init(void))
#define DEVICE_BUSY busy[target]
#define USAGE access_count[target]
#define CAPACITY (hd_info[target].head*hd_info[target].sect*hd_info[target].cyl)
-/* We assume that the the bios parameters do not change, so the disk capacity
+/* We assume that the BIOS parameters do not change, so the disk capacity
will not change */
#undef MAYBE_REINIT
#define GENDISK_STRUCT hd_gendisk
diff --git a/drivers/block/ht6560b.c b/drivers/block/ht6560b.c
index 6bf60e4dd..a3e1229bc 100644
--- a/drivers/block/ht6560b.c
+++ b/drivers/block/ht6560b.c
@@ -30,7 +30,7 @@
* of the value is the Active Time (at). Minimum value 2 is the fastest and
* the maximum value 15 is the slowest. Default values should be 15 for both.
* So 0x24 means 2 for rt and 4 for at. Each of the drives should have
- * both values, and IDESETUP gives automatically rt=15 st=15 for cdroms or
+ * both values, and IDESETUP gives automatically rt=15 st=15 for CDROMs or
* similar. If value is too small there will be all sorts of failures.
*
* Port 0x3e6 bit 0x20 sets these timings on/off. If 0x20 bit is set
@@ -103,7 +103,7 @@ static byte ht6560b_selects [2][MAX_DRIVES] = {{0x3c,0x3c}, {0x3d,0x3d}};
* Active Time for each drive. Smaller value gives higher speed.
* In case of failures you should probably fall back to a higher value.
*
- * Hopefully this example will make it clearer:
+ * Here's an example to make it clearer:
*
* DOS: DEVICE=C:\bin\HTIDE\HTIDE.SYS /D0=2,4 /D1=4,5 /D2=10,10 /D3=15,15
* Linux: byte ht6560b_timings [][] = {{0x24, 0x45}, {0xaa, 0xff}};
@@ -198,7 +198,7 @@ static void tune_ht6560b (ide_drive_t *drive, byte pio)
if (pio == 255) { /* auto-tune */
if (drive->media != ide_disk)
- pio = 0; /* some cdroms don't like fast modes (?) */
+ pio = 0; /* some CDROMs don't like fast modes (?) */
else
pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
}
diff --git a/drivers/block/ide-cd.c b/drivers/block/ide-cd.c
index 898d45f04..34ac359d2 100644
--- a/drivers/block/ide-cd.c
+++ b/drivers/block/ide-cd.c
@@ -13,22 +13,31 @@
* Suggestions are welcome. Patches that work are more welcome though. ;-)
* For those wishing to work on this driver, please be sure you download
* and comply with the latest ATAPI standard. This document can be
- * obtained by anonymous ftp from fission.dt.wdc.com in directory:
- * /pub/standards/SFF_atapi/spec/SFF8020-r2.6/PDF/8020r26.pdf
+ * obtained by anonymous ftp from:
+ * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
*
* Drives that deviate from the ATAPI standard will be accomodated as much
- * as possible via compile options. Since I only have a few drives, you you
- * generally need to send me patches...
+ * as possable via compile time or command-line options. Since I only have
+ * a few drives, you generally need to send me patches...
*
* ----------------------------------
* TO DO LIST:
- * -Avoid printing error messages for expected errors from the drive.
- * (If you are using a cd changer, you may get errors in the kernel
- * logs that are completly expected. Don't complain to me about this,
- * unless you have a patch to fix it. I am working on it...)
+ * -Implement Microsoft Media Status Notification per the spec at
+ * http://www.microsoft.com/hwdev/respec/storspec.htm
+ * This will allow us to get automagically notified when the media changes
+ * on ATAPI drives (something the stock ATAPI spec is lacking). Looks
+ * very cool. I discovered its existance the other day at work...
* -Fix ide_cdrom_reset so that it works (it does nothing right now)
* -Query the drive to find what features are available before trying to
* use them (like trying to close the tray in drives that can't).
+ * -Make it so that Pioneer CD DR-A24X and friends don't get screwed up on
+ * boot
+ * -Handle older drives that can't report their speed. (i.e. check if they
+ * support a version of ATAPI where they can report their speed before
+ * checking their speed and believing what they return).
+ * -It seems we do not always honor it when Uniform gets a request to change
+ * the cdi->options. We should _always_ check the options before doing stuff.
+ * This must be fixed.
*
*
* ----------------------------------
@@ -205,10 +214,13 @@
* messages, since this is not an error.
* -- Change error messages to be const
* -- Remove a "\t" which looks ugly in the syslogs
+ * 4.14 July 17, 1998 -- Change to pointing to .ps version of ATAPI spec
+ * since the .pdf version doesn't seem to work...
+ * -- Updated the TODO list to something more current.
*
*************************************************************************/
-#define IDECD_VERSION "4.13"
+#define IDECD_VERSION "4.14"
#include <linux/module.h>
#include <linux/types.h>
@@ -1157,7 +1169,7 @@ static void cdrom_pc_intr (ide_drive_t *drive)
if (pc->buflen == 0)
cdrom_end_request (1, drive);
else {
- /* Comment this out, because this always happins
+ /* Comment this out, because this always happens
right after a reset occurs, and it is annoying to
always print expected stuff. */
/*
diff --git a/drivers/block/ide-cd.h b/drivers/block/ide-cd.h
index 785fbe1ed..fbb2f859e 100644
--- a/drivers/block/ide-cd.h
+++ b/drivers/block/ide-cd.h
@@ -105,9 +105,9 @@
#define ABORTED_COMMAND 0x0b
#define MISCOMPARE 0x0e
-/* We want some additional flags for cd-rom drives.
+/* We want some additional flags for CDROM drives.
To save space in the ide_drive_t struct, use some fields which
- doesn't make sense for cd-roms -- `bios_cyl' and `bios_head'. */
+ doesn't make sense for CDROMs -- `bios_cyl' and `bios_head'. */
/* Configuration flags. These describe the capabilities of the drive.
They generally do not change after initialization, unless we learn
diff --git a/drivers/block/ide-disk.c b/drivers/block/ide-disk.c
index 1ac07f698..c4672208e 100644
--- a/drivers/block/ide-disk.c
+++ b/drivers/block/ide-disk.c
@@ -588,7 +588,7 @@ static int set_nowerr(ide_drive_t *drive, int arg)
{
unsigned long flags;
- if (ide_spin_wait_hwgroup("set_nowerr", drive, &flags))
+ if (ide_spin_wait_hwgroup(drive, &flags))
return -EBUSY;
drive->nowerr = arg;
drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
diff --git a/drivers/block/ide-dma.c b/drivers/block/ide-dma.c
index c314d1c82..93cc2cc1c 100644
--- a/drivers/block/ide-dma.c
+++ b/drivers/block/ide-dma.c
@@ -210,7 +210,7 @@ static int config_drive_for_dma (ide_drive_t *drive)
struct hd_driveid *id = drive->id;
ide_hwif_t *hwif = HWIF(drive);
- if (id && (id->capability & 1) && !hwif->no_autodma) {
+ if (id && (id->capability & 1) && hwif->autodma) {
/* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */
if (id->field_valid & 4) /* UltraDMA */
if ((id->dma_ultra & (id->dma_ultra >> 8) & 7))
diff --git a/drivers/block/ide-floppy.c b/drivers/block/ide-floppy.c
index e59565e21..3c6d0c006 100644
--- a/drivers/block/ide-floppy.c
+++ b/drivers/block/ide-floppy.c
@@ -43,6 +43,7 @@
#include <linux/errno.h>
#include <linux/genhd.h>
#include <linux/malloc.h>
+#include <linux/cdrom.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
@@ -1141,7 +1142,18 @@ static int idefloppy_get_capacity (ide_drive_t *drive)
static int idefloppy_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- return -EIO;
+ idefloppy_pc_t pc;
+
+ if (cmd == CDROMEJECT) {
+ if (drive->usage > 1)
+ return -EBUSY;
+ idefloppy_create_prevent_cmd (&pc, 0);
+ (void) idefloppy_queue_pc_tail (drive, &pc);
+ idefloppy_create_start_stop_cmd (&pc, 2);
+ (void) idefloppy_queue_pc_tail (drive, &pc);
+ return 0;
+ }
+ return -EIO;
}
/*
diff --git a/drivers/block/ide-pci.c b/drivers/block/ide-pci.c
index 811b7bed0..1122757cb 100644
--- a/drivers/block/ide-pci.c
+++ b/drivers/block/ide-pci.c
@@ -225,11 +225,14 @@ __initfunc(static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *n
*/
__initfunc(static void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d))
{
- unsigned int port, at_least_one_hwif_enabled = 0, no_autodma = 0, pciirq = 0;
+ unsigned int port, at_least_one_hwif_enabled = 0, autodma = 0, pciirq = 0;
unsigned short pcicmd = 0, tried_config = 0;
byte tmp = 0;
ide_hwif_t *hwif, *mate = NULL;
+#ifdef CONFIG_IDEDMA_AUTO
+ autodma = 1;
+#endif
check_if_enabled:
if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) {
printk("%s: error accessing PCI regs\n", d->name);
@@ -249,7 +252,7 @@ check_if_enabled:
printk("%s: device disabled (BIOS)\n", d->name);
return;
}
- no_autodma = 1; /* default DMA off if we had to configure it here */
+ autodma = 0; /* default DMA off if we had to configure it here */
goto check_if_enabled;
}
if (tried_config)
@@ -268,8 +271,9 @@ check_if_enabled:
printk("%s: bad irq (%d): will probe later\n", d->name, pciirq);
pciirq = 0;
} else {
-#ifdef __sparc_v9__
- printk("%s: 100%% native mode on irq %08x\n", d->name, pciirq);
+#ifdef __sparc__
+ printk("%s: 100%% native mode on irq %s\n",
+ d->name, __irq_itoa(pciirq));
#else
printk("%s: 100%% native mode on irq %d\n", d->name, pciirq);
#endif
@@ -282,11 +286,16 @@ check_if_enabled:
ide_pci_enablebit_t *e = &(d->enablebits[port]);
if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val))
continue; /* port not enabled */
- ctl = dev->base_address[(2*port)+1] & PCI_BASE_ADDRESS_IO_MASK;
+ if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) {
+ ctl = dev->base_address[(2*port)+1] & PCI_BASE_ADDRESS_IO_MASK;
+ base = dev->base_address[2*port] & ~7;
+ }
+ if ((ctl && !base) || (base && !ctl)) {
+ printk("%s: inconsistent baseregs (BIOS) for port %d, skipping\n", d->name, port);
+ continue;
+ }
if (!ctl)
ctl = port ? 0x374 : 0x3f4; /* use default value */
- base = dev->base_address[2*port] & ~7;
-
if (!base)
base = port ? 0x170 : 0x1f0; /* use default value */
if ((hwif = ide_match_hwif(base, d->name)) == NULL)
@@ -306,9 +315,11 @@ check_if_enabled:
hwif->mate = mate;
mate->mate = hwif;
}
- if (no_autodma)
- hwif->no_autodma = 1;
#ifdef CONFIG_BLK_DEV_IDEDMA
+ if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513))
+ autodma = 0;
+ if (autodma)
+ hwif->autodma = 1;
if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) ||
((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) {
unsigned int extra = (!mate && IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246)) ? 16 : 0;
@@ -317,8 +328,7 @@ check_if_enabled:
/*
* Set up BM-DMA capability (PnP BIOS should have done this)
*/
-printk("%s: %s enabling Bus-Master DMA\n", hwif->name, d->name);
- hwif->no_autodma = 1; /* default DMA off if we had to configure it here */
+ hwif->autodma = 0; /* default DMA off if we had to configure it here */
(void) pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER);
if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) {
printk("%s: %s error updating PCICMD\n", hwif->name, d->name);
diff --git a/drivers/block/ide-probe.c b/drivers/block/ide-probe.c
index 7af146b28..ffe446afe 100644
--- a/drivers/block/ide-probe.c
+++ b/drivers/block/ide-probe.c
@@ -45,8 +45,8 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
int bswap = 1;
struct hd_driveid *id;
- id = drive->id = kmalloc (SECTOR_WORDS*4, GFP_KERNEL);
- ide_input_data(drive, id, SECTOR_WORDS); /* read 512 bytes of id info */
+ id = drive->id = kmalloc (SECTOR_WORDS*4, GFP_ATOMIC); /* called with interrupts disabled! */
+ ide_input_data(drive, id, SECTOR_WORDS); /* read 512 bytes of id info */
ide__sti(); /* local CPU only */
ide_fix_driveid(id);
@@ -568,14 +568,23 @@ static int init_irq (ide_hwif_t *hwif)
hwgroup->hwif = HWIF(hwgroup->drive);
restore_flags(flags); /* all CPUs; safe now that hwif->hwgroup is set up */
-#ifndef __mc68000__
+#if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__)
printk("%s at 0x%03x-0x%03x,0x%03x on irq %d", hwif->name,
- hwif->io_ports[IDE_DATA_OFFSET], hwif->io_ports[IDE_DATA_OFFSET]+7, hwif->io_ports[IDE_CONTROL_OFFSET], hwif->irq);
+ hwif->io_ports[IDE_DATA_OFFSET],
+ hwif->io_ports[IDE_DATA_OFFSET]+7,
+ hwif->io_ports[IDE_CONTROL_OFFSET], hwif->irq);
+#elif defined(__sparc__)
+ printk("%s at 0x%03x-0x%03x,0x%03x on irq %s", hwif->name,
+ hwif->io_ports[IDE_DATA_OFFSET],
+ hwif->io_ports[IDE_DATA_OFFSET]+7,
+ hwif->io_ports[IDE_CONTROL_OFFSET], __irq_itoa(hwif->irq));
#else
- printk("%s at %p on irq 0x%08x", hwif->name, hwif->io_ports[IDE_DATA_OFFSET], hwif->irq);
-#endif /* __mc68000__ */
+ printk("%s at %p on irq 0x%08x", hwif->name,
+ hwif->io_ports[IDE_DATA_OFFSET], hwif->irq);
+#endif /* __mc68000__ && CONFIG_APUS */
if (match)
- printk(" (%sed with %s)", hwif->sharing_irq ? "shar" : "serializ", match->name);
+ printk(" (%sed with %s)",
+ hwif->sharing_irq ? "shar" : "serializ", match->name);
printk("\n");
return 0;
}
diff --git a/drivers/block/ide.c b/drivers/block/ide.c
index 191678d77..01a4e18e4 100644
--- a/drivers/block/ide.c
+++ b/drivers/block/ide.c
@@ -1,9 +1,8 @@
/*
- * linux/drivers/block/ide.c Version 6.13 March 29, 1998
+ * linux/drivers/block/ide.c Version 6.18 August 16, 1998
*
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
*/
-#define _IDE_C /* needed by <linux/blk.h> */
/*
* Maintained by Mark Lord <mlord@pobox.com>
@@ -89,6 +88,8 @@
* Version 6.14 fixed IRQ sharing among PCI devices
* Version 6.15 added SMP awareness to IDE drivers
* Version 6.16 fixed various bugs; even more SMP friendly
+ * Version 6.17 fix for newest EZ-Drive problem
+ * Version 6.18 default unpartitioned-disk translation now "BIOS LBA"
*
* Some additional driver compile-time options are in ide.h
*
@@ -98,6 +99,8 @@
#undef REALLY_SLOW_IO /* most systems can safely undef this */
+#define _IDE_C /* Tell ide.h it's really us */
+
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
@@ -405,70 +408,27 @@ static inline int drive_is_ready (ide_drive_t *drive)
return 1; /* drive ready: *might* be interrupting */
}
-#if !defined(__SMP__) && defined(DEBUG_SPINLOCKS) && (DEBUG_SPINLOCKS > 1)
-
-static const char *ide_lock_name(spinlock_t *spinlock)
+/*
+ * This is our end_request replacement function.
+ */
+void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup)
{
- int index;
-
- if (spinlock == &io_request_lock)
- return "io_request_lock";
- for (index = 0; index < MAX_HWIFS; index++) {
- ide_hwif_t *hwif = &ide_hwifs[index];
- ide_hwgroup_t *hwgroup = hwif->hwgroup;
- if (spinlock == &hwgroup->spinlock)
- return hwif->name;
- }
- return "?";
-}
-
-#define IDE_SPIN_LOCK_IRQ(msg,spinlock) \
-{ \
- static int __babble = 20; \
- __cli(); \
- if ((spinlock)->lock && __babble) { \
- __babble--; \
- printk("ide_lock: %s: already locked (%s)\n", msg, ide_lock_name(spinlock)); \
- } \
- /* spin_lock_irq(spinlock); */ \
- (spinlock)->lock = 1; \
-}
-
-#define IDE_SPIN_LOCK_IRQSAVE(msg,spinlock,flags) \
-{ \
- __save_flags(flags); \
- IDE_SPIN_LOCK_IRQ(msg,spinlock); \
-}
+ struct request *rq;
+ unsigned long flags;
-#define IDE_SPIN_UNLOCK_IRQRESTORE(msg,spinlock,flags) \
-{ \
- static int __babble = 20; \
- __cli(); \
- if (!((spinlock)->lock) && __babble) { \
- __babble--; \
- printk("ide_unlock: %s: not locked (%s)\n", msg, ide_lock_name(spinlock)); \
- } \
- /* spin_unlock_irqrestore(msg,spinlock,flags); */ \
- (spinlock)->lock = 0; \
- restore_flags(flags); \
-}
+ spin_lock_irqsave(&io_request_lock, flags);
+ rq = hwgroup->rq;
-#define IDE_SPIN_UNLOCK(msg,spinlock) \
-{ \
- unsigned long __flags; \
- __save_flags(__flags); \
- IDE_SPIN_UNLOCK_IRQRESTORE(msg,spinlock,__flags); \
+ if (!end_that_request_first(rq, uptodate, hwgroup->drive->name)) {
+ add_blkdev_randomness(MAJOR(rq->rq_dev));
+ hwgroup->drive->queue = rq->next;
+ blk_dev[MAJOR(rq->rq_dev)].current_request = NULL;
+ hwgroup->rq = NULL;
+ end_that_request_last(rq);
+ }
+ spin_unlock_irqrestore(&io_request_lock, flags);
}
-#else /* DEBUG_SPINLOCKS */
-
-#define IDE_SPIN_LOCK_IRQ(msg,spinlock) spin_lock_irq(spinlock)
-#define IDE_SPIN_LOCK_IRQSAVE(msg,spinlock,flags) spin_lock_irqsave(spinlock,flags)
-#define IDE_SPIN_UNLOCK(msg,spinlock) spin_unlock(spinlock)
-#define IDE_SPIN_UNLOCK_IRQRESTORE(msg,spinlock,flags) spin_unlock_irqrestore(spinlock,flags)
-
-#endif /* DEBUG_SPINLOCKS */
-
/*
* This should get invoked any time we exit the driver to
* wait for an interrupt response from a drive. handler() points
@@ -481,7 +441,7 @@ void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int t
unsigned long flags;
ide_hwgroup_t *hwgroup = HWGROUP(drive);
- IDE_SPIN_LOCK_IRQSAVE("ide_set_handler", &hwgroup->spinlock, flags);
+ spin_lock_irqsave(&hwgroup->spinlock, flags);
#ifdef DEBUG
if (hwgroup->handler != NULL) {
printk("%s: ide_set_handler: handler not null; old=%p, new=%p\n",
@@ -491,7 +451,7 @@ void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int t
hwgroup->handler = handler;
hwgroup->timer.expires = jiffies + timeout;
add_timer(&(hwgroup->timer));
- IDE_SPIN_UNLOCK_IRQRESTORE("ide_set_handler", &hwgroup->spinlock, flags);
+ spin_unlock_irqrestore(&hwgroup->spinlock, flags);
}
/*
@@ -707,12 +667,12 @@ void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err)
args[2] = IN_BYTE(IDE_NSECTOR_REG);
}
}
- IDE_SPIN_LOCK_IRQSAVE("ide_end_drive_cmd", &io_request_lock, flags);
+ spin_lock_irqsave(&io_request_lock, flags);
drive->queue = rq->next;
blk_dev[MAJOR(rq->rq_dev)].current_request = NULL;
HWGROUP(drive)->rq = NULL;
rq->rq_status = RQ_INACTIVE;
- IDE_SPIN_UNLOCK_IRQRESTORE("ide_end_drive_cmd", &io_request_lock, flags);
+ spin_unlock_irqrestore(&io_request_lock, flags);
save_flags(flags); /* all CPUs; overkill? */
cli(); /* all CPUs; overkill? */
if (rq->sem != NULL)
@@ -1115,22 +1075,7 @@ repeat:
}
/*
- * The driver enables interrupts as much as possible. In order to do this,
- * (a) the device-interrupt is always masked before entry, and
- * (b) the timeout-interrupt is always disabled before entry.
- *
- * If we enter here from, say irq14, and then start a new request for irq15,
- * (possible with "serialize" option) then we cannot ensure that we exit
- * before the irq15 hits us. So, we must be careful not to let this bother us.
- *
- * Interrupts are still masked (by default) whenever we are exchanging
- * data/cmds with a drive, because some drives seem to have very poor
- * tolerance for latency during I/O. For devices which don't suffer from
- * this problem (most don't), the unmask flag can be set using the "hdparm"
- * utility, to permit other interrupts during data/cmd transfers.
- *
* Caller must have already acquired spinlock using *spinflags
- *
*/
static void ide_do_request (ide_hwgroup_t *hwgroup, unsigned long *hwgroup_flags, int masked_irq)
{
@@ -1141,7 +1086,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, unsigned long *hwgroup_flags
hwgroup->busy = 1;
while (hwgroup->handler == NULL) {
- IDE_SPIN_LOCK_IRQSAVE("ide_do_request1", &io_request_lock, io_flags);
+ spin_lock_irqsave(&io_request_lock, io_flags);
drive = choose_drive(hwgroup);
if (drive == NULL) {
unsigned long sleep = 0;
@@ -1155,7 +1100,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, unsigned long *hwgroup_flags
if (drive->sleep && (!sleep || 0 < (signed long)(sleep - drive->sleep)))
sleep = drive->sleep;
} while ((drive = drive->next) != hwgroup->drive);
- IDE_SPIN_UNLOCK_IRQRESTORE("ide_do_request2", &io_request_lock, io_flags);
+ spin_unlock_irqrestore(&io_request_lock, io_flags);
if (sleep) {
if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep))
sleep = jiffies + WAIT_MIN_SLEEP;
@@ -1180,13 +1125,13 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, unsigned long *hwgroup_flags
if (bdev->current_request == &bdev->plug) /* FIXME: paranoia */
printk("%s: Huh? nuking plugged queue\n", drive->name);
bdev->current_request = hwgroup->rq = drive->queue;
- IDE_SPIN_UNLOCK_IRQRESTORE("ide_do_request3", &io_request_lock, io_flags);
+ spin_unlock_irqrestore(&io_request_lock, io_flags);
if (hwif->irq != masked_irq)
disable_irq(hwif->irq);
- IDE_SPIN_UNLOCK_IRQRESTORE("ide_do_request4", &hwgroup->spinlock, *hwgroup_flags);
+ spin_unlock_irqrestore(&hwgroup->spinlock, *hwgroup_flags);
start_request(drive);
- IDE_SPIN_LOCK_IRQSAVE("ide_do_request5", &hwgroup->spinlock, *hwgroup_flags);
+ spin_lock_irqsave(&hwgroup->spinlock, *hwgroup_flags);
if (hwif->irq != masked_irq)
enable_irq(hwif->irq);
}
@@ -1205,36 +1150,35 @@ struct request **ide_get_queue (kdev_t dev)
/*
* do_hwgroup_request() invokes ide_do_request() after claiming hwgroup->busy.
*/
-static void do_hwgroup_request (const char *msg, ide_hwgroup_t *hwgroup)
+static void do_hwgroup_request (ide_hwgroup_t *hwgroup)
{
unsigned long flags;
- IDE_SPIN_LOCK_IRQSAVE(msg, &hwgroup->spinlock, flags);
+ spin_lock_irqsave(&hwgroup->spinlock, flags);
if (hwgroup->busy) {
- IDE_SPIN_UNLOCK_IRQRESTORE(msg, &hwgroup->spinlock, flags);
+ spin_unlock_irqrestore(&hwgroup->spinlock, flags);
return;
}
del_timer(&hwgroup->timer);
ide_get_lock(&ide_lock, ide_intr, hwgroup); /* for atari only */
ide_do_request(hwgroup, &flags, 0);
- IDE_SPIN_UNLOCK_IRQRESTORE(msg, &hwgroup->spinlock, flags);
+ spin_unlock_irqrestore(&hwgroup->spinlock, flags);
}
/*
- * As of linux-2.1.95, ll_rw_blk.c invokes our do_idex_request()
- * functions with the io_request_spinlock already grabbed.
+ * ll_rw_blk.c invokes our do_idex_request() function
+ * with the io_request_spinlock already grabbed.
* Since we need to do our own spinlock's internally,
* on paths that don't necessarily originate through the
- * do_idex_request() path.
- *
- * We have to undo the spinlock on entry, and restore it again on exit.
+ * do_idex_request() path, we have to undo the spinlock on entry,
+ * and restore it again on exit.
* Fortunately, this is mostly a nop for non-SMP kernels.
*/
static inline void unlock_do_hwgroup_request (ide_hwgroup_t *hwgroup)
{
- IDE_SPIN_UNLOCK("unlock_do_hwgroup_request", &io_request_lock);
- do_hwgroup_request ("from unlock_do_hwgroup_request", hwgroup);
- IDE_SPIN_LOCK_IRQ("unlock_do_hwgroup_request", &io_request_lock);
+ spin_unlock(&io_request_lock);
+ do_hwgroup_request (hwgroup);
+ spin_lock_irq(&io_request_lock);
}
void do_ide0_request (void)
@@ -1282,16 +1226,16 @@ static void start_next_request (ide_hwgroup_t *hwgroup, int masked_irq)
unsigned long flags;
ide_drive_t *drive;
- IDE_SPIN_LOCK_IRQSAVE("start_next_request", &hwgroup->spinlock, flags);
+ spin_lock_irqsave(&hwgroup->spinlock, flags);
if (hwgroup->handler != NULL) {
- IDE_SPIN_UNLOCK_IRQRESTORE("start_next_request", &hwgroup->spinlock, flags);
+ spin_unlock_irqrestore(&hwgroup->spinlock, flags);
return;
}
drive = hwgroup->drive;
set_recovery_timer(HWIF(drive));
drive->service_time = jiffies - drive->service_start;
ide_do_request(hwgroup, &flags, masked_irq);
- IDE_SPIN_UNLOCK_IRQRESTORE("start_next_request", &hwgroup->spinlock, flags);
+ spin_unlock_irqrestore(&hwgroup->spinlock, flags);
}
void ide_timer_expiry (unsigned long data)
@@ -1301,31 +1245,31 @@ void ide_timer_expiry (unsigned long data)
ide_handler_t *handler;
unsigned long flags;
- IDE_SPIN_LOCK_IRQSAVE("ide_timer_expiry1", &hwgroup->spinlock, flags);
+ spin_lock_irqsave(&hwgroup->spinlock, flags);
drive = hwgroup->drive;
if ((handler = hwgroup->handler) == NULL) {
- IDE_SPIN_UNLOCK_IRQRESTORE("ide_timer_expiry2", &hwgroup->spinlock, flags);
- do_hwgroup_request("timer do_hwgroup_request", hwgroup);
+ spin_unlock_irqrestore(&hwgroup->spinlock, flags);
+ do_hwgroup_request(hwgroup);
return;
}
hwgroup->busy = 1; /* should already be "1" */
hwgroup->handler = NULL;
+ del_timer(&hwgroup->timer);
if (hwgroup->poll_timeout != 0) { /* polling in progress? */
- IDE_SPIN_UNLOCK_IRQRESTORE("ide_timer_expiry3", &hwgroup->spinlock, flags);
+ spin_unlock_irqrestore(&hwgroup->spinlock, flags);
handler(drive);
} else if (drive_is_ready(drive)) {
printk("%s: lost interrupt\n", drive->name);
- IDE_SPIN_UNLOCK_IRQRESTORE("ide_timer_expiry4", &hwgroup->spinlock, flags);
+ spin_unlock_irqrestore(&hwgroup->spinlock, flags);
handler(drive);
} else {
if (drive->waiting_for_dma) {
(void) hwgroup->hwif->dmaproc(ide_dma_end, drive);
printk("%s: timeout waiting for DMA\n", drive->name);
}
- IDE_SPIN_UNLOCK_IRQRESTORE("ide_timer_expiry5", &hwgroup->spinlock, flags);
+ spin_unlock_irqrestore(&hwgroup->spinlock, flags);
ide_error(drive, "irq timeout", GET_STAT());
}
- del_timer(&hwgroup->timer);
start_next_request(hwgroup, 0);
}
@@ -1388,7 +1332,7 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
ide_handler_t *handler;
__cli(); /* local CPU only */
- IDE_SPIN_LOCK_IRQSAVE("ide_intr1", &hwgroup->spinlock, flags);
+ spin_lock_irqsave(&hwgroup->spinlock, flags);
hwif = hwgroup->hwif;
if ((handler = hwgroup->handler) == NULL || hwgroup->poll_timeout != 0) {
/*
@@ -1414,18 +1358,18 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
(void)ide_ack_intr(hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]);
unexpected_intr(irq, hwgroup);
}
- IDE_SPIN_UNLOCK_IRQRESTORE("ide_intr2", &hwgroup->spinlock, flags);
+ spin_unlock_irqrestore(&hwgroup->spinlock, flags);
return;
}
drive = hwgroup->drive;
if (!drive || !drive_is_ready(drive)) {
- IDE_SPIN_UNLOCK_IRQRESTORE("ide_intr3", &hwgroup->spinlock, flags);
+ spin_unlock_irqrestore(&hwgroup->spinlock, flags);
return;
}
hwgroup->handler = NULL;
(void)ide_ack_intr(hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]);
del_timer(&(hwgroup->timer));
- IDE_SPIN_UNLOCK_IRQRESTORE("ide_intr4", &hwgroup->spinlock, flags);
+ spin_unlock_irqrestore(&hwgroup->spinlock, flags);
if (drive->unmask)
ide__sti(); /* local CPU only */
handler(drive); /* service this interrupt, may set handler for next interrupt */
@@ -1520,7 +1464,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
if (action == ide_wait)
rq->sem = &sem;
- IDE_SPIN_LOCK_IRQSAVE("ide_do_drive_cmd", &io_request_lock, flags);
+ spin_lock_irqsave(&io_request_lock, flags);
cur_rq = drive->queue;
if (cur_rq == NULL || action == ide_preempt) {
rq->next = cur_rq;
@@ -1535,8 +1479,8 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
rq->next = cur_rq->next;
cur_rq->next = rq;
}
- IDE_SPIN_UNLOCK_IRQRESTORE("ide_do_drive_cmd", &io_request_lock, flags);
- do_hwgroup_request("drive_cmd do_hwgroup_request", hwgroup);
+ spin_unlock_irqrestore(&io_request_lock, flags);
+ do_hwgroup_request(hwgroup);
save_flags(flags); /* all CPUs; overkill? */
cli(); /* all CPUs; overkill? */
if (action == ide_wait && rq->rq_status != RQ_INACTIVE)
@@ -1565,14 +1509,14 @@ int ide_revalidate_disk(kdev_t i_rdev)
major = MAJOR(i_rdev);
minor = drive->select.b.unit << PARTN_BITS;
hwgroup = HWGROUP(drive);
- IDE_SPIN_LOCK_IRQSAVE("ide_revalidate_disk", &hwgroup->spinlock, flags);
+ spin_lock_irqsave(&hwgroup->spinlock, flags);
if (drive->busy || (drive->usage > 1)) {
- IDE_SPIN_UNLOCK_IRQRESTORE("ide_revalidate_disk", &hwgroup->spinlock, flags);
+ spin_unlock_irqrestore(&hwgroup->spinlock, flags);
return -EBUSY;
};
drive->busy = 1;
MOD_INC_USE_COUNT;
- IDE_SPIN_UNLOCK_IRQRESTORE("ide_revalidate_disk", &hwgroup->spinlock, flags);
+ spin_unlock_irqrestore(&hwgroup->spinlock, flags);
for (p = 0; p < (1<<PARTN_BITS); ++p) {
if (drive->part[p].nr_sects > 0) {
@@ -1582,6 +1526,7 @@ int ide_revalidate_disk(kdev_t i_rdev)
if (sb)
invalidate_inodes(sb);
invalidate_buffers (devp);
+ set_blocksize(devp, 1024);
}
drive->part[p].start_sect = 0;
drive->part[p].nr_sects = 0;
@@ -1931,7 +1876,7 @@ int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
unsigned long flags;
if ((setting->rw & SETTING_READ)) {
- IDE_SPIN_LOCK_IRQSAVE("ide_read_setting", &HWGROUP(drive)->spinlock, flags);
+ spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
switch(setting->data_type) {
case TYPE_BYTE:
val = *((u8 *) setting->data);
@@ -1944,25 +1889,25 @@ int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
val = *((u32 *) setting->data);
break;
}
- IDE_SPIN_UNLOCK_IRQRESTORE("ide_read_setting", &HWGROUP(drive)->spinlock, flags);
+ spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
}
return val;
}
-int ide_spin_wait_hwgroup (const char *msg, ide_drive_t *drive, unsigned long *flags)
+int ide_spin_wait_hwgroup (ide_drive_t *drive, unsigned long *flags)
{
ide_hwgroup_t *hwgroup = HWGROUP(drive);
unsigned long timeout = jiffies + (3 * HZ);
- IDE_SPIN_LOCK_IRQSAVE(msg, &hwgroup->spinlock, *flags);
+ spin_lock_irqsave(&hwgroup->spinlock, *flags);
while (hwgroup->busy) {
- IDE_SPIN_UNLOCK_IRQRESTORE(msg, &hwgroup->spinlock, *flags);
+ spin_unlock_irqrestore(&hwgroup->spinlock, *flags);
__sti(); /* local CPU only; needed for jiffies */
if (0 < (signed long)(jiffies - timeout)) {
- printk("%s: %s: channel busy\n", drive->name, msg);
+ printk("%s: channel busy\n", drive->name);
return -EBUSY;
}
- IDE_SPIN_LOCK_IRQSAVE(msg, &hwgroup->spinlock, *flags);
+ spin_lock_irqsave(&hwgroup->spinlock, *flags);
}
return 0;
}
@@ -1981,7 +1926,7 @@ int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val)
return -EINVAL;
if (setting->set)
return setting->set(drive, val);
- if (ide_spin_wait_hwgroup("ide_write_settings", drive, &flags))
+ if (ide_spin_wait_hwgroup(drive, &flags))
return -EBUSY;
switch (setting->data_type) {
case TYPE_BYTE:
@@ -1999,7 +1944,7 @@ int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val)
*p = val;
break;
}
- IDE_SPIN_UNLOCK_IRQRESTORE("ide_write_setting4", &HWGROUP(drive)->spinlock, flags);
+ spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
return 0;
}
@@ -2345,7 +2290,7 @@ __initfunc(static int match_parm (char *s, const char *keywords[], int vals[], i
* "idex=serialize" : do not overlap operations on idex and ide(x^1)
* "idex=four" : four drives on idex and ide(x^1) share same ports
* "idex=reset" : reset interface before first use
- * "idex=nodma" : do not enable DMA by default on either drive
+ * "idex=dma" : enable DMA by default on both drives if possible
*
* The following are valid ONLY on ide0,
* and the defaults for the base,ctl ports must not be altered.
@@ -2447,7 +2392,7 @@ __initfunc(void ide_setup (char *s))
/*
* Be VERY CAREFUL changing this: note hardcoded indexes below
*/
- const char *ide_words[] = {"noprobe", "serialize", "autotune", "noautotune", "reset", "nodma", "four",
+ const char *ide_words[] = {"noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "four",
"qd6580", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL};
hw = s[3] - '0';
hwif = &ide_hwifs[hw];
@@ -2535,8 +2480,8 @@ __initfunc(void ide_setup (char *s))
goto do_serialize;
}
#endif /* CONFIG_BLK_DEV_4DRIVES */
- case -6: /* nodma */
- hwif->no_autodma = 1;
+ case -6: /* dma */
+ hwif->autodma = 1;
goto done;
case -5: /* "reset" */
hwif->reset = 1;
@@ -2618,7 +2563,7 @@ int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg)
printk("%s ", msg);
- if (xparm == -1 && drive->bios_cyl < 1024)
+ if (xparm < 0 && (drive->bios_cyl * drive->bios_head * drive->bios_sect) < (1024 * 16 * 63))
return 0; /* small disk: no translation needed */
if (drive->id) {
@@ -2646,15 +2591,14 @@ int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg)
#if FAKE_FDISK_FOR_EZDRIVE
if (xparm == -1) {
drive->remap_0_to_1 = 1;
- msg = "0->1";
+ printk("[remap 0->1] ");
} else
#endif /* FAKE_FDISK_FOR_EZDRIVE */
if (xparm == 1) {
drive->sect0 = 63;
drive->bios_cyl = (tracks - 1) / drive->bios_head;
- msg = "+63";
+ printk("[remap +63] ");
}
- printk("[remap %s] ", msg);
}
drive->part[0].nr_sects = current_capacity(drive);
printk("[%d/%d/%d]", drive->bios_cyl, drive->bios_head, drive->bios_sect);
@@ -2935,6 +2879,7 @@ struct file_operations ide_fops[] = {{
EXPORT_SYMBOL(ide_hwifs);
EXPORT_SYMBOL(ide_register_module);
EXPORT_SYMBOL(ide_unregister_module);
+EXPORT_SYMBOL(ide_spin_wait_hwgroup);
/*
* Probe module
diff --git a/drivers/block/ide.h b/drivers/block/ide.h
index f0c9604f0..1da4ff371 100644
--- a/drivers/block/ide.h
+++ b/drivers/block/ide.h
@@ -309,7 +309,7 @@ typedef enum { ide_unknown, ide_generic, ide_pci,
ide_cmd640, ide_dtc2278, ide_ali14xx,
ide_qd6580, ide_umc8672, ide_ht6560b,
ide_pdc4030, ide_rz1000, ide_trm290,
- ide_4drives
+ ide_cmd646, ide_4drives
} hwif_chipset_t;
typedef struct ide_pci_devid_s {
@@ -345,7 +345,7 @@ typedef struct hwif_s {
unsigned serialized : 1; /* serialized operation with mate hwif */
unsigned sharing_irq: 1; /* 1 = sharing irq with another hwif */
unsigned reset : 1; /* reset after probe */
- unsigned no_autodma : 1; /* don't automatically enable DMA at boot */
+ unsigned autodma : 1; /* automatically try to enable DMA at boot */
byte channel; /* for dual-port chips: 0=primary, 1=secondary */
struct pci_dev *pci_dev; /* for pci chipsets */
ide_pci_devid_t pci_devid; /* for pci chipsets: {VID,DID} */
@@ -512,11 +512,14 @@ extern ide_module_t *ide_modules;
#endif
/*
- * One final include file, which references some of the data/defns from above
+ * We need blk.h, but we replace its end_request by our own version.
*/
-#define IDE_DRIVER /* "parameter" for blk.h */
+#define IDE_DRIVER /* Toggle some magic bits in blk.h */
+#define LOCAL_END_REQUEST /* Don't generate end_request in blk.h */
#include <linux/blk.h>
+void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup);
+
/*
* This is used for (nearly) all data transfers from/to the IDE interface
*/
@@ -671,7 +674,7 @@ void ide_stall_queue (ide_drive_t *drive, unsigned long timeout);
*/
struct request **ide_get_queue (kdev_t dev);
-int ide_spin_wait_hwgroup(const char *msg, ide_drive_t *drive, unsigned long *flags);
+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);
void ide_geninit (struct gendisk *gd);
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index ac8d5bc12..158b5e975 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -435,7 +435,7 @@ void make_request(int major,int rw, struct buffer_head * bh)
/* look for a free request. */
/* Loop uses two requests, 1 for loop and 1 for the real device.
* Cut max_req in half to avoid running out and deadlocking. */
- if (major == LOOP_MAJOR)
+ if ((major == LOOP_MAJOR) || (major == NBD_MAJOR))
max_req >>= 1;
/*
@@ -452,7 +452,7 @@ void make_request(int major,int rw, struct buffer_head * bh)
if (!req) {
/* MD and loop can't handle plugging without deadlocking */
if (major != MD_MAJOR && major != LOOP_MAJOR &&
- major != DDV_MAJOR)
+ major != DDV_MAJOR && major != NBD_MAJOR)
plug_device(blk_dev + major); /* is atomic */
} else switch (major) {
case IDE0_MAJOR: /* same as HD_MAJOR */
@@ -463,6 +463,7 @@ void make_request(int major,int rw, struct buffer_head * bh)
case IDE4_MAJOR:
case IDE5_MAJOR:
case ACSI_MAJOR:
+ case MFM_ACORN_MAJOR:
/*
* The scsi disk and cdrom drivers completely remove the request
* from the queue when they start processing an entry. For this
@@ -669,7 +670,7 @@ void ll_rw_swap_file(int rw, kdev_t dev, unsigned int *b, int nb, char *buf)
}
buffersize = PAGE_SIZE / nb;
- if (major == LOOP_MAJOR)
+ if ((major == LOOP_MAJOR) || (major == NBD_MAJOR))
max_req >>= 1;
for (j=0, i=0; i<nb;)
{
@@ -715,6 +716,61 @@ void ll_rw_swap_file(int rw, kdev_t dev, unsigned int *b, int nb, char *buf)
}
}
}
+#ifdef CONFIG_STRAM_SWAP
+extern int stram_device_init( void );
+#endif
+
+/*
+ * First step of what used to be end_request
+ *
+ * 0 means continue with end_that_request_last,
+ * 1 means we are done
+ */
+
+int
+end_that_request_first( struct request *req, int uptodate, char *name )
+{
+ struct buffer_head * bh;
+ int nsect;
+
+ req->errors = 0;
+ if (!uptodate) {
+ printk("end_request: I/O error, dev %s (%s), sector %lu\n",
+ kdevname(req->rq_dev), name, req->sector);
+ if ((bh = req->bh) != NULL) {
+ nsect = bh->b_size >> 9;
+ req->nr_sectors--;
+ req->nr_sectors &= ~(nsect - 1);
+ req->sector += nsect;
+ req->sector &= ~(nsect - 1);
+ }
+ }
+
+ if ((bh = req->bh) != NULL) {
+ req->bh = bh->b_reqnext;
+ bh->b_reqnext = NULL;
+ bh->b_end_io(bh, uptodate);
+ if ((bh = req->bh) != NULL) {
+ req->current_nr_sectors = bh->b_size >> 9;
+ if (req->nr_sectors < req->current_nr_sectors) {
+ req->nr_sectors = req->current_nr_sectors;
+ printk("end_request: buffer-list destroyed\n");
+ }
+ req->buffer = bh->b_data;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void
+end_that_request_last( struct request *req )
+{
+ if (req->sem != NULL)
+ up(req->sem);
+ req->rq_status = RQ_INACTIVE;
+ wake_up(&wait_for_request);
+}
__initfunc(int blk_dev_init(void))
{
@@ -744,6 +800,9 @@ __initfunc(int blk_dev_init(void))
#ifdef CONFIG_AMIGA_Z2RAM
z2_init();
#endif
+#ifdef CONFIG_STRAM_SWAP
+ stram_device_init();
+#endif
#ifdef CONFIG_BLK_DEV_RAM
rd_init();
#endif
@@ -765,17 +824,26 @@ __initfunc(int blk_dev_init(void))
#ifdef CONFIG_BLK_DEV_XD
xd_init();
#endif
+#ifdef CONFIG_BLK_DEV_MFM
+ mfm_init();
+#endif
#ifdef CONFIG_PARIDE
{ extern void paride_init(void); paride_init(); };
#endif
#ifdef CONFIG_MAC_FLOPPY
swim3_init();
#endif
+#ifdef CONFIG_AMIGA_FLOPPY
+ amiga_floppy_init();
+#endif
+#ifdef CONFIG_ATARI_FLOPPY
+ atari_floppy_init();
+#endif
#ifdef CONFIG_BLK_DEV_FD
floppy_init();
#else
-#if !defined(CONFIG_SGI) && !defined (__mc68000__) \
- && !defined(CONFIG_PMAC) && !defined(__sparc__)
+#if !defined(CONFIG_SGI) && !defined (__mc68000__) && !defined(CONFIG_PMAC)
+ && !defined(__sparc__) && !defined(CONFIG_APUS)
outb_p(0xc, 0x3f2);
#endif
#endif
@@ -821,7 +889,12 @@ __initfunc(int blk_dev_init(void))
#ifdef CONFIG_DDV
ddv_init();
#endif
+#ifdef CONFIG_BLK_DEV_NBD
+ nbd_init();
+#endif
return 0;
};
EXPORT_SYMBOL(io_request_lock);
+EXPORT_SYMBOL(end_that_request_first);
+EXPORT_SYMBOL(end_that_request_last);
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index d1201086d..268c9187a 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -6,14 +6,15 @@
* Copyright 1993 by Theodore Ts'o. Redistribution of this file is
* permitted under the GNU Public License.
*
- * more DES encryption plus IDEA encryption by Nicholas J. Leon, June 20, 1996
* DES encryption plus some minor changes by Werner Almesberger, 30-MAY-1993
+ * more DES encryption plus IDEA encryption by Nicholas J. Leon, June 20, 1996
*
* Modularized and updated for 1.1.16 kernel - Mitch Dsouza 28th May 1994
- *
* Adapted for 1.3.59 kernel - Andries Brouwer, 1 Feb 1996
*
- * Fixed do_loop_request() re-entrancy - <Vincent.Renardias@waw.com> Mar 20, 1997
+ * Fixed do_loop_request() re-entrancy - Vincent.Renardias@waw.com Mar 20, 1997
+ *
+ * Handle sparse backing files correctly - Kenn Humborg, Jun 28, 1998
*/
#include <linux/module.h>
@@ -55,6 +56,14 @@ static struct loop_device loop_dev[MAX_LOOP];
static int loop_sizes[MAX_LOOP];
static int loop_blksizes[MAX_LOOP];
+#define FALSE 0
+#define TRUE (!FALSE)
+
+/* Forward declaration of function to create missing blocks in the
+ backing file (can happen if the backing file is sparse) */
+static int create_missing_block(struct loop_device *lo, int block, int blksize);
+
+
/*
* Transfer functions
*/
@@ -166,8 +175,8 @@ static void figure_loop_size(struct loop_device *lo)
{
int size;
- if (S_ISREG(lo->lo_inode->i_mode))
- size = (lo->lo_inode->i_size - lo->lo_offset) / BLOCK_SIZE;
+ if (S_ISREG(lo->lo_dentry->d_inode->i_mode))
+ size = (lo->lo_dentry->d_inode->i_size - lo->lo_offset) / BLOCK_SIZE;
else {
kdev_t lodev = lo->lo_device;
if (blk_size[MAJOR(lodev)])
@@ -187,6 +196,7 @@ static void do_lo_request(void)
struct loop_device *lo;
struct buffer_head *bh;
struct request *current_request;
+ int block_present;
repeat:
INIT_REQUEST;
@@ -195,7 +205,7 @@ repeat:
if (MINOR(current_request->rq_dev) >= MAX_LOOP)
goto error_out;
lo = &loop_dev[MINOR(current_request->rq_dev)];
- if (!lo->lo_inode || !lo->transfer)
+ if (!lo->lo_dentry || !lo->transfer)
goto error_out;
blksize = BLOCK_SIZE;
@@ -226,58 +236,82 @@ repeat:
if (lo->lo_flags & LO_FLAGS_READ_ONLY)
goto error_out;
} else if (current_request->cmd != READ) {
- printk("unknown loop device command (%d)?!?", current_request->cmd);
+ printk(KERN_ERR "unknown loop device command (%d)?!?", current_request->cmd);
goto error_out;
}
+ spin_unlock_irq(&io_request_lock);
while (len > 0) {
+
+ size = blksize - offset;
+ if (size > len)
+ size = len;
+
real_block = block;
+ block_present = TRUE;
+
if (lo->lo_flags & LO_FLAGS_DO_BMAP) {
- real_block = bmap(lo->lo_inode, block);
+ real_block = bmap(lo->lo_dentry->d_inode, block);
if (!real_block) {
- printk("loop: block %d not present\n", block);
- goto error_out;
+
+ /* The backing file is a sparse file and this block
+ doesn't exist. If reading, return zeros. If
+ writing, force the underlying FS to create
+ the block */
+ if (current_request->cmd == READ) {
+ memset(dest_addr, 0, size);
+ block_present = FALSE;
+ } else {
+ if (!create_missing_block(lo, block, blksize)) {
+ goto error_out_lock;
+ }
+ }
+
}
}
- bh = getblk(lo->lo_device, real_block, blksize);
- if (!bh) {
- printk("loop: device %s: getblk(-, %d, %d) returned NULL",
- kdevname(lo->lo_device),
- block, blksize);
- goto error_out;
- }
- if (!buffer_uptodate(bh) && ((current_request->cmd == READ) ||
- (offset || (len < blksize)))) {
- ll_rw_block(READ, 1, &bh);
- wait_on_buffer(bh);
- if (!buffer_uptodate(bh)) {
+
+ if (block_present) {
+ bh = getblk(lo->lo_device, real_block, blksize);
+ if (!bh) {
+ printk(KERN_ERR "loop: device %s: getblk(-, %d, %d) returned NULL",
+ kdevname(lo->lo_device),
+ block, blksize);
+ goto error_out_lock;
+ }
+ if (!buffer_uptodate(bh) && ((current_request->cmd == READ) ||
+ (offset || (len < blksize)))) {
+ ll_rw_block(READ, 1, &bh);
+ wait_on_buffer(bh);
+ if (!buffer_uptodate(bh)) {
+ brelse(bh);
+ goto error_out_lock;
+ }
+ }
+
+ if ((lo->transfer)(lo, current_request->cmd, bh->b_data + offset,
+ dest_addr, size)) {
+ printk(KERN_ERR "loop: transfer error block %d\n", block);
brelse(bh);
- goto error_out;
+ goto error_out_lock;
+ }
+
+ if (current_request->cmd == WRITE) {
+ mark_buffer_uptodate(bh, 1);
+ mark_buffer_dirty(bh, 1);
}
- }
- size = blksize - offset;
- if (size > len)
- size = len;
-
- if ((lo->transfer)(lo, current_request->cmd, bh->b_data + offset,
- dest_addr, size)) {
- printk("loop: transfer error block %d\n", block);
brelse(bh);
- goto error_out;
- }
- if (current_request->cmd == WRITE) {
- mark_buffer_uptodate(bh, 1);
- mark_buffer_dirty(bh, 1);
}
- brelse(bh);
dest_addr += size;
len -= size;
offset = 0;
block++;
}
+ spin_lock_irq(&io_request_lock);
current_request->next=CURRENT;
CURRENT=current_request;
end_request(1);
goto repeat;
+error_out_lock:
+ spin_lock_irq(&io_request_lock);
error_out:
current_request->next=CURRENT;
CURRENT=current_request;
@@ -285,6 +319,57 @@ error_out:
goto repeat;
}
+static int create_missing_block(struct loop_device *lo, int block, int blksize)
+{
+ struct file *file;
+ loff_t new_offset;
+ char zero_buf[1] = { 0 };
+ ssize_t retval;
+ mm_segment_t old_fs;
+
+ file = lo->lo_backing_file;
+ if (file == NULL) {
+ printk(KERN_WARNING "loop: cannot create block - no backing file\n");
+ return FALSE;
+ }
+
+ if (file->f_op == NULL) {
+ printk(KERN_WARNING "loop: cannot create block - no file ops\n");
+ return FALSE;
+ }
+
+ new_offset = block * blksize;
+
+ if (file->f_op->llseek != NULL) {
+ file->f_op->llseek(file, new_offset, 0);
+ } else {
+ /* Do what the default llseek() code would have done */
+ file->f_pos = new_offset;
+ file->f_reada = 0;
+ file->f_version = ++event;
+ }
+
+ if (file->f_op->write == NULL) {
+ printk(KERN_WARNING "loop: cannot create block - no write file op\n");
+ return FALSE;
+ }
+
+ old_fs = get_fs();
+ set_fs(get_ds());
+
+ retval = file->f_op->write(file, zero_buf, 1, &file->f_pos);
+
+ set_fs(old_fs);
+
+ if (retval < 0) {
+ printk(KERN_WARNING "loop: cannot create block - FS write failed: code %d\n",
+ retval);
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg)
{
struct file *file;
@@ -292,19 +377,20 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg)
int error;
MOD_INC_USE_COUNT;
+
+ error = -EBUSY;
+ if (lo->lo_dentry)
+ goto out;
+
error = -EBADF;
file = fget(arg);
if (!file)
goto out;
- error = -EBUSY;
- if (lo->lo_inode)
- goto out_putf;
-
error = -EINVAL;
inode = file->f_dentry->d_inode;
if (!inode) {
- printk("loop_set_fd: NULL inode?!?\n");
+ printk(KERN_ERR "loop_set_fd: NULL inode?!?\n");
goto out_putf;
}
@@ -312,10 +398,40 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg)
error = blkdev_open(inode, file);
lo->lo_device = inode->i_rdev;
lo->lo_flags = 0;
+
+ /* Backed by a block device - don't need to hold onto
+ a file structure */
+ lo->lo_backing_file = NULL;
} else if (S_ISREG(inode->i_mode)) {
+
+ /* Backed by a regular file - we need to hold onto
+ a file structure for this file. We'll use it to
+ write to blocks that are not already present in
+ a sparse file. We create a new file structure
+ based on the one passed to us via 'arg'. This is
+ to avoid changing the file structure that the
+ caller is using */
+
lo->lo_device = inode->i_dev;
lo->lo_flags = LO_FLAGS_DO_BMAP;
- error = 0;
+
+ error = -ENFILE;
+ lo->lo_backing_file = get_empty_filp();
+ if (lo->lo_backing_file) {
+ lo->lo_backing_file->f_mode = file->f_mode;
+ lo->lo_backing_file->f_pos = file->f_pos;
+ lo->lo_backing_file->f_flags = file->f_flags;
+ lo->lo_backing_file->f_owner = file->f_owner;
+ lo->lo_backing_file->f_dentry = file->f_dentry;
+ lo->lo_backing_file->f_op = file->f_op;
+ lo->lo_backing_file->private_data = file->private_data;
+
+ error = get_write_access(inode); /* cannot fail */
+ if (error) {
+ fput(lo->lo_backing_file);
+ lo->lo_backing_file = NULL;
+ }
+ }
}
if (error)
goto out_putf;
@@ -328,9 +444,8 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg)
set_device_ro(dev, 0);
}
- /* N.B. Should keep the file or dentry ... */
- inode->i_count++;
- lo->lo_inode = inode;
+ lo->lo_dentry = file->f_dentry;
+ lo->lo_dentry->d_count++;
lo->transfer = NULL;
figure_loop_size(lo);
@@ -344,17 +459,24 @@ out:
static int loop_clr_fd(struct loop_device *lo, kdev_t dev)
{
- struct inode *inode = lo->lo_inode;
+ struct dentry *dentry = lo->lo_dentry;
- if (!inode)
+ if (!dentry)
return -ENXIO;
if (lo->lo_refcnt > 1) /* we needed one fd for the ioctl */
return -EBUSY;
- if (S_ISBLK(inode->i_mode))
- blkdev_release (inode);
- lo->lo_inode = NULL;
- iput(inode);
+ if (S_ISBLK(dentry->d_inode->i_mode))
+ blkdev_release (dentry->d_inode);
+ lo->lo_dentry = NULL;
+
+ if (lo->lo_backing_file != NULL) {
+ fput(lo->lo_backing_file);
+ lo->lo_backing_file = NULL;
+ } else {
+ dput(dentry);
+ }
+
lo->lo_device = 0;
lo->lo_encrypt_type = 0;
lo->lo_offset = 0;
@@ -372,7 +494,7 @@ static int loop_set_status(struct loop_device *lo, struct loop_info *arg)
struct loop_info info;
int err;
- if (!lo->lo_inode)
+ if (!lo->lo_dentry)
return -ENXIO;
if (!arg)
return -EINVAL;
@@ -432,7 +554,7 @@ static int loop_get_status(struct loop_device *lo, struct loop_info *arg)
struct loop_info info;
int err;
- if (!lo->lo_inode)
+ if (!lo->lo_dentry)
return -ENXIO;
if (!arg)
return -EINVAL;
@@ -441,8 +563,8 @@ static int loop_get_status(struct loop_device *lo, struct loop_info *arg)
return err;
memset(&info, 0, sizeof(info));
info.lo_number = lo->lo_number;
- info.lo_device = kdev_t_to_nr(lo->lo_inode->i_dev);
- info.lo_inode = lo->lo_inode->i_ino;
+ info.lo_device = kdev_t_to_nr(lo->lo_dentry->d_inode->i_dev);
+ info.lo_inode = lo->lo_dentry->d_inode->i_ino;
info.lo_rdevice = kdev_t_to_nr(lo->lo_device);
info.lo_offset = lo->lo_offset;
info.lo_flags = lo->lo_flags;
@@ -466,7 +588,7 @@ static int lo_ioctl(struct inode * inode, struct file * file,
if (!inode)
return -EINVAL;
if (MAJOR(inode->i_rdev) != MAJOR_NR) {
- printk("lo_ioctl: pseudo-major != %d\n", MAJOR_NR);
+ printk(KERN_WARNING "lo_ioctl: pseudo-major != %d\n", MAJOR_NR);
return -ENODEV;
}
dev = MINOR(inode->i_rdev);
@@ -483,7 +605,7 @@ static int lo_ioctl(struct inode * inode, struct file * file,
case LOOP_GET_STATUS:
return loop_get_status(lo, (struct loop_info *) arg);
case BLKGETSIZE: /* Return device size */
- if (!lo->lo_inode)
+ if (!lo->lo_dentry)
return -ENXIO;
if (!arg)
return -EINVAL;
@@ -502,7 +624,7 @@ static int lo_open(struct inode *inode, struct file *file)
if (!inode)
return -EINVAL;
if (MAJOR(inode->i_rdev) != MAJOR_NR) {
- printk("lo_open: pseudo-major != %d\n", MAJOR_NR);
+ printk(KERN_WARNING "lo_open: pseudo-major != %d\n", MAJOR_NR);
return -ENODEV;
}
dev = MINOR(inode->i_rdev);
@@ -522,7 +644,7 @@ static int lo_release(struct inode *inode, struct file *file)
if (!inode)
return 0;
if (MAJOR(inode->i_rdev) != MAJOR_NR) {
- printk("lo_release: pseudo-major != %d\n", MAJOR_NR);
+ printk(KERN_WARNING "lo_release: pseudo-major != %d\n", MAJOR_NR);
return 0;
}
dev = MINOR(inode->i_rdev);
@@ -531,7 +653,7 @@ static int lo_release(struct inode *inode, struct file *file)
fsync_dev(inode->i_rdev);
lo = &loop_dev[dev];
if (lo->lo_refcnt <= 0)
- printk("lo_release: refcount(%d) <= 0\n", lo->lo_refcnt);
+ printk(KERN_ERR "lo_release: refcount(%d) <= 0\n", lo->lo_refcnt);
else {
lo->lo_refcnt--;
MOD_DEC_USE_COUNT;
@@ -563,17 +685,17 @@ loop_init( void )) {
int i;
if (register_blkdev(MAJOR_NR, "loop", &lo_fops)) {
- printk("Unable to get major number %d for loop device\n",
+ printk(KERN_WARNING "Unable to get major number %d for loop device\n",
MAJOR_NR);
return -EIO;
}
#ifndef MODULE
- printk("loop: registered device at major %d\n", MAJOR_NR);
+ printk(KERN_INFO "loop: registered device at major %d\n", MAJOR_NR);
#ifdef DES_AVAILABLE
- printk("loop: DES encryption available\n");
+ printk(KERN_INFO "loop: DES encryption available\n");
#endif
#ifdef IDEA_AVAILABLE
- printk("loop: IDEA encryption available\n");
+ printk(KERN_INFO "loop: IDEA encryption available\n");
#endif
#endif
@@ -594,6 +716,6 @@ loop_init( void )) {
void
cleanup_module( void ) {
if (unregister_blkdev(MAJOR_NR, "loop") != 0)
- printk("loop: cleanup_module failed\n");
+ printk(KERN_WARNING "loop: cleanup_module failed\n");
}
#endif
diff --git a/drivers/block/md.c b/drivers/block/md.c
index 8b4b487e1..d0eae5a29 100644
--- a/drivers/block/md.c
+++ b/drivers/block/md.c
@@ -70,7 +70,6 @@ extern kdev_t name_to_kdev_t(char *line) __init;
static struct hd_struct md_hd_struct[MAX_MD_DEV];
static int md_blocksizes[MAX_MD_DEV];
int md_maxreadahead[MAX_MD_DEV];
-static struct md_thread md_threads[MAX_MD_THREADS];
#if SUPPORT_RECONSTRUCTION
static struct md_thread *md_sync_thread = NULL;
#endif /* SUPPORT_RECONSTRUCTION */
@@ -97,6 +96,8 @@ static struct gendisk md_gendisk=
static struct md_personality *pers[MAX_PERSONALITY]={NULL, };
struct md_dev md_dev[MAX_MD_DEV];
+int md_thread(void * arg);
+
static struct gendisk *find_gendisk (kdev_t dev)
{
struct gendisk *tmp=gendisk_head;
@@ -289,7 +290,7 @@ static int analyze_sbs (int minor, int pnum)
}
/*
- * Ok, we have all disks and the array is ready to run. Lets
+ * OK, we have all disks and the array is ready to run. Let's
* find the freshest superblock, that one will be the superblock
* that represents the whole array.
*/
@@ -593,9 +594,9 @@ static int do_md_add (int minor, kdev_t dev)
if (hot_add) {
/*
* Check the superblock for consistency.
- * the personality itself has to check wether it's getting
- * added with the proper flags ... also, personality has to
- * be checked too ;)
+ * The personality itself has to check whether it's getting
+ * added with the proper flags. The personality has to be
+ * checked too. ;)
*/
if (analyze_one_sb (realdev))
return -EINVAL;
@@ -803,39 +804,98 @@ static void do_md_request (void)
{
printk ("Got md request, not good...");
return;
-}
+}
+
+void md_wakeup_thread(struct md_thread *thread)
+{
+ set_bit(THREAD_WAKEUP, &thread->flags);
+ wake_up(&thread->wqueue);
+}
-/*
- * We run MAX_MD_THREADS from md_init() and arbitrate them in run time.
- * This is not so elegant, but how can we use kernel_thread() from within
- * loadable modules?
- */
struct md_thread *md_register_thread (void (*run) (void *), void *data)
{
- int i;
- for (i = 0; i < MAX_MD_THREADS; i++) {
- if (md_threads[i].run == NULL) {
- md_threads[i].run = run;
- md_threads[i].data = data;
- return md_threads + i;
- }
+ struct md_thread *thread = (struct md_thread *)
+ kmalloc(sizeof(struct md_thread), GFP_KERNEL);
+ int ret;
+ struct semaphore sem = MUTEX_LOCKED;
+
+ if (!thread) return NULL;
+
+ memset(thread, 0, sizeof(struct md_thread));
+ init_waitqueue(&thread->wqueue);
+
+ thread->sem = &sem;
+ thread->run = run;
+ thread->data = data;
+ ret = kernel_thread(md_thread, thread, 0);
+ if (ret < 0) {
+ kfree(thread);
+ return NULL;
}
- return NULL;
+ down(&sem);
+ return thread;
}
void md_unregister_thread (struct md_thread *thread)
{
+ struct semaphore sem = MUTEX_LOCKED;
+
+ thread->sem = &sem;
thread->run = NULL;
- thread->data = NULL;
- thread->flags = 0;
+ if (thread->tsk)
+ printk("Killing md_thread %d %p %s\n",
+ thread->tsk->pid, thread->tsk, thread->tsk->comm);
+ else
+ printk("Aiee. md_thread has 0 tsk\n");
+ send_sig(SIGKILL, thread->tsk, 1);
+ printk("downing on %p\n", &sem);
+ down(&sem);
}
-void md_wakeup_thread(struct md_thread *thread)
+#define SHUTDOWN_SIGS (sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM))
+
+int md_thread(void * arg)
{
- set_bit(THREAD_WAKEUP, &thread->flags);
- wake_up(&thread->wqueue);
-}
+ struct md_thread *thread = arg;
+
+ lock_kernel();
+ exit_mm(current);
+ exit_files(current);
+ exit_fs(current);
+
+ current->session = 1;
+ current->pgrp = 1;
+ sprintf(current->comm, "md_thread");
+ siginitsetinv(&current->blocked, SHUTDOWN_SIGS);
+ thread->tsk = current;
+ up(thread->sem);
+ for (;;) {
+ cli();
+ if (!test_bit(THREAD_WAKEUP, &thread->flags)) {
+ do {
+ spin_lock(&current->sigmask_lock);
+ flush_signals(current);
+ spin_unlock(&current->sigmask_lock);
+ interruptible_sleep_on(&thread->wqueue);
+ cli();
+ if (test_bit(THREAD_WAKEUP, &thread->flags))
+ break;
+ if (!thread->run) {
+ sti();
+ up(thread->sem);
+ return 0;
+ }
+ } while (signal_pending(current));
+ }
+ sti();
+ clear_bit(THREAD_WAKEUP, &thread->flags);
+ if (thread->run) {
+ thread->run(thread->data);
+ run_task_queue(&tq_disk);
+ }
+ }
+}
EXPORT_SYMBOL(md_size);
EXPORT_SYMBOL(md_maxreadahead);
@@ -981,37 +1041,6 @@ int unregister_md_personality (int p_num)
return 0;
}
-int md_thread(void * arg)
-{
- struct md_thread *thread = arg;
-
- current->session = 1;
- current->pgrp = 1;
- sprintf(current->comm, "md_thread");
-
- lock_kernel();
- for (;;) {
- sti();
- clear_bit(THREAD_WAKEUP, &thread->flags);
- if (thread->run) {
- thread->run(thread->data);
- run_task_queue(&tq_disk);
- }
- cli();
- if (!test_bit(THREAD_WAKEUP, &thread->flags)) {
- do {
- spin_lock(&current->sigmask_lock);
- flush_signals(current);
- spin_unlock(&current->sigmask_lock);
- interruptible_sleep_on(&thread->wqueue);
- cli();
- if (test_bit(THREAD_WAKEUP, &thread->flags))
- break;
- } while (signal_pending(current));
- }
- }
-}
-
static md_descriptor_t *get_spare(struct md_dev *mddev)
{
int i;
@@ -1105,7 +1134,7 @@ int md_do_sync(struct md_dev *mddev)
}
/*
- * Lets sleep some if we are faster than our speed limit:
+ * Let's sleep some if we are faster than our speed limit:
*/
while (blocksize*j/(jiffies-starttime+1)*HZ/1024 > SPEED_LIMIT)
{
@@ -1281,8 +1310,6 @@ void raid5_init (void);
__initfunc(int md_init (void))
{
- int i;
-
printk ("md driver %d.%d.%d MAX_MD_DEV=%d, MAX_REAL=%d\n",
MD_MAJOR_VERSION, MD_MINOR_VERSION, MD_PATCHLEVEL_VERSION,
MAX_MD_DEV, MAX_REAL);
@@ -1293,15 +1320,6 @@ __initfunc(int md_init (void))
return (-1);
}
- memset(md_threads, 0, MAX_MD_THREADS * sizeof(struct md_thread));
- printk("md: starting %d kernel threads\n", MAX_MD_THREADS);
- for (i = 0; i < MAX_MD_THREADS; i++) {
- md_threads[i].run = NULL;
- init_waitqueue(&md_threads[i].wqueue);
- md_threads[i].flags = 0;
- kernel_thread (md_thread, md_threads + i, 0);
- }
-
blk_dev[MD_MAJOR].request_fn=DEVICE_REQUEST;
blk_dev[MD_MAJOR].current_request=NULL;
read_ahead[MD_MAJOR]=INT_MAX;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index cd733884c..ddec2b425 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -16,6 +16,7 @@
* once to be processed
* 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
*
* 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
@@ -24,18 +25,24 @@
#define PARANOIA
#include <linux/major.h>
-#define MAJOR_NR NBD_MAJOR
-#include <linux/nbd.h>
#include <linux/module.h>
+#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/file.h>
+#include <linux/ioctl.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
+#include <asm/types.h>
+
+#define MAJOR_NR NBD_MAJOR
+#include <linux/nbd.h>
+
+#define LO_MAGIC 0x68797548
static int nbd_blksizes[MAX_NBD] = {1024, 1024,};
static int nbd_sizes[MAX_NBD] = {0x7fffffff, 0x7fffffff,};
@@ -68,8 +75,7 @@ static int nbd_open(struct inode *inode, struct file *file)
/*
* Send or receive packet.
*/
-static
-int nbd_xmit(int send, struct socket *sock, char *buf, int size)
+static int nbd_xmit(int send, struct socket *sock, char *buf, int size)
{
mm_segment_t oldfs;
int result;
@@ -110,8 +116,8 @@ int nbd_xmit(int send, struct socket *sock, char *buf, int size)
if (result <= 0) {
#ifdef PARANOIA
- printk(KERN_ERR "NBD: %s - sock=%d at buf=%d, size=%d returned %d.\n",
- send ? "send" : "receive", (int) sock, (int) buf, size, result);
+ printk(KERN_ERR "NBD: %s - sock=%ld at buf=%ld, size=%d returned %d.\n",
+ send ? "send" : "receive", (long) sock, (long) buf, size, result);
#endif
break;
}
@@ -132,7 +138,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 = htonl(req->sector * 512);
+ request.from = cpu_to_be64( (u64) req->sector * (u64) 512);
request.len = htonl(req->current_nr_sectors << 9);
memcpy(request.handle, &req, sizeof(req));
@@ -153,8 +159,8 @@ void nbd_send_req(struct socket *sock, struct request *req)
}
#define HARDFAIL( s ) { printk( KERN_ERR "NBD: " s "(result %d)\n", result ); lo->harderror = result; return NULL; }
-struct request * /* NULL returned = something went wrong, inform userspace */
- nbd_read_stat(struct nbd_device *lo)
+struct request *nbd_read_stat(struct nbd_device *lo)
+ /* NULL returned = something went wrong, inform userspace */
{
int result;
struct nbd_reply reply;
@@ -316,6 +322,8 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
struct nbd_device *lo;
int dev, error;
+ /* Anyone capable of this syscall can do *real bad* things */
+
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (!inode)
@@ -369,8 +377,8 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
return 0;
#ifdef PARANOIA
case NBD_PRINT_DEBUG:
- printk(KERN_INFO "NBD device %d: head = %x, tail = %x. Global: in %d, out %d\n",
- dev, (int) lo->head, (int) lo->tail, requests_in, requests_out);
+ printk(KERN_INFO "NBD device %d: head = %lx, tail = %lx. Global: in %d, out %d\n",
+ dev, (long) lo->head, (long) lo->tail, requests_in, requests_out);
return 0;
#endif
}
@@ -423,6 +431,11 @@ int nbd_init(void)
{
int i;
+ if (sizeof(struct nbd_request) != 28) {
+ printk(KERN_CRIT "Sizeof nbd_request needs to be 28 in order to work!\n" );
+ return -EIO;
+ }
+
if (register_blkdev(MAJOR_NR, "nbd", &nbd_fops)) {
printk("Unable to get major number %d for NBD\n",
MAJOR_NR);
diff --git a/drivers/block/ns87415.c b/drivers/block/ns87415.c
index e7006ed69..d065606c7 100644
--- a/drivers/block/ns87415.c
+++ b/drivers/block/ns87415.c
@@ -130,6 +130,19 @@ __initfunc(void ide_init_ns87415 (ide_hwif_t *hwif))
int timeout;
byte stat;
/*
+ * Put reasonable values in the timing registers
+ * for DMA2 mode performance.
+ */
+ pci_write_config_byte(dev, 0x44, 0xfe);
+ pci_write_config_byte(dev, 0x45, 0xfe);
+ pci_write_config_byte(dev, 0x48, 0xfe);
+ pci_write_config_byte(dev, 0x49, 0xfe);
+ pci_write_config_byte(dev, 0x4c, 0xfe);
+ pci_write_config_byte(dev, 0x4d, 0xfe);
+ pci_write_config_byte(dev, 0x50, 0xfe);
+ pci_write_config_byte(dev, 0x51, 0xfe);
+
+ /*
* XXX: Reset the device, if we don't it will not respond
* to SELECT_DRIVE() properly during first probe_hwif().
*/
diff --git a/drivers/block/paride/Config.in b/drivers/block/paride/Config.in
index cc9479184..00dd9c8e4 100644
--- a/drivers/block/paride/Config.in
+++ b/drivers/block/paride/Config.in
@@ -6,15 +6,19 @@ dep_tristate ' Parallel port IDE disks' CONFIG_PARIDE_PD $CONFIG_PARIDE
dep_tristate ' Parallel port ATAPI CD-ROMs' CONFIG_PARIDE_PCD $CONFIG_PARIDE
dep_tristate ' Parallel port ATAPI disks' CONFIG_PARIDE_PF $CONFIG_PARIDE
dep_tristate ' Parallel port ATAPI tapes' CONFIG_PARIDE_PT $CONFIG_PARIDE
+dep_tristate ' Parallel port generic ATAPI devices' CONFIG_PARIDE_PG $CONFIG_PARIDE
comment 'Parallel IDE protocol modules'
dep_tristate ' ATEN EH-100 protocol' CONFIG_PARIDE_ATEN $CONFIG_PARIDE
dep_tristate ' MicroSolutions backpack protocol' CONFIG_PARIDE_BPCK $CONFIG_PARIDE
dep_tristate ' DataStor Commuter protocol' CONFIG_PARIDE_COMM $CONFIG_PARIDE
dep_tristate ' DataStor EP-2000 protocol' CONFIG_PARIDE_DSTR $CONFIG_PARIDE
+dep_tristate ' FIT TD-2000 protocol' CONFIG_PARIDE_FIT2 $CONFIG_PARIDE
+dep_tristate ' FIT TD-3000 protocol' CONFIG_PARIDE_FIT3 $CONFIG_PARIDE
dep_tristate ' Shuttle EPAT/EPEZ protocol' CONFIG_PARIDE_EPAT $CONFIG_PARIDE
dep_tristate ' Shuttle EPIA protocol' CONFIG_PARIDE_EPIA $CONFIG_PARIDE
dep_tristate ' FreeCom power protocol' CONFIG_PARIDE_FRPW $CONFIG_PARIDE
dep_tristate ' KingByte KBIC-951A/971A protocols' CONFIG_PARIDE_KBIC $CONFIG_PARIDE
+dep_tristate ' KT PHd protocol' CONFIG_PARIDE_KTTI $CONFIG_PARIDE
dep_tristate ' OnSpec 90c20 protocol' CONFIG_PARIDE_ON20 $CONFIG_PARIDE
dep_tristate ' OnSpec 90c26 protocol' CONFIG_PARIDE_ON26 $CONFIG_PARIDE
#
diff --git a/drivers/block/paride/Makefile b/drivers/block/paride/Makefile
index 61e710801..abb45d2fc 100644
--- a/drivers/block/paride/Makefile
+++ b/drivers/block/paride/Makefile
@@ -58,6 +58,14 @@ else
endif
endif
+ifeq ($(CONFIG_PARIDE_PG),y)
+ LX_OBJS += pg.o
+else
+ ifeq ($(CONFIG_PARIDE_PG),m)
+ MX_OBJS += pg.o
+ endif
+endif
+
ifeq ($(CONFIG_PARIDE_ATEN),y)
LX_OBJS += aten.o
else
@@ -114,6 +122,22 @@ else
endif
endif
+ifeq ($(CONFIG_PARIDE_FIT2),y)
+ LX_OBJS += fit2.o
+else
+ ifeq ($(CONFIG_PARIDE_FIT2),m)
+ MX_OBJS += fit2.o
+ endif
+endif
+
+ifeq ($(CONFIG_PARIDE_FIT3),y)
+ LX_OBJS += fit3.o
+else
+ ifeq ($(CONFIG_PARIDE_FIT3),m)
+ MX_OBJS += fit3.o
+ endif
+endif
+
ifeq ($(CONFIG_PARIDE_FRPW),y)
LX_OBJS += frpw.o
else
@@ -138,4 +162,13 @@ else
endif
endif
+ifeq ($(CONFIG_PARIDE_KTTI),y)
+ LX_OBJS += ktti.o
+else
+ ifeq ($(CONFIG_PARIDE_KTTI),m)
+ MX_OBJS += ktti.o
+ endif
+endif
+
include $(TOPDIR)/Rules.make
+
diff --git a/drivers/block/paride/aten.c b/drivers/block/paride/aten.c
index dd11b03f1..6f80be57e 100644
--- a/drivers/block/paride/aten.c
+++ b/drivers/block/paride/aten.c
@@ -1,6 +1,6 @@
/*
- aten.c (c) 1997 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU public license.
+ aten.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
aten.c is a low-level protocol driver for the ATEN EH-100
parallel port adapter. The EH-100 supports 4-bit and 8-bit
@@ -9,7 +9,13 @@
*/
-#define ATEN_VERSION "1.0"
+/* Changes:
+
+ 1.01 GRG 1998.05.05 init_proto, release_proto
+
+*/
+
+#define ATEN_VERSION "1.01"
#include <linux/module.h>
#include <linux/delay.h>
@@ -123,12 +129,12 @@ static void aten_log_adapter( PIA *pi, char * scratch, int verbose )
}
-static void aten_inc_use ( void )
+static void aten_init_proto( PIA *pi )
{ MOD_INC_USE_COUNT;
}
-static void aten_dec_use ( void )
+static void aten_release_proto( PIA *pi )
{ MOD_DEC_USE_COUNT;
}
@@ -144,8 +150,8 @@ struct pi_protocol aten = {"aten",0,2,2,1,1,
0,
0,
aten_log_adapter,
- aten_inc_use,
- aten_dec_use
+ aten_init_proto,
+ aten_release_proto
};
diff --git a/drivers/block/paride/bpck.c b/drivers/block/paride/bpck.c
index 21caad680..4b241c737 100644
--- a/drivers/block/paride/bpck.c
+++ b/drivers/block/paride/bpck.c
@@ -1,13 +1,19 @@
/*
- bpck.c (c) 1996,1997 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU public license.
+ bpck.c (c) 1996-8 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
bpck.c is a low-level protocol driver for the MicroSolutions
"backpack" parallel port IDE adapter.
*/
-#define BPCK_VERSION "1.0"
+/* Changes:
+
+ 1.01 GRG 1998.05.05 init_proto, release_proto, pi->delay
+
+*/
+
+#define BPCK_VERSION "1.01"
#include <linux/module.h>
#include <linux/delay.h>
@@ -338,12 +344,12 @@ static int bpck_test_proto( PIA *pi, char * scratch, int verbose )
static void bpck_read_eeprom ( PIA *pi, char * buf )
-{ int i,j,k,n,p,v,f, om;
+{ int i,j,k,n,p,v,f, om, od;
bpck_force_spp(pi);
- om = pi->mode;
- pi->mode = 0;
+ om = pi->mode; od = pi->delay;
+ pi->mode = 0; pi->delay = 6;
bpck_connect(pi);
@@ -385,7 +391,7 @@ static void bpck_read_eeprom ( PIA *pi, char * buf )
bpck_disconnect(pi);
}
- pi->mode = om;
+ pi->mode = om; pi->delay = od;
}
static int bpck_test_port ( PIA *pi ) /* check for 8-bit port */
@@ -434,17 +440,17 @@ static void bpck_log_adapter( PIA *pi, char * scratch, int verbose )
pi->mode,mode_string[pi->mode],pi->delay);
}
-static void bpck_inc_use( void )
+static void bpck_init_proto( PIA *pi)
{ MOD_INC_USE_COUNT;
}
-static void bpck_dec_use( void )
+static void bpck_release_proto( PIA *pi)
{ MOD_DEC_USE_COUNT;
}
-struct pi_protocol bpck = { "bpck",0,5,2,4,256,
+struct pi_protocol bpck = { "bpck",0,5,2,1,256,
bpck_write_regr,
bpck_read_regr,
bpck_write_block,
@@ -455,8 +461,8 @@ struct pi_protocol bpck = { "bpck",0,5,2,4,256,
bpck_probe_unit,
bpck_test_proto,
bpck_log_adapter,
- bpck_inc_use,
- bpck_dec_use
+ bpck_init_proto,
+ bpck_release_proto
};
#ifdef MODULE
diff --git a/drivers/block/paride/comm.c b/drivers/block/paride/comm.c
index 794bbb9b4..99660e218 100644
--- a/drivers/block/paride/comm.c
+++ b/drivers/block/paride/comm.c
@@ -1,6 +1,6 @@
/*
- comm.c (c) 1997 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU public license.
+ comm.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
comm.c is a low-level protocol driver for some older models
of the DataStor "Commuter" parallel to IDE adapter. Some of
@@ -8,7 +8,13 @@
use this adapter.
*/
-#define COMM_VERSION "1.0"
+/* Changes:
+
+ 1.01 GRG 1998.05.05 init_proto, release_proto
+
+*/
+
+#define COMM_VERSION "1.01"
#include <linux/module.h>
#include <linux/delay.h>
@@ -179,12 +185,12 @@ static void comm_log_adapter( PIA *pi, char * scratch, int verbose )
}
-static void comm_inc_use ( void )
+static void comm_init_proto(PIA *pi)
{ MOD_INC_USE_COUNT;
}
-static void comm_dec_use ( void )
+static void comm_release_proto(PIA *pi)
{ MOD_DEC_USE_COUNT;
}
@@ -200,8 +206,8 @@ struct pi_protocol comm = {"comm",0,5,2,1,1,
0,
0,
comm_log_adapter,
- comm_inc_use,
- comm_dec_use
+ comm_init_proto,
+ comm_release_proto
};
diff --git a/drivers/block/paride/dstr.c b/drivers/block/paride/dstr.c
index 53cedcc2c..cc522fab2 100644
--- a/drivers/block/paride/dstr.c
+++ b/drivers/block/paride/dstr.c
@@ -1,13 +1,19 @@
/*
- dstr.c (c) 1997 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU public license.
+ dstr.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
dstr.c is a low-level protocol driver for the
DataStor EP2000 parallel to IDE adapter chip.
*/
-#define DSTR_VERSION "1.0"
+/* Changes:
+
+ 1.01 GRG 1998.05.06 init_proto, release_proto
+
+*/
+
+#define DSTR_VERSION "1.01"
#include <linux/module.h>
#include <linux/delay.h>
@@ -194,12 +200,12 @@ static void dstr_log_adapter( PIA *pi, char * scratch, int verbose )
}
-static void dstr_inc_use ( void )
+static void dstr_init_proto( PIA *pi)
{ MOD_INC_USE_COUNT;
}
-static void dstr_dec_use ( void )
+static void dstr_release_proto( PIA *pi)
{ MOD_DEC_USE_COUNT;
}
@@ -215,8 +221,8 @@ struct pi_protocol dstr = {"dstr",0,5,2,1,1,
0,
0,
dstr_log_adapter,
- dstr_inc_use,
- dstr_dec_use
+ dstr_init_proto,
+ dstr_release_proto
};
diff --git a/drivers/block/paride/epat.c b/drivers/block/paride/epat.c
index f6c19c994..980eb695f 100644
--- a/drivers/block/paride/epat.c
+++ b/drivers/block/paride/epat.c
@@ -1,6 +1,6 @@
/*
- epat.c (c) 1997 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU public license.
+ epat.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
This is the low level protocol driver for the EPAT parallel
to IDE adapter from Shuttle Technologies. This adapter is
@@ -9,7 +9,13 @@
*/
-#define EPAT_VERSION "1.0"
+/* Changes:
+
+ 1.01 GRG 1998.05.06 init_proto, release_proto
+
+*/
+
+#define EPAT_VERSION "1.01"
#include <linux/module.h>
#include <linux/delay.h>
@@ -272,12 +278,12 @@ static void epat_log_adapter( PIA *pi, char * scratch, int verbose )
}
-static void epat_inc_use ( void )
+static void epat_init_proto( PIA *pi)
{ MOD_INC_USE_COUNT;
}
-static void epat_dec_use ( void )
+static void epat_release_proto( PIA *pi)
{ MOD_DEC_USE_COUNT;
}
@@ -293,8 +299,8 @@ struct pi_protocol epat = {"epat",0,6,3,1,1,
0,
epat_test_proto,
epat_log_adapter,
- epat_inc_use,
- epat_dec_use
+ epat_init_proto,
+ epat_release_proto
};
diff --git a/drivers/block/paride/epia.c b/drivers/block/paride/epia.c
index 73d83fe8d..6e7fc2e42 100644
--- a/drivers/block/paride/epia.c
+++ b/drivers/block/paride/epia.c
@@ -1,6 +1,6 @@
/*
- epia.c (c) 1997 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU public license.
+ epia.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
epia.c is a low-level protocol driver for Shuttle Technologies
EPIA parallel to IDE adapter chip. This device is now obsolete
@@ -10,7 +10,14 @@
*/
-#define EPIA_VERSION "1.0"
+/* Changes:
+
+ 1.01 GRG 1998.05.06 init_proto, release_proto
+ 1.02 GRG 1998.06.17 support older versions of EPIA
+
+*/
+
+#define EPIA_VERSION "1.02"
#include <linux/module.h>
#include <linux/delay.h>
@@ -117,7 +124,7 @@ static void epia_connect ( PIA *pi )
static void epia_disconnect ( PIA *pi )
-{ WR(0x84,0x10);
+{ /* WR(0x84,0x10); */
w0(pi->saved_r0);
w2(1); w2(4);
w0(pi->saved_r0);
@@ -238,6 +245,7 @@ static int epia_test_proto( PIA *pi, char * scratch, int verbose )
WR(3,k^0x55);
if (RR(2) != (k^0xaa)) e[j]++;
}
+ WR(2,1); WR(3,1);
}
epia_disconnect(pi);
@@ -274,12 +282,12 @@ static void epia_log_adapter( PIA *pi, char * scratch, int verbose )
}
-static void epia_inc_use ( void )
+static void epia_init_proto( PIA *pi)
{ MOD_INC_USE_COUNT;
}
-static void epia_dec_use ( void )
+static void epia_release_proto( PIA *pi)
{ MOD_DEC_USE_COUNT;
}
@@ -295,8 +303,8 @@ struct pi_protocol epia = {"epia",0,6,3,1,1,
0,
epia_test_proto,
epia_log_adapter,
- epia_inc_use,
- epia_dec_use
+ epia_init_proto,
+ epia_release_proto
};
diff --git a/drivers/block/paride/fit2.c b/drivers/block/paride/fit2.c
new file mode 100644
index 000000000..b93fff049
--- /dev/null
+++ b/drivers/block/paride/fit2.c
@@ -0,0 +1,161 @@
+/*
+ fit2.c (c) 1998 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
+
+ fit2.c is a low-level protocol driver for the older version
+ of the Fidelity International Technology parallel port adapter.
+ This adapter is used in their TransDisk 2000 and older TransDisk
+ 3000 portable hard-drives. As far as I can tell, this device
+ supports 4-bit mode _only_.
+
+ Newer models of the FIT products use an enhanced protocol.
+ The "fit3" protocol module should support current drives.
+
+*/
+
+#define FIT2_VERSION "1.0"
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/io.h>
+
+#include "paride.h"
+
+#define j44(a,b) (((a>>4)&0x0f)|(b&0xf0))
+
+/* cont = 0 - access the IDE register file
+ cont = 1 - access the IDE command set
+
+NB: The FIT adapter does not appear to use the control registers.
+So, we map ALT_STATUS to STATUS and NO-OP writes to the device
+control register - this means that IDE reset will not work on these
+devices.
+
+*/
+
+static void fit2_write_regr( PIA *pi, int cont, int regr, int val)
+
+{ if (cont == 1) return;
+ w2(0xc); w0(regr); w2(4); w0(val); w2(5); w0(0); w2(4);
+}
+
+static int fit2_read_regr( PIA *pi, int cont, int regr )
+
+{ int a, b, r;
+
+ if (cont) {
+ if (regr != 6) return 0xff;
+ r = 7;
+ } else r = regr + 0x10;
+
+ w2(0xc); w0(r); w2(4); w2(5);
+ w0(0); a = r1();
+ w0(1); b = r1();
+ w2(4);
+
+ return j44(a,b);
+
+}
+
+static void fit2_read_block( PIA *pi, char * buf, int count )
+
+{ int k, a, b, c, d;
+
+ w2(0xc); w0(0x10);
+
+ for (k=0;k<count/4;k++) {
+
+ w2(4); w2(5);
+ w0(0); a = r1(); w0(1); b = r1();
+ w0(3); c = r1(); w0(2); d = r1();
+ buf[4*k+0] = j44(a,b);
+ buf[4*k+1] = j44(d,c);
+
+ w2(4); w2(5);
+ a = r1(); w0(3); b = r1();
+ w0(1); c = r1(); w0(0); d = r1();
+ buf[4*k+2] = j44(d,c);
+ buf[4*k+3] = j44(a,b);
+
+ }
+
+ w2(4);
+
+}
+
+static void fit2_write_block( PIA *pi, char * buf, int count )
+
+{ int k;
+
+
+ w2(0xc); w0(0);
+ for (k=0;k<count/2;k++) {
+ w2(4); w0(buf[2*k]);
+ w2(5); w0(buf[2*k+1]);
+ }
+ w2(4);
+}
+
+static void fit2_connect ( PIA *pi )
+
+{ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
+ w2(0xcc);
+}
+
+static void fit2_disconnect ( PIA *pi )
+
+{ w0(pi->saved_r0);
+ w2(pi->saved_r2);
+}
+
+static void fit2_log_adapter( PIA *pi, char * scratch, int verbose )
+
+{ printk("%s: fit2 %s, FIT 2000 adapter at 0x%x, delay %d\n",
+ pi->device,FIT2_VERSION,pi->port,pi->delay);
+
+}
+
+static void fit2_init_proto( PIA *pi)
+
+{ MOD_INC_USE_COUNT;
+}
+
+static void fit2_release_proto( PIA *pi)
+
+{ MOD_DEC_USE_COUNT;
+}
+
+struct pi_protocol fit2 = {"fit2",0,1,2,1,1,
+ fit2_write_regr,
+ fit2_read_regr,
+ fit2_write_block,
+ fit2_read_block,
+ fit2_connect,
+ fit2_disconnect,
+ 0,
+ 0,
+ 0,
+ fit2_log_adapter,
+ fit2_init_proto,
+ fit2_release_proto
+ };
+
+
+#ifdef MODULE
+
+int init_module(void)
+
+{ return pi_register( &fit2 ) - 1;
+}
+
+void cleanup_module(void)
+
+{ pi_unregister( &fit2 );
+}
+
+#endif
+
+/* end of fit2.c */
diff --git a/drivers/block/paride/fit3.c b/drivers/block/paride/fit3.c
new file mode 100644
index 000000000..f449bcf2f
--- /dev/null
+++ b/drivers/block/paride/fit3.c
@@ -0,0 +1,221 @@
+/*
+ fit3.c (c) 1998 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
+
+ fit3.c is a low-level protocol driver for newer models
+ of the Fidelity International Technology parallel port adapter.
+ This adapter is used in their TransDisk 3000 portable
+ hard-drives, as well as CD-ROM, PD-CD and other devices.
+
+ The TD-2000 and certain older devices use a different protocol.
+ Try the fit2 protocol module with them.
+
+ NB: The FIT adapters do not appear to support the control
+ registers. So, we map ALT_STATUS to STATUS and NO-OP writes
+ to the device control register - this means that IDE reset
+ will not work on these devices.
+
+*/
+
+#define FIT3_VERSION "1.0"
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/io.h>
+
+#include "paride.h"
+
+#define j44(a,b) (((a>>3)&0x0f)|((b<<1)&0xf0))
+
+#define w7(byte) {out_p(7,byte);}
+#define r7() (in_p(7) & 0xff)
+
+/* cont = 0 - access the IDE register file
+ cont = 1 - access the IDE command set
+
+*/
+
+static void fit3_write_regr( PIA *pi, int cont, int regr, int val)
+
+{ if (cont == 1) return;
+
+ switch (pi->mode) {
+
+ case 0:
+ case 1: w2(0xc); w0(regr); w2(0x8); w2(0xc);
+ w0(val); w2(0xd);
+ w0(0); w2(0xc);
+ break;
+
+ case 2: w2(0xc); w0(regr); w2(0x8); w2(0xc);
+ w4(val); w4(0);
+ w2(0xc);
+ break;
+
+ }
+}
+
+static int fit3_read_regr( PIA *pi, int cont, int regr )
+
+{ int a, b;
+
+ if (cont) {
+ if (regr != 6) return 0xff;
+ regr = 7;
+ }
+
+ switch (pi->mode) {
+
+ case 0: w2(0xc); w0(regr + 0x10); w2(0x8); w2(0xc);
+ w2(0xd); a = r1();
+ w2(0xf); b = r1();
+ w2(0xc);
+ return j44(a,b);
+
+ case 1: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc);
+ w2(0xec); w2(0xee); w2(0xef); a = r0();
+ w2(0xc);
+ return a;
+
+ case 2: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc);
+ w2(0xec);
+ a = r4(); b = r4();
+ w2(0xc);
+ return a;
+
+ }
+ return -1;
+
+}
+
+static void fit3_read_block( PIA *pi, char * buf, int count )
+
+{ int k, a, b, c, d;
+
+ switch (pi->mode) {
+
+ case 0: w2(0xc); w0(0x10); w2(0x8); w2(0xc);
+ for (k=0;k<count/2;k++) {
+ w2(0xd); a = r1();
+ w2(0xf); b = r1();
+ w2(0xc); c = r1();
+ w2(0xe); d = r1();
+ buf[2*k ] = j44(a,b);
+ buf[2*k+1] = j44(c,d);
+ }
+ w2(0xc);
+ break;
+
+ case 1: w2(0xc); w0(0x90); w2(0x8); w2(0xc);
+ w2(0xec); w2(0xee);
+ for (k=0;k<count/2;k++) {
+ w2(0xef); a = r0();
+ w2(0xee); b = r0();
+ buf[2*k ] = a;
+ buf[2*k+1] = b;
+ }
+ w2(0xec);
+ w2(0xc);
+ break;
+
+ case 2: w2(0xc); w0(0x90); w2(0x8); w2(0xc);
+ w2(0xec);
+ for (k=0;k<count;k++) buf[k] = r4();
+ w2(0xc);
+ break;
+
+ }
+}
+
+static void fit3_write_block( PIA *pi, char * buf, int count )
+
+{ int k;
+
+ switch (pi->mode) {
+
+ case 0:
+ case 1: w2(0xc); w0(0); w2(0x8); w2(0xc);
+ for (k=0;k<count/2;k++) {
+ w0(buf[2*k ]); w2(0xd);
+ w0(buf[2*k+1]); w2(0xc);
+ }
+ break;
+
+ case 2: w2(0xc); w0(0); w2(0x8); w2(0xc);
+ for (k=0;k<count;k++) w4(buf[k]);
+ w2(0xc);
+ break;
+ }
+}
+
+static void fit3_connect ( PIA *pi )
+
+{ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
+ w2(0xc); w0(0); w2(0xa);
+ if (pi->mode == 2) {
+ w2(0xc); w0(0x9); w2(0x8); w2(0xc);
+ }
+}
+
+static void fit3_disconnect ( PIA *pi )
+
+{ w2(0xc); w0(0xa); w2(0x8); w2(0xc);
+ w0(pi->saved_r0);
+ w2(pi->saved_r2);
+}
+
+static void fit3_log_adapter( PIA *pi, char * scratch, int verbose )
+
+{ char *mode_string[3] = {"4-bit","8-bit","EPP"};
+
+ printk("%s: fit3 %s, FIT 3000 adapter at 0x%x, "
+ "mode %d (%s), delay %d\n",
+ pi->device,FIT3_VERSION,pi->port,
+ pi->mode,mode_string[pi->mode],pi->delay);
+
+}
+
+static void fit3_init_proto(PIA *pi)
+
+{ MOD_INC_USE_COUNT;
+}
+
+static void fit3_release_proto(PIA *pi)
+
+{ MOD_DEC_USE_COUNT;
+}
+
+struct pi_protocol fit3 = {"fit3",0,3,2,1,1,
+ fit3_write_regr,
+ fit3_read_regr,
+ fit3_write_block,
+ fit3_read_block,
+ fit3_connect,
+ fit3_disconnect,
+ 0,
+ 0,
+ 0,
+ fit3_log_adapter,
+ fit3_init_proto,
+ fit3_release_proto
+ };
+
+
+#ifdef MODULE
+
+int init_module(void)
+
+{ return pi_register( &fit3 ) - 1;
+}
+
+void cleanup_module(void)
+
+{ pi_unregister( &fit3 );
+}
+
+#endif
+
+/* end of fit3.c */
diff --git a/drivers/block/paride/frpw.c b/drivers/block/paride/frpw.c
index fe7b1452f..f965fb9da 100644
--- a/drivers/block/paride/frpw.c
+++ b/drivers/block/paride/frpw.c
@@ -1,13 +1,21 @@
/*
- frpw.c (c) 1997 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU public license
+ frpw.c (c) 1996-8 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license
frpw.c is a low-level protocol driver for the Freecom "Power"
parallel port IDE adapter.
*/
-#define FRPW_VERSION "1.0"
+/* Changes:
+
+ 1.01 GRG 1998.05.06 init_proto, release_proto
+ fix chip detect
+ added EPP-16 and EPP-32
+
+*/
+
+#define FRPW_VERSION "1.01"
#include <linux/module.h>
#include <linux/delay.h>
@@ -93,6 +101,24 @@ static void frpw_read_block_int( PIA *pi, char * buf, int count, int regr )
w2(4);
break;
+ case 4: w2(4); w0(regr + 0x80); cec4;
+ for (k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w();
+ w2(0xac); w2(0xa4);
+ buf[count-2] = r4();
+ buf[count-1] = r4();
+ w2(4);
+ break;
+
+ case 5: w2(4); w0(regr + 0x80); cec4;
+ for (k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l();
+ buf[count-4] = r4();
+ buf[count-3] = r4();
+ w2(0xac); w2(0xa4);
+ buf[count-2] = r4();
+ buf[count-1] = r4();
+ w2(4);
+ break;
+
}
}
@@ -121,6 +147,16 @@ static void frpw_write_block( PIA *pi, char * buf, int count )
for (k=0;k<count;k++) w4(buf[k]);
w2(4);
break;
+
+ case 4: w2(4); w0(0xc8); cec4; w2(5);
+ for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
+ w2(4);
+ break;
+
+ case 5: w2(4); w0(0xc8); cec4; w2(5);
+ for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
+ w2(4);
+ break;
}
}
@@ -144,6 +180,8 @@ static void frpw_disconnect ( PIA *pi )
static int frpw_test_pnp ( PIA *pi )
+/* returns chip_type: 0 = Xilinx, 1 = ASIC */
+
{ int olddelay, a, b;
olddelay = pi->delay;
@@ -163,24 +201,27 @@ static int frpw_test_pnp ( PIA *pi )
return ((~a&0x40) && (b&0x40));
}
-/* We use pi->private to record the chip type:
- 0 = untested, 2 = Xilinx, 3 = ASIC
-*/
+/* We use the pi->private to remember the result of the PNP test.
+ To make this work, private = port*2 + chip. Yes, I know it's
+ a hack :-(
+*/
static int frpw_test_proto( PIA *pi, char * scratch, int verbose )
-{ int k, r;
+{ int j, k, r;
+ int e[2] = {0,0};
- if (!pi->private) pi->private = frpw_test_pnp(pi) + 2;
+ if ((pi->private>>1) != pi->port)
+ pi->private = frpw_test_pnp(pi) + 2*pi->port;
- if ((pi->private == 2) && (pi->mode > 2)) {
+ if (((pi->private%2) == 0) && (pi->mode > 2)) {
if (verbose)
printk("%s: frpw: Xilinx does not support mode %d\n",
pi->device, pi->mode);
return 1;
}
- if ((pi->private == 3) && (pi->mode == 2)) {
+ if (((pi->private%2) == 1) && (pi->mode == 2)) {
if (verbose)
printk("%s: frpw: ASIC does not support mode 2\n",
pi->device);
@@ -188,42 +229,55 @@ static int frpw_test_proto( PIA *pi, char * scratch, int verbose )
}
frpw_connect(pi);
+ for (j=0;j<2;j++) {
+ frpw_write_regr(pi,0,6,0xa0+j*0x10);
+ for (k=0;k<256;k++) {
+ frpw_write_regr(pi,0,2,k^0xaa);
+ frpw_write_regr(pi,0,3,k^0x55);
+ if (frpw_read_regr(pi,0,2) != (k^0xaa)) e[j]++;
+ }
+ }
+ frpw_disconnect(pi);
+
+ frpw_connect(pi);
frpw_read_block_int(pi,scratch,512,0x10);
r = 0;
for (k=0;k<128;k++) if (scratch[k] != k) r++;
frpw_disconnect(pi);
if (verbose) {
- printk("%s: frpw: port 0x%x, mode %d, test=%d\n",
- pi->device,pi->port,pi->mode,r);
+ printk("%s: frpw: port 0x%x, chip %d, mode %d, test=(%d,%d,%d)\n",
+ pi->device,pi->port,(pi->private%2),pi->mode,e[0],e[1],r);
}
- return r;
+ return (r || (e[0] && e[1]));
}
static void frpw_log_adapter( PIA *pi, char * scratch, int verbose )
-{ char *mode_string[4] = {"4-bit","8-bit","EPP-X","EPP-A"};
+{ char *mode_string[6] = {"4-bit","8-bit","EPP",
+ "EPP-8","EPP-16","EPP-32"};
printk("%s: frpw %s, Freecom (%s) adapter at 0x%x, ", pi->device,
- FRPW_VERSION,(pi->private == 2)?"Xilinx":"ASIC",pi->port);
+ FRPW_VERSION,((pi->private%2) == 0)?"Xilinx":"ASIC",pi->port);
printk("mode %d (%s), delay %d\n",pi->mode,
mode_string[pi->mode],pi->delay);
}
-static void frpw_inc_use ( void )
+static void frpw_init_proto( PIA *pi)
{ MOD_INC_USE_COUNT;
+ pi->private = 0;
}
-static void frpw_dec_use ( void )
+static void frpw_release_proto( PIA *pi)
{ MOD_DEC_USE_COUNT;
}
-struct pi_protocol frpw = {"frpw",0,4,2,2,1,
+struct pi_protocol frpw = {"frpw",0,6,2,2,1,
frpw_write_regr,
frpw_read_regr,
frpw_write_block,
@@ -234,8 +288,8 @@ struct pi_protocol frpw = {"frpw",0,4,2,2,1,
0,
frpw_test_proto,
frpw_log_adapter,
- frpw_inc_use,
- frpw_dec_use
+ frpw_init_proto,
+ frpw_release_proto
};
diff --git a/drivers/block/paride/kbic.c b/drivers/block/paride/kbic.c
index 47f5cd29f..589ac00d0 100644
--- a/drivers/block/paride/kbic.c
+++ b/drivers/block/paride/kbic.c
@@ -1,6 +1,6 @@
/*
- kbic.c (c) 1997 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU public license.
+ kbic.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
This is a low-level driver for the KBIC-951A and KBIC-971A
parallel to IDE adapter chips from KingByte Information Systems.
@@ -12,7 +12,13 @@
*/
-#define KBIC_VERSION "1.0"
+/* Changes:
+
+ 1.01 GRG 1998.05.06 init_proto, release_proto
+
+*/
+
+#define KBIC_VERSION "1.01"
#include <linux/module.h>
#include <linux/delay.h>
@@ -241,12 +247,12 @@ static void k971_log_adapter( PIA *pi, char * scratch, int verbose )
{ kbic_log_adapter(pi,scratch,verbose,"KBIC-971A");
}
-static void kbic_inc_use ( void )
+static void kbic_init_proto( PIA *pi)
{ MOD_INC_USE_COUNT;
}
-static void kbic_dec_use ( void )
+static void kbic_release_proto( PIA *pi)
{ MOD_DEC_USE_COUNT;
}
@@ -262,8 +268,8 @@ struct pi_protocol k951 = {"k951",0,6,3,1,1,
0,
0,
k951_log_adapter,
- kbic_inc_use,
- kbic_dec_use
+ kbic_init_proto,
+ kbic_release_proto
};
@@ -278,8 +284,8 @@ struct pi_protocol k971 = {"k971",0,6,3,1,1,
0,
0,
k971_log_adapter,
- kbic_inc_use,
- kbic_dec_use
+ kbic_init_proto,
+ kbic_release_proto
};
#ifdef MODULE
diff --git a/drivers/block/paride/ktti.c b/drivers/block/paride/ktti.c
new file mode 100644
index 000000000..606bcfde9
--- /dev/null
+++ b/drivers/block/paride/ktti.c
@@ -0,0 +1,138 @@
+/*
+ ktti.c (c) 1998 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
+
+ ktti.c is a low-level protocol driver for the KT Technology
+ parallel port adapter. This adapter is used in the "PHd"
+ portable hard-drives. As far as I can tell, this device
+ supports 4-bit mode _only_.
+
+*/
+
+#define KTTI_VERSION "1.0"
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/io.h>
+
+#include "paride.h"
+
+#define j44(a,b) (((a>>4)&0x0f)|(b&0xf0))
+
+/* cont = 0 - access the IDE register file
+ cont = 1 - access the IDE command set
+*/
+
+static int cont_map[2] = { 0x10, 0x08 };
+
+static void ktti_write_regr( PIA *pi, int cont, int regr, int val)
+
+{ int r;
+
+ r = regr + cont_map[cont];
+
+ w0(r); w2(0xb); w2(0xa); w2(3); w2(6);
+ w0(val); w2(3); w0(0); w2(6); w2(0xb);
+}
+
+static int ktti_read_regr( PIA *pi, int cont, int regr )
+
+{ int a, b, r;
+
+ r = regr + cont_map[cont];
+
+ w0(r); w2(0xb); w2(0xa); w2(9); w2(0xc); w2(9);
+ a = r1(); w2(0xc); b = r1(); w2(9); w2(0xc); w2(9);
+ return j44(a,b);
+
+}
+
+static void ktti_read_block( PIA *pi, char * buf, int count )
+
+{ int k, a, b;
+
+ for (k=0;k<count/2;k++) {
+ w0(0x10); w2(0xb); w2(0xa); w2(9); w2(0xc); w2(9);
+ a = r1(); w2(0xc); b = r1(); w2(9);
+ buf[2*k] = j44(a,b);
+ a = r1(); w2(0xc); b = r1(); w2(9);
+ buf[2*k+1] = j44(a,b);
+ }
+}
+
+static void ktti_write_block( PIA *pi, char * buf, int count )
+
+{ int k;
+
+ for (k=0;k<count/2;k++) {
+ w0(0x10); w2(0xb); w2(0xa); w2(3); w2(6);
+ w0(buf[2*k]); w2(3);
+ w0(buf[2*k+1]); w2(6);
+ w2(0xb);
+ }
+}
+
+static void ktti_connect ( PIA *pi )
+
+{ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
+ w2(0xb); w2(0xa); w0(0); w2(3); w2(6);
+}
+
+static void ktti_disconnect ( PIA *pi )
+
+{ w2(0xb); w2(0xa); w0(0xa0); w2(3); w2(4);
+ w0(pi->saved_r0);
+ w2(pi->saved_r2);
+}
+
+static void ktti_log_adapter( PIA *pi, char * scratch, int verbose )
+
+{ printk("%s: ktti %s, KT adapter at 0x%x, delay %d\n",
+ pi->device,KTTI_VERSION,pi->port,pi->delay);
+
+}
+
+static void ktti_init_proto( PIA *pi)
+
+{ MOD_INC_USE_COUNT;
+}
+
+static void ktti_release_proto( PIA *pi)
+
+{ MOD_DEC_USE_COUNT;
+}
+
+struct pi_protocol ktti = {"ktti",0,1,2,1,1,
+ ktti_write_regr,
+ ktti_read_regr,
+ ktti_write_block,
+ ktti_read_block,
+ ktti_connect,
+ ktti_disconnect,
+ 0,
+ 0,
+ 0,
+ ktti_log_adapter,
+ ktti_init_proto,
+ ktti_release_proto
+ };
+
+
+#ifdef MODULE
+
+int init_module(void)
+
+{ return pi_register( &ktti ) - 1;
+}
+
+void cleanup_module(void)
+
+{ pi_unregister( &ktti );
+}
+
+#endif
+
+/* end of ktti.c */
diff --git a/drivers/block/paride/mkd b/drivers/block/paride/mkd
new file mode 100644
index 000000000..971f099b4
--- /dev/null
+++ b/drivers/block/paride/mkd
@@ -0,0 +1,30 @@
+#!/bin/bash
+#
+# mkd -- a script to create the device special files for the PARIDE subsystem
+#
+# block devices: pd (45), pcd (46), pf (47)
+# character devices: pt (96), pg (97)
+#
+function mkdev {
+ mknod $1 $2 $3 $4 ; chmod 0660 $1 ; chown root:disk $1
+}
+#
+function pd {
+ D=$( printf \\$( printf "x%03x" $[ $1 + 97 ] ) )
+ mkdev pd$D b 45 $[ $1 * 16 ]
+ for P in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ do mkdev pd$D$P b 45 $[ $1 * 16 + $P ]
+ done
+}
+#
+cd /dev
+#
+for u in 0 1 2 3 ; do pd $u ; done
+for u in 0 1 2 3 ; do mkdev pcd$u b 46 $u ; done
+for u in 0 1 2 3 ; do mkdev pf$u b 47 $u ; done
+for u in 0 1 2 3 ; do mkdev pt$u c 96 $u ; done
+for u in 0 1 2 3 ; do mkdev npt$u c 96 $[ $u + 128 ] ; done
+for u in 0 1 2 3 ; do mkdev pg$u c 97 $u ; done
+#
+# end of mkd
+
diff --git a/drivers/block/paride/on20.c b/drivers/block/paride/on20.c
index c9b3fa35b..749879c73 100644
--- a/drivers/block/paride/on20.c
+++ b/drivers/block/paride/on20.c
@@ -1,12 +1,18 @@
/*
- on20.c (c) 1996 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU public license.
+ on20.c (c) 1996-8 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
on20.c is a low-level protocol driver for the
Onspec 90c20 parallel to IDE adapter.
*/
-#define ON20_VERSION "1.0"
+/* Changes:
+
+ 1.01 GRG 1998.05.06 init_proto, release_proto
+
+*/
+
+#define ON20_VERSION "1.01"
#include <linux/module.h>
#include <linux/delay.h>
@@ -114,12 +120,12 @@ static void on20_log_adapter( PIA *pi, char * scratch, int verbose )
}
-static void on20_inc_use ( void )
+static void on20_init_proto( PIA *pi)
{ MOD_INC_USE_COUNT;
}
-static void on20_dec_use ( void )
+static void on20_release_proto( PIA *pi)
{ MOD_DEC_USE_COUNT;
}
@@ -135,8 +141,8 @@ struct pi_protocol on20 = {"on20",0,2,2,1,1,
0,
0,
on20_log_adapter,
- on20_inc_use,
- on20_dec_use
+ on20_init_proto,
+ on20_release_proto
};
diff --git a/drivers/block/paride/on26.c b/drivers/block/paride/on26.c
index 21e6e017e..89457cc80 100644
--- a/drivers/block/paride/on26.c
+++ b/drivers/block/paride/on26.c
@@ -1,13 +1,19 @@
/*
- on26.c (c) 1997 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU public license.
+ on26.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
on26.c is a low-level protocol driver for the
OnSpec 90c26 parallel to IDE adapter chip.
*/
-#define ON26_VERSION "1.0"
+/* Changes:
+
+ 1.01 GRG 1998.05.06 init_proto, release_proto
+
+*/
+
+#define ON26_VERSION "1.01"
#include <linux/module.h>
#include <linux/delay.h>
@@ -217,12 +223,12 @@ static void on26_log_adapter( PIA *pi, char * scratch, int verbose )
}
-static void on26_inc_use ( void )
+static void on26_init_proto( PIA *pi)
{ MOD_INC_USE_COUNT;
}
-static void on26_dec_use ( void )
+static void on26_release_proto( PIA *pi)
{ MOD_DEC_USE_COUNT;
}
@@ -238,8 +244,8 @@ struct pi_protocol on26 = {"on26",0,5,2,1,1,
0,
0,
on26_log_adapter,
- on26_inc_use,
- on26_dec_use
+ on26_init_proto,
+ on26_release_proto
};
diff --git a/drivers/block/paride/paride.c b/drivers/block/paride/paride.c
index 0d7cf2f01..805b69e19 100644
--- a/drivers/block/paride/paride.c
+++ b/drivers/block/paride/paride.c
@@ -1,13 +1,20 @@
/*
- paride.c (c) 1997 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU public license.
+ paride.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
This is the base module for the family of device drivers
that support parallel port IDE devices.
*/
-#define PI_VERSION "1.0"
+/* Changes:
+
+ 1.01 GRG 1998.05.03 Use spinlocks
+ 1.02 GRG 1998.05.05 init_proto, release_proto, ktti
+
+*/
+
+#define PI_VERSION "1.02"
#include <linux/module.h>
#include <linux/config.h>
@@ -15,6 +22,7 @@
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/string.h>
+#include <asm/spinlock.h>
#ifdef CONFIG_PARPORT_MODULE
#define CONFIG_PARPORT
@@ -30,6 +38,7 @@
static struct pi_protocol *protocols[MAX_PROTOS];
+spinlock_t pi_spinlock = SPIN_LOCK_UNLOCKED;
void pi_write_regr( PIA *pi, int cont, int regr, int val)
@@ -59,8 +68,7 @@ static void pi_wake_up( void *p)
long flags;
void (*cont)(void) = NULL;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&pi_spinlock,flags);
if (pi->claim_cont && !parport_claim(pi->pardev)) {
cont = pi->claim_cont;
@@ -68,8 +76,10 @@ static void pi_wake_up( void *p)
pi->claimed = 1;
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&pi_spinlock,flags);
+
wake_up(&(pi->parq));
+
if (cont) cont();
}
@@ -81,16 +91,15 @@ void pi_do_claimed( PIA *pi, void(*cont)(void))
{ long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&pi_spinlock,flags);
if (!pi->pardev || !parport_claim(pi->pardev)) {
pi->claimed = 1;
- restore_flags(flags);
+ spin_unlock_irqrestore(&pi_spinlock,flags);
cont();
} else {
pi->claim_cont = cont;
- restore_flags(flags);
+ spin_unlock_irqrestore(&pi_spinlock,flags);
}
}
@@ -148,7 +157,7 @@ void pi_release( PIA *pi)
{ pi_unregister_parport(pi);
if ((!pi->pardev)&&(pi->reserved))
release_region(pi->port,pi->reserved);
- pi->proto->dec_use();
+ pi->proto->release_proto(pi);
}
#define WR(r,v) pi_write_regr(pi,0,r,v)
@@ -337,12 +346,12 @@ int pi_init(PIA *pi, int autoprobe, int port, int mode,
for (p=s;p<e;p++) {
if (protocols[p]) {
pi->proto = protocols[p];
- pi->proto->inc_use();
+ pi->private = 0;
+ pi->proto->init_proto(pi);
if (delay == -1) pi->delay = pi->proto->default_delay;
else pi->delay = delay;
pi->devtype = devtype;
pi->device = device;
- pi->private = 0;
pi->parname = NULL;
pi->pardev = NULL;
@@ -361,7 +370,7 @@ int pi_init(PIA *pi, int autoprobe, int port, int mode,
if (pi_probe_unit(pi,unit,scratch,verbose)) break;
if (pi->port) break;
}
- pi->proto->dec_use();
+ pi->proto->release_proto(pi);
}
}
@@ -440,6 +449,16 @@ void paride_init( void )
pi_register(&frpw);
};
#endif
+#ifdef CONFIG_PARIDE_FIT2
+ { extern struct pi_protocol fit2;
+ pi_register(&fit2);
+ };
+#endif
+#ifdef CONFIG_PARIDE_FIT3
+ { extern struct pi_protocol fit3;
+ pi_register(&fit3);
+ };
+#endif
#ifdef CONFIG_PARIDE_KBIC
{ extern struct pi_protocol k951;
extern struct pi_protocol k971;
@@ -447,6 +466,11 @@ void paride_init( void )
pi_register(&k971);
};
#endif
+#ifdef CONFIG_PARIDE_KTTI
+ { extern struct pi_protocol ktti;
+ pi_register(&ktti);
+ };
+#endif
#ifdef CONFIG_PARIDE_ON20
{ extern struct pi_protocol on20;
pi_register(&on20);
@@ -478,6 +502,11 @@ void paride_init( void )
pt_init();
};
#endif
+#ifdef CONFIG_PARIDE_PG
+ { extern int pg_init(void);
+ pg_init();
+ };
+#endif
}
#endif
diff --git a/drivers/block/paride/paride.h b/drivers/block/paride/paride.h
index 04de51441..6d37736ec 100644
--- a/drivers/block/paride/paride.h
+++ b/drivers/block/paride/paride.h
@@ -1,12 +1,18 @@
-/* paride.h (c) 1997 Grant R. Guenther <grant@torque.net>
- Under the terms of the GPL.
+/*
+ paride.h (c) 1997-8 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GPL.
This file defines the interface between the high-level parallel
IDE device drivers (pd, pf, pcd, pt) and the adapter chips.
*/
-#define PARIDE_H_VERSION "1.0"
+/* Changes:
+
+ 1.01 GRG 1998.05.05 init_proto, release_proto
+*/
+
+#define PARIDE_H_VERSION "1.01"
/* Some adapters need to know what kind of device they are in
@@ -17,6 +23,7 @@
#define PI_PCD 1 /* ATAPI CDrom */
#define PI_PF 2 /* ATAPI disk */
#define PI_PT 3 /* ATAPI tape */
+#define PI_PG 4 /* ATAPI generic */
/* The paride module contains no state, instead the drivers allocate
a pi_adapter data structure and pass it to paride in every operation.
@@ -145,8 +152,8 @@ struct pi_protocol {
int (*test_proto)(PIA *,char *,int);
void (*log_adapter)(PIA *,char *,int);
- void (*inc_use)(void);
- void (*dec_use)(void);
+ void (*init_proto)(PIA *);
+ void (*release_proto)(PIA *);
};
typedef struct pi_protocol PIP;
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index ca520d32b..ecacacb3b 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -1,12 +1,12 @@
/*
- pcd.c (c) 1997 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU public license.
+ pcd.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
- This is high-level driver for parallel port ATAPI CDrom
+ This is a high-level driver for parallel port ATAPI CDROM
drives based on chips supported by the paride module.
By default, the driver will autoprobe for a single parallel
- port ATAPI CDrom drive, but if their individual parameters are
+ port ATAPI CDROM drive, but if their individual parameters are
specified, the driver can handle up to 4 drives.
The behaviour of the pcd driver can be altered by setting
@@ -38,7 +38,7 @@
of the mode numbers supported by the adapter.
(-1 if not given)
- <slv> ATAPI CDroms can be jumpered to master or slave.
+ <slv> ATAPI CDROMs can be jumpered to master or slave.
Set this to 0 to choose the master drive, 1 to
choose the slave, -1 (the default) to choose the
first drive found.
@@ -86,16 +86,21 @@
/* Changes:
1.01 GRG 1997.01.24 Added test unit ready support
+ 1.02 GRG 1998.05.06 Changes to pcd_completion, ready_wait,
+ and loosen interpretation of ATAPI
+ standard for clearing error status.
+ Use spinlocks. Eliminate sti().
+ 1.03 GRG 1998.06.16 Eliminated an Ugh
*/
-#define PCD_VERSION "1.01"
+#define PCD_VERSION "1.03"
#define PCD_MAJOR 46
#define PCD_NAME "pcd"
#define PCD_UNITS 4
/* Here are things one can override from the insmod command.
- Most are autoprobed by paride unless set here. Verbose is on
+ Most are autoprobed by paride unless set here. Verbose is off
by default.
*/
@@ -133,6 +138,7 @@ static int pcd_drive_count;
#include <linux/cdrom.h>
#include <asm/uaccess.h>
+#include <asm/spinlock.h>
#ifndef MODULE
@@ -193,7 +199,7 @@ void cleanup_module( void );
static int pcd_open(struct inode *inode, struct file *file);
static void do_pcd_request(void);
-static void do_pcd_read(int unit);
+static void do_pcd_read(void);
static int pcd_ioctl(struct inode *inode,struct file *file,
unsigned int cmd, unsigned long arg);
@@ -343,8 +349,9 @@ static void do_pcd_request (void)
pcd_sector = CURRENT->sector;
pcd_count = CURRENT->nr_sectors;
pcd_buf = CURRENT->buffer;
- do_pcd_read(unit);
- if (pcd_busy) return;
+ pcd_busy = 1;
+ ps_set_intr(do_pcd_read,0,0,nice);
+ return;
}
else end_request(0);
}
@@ -407,30 +414,20 @@ static int pcd_release (struct inode *inode, struct file *file)
int init_module(void)
{ int err;
- long flags;
-
- save_flags(flags);
- cli();
err = pcd_init();
- restore_flags(flags);
return err;
}
void cleanup_module(void)
-{ long flags;
- int unit;
+{ int unit;
- save_flags(flags);
- cli();
unregister_blkdev(MAJOR_NR,name);
for (unit=0;unit<PCD_UNITS;unit++)
if (PCD.present) pi_release(PI);
-
- restore_flags(flags);
}
#endif
@@ -474,7 +471,7 @@ static int pcd_command( int unit, char * cmd, int dlen, char * fun )
WR(0,5,dlen / 256);
WR(0,7,0xa0); /* ATAPI packet command */
- if (pcd_wait(unit,IDE_BUSY,IDE_DRQ|IDE_ERR,fun,"command DRQ")) {
+ if (pcd_wait(unit,IDE_BUSY,IDE_DRQ,fun,"command DRQ")) {
pi_disconnect(PI);
return -1;
}
@@ -497,7 +494,7 @@ static int pcd_completion( int unit, char * buf, char * fun )
r = pcd_wait(unit,IDE_BUSY,IDE_DRQ|IDE_READY|IDE_ERR,fun,"completion");
if ((RR(0,2)&2) && (RR(0,7)&IDE_DRQ)) {
- n = (RR(0,4)+256*RR(0,5));
+ n = (((RR(0,4)+256*RR(0,5))+3)&0xfffc);
pi_read_block(PI,buf,n);
}
@@ -515,7 +512,7 @@ static void pcd_req_sense( int unit, int quiet )
int r;
r = pcd_command(unit,rs_cmd,16,"Request sense");
- udelay(1000);
+ mdelay(1);
if (!r) pcd_completion(unit,buf,"Request sense");
PCD.last_sense = -1;
@@ -532,7 +529,7 @@ static int pcd_atapi( int unit, char * cmd, int dlen, char * buf, char * fun )
{ int r;
r = pcd_command(unit,cmd,dlen,fun);
- udelay(1000);
+ mdelay(1);
if (!r) r = pcd_completion(unit,buf,fun);
if (r) pcd_req_sense(unit,!fun);
@@ -589,23 +586,17 @@ static int pcd_reset( int unit )
{ int i, k, flg;
int expect[5] = {1,1,1,0x14,0xeb};
- long flags;
pi_connect(PI);
WR(0,6,0xa0 + 0x10*PCD.drive);
WR(0,7,8);
- save_flags(flags);
- sti();
-
pcd_sleep(2); /* delay a bit*/
k = 0;
while ((k++ < PCD_RESET_TMO) && (RR(1,6)&IDE_BUSY))
pcd_sleep(10);
- restore_flags(flags);
-
flg = 1;
for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]);
@@ -631,7 +622,7 @@ static int pcd_ready_wait( int unit, int tmo )
pcd_atapi(unit,tr_cmd,0,NULL,DBMSG("test unit ready"));
p = PCD.last_sense;
if (!p) return 0;
- if (!((p == 0x010402)||((p & 0xff) == 6))) return p;
+ if (!(((p & 0xffff) == 0x0402)||((p & 0xff) == 6))) return p;
k++;
pcd_sleep(100);
}
@@ -657,7 +648,7 @@ static int pcd_identify( int unit, char * id )
if (s) return -1;
if ((pcd_buffer[0] & 0x1f) != 5) {
- if (verbose) printk("%s: %s is not a CDrom\n",
+ if (verbose) printk("%s: %s is not a CDROM\n",
PCD.name,PCD.drive?"Slave":"Master");
return -1;
}
@@ -718,7 +709,7 @@ static int pcd_detect( void )
if (k) return 0;
- printk("%s: No CDrom drive found\n",name);
+ printk("%s: No CDROM drive found\n",name);
return -1;
}
@@ -749,6 +740,7 @@ static void pcd_start( void )
{ int unit = pcd_unit;
int b, i;
char rd_cmd[12] = {0xa8,0,0,0,0,0,0,0,0,1,0,0};
+ long saved_flags;
pcd_bufblk = pcd_sector / 4;
b = pcd_bufblk;
@@ -757,33 +749,39 @@ static void pcd_start( void )
b = b >> 8;
}
-
if (pcd_command(unit,rd_cmd,2048,"read block")) {
pcd_bufblk = -1;
+ spin_lock_irqsave(&io_request_lock,saved_flags);
pcd_busy = 0;
- cli();
end_request(0);
do_pcd_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
- udelay(1000);
+ mdelay(1);
ps_set_intr(do_pcd_read_drq,pcd_ready,PCD_TMO,nice);
}
-static void do_pcd_read( int unit )
+static void do_pcd_read( void )
-{ pcd_busy = 1;
+
+{ int unit = pcd_unit;
+ long saved_flags;
+
+ pcd_busy = 1;
pcd_retries = 0;
pcd_transfer();
if (!pcd_count) {
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(1);
pcd_busy = 0;
+ do_pcd_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
- sti();
pi_do_claimed(PI,pcd_start);
}
@@ -791,26 +789,29 @@ static void do_pcd_read( int unit )
static void do_pcd_read_drq( void )
{ int unit = pcd_unit;
-
- sti();
+ long saved_flags;
if (pcd_completion(unit,pcd_buffer,"read block")) {
if (pcd_retries < PCD_RETRIES) {
- udelay(1000);
+ mdelay(1);
pcd_retries++;
pi_do_claimed(PI,pcd_start);
return;
}
- cli();
+ spin_lock_irqsave(&io_request_lock,saved_flags);
pcd_busy = 0;
pcd_bufblk = -1;
end_request(0);
do_pcd_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
- do_pcd_read(unit);
+ do_pcd_read();
+ spin_lock_irqsave(&io_request_lock,saved_flags);
do_pcd_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
/* end of pcd.c */
+
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index c2f9473bc..3be1de32c 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -1,6 +1,6 @@
/*
- pd.c (c) 1997 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU public license.
+ pd.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
This is the high-level driver for parallel port IDE hard
drives based on chips supported by the paride module.
@@ -14,9 +14,9 @@
parameters are adjustable:
drive0 These four arguments can be arrays of
- drive1 1-7 integers as follows:
+ drive1 1-8 integers as follows:
drive2
- drive3 <prt>,<pro>,<uni>,<mod>,<geo>,<sby>,<dly>
+ drive3 <prt>,<pro>,<uni>,<mod>,<geo>,<sby>,<dly>,<slv>
Where,
@@ -54,6 +54,11 @@
set this to a small integer, the larger it is
the slower the port i/o. In some cases, setting
this to zero will speed up the device. (default -1)
+
+ <slv> IDE disks can be jumpered to master or slave.
+ Set this to 0 to choose the master drive, 1 to
+ choose the slave, -1 (the default) to choose the
+ first drive found.
major You may use this parameter to overide the
@@ -100,16 +105,19 @@
1.01 GRG 1997.01.24 Restored pd_reset()
Added eject ioctl
+ 1.02 GRG 1998.05.06 SMP spinlock changes,
+ Added slave support
+ 1.03 GRG 1998.06.16 Eliminate an Ugh.
*/
-#define PD_VERSION "1.01"
+#define PD_VERSION "1.03"
#define PD_MAJOR 45
#define PD_NAME "pd"
#define PD_UNITS 4
/* Here are things one can override from the insmod command.
- Most are autoprobed by paride unless set here. Verbose is on
+ Most are autoprobed by paride unless set here. Verbose is off
by default.
*/
@@ -121,12 +129,12 @@ static int cluster = 64;
static int nice = 0;
static int disable = 0;
-static int drive0[7] = {0,0,0,-1,0,1,-1};
-static int drive1[7] = {0,0,0,-1,0,1,-1};
-static int drive2[7] = {0,0,0,-1,0,1,-1};
-static int drive3[7] = {0,0,0,-1,0,1,-1};
+static int drive0[8] = {0,0,0,-1,0,1,-1,-1};
+static int drive1[8] = {0,0,0,-1,0,1,-1,-1};
+static int drive2[8] = {0,0,0,-1,0,1,-1,-1};
+static int drive3[8] = {0,0,0,-1,0,1,-1,-1};
-static int (*drives[4])[7] = {&drive0,&drive1,&drive2,&drive3};
+static int (*drives[4])[8] = {&drive0,&drive1,&drive2,&drive3};
static int pd_drive_count;
#define D_PRT 0
@@ -136,6 +144,7 @@ static int pd_drive_count;
#define D_GEO 4
#define D_SBY 5
#define D_DLY 6
+#define D_SLV 7
#define DU (*drives[unit])
@@ -150,16 +159,17 @@ static int pd_drive_count;
#include <linux/hdreg.h>
#include <linux/cdrom.h> /* for the eject ioctl */
+#include <asm/spinlock.h>
#include <asm/uaccess.h>
#ifndef MODULE
#include "setup.h"
-static STT pd_stt[7] = {{"drive0",7,drive0},
- {"drive1",7,drive1},
- {"drive2",7,drive2},
- {"drive3",7,drive3},
+static STT pd_stt[7] = {{"drive0",8,drive0},
+ {"drive1",8,drive1},
+ {"drive2",8,drive2},
+ {"drive3",8,drive3},
{"disable",1,&disable},
{"cluster",1,&cluster},
{"nice",1,&nice}};
@@ -176,10 +186,10 @@ MODULE_PARM(major,"i");
MODULE_PARM(name,"s");
MODULE_PARM(cluster,"i");
MODULE_PARM(nice,"i");
-MODULE_PARM(drive0,"1-7i");
-MODULE_PARM(drive1,"1-7i");
-MODULE_PARM(drive2,"1-7i");
-MODULE_PARM(drive3,"1-7i");
+MODULE_PARM(drive0,"1-8i");
+MODULE_PARM(drive1,"1-8i");
+MODULE_PARM(drive2,"1-8i");
+MODULE_PARM(drive3,"1-8i");
#include "paride.h"
@@ -258,7 +268,9 @@ static int pd_release (struct inode *inode, struct file *file);
static int pd_revalidate(kdev_t dev);
static int pd_detect(void);
static void do_pd_read(void);
+static void do_pd_read_start(void);
static void do_pd_write(void);
+static void do_pd_write_start(void);
static void do_pd_read_drq( void );
static void do_pd_write_done( void );
@@ -282,6 +294,7 @@ struct pd_unit {
int heads; /* physical geometry */
int sectors;
int cylinders;
+ int drive; /* master=0 slave=1 */
int changed; /* Have we seen a disk change ? */
int removable; /* removable media device ? */
int standby;
@@ -363,6 +376,7 @@ void pd_init_units( void )
PD.access = 0;
PD.changed = 1;
PD.capacity = 0;
+ PD.drive = DU[D_SLV];
PD.present = 0;
j = 0;
while ((j < PD_NAMELEN-2) && (PD.name[j]=name[j])) j++;
@@ -593,42 +607,27 @@ void cleanup_module(void);
int init_module(void)
{ int err, unit;
- long flags;
-
- save_flags(flags);
- cli();
err = pd_init();
- if (err) {
- restore_flags(flags);
- return err;
- }
+ if (err) return err;
pd_geninit(&pd_gendisk);
- if (!pd_gendisk.nr_real) {
- restore_flags(flags);
- return -1;
- }
+ if (!pd_gendisk.nr_real) return -1;
pd_valid = 0;
for (unit=0;unit<PD_UNITS;unit++)
if (PD.present) resetup_one_dev(&pd_gendisk,unit);
pd_valid = 1;
- restore_flags(flags);
return 0;
}
void cleanup_module(void)
{ struct gendisk **gdp;
- long flags;
int unit;
- save_flags(flags);
- cli();
-
unregister_blkdev(MAJOR_NR,name);
for(gdp=&gendisk_head;*gdp;gdp=&((*gdp)->next))
@@ -637,8 +636,6 @@ void cleanup_module(void)
for (unit=0;unit<PD_UNITS;unit++)
if (PD.present) pi_release(PI);
-
- restore_flags(flags);
}
#endif
@@ -646,6 +643,8 @@ void cleanup_module(void)
#define WR(c,r,v) pi_write_regr(PI,c,r,v)
#define RR(c,r) (pi_read_regr(PI,c,r))
+#define DRIVE (0xa0+0x10*PD.drive)
+
/* ide command interface */
static void pd_print_error( int unit, char * msg, int status )
@@ -657,7 +656,7 @@ static void pd_print_error( int unit, char * msg, int status )
printk("\n");
}
-static void pd_reset( int unit )
+static void pd_reset( int unit ) /* called only for MASTER drive */
{ pi_connect(PI);
WR(1,6,4);
@@ -691,7 +690,7 @@ static void pd_send_command( int unit, int n, int s, int h,
int c0, int c1, int func )
{
- WR(0,6,0xa0+h);
+ WR(0,6,DRIVE+h);
WR(0,1,0); /* the IDE task file */
WR(0,2,n);
WR(0,3,s);
@@ -793,10 +792,16 @@ static int pd_identify( int unit )
{ int j;
char id[PD_ID_LEN+1];
- pd_reset(unit);
+/* WARNING: here there may be dragons. reset() applies to both drives,
+ but we call it only on probing the MASTER. This should allow most
+ common configurations to work, but be warned that a reset can clear
+ settings on the SLAVE drive.
+*/
+
+ if (PD.drive == 0) pd_reset(unit);
pi_connect(PI);
- WR(0,6,0xa0);
+ WR(0,6,DRIVE);
pd_wait_for(unit,0,DBMSG("before IDENT"));
pd_send_command(unit,1,0,0,0,0,IDE_IDENTIFY);
@@ -818,8 +823,10 @@ static int pd_identify( int unit )
PD.removable = (word_val(0) & 0x80);
- printk("%s: %s, %d blocks [%dM], (%d/%d/%d), %s media\n",
- PD.name,id,PD.capacity,PD.capacity/2048,
+ printk("%s: %s, %s, %d blocks [%dM], (%d/%d/%d), %s media\n",
+ PD.name,id,
+ PD.drive?"slave":"master",
+ PD.capacity,PD.capacity/2048,
PD.cylinders,PD.heads,PD.sectors,
PD.removable?"removable":"fixed");
@@ -832,36 +839,39 @@ static int pd_identify( int unit )
return 1;
}
+static int pd_probe_drive( int unit )
+
+{ if (PD.drive == -1) {
+ for (PD.drive=0;PD.drive<=1;PD.drive++)
+ if (pd_identify(unit)) return 1;
+ return 0;
+ }
+ else return pd_identify(unit);
+}
+
static int pd_detect( void )
-{ long flags;
- int k, unit;
+{ int k, unit;
k = 0;
if (pd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */
unit = 0;
if (pi_init(PI,1,-1,-1,-1,-1,-1,pd_scratch,
PI_PD,verbose,PD.name)) {
- save_flags(flags);
- sti();
- if (pd_identify(unit)) {
+ if (pd_probe_drive(unit)) {
PD.present = 1;
k = 1;
} else pi_release(PI);
- restore_flags(flags);
}
} else for (unit=0;unit<PD_UNITS;unit++) if (DU[D_PRT])
if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI],
DU[D_PRO],DU[D_DLY],pd_scratch,
PI_PD,verbose,PD.name)) {
- save_flags(flags);
- sti();
- if (pd_identify(unit)) {
+ if (pd_probe_drive(unit)) {
PD.present = 1;
k = unit+1;
} else pi_release(PI);
- restore_flags(flags);
}
/* We lie about the number of drives found, as the generic partition
@@ -926,18 +936,24 @@ repeat:
pd_buf = CURRENT->buffer;
pd_retries = 0;
+ pd_busy = 1;
if (pd_cmd == READ) pi_do_claimed(PI,do_pd_read);
else if (pd_cmd == WRITE) pi_do_claimed(PI,do_pd_write);
- else { end_request(0);
+ else { pd_busy = 0;
+ end_request(0);
goto repeat;
}
}
static void pd_next_buf( int unit )
-{ cli();
+{ long saved_flags;
+
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(1);
- if (!pd_run) { sti(); return; }
+ if (!pd_run) { spin_unlock_irqrestore(&io_request_lock,saved_flags);
+ return;
+ }
/* paranoia */
@@ -951,29 +967,34 @@ static void pd_next_buf( int unit )
pd_count = CURRENT->nr_sectors;
pd_buf = CURRENT->buffer;
- sti();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
static void do_pd_read( void )
+{ ps_set_intr(do_pd_read_start,0,0,nice);
+}
+
+static void do_pd_read_start( void )
+
{ int unit = pd_unit;
+ long saved_flags;
pd_busy = 1;
- sti();
-
pi_connect(PI);
if (pd_wait_for(unit,STAT_READY,"do_pd_read") & STAT_ERR) {
pi_disconnect(PI);
if (pd_retries < PD_MAX_RETRIES) {
pd_retries++;
- pi_do_claimed(PI,do_pd_read);
+ pi_do_claimed(PI,do_pd_read_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pd_busy = 0;
- cli();
do_pd_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
pd_ide_command(unit,IDE_READ,pd_block,pd_run);
@@ -983,21 +1004,21 @@ static void do_pd_read( void )
static void do_pd_read_drq( void )
{ int unit = pd_unit;
-
- sti();
+ long saved_flags;
while (1) {
if (pd_wait_for(unit,STAT_DRQ,"do_pd_read_drq") & STAT_ERR) {
pi_disconnect(PI);
if (pd_retries < PD_MAX_RETRIES) {
pd_retries++;
- pi_do_claimed(PI,do_pd_read);
+ pi_do_claimed(PI,do_pd_read_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pd_busy = 0;
- cli();
do_pd_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
pi_read_block(PI,pd_buf,512);
@@ -1008,32 +1029,38 @@ static void do_pd_read_drq( void )
if (!pd_count) pd_next_buf(unit);
}
pi_disconnect(PI);
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(1);
pd_busy = 0;
- cli();
do_pd_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
static void do_pd_write( void )
+{ ps_set_intr(do_pd_write_start,0,0,nice);
+}
+
+static void do_pd_write_start( void )
+
{ int unit = pd_unit;
+ long saved_flags;
pd_busy = 1;
- sti();
-
pi_connect(PI);
if (pd_wait_for(unit,STAT_READY,"do_pd_write") & STAT_ERR) {
pi_disconnect(PI);
if (pd_retries < PD_MAX_RETRIES) {
pd_retries++;
- pi_do_claimed(PI,do_pd_write);
+ pi_do_claimed(PI,do_pd_write_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pd_busy = 0;
- cli();
do_pd_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
pd_ide_command(unit,IDE_WRITE,pd_block,pd_run);
@@ -1042,14 +1069,15 @@ static void do_pd_write( void )
pi_disconnect(PI);
if (pd_retries < PD_MAX_RETRIES) {
pd_retries++;
- pi_do_claimed(PI,do_pd_write);
+ pi_do_claimed(PI,do_pd_write_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pd_busy = 0;
- cli();
do_pd_request();
- return;
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
+ return;
}
pi_write_block(PI,pd_buf,512);
pd_count--; pd_run--;
@@ -1064,26 +1092,28 @@ static void do_pd_write( void )
static void do_pd_write_done( void )
{ int unit = pd_unit;
+ long saved_flags;
- sti();
if (pd_wait_for(unit,STAT_READY,"do_pd_write_done") & STAT_ERR) {
pi_disconnect(PI);
if (pd_retries < PD_MAX_RETRIES) {
pd_retries++;
- pi_do_claimed(PI,do_pd_write);
+ pi_do_claimed(PI,do_pd_write_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pd_busy = 0;
- cli();
do_pd_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
pi_disconnect(PI);
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(1);
pd_busy = 0;
- cli();
do_pd_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
/* end of pd.c */
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index b894e2cc9..a176c45d3 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -1,6 +1,6 @@
/*
- pf.c (c) 1997 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU public license.
+ pf.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
This is the high-level driver for parallel port ATAPI disk
drives based on chips supported by the paride module.
@@ -83,8 +83,8 @@
nice This parameter controls the driver's use of
idle CPU time, at the expense of some speed.
- If this driver is built into the kernel, you can use kernel
- the following command line parameters, with the same values
+ If this driver is built into the kernel, you can use the
+ following command line parameters, with the same values
as the corresponding module parameters listed above:
pf.drive0
@@ -99,13 +99,24 @@
*/
-#define PF_VERSION "1.0"
+/* Changes:
+
+ 1.01 GRG 1998.05.03 Changes for SMP. Eliminate sti().
+ Fix for drives that don't clear STAT_ERR
+ until after next CDB delivered.
+ Small change in pf_completion to round
+ up transfer size.
+ 1.02 GRG 1998.06.16 Eliminated an Ugh
+
+*/
+
+#define PF_VERSION "1.02"
#define PF_MAJOR 47
#define PF_NAME "pf"
#define PF_UNITS 4
/* Here are things one can override from the insmod command.
- Most are autoprobed by paride unless set here. Verbose is on
+ Most are autoprobed by paride unless set here. Verbose is off
by default.
*/
@@ -146,6 +157,7 @@ static int pf_drive_count;
#include <linux/genhd.h>
#include <linux/hdreg.h>
#include <linux/cdrom.h>
+#include <asm/spinlock.h>
#include <asm/uaccess.h>
@@ -238,7 +250,9 @@ static int pf_release (struct inode *inode, struct file *file);
static int pf_detect(void);
static void do_pf_read(void);
+static void do_pf_read_start(void);
static void do_pf_write(void);
+static void do_pf_write_start(void);
static void do_pf_read_drq( void );
static void do_pf_write_done( void );
@@ -491,31 +505,20 @@ void cleanup_module(void);
int init_module(void)
{ int err;
- long flags;
-
- save_flags(flags);
- cli();
err = pf_init();
- restore_flags(flags);
return err;
}
void cleanup_module(void)
-{ long flags;
- int unit;
-
- save_flags(flags);
- cli();
+{ int unit;
unregister_blkdev(MAJOR_NR,name);
for (unit=0;unit<PF_UNITS;unit++)
if (PF.present) pi_release(PI);
-
- restore_flags(flags);
}
#endif
@@ -562,7 +565,7 @@ static int pf_command( int unit, char * cmd, int dlen, char * fun )
WR(0,5,dlen / 256);
WR(0,7,0xa0); /* ATAPI packet command */
- if (pf_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR,fun,"command DRQ")) {
+ if (pf_wait(unit,STAT_BUSY,STAT_DRQ,fun,"command DRQ")) {
pi_disconnect(PI);
return -1;
}
@@ -586,7 +589,7 @@ static int pf_completion( int unit, char * buf, char * fun )
fun,"completion");
if ((RR(0,2)&2) && (RR(0,7)&STAT_DRQ)) {
- n = (RR(0,4)+256*RR(0,5));
+ n = (((RR(0,4)+256*RR(0,5))+3)&0xfffc);
pi_read_block(PI,buf,n);
}
@@ -604,7 +607,7 @@ static void pf_req_sense( int unit, int quiet )
int r;
r = pf_command(unit,rs_cmd,16,"Request sense");
- udelay(1000);
+ mdelay(1);
if (!r) pf_completion(unit,buf,"Request sense");
if ((!r)&&(!quiet))
@@ -617,7 +620,7 @@ static int pf_atapi( int unit, char * cmd, int dlen, char * buf, char * fun )
{ int r;
r = pf_command(unit,cmd,dlen,fun);
- udelay(1000);
+ mdelay(1);
if (!r) r = pf_completion(unit,buf,fun);
if (r) pf_req_sense(unit,!fun);
@@ -661,23 +664,17 @@ static int pf_reset( int unit )
{ int i, k, flg;
int expect[5] = {1,1,1,0x14,0xeb};
- long flags;
pi_connect(PI);
WR(0,6,DRIVE);
WR(0,7,8);
- save_flags(flags);
- sti();
-
pf_sleep(2);
k = 0;
while ((k++ < PF_RESET_TMO) && (RR(1,6)&STAT_BUSY))
pf_sleep(10);
- restore_flags(flags);
-
flg = 1;
for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]);
@@ -857,7 +854,7 @@ static int pf_start( int unit, int cmd, int b, int c )
i = pf_command(unit,io_cmd,c*512,"start i/o");
- udelay(1000);
+ mdelay(1);
return i;
}
@@ -906,19 +903,24 @@ repeat:
pf_buf = CURRENT->buffer;
pf_retries = 0;
-
+ pf_busy = 1;
if (pf_cmd == READ) pi_do_claimed(PI,do_pf_read);
else if (pf_cmd == WRITE) pi_do_claimed(PI,do_pf_write);
- else { end_request(0);
+ else { pf_busy = 0;
+ end_request(0);
goto repeat;
}
}
static void pf_next_buf( int unit )
-{ cli();
+{ long saved_flags;
+
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(1);
- if (!pf_run) { sti(); return; }
+ if (!pf_run) { spin_unlock_irqrestore(&io_request_lock,saved_flags);
+ return;
+ }
/* paranoia */
@@ -932,39 +934,46 @@ static void pf_next_buf( int unit )
pf_count = CURRENT->nr_sectors;
pf_buf = CURRENT->buffer;
- sti();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
static void do_pf_read( void )
+/* detach from the calling context - in case the spinlock is held */
+
+{ ps_set_intr(do_pf_read_start,0,0,nice);
+}
+
+static void do_pf_read_start( void )
+
{ int unit = pf_unit;
+ long saved_flags;
pf_busy = 1;
- sti();
-
if (pf_start(unit,ATAPI_READ_10,pf_block,pf_run)) {
pi_disconnect(PI);
if (pf_retries < PF_MAX_RETRIES) {
pf_retries++;
- pi_do_claimed(PI,do_pf_read);
+ pi_do_claimed(PI,do_pf_read_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pf_busy = 0;
- cli();
do_pf_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
- pf_mask=STAT_DRQ;
+ pf_mask = STAT_DRQ;
ps_set_intr(do_pf_read_drq,pf_ready,PF_TMO,nice);
}
static void do_pf_read_drq( void )
{ int unit = pf_unit;
-
- sti();
+ long saved_flags;
+
while (1) {
if (pf_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR,
"read block","completion") & STAT_ERR) {
@@ -972,13 +981,14 @@ static void do_pf_read_drq( void )
if (pf_retries < PF_MAX_RETRIES) {
pf_req_sense(unit,0);
pf_retries++;
- pi_do_claimed(PI,do_pf_read);
+ pi_do_claimed(PI,do_pf_read_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pf_busy = 0;
- cli();
do_pf_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
pi_read_block(PI,pf_buf,512);
@@ -989,31 +999,37 @@ static void do_pf_read_drq( void )
if (!pf_count) pf_next_buf(unit);
}
pi_disconnect(PI);
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(1);
pf_busy = 0;
- cli();
do_pf_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
static void do_pf_write( void )
+{ ps_set_intr(do_pf_write_start,0,0,nice);
+}
+
+static void do_pf_write_start( void )
+
{ int unit = pf_unit;
+ long saved_flags;
pf_busy = 1;
- sti();
-
if (pf_start(unit,ATAPI_WRITE_10,pf_block,pf_run)) {
pi_disconnect(PI);
if (pf_retries < PF_MAX_RETRIES) {
pf_retries++;
- pi_do_claimed(PI,do_pf_write);
+ pi_do_claimed(PI,do_pf_write_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pf_busy = 0;
- cli();
do_pf_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
@@ -1023,13 +1039,14 @@ static void do_pf_write( void )
pi_disconnect(PI);
if (pf_retries < PF_MAX_RETRIES) {
pf_retries++;
- pi_do_claimed(PI,do_pf_write);
+ pi_do_claimed(PI,do_pf_write_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pf_busy = 0;
- cli();
do_pf_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
pi_write_block(PI,pf_buf,512);
@@ -1046,26 +1063,28 @@ static void do_pf_write( void )
static void do_pf_write_done( void )
{ int unit = pf_unit;
+ long saved_flags;
- sti();
if (pf_wait(unit,STAT_BUSY,0,"write block","done") & STAT_ERR) {
pi_disconnect(PI);
if (pf_retries < PF_MAX_RETRIES) {
pf_retries++;
- pi_do_claimed(PI,do_pf_write);
+ pi_do_claimed(PI,do_pf_write_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pf_busy = 0;
- cli();
do_pf_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
pi_disconnect(PI);
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(1);
pf_busy = 0;
- cli();
do_pf_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
/* end of pf.c */
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
new file mode 100644
index 000000000..816b44ede
--- /dev/null
+++ b/drivers/block/paride/pg.c
@@ -0,0 +1,691 @@
+/*
+ pg.c (c) 1998 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
+
+ The pg driver provides a simple character device interface for
+ sending ATAPI commands to a device. With the exception of the
+ ATAPI reset operation, all operations are performed by a pair
+ of read and write operations to the appropriate /dev/pgN device.
+ A write operation delivers a command and any outbound data in
+ a single buffer. Normally, the write will succeed unless the
+ device is offline or malfunctioning, or there is already another
+ command pending. If the write succeeds, it should be followed
+ immediately by a read operation, to obtain any returned data and
+ status information. A read will fail if there is no operation
+ in progress.
+
+ As a special case, the device can be reset with a write operation,
+ and in this case, no following read is expected, or permitted.
+
+ There are no ioctl() operations. Any single operation
+ may transfer at most PG_MAX_DATA bytes. Note that the driver must
+ copy the data through an internal buffer. In keeping with all
+ current ATAPI devices, command packets are assumed to be exactly
+ 12 bytes in length.
+
+ To permit future changes to this interface, the headers in the
+ read and write buffers contain a single character "magic" flag.
+ Currently this flag must be the character "P".
+
+ By default, the driver will autoprobe for a single parallel
+ port ATAPI device, but if their individual parameters are
+ specified, the driver can handle up to 4 devices.
+
+ To use this device, you must have the following device
+ special files defined:
+
+ /dev/pg0 b 97 0
+ /dev/pg1 b 97 1
+ /dev/pg2 b 97 2
+ /dev/pg3 b 97 3
+
+ (You'll need to change the 97 to something else if you use
+ the 'major' parameter to install the driver on a different
+ major number.)
+
+ The behaviour of the pg driver can be altered by setting
+ some parameters from the insmod command line. The following
+ parameters are adjustable:
+
+ drive0 These four arguments can be arrays of
+ drive1 1-6 integers as follows:
+ drive2
+ drive3 <prt>,<pro>,<uni>,<mod>,<slv>,<dly>
+
+ Where,
+
+ <prt> is the base of the parallel port address for
+ the corresponding drive. (required)
+
+ <pro> is the protocol number for the adapter that
+ supports this drive. These numbers are
+ logged by 'paride' when the protocol modules
+ are initialised. (0 if not given)
+
+ <uni> for those adapters that support chained
+ devices, this is the unit selector for the
+ chain of devices on the given port. It should
+ be zero for devices that don't support chaining.
+ (0 if not given)
+
+ <mod> this can be -1 to choose the best mode, or one
+ of the mode numbers supported by the adapter.
+ (-1 if not given)
+
+ <slv> ATAPI devices can be jumpered to master or slave.
+ Set this to 0 to choose the master drive, 1 to
+ choose the slave, -1 (the default) to choose the
+ first drive found.
+
+ <dly> some parallel ports require the driver to
+ go more slowly. -1 sets a default value that
+ should work with the chosen protocol. Otherwise,
+ set this to a small integer, the larger it is
+ the slower the port i/o. In some cases, setting
+ this to zero will speed up the device. (default -1)
+
+ major You may use this parameter to overide the
+ default major number (97) that this driver
+ will use. Be sure to change the device
+ name as well.
+
+ name This parameter is a character string that
+ contains the name the kernel will use for this
+ device (in /proc output, for instance).
+ (default "pg").
+
+ verbose This parameter controls the amount of logging
+ that is done by the driver. Set it to 0 for
+ quiet operation, to 1 to enable progress
+ messages while the driver probes for devices,
+ or to 2 for full debug logging. (default 0)
+
+ If this driver is built into the kernel, you can use
+ the following command line parameters, with the same values
+ as the corresponding module parameters listed above:
+
+ pg.drive0
+ pg.drive1
+ pg.drive2
+ pg.drive3
+
+ In addition, you can use the parameter pg.disable to disable
+ the driver entirely.
+
+*/
+
+/* Changes:
+
+ 1.01 GRG 1998.06.16 Bug fixes
+*/
+
+#define PG_VERSION "1.01"
+#define PG_MAJOR 97
+#define PG_NAME "pg"
+#define PG_UNITS 4
+
+#ifndef PI_PG
+#define PI_PG 4
+#endif
+
+/* Here are things one can override from the insmod command.
+ Most are autoprobed by paride unless set here. Verbose is 0
+ by default.
+
+*/
+
+static int verbose = 0;
+static int major = PG_MAJOR;
+static char *name = PG_NAME;
+static int disable = 0;
+
+static int drive0[6] = {0,0,0,-1,-1,-1};
+static int drive1[6] = {0,0,0,-1,-1,-1};
+static int drive2[6] = {0,0,0,-1,-1,-1};
+static int drive3[6] = {0,0,0,-1,-1,-1};
+
+static int (*drives[4])[6] = {&drive0,&drive1,&drive2,&drive3};
+static int pg_drive_count;
+
+#define D_PRT 0
+#define D_PRO 1
+#define D_UNI 2
+#define D_MOD 3
+#define D_SLV 4
+#define D_DLY 5
+
+#define DU (*drives[unit])
+
+/* end of parameters */
+
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/mtio.h>
+#include <linux/pg.h>
+
+#include <asm/uaccess.h>
+
+#ifndef MODULE
+
+#include "setup.h"
+
+static STT pg_stt[5] = {{"drive0",6,drive0},
+ {"drive1",6,drive1},
+ {"drive2",6,drive2},
+ {"drive3",6,drive3},
+ {"disable",1,&disable}};
+
+void pg_setup( char *str, int *ints)
+
+{ generic_setup(pg_stt,5,str);
+}
+
+#endif
+
+MODULE_PARM(verbose,"i");
+MODULE_PARM(major,"i");
+MODULE_PARM(name,"s");
+MODULE_PARM(drive0,"1-6i");
+MODULE_PARM(drive1,"1-6i");
+MODULE_PARM(drive2,"1-6i");
+MODULE_PARM(drive3,"1-6i");
+
+#include "paride.h"
+
+#define PG_SPIN_DEL 50 /* spin delay in micro-seconds */
+#define PG_SPIN 200
+#define PG_TMO HZ
+#define PG_RESET_TMO 10*HZ
+
+#define STAT_ERR 0x01
+#define STAT_INDEX 0x02
+#define STAT_ECC 0x04
+#define STAT_DRQ 0x08
+#define STAT_SEEK 0x10
+#define STAT_WRERR 0x20
+#define STAT_READY 0x40
+#define STAT_BUSY 0x80
+
+#define ATAPI_IDENTIFY 0x12
+
+int pg_init(void);
+#ifdef MODULE
+void cleanup_module( void );
+#endif
+
+static int pg_open(struct inode *inode, struct file *file);
+static int pg_release (struct inode *inode, struct file *file);
+static ssize_t pg_read(struct file * filp, char * buf,
+ size_t count, loff_t *ppos);
+static ssize_t pg_write(struct file * filp, const char * buf,
+ size_t count, loff_t *ppos);
+static int pg_detect(void);
+
+static int pg_identify (int unit, int log);
+
+#define PG_NAMELEN 8
+
+struct pg_unit {
+ struct pi_adapter pia; /* interface to paride layer */
+ struct pi_adapter *pi;
+ int busy; /* write done, read expected */
+ int start; /* jiffies at command start */
+ int dlen; /* transfer size requested */
+ int timeout; /* timeout requested */
+ int status; /* last sense key */
+ int drive; /* drive */
+ int access; /* count of active opens ... */
+ int present; /* device present ? */
+ char *bufptr;
+ char name[PG_NAMELEN]; /* pg0, pg1, ... */
+ };
+
+struct pg_unit pg[PG_UNITS];
+
+/* 'unit' must be defined in all functions - either as a local or a param */
+
+#define PG pg[unit]
+#define PI PG.pi
+
+static char pg_scratch[512]; /* scratch block buffer */
+
+/* kernel glue structures */
+
+static struct file_operations pg_fops = {
+ NULL, /* lseek - default */
+ pg_read, /* read */
+ pg_write, /* write */
+ NULL, /* readdir - bad */
+ NULL, /* select */
+ NULL, /* ioctl */
+ NULL, /* mmap */
+ pg_open, /* open */
+ pg_release, /* release */
+ NULL, /* fsync */
+ NULL, /* fasync */
+ NULL, /* media change ? */
+ NULL /* revalidate new media */
+};
+
+void pg_init_units( void )
+
+{ int unit, j;
+
+ pg_drive_count = 0;
+ for (unit=0;unit<PG_UNITS;unit++) {
+ PG.pi = & PG.pia;
+ PG.access = 0;
+ PG.busy = 0;
+ PG.present = 0;
+ PG.bufptr = NULL;
+ PG.drive = DU[D_SLV];
+ j = 0;
+ while ((j < PG_NAMELEN-2) && (PG.name[j]=name[j])) j++;
+ PG.name[j++] = '0' + unit;
+ PG.name[j] = 0;
+ if (DU[D_PRT]) pg_drive_count++;
+ }
+}
+
+int pg_init (void) /* preliminary initialisation */
+
+{ int unit;
+
+ if (disable) return -1;
+
+ pg_init_units();
+
+ if (pg_detect()) return -1;
+
+ if (register_chrdev(major,name,&pg_fops)) {
+ printk("pg_init: unable to get major number %d\n",
+ major);
+ for (unit=0;unit<PG_UNITS;unit++)
+ if (PG.present) pi_release(PI);
+ return -1;
+ }
+
+ return 0;
+}
+
+#ifdef MODULE
+
+/* Glue for modules ... */
+
+void cleanup_module(void);
+
+int init_module(void)
+
+{ int err;
+
+ err = pg_init();
+
+ return err;
+}
+
+void cleanup_module(void)
+
+{ int unit;
+
+ unregister_chrdev(major,name);
+
+ for (unit=0;unit<PG_UNITS;unit++)
+ if (PG.present) pi_release(PI);
+}
+
+#endif
+
+#define WR(c,r,v) pi_write_regr(PI,c,r,v)
+#define RR(c,r) (pi_read_regr(PI,c,r))
+
+#define DRIVE (0xa0+0x10*PG.drive)
+
+static void pg_sleep( int cs )
+
+{ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + cs;
+ schedule();
+}
+
+static int pg_wait( int unit, int go, int stop, int tmo, char * msg )
+
+{ int j, r, e, s, p;
+
+ PG.status = 0;
+
+ j = 0;
+ while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(jiffies<tmo)) {
+ if (j++ < PG_SPIN) udelay(PG_SPIN_DEL);
+ else pg_sleep(1);
+ }
+
+ if ((r&(STAT_ERR&stop))||(jiffies>=tmo)) {
+ s = RR(0,7);
+ e = RR(0,1);
+ p = RR(0,2);
+ if (verbose > 1)
+ printk("%s: %s: stat=0x%x err=0x%x phase=%d%s\n",
+ PG.name,msg,s,e,p,(jiffies>=tmo)?" timeout":"");
+
+
+ if (jiffies>=tmo) e |= 0x100;
+ PG.status = (e >> 4) & 0xff;
+ return -1;
+ }
+ return 0;
+}
+
+static int pg_command( int unit, char * cmd, int dlen, int tmo )
+
+{ int k;
+
+ pi_connect(PI);
+
+ WR(0,6,DRIVE);
+
+ if (pg_wait(unit,STAT_BUSY|STAT_DRQ,0,tmo,"before command")) {
+ pi_disconnect(PI);
+ return -1;
+ }
+
+ WR(0,4,dlen % 256);
+ WR(0,5,dlen / 256);
+ WR(0,7,0xa0); /* ATAPI packet command */
+
+ if (pg_wait(unit,STAT_BUSY,STAT_DRQ,tmo,"command DRQ")) {
+ pi_disconnect(PI);
+ return -1;
+ }
+
+ if (RR(0,2) != 1) {
+ printk("%s: command phase error\n",PG.name);
+ pi_disconnect(PI);
+ return -1;
+ }
+
+ pi_write_block(PI,cmd,12);
+
+ if (verbose > 1) {
+ printk("%s: Command sent, dlen=%d packet= ", PG.name,dlen);
+ for (k=0;k<12;k++) printk("%02x ",cmd[k]&0xff);
+ printk("\n");
+ }
+ return 0;
+}
+
+static int pg_completion( int unit, char * buf, int tmo)
+
+{ int r, d, n, p;
+
+ r = pg_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR,
+ tmo,"completion");
+
+ PG.dlen = 0;
+
+ while (RR(0,7)&STAT_DRQ) {
+ d = (RR(0,4)+256*RR(0,5));
+ n = ((d+3)&0xfffc);
+ p = RR(0,2)&3;
+ if (p == 0) pi_write_block(PI,buf,n);
+ if (p == 2) pi_read_block(PI,buf,n);
+ if (verbose > 1) printk("%s: %s %d bytes\n",PG.name,
+ p?"Read":"Write",n);
+ PG.dlen += (1-p)*d;
+ buf += d;
+ r = pg_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR,
+ tmo,"completion");
+ }
+
+ pi_disconnect(PI);
+
+ return r;
+}
+
+static int pg_reset( int unit )
+
+{ int i, k, flg;
+ int expect[5] = {1,1,1,0x14,0xeb};
+
+ pi_connect(PI);
+ WR(0,6,DRIVE);
+ WR(0,7,8);
+
+ pg_sleep(2);
+
+ k = 0;
+ while ((k++ < PG_RESET_TMO) && (RR(1,6)&STAT_BUSY))
+ pg_sleep(1);
+
+ flg = 1;
+ for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]);
+
+ if (verbose) {
+ printk("%s: Reset (%d) signature = ",PG.name,k);
+ for (i=0;i<5;i++) printk("%3x",RR(0,i+1));
+ if (!flg) printk(" (incorrect)");
+ printk("\n");
+ }
+
+ pi_disconnect(PI);
+ return flg-1;
+}
+
+static void xs( char *buf, char *targ, int offs, int len )
+
+{ int j,k,l;
+
+ j=0; l=0;
+ for (k=0;k<len;k++)
+ if((buf[k+offs]!=0x20)||(buf[k+offs]!=l))
+ l=targ[j++]=buf[k+offs];
+ if (l==0x20) j--; targ[j]=0;
+}
+
+static int pg_identify( int unit, int log )
+
+{ int s;
+ char *ms[2] = {"master","slave"};
+ char mf[10], id[18];
+ char id_cmd[12] = { ATAPI_IDENTIFY,0,0,0,36,0,0,0,0,0,0,0};
+ char buf[36];
+
+ s = pg_command(unit,id_cmd,36,jiffies+PG_TMO);
+ if (s) return -1;
+ s = pg_completion(unit,buf,jiffies+PG_TMO);
+ if (s) return -1;
+
+ if (log) {
+ xs(buf,mf,8,8);
+ xs(buf,id,16,16);
+ printk("%s: %s %s, %s\n",PG.name,mf,id,ms[PG.drive]);
+ }
+
+ return 0;
+}
+
+static int pg_probe( int unit )
+
+/* returns 0, with id set if drive is detected
+ -1, if drive detection failed
+*/
+
+{ if (PG.drive == -1) {
+ for (PG.drive=0;PG.drive<=1;PG.drive++)
+ if (!pg_reset(unit)) return pg_identify(unit,1);
+ } else {
+ if (!pg_reset(unit)) return pg_identify(unit,1);
+ }
+ return -1;
+}
+
+static int pg_detect( void )
+
+{ int k, unit;
+
+ printk("%s: %s version %s, major %d\n",
+ name,name,PG_VERSION,major);
+
+ k = 0;
+ if (pg_drive_count == 0) {
+ unit = 0;
+ if (pi_init(PI,1,-1,-1,-1,-1,-1,pg_scratch,
+ PI_PG,verbose,PG.name)) {
+ if (!pg_probe(unit)) {
+ PG.present = 1;
+ k++;
+ } else pi_release(PI);
+ }
+
+ } else for (unit=0;unit<PG_UNITS;unit++) if (DU[D_PRT])
+ if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI],
+ DU[D_PRO],DU[D_DLY],pg_scratch,PI_PG,verbose,
+ PG.name)) {
+ if (!pg_probe(unit)) {
+ PG.present = 1;
+ k++;
+ } else pi_release(PI);
+ }
+
+ if (k) return 0;
+
+ printk("%s: No ATAPI device detected\n",name);
+ return -1;
+}
+
+#define DEVICE_NR(dev) (MINOR(dev) % 128)
+
+static int pg_open (struct inode *inode, struct file *file)
+
+{ int unit = DEVICE_NR(inode->i_rdev);
+
+ if ((unit >= PG_UNITS) || (!PG.present)) return -ENODEV;
+
+ PG.access++;
+
+ if (PG.access > 1) {
+ PG.access--;
+ return -EBUSY;
+ }
+
+ MOD_INC_USE_COUNT;
+
+ if (PG.busy) {
+ pg_reset(unit);
+ PG.busy = 0;
+ }
+
+ pg_identify(unit,(verbose>1));
+
+
+ PG.bufptr = kmalloc(PG_MAX_DATA,GFP_KERNEL);
+ if (PG.bufptr == NULL) {
+ PG.access--;
+ MOD_DEC_USE_COUNT;
+ printk("%s: buffer allocation failed\n",PG.name);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int pg_release (struct inode *inode, struct file *file)
+{
+ int unit = DEVICE_NR(inode->i_rdev);
+
+ if ((unit >= PG_UNITS) || (PG.access <= 0))
+ return -EINVAL;
+
+ PG.access--;
+
+ kfree(PG.bufptr);
+ PG.bufptr = NULL;
+
+ MOD_DEC_USE_COUNT;
+
+ return 0;
+
+}
+
+static ssize_t pg_write(struct file * filp, const char * buf,
+ size_t count, loff_t *ppos)
+
+{ struct inode *ino = filp->f_dentry->d_inode;
+ int unit = DEVICE_NR(ino->i_rdev);
+ struct pg_write_hdr hdr;
+ int hs = sizeof(hdr);
+
+ if (PG.busy) return -EBUSY;
+ if (count < hs) return -EINVAL;
+
+ copy_from_user((char *)&hdr,buf,hs);
+
+ if (hdr.magic != PG_MAGIC) return -EINVAL;
+ if (hdr.dlen > PG_MAX_DATA) return -EINVAL;
+ if ((count - hs) > PG_MAX_DATA) return -EINVAL;
+
+ if (hdr.func == PG_RESET) {
+ if (count != hs) return -EINVAL;
+ if (pg_reset(unit)) return -EIO;
+ return count;
+ }
+
+ if (hdr.func != PG_COMMAND) return -EINVAL;
+
+ PG.start = jiffies;
+ PG.timeout = hdr.timeout*HZ + HZ/2 + jiffies;
+
+ if (pg_command(unit,hdr.packet,hdr.dlen,jiffies+PG_TMO)) {
+ if (PG.status & 0x10) return -ETIME;
+ return -EIO;
+ }
+
+ PG.busy = 1;
+
+ copy_from_user(PG.bufptr,buf+hs,count-hs);
+
+ return count;
+}
+
+static ssize_t pg_read(struct file * filp, char * buf,
+ size_t count, loff_t *ppos)
+
+{ struct inode *ino = filp->f_dentry->d_inode;
+ int unit = DEVICE_NR(ino->i_rdev);
+ struct pg_read_hdr hdr;
+ int hs = sizeof(hdr);
+ int copy;
+
+ if (!PG.busy) return -EINVAL;
+ if (count < hs) return -EINVAL;
+
+ PG.busy = 0;
+
+ if (pg_completion(unit,PG.bufptr,PG.timeout))
+ if (PG.status & 0x10) return -ETIME;
+
+ hdr.magic = PG_MAGIC;
+ hdr.dlen = PG.dlen;
+ copy = 0;
+
+ if (hdr.dlen < 0) {
+ hdr.dlen = -1 * hdr.dlen;
+ copy = hdr.dlen;
+ if (copy > (count - hs)) copy = count - hs;
+ }
+
+ hdr.duration = (jiffies - PG.start + HZ/2) / HZ;
+ hdr.scsi = PG.status & 0x0f;
+
+ copy_to_user(buf,(char *)&hdr,hs);
+ if (copy > 0) copy_to_user(buf+hs,PG.bufptr,copy);
+
+ return copy+hs;
+}
+
+/* end of pg.c */
+
diff --git a/drivers/block/paride/pseudo.h b/drivers/block/paride/pseudo.h
index 44c74c7c9..17615c2ca 100644
--- a/drivers/block/paride/pseudo.h
+++ b/drivers/block/paride/pseudo.h
@@ -1,6 +1,6 @@
/*
- pseudo.h (c) 1997 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU public license.
+ pseudo.h (c) 1997-8 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
This is the "pseudo-interrupt" logic for parallel port drivers.
@@ -22,6 +22,14 @@
*/
+/* Changes:
+
+ 1.01 1998.05.03 Switched from cli()/sti() to spinlocks
+
+*/
+
+#define PS_VERSION "1.01"
+
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/tqueue.h>
@@ -37,6 +45,8 @@ static int ps_timeout;
static int ps_timer_active = 0;
static int ps_tq_active = 0;
+static spinlock_t ps_spinlock = SPIN_LOCK_UNLOCKED;
+
static struct timer_list ps_timer = {0,0,0,0,ps_timer_int};
static struct tq_struct ps_tq = {0,0,ps_tq_int,NULL};
@@ -46,8 +56,7 @@ static void ps_set_intr( void (*continuation)(void),
{ long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&ps_spinlock,flags);
ps_continuation = continuation;
ps_ready = ready;
@@ -69,7 +78,7 @@ static void ps_set_intr( void (*continuation)(void),
add_timer(&ps_timer);
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&ps_spinlock,flags);
}
static void ps_tq_int( void *data )
@@ -77,8 +86,7 @@ static void ps_tq_int( void *data )
{ void (*con)(void);
long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&ps_spinlock,flags);
con = ps_continuation;
@@ -89,12 +97,12 @@ static void ps_tq_int( void *data )
ps_tq_active = 0;
if (!con) {
- restore_flags(flags);
+ spin_unlock_irqrestore(&ps_spinlock,flags);
return;
}
- if (ps_ready() || (jiffies >= ps_timeout)) {
+ if (!ps_ready || ps_ready() || (jiffies >= ps_timeout)) {
ps_continuation = NULL;
- restore_flags(flags);
+ spin_unlock_irqrestore(&ps_spinlock,flags);
con();
return;
}
@@ -105,7 +113,7 @@ static void ps_tq_int( void *data )
ps_tq_active = 1;
queue_task(&ps_tq,&tq_scheduler);
- restore_flags(flags);
+ spin_unlock_irqrestore(&ps_spinlock,flags);
}
static void ps_timer_int( unsigned long data)
@@ -113,25 +121,24 @@ static void ps_timer_int( unsigned long data)
{ void (*con)(void);
long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&ps_spinlock,flags);
con = ps_continuation;
ps_timer_active = 0;
if (!con) {
- restore_flags(flags);
+ spin_unlock_irqrestore(&ps_spinlock,flags);
return;
}
- if (ps_ready() || (jiffies >= ps_timeout)) {
+ if (!ps_ready || ps_ready() || (jiffies >= ps_timeout)) {
ps_continuation = NULL;
- restore_flags(flags);
+ spin_unlock_irqrestore(&ps_spinlock,flags);
con();
return;
}
ps_timer_active = 1;
ps_timer.expires = jiffies;
add_timer(&ps_timer);
- restore_flags(flags);
+ spin_unlock_irqrestore(&ps_spinlock,flags);
}
/* end of pseudo.h */
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 922e98271..de77c1b5a 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -90,7 +90,17 @@
*/
-#define PT_VERSION "1.0"
+/* Changes:
+
+ 1.01 GRG 1998.05.06 Round up transfer size, fix ready_wait,
+ loosed interpretation of ATAPI standard
+ for clearing error status.
+ Eliminate sti();
+ 1.02 GRG 1998.06.16 Eliminate an Ugh.
+
+*/
+
+#define PT_VERSION "1.02"
#define PT_MAJOR 96
#define PT_NAME "pt"
#define PT_UNITS 4
@@ -313,31 +323,20 @@ void cleanup_module(void);
int init_module(void)
{ int err;
- long flags;
-
- save_flags(flags);
- cli();
err = pt_init();
- restore_flags(flags);
return err;
}
void cleanup_module(void)
-{ long flags;
- int unit;
-
- save_flags(flags);
- cli();
+{ int unit;
unregister_chrdev(major,name);
for (unit=0;unit<PT_UNITS;unit++)
if (PT.present) pi_release(PI);
-
- restore_flags(flags);
}
#endif
@@ -383,7 +382,7 @@ static int pt_command( int unit, char * cmd, int dlen, char * fun )
WR(0,5,dlen / 256);
WR(0,7,0xa0); /* ATAPI packet command */
- if (pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR,fun,"command DRQ")) {
+ if (pt_wait(unit,STAT_BUSY,STAT_DRQ,fun,"command DRQ")) {
pi_disconnect(PI);
return -1;
}
@@ -407,7 +406,7 @@ static int pt_completion( int unit, char * buf, char * fun )
fun,"completion");
if (RR(0,7)&STAT_DRQ) {
- n = (RR(0,4)+256*RR(0,5));
+ n = (((RR(0,4)+256*RR(0,5))+3)&0xfffc);
p = RR(0,2)&3;
if (p == 0) pi_write_block(PI,buf,n);
if (p == 2) pi_read_block(PI,buf,n);
@@ -427,7 +426,7 @@ static void pt_req_sense( int unit, int quiet )
int r;
r = pt_command(unit,rs_cmd,16,"Request sense");
- udelay(1000);
+ mdelay(1);
if (!r) pt_completion(unit,buf,"Request sense");
PT.last_sense = -1;
@@ -444,7 +443,7 @@ static int pt_atapi( int unit, char * cmd, int dlen, char * buf, char * fun )
{ int r;
r = pt_command(unit,cmd,dlen,fun);
- udelay(1000);
+ mdelay(1);
if (!r) r = pt_completion(unit,buf,fun);
if (r) pt_req_sense(unit,!fun);
@@ -512,23 +511,17 @@ static int pt_reset( int unit )
{ int i, k, flg;
int expect[5] = {1,1,1,0x14,0xeb};
- long flags;
pi_connect(PI);
WR(0,6,DRIVE);
WR(0,7,8);
- save_flags(flags);
- sti();
-
pt_sleep(2);
k = 0;
while ((k++ < PT_RESET_TMO) && (RR(1,6)&STAT_BUSY))
pt_sleep(10);
- restore_flags(flags);
-
flg = 1;
for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]);
@@ -554,7 +547,7 @@ static int pt_ready_wait( int unit, int tmo )
pt_atapi(unit,tr_cmd,0,NULL,DBMSG("test unit ready"));
p = PT.last_sense;
if (!p) return 0;
- if (!((p == 0x010402)||((p & 0xff) == 6))) return p;
+ if (!(((p & 0xffff) == 0x0402)||((p & 0xff) == 6))) return p;
k++;
pt_sleep(100);
}
@@ -817,7 +810,7 @@ static ssize_t pt_read(struct file * filp, char * buf,
r = pt_command(unit,rd_cmd,n,"read");
- udelay(1000);
+ mdelay(1);
if (r) {
pt_req_sense(unit,0);
@@ -903,7 +896,7 @@ static ssize_t pt_write(struct file * filp, const char * buf,
r = pt_command(unit,wr_cmd,n,"write");
- udelay(1000);
+ mdelay(1);
if (r) { /* error delivering command only */
pt_req_sense(unit,0);
diff --git a/drivers/block/paride/setup.h b/drivers/block/paride/setup.h
index 6d941cc09..931924179 100644
--- a/drivers/block/paride/setup.h
+++ b/drivers/block/paride/setup.h
@@ -1,12 +1,18 @@
/*
- setup.h (c) 1997 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU public license.
+ setup.h (c) 1997-8 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
This is a table driven setup function for kernel modules
using the module.variable=val,... command line notation.
*/
+/* Changes:
+
+ 1.01 GRG 1998.05.05 Allow negative and defaulted values
+
+*/
+
#include <linux/ctype.h>
#include <linux/string.h>
@@ -29,7 +35,7 @@ typedef struct setup_tab_t STT;
static void generic_setup( STT t[], int n, char *ss )
-{ int j,k;
+{ int j,k, sgn;
k = 0;
for (j=0;j<n;j++) {
@@ -47,10 +53,17 @@ static void generic_setup( STT t[], int n, char *ss )
ss += (k+1);
k = 0;
- while (ss && isdigit(*ss) && (k < t[j].size)) {
- t[j].iv[k++] = simple_strtoul(ss,NULL,0);
+ while (ss && (k < t[j].size)) {
+ if (!*ss) break;
+ sgn = 1;
+ if (*ss == '-') { ss++; sgn = -1; }
+ if (!*ss) break;
+ if (isdigit(*ss))
+ t[j].iv[k] = sgn * simple_strtoul(ss,NULL,0);
+ k++;
if ((ss = strchr(ss,',')) != NULL) ss++;
}
}
/* end of setup.h */
+
diff --git a/drivers/block/raid0.c b/drivers/block/raid0.c
index 7b8aea1c9..2e95d34f8 100644
--- a/drivers/block/raid0.c
+++ b/drivers/block/raid0.c
@@ -104,7 +104,7 @@ static int raid0_run (int minor, struct md_dev *mddev)
md_size[minor]/data->smallest->size +
(md_size[minor]%data->smallest->size ? 1 : 0);
- printk ("raid0 : Allocating %d bytes for hash.\n",sizeof(struct raid0_hash)*nb_zone);
+ printk ("raid0 : Allocating %ld bytes for hash.\n",(long)sizeof(struct raid0_hash)*nb_zone);
if ((data->hash_table=vmalloc (sizeof (struct raid0_hash)*nb_zone)) == NULL)
{
vfree(data->strip_zone);
diff --git a/drivers/block/raid1.c b/drivers/block/raid1.c
index e85d8fd69..12512c8df 100644
--- a/drivers/block/raid1.c
+++ b/drivers/block/raid1.c
@@ -164,7 +164,7 @@ void raid1_end_request (struct buffer_head *bh, int uptodate)
PRINTK(("raid1_end_request(), write branch.\n"));
/*
- * lets see if all mirrored write operations have finished
+ * Let's see if all mirrored write operations have finished
* already [we have irqs off, so we can decrease]:
*/
@@ -457,8 +457,8 @@ static int raid1_hot_add_disk (struct md_dev *mddev, kdev_t dev)
int n;
/*
- * The device has it's superblock already read and it was found
- * to be consistent for generic RAID usage, now we check wether
+ * The device has its superblock already read and it was found
+ * to be consistent for generic RAID usage. Now we check whether
* it's usable for RAID-1 hot addition.
*/
diff --git a/drivers/block/raid5.c b/drivers/block/raid5.c
index 88e2eb133..66713a84b 100644
--- a/drivers/block/raid5.c
+++ b/drivers/block/raid5.c
@@ -21,6 +21,7 @@
#include <linux/raid5.h>
#include <asm/bitops.h>
#include <asm/atomic.h>
+#include <asm/md.h>
static struct md_personality raid5_personality;
@@ -741,10 +742,16 @@ static unsigned long compute_blocknr(struct stripe_head *sh, int i)
return blocknr;
}
+#ifdef HAVE_ARCH_XORBLOCK
static void xor_block(struct buffer_head *dest, struct buffer_head *source)
{
- int lines = dest->b_size / (sizeof (int)) / 8, i;
- int *destp = (int *) dest->b_data, *sourcep = (int *) source->b_data;
+ __xor_block((char *) dest->b_data, (char *) source->b_data, dest->b_size);
+}
+#else
+static void xor_block(struct buffer_head *dest, struct buffer_head *source)
+{
+ long lines = dest->b_size / (sizeof (long)) / 8, i;
+ long *destp = (long *) dest->b_data, *sourcep = (long *) source->b_data;
for (i = lines; i > 0; i--) {
*(destp + 0) ^= *(sourcep + 0);
@@ -759,6 +766,7 @@ static void xor_block(struct buffer_head *dest, struct buffer_head *source)
sourcep += 8;
}
}
+#endif
static void compute_block(struct stripe_head *sh, int dd_idx)
{
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index a3366d04b..822e3ec18 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -1,39 +1,39 @@
/*
- * ramdisk.c - Multiple ramdisk driver - gzip-loading version - v. 0.8 beta.
+ * ramdisk.c - Multiple RAM disk driver - gzip-loading version - v. 0.8 beta.
*
* (C) Chad Page, Theodore Ts'o, et. al, 1995.
*
- * This ramdisk is designed to have filesystems created on it and mounted
+ * This RAM disk is designed to have filesystems created on it and mounted
* just like a regular floppy disk.
*
* It also does something suggested by Linus: use the buffer cache as the
- * ramdisk data. This makes it possible to dynamically allocate the ramdisk
+ * RAM disk data. This makes it possible to dynamically allocate the RAM disk
* buffer - with some consequences I have to deal with as I write this.
*
* This code is based on the original ramdisk.c, written mostly by
* Theodore Ts'o (TYT) in 1991. The code was largely rewritten by
- * Chad Page to use the buffer cache to store the ramdisk data in
+ * Chad Page to use the buffer cache to store the RAM disk data in
* 1995; Theodore then took over the driver again, and cleaned it up
* for inclusion in the mainline kernel.
*
* The original CRAMDISK code was written by Richard Lyons, and
- * adapted by Chad Page to use the new ramdisk interface. Theodore
- * Ts'o rewrote it so that both the compressed ramdisk loader and the
- * kernel decompressor uses the same inflate.c codebase. The ramdisk
- * loader now also loads into a dynamic (buffer cache based) ramdisk,
- * not the old static ramdisk. Support for the old static ramdisk has
+ * adapted by Chad Page to use the new RAM disk interface. Theodore
+ * Ts'o rewrote it so that both the compressed RAM disk loader and the
+ * kernel decompressor uses the same inflate.c codebase. The RAM disk
+ * loader now also loads into a dynamic (buffer cache based) RAM disk,
+ * not the old static RAM disk. Support for the old static RAM disk has
* been completely removed.
*
* Loadable module support added by Tom Dyas.
*
* Further cleanups by Chad Page (page0588@sundance.sjsu.edu):
- * Cosmetic changes in #ifdef MODULE, code movement, etc...
- * When the ramdisk is rmmod'ed, free the protected buffers
- * Default ramdisk size changed to 2.88MB
+ * Cosmetic changes in #ifdef MODULE, code movement, etc.
+ * When the RAM disk module is removed, free the protected buffers
+ * Default RAM disk size changed to 2.88 MB
*
* Added initrd: Werner Almesberger & Hans Lermen, Feb '96
*
- * 4/25/96 : Made ramdisk size a parameter (default is now 4MB)
+* 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
@@ -70,11 +70,11 @@ extern void wait_for_keypress(void);
#define MAJOR_NR RAMDISK_MAJOR
#include <linux/blk.h>
-/* The ramdisk size is now a parameter */
+/* The RAM disk size is now a parameter */
#define NUM_RAMDISKS 16 /* This cannot be overridden (yet) */
#ifndef MODULE
-/* We don't have to load ramdisks or gunzip them in a module... */
+/* We don't have to load RAM disks or gunzip them in a module. */
#define RD_LOADER
#define BUILD_CRAMDISK
@@ -86,22 +86,23 @@ static int initrd_users = 0;
#endif
#endif
-/* Various static variables go here... mostly used within the ramdisk code only. */
+/* 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];
/*
- * Parameters for the boot-loading of the ramdisk. These are set by
+ * Parameters for the boot-loading of the RAM disk. These are set by
* init/main.c (from arguments to the kernel command line) or from the
- * architecture-specific setup routine (from the stored bootsector
+ * architecture-specific setup routine (from the stored boot sector
* information).
*/
-int rd_size = 4096; /* Size of the ramdisks */
+int rd_size = 4096; /* Size of the RAM disks */
#ifndef MODULE
-int rd_doload = 0; /* 1 = load ramdisk, 0 = don't load */
-int rd_prompt = 1; /* 1 = prompt for ramdisk, 0 = don't prompt */
+int rd_doload = 0; /* 1 = load RAM disk, 0 = don't load */
+int rd_prompt = 1; /* 1 = prompt for RAM disk, 0 = don't prompt */
int rd_image_start = 0; /* starting block # of image */
#ifdef CONFIG_BLK_DEV_INITRD
unsigned long initrd_start,initrd_end;
@@ -273,7 +274,7 @@ static struct file_operations fd_fops = {
block_fsync /* fsync */
};
-/* This is the registration and initialization section of the ramdisk driver */
+/* This is the registration and initialization section of the RAM disk driver */
__initfunc(int rd_init(void))
{
int i;
@@ -292,7 +293,7 @@ __initfunc(int rd_init(void))
blksize_size[MAJOR_NR] = rd_blocksizes;
- printk("Ramdisk driver initialized : %d ramdisks of %dK size\n",
+ printk("RAM disk driver initialized: %d RAM disks of %dK size\n",
NUM_RAMDISKS, rd_size);
return 0;
@@ -324,11 +325,11 @@ void cleanup_module(void)
#endif /* MODULE */
-/* End of non-loading portions of the ramdisk driver */
+/* End of non-loading portions of the RAM disk driver */
#ifdef RD_LOADER
/*
- * This routine tries to find a ramdisk image to load, and returns the
+ * This routine tries to find a RAM disk image to load, and returns the
* number of blocks to read for a non-compressed image, 0 if the image
* is a compressed image, and -1 if an image with the right magic
* numbers could not be found.
@@ -382,7 +383,7 @@ identify_ramdisk_image(kdev_t device, struct file *fp, int start_block))
if (romfsb->word0 == ROMSB_WORD0 &&
romfsb->word1 == ROMSB_WORD1) {
printk(KERN_NOTICE
- "RAMDISK: Romfs filesystem found at block %d\n",
+ "RAMDISK: romfs filesystem found at block %d\n",
start_block);
nblocks = (ntohl(romfsb->size)+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
goto done;
@@ -410,14 +411,14 @@ identify_ramdisk_image(kdev_t device, struct file *fp, int start_block))
/* Try ext2 */
if (ext2sb->s_magic == cpu_to_le16(EXT2_SUPER_MAGIC)) {
printk(KERN_NOTICE
- "RAMDISK: Ext2 filesystem found at block %d\n",
+ "RAMDISK: ext2 filesystem found at block %d\n",
start_block);
nblocks = le32_to_cpu(ext2sb->s_blocks_count);
goto done;
}
printk(KERN_NOTICE
- "RAMDISK: Couldn't find valid ramdisk image starting at %d.\n",
+ "RAMDISK: Couldn't find valid RAM disk image starting at %d.\n",
start_block);
done:
@@ -430,7 +431,7 @@ done:
}
/*
- * This routine loads in the ramdisk image.
+ * This routine loads in the RAM disk image.
*/
__initfunc(static void rd_load_image(kdev_t device,int offset))
{
@@ -480,7 +481,7 @@ __initfunc(static void rd_load_image(kdev_t device,int offset))
#else
printk(KERN_NOTICE
"RAMDISK: Kernel does not support compressed "
- "ramdisk images\n");
+ "RAM disk images\n");
#endif
goto done;
}
@@ -564,7 +565,7 @@ __initfunc(void rd_load(void))
floppy_eject();
#endif
printk(KERN_NOTICE
- "VFS: Insert root floppy disk to be loaded into ramdisk and press ENTER\n");
+ "VFS: Insert root floppy disk to be loaded into RAM disk and press ENTER\n");
wait_for_keypress();
}
diff --git a/drivers/block/sl82c105.c b/drivers/block/sl82c105.c
index ef05e4656..39b62fddd 100644
--- a/drivers/block/sl82c105.c
+++ b/drivers/block/sl82c105.c
@@ -38,7 +38,10 @@ void ide_init_sl82c105(ide_hwif_t *hwif)
pci_write_config_dword(dev, 0x40, 0x10ff08a1);
}
-#if 0 /* nobody ever calls these.. ?? */
+/* nobody ever calls these.. ?? -mlord
+ *
+ * Yes somebody certainly does, check asm-ppc/ide.h for the place. -DaveM
+ */
void chrp_ide_probe(void) {
struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL);
@@ -68,4 +71,3 @@ void chrp_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
if (irq != NULL)
*irq = chrp_ide_irq;
}
-#endif
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index 58ced412f..5598ad0a7 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -21,6 +21,7 @@
#include <asm/dbdma.h>
#include <asm/prom.h>
#include <asm/uaccess.h>
+#include <asm/mediabay.h>
#define MAJOR_NR FLOPPY_MAJOR
#include <linux/blk.h>
@@ -134,9 +135,11 @@ struct floppy_state {
int ref_count;
int expect_cyl;
struct timer_list timeout;
+ int timeout_pending;
int ejected;
struct wait_queue *wait;
int wanted;
+ int in_media_bay;
char dbdma_cmd_space[5 * sizeof(struct dbdma_cmd)];
};
@@ -161,6 +164,8 @@ static void swim3_action(struct floppy_state *fs, int action);
static int swim3_readbit(struct floppy_state *fs, int bit);
static void do_fd_request(void);
static void start_request(struct floppy_state *fs);
+static void set_timeout(struct floppy_state *fs, int nticks,
+ void (*proc)(unsigned long));
static void scan_track(struct floppy_state *fs);
static void seek_track(struct floppy_state *fs, int n);
static void init_dma(struct dbdma_cmd *cp, int cmd, void *buf, int count);
@@ -179,10 +184,10 @@ static int floppy_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long param);
static int floppy_open(struct inode *inode, struct file *filp);
static int floppy_release(struct inode *inode, struct file *filp);
-static long floppy_read(struct inode *inode, struct file *filp,
- char *buf, unsigned long count);
-static long floppy_write(struct inode *inode, struct file *filp,
- const char *buf, unsigned long count);
+static ssize_t floppy_read(struct file *filp, char *buf,
+ size_t count, loff_t *ppos);
+static ssize_t floppy_write(struct file *filp, const char *buf,
+ size_t count, loff_t *ppos);
static int floppy_check_change(kdev_t dev);
static int floppy_revalidate(kdev_t dev);
int swim3_init(void);
@@ -294,6 +299,22 @@ static void start_request(struct floppy_state *fs)
}
}
+static void set_timeout(struct floppy_state *fs, int nticks,
+ void (*proc)(unsigned long))
+{
+ unsigned long flags;
+
+ save_flags(flags); cli();
+ if (fs->timeout_pending)
+ del_timer(&fs->timeout);
+ fs->timeout.expires = jiffies + nticks;
+ fs->timeout.function = proc;
+ fs->timeout.data = (unsigned long) fs;
+ add_timer(&fs->timeout);
+ fs->timeout_pending = 1;
+ restore_flags(flags);
+}
+
static inline void scan_track(struct floppy_state *fs)
{
volatile struct swim3 *sw = fs->swim3;
@@ -304,11 +325,7 @@ static inline void scan_track(struct floppy_state *fs)
out_8(&sw->control_bis, SCAN_TRACK);
/* enable intr when track found */
out_8(&sw->intr_enable, ERROR | SEEN_SECTOR);
- /* enable timeout */
- fs->timeout.expires = jiffies + HZ;
- fs->timeout.function = scan_timeout;
- fs->timeout.data = (unsigned long) fs;
- add_timer(&fs->timeout);
+ set_timeout(fs, HZ, scan_timeout); /* enable timeout */
}
static inline void seek_track(struct floppy_state *fs, int n)
@@ -327,11 +344,7 @@ static inline void seek_track(struct floppy_state *fs, int n)
out_8(&sw->control_bis, DO_SEEK);
/* enable intr when seek finished */
out_8(&sw->intr_enable, ERROR | SEEK_DONE);
- /* enable timeout */
- fs->timeout.expires = jiffies + HZ/2;
- fs->timeout.function = seek_timeout;
- fs->timeout.data = (unsigned long) fs;
- add_timer(&fs->timeout);
+ set_timeout(fs, HZ/2, seek_timeout); /* enable timeout */
}
static inline void init_dma(struct dbdma_cmd *cp, int cmd,
@@ -384,11 +397,7 @@ static inline void setup_transfer(struct floppy_state *fs)
(CURRENT->cmd == WRITE? WRITE_SECTORS: 0) | SCAN_TRACK);
/* enable intr when transfer complete */
out_8(&sw->intr_enable, ERROR | TRANSFER_DONE);
- /* enable timeout */
- fs->timeout.expires = jiffies + 2*HZ;
- fs->timeout.function = xfer_timeout;
- fs->timeout.data = (unsigned long) fs;
- add_timer(&fs->timeout);
+ set_timeout(fs, 2*HZ, xfer_timeout); /* enable timeout */
}
static void act(struct floppy_state *fs)
@@ -434,10 +443,7 @@ static void act(struct floppy_state *fs)
in_8(&sw->intr); /* clear DATA_CHANGED */
if (in_8(&sw->status) & DATA) {
/* seek_complete is not yet true */
- fs->timeout.expires = jiffies + HZ/2;
- fs->timeout.function = seek_timeout;
- fs->timeout.data = (unsigned long) fs;
- add_timer(&fs->timeout);
+ set_timeout(fs, HZ/2, seek_timeout);
return;
}
out_8(&sw->intr_enable, 0);
@@ -474,6 +480,7 @@ static void scan_timeout(unsigned long data)
struct floppy_state *fs = (struct floppy_state *) data;
volatile struct swim3 *sw = fs->swim3;
+ fs->timeout_pending = 0;
out_8(&sw->control_bic, SCAN_TRACK);
out_8(&sw->select, RELAX);
out_8(&sw->intr_enable, 0);
@@ -493,6 +500,7 @@ static void seek_timeout(unsigned long data)
struct floppy_state *fs = (struct floppy_state *) data;
volatile struct swim3 *sw = fs->swim3;
+ fs->timeout_pending = 0;
if (fs->state == settling) {
printk(KERN_ERR "swim3: MSI sel=%x ctrl=%x stat=%x intr=%x ie=%x\n",
sw->select, sw->control, sw->status, sw->intr, sw->intr_enable);
@@ -520,6 +528,7 @@ static void xfer_timeout(unsigned long data)
struct dbdma_cmd *cp = fs->dma_cmd;
unsigned long s;
+ 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);
@@ -550,6 +559,9 @@ static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
err = in_8(&sw->error);
intr = in_8(&sw->intr);
+#if 0
+ printk(KERN_DEBUG "swim3 intr state=%d intr=%x err=%x\n", fs->state, intr, err);
+#endif
if ((intr & ERROR) && fs->state != do_transfer)
printk(KERN_ERR "swim3_interrupt, state=%d, cmd=%x, intr=%x, err=%x\n",
fs->state, CURRENT->cmd, intr, err);
@@ -560,6 +572,7 @@ static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
out_8(&sw->select, RELAX);
out_8(&sw->intr_enable, 0);
del_timer(&fs->timeout);
+ fs->timeout_pending = 0;
if (sw->ctrack == 0xff) {
printk(KERN_ERR "swim3: seen sector but cyl=ff?\n");
fs->cur_cyl = -1;
@@ -589,6 +602,7 @@ static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
out_8(&sw->select, RELAX);
out_8(&sw->intr_enable, 0);
del_timer(&fs->timeout);
+ fs->timeout_pending = 0;
if (fs->state == seeking)
++fs->retries;
fs->state = settling;
@@ -598,6 +612,7 @@ static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
case settling:
out_8(&sw->intr_enable, 0);
del_timer(&fs->timeout);
+ fs->timeout_pending = 0;
act(fs);
break;
case do_transfer:
@@ -610,6 +625,7 @@ static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
out_8(&sw->control_bic, WRITE_SECTORS | SCAN_TRACK);
out_8(&sw->select, RELAX);
del_timer(&fs->timeout);
+ fs->timeout_pending = 0;
if (CURRENT->cmd == WRITE)
++cp;
stat = ld_le16(&cp->xfer_status);
@@ -772,6 +788,12 @@ static int floppy_open(struct inode *inode, struct file *filp)
sw = fs->swim3;
err = 0;
if (fs->ref_count == 0) {
+ if (fs->in_media_bay && !check_media_bay(MB_FD))
+ return -ENXIO;
+ out_8(&sw->mode, 0x95);
+ out_8(&sw->control_bic, 0xff);
+ out_8(&sw->reg5, 0x28);
+ udelay(1);
out_8(&sw->intr_enable, 0);
out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE);
swim3_action(fs, MOTOR_ON);
@@ -905,9 +927,10 @@ static int floppy_revalidate(kdev_t dev)
return ret;
}
-static long floppy_read(struct inode *inode, struct file *filp,
- char *buf, unsigned long count)
+static ssize_t floppy_read(struct file *filp, char *buf,
+ size_t count, loff_t *ppos)
{
+ struct inode *inode = filp->f_dentry->d_inode;
struct floppy_state *fs;
if (MINOR(inode->i_rdev) != 0)
@@ -915,12 +938,13 @@ static long floppy_read(struct inode *inode, struct file *filp,
fs = &floppy_states[0];
if (fs->ejected)
return -ENXIO;
- return block_read(inode, filp, buf, count);
+ return block_read(filp, buf, count, ppos);
}
-static long floppy_write(struct inode *inode, struct file *filp,
- const char *buf, unsigned long count)
+static ssize_t floppy_write(struct file * filp, const char * buf,
+ size_t count, loff_t *ppos)
{
+ struct inode * inode = filp->f_dentry->d_inode;
struct floppy_state *fs;
if (MINOR(inode->i_rdev) != 0)
@@ -928,7 +952,7 @@ static long floppy_write(struct inode *inode, struct file *filp,
fs = &floppy_states[0];
if (fs->ejected)
return -ENXIO;
- return block_write(inode, filp, buf, count);
+ return block_write(filp, buf, count, ppos);
}
static void floppy_off(unsigned int nr)
@@ -955,9 +979,16 @@ int swim3_init(void)
{
struct device_node *swims;
struct floppy_state *fs = &floppy_states[0];
- volatile struct swim3 *sw;
+ int is_3400 = 0;
+
+ if (find_devices("media-bay") != NULL) {
+ /* assume this is a PB3400 */
+ swims = find_devices("floppy");
+ is_3400 = 1;
+ } else {
+ swims = find_devices("swim3");
+ }
- swims = find_devices("swim3");
if (swims == NULL)
return 0;
@@ -982,13 +1013,14 @@ int swim3_init(void)
fs->state = idle;
fs->swim3 = (volatile struct swim3 *) swims->addrs[0].address;
fs->dma = (struct dbdma_regs *) swims->addrs[1].address;
- fs->swim3_intr = swims->intrs[0];
- fs->dma_intr = swims->intrs[1];
+ fs->swim3_intr = swims->intrs[0].line;
+ fs->dma_intr = swims->intrs[1].line;
fs->cur_cyl = -1;
fs->cur_sector = -1;
fs->secpercyl = 36;
fs->secpertrack = 18;
fs->total_secs = 2880;
+ fs->in_media_bay = is_3400;
fs->dma_cmd = (struct dbdma_cmd *) DBDMA_ALIGN(fs->dbdma_cmd_space);
memset(fs->dma_cmd, 0, 2 * sizeof(struct dbdma_cmd));
@@ -1004,10 +1036,7 @@ int swim3_init(void)
return -EBUSY;
}
- sw = fs->swim3;
- out_8(&sw->mode, 0x95);
- out_8(&sw->control_bic, 0xff);
- out_8(&sw->reg5, 0x28);
+ init_timer(&fs->timeout);
do_floppy = NULL;
diff --git a/drivers/block/trm290.c b/drivers/block/trm290.c
index 2b0678849..a502fedf6 100644
--- a/drivers/block/trm290.c
+++ b/drivers/block/trm290.c
@@ -249,7 +249,7 @@ __initfunc(void ide_init_trm290 (ide_hwif_t *hwif))
ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3);
hwif->dmaproc = &trm290_dmaproc;
hwif->selectproc = &trm290_selectproc;
- hwif->no_autodma = 1; /* play it safe for now */
+ hwif->autodma = 0; /* play it safe for now */
#if 1
{
/*
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index b7d604db8..ffb1645ac 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -240,7 +240,7 @@ __initfunc(static void xd_geninit (struct gendisk *ignored))
}
if (xd_drives) {
- if (!request_irq(xd_irq,xd_interrupt_handler, 0, "XT harddisk", NULL)) {
+ if (!request_irq(xd_irq,xd_interrupt_handler, 0, "XT hard disk", NULL)) {
if (request_dma(xd_dma,"xd")) {
printk("xd: unable to get DMA%d\n",xd_dma);
free_irq(xd_irq, NULL);
@@ -708,8 +708,7 @@ __initfunc(static void xd_dtc_init_controller (unsigned int address))
switch (address) {
case 0x00000:
case 0xC8000: break; /*initial: 0x320 */
- case 0xCA000: if (xd[3]<=0) xd_iobase = 0x324;
- break;
+ case 0xCA000: xd_iobase = 0x324;
case 0xD0000: /*5150CX*/
case 0xD8000: break; /*5150CX & 5150XL*/
default: printk("xd_dtc_init_controller: unsupported BIOS address %06x\n",address);
@@ -873,13 +872,14 @@ __initfunc(static void xd_wd_init_drive (u_char drive))
xd_info[drive].ecc = 0x0B;
#endif /* 0 */
}
- if (!wd_1002)
+ if (!wd_1002) {
if (use_jumper_geo)
xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,
geometry_table[n][2],geometry_table[n][3],0x0B);
else
xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,
((u_short *) (buf))[0xD8],((u_short *) (buf))[0xDA],buf[0x1B4]);
+ }
/* 1002 based RLL controler requests converted adressing, but reports physical
(physical 26 sec., logical 17 sec.)
1004 based ???? */