diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-08-25 09:12:35 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-08-25 09:12:35 +0000 |
commit | c7fc24dc4420057f103afe8fc64524ebc25c5d37 (patch) | |
tree | 3682407a599b8f9f03fc096298134cafba1c9b2f /drivers/block | |
parent | 1d793fade8b063fde3cf275bf1a5c2d381292cd9 (diff) |
o Merge with Linux 2.1.116.
o New Newport console code.
o New G364 console code.
Diffstat (limited to 'drivers/block')
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(¤t->blocked, SHUTDOWN_SIGS); + thread->tsk = current; + up(thread->sem); + for (;;) { + cli(); + if (!test_bit(THREAD_WAKEUP, &thread->flags)) { + do { + spin_lock(¤t->sigmask_lock); + flush_signals(current); + spin_unlock(¤t->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(¤t->sigmask_lock); - flush_signals(current); - spin_unlock(¤t->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 ???? */ |