summaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/Config.in11
-rw-r--r--drivers/block/Makefile8
-rw-r--r--drivers/block/README.fd11
-rw-r--r--drivers/block/acsi.c4
-rw-r--r--drivers/block/amiflop.c16
-rw-r--r--drivers/block/floppy.c79
-rw-r--r--drivers/block/genhd.c35
-rw-r--r--drivers/block/ide-cd.c29
-rw-r--r--drivers/block/ide-cd.h257
-rw-r--r--drivers/block/ide-disk.c21
-rw-r--r--drivers/block/ide-dma.c79
-rw-r--r--drivers/block/ide-floppy.c156
-rw-r--r--drivers/block/ide-pci.c132
-rw-r--r--drivers/block/ide-pmac.c33
-rw-r--r--drivers/block/ide-probe.c24
-rw-r--r--drivers/block/ide-tape.c4
-rw-r--r--drivers/block/ide.c28
-rw-r--r--drivers/block/ide.h19
-rw-r--r--drivers/block/ll_rw_blk.c33
-rw-r--r--drivers/block/loop.c312
-rw-r--r--drivers/block/md.c4
-rw-r--r--drivers/block/ns87415.c46
-rw-r--r--drivers/block/paride/frpw.c6
-rw-r--r--drivers/block/paride/jumbo70
-rw-r--r--drivers/block/paride/on26.c63
-rw-r--r--drivers/block/paride/pcd.c14
-rw-r--r--drivers/block/paride/pd.c9
-rw-r--r--drivers/block/paride/pf.c12
-rw-r--r--drivers/block/paride/pg.c21
-rw-r--r--drivers/block/paride/pt.c18
-rw-r--r--drivers/block/ps2esdi.c72
-rw-r--r--drivers/block/sl82c105.c39
-rw-r--r--drivers/block/swim3.c198
-rw-r--r--drivers/block/via82c586.c86
-rw-r--r--drivers/block/xd.c21
35 files changed, 1458 insertions, 512 deletions
diff --git a/drivers/block/Config.in b/drivers/block/Config.in
index 02bfe7dcd..a4920df2a 100644
--- a/drivers/block/Config.in
+++ b/drivers/block/Config.in
@@ -33,6 +33,7 @@ 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
+ bool ' Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD
if [ "$CONFIG_BLK_DEV_IDEDMA" = "y" ]; then
bool ' Use DMA by default when available' CONFIG_IDEDMA_AUTO
fi
@@ -41,11 +42,13 @@ else
if [ "$CONFIG_BLK_DEV_IDEDMA" = "y" ]; then
bool ' Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290
bool ' NS87415 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_NS87415
+ bool ' VIA82C586 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82C586
+ bool ' CMD646 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_CMD646
fi
fi
fi
if [ "$CONFIG_PPC" = "y" ]; then
- bool ' WInbond SL82c105 support' CONFIG_BLK_DEV_SL82C105
+ bool ' Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105
fi
fi
if [ "$CONFIG_PMAC" = "y" ]; then
@@ -74,7 +77,7 @@ else
fi
fi
if [ "$CONFIG_MCA" = "y" ]; then
- bool 'PS/2 ESDI hard disk support' CONFIG_BLK_DEV_PS2
+ tristate '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
@@ -91,7 +94,9 @@ fi
comment 'Additional Block Devices'
tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
-tristate 'Network block device support' CONFIG_BLK_DEV_NBD
+if [ "$CONFIG_NET" = "y" ]; then
+ tristate 'Network block device support' CONFIG_BLK_DEV_NBD
+fi
bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD
if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then
tristate ' Linear (append) mode' CONFIG_MD_LINEAR
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index fa943cc48..6d48ecb98 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -87,10 +87,10 @@ else
endif
ifeq ($(CONFIG_BLK_DEV_LOOP),y)
-L_OBJS += loop.o
+LX_OBJS += loop.o
else
ifeq ($(CONFIG_BLK_DEV_LOOP),m)
- M_OBJS += loop.o
+ MX_OBJS += loop.o
endif
endif
@@ -154,6 +154,10 @@ ifeq ($(CONFIG_BLK_DEV_NS87415),y)
IDE_OBJS += ns87415.o
endif
+ifeq ($(CONFIG_BLK_DEV_VIA82C586),y)
+IDE_OBJS += via82c586.o
+endif
+
ifeq ($(CONFIG_BLK_DEV_CMD646),y)
IDE_OBJS += cmd646.o
endif
diff --git a/drivers/block/README.fd b/drivers/block/README.fd
index b750c89cf..3e3e8f346 100644
--- a/drivers/block/README.fd
+++ b/drivers/block/README.fd
@@ -102,12 +102,12 @@ isn't, use the old method using environment variables.
Tells the floppy driver that a workable DMA channel is available
(the default).
-floppy=nofifo
+ floppy=nofifo
Disables the FIFO entirely. This is needed if you get "Bus
master arbitration error" messages from your Ethernet card (or
from other devices) while accessing the floppy.
-floppy=fifo
+ floppy=fifo
Enables the FIFO (default)
floppy=<threshold>,fifo_depth
@@ -189,6 +189,13 @@ floppy=fifo
floppy=<nr>,dma
Sets the floppy DMA channel to <nr> instead of 2
+ floppy=slow
+ Use PS/2 stepping rate:
+ " PS/2 floppies have much slower step rates than regular floppies.
+ It's been recommended that take about 1/4 of the default speed
+ in some more extreme cases."
+
+
Supporting utilities and additional documentation:
==================================================
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index f49f186a8..9d6c4fb00 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -3,7 +3,7 @@
*
* Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
*
- * Some parts are based on hd.c by Linus Thorvalds
+ * Some parts are based on hd.c by Linus Torvalds
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
@@ -1343,7 +1343,7 @@ static int acsi_mode_sense( int target, int lun, SENSE_DATA *sd )
if (acsi_wait_for_noIRQ( 20 ) &&
acsicmd_nodma( modesense_cmd, 0 ) &&
acsi_wait_for_IRQ( 3*HZ ) &&
- acsi_getstatus() == 0);
+ acsi_getstatus() == 0)
break;
}
if (page == 4) {
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index a7631741e..cc97d18dd 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -114,7 +114,7 @@
#define FD_HD_3 0x55555555 /* high-density 3.5" (1760K) drive */
#define FD_DD_5 0xaaaaaaaa /* double-density 5.25" (440K) drive */
-static long int fd_def_df0 = 0; /* default for df0 if it doesn't identify */
+static long int fd_def_df0 = FD_DD_3; /* default for df0 if it doesn't identify */
MODULE_PARM(fd_def_df0,"l");
@@ -1859,20 +1859,6 @@ __initfunc(int amiga_floppy_init(void))
blksize_size[MAJOR_NR] = floppy_blocksizes;
blk_size[MAJOR_NR] = floppy_sizes;
-
- #if 0 /* Doesn't seem to be correct */
- if (fd_def_df0==0) {
- if ((amiga.model == AMI_3000) || (amiga.model == AMI_3000T) ||
- (amiga.model == AMI_3000PLUS) || (amiga.model == AMI_4000))
- fd_def_df0=FD_HD_3;
- else
- fd_def_df0=FD_DD_3;
- }
- #else
- /* Now we hope that every HD drive will identify itself correctly */
- fd_def_df0 = FD_DD_3;
- #endif
-
for (i = 0; i < 128; i++)
mfmdecode[i]=255;
for (i = 0; i < 16; i++)
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index e555aa9d9..1a40d6009 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -102,6 +102,10 @@
* failures.
*/
+/*
+ * 1998/09/20 -- David Weinehall -- Added slow-down code for buggy PS/2-drives.
+ */
+
#define FLOPPY_SANITY_CHECK
#undef FLOPPY_SILENT_DCL_CLEAR
@@ -149,6 +153,13 @@ static int irqdma_allocated = 0;
#include <linux/interrupt.h>
#include <linux/init.h>
+/*
+ * PS/2 floppies have much slower step rates than regular floppies.
+ * It's been recommended that take about 1/4 of the default speed
+ * in some more extreme cases.
+ */
+static int slow_floppy = 0;
+
#include <asm/dma.h>
#include <asm/irq.h>
#include <asm/system.h>
@@ -348,7 +359,7 @@ static struct {
0, { 1, 0, 0, 0, 0, 0, 0, 0}, 3*HZ/2, 1 }, "360K PC" }, /*5 1/4 360 KB PC*/
{{2, 500, 16, 16, 6000, 4*HZ/10, 3*HZ, 14, SEL_DLY, 6, 83, 3*HZ, 17, {3,1,2,0,2}, 0,
- 0, { 2, 5, 6,23,10,20,11, 0}, 3*HZ/2, 2 }, "1.2M" }, /*5 1/4 HD AT*/
+ 0, { 2, 5, 6,23,10,20,12, 0}, 3*HZ/2, 2 }, "1.2M" }, /*5 1/4 HD AT*/
{{3, 250, 16, 16, 3000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0,
0, { 4,22,21,30, 3, 0, 0, 0}, 3*HZ/2, 4 }, "720k" }, /*3 1/2 DD*/
@@ -1045,6 +1056,7 @@ static void floppy_enable_hlt(void)
static void setup_DMA(void)
{
unsigned long flags;
+ unsigned long f;
#ifdef FLOPPY_SANITY_CHECK
if (raw_cmd->length == 0){
@@ -1066,17 +1078,20 @@ static void setup_DMA(void)
}
#endif
INT_OFF;
+ f=claim_dma_lock();
fd_disable_dma(FLOPPY_DMA);
#ifdef fd_dma_setup
if(fd_dma_setup(raw_cmd->kernel_data, raw_cmd->length,
(raw_cmd->flags & FD_RAW_READ)?
DMA_MODE_READ : DMA_MODE_WRITE,
FDCS->address) < 0) {
+ release_dma_lock(f);
INT_ON;
cont->done(0);
FDCS->reset=1;
return;
}
+ release_dma_lock(f);
#else
fd_clear_dma_ff(FLOPPY_DMA);
dma_cache_wback_inv((unsigned long)raw_cmd->kernel_data,
@@ -1088,6 +1103,7 @@ static void setup_DMA(void)
fd_set_dma_count(FLOPPY_DMA, raw_cmd->length);
virtual_dma_port = FDCS->address;
fd_enable_dma(FLOPPY_DMA);
+ release_dma_lock(f);
#endif
INT_ON;
floppy_disable_hlt();
@@ -1302,6 +1318,9 @@ static void fdc_specify(void)
/* Convert step rate from microseconds to milliseconds and 4 bits */
srt = 16 - (DP->srt*scale_dtr/1000 + NOMINAL_DTR - 1)/NOMINAL_DTR;
+ if( slow_floppy ) {
+ srt = srt / 4;
+ }
SUPBOUND(srt, 0xf);
INFBOUND(srt, 0);
@@ -1687,11 +1706,15 @@ void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
void (*handler)(void) = DEVICE_INTR;
int do_print;
+ unsigned long f;
lasthandler = handler;
interruptjiffies = jiffies;
+ f=claim_dma_lock();
fd_disable_dma(FLOPPY_DMA);
+ release_dma_lock(f);
+
floppy_enable_hlt();
CLEAR_INTR;
if (fdc >= N_FDC || FDCS->address == -1){
@@ -1719,12 +1742,14 @@ void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs)
if(do_print)
print_result("unexpected interrupt", inr);
if (inr == 0){
+ int max_sensei = 4;
do {
output_byte(FD_SENSEI);
inr = result();
if(do_print)
print_result("sensei", inr);
- } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2);
+ max_sensei--;
+ } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2 && max_sensei);
}
if (handler) {
int cpu = smp_processor_id();
@@ -1772,13 +1797,18 @@ static void reset_interrupt(void)
*/
static void reset_fdc(void)
{
+ unsigned long flags;
+
SET_INTR(reset_interrupt);
FDCS->reset = 0;
reset_fdc_info(0);
/* Pseudo-DMA may intercept 'reset finished' interrupt. */
/* Irrelevant for systems with true DMA (i386). */
+
+ flags=claim_dma_lock();
fd_disable_dma(FLOPPY_DMA);
+ release_dma_lock(flags);
if (FDCS->version >= FDC_82072A)
fd_outb(0x80 | (FDCS->dtr &3), FD_STATUS);
@@ -1837,12 +1867,18 @@ static void show_floppy(void)
static void floppy_shutdown(void)
{
+ unsigned long flags;
+
if (!initialising)
show_floppy();
cancel_activity();
floppy_enable_hlt();
+
+ flags=claim_dma_lock();
fd_disable_dma(FLOPPY_DMA);
+ release_dma_lock(flags);
+
/* avoid dma going to a random drive after shutdown */
if (!initialising)
@@ -1890,6 +1926,8 @@ static int start_motor(void (*function)(void) )
static void floppy_ready(void)
{
+ unsigned long flags;
+
CHECK_RESET;
if (start_motor(floppy_ready)) return;
if (fdc_dtr()) return;
@@ -1908,8 +1946,12 @@ static void floppy_ready(void)
#ifdef fd_chose_dma_mode
if ((raw_cmd->flags & FD_RAW_READ) ||
(raw_cmd->flags & FD_RAW_WRITE))
+ {
+ flags=claim_dma_lock();
fd_chose_dma_mode(raw_cmd->kernel_data,
raw_cmd->length);
+ release_dma_lock(flags);
+ }
#endif
if (raw_cmd->flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)){
@@ -2886,7 +2928,8 @@ static void process_fd_request(void)
static void do_fd_request(void)
{
if(usage_count == 0) {
- printk("warning: usage count=0, CURRENT=%p exiting\n", CURRENT); printk("sect=%ld cmd=%d\n", CURRENT->sector, CURRENT->cmd);
+ printk("warning: usage count=0, CURRENT=%p exiting\n", CURRENT);
+ printk("sect=%ld cmd=%d\n", CURRENT->sector, CURRENT->cmd);
return;
}
if (fdc_busy){
@@ -3012,7 +3055,12 @@ static void raw_cmd_done(int flag)
raw_cmd->reply[i] = reply_buffer[i];
if (raw_cmd->flags & (FD_RAW_READ | FD_RAW_WRITE))
+ {
+ unsigned long flags;
+ flags=claim_dma_lock();
raw_cmd->length = fd_get_dma_residue(FLOPPY_DMA);
+ release_dma_lock(flags);
+ }
if ((raw_cmd->flags & FD_RAW_SOFTFAILURE) &&
(!raw_cmd->reply_count || (raw_cmd->reply[0] & 0xc0)))
@@ -4017,6 +4065,7 @@ static struct param_table {
{ "usefifo", 0, &no_fifo, 0, 0 },
{ "cmos", set_cmos, 0, 0, 0 },
+ { "slow", 0, &slow_floppy, 1, 0 },
{ "unexpected_interrupts", 0, &print_unex, 1, 0 },
{ "no_unexpected_interrupts", 0, &print_unex, 0, 0 },
@@ -4027,7 +4076,7 @@ __initfunc(void floppy_setup(char *str, int *ints))
{
int i;
int param;
- if (str)
+ if (str) {
for (i=0; i< ARRAY_SIZE(config_params); i++){
if (strcmp(str,config_params[i].name) == 0){
if (ints[0])
@@ -4045,6 +4094,7 @@ __initfunc(void floppy_setup(char *str, int *ints))
return;
}
}
+ }
if (str) {
DPRINT("unknown floppy option [%s]\n", str);
@@ -4107,6 +4157,8 @@ __initfunc(int floppy_init(void))
#endif
if (floppy_grab_irq_and_dma()){
+ del_timer(&fd_timeout);
+ blk_dev[MAJOR_NR].request_fn = NULL;
unregister_blkdev(MAJOR_NR,"fd");
del_timer(&fd_timeout);
return -EBUSY;
@@ -4116,7 +4168,9 @@ __initfunc(int floppy_init(void))
for (drive = 0; drive < N_DRIVE; drive++) {
CLEARSTRUCT(UDRS);
CLEARSTRUCT(UDRWE);
- UDRS->flags = FD_VERIFY | FD_DISK_NEWCHANGE | FD_DISK_CHANGED;
+ USETF(FD_DISK_NEWCHANGE);
+ USETF(FD_DISK_CHANGED);
+ USETF(FD_VERIFY);
UDRS->fd_device = -1;
floppy_track_buffer = NULL;
max_buffer_sectors = 0;
@@ -4131,6 +4185,9 @@ __initfunc(int floppy_init(void))
continue;
FDCS->rawcmd = 2;
if (user_reset_fdc(-1,FD_RESET_ALWAYS,0)){
+ /* free ioports reserved by floppy_grab_irq_and_dma() */
+ release_region(FDCS->address, 6);
+ release_region(FDCS->address+7, 1);
FDCS->address = -1;
FDCS->version = FDC_NONE;
continue;
@@ -4138,6 +4195,9 @@ __initfunc(int floppy_init(void))
/* Try to determine the floppy controller type */
FDCS->version = get_fdc_version();
if (FDCS->version == FDC_NONE){
+ /* free ioports reserved by floppy_grab_irq_and_dma() */
+ release_region(FDCS->address, 6);
+ release_region(FDCS->address+7, 1);
FDCS->address = -1;
continue;
}
@@ -4156,8 +4216,15 @@ __initfunc(int floppy_init(void))
current_drive = 0;
floppy_release_irq_and_dma();
initialising=0;
- if (have_no_fdc) {
+ if (have_no_fdc)
+ {
DPRINT("no floppy controllers found\n");
+ floppy_tq.routine = (void *)(void *) empty;
+ mark_bh(IMMEDIATE_BH);
+ schedule();
+ if (usage_count)
+ floppy_release_irq_and_dma();
+ blk_dev[MAJOR_NR].request_fn = NULL;
unregister_blkdev(MAJOR_NR,"fd");
}
return have_no_fdc;
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index c1b1e4e06..7fb8430ee 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -16,6 +16,8 @@
* More flexible handling of extended partitions - aeb, 950831
*
* Check partition table on IDE disks for common CHS translations
+ *
+ * Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl}
*/
#include <linux/config.h>
@@ -59,6 +61,10 @@ extern int blk_dev_init(void);
extern int scsi_dev_init(void);
extern int net_dev_init(void);
+#ifdef CONFIG_PPC
+extern void note_bootable_part(kdev_t dev, int part);
+#endif
+
/*
* disk_name() is used by genhd.c and md.c.
* It formats the devicename of the indicated disk
@@ -69,7 +75,7 @@ char *disk_name (struct gendisk *hd, int minor, char *buf)
{
unsigned int part;
const char *maj = hd->major_name;
- char unit = (minor >> hd->minor_shift) + 'a';
+ int unit = (minor >> hd->minor_shift) + 'a';
/*
* IDE devices use multiple major numbers, but the drives
@@ -77,6 +83,10 @@ char *disk_name (struct gendisk *hd, int minor, char *buf)
* This requires special handling here.
*/
switch (hd->major) {
+ case IDE5_MAJOR:
+ unit += 2;
+ case IDE4_MAJOR:
+ unit += 2;
case IDE3_MAJOR:
unit += 2;
case IDE2_MAJOR:
@@ -85,8 +95,19 @@ char *disk_name (struct gendisk *hd, int minor, char *buf)
unit += 2;
case IDE0_MAJOR:
maj = "hd";
+ break;
}
part = minor & ((1 << hd->minor_shift) - 1);
+ if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
+ unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
+ if (unit > 'z') {
+ unit -= 'z' + 1;
+ sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);
+ if (part)
+ sprintf(buf + 4, "%d", part);
+ return buf;
+ }
+ }
if (part)
sprintf(buf, "%s%c%d", maj, unit, part);
else
@@ -421,8 +442,8 @@ check_table:
&& (q->end_sector & 63) == 63) {
unsigned int heads = q->end_head + 1;
if (heads == 32 || heads == 64 ||
- heads == 128 || heads == 255 ||
- heads == 240) {
+ heads == 128 || heads == 240 ||
+ heads == 255) {
(void) ide_xlate_1024(dev, heads, " [PTBL]");
break;
}
@@ -845,7 +866,7 @@ static int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec)
int blk, blocks_in_map;
int dev_bsize, dev_pos, pos;
unsigned secsize;
-#ifdef CONFIG_PMAC
+#ifdef CONFIG_PPC
int first_bootable = 1;
#endif
struct mac_partition *part;
@@ -899,18 +920,18 @@ static int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec)
fsec + be32_to_cpu(part->start_block) * (secsize/512),
be32_to_cpu(part->block_count) * (secsize/512));
-#ifdef CONFIG_PMAC
+#ifdef CONFIG_PPC
/*
* If this is the first bootable partition, tell the
* setup code, in case it wants to make this the root.
*/
- if (first_bootable
+ if ( (_machine == _MACH_Pmac) && first_bootable
&& (be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE)
&& strcasecmp(part->processor, "powerpc") == 0) {
note_bootable_part(dev, blk);
first_bootable = 0;
}
-#endif /* CONFIG_PMAC */
+#endif /* CONFIG_PPC */
++current_minor;
}
diff --git a/drivers/block/ide-cd.c b/drivers/block/ide-cd.c
index 34ac359d2..2231f5693 100644
--- a/drivers/block/ide-cd.c
+++ b/drivers/block/ide-cd.c
@@ -1,8 +1,9 @@
-#define VERBOSE_IDE_CD_ERRORS 1
+#define VERBOSE_IDE_CD_ERRORS 1
/*
* linux/drivers/block/ide-cd.c
* Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov>
* Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org>
+ * Copyright (C) 1998 Jens Axboe and Chris Zwilling
*
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
@@ -218,9 +219,16 @@
* since the .pdf version doesn't seem to work...
* -- Updated the TODO list to something more current.
*
+ * 4.15 Aug 25, 1998 -- Updated ide-cd.h to respect mechine endianess,
+ * patch thanks to "Eddie C. Dost" <ecd@skynet.be>
+ *
+ * 4.50 Oct 19, 1998 -- New maintainers!
+ * Jens Axboe <axboe@image.dk>
+ * Chris Zwilling <chris@cloudnet.com>
+ *
*************************************************************************/
-#define IDECD_VERSION "4.14"
+#define IDECD_VERSION "4.50"
#include <linux/module.h>
#include <linux/types.h>
@@ -1287,8 +1295,7 @@ static
void cdrom_sleep (int time)
{
current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + time;
- schedule ();
+ schedule_timeout(time);
}
static
@@ -2597,6 +2604,8 @@ int ide_cdrom_select_disc (struct cdrom_device_info *cdi, int slot)
return 0;
}
else {
+ int was_locked;
+
if (
#if ! STANDARD_ATAPI
CDROM_STATE_FLAGS (drive)->sanyo_slot == 0 &&
@@ -2605,6 +2614,10 @@ int ide_cdrom_select_disc (struct cdrom_device_info *cdi, int slot)
return -ENOMEDIUM;
}
+ was_locked = CDROM_STATE_FLAGS (drive)->door_locked;
+ if (was_locked)
+ (void) cdrom_lockdoor (drive, 0, NULL);
+
stat = cdrom_load_unload (drive, slot, NULL);
cdrom_saw_media_change (drive);
if (stat)
@@ -2618,10 +2631,12 @@ int ide_cdrom_select_disc (struct cdrom_device_info *cdi, int slot)
stat = cdrom_read_toc (drive, &my_reqbuf);
if (stat)
return stat;
- return slot;
}
- else
- return stat;
+
+ if (was_locked)
+ (void) cdrom_lockdoor (drive, 1, NULL);
+
+ return slot;
}
}
diff --git a/drivers/block/ide-cd.h b/drivers/block/ide-cd.h
index fbb2f859e..e72777fdd 100644
--- a/drivers/block/ide-cd.h
+++ b/drivers/block/ide-cd.h
@@ -4,8 +4,11 @@
* linux/drivers/block/ide_modes.h
*
* Copyright (C) 1996 Erik Andersen
+ * Copyright (C) 1998 Jens Axboe and Chris Zwilling
*/
+#include <asm/byteorder.h>
+
/* Turn this on to have the driver print out the meanings of the
ATAPI error codes. This will use up additional kernel-space
memory, though. */
@@ -148,13 +151,29 @@ struct ide_cd_state_flags {
struct atapi_request_sense {
+#if defined(__BIG_ENDIAN_BITFIELD)
+ unsigned char valid : 1;
+ unsigned char error_code : 7;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
unsigned char error_code : 7;
unsigned char valid : 1;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
byte reserved1;
+#if defined(__BIG_ENDIAN_BITFIELD)
+ unsigned char reserved3 : 2;
+ unsigned char ili : 1;
+ unsigned char reserved2 : 1;
+ unsigned char sense_key : 4;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
unsigned char sense_key : 4;
unsigned char reserved2 : 1;
unsigned char ili : 1;
unsigned char reserved3 : 2;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
byte info[4];
byte sense_len;
byte command_info[4];
@@ -190,8 +209,15 @@ struct atapi_toc_header {
struct atapi_toc_entry {
byte reserved1;
- unsigned control : 4;
- unsigned adr : 4;
+#if defined(__BIG_ENDIAN_BITFIELD)
+ __u8 adr : 4;
+ __u8 control : 4;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 control : 4;
+ __u8 adr : 4;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
byte track;
byte reserved2;
union {
@@ -218,8 +244,15 @@ struct atapi_cdrom_subchnl {
u_short acdsc_length;
u_char acdsc_format;
+#if defined(__BIG_ENDIAN_BITFIELD)
+ u_char acdsc_ctrl: 4;
+ u_char acdsc_adr: 4;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
u_char acdsc_adr: 4;
u_char acdsc_ctrl: 4;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
u_char acdsc_trk;
u_char acdsc_ind;
union {
@@ -243,79 +276,182 @@ typedef enum {
struct atapi_capabilities_page {
- unsigned page_code : 6;
- unsigned reserved1 : 1;
- unsigned parameters_saveable : 1;
+#if defined(__BIG_ENDIAN_BITFIELD)
+ __u8 parameters_saveable : 1;
+ __u8 reserved1 : 1;
+ __u8 page_code : 6;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 page_code : 6;
+ __u8 reserved1 : 1;
+ __u8 parameters_saveable : 1;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
byte page_length;
+#if defined(__BIG_ENDIAN_BITFIELD)
+ __u8 reserved2 : 5;
+ /* Drive supports reading CD-R discs with addressing method 2 */
+ __u8 method2 : 1; /* reserved in 1.2 */
+ /* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
+ __u8 cd_rw_read : 1; /* reserved in 1.2 */
/* Drive supports read from CD-R discs (orange book, part II) */
- unsigned cd_r_read : 1; /* reserved in 1.2 */
- /* Drive supports read from CD-R/W (CD-E) discs (orange book, part III) */
- unsigned cd_rw_read : 1; /* reserved in 1.2 */
+ __u8 cd_r_read : 1; /* reserved in 1.2 */
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+ /* Drive supports read from CD-R discs (orange book, part II) */
+ __u8 cd_r_read : 1; /* reserved in 1.2 */
+ /* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
+ __u8 cd_rw_read : 1; /* reserved in 1.2 */
/* Drive supports reading CD-R discs with addressing method 2 */
- unsigned method2 : 1; /* reserved in 1.2 */
- unsigned reserved2 : 5;
+ __u8 method2 : 1; /* reserved in 1.2 */
+ __u8 reserved2 : 5;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+#if defined(__BIG_ENDIAN_BITFIELD)
+ __u8 reserved3 : 6;
+ /* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
+ __u8 cd_rw_write : 1; /* reserved in 1.2 */
/* Drive supports write to CD-R discs (orange book, part II) */
- unsigned cd_r_write : 1; /* reserved in 1.2 */
- /* Drive supports write to CD-R/W (CD-E) discs (orange book, part III) */
- unsigned cd_rw_write : 1; /* reserved in 1.2 */
- unsigned reserved3 : 6;
+ __u8 cd_r_write : 1; /* reserved in 1.2 */
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+
+ /* Drive can write to CD-R discs (orange book, part II) */
+ __u8 cd_r_write : 1; /* reserved in 1.2 */
+ /* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
+ __u8 cd_rw_write : 1; /* reserved in 1.2 */
+ __u8 reserved3 : 6;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+#if defined(__BIG_ENDIAN_BITFIELD)
+ __u8 reserved4 : 1;
+ /* Drive can read multisession discs. */
+ __u8 multisession : 1;
+ /* Drive can read mode 2, form 2 data. */
+ __u8 mode2_form2 : 1;
+ /* Drive can read mode 2, form 1 (XA) data. */
+ __u8 mode2_form1 : 1;
+ /* Drive supports digital output on port 2. */
+ __u8 digport2 : 1;
+ /* Drive supports digital output on port 1. */
+ __u8 digport1 : 1;
+ /* Drive can deliver a composite audio/video data stream. */
+ __u8 composite : 1;
/* Drive supports audio play operations. */
- unsigned audio_play : 1;
+ __u8 audio_play : 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+ /* Drive supports audio play operations. */
+ __u8 audio_play : 1;
/* Drive can deliver a composite audio/video data stream. */
- unsigned composite : 1;
+ __u8 composite : 1;
/* Drive supports digital output on port 1. */
- unsigned digport1 : 1;
+ __u8 digport1 : 1;
/* Drive supports digital output on port 2. */
- unsigned digport2 : 1;
+ __u8 digport2 : 1;
/* Drive can read mode 2, form 1 (XA) data. */
- unsigned mode2_form1 : 1;
+ __u8 mode2_form1 : 1;
/* Drive can read mode 2, form 2 data. */
- unsigned mode2_form2 : 1;
+ __u8 mode2_form2 : 1;
/* Drive can read multisession discs. */
- unsigned multisession : 1;
- unsigned reserved4 : 1;
+ __u8 multisession : 1;
+ __u8 reserved4 : 1;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+#if defined(__BIG_ENDIAN_BITFIELD)
+ __u8 reserved5 : 1;
+ /* Drive can return Media Catalog Number (UPC) info. */
+ __u8 upc : 1;
+ /* Drive can return International Standard Recording Code info. */
+ __u8 isrc : 1;
+ /* Drive supports C2 error pointers. */
+ __u8 c2_pointers : 1;
+ /* R-W data will be returned deinterleaved and error corrected. */
+ __u8 rw_corr : 1;
+ /* Subchannel reads can return combined R-W information. */
+ __u8 rw_supported : 1;
+ /* Drive can continue a read cdda operation from a loss of streaming.*/
+ __u8 cdda_accurate : 1;
+ /* Drive can read Red Book audio data. */
+ __u8 cdda : 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
/* Drive can read Red Book audio data. */
- unsigned cdda : 1;
+ __u8 cdda : 1;
/* Drive can continue a read cdda operation from a loss of streaming.*/
- unsigned cdda_accurate : 1;
+ __u8 cdda_accurate : 1;
/* Subchannel reads can return combined R-W information. */
- unsigned rw_supported : 1;
+ __u8 rw_supported : 1;
/* R-W data will be returned deinterleaved and error corrected. */
- unsigned rw_corr : 1;
+ __u8 rw_corr : 1;
/* Drive supports C2 error pointers. */
- unsigned c2_pointers : 1;
+ __u8 c2_pointers : 1;
/* Drive can return International Standard Recording Code info. */
- unsigned isrc : 1;
+ __u8 isrc : 1;
/* Drive can return Media Catalog Number (UPC) info. */
- unsigned upc : 1;
- unsigned reserved5 : 1;
+ __u8 upc : 1;
+ __u8 reserved5 : 1;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+ /* Drive mechanism types. */
+ mechtype_t mechtype : 3;
+ __u8 reserved6 : 1;
+ /* Drive can eject a disc or changer cartridge. */
+ __u8 eject : 1;
+ /* State of prevent/allow jumper. */
+ __u8 prevent_jumper : 1;
+ /* Present state of door lock. */
+ __u8 lock_state : 1;
+ /* Drive can lock the door. */
+ __u8 lock : 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
/* Drive can lock the door. */
- unsigned lock : 1;
+ __u8 lock : 1;
/* Present state of door lock. */
- unsigned lock_state : 1;
+ __u8 lock_state : 1;
/* State of prevent/allow jumper. */
- unsigned prevent_jumper : 1;
+ __u8 prevent_jumper : 1;
/* Drive can eject a disc or changer cartridge. */
- unsigned eject : 1;
- unsigned reserved6 : 1;
+ __u8 eject : 1;
+ __u8 reserved6 : 1;
/* Drive mechanism types. */
mechtype_t mechtype : 3;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+ __u8 reserved7 : 4;
+ /* Drive supports software slot selection. */
+ __u8 sss : 1; /* reserved in 1.2 */
+ /* Changer can report exact contents of slots. */
+ __u8 disc_present : 1; /* reserved in 1.2 */
+ /* Audio for each channel can be muted independently. */
+ __u8 separate_mute : 1;
+ /* Audio level for each channel can be controlled independently. */
+ __u8 separate_volume : 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
/* Audio level for each channel can be controlled independently. */
- unsigned separate_volume : 1;
+ __u8 separate_volume : 1;
/* Audio for each channel can be muted independently. */
- unsigned separate_mute : 1;
+ __u8 separate_mute : 1;
/* Changer can report exact contents of slots. */
- unsigned disc_present : 1; /* reserved in 1.2 */
+ __u8 disc_present : 1; /* reserved in 1.2 */
/* Drive supports software slot selection. */
- unsigned sss : 1; /* reserved in 1.2 */
- unsigned reserved7 : 4;
+ __u8 sss : 1; /* reserved in 1.2 */
+ __u8 reserved7 : 4;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
/* Note: the following four fields are returned in big-endian form. */
/* Maximum speed (in kB/s). */
@@ -333,23 +469,46 @@ struct atapi_capabilities_page {
struct atapi_mechstat_header {
- unsigned curslot : 5;
- unsigned changer_state : 2;
- unsigned fault : 1;
+#if defined(__BIG_ENDIAN_BITFIELD)
+ __u8 fault : 1;
+ __u8 changer_state : 2;
+ __u8 curslot : 5;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 curslot : 5;
+ __u8 changer_state : 2;
+ __u8 fault : 1;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
- unsigned reserved1 : 5;
- unsigned mech_state : 3;
+#if defined(__BIG_ENDIAN_BITFIELD)
+ __u8 mech_state : 3;
+ __u8 reserved1 : 5;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 reserved1 : 5;
+ __u8 mech_state : 3;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
byte curlba[3];
byte nslots;
- unsigned short slot_tablelen;
+ __u8 short slot_tablelen;
};
struct atapi_slot {
- unsigned change : 1;
- unsigned reserved1 : 6;
- unsigned disc_present : 1;
+#if defined(__BIG_ENDIAN_BITFIELD)
+ __u8 disc_present : 1;
+ __u8 reserved1 : 6;
+ __u8 change : 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 change : 1;
+ __u8 reserved1 : 6;
+ __u8 disc_present : 1;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
byte reserved2[3];
};
diff --git a/drivers/block/ide-disk.c b/drivers/block/ide-disk.c
index c4672208e..2062f5cdf 100644
--- a/drivers/block/ide-disk.c
+++ b/drivers/block/ide-disk.c
@@ -19,6 +19,7 @@
* Version 1.05 add capacity support for ATA3 >= 8GB
* Version 1.06 get boot-up messages to show full cyl count
* Version 1.07 disable door-locking if it fails
+ * Version 1.07a fixed mult_count enables
*/
#define IDEDISK_VERSION "1.07"
@@ -724,20 +725,24 @@ static void idedisk_setup (ide_drive_t *drive)
drive->name, id->model, idedisk_capacity(drive)/2048L, id->buf_size/2,
drive->bios_cyl, drive->bios_head, drive->bios_sect);
if (drive->using_dma) {
- if ((id->field_valid & 4) && (id->dma_ultra & (id->dma_ultra >> 8) & 7))
- printk(", UDMA");
- else
+ if ((id->field_valid & 4) &&
+ (id->dma_ultra & (id->dma_ultra >> 8) & 7)) {
+ printk(", UDMA"); /* UDMA BIOS-enabled! */
+ } else if (id->field_valid & 4) {
+ printk(", (U)DMA"); /* Can be BIOS-enabled! */
+ } else {
printk(", DMA");
+ }
}
printk("\n");
drive->mult_count = 0;
if (id->max_multsect) {
- drive->mult_req = INITIAL_MULT_COUNT;
- if (drive->mult_req > id->max_multsect)
- drive->mult_req = id->max_multsect;
- if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
- drive->special.b.set_multmode = 1;
+ id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
+ id->multsect_valid = id->multsect ? 1 : 0;
+ drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;
+ drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
}
+ drive->no_io_32bit = id->dword_io ? 1 : 0;
}
int idedisk_init (void)
diff --git a/drivers/block/ide-dma.c b/drivers/block/ide-dma.c
index 93cc2cc1c..058d93b85 100644
--- a/drivers/block/ide-dma.c
+++ b/drivers/block/ide-dma.c
@@ -62,6 +62,13 @@
* for supplying a Promise UDMA board & WD UDMA drive for this work!
*
* And, yes, Intel Zappa boards really *do* use both PIIX IDE ports.
+ *
+ * ACARD ATP850UF Chipset "Modified SCSI Class" with other names
+ * AEC6210 U/UF
+ * SIIG's UltraIDE Pro CN-2449
+ * TTI HPT343 Chipset "Modified SCSI Class" but reports as an
+ * unknown storage device.
+ * NEW check_drive_lists(ide_drive_t *drive, int good_bad)
*/
#include <linux/config.h>
#include <linux/types.h>
@@ -85,9 +92,19 @@
const char *good_dma_drives[] = {"Micropolis 2112A",
"CONNER CTMA 4000",
"ST34342A", /* for Sun Ultra */
+ "WDC AC2340F", /* DMA mode1 */
+ "WDC AC2340H", /* DMA mode1 */
NULL};
/*
+ * bad_dma_drives() lists the model names (from "hdparm -i")
+ * of drives which supposedly support (U)DMA but which are
+ * known to corrupt data with this interface under Linux.
+ */
+const char *bad_dma_drives[] = {"WDC AC22100H",
+ NULL};
+
+/*
* Our Physical Region Descriptor (PRD) table should be large enough
* to handle the biggest I/O request we are likely to see. Since requests
* can have no more than 256 sectors, and since the typical blocksize is
@@ -204,27 +221,57 @@ int ide_build_dmatable (ide_drive_t *drive)
return count;
}
-static int config_drive_for_dma (ide_drive_t *drive)
+/*
+ * For both Blacklisted and Whitelisted drives.
+ * This is setup to be called as an extern for future support
+ * to other special driver code.
+ */
+int check_drive_lists (ide_drive_t *drive, int good_bad)
{
const char **list;
struct hd_driveid *id = drive->id;
+
+ if (good_bad) {
+ /* Consult the list of known "good" drives */
+ list = good_dma_drives;
+ while (*list) {
+ if (!strcmp(*list++,id->model))
+ return 1;
+ }
+ } else {
+ /* Consult the list of known "bad" drives */
+ list = bad_dma_drives;
+ while (*list) {
+ if (!strcmp(*list++,id->model)) {
+ printk("%s: (U)DMA capability is broken for %s\n",
+ drive->name, id->model);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+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->autodma) {
+ /* Consult the list of known "bad" drives */
+ if (check_drive_lists(drive, BAD_DMA_DRIVE))
+ return hwif->dmaproc(ide_dma_off, drive);
/* 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))
return hwif->dmaproc(ide_dma_on, drive);
/* Enable DMA on any drive that has mode2 DMA (multi or single) enabled */
if (id->field_valid & 2) /* regular DMA */
- if ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404)
+ if ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404)
return hwif->dmaproc(ide_dma_on, drive);
/* Consult the list of known "good" drives */
- list = good_dma_drives;
- while (*list) {
- if (!strcmp(*list++,id->model))
- return hwif->dmaproc(ide_dma_on, drive);
- }
+ if (check_drive_lists(drive, GOOD_DMA_DRIVE))
+ return hwif->dmaproc(ide_dma_on, drive);
}
return hwif->dmaproc(ide_dma_off_quietly, drive);
}
@@ -297,6 +344,21 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
}
}
+/*
+ * Needed for allowing full modular support of ide-driver
+ */
+int ide_release_dma (ide_hwif_t *hwif)
+{
+ if (hwif->dmatable) {
+ clear_page((unsigned long)hwif->dmatable); /* clear PRD 1st */
+ free_page((unsigned long)hwif->dmatable); /* free PRD 2nd */
+ }
+ if ((hwif->dma_extra) && (hwif->channel == 0))
+ release_region((hwif->dma_base + 16), hwif->dma_extra);
+ release_region(hwif->dma_base, 8);
+ return 1;
+}
+
__initfunc(void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports))
{
static unsigned long dmatable = 0;
@@ -354,9 +416,10 @@ __initfunc(unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, c
}
}
if (dma_base) {
- if (extra) /* PDC20246 */
+ if (extra) /* PDC20246 & HPT343 */
request_region(dma_base+16, extra, name);
dma_base += hwif->channel ? 8 : 0;
+ hwif->dma_extra = extra;
if (inb(dma_base+2) & 0x80) {
printk("%s: simplex device: DMA disabled\n", name);
dma_base = 0;
diff --git a/drivers/block/ide-floppy.c b/drivers/block/ide-floppy.c
index 3c6d0c006..e5d48249d 100644
--- a/drivers/block/ide-floppy.c
+++ b/drivers/block/ide-floppy.c
@@ -121,10 +121,19 @@ typedef struct idefloppy_packet_command_s {
* Removable Block Access Capabilities Page
*/
typedef struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned page_code :6; /* Page code - Should be 0x1b */
unsigned reserved1_6 :1; /* Reserved */
unsigned ps :1; /* Should be 0 */
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ unsigned ps :1; /* Should be 0 */
+ unsigned reserved1_6 :1; /* Reserved */
+ unsigned page_code :6; /* Page code - Should be 0x1b */
+#else
+#error "Bitfield endianness not defined! Check your byteorder.h"
+#endif
u8 page_length; /* Page Length - Should be 0xa */
+#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned reserved2 :6;
unsigned srfp :1; /* Supports reporting progress of format */
unsigned sflp :1; /* System floppy type device */
@@ -132,6 +141,17 @@ typedef struct {
unsigned reserved3 :3;
unsigned sml :1; /* Single / Multiple lun supported */
unsigned ncd :1; /* Non cd optical device */
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ unsigned sflp :1; /* System floppy type device */
+ unsigned srfp :1; /* Supports reporting progress of format */
+ unsigned reserved2 :6;
+ unsigned ncd :1; /* Non cd optical device */
+ unsigned sml :1; /* Single / Multiple lun supported */
+ unsigned reserved3 :3;
+ unsigned tlun :3; /* Total logical units supported by the device */
+#else
+#error "Bitfield endianness not defined! Check your byteorder.h"
+#endif
u8 reserved[8];
} idefloppy_capabilities_page_t;
@@ -139,9 +159,17 @@ typedef struct {
* Flexible disk page.
*/
typedef struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned page_code :6; /* Page code - Should be 0x5 */
unsigned reserved1_6 :1; /* Reserved */
unsigned ps :1; /* The device is capable of saving the page */
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ unsigned ps :1; /* The device is capable of saving the page */
+ unsigned reserved1_6 :1; /* Reserved */
+ unsigned page_code :6; /* Page code - Should be 0x5 */
+#else
+#error "Bitfield endianness not defined! Check your byteorder.h"
+#endif
u8 page_length; /* Page Length - Should be 0x1e */
u16 transfer_rate; /* In kilobits per second */
u8 heads, sectors; /* Number of heads, Number of sectors per track */
@@ -164,8 +192,15 @@ typedef struct {
typedef struct {
u32 blocks; /* Number of blocks */
+#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned dc :2; /* Descriptor Code */
unsigned reserved :6;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ unsigned reserved :6;
+ unsigned dc :2; /* Descriptor Code */
+#else
+#error "Bitfield endianness not defined! Check your byteorder.h"
+#endif
u8 length_msb; /* Block Length (MSB)*/
u16 length; /* Block Length */
} idefloppy_capacity_descriptor_t;
@@ -271,6 +306,7 @@ typedef struct {
typedef union {
unsigned all :8;
struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned check :1; /* Error occurred */
unsigned idx :1; /* Reserved */
unsigned corr :1; /* Correctable error occurred */
@@ -279,6 +315,18 @@ typedef union {
unsigned reserved5 :1; /* Reserved */
unsigned drdy :1; /* Ignored for ATAPI commands (ready to accept ATA command) */
unsigned bsy :1; /* The device has access to the command block */
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ unsigned bsy :1; /* The device has access to the command block */
+ unsigned drdy :1; /* Ignored for ATAPI commands (ready to accept ATA command) */
+ unsigned reserved5 :1; /* Reserved */
+ unsigned dsc :1; /* Media access command finished */
+ unsigned drq :1; /* Data is request by the device */
+ unsigned corr :1; /* Correctable error occurred */
+ unsigned idx :1; /* Reserved */
+ unsigned check :1; /* Error occurred */
+#else
+#error "Bitfield endianness not defined! Check your byteorder.h"
+#endif
} b;
} idefloppy_status_reg_t;
@@ -288,11 +336,21 @@ typedef union {
typedef union {
unsigned all :8;
struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned ili :1; /* Illegal Length Indication */
unsigned eom :1; /* End Of Media Detected */
unsigned abrt :1; /* Aborted command - As defined by ATA */
unsigned mcr :1; /* Media Change Requested - As defined by ATA */
unsigned sense_key :4; /* Sense key of the last failed packet command */
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ unsigned sense_key :4; /* Sense key of the last failed packet command */
+ unsigned mcr :1; /* Media Change Requested - As defined by ATA */
+ unsigned abrt :1; /* Aborted command - As defined by ATA */
+ unsigned eom :1; /* End Of Media Detected */
+ unsigned ili :1; /* Illegal Length Indication */
+#else
+#error "Bitfield endianness not defined! Check your byteorder.h"
+#endif
} b;
} idefloppy_error_reg_t;
@@ -302,10 +360,19 @@ typedef union {
typedef union {
unsigned all :8;
struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned dma :1; /* Using DMA or PIO */
unsigned reserved321 :3; /* Reserved */
unsigned reserved654 :3; /* Reserved (Tag Type) */
unsigned reserved7 :1; /* Reserved */
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ unsigned reserved7 :1; /* Reserved */
+ unsigned reserved654 :3; /* Reserved (Tag Type) */
+ unsigned reserved321 :3; /* Reserved */
+ unsigned dma :1; /* Using DMA or PIO */
+#else
+#error "Bitfield endianness not defined! Check your byteorder.h"
+#endif
} b;
} idefloppy_feature_reg_t;
@@ -315,8 +382,15 @@ typedef union {
typedef union {
unsigned all :16;
struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned low :8; /* LSB */
unsigned high :8; /* MSB */
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ unsigned high :8; /* MSB */
+ unsigned low :8; /* LSB */
+#else
+#error "Bitfield endianness not defined! Check your byteorder.h"
+#endif
} b;
} idefloppy_bcount_reg_t;
@@ -326,9 +400,17 @@ typedef union {
typedef union {
unsigned all :8;
struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned cod :1; /* Information transferred is command (1) or data (0) */
unsigned io :1; /* The device requests us to read (1) or write (0) */
unsigned reserved :6; /* Reserved */
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ unsigned reserved :6; /* Reserved */
+ unsigned io :1; /* The device requests us to read (1) or write (0) */
+ unsigned cod :1; /* Information transferred is command (1) or data (0) */
+#else
+#error "Bitfield endianness not defined! Check your byteorder.h"
+#endif
} b;
} idefloppy_ireason_reg_t;
@@ -338,12 +420,23 @@ typedef union {
typedef union {
unsigned all :8;
struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned sam_lun :3; /* Logical unit number */
unsigned reserved3 :1; /* Reserved */
unsigned drv :1; /* The responding drive will be drive 0 (0) or drive 1 (1) */
unsigned one5 :1; /* Should be set to 1 */
unsigned reserved6 :1; /* Reserved */
unsigned one7 :1; /* Should be set to 1 */
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ unsigned one7 :1; /* Should be set to 1 */
+ unsigned reserved6 :1; /* Reserved */
+ unsigned one5 :1; /* Should be set to 1 */
+ unsigned drv :1; /* The responding drive will be drive 0 (0) or drive 1 (1) */
+ unsigned reserved3 :1; /* Reserved */
+ unsigned sam_lun :3; /* Logical unit number */
+#else
+#error "Bitfield endianness not defined! Check your byteorder.h"
+#endif
} b;
} idefloppy_drivesel_reg_t;
@@ -353,11 +446,21 @@ typedef union {
typedef union {
unsigned all :8;
struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned zero0 :1; /* Should be set to zero */
unsigned nien :1; /* Device interrupt is disabled (1) or enabled (0) */
unsigned srst :1; /* ATA software reset. ATAPI devices should use the new ATAPI srst. */
unsigned one3 :1; /* Should be set to 1 */
unsigned reserved4567 :4; /* Reserved */
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ unsigned reserved4567 :4; /* Reserved */
+ unsigned one3 :1; /* Should be set to 1 */
+ unsigned srst :1; /* ATA software reset. ATAPI devices should use the new ATAPI srst. */
+ unsigned nien :1; /* Device interrupt is disabled (1) or enabled (0) */
+ unsigned zero0 :1; /* Should be set to zero */
+#else
+#error "Bitfield endianness not defined! Check your byteorder.h"
+#endif
} b;
} idefloppy_control_reg_t;
@@ -366,6 +469,7 @@ typedef union {
* the ATAPI IDENTIFY DEVICE command.
*/
struct idefloppy_id_gcw {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned packet_size :2; /* Packet Size */
unsigned reserved234 :3; /* Reserved */
unsigned drq_type :2; /* Command packet DRQ type */
@@ -373,12 +477,24 @@ struct idefloppy_id_gcw {
unsigned device_type :5; /* Device type */
unsigned reserved13 :1; /* Reserved */
unsigned protocol :2; /* Protocol type */
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ unsigned protocol :2; /* Protocol type */
+ unsigned reserved13 :1; /* Reserved */
+ unsigned device_type :5; /* Device type */
+ unsigned removable :1; /* Removable media */
+ unsigned drq_type :2; /* Command packet DRQ type */
+ unsigned reserved234 :3; /* Reserved */
+ unsigned packet_size :2; /* Packet Size */
+#else
+#error "Bitfield endianness not defined! Check your byteorder.h"
+#endif
};
/*
* INQUIRY packet command - Data Format
*/
typedef struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned device_type :5; /* Peripheral Device Type */
unsigned reserved0_765 :3; /* Peripheral Qualifier - Reserved */
unsigned reserved1_6t0 :7; /* Reserved */
@@ -390,6 +506,21 @@ typedef struct {
unsigned reserved3_45 :2; /* Reserved */
unsigned reserved3_6 :1; /* TrmIOP - Reserved */
unsigned reserved3_7 :1; /* AENC - Reserved */
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ unsigned reserved0_765 :3; /* Peripheral Qualifier - Reserved */
+ unsigned device_type :5; /* Peripheral Device Type */
+ unsigned rmb :1; /* Removable Medium Bit */
+ unsigned reserved1_6t0 :7; /* Reserved */
+ unsigned iso_version :2; /* ISO Version */
+ unsigned ecma_version :3; /* ECMA Version */
+ unsigned ansi_version :3; /* ANSI Version */
+ unsigned reserved3_7 :1; /* AENC - Reserved */
+ unsigned reserved3_6 :1; /* TrmIOP - Reserved */
+ unsigned reserved3_45 :2; /* Reserved */
+ unsigned response_format :4; /* Response Data Format */
+#else
+#error "Bitfield endianness not defined! Check your byteorder.h"
+#endif
u8 additional_length; /* Additional Length (total_length-4) */
u8 rsv5, rsv6, rsv7; /* Reserved */
u8 vendor_id[8]; /* Vendor Identification */
@@ -404,6 +535,7 @@ typedef struct {
* REQUEST SENSE packet command result - Data Format.
*/
typedef struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned error_code :7; /* Current error (0x70) */
unsigned valid :1; /* The information field conforms to SFF-8070i */
u8 reserved1 :8; /* Reserved */
@@ -411,6 +543,17 @@ typedef struct {
unsigned reserved2_4 :1; /* Reserved */
unsigned ili :1; /* Incorrect Length Indicator */
unsigned reserved2_67 :2;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ unsigned valid :1; /* The information field conforms to SFF-8070i */
+ unsigned error_code :7; /* Current error (0x70) */
+ u8 reserved1 :8; /* Reserved */
+ unsigned reserved2_67 :2;
+ unsigned ili :1; /* Incorrect Length Indicator */
+ unsigned reserved2_4 :1; /* Reserved */
+ unsigned sense_key :4; /* Sense Key */
+#else
+#error "Bitfield endianness not defined! Check your byteorder.h"
+#endif
u32 information __attribute__ ((packed));
u8 asl; /* Additional sense length (n-7) */
u32 command_specific; /* Additional command specific information */
@@ -433,8 +576,15 @@ typedef struct {
typedef struct {
u16 mode_data_length; /* Length of the following data transfer */
u8 medium_type; /* Medium Type */
+#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned reserved3 :7;
unsigned wp :1; /* Write protect */
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ unsigned wp :1; /* Write protect */
+ unsigned reserved3 :7;
+#else
+#error "Bitfield endianness not defined! Check your byteorder.h"
+#endif
u8 reserved[4];
} idefloppy_mode_parameter_header_t;
@@ -718,7 +868,7 @@ static void idefloppy_pc_intr (ide_drive_t *drive)
if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */
#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "ide-floppy: %s: I/O error, ",drive->name);
+ printk (KERN_INFO "ide-floppy: %s: I/O error\n",drive->name);
#endif /* IDEFLOPPY_DEBUG_LOG */
rq->errors++;
if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {
@@ -907,6 +1057,7 @@ static void idefloppy_create_read_capacity_cmd (idefloppy_pc_t *pc)
pc->c[0] = IDEFLOPPY_READ_CAPACITY_CMD;
pc->c[7] = 255;
pc->c[8] = 255;
+ pc->request_transfer = 255;
}
/*
@@ -1371,7 +1522,8 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
if (gcw.drq_type == 1)
set_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags);
if (strcmp(drive->id->model, "IOMEGA ZIP 100 ATAPI") == 0 &&
- strcmp(drive->id->fw_rev, "21.D") == 0) {
+ ((strcmp(drive->id->fw_rev, "21.D") == 0) ||
+ (strcmp(drive->id->fw_rev, "23.D") == 0))) {
for (i = 0; i < 1 << PARTN_BITS; i++)
max_sectors[major][minor + i] = 64;
}
diff --git a/drivers/block/ide-pci.c b/drivers/block/ide-pci.c
index 1122757cb..88b0dc631 100644
--- a/drivers/block/ide-pci.c
+++ b/drivers/block/ide-pci.c
@@ -42,8 +42,10 @@
#define DEVID_NS87410 ((ide_pci_devid_t){PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410})
#define DEVID_NS87415 ((ide_pci_devid_t){PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415})
#define DEVID_HT6565 ((ide_pci_devid_t){PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565})
-#define DEVID_AEC6210 ((ide_pci_devid_t){0x1191, 0x0005})
+#define DEVID_AEC6210 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF})
#define DEVID_W82C105 ((ide_pci_devid_t){PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105})
+#define DEVID_UM8886BF ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF})
+#define DEVID_HPT343 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343})
#define IDE_IGNORE ((void *)-1)
@@ -93,6 +95,13 @@ extern void ide_init_rz1000(ide_hwif_t *);
#define INIT_RZ1000 IDE_IGNORE
#endif
+#ifdef CONFIG_BLK_DEV_VIA82C586
+extern void ide_init_via82c586(ide_hwif_t *);
+#define INIT_VIA82C586 &ide_init_via82c586
+#else
+#define INIT_VIA82C586 NULL
+#endif
+
typedef struct ide_pci_enablebit_s {
byte reg; /* byte pci reg holding the enable-bit */
byte mask; /* mask to isolate the enable-bit */
@@ -104,35 +113,82 @@ typedef struct ide_pci_device_s {
const char *name;
void (*init_hwif)(ide_hwif_t *hwif);
ide_pci_enablebit_t enablebits[2];
+ byte bootable;
+ unsigned int extra;
} ide_pci_device_t;
static ide_pci_device_t ide_pci_chipsets[] __initdata = {
- {DEVID_PIIXa, "PIIX", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}} },
- {DEVID_PIIXb, "PIIX", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}} },
- {DEVID_PIIX3, "PIIX3", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}} },
- {DEVID_PIIX4, "PIIX4", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}} },
- {DEVID_VP_IDE, "VP_IDE", NULL, {{0x40,0x02,0x02}, {0x40,0x01,0x01}} },
- {DEVID_PDC20246,"PDC20246", NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}} },
- {DEVID_RZ1000, "RZ1000", INIT_RZ1000, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
- {DEVID_RZ1001, "RZ1001", INIT_RZ1000, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
- {DEVID_CMD640, "CMD640", IDE_IGNORE, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
- {DEVID_NS87410, "NS87410", NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}} },
- {DEVID_SIS5513, "SIS5513", NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}} },
- {DEVID_CMD646, "CMD646", INIT_CMD646, {{0x00,0x00,0x00}, {0x51,0x80,0x80}} },
- {DEVID_HT6565, "HT6565", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
- {DEVID_OPTI621, "OPTI621", INIT_OPTI621, {{0x45,0x80,0x00}, {0x40,0x08,0x00}} },
- {DEVID_OPTI621X,"OPTI621X", INIT_OPTI621, {{0x45,0x80,0x00}, {0x40,0x08,0x00}} },
- {DEVID_TRM290, "TRM290", INIT_TRM290, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
- {DEVID_NS87415, "NS87415", INIT_NS87415, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
- {DEVID_AEC6210, "AEC6210", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
- {DEVID_W82C105, "W82C105", INIT_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}} },
- {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} }};
+ {DEVID_PIIXa, "PIIX", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
+ {DEVID_PIIXb, "PIIX", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
+ {DEVID_PIIX3, "PIIX3", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
+ {DEVID_PIIX4, "PIIX4", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
+ {DEVID_VP_IDE, "VP_IDE", INIT_VIA82C586, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 },
+ {DEVID_PDC20246,"PDC20246", NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 },
+ {DEVID_RZ1000, "RZ1000", INIT_RZ1000, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
+ {DEVID_RZ1001, "RZ1001", INIT_RZ1000, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
+ {DEVID_CMD640, "CMD640", IDE_IGNORE, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
+ {DEVID_NS87410, "NS87410", NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0 },
+ {DEVID_SIS5513, "SIS5513", NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 0 },
+ {DEVID_CMD646, "CMD646", INIT_CMD646, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0 },
+ {DEVID_HT6565, "HT6565", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
+ {DEVID_OPTI621, "OPTI621", INIT_OPTI621, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 },
+ {DEVID_OPTI621X,"OPTI621X", INIT_OPTI621, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 },
+ {DEVID_TRM290, "TRM290", INIT_TRM290, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
+ {DEVID_NS87415, "NS87415", INIT_NS87415, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
+ {DEVID_AEC6210, "AEC6210", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 },
+ {DEVID_W82C105, "W82C105", INIT_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 },
+ {DEVID_UM8886BF,"UM8886BF", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
+ {DEVID_HPT343, "HPT343", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 },
+ {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }};
+
+/*
+ * This allows offboard ide-pci cards the enable a BIOS, verify interrupt
+ * settings of split-mirror pci-config space, place chipset into init-mode,
+ * and/or preserve an interrupt if the card is not native ide support.
+ */
+__initfunc(static unsigned int ide_special_settings (struct pci_dev *dev, const char *name))
+{
+ unsigned int addressbios = 0;
+
+ pci_read_config_dword(dev, PCI_ROM_ADDRESS, &addressbios);
+
+ switch(dev->device) {
+ case PCI_DEVICE_ID_ARTOP_ATP850UF:
+ case PCI_DEVICE_ID_PROMISE_20246:
+ pci_write_config_byte(dev, PCI_ROM_ADDRESS, PCI_ROM_ADDRESS_ENABLE);
+ printk("%s: ROM enabled ", name);
+
+ if (!addressbios) {
+ printk("but no address\n");
+ } else {
+ printk("at 0x%08x\n", addressbios);
+ }
+
+ if ((dev->class >> 8) == PCI_CLASS_STORAGE_RAID) {
+ unsigned char irq1 = 0, irq2 = 0;
+
+ pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq1);
+ pci_read_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, &irq2); /* 0xbc */
+ if (irq1 != irq2) {
+ printk("%s: IRQ1 %d IRQ2 %d\n",
+ name, irq1, irq2);
+ pci_write_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, irq1); /* 0xbc */
+ }
+ }
+ return dev->irq;
+ case PCI_DEVICE_ID_TTI_HPT343:
+ return dev->irq;
+ default:
+ break;
+ }
+ return 0;
+}
/*
* Match a PCI IDE port against an entry in ide_hwifs[],
* based on io_base port if possible.
*/
-__initfunc(static ide_hwif_t *ide_match_hwif (unsigned long io_base, const char *name))
+__initfunc(static ide_hwif_t *ide_match_hwif (unsigned long io_base, byte bootable, const char *name))
{
int h;
ide_hwif_t *hwif;
@@ -168,11 +224,22 @@ __initfunc(static ide_hwif_t *ide_match_hwif (unsigned long io_base, const char
* Give preference to claiming other slots before claiming ide0/ide1,
* just in case there's another interface yet-to-be-scanned
* which uses ports 1f0/170 (the ide0/ide1 defaults).
+ *
+ * Unless there is a bootable card that does not use the standard
+ * ports 1f0/170 (the ide0/ide1 defaults). The (bootable) flag.
*/
- for (h = 2; h < MAX_HWIFS; ++h) {
- hwif = ide_hwifs + h;
- if (hwif->chipset == ide_unknown)
- return hwif; /* pick an unused entry */
+ if (bootable) {
+ for (h = 0; h < MAX_HWIFS; ++h) {
+ hwif = &ide_hwifs[h];
+ if (hwif->chipset == ide_unknown)
+ return hwif; /* pick an unused entry */
+ }
+ } else {
+ for (h = 2; h < MAX_HWIFS; ++h) {
+ hwif = ide_hwifs + h;
+ if (hwif->chipset == ide_unknown)
+ return hwif; /* pick an unused entry */
+ }
}
for (h = 0; h < 2; ++h) {
hwif = ide_hwifs + h;
@@ -263,7 +330,7 @@ check_if_enabled:
pciirq = dev->irq;
if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) {
printk("%s: not 100%% native mode: will probe irqs later\n", d->name);
- pciirq = 0;
+ pciirq = ide_special_settings(dev, d->name);
} else if (tried_config) {
printk("%s: will probe irqs later\n", d->name);
pciirq = 0;
@@ -298,7 +365,7 @@ check_if_enabled:
ctl = port ? 0x374 : 0x3f4; /* use default value */
if (!base)
base = port ? 0x170 : 0x1f0; /* use default value */
- if ((hwif = ide_match_hwif(base, d->name)) == NULL)
+ if ((hwif = ide_match_hwif(base, d->bootable, d->name)) == NULL)
continue; /* no room in ide_hwifs[] */
if (hwif->io_ports[IDE_DATA_OFFSET] != base) {
ide_init_hwif_ports(hwif->io_ports, base, NULL);
@@ -314,6 +381,10 @@ check_if_enabled:
if (mate) {
hwif->mate = mate;
mate->mate = hwif;
+ if (IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210)) {
+ hwif->serialized = 1;
+ mate->serialized = 1;
+ }
}
#ifdef CONFIG_BLK_DEV_IDEDMA
if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513))
@@ -321,9 +392,10 @@ check_if_enabled:
if (autodma)
hwif->autodma = 1;
if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) ||
+ IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) ||
+ IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT343) ||
((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) {
- unsigned int extra = (!mate && IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246)) ? 16 : 0;
- unsigned long dma_base = ide_get_or_set_dma_base(hwif, extra, d->name);
+ unsigned long dma_base = ide_get_or_set_dma_base(hwif, (!mate && d->extra) ? d->extra : 0, d->name);
if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) {
/*
* Set up BM-DMA capability (PnP BIOS should have done this)
diff --git a/drivers/block/ide-pmac.c b/drivers/block/ide-pmac.c
index cb8b13e06..f504cb9c2 100644
--- a/drivers/block/ide-pmac.c
+++ b/drivers/block/ide-pmac.c
@@ -25,10 +25,13 @@
#include <asm/dbdma.h>
#include <asm/ide.h>
#include <asm/mediabay.h>
+#include <asm/feature.h>
#include "ide.h"
ide_ioreg_t pmac_ide_regbase[MAX_HWIFS];
int pmac_ide_irq[MAX_HWIFS];
+int pmac_ide_count;
+struct device_node *pmac_ide_node[MAX_HWIFS];
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
#define MAX_DCMDS 256 /* allow up to 256 DBDMA commands per xfer */
@@ -45,15 +48,18 @@ static int pmac_ide_build_dmatable(ide_drive_t *drive, int wr);
void
pmac_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)
{
- int i;
+ int i, r;
*p = 0;
if (base == 0)
return;
- if (base == mb_cd_base && !check_media_bay(MB_CD)) {
- mb_cd_index = -1;
+ /* we check only for -EINVAL meaning that we have found a matching
+ bay but with the wrong device type */
+
+ r = check_media_bay_by_base(base, MB_CD);
+ if (r == -EINVAL)
return;
- }
+
for (i = 0; i < 8; ++i)
*p++ = base + i * 0x10;
*p = base + 0x160;
@@ -93,8 +99,8 @@ pmac_ide_probe(void))
/* Move removable devices such as the media-bay CDROM
on the PB3400 to the end of the list. */
for (; p != NULL; p = p->next) {
- if (p->parent && p->parent->name
- && strcasecmp(p->parent->name, "media-bay") == 0) {
+ if (p->parent && p->parent->type
+ && strcasecmp(p->parent->type, "media-bay") == 0) {
*rp = p;
rp = &p->next;
} else {
@@ -111,7 +117,13 @@ pmac_ide_probe(void))
np->full_name);
continue;
}
+
base = (unsigned long) ioremap(np->addrs[0].address, 0x200);
+
+ /* XXX This is bogus. Should be fixed in the registry by checking
+ the kind of host interrupt controller, a bit like gatwick
+ fixes in irq.c
+ */
if (np->n_intrs == 0) {
printk("ide: no intrs for device %s, using 13\n",
np->full_name);
@@ -121,13 +133,13 @@ pmac_ide_probe(void))
}
pmac_ide_regbase[i] = base;
pmac_ide_irq[i] = irq;
+ pmac_ide_node[i] = np;
if (np->parent && np->parent->name
&& strcasecmp(np->parent->name, "media-bay") == 0) {
- mb_cd_index = i;
- mb_cd_base = base;
- mb_cd_irq = irq;
- }
+ media_bay_set_ide_infos(np->parent,base,irq,i);
+ } else
+ feature_set(np, FEATURE_IDE_enable);
hwif = &ide_hwifs[i];
pmac_ide_init_hwif_ports(hwif->io_ports, base, &hwif->irq);
@@ -143,6 +155,7 @@ pmac_ide_probe(void))
++i;
}
+ pmac_ide_count = i;
}
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
diff --git a/drivers/block/ide-probe.c b/drivers/block/ide-probe.c
index 14b6bf323..bcaa40221 100644
--- a/drivers/block/ide-probe.c
+++ b/drivers/block/ide-probe.c
@@ -78,8 +78,18 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
ide_fixstring (id->serial_no, sizeof(id->serial_no), bswap);
id->model[sizeof(id->model)-1] = '\0'; /* we depend on this a lot! */
- drive->present = 1;
printk("%s: %s, ", drive->name, id->model);
+ drive->present = 1;
+
+ /*
+ * Prevent long system lockup probing later for non-existant
+ * slave drive if the hwif is actually a Kodak CompactFlash card.
+ */
+ if (!strcmp(id->model, "KODAK ATA_FLASH")) {
+ ide_drive_t *mate = &HWIF(drive)->drives[1^drive->select.b.unit];
+ mate->present = 0;
+ mate->noprobe = 1;
+ }
/*
* Check for an ATAPI device
@@ -273,6 +283,18 @@ static int do_probe (ide_drive_t *drive, byte cmd)
{
if ((rc = try_to_identify(drive,cmd))) /* send cmd and wait */
rc = try_to_identify(drive,cmd); /* failed: try again */
+ if (rc == 1 && cmd == WIN_PIDENTIFY && drive->autotune != 2) {
+ unsigned long timeout;
+ printk("%s: no response (status = 0x%02x), resetting drive\n", drive->name, GET_STAT());
+ delay_50ms();
+ OUT_BYTE (drive->select.all, IDE_SELECT_REG);
+ delay_50ms();
+ OUT_BYTE(WIN_SRST, IDE_COMMAND_REG);
+ timeout = jiffies;
+ while ((GET_STAT() & BUSY_STAT) && jiffies < timeout + WAIT_WORSTCASE)
+ delay_50ms();
+ rc = try_to_identify(drive, cmd);
+ }
if (rc == 1)
printk("%s: no response (status = 0x%02x)\n", drive->name, GET_STAT());
(void) GET_STAT(); /* ensure drive irq is clear */
diff --git a/drivers/block/ide-tape.c b/drivers/block/ide-tape.c
index 61e084366..f99fe7d41 100644
--- a/drivers/block/ide-tape.c
+++ b/drivers/block/ide-tape.c
@@ -45,7 +45,7 @@
* flag, can be configured by issuing an ioctl to the block device interface,
* as any other ide device.
*
- * Our own ide-tape ioctl's can can be issued to either the block device or
+ * Our own ide-tape ioctl's can be issued to either the block device or
* the character device interface.
*
* Maximal throughput with minimal bus load will usually be achieved in the
@@ -276,7 +276,7 @@
* loop which checks if the pipeline is empty, and if it is, we
* increase the maximum number of stages as necessary until we
* reach the optimum value which just manages to keep the tape
- * busy with with minimum allocated memory or until we reach
+ * busy with minimum allocated memory or until we reach
* IDETAPE_MAX_PIPELINE_STAGES.
*
* Concerning (2):
diff --git a/drivers/block/ide.c b/drivers/block/ide.c
index 9213f5274..23a554398 100644
--- a/drivers/block/ide.c
+++ b/drivers/block/ide.c
@@ -1104,6 +1104,10 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, unsigned long *hwgroup_flags
if (sleep) {
if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep))
sleep = jiffies + WAIT_MIN_SLEEP;
+#if 1
+ if (hwgroup->timer.next || hwgroup->timer.prev)
+ printk("ide_set_handler: timer already active\n");
+#endif
mod_timer(&hwgroup->timer, sleep);
} else {
/* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_scheduler? */
@@ -1253,7 +1257,7 @@ void ide_timer_expiry (unsigned long data)
}
hwgroup->busy = 1; /* should already be "1" */
hwgroup->handler = NULL;
- del_timer(&hwgroup->timer);
+ del_timer(&hwgroup->timer); /* Is this needed?? */
if (hwgroup->poll_timeout != 0) { /* polling in progress? */
spin_unlock_irqrestore(&hwgroup->spinlock, flags);
handler(drive);
@@ -1265,6 +1269,10 @@ void ide_timer_expiry (unsigned long data)
if (drive->waiting_for_dma) {
(void) hwgroup->hwif->dmaproc(ide_dma_end, drive);
printk("%s: timeout waiting for DMA\n", drive->name);
+ /*
+ * need something here for HX PIIX3 UDMA and HPT343.......AMH
+ * irq timeout: status=0x58 { DriveReady SeekComplete DataRequest }
+ */
}
spin_unlock_irqrestore(&hwgroup->spinlock, flags);
ide_error(drive, "irq timeout", GET_STAT());
@@ -1426,9 +1434,9 @@ void ide_init_drive_cmd (struct request *rq)
* This function issues a special IDE device request
* onto the request queue.
*
- * If action is ide_wait, then then rq is queued at the end of
- * the request queue, and the function sleeps until it has been
- * processed. This is for use when invoked from an ioctl handler.
+ * If action is ide_wait, then the rq is queued at the end of the
+ * request queue, and the function sleeps until it has been processed.
+ * This is for use when invoked from an ioctl handler.
*
* If action is ide_preempt, then the rq is queued at the head of
* the request queue, displacing the currently-being-processed
@@ -1729,6 +1737,11 @@ void ide_unregister (unsigned int index)
else
hwgroup->hwif = HWIF(hwgroup->drive);
+#ifdef CONFIG_BLK_DEV_IDEDMA
+ if (hwif->dma_base)
+ (void) ide_release_dma(hwif);
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
/*
* Remove us from the kernel's knowledge
*/
@@ -2990,8 +3003,13 @@ void cleanup_module (void)
{
int index;
- for (index = 0; index < MAX_HWIFS; ++index)
+ for (index = 0; index < MAX_HWIFS; ++index) {
ide_unregister(index);
+#ifdef CONFIG_BLK_DEV_IDEDMA
+ if (ide_hwifs[index].dma_base)
+ (void) ide_release_dma(&ide_hwifs[index]);
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+ }
#ifdef CONFIG_PROC_FS
proc_ide_destroy();
#endif
diff --git a/drivers/block/ide.h b/drivers/block/ide.h
index 1da4ff371..0919ca710 100644
--- a/drivers/block/ide.h
+++ b/drivers/block/ide.h
@@ -332,6 +332,7 @@ typedef struct hwif_s {
unsigned long *dmatable; /* dma physical region descriptor table */
struct hwif_s *mate; /* other hwif from same PCI chip */
unsigned long dma_base; /* base addr for dma ports */
+ unsigned dma_extra; /* extra addr for dma ports */
unsigned long config_data; /* for use by chipset-specific code */
unsigned long select_data; /* for use by chipset-specific code */
struct proc_dir_entry *proc; /* /proc/ide/ directory entry */
@@ -615,9 +616,9 @@ typedef enum
* This function issues a special IDE device request
* onto the request queue.
*
- * If action is ide_wait, then then rq is queued at the end of
- * the request queue, and the function sleeps until it has been
- * processed. This is for use when invoked from an ioctl handler.
+ * If action is ide_wait, then the rq is queued at the end of the
+ * request queue, and the function sleeps until it has been processed.
+ * This is for use when invoked from an ioctl handler.
*
* If action is ide_preempt, then the rq is queued at the head of
* the request queue, displacing the currently-being-processed
@@ -729,13 +730,25 @@ int ide_unregister_subdriver (ide_drive_t *drive);
int ide_replace_subdriver(ide_drive_t *drive, const char *driver);
#ifdef CONFIG_BLK_DEV_IDEPCI
+#define ON_BOARD 1
+#define NEVER_BOARD 0
+#ifdef CONFIG_BLK_DEV_OFFBOARD
+# define OFF_BOARD ON_BOARD
+#else /* CONFIG_BLK_DEV_OFFBOARD */
+# define OFF_BOARD NEVER_BOARD
+#endif /* CONFIG_BLK_DEV_OFFBOARD */
+
unsigned long ide_find_free_region (unsigned short size) __init;
void ide_scan_pcibus (void) __init;
#endif
#ifdef CONFIG_BLK_DEV_IDEDMA
+#define BAD_DMA_DRIVE 0
+#define GOOD_DMA_DRIVE 1
int ide_build_dmatable (ide_drive_t *drive);
void ide_dma_intr (ide_drive_t *drive);
+int check_drive_lists (ide_drive_t *drive, int good_bad);
int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive);
+int ide_release_dma (ide_hwif_t *hwif);
void ide_setup_dma (ide_hwif_t *hwif, unsigned long dmabase, unsigned int num_ports) __init;
unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) __init;
#endif
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 158b5e975..35403ce59 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -93,8 +93,8 @@ int * blksize_size[MAX_BLKDEV] = { NULL, NULL, };
* then 512 bytes is assumed.
* else
* sector_size is hardsect_size[MAJOR][MINOR]
- * This is currently set by some scsi device and read by the msdos fs driver
- * This might be a some uses later.
+ * This is currently set by some scsi devices and read by the msdos fs driver.
+ * Other uses may appear later.
*/
int * hardsect_size[MAX_BLKDEV] = { NULL, NULL, };
@@ -297,8 +297,8 @@ void add_request(struct blk_dev_struct * dev, struct request * req)
int queue_new_request = 0;
switch (MAJOR(req->rq_dev)) {
- case SCSI_DISK_MAJOR:
- disk_index = (MINOR(req->rq_dev) & 0x0070) >> 4;
+ case SCSI_DISK0_MAJOR:
+ disk_index = (MINOR(req->rq_dev) & 0x00f0) >> 4;
if (disk_index < 4)
drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
break;
@@ -331,10 +331,16 @@ void add_request(struct blk_dev_struct * dev, struct request * req)
goto out;
}
for ( ; tmp->next ; tmp = tmp->next) {
- if ((IN_ORDER(tmp,req) ||
- !IN_ORDER(tmp,tmp->next)) &&
- IN_ORDER(req,tmp->next))
- break;
+ const int after_current = IN_ORDER(tmp,req);
+ const int before_next = IN_ORDER(req,tmp->next);
+
+ if (!IN_ORDER(tmp,tmp->next)) {
+ if (after_current || before_next)
+ break;
+ } else {
+ if (after_current && before_next)
+ break;
+ }
}
req->next = tmp->next;
tmp->next = req;
@@ -479,7 +485,14 @@ void make_request(int major,int rw, struct buffer_head * bh)
break;
/* fall through */
- case SCSI_DISK_MAJOR:
+ case SCSI_DISK0_MAJOR:
+ case SCSI_DISK1_MAJOR:
+ case SCSI_DISK2_MAJOR:
+ case SCSI_DISK3_MAJOR:
+ case SCSI_DISK4_MAJOR:
+ case SCSI_DISK5_MAJOR:
+ case SCSI_DISK6_MAJOR:
+ case SCSI_DISK7_MAJOR:
case SCSI_CDROM_MAJOR:
do {
@@ -842,7 +855,7 @@ __initfunc(int blk_dev_init(void))
#ifdef CONFIG_BLK_DEV_FD
floppy_init();
#else
-#if !defined(CONFIG_SGI) && !defined (__mc68000__) && !defined(CONFIG_PMAC)
+#if !defined(CONFIG_SGI) && !defined (__mc68000__) && !defined(CONFIG_PMAC) \
&& !defined(__sparc__) && !defined(CONFIG_APUS)
outb_p(0xc, 0x3f2);
#endif
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 5a936899f..f635dd6c0 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -15,30 +15,34 @@
* Fixed do_loop_request() re-entrancy - Vincent.Renardias@waw.com Mar 20, 1997
*
* Handle sparse backing files correctly - Kenn Humborg, Jun 28, 1998
+ *
+ * Loadable modules and other fixes by AK, 1998
+ *
+ * Make real block number available to downstream transfer functions, enables
+ * CBC (and relatives) mode encryption requiring unique IVs per data block.
+ * Reed H. Petty, rhp@draper.net
+ *
+ * Still To Fix:
+ * - Advisory locking is ignored here.
+ * - Should use an own CAP_* category instead of CAP_SYS_ADMIN
+ * - Should use the underlying filesystems/devices read function if possible
+ * to support read ahead (and for write)
*/
#include <linux/module.h>
-#include <linux/config.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/major.h>
+
#include <linux/init.h>
#include <asm/uaccess.h>
-#ifdef CONFIG_BLK_DEV_LOOP_DES
-# /*nodep*/ include <linux/des.h>
-#endif
-
-#ifdef CONFIG_BLK_DEV_LOOP_IDEA
-# /*nodep*/ include <linux/idea.h>
-#endif
-
-#include <linux/loop.h> /* must follow des.h */
+#include <linux/loop.h>
#define MAJOR_NR LOOP_MAJOR
@@ -63,12 +67,11 @@ static int loop_blksizes[MAX_LOOP];
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
*/
static int transfer_none(struct loop_device *lo, int cmd, char *raw_buf,
- char *loop_buf, int size)
+ char *loop_buf, int size, int real_block)
{
if (cmd == READ)
memcpy(loop_buf, raw_buf, size);
@@ -78,7 +81,7 @@ static int transfer_none(struct loop_device *lo, int cmd, char *raw_buf,
}
static int transfer_xor(struct loop_device *lo, int cmd, char *raw_buf,
- char *loop_buf, int size)
+ char *loop_buf, int size, int real_block)
{
char *in, *out, *key;
int i, keysize;
@@ -97,80 +100,38 @@ static int transfer_xor(struct loop_device *lo, int cmd, char *raw_buf,
return 0;
}
-#ifdef DES_AVAILABLE
-static int transfer_des(struct loop_device *lo, int cmd, char *raw_buf,
- char *loop_buf, int size)
+static int none_status(struct loop_device *lo, struct loop_info *info)
{
- unsigned long tmp[2];
- unsigned long x0,x1,p0,p1;
+ return 0;
+}
- if (size & 7)
+static int xor_status(struct loop_device *lo, struct loop_info *info)
+{
+ if (info->lo_encrypt_key_size < 0)
return -EINVAL;
- x0 = lo->lo_des_init[0];
- x1 = lo->lo_des_init[1];
- while (size) {
- if (cmd == READ) {
- tmp[0] = (p0 = ((unsigned long *) raw_buf)[0])^x0;
- tmp[1] = (p1 = ((unsigned long *) raw_buf)[1])^x1;
- des_ecb_encrypt((des_cblock *) tmp,(des_cblock *)
- loop_buf,lo->lo_des_key,DES_ENCRYPT);
- x0 = p0^((unsigned long *) loop_buf)[0];
- x1 = p1^((unsigned long *) loop_buf)[1];
- }
- else {
- p0 = ((unsigned long *) loop_buf)[0];
- p1 = ((unsigned long *) loop_buf)[1];
- des_ecb_encrypt((des_cblock *) loop_buf,(des_cblock *)
- raw_buf,lo->lo_des_key,DES_DECRYPT);
- ((unsigned long *) raw_buf)[0] ^= x0;
- ((unsigned long *) raw_buf)[1] ^= x1;
- x0 = p0^((unsigned long *) raw_buf)[0];
- x1 = p1^((unsigned long *) raw_buf)[1];
- }
- size -= 8;
- raw_buf += 8;
- loop_buf += 8;
- }
return 0;
}
-#endif
-
-#ifdef IDEA_AVAILABLE
-extern void idea_encrypt_block(idea_key,char *,char *,int);
-
-static int transfer_idea(struct loop_device *lo, int cmd, char *raw_buf,
- char *loop_buf, int size)
-{
- if (cmd==READ) {
- idea_encrypt_block(lo->lo_idea_en_key,raw_buf,loop_buf,size);
- }
- else {
- idea_encrypt_block(lo->lo_idea_de_key,loop_buf,raw_buf,size);
- }
- return 0;
-}
-#endif
-
-static transfer_proc_t xfer_funcs[MAX_LOOP] = {
- transfer_none, /* LO_CRYPT_NONE */
- transfer_xor, /* LO_CRYPT_XOR */
-#ifdef DES_AVAILABLE
- transfer_des, /* LO_CRYPT_DES */
-#else
- NULL, /* LO_CRYPT_DES */
-#endif
-#ifdef IDEA_AVAILABLE /* LO_CRYPT_IDEA */
- transfer_idea
-#else
- NULL
-#endif
+struct loop_func_table none_funcs = {
+ number: LO_CRYPT_NONE,
+ transfer: transfer_none,
+ init: none_status
+};
+
+struct loop_func_table xor_funcs = {
+ number: LO_CRYPT_XOR,
+ transfer: transfer_xor,
+ init: xor_status
+};
+
+/* xfer_funcs[0] is special - its release function is never called */
+struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = {
+ &none_funcs,
+ &xor_funcs
};
-
#define MAX_DISK_SIZE 1024*1024*1024
-
static void figure_loop_size(struct loop_device *lo)
{
int size;
@@ -288,7 +249,7 @@ repeat:
}
if ((lo->transfer)(lo, current_request->cmd, bh->b_data + offset,
- dest_addr, size)) {
+ dest_addr, size, real_block)) {
printk(KERN_ERR "loop: transfer error block %d\n", block);
brelse(bh);
goto error_out_lock;
@@ -326,6 +287,7 @@ static int create_missing_block(struct loop_device *lo, int block, int blksize)
char zero_buf[1] = { 0 };
ssize_t retval;
mm_segment_t old_fs;
+ struct inode *inode;
file = lo->lo_backing_file;
if (file == NULL) {
@@ -350,15 +312,18 @@ static int create_missing_block(struct loop_device *lo, int block, int blksize)
}
if (file->f_op->write == NULL) {
- printk(KERN_WARNING "loop: cannot create block - no write file op\n");
+ printk(KERN_WARNING "loop: cannot create block - file not writeable\n");
return FALSE;
}
old_fs = get_fs();
set_fs(get_ds());
+ inode = file->f_dentry->d_inode;
+ down(&inode->i_sem);
retval = file->f_op->write(file, zero_buf, 1, &file->f_pos);
-
+ up(&inode->i_sem);
+
set_fs(old_fs);
if (retval < 0) {
@@ -426,9 +391,9 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg)
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 */
+ error = get_write_access(inode);
if (error) {
- fput(lo->lo_backing_file);
+ put_filp(lo->lo_backing_file);
lo->lo_backing_file = NULL;
}
}
@@ -444,9 +409,9 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg)
set_device_ro(dev, 0);
}
- lo->lo_dentry = file->f_dentry;
- lo->lo_dentry->d_count++;
+ lo->lo_dentry = dget(file->f_dentry);
lo->transfer = NULL;
+ lo->ioctl = NULL;
figure_loop_size(lo);
out_putf:
@@ -457,6 +422,36 @@ out:
return error;
}
+static int loop_release_xfer(struct loop_device *lo)
+{
+ int err = 0;
+ if (lo->lo_encrypt_type) {
+ struct loop_func_table *xfer= xfer_funcs[lo->lo_encrypt_type];
+ if (xfer && xfer->release)
+ err = xfer->release(lo);
+ if (xfer && xfer->unlock)
+ xfer->unlock(lo);
+ lo->lo_encrypt_type = 0;
+ }
+ return err;
+}
+
+static int loop_init_xfer(struct loop_device *lo, int type,struct loop_info *i)
+{
+ int err = 0;
+ if (type) {
+ struct loop_func_table *xfer = xfer_funcs[type];
+ if (xfer->init)
+ err = xfer->init(lo, i);
+ if (!err) {
+ lo->lo_encrypt_type = type;
+ if (xfer->lock)
+ xfer->lock(lo);
+ }
+ }
+ return err;
+}
+
static int loop_clr_fd(struct loop_device *lo, kdev_t dev)
{
struct dentry *dentry = lo->lo_dentry;
@@ -477,6 +472,9 @@ static int loop_clr_fd(struct loop_device *lo, kdev_t dev)
dput(dentry);
}
+ loop_release_xfer(lo);
+ lo->transfer = NULL;
+ lo->ioctl = NULL;
lo->lo_device = 0;
lo->lo_encrypt_type = 0;
lo->lo_offset = 0;
@@ -491,60 +489,41 @@ static int loop_clr_fd(struct loop_device *lo, kdev_t dev)
static int loop_set_status(struct loop_device *lo, struct loop_info *arg)
{
- struct loop_info info;
+ struct loop_info info;
int err;
+ unsigned int type;
+ if (lo->lo_encrypt_key_size && lo->lo_key_owner != current->uid &&
+ !capable(CAP_SYS_ADMIN))
+ return -EPERM;
if (!lo->lo_dentry)
return -ENXIO;
- if (!arg)
- return -EINVAL;
- err = verify_area(VERIFY_READ, arg, sizeof(info));
- if (err)
- return err;
- copy_from_user(&info, arg, sizeof(info));
+ if (copy_from_user(&info, arg, sizeof (struct loop_info)))
+ return -EFAULT;
if ((unsigned int) info.lo_encrypt_key_size > LO_KEY_SIZE)
return -EINVAL;
- switch (info.lo_encrypt_type) {
- case LO_CRYPT_NONE:
- break;
- case LO_CRYPT_XOR:
- if (info.lo_encrypt_key_size < 0)
- return -EINVAL;
- break;
-#ifdef DES_AVAILABLE
- case LO_CRYPT_DES:
- if (info.lo_encrypt_key_size != 8)
- return -EINVAL;
- des_set_key((des_cblock *) lo->lo_encrypt_key,
- lo->lo_des_key);
- memcpy(lo->lo_des_init,info.lo_init,8);
- break;
-#endif
-#ifdef IDEA_AVAILABLE
- case LO_CRYPT_IDEA:
- {
- uint16 tmpkey[8];
-
- if (info.lo_encrypt_key_size != IDEAKEYSIZE)
- return -EINVAL;
- /* create key in lo-> from info.lo_encrypt_key */
- memcpy(tmpkey,info.lo_encrypt_key,sizeof(tmpkey));
- en_key_idea(tmpkey,lo->lo_idea_en_key);
- de_key_idea(lo->lo_idea_en_key,lo->lo_idea_de_key);
- break;
- }
-#endif
- default:
+ type = info.lo_encrypt_type;
+ if (type >= MAX_LO_CRYPT || xfer_funcs[type] == NULL)
return -EINVAL;
- }
+ err = loop_release_xfer(lo);
+ if (!err)
+ err = loop_init_xfer(lo, type, &info);
+ if (err)
+ return err;
+
lo->lo_offset = info.lo_offset;
strncpy(lo->lo_name, info.lo_name, LO_NAME_SIZE);
- lo->lo_encrypt_type = info.lo_encrypt_type;
- lo->transfer = xfer_funcs[lo->lo_encrypt_type];
+
+ lo->transfer = xfer_funcs[type]->transfer;
+ lo->ioctl = xfer_funcs[type]->ioctl;
lo->lo_encrypt_key_size = info.lo_encrypt_key_size;
- if (info.lo_encrypt_key_size)
- memcpy(lo->lo_encrypt_key, info.lo_encrypt_key,
+ lo->lo_init[0] = info.lo_init[0];
+ lo->lo_init[1] = info.lo_init[1];
+ if (info.lo_encrypt_key_size) {
+ memcpy(lo->lo_encrypt_key, info.lo_encrypt_key,
info.lo_encrypt_key_size);
+ lo->lo_key_owner = current->uid;
+ }
figure_loop_size(lo);
return 0;
}
@@ -552,15 +531,11 @@ static int loop_set_status(struct loop_device *lo, struct loop_info *arg)
static int loop_get_status(struct loop_device *lo, struct loop_info *arg)
{
struct loop_info info;
- int err;
-
+
if (!lo->lo_dentry)
return -ENXIO;
if (!arg)
return -EINVAL;
- err = verify_area(VERIFY_WRITE, arg, sizeof(info));
- if (err)
- return err;
memset(&info, 0, sizeof(info));
info.lo_number = lo->lo_number;
info.lo_device = kdev_t_to_nr(lo->lo_dentry->d_inode->i_dev);
@@ -575,8 +550,7 @@ static int loop_get_status(struct loop_device *lo, struct loop_info *arg)
memcpy(info.lo_encrypt_key, lo->lo_encrypt_key,
lo->lo_encrypt_key_size);
}
- copy_to_user(arg, &info, sizeof(info));
- return 0;
+ return copy_to_user(arg, &info, sizeof(info)) ? -EFAULT : 0;
}
static int lo_ioctl(struct inode * inode, struct file * file,
@@ -611,7 +585,7 @@ static int lo_ioctl(struct inode * inode, struct file * file,
return -EINVAL;
return put_user(loop_sizes[lo->lo_number] << 1, (long *) arg);
default:
- return -EINVAL;
+ return lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL;
}
return 0;
}
@@ -619,7 +593,8 @@ static int lo_ioctl(struct inode * inode, struct file * file,
static int lo_open(struct inode *inode, struct file *file)
{
struct loop_device *lo;
- int dev;
+ int dev, type;
+
if (!inode)
return -EINVAL;
@@ -628,9 +603,14 @@ static int lo_open(struct inode *inode, struct file *file)
return -ENODEV;
}
dev = MINOR(inode->i_rdev);
- if (dev >= MAX_LOOP)
+ if (dev >= MAX_LOOP) {
return -ENODEV;
+ }
lo = &loop_dev[dev];
+
+ type = lo->lo_encrypt_type;
+ if (type && xfer_funcs[type] && xfer_funcs[type]->lock)
+ xfer_funcs[type]->lock(lo);
lo->lo_refcnt++;
MOD_INC_USE_COUNT;
return 0;
@@ -639,7 +619,7 @@ static int lo_open(struct inode *inode, struct file *file)
static int lo_release(struct inode *inode, struct file *file)
{
struct loop_device *lo;
- int dev;
+ int dev, err;
if (!inode)
return 0;
@@ -650,15 +630,18 @@ static int lo_release(struct inode *inode, struct file *file)
dev = MINOR(inode->i_rdev);
if (dev >= MAX_LOOP)
return 0;
- fsync_dev(inode->i_rdev);
+ err = fsync_dev(inode->i_rdev);
lo = &loop_dev[dev];
if (lo->lo_refcnt <= 0)
printk(KERN_ERR "lo_release: refcount(%d) <= 0\n", lo->lo_refcnt);
else {
- lo->lo_refcnt--;
+ int type = lo->lo_encrypt_type;
+ --lo->lo_refcnt;
+ if (xfer_funcs[type] && xfer_funcs[type]->unlock)
+ xfer_funcs[type]->unlock(lo);
MOD_DEC_USE_COUNT;
}
- return 0;
+ return err;
}
static struct file_operations lo_fops = {
@@ -681,8 +664,37 @@ static struct file_operations lo_fops = {
#define loop_init init_module
#endif
-__initfunc(int
-loop_init( void )) {
+int loop_register_transfer(struct loop_func_table *funcs)
+{
+ if ((unsigned)funcs->number > MAX_LO_CRYPT || xfer_funcs[funcs->number])
+ return -EINVAL;
+ xfer_funcs[funcs->number] = funcs;
+ return 0;
+}
+
+int loop_unregister_transfer(int number)
+{
+ struct loop_device *lo;
+
+ if ((unsigned)number >= MAX_LO_CRYPT)
+ return -EINVAL;
+ for (lo = &loop_dev[0]; lo < &loop_dev[MAX_LOOP]; lo++) {
+ int type = lo->lo_encrypt_type;
+ if (type == number) {
+ xfer_funcs[type]->release(lo);
+ lo->transfer = NULL;
+ lo->lo_encrypt_type = 0;
+ }
+ }
+ xfer_funcs[number] = NULL;
+ return 0;
+}
+
+EXPORT_SYMBOL(loop_register_transfer);
+EXPORT_SYMBOL(loop_unregister_transfer);
+
+int __init loop_init(void)
+{
int i;
if (register_blkdev(MAJOR_NR, "loop", &lo_fops)) {
@@ -692,12 +704,6 @@ loop_init( void )) {
}
#ifndef MODULE
printk(KERN_INFO "loop: registered device at major %d\n", MAJOR_NR);
-#ifdef DES_AVAILABLE
- printk(KERN_INFO "loop: DES encryption available\n");
-#endif
-#ifdef IDEA_AVAILABLE
- printk(KERN_INFO "loop: IDEA encryption available\n");
-#endif
#endif
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
@@ -714,9 +720,9 @@ loop_init( void )) {
}
#ifdef MODULE
-void
-cleanup_module( void ) {
- if (unregister_blkdev(MAJOR_NR, "loop") != 0)
- printk(KERN_WARNING "loop: cleanup_module failed\n");
+void cleanup_module(void)
+{
+ if (unregister_blkdev(MAJOR_NR, "loop") != 0)
+ printk(KERN_WARNING "loop: cannot unregister blkdev\n");
}
#endif
diff --git a/drivers/block/md.c b/drivers/block/md.c
index b6cf3d34e..77090708e 100644
--- a/drivers/block/md.c
+++ b/drivers/block/md.c
@@ -696,7 +696,6 @@ static int md_ioctl (struct inode *inode, struct file *file,
RO_IOCTLS(inode->i_rdev,arg);
default:
- printk ("Unknown md_ioctl %d\n", cmd);
return -EINVAL;
}
@@ -1140,8 +1139,7 @@ int md_do_sync(struct md_dev *mddev)
while (blocksize*j/(jiffies-starttime+1)*HZ/1024 > SPEED_LIMIT)
{
current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies+1;
- schedule();
+ schedule_timeout(1);
}
/*
diff --git a/drivers/block/ns87415.c b/drivers/block/ns87415.c
index d065606c7..dbce52137 100644
--- a/drivers/block/ns87415.c
+++ b/drivers/block/ns87415.c
@@ -31,7 +31,7 @@ static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 };
static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
{
ide_hwif_t *hwif = HWIF(drive);
- unsigned int bit, new, *old = (unsigned int *) hwif->select_data;
+ unsigned int bit, other, new, *old = (unsigned int *) hwif->select_data;
struct pci_dev *dev = hwif->pci_dev;
unsigned long flags;
@@ -39,24 +39,20 @@ static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
__cli(); /* local CPU only */
new = *old;
- /* adjust IRQ enable bit */
+ /* Adjust IRQ enable bit */
bit = 1 << (8 + hwif->channel);
new = drive->present ? (new & ~bit) : (new | bit);
- /* select PIO or DMA */
- bit = 1 << (20 + drive->select.b.unit + (hwif->channel << 1));
- new = use_dma ? (new | bit) : (new & ~bit);
+ /* Select PIO or DMA, DMA may only be selected for one drive/channel. */
+ bit = 1 << (20 + drive->select.b.unit + (hwif->channel << 1));
+ other = 1 << (20 + (1 - drive->select.b.unit) + (hwif->channel << 1));
+ new = use_dma ? ((new & ~other) | bit) : (new & ~bit);
if (new != *old) {
- if (use_dma) {
- bit = (1 << (5 + drive->select.b.unit));
- outb((inb(hwif->dma_base+2) & 0x60) | bit,
- hwif->dma_base+2);
- }
-
*old = new;
(void) pci_write_config_dword(dev, 0x40, new);
}
+
__restore_flags(flags); /* local CPU only */
}
@@ -74,8 +70,8 @@ static int ns87415_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
case ide_dma_end: /* returns 1 on error, 0 otherwise */
drive->waiting_for_dma = 0;
dma_stat = inb(hwif->dma_base+2);
- outb(7, hwif->dma_base); /* from errata: stop DMA, clear INTR & ERROR */
- outb(dma_stat|6, hwif->dma_base+2); /* clear the INTR & ERROR bits */
+ outb(inb(hwif->dma_base)&~1, hwif->dma_base); /* stop DMA */
+ outb(inb(hwif->dma_base)|6, hwif->dma_base); /* from ERRATA: clear the INTR & ERROR bits */
return (dma_stat & 7) != 4; /* verify good DMA status */
case ide_dma_write:
case ide_dma_read:
@@ -94,6 +90,10 @@ __initfunc(void ide_init_ns87415 (ide_hwif_t *hwif))
struct pci_dev *dev = hwif->pci_dev;
unsigned int ctrl, using_inta;
byte progif;
+#ifdef __sparc_v9__
+ int timeout;
+ byte stat;
+#endif
/*
* We cannot probe for IRQ: both ports share common IRQ on INTA.
@@ -126,22 +126,6 @@ __initfunc(void ide_init_ns87415 (ide_hwif_t *hwif))
pci_write_config_byte(dev, 0x55, 0xee);
#ifdef __sparc_v9__
-{
- 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().
@@ -156,9 +140,11 @@ __initfunc(void ide_init_ns87415 (ide_hwif_t *hwif))
if (stat == 0xff)
break;
} while ((stat & BUSY_STAT) && --timeout);
-}
#endif
}
+
+ outb(0x60, hwif->dma_base + 2);
+
if (!using_inta)
hwif->irq = hwif->channel ? 15 : 14; /* legacy mode */
else if (!hwif->irq && hwif->mate && hwif->mate->irq)
diff --git a/drivers/block/paride/frpw.c b/drivers/block/paride/frpw.c
index f965fb9da..680f9e592 100644
--- a/drivers/block/paride/frpw.c
+++ b/drivers/block/paride/frpw.c
@@ -12,10 +12,11 @@
1.01 GRG 1998.05.06 init_proto, release_proto
fix chip detect
added EPP-16 and EPP-32
+ 1.02 GRG 1998.09.23 added hard reset to initialisation process
*/
-#define FRPW_VERSION "1.01"
+#define FRPW_VERSION "1.02"
#include <linux/module.h>
#include <linux/delay.h>
@@ -184,6 +185,9 @@ static int frpw_test_pnp ( PIA *pi )
{ int olddelay, a, b;
+ w0(0); w2(8); udelay(50); w2(0xc); /* parallel bus reset */
+ mdelay(1500);
+
olddelay = pi->delay;
pi->delay = 10;
diff --git a/drivers/block/paride/jumbo b/drivers/block/paride/jumbo
new file mode 100644
index 000000000..b952fde92
--- /dev/null
+++ b/drivers/block/paride/jumbo
@@ -0,0 +1,70 @@
+#!/bin/sh
+#
+# This script can be used to build "jumbo" modules that contain the
+# base PARIDE support, one protocol module and one high-level driver.
+#
+echo -n "High level driver [pcd] : "
+read X
+HLD=${X:-pcd}
+#
+echo -n "Protocol module [bpck] : "
+read X
+PROTO=${X:-bpck}
+#
+echo -n "Use MODVERSIONS [y] ? "
+read X
+UMODV=${X:-y}
+#
+echo -n "For SMP kernel [n] ? "
+read X
+USMP=${X:-n}
+#
+echo -n "Support PARPORT [n] ? "
+read X
+UPARP=${X:-n}
+#
+echo
+#
+case $USMP in
+ y* | Y* ) FSMP="-D__SMP__"
+ ;;
+ *) FSMP=""
+ ;;
+esac
+#
+MODI="-include ../../../include/linux/modversions.h"
+#
+case $UMODV in
+ y* | Y* ) FMODV="-DMODVERSIONS $MODI"
+ ;;
+ *) FMODV=""
+ ;;
+esac
+#
+case $UPARP in
+ y* | Y* ) FPARP="-DCONFIG_PARPORT"
+ ;;
+ *) FPARP=""
+ ;;
+esac
+#
+TARG=$HLD-$PROTO.o
+FPROTO=-DCONFIG_PARIDE_`echo "$PROTO" | tr [a-z] [A-Z]`
+FK="-D__KERNEL__ -I ../../../include"
+FLCH=-D_LINUX_CONFIG_H
+#
+echo cc $FK $FSMP $FLCH $FPARP $FPROTO -Wall -O2 -o Jb.o -c paride.c
+cc $FK $FSMP $FLCH $FPARP $FPROTO -Wall -O2 -o Jb.o -c paride.c
+#
+echo cc $FK $FSMP -Wall -O2 -o Jp.o -c $PROTO.c
+cc $FK $FSMP -Wall -O2 -o Jp.o -c $PROTO.c
+#
+echo cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c
+cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c
+#
+echo ld -r -o $TARG Jp.o Jb.o Jd.o
+ld -r -o $TARG Jp.o Jb.o Jd.o
+#
+#
+rm Jp.o Jb.o Jd.o
+#
diff --git a/drivers/block/paride/on26.c b/drivers/block/paride/on26.c
index 89457cc80..78477593e 100644
--- a/drivers/block/paride/on26.c
+++ b/drivers/block/paride/on26.c
@@ -10,10 +10,11 @@
/* Changes:
1.01 GRG 1998.05.06 init_proto, release_proto
+ 1.02 GRG 1998.09.23 updates for the -E rev chip
*/
-#define ON26_VERSION "1.01"
+#define ON26_VERSION "1.02"
#include <linux/module.h>
#include <linux/delay.h>
@@ -91,8 +92,8 @@ static void on26_write_regr( PIA *pi, int cont, int regr, int val )
}
}
-#define CCP(x) w0(0xff);w0(0xaa);w0(0x55);w0(0);w0(0xff);\
- w0(0x87);w0(0x78);w0(x);w2(4);
+#define CCP(x) w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);\
+ w0(0x87);w0(0x78);w0(x);w2(4);w2(5);w2(4);w0(0xff);
static void on26_connect ( PIA *pi )
@@ -102,7 +103,6 @@ static void on26_connect ( PIA *pi )
pi->saved_r2 = r2();
CCP(0x20);
- w2(0xcd); w2(0xcc); w0(0xff);
x = 8; if (pi->mode) x = 9;
w0(2); P1; w0(8); P2;
@@ -114,11 +114,62 @@ static void on26_disconnect ( PIA *pi )
{ if (pi->mode >= 2) { w3(4); w3(4); w3(4); w3(4); }
else { w0(4); P1; w0(4); P1; }
CCP(0x30);
- w2(0xcd); w2(0xcc); w0(0xff);
w0(pi->saved_r0);
w2(pi->saved_r2);
}
+static int on26_test_port( PIA *pi) /* hard reset */
+
+{ int i, m, d;
+
+ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
+
+ d = pi->delay;
+ m = pi->mode;
+ pi->delay = 5;
+ pi->mode = 0;
+
+ w2(0xc);
+
+ CCP(0x30); CCP(0);
+
+ w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);
+ i = ((r1() & 0xf0) << 4); w0(0x87);
+ i |= (r1() & 0xf0); w0(0x78);
+ w0(0x20);w2(4);w2(5);
+ i |= ((r1() & 0xf0) >> 4);
+ w2(4);w0(0xff);
+
+ if (i == 0xb5f) {
+
+ w0(2); P1; w0(0); P2;
+ w0(3); P1; w0(0); P2;
+ w0(2); P1; w0(8); P2; udelay(100);
+ w0(2); P1; w0(0xa); P2; udelay(100);
+ w0(2); P1; w0(8); P2; udelay(1000);
+
+ on26_write_regr(pi,0,6,0xa0);
+
+ for (i=0;i<100;i++) {
+ if (!(on26_read_regr(pi,0,7) & 0x80)) break;
+ udelay(100000);
+ }
+
+ w0(4); P1; w0(4); P1;
+ }
+
+ CCP(0x30);
+
+ pi->delay = d;
+ pi->mode = m;
+ w0(pi->saved_r0);
+ w2(pi->saved_r2);
+
+ return 5;
+}
+
+
static void on26_read_block( PIA *pi, char * buf, int count )
{ int k, a, b;
@@ -240,7 +291,7 @@ struct pi_protocol on26 = {"on26",0,5,2,1,1,
on26_read_block,
on26_connect,
on26_disconnect,
- 0,
+ on26_test_port,
0,
0,
on26_log_adapter,
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index 4a083abbf..6366afa6b 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -96,10 +96,11 @@
pcd_completion, use HZ in loop timing
1.05 GRG 1998.08.16 Conformed to "Uniform CD-ROM" standard
1.06 GRG 1998.08.19 Added audio ioctl support
+ 1.07 GRG 1998.09.24 Increased reset timeout, added jumbo support
*/
-#define PCD_VERSION "1.06"
+#define PCD_VERSION "1.07"
#define PCD_MAJOR 46
#define PCD_NAME "pcd"
#define PCD_UNITS 4
@@ -191,7 +192,7 @@ MODULE_PARM(drive3,"1-6i");
#define PCD_TMO 800 /* timeout in jiffies */
#define PCD_DELAY 50 /* spin delay in uS */
#define PCD_READY_TMO 20 /* in seconds */
-#define PCD_RESET_TMO 30 /* in tenths of a second */
+#define PCD_RESET_TMO 100 /* in tenths of a second */
#define PCD_SPIN (1000000*PCD_TMO)/(HZ*PCD_DELAY)
@@ -365,6 +366,12 @@ int init_module(void)
{ int err;
+#ifdef PARIDE_JUMBO
+ { extern paride_init();
+ paride_init();
+ }
+#endif
+
err = pcd_init();
return err;
@@ -552,8 +559,7 @@ static int pcd_tray_move(struct cdrom_device_info *cdi, int position)
static void pcd_sleep( int cs )
{ current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + cs;
- schedule();
+ schedule_timeout(cs);
}
static int pcd_reset( int unit )
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 69274fe48..3518a59d6 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -110,10 +110,11 @@
Added slave support
1.03 GRG 1998.06.16 Eliminate an Ugh.
1.04 GRG 1998.08.15 Extra debugging, use HZ in loop timing
+ 1.05 GRG 1998.09.24 Added jumbo support
*/
-#define PD_VERSION "1.04"
+#define PD_VERSION "1.05"
#define PD_MAJOR 45
#define PD_NAME "pd"
#define PD_UNITS 4
@@ -611,6 +612,12 @@ int init_module(void)
{ int err, unit;
+#ifdef PARIDE_JUMBO
+ { extern paride_init();
+ paride_init();
+ }
+#endif
+
err = pd_init();
if (err) return err;
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index a2f1f1da9..255352f0a 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -109,10 +109,11 @@
up transfer size.
1.02 GRG 1998.06.16 Eliminated an Ugh
1.03 GRG 1998.08.16 Use HZ in loop timings, extra debugging
+ 1.04 GRG 1998.09.24 Added jumbo support
*/
-#define PF_VERSION "1.03"
+#define PF_VERSION "1.04"
#define PF_MAJOR 47
#define PF_NAME "pf"
#define PF_UNITS 4
@@ -509,6 +510,12 @@ int init_module(void)
{ int err;
+#ifdef PARIDE_JUMBO
+ { extern paride_init();
+ paride_init();
+ }
+#endif
+
err = pf_init();
return err;
@@ -653,8 +660,7 @@ static void pf_eject( int unit )
static void pf_sleep( int cs )
{ current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + cs;
- schedule();
+ schedule_timeout(cs);
}
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index fd001008d..1563a2afc 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -34,10 +34,10 @@
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
+ /dev/pg0 c 97 0
+ /dev/pg1 c 97 1
+ /dev/pg2 c 97 2
+ /dev/pg3 c 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
@@ -117,9 +117,11 @@
/* Changes:
1.01 GRG 1998.06.16 Bug fixes
+ 1.02 GRG 1998.09.24 Added jumbo support
+
*/
-#define PG_VERSION "1.01"
+#define PG_VERSION "1.02"
#define PG_MAJOR 97
#define PG_NAME "pg"
#define PG_UNITS 4
@@ -324,6 +326,12 @@ int init_module(void)
{ int err;
+#ifdef PARIDE_JUMBO
+ { extern paride_init();
+ paride_init();
+ }
+#endif
+
err = pg_init();
return err;
@@ -349,8 +357,7 @@ void cleanup_module(void)
static void pg_sleep( int cs )
{ current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + cs;
- schedule();
+ schedule_timeout(cs);
}
static int pg_wait( int unit, int go, int stop, int tmo, char * msg )
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 44c4dadfb..1a09c84b0 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -100,10 +100,11 @@
1.02 GRG 1998.06.16 Eliminate an Ugh.
1.03 GRG 1998.08.15 Adjusted PT_TMO, use HZ in loop timing,
extra debugging
-
+ 1.04 GRG 1998.09.24 Repair minor coding error, added jumbo support
+
*/
-#define PT_VERSION "1.03"
+#define PT_VERSION "1.04"
#define PT_MAJOR 96
#define PT_NAME "pt"
#define PT_UNITS 4
@@ -328,6 +329,12 @@ int init_module(void)
{ int err;
+#ifdef PARIDE_JUMBO
+ { extern paride_init();
+ paride_init();
+ }
+#endif
+
err = pt_init();
return err;
@@ -457,8 +464,7 @@ static int pt_atapi( int unit, char * cmd, int dlen, char * buf, char * fun )
static void pt_sleep( int cs )
{ current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + cs;
- schedule();
+ schedule_timeout(cs);
}
static int pt_poll_dsc( int unit, int pause, int tmo, char *msg )
@@ -584,8 +590,8 @@ static int pt_identify( int unit )
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 ms_cmd[12] = { ATAPI_MODE_SENSE,0,0x2a,0,128,0,0,0,0,0,0,0};
- char ls_cmd[12] = { ATAPI_LOG_SENSE,0,0x71,0,0,0,0,0,128,0,0,0};
+ char ms_cmd[12] = { ATAPI_MODE_SENSE,0,0x2a,0,36,0,0,0,0,0,0,0};
+ char ls_cmd[12] = { ATAPI_LOG_SENSE,0,0x71,0,0,0,0,0,36,0,0,0};
char buf[36];
s = pt_atapi(unit,id_cmd,36,buf,"identify");
diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
index e56616a77..4e165bbd0 100644
--- a/drivers/block/ps2esdi.c
+++ b/drivers/block/ps2esdi.c
@@ -109,20 +109,16 @@ u_int dma_arb_level; /* DMA arbitration level */
static struct wait_queue *ps2esdi_int = NULL, *ps2esdi_wait_open = NULL;
int no_int_yet;
-static int access_count[MAX_HD] =
-{0,};
-static char ps2esdi_valid[MAX_HD] =
-{0,};
-static int ps2esdi_sizes[MAX_HD << 6] =
-{0,};
-static int ps2esdi_blocksizes[MAX_HD << 6] =
-{0,};
+static int access_count[MAX_HD] = {0,};
+static char ps2esdi_valid[MAX_HD] = {0,};
+static int ps2esdi_sizes[MAX_HD << 6] = {0,};
+static int ps2esdi_blocksizes[MAX_HD << 6] = {0,};
static int ps2esdi_drives = 0;
static struct hd_struct ps2esdi[MAX_HD << 6];
static u_short io_base;
-static struct timer_list esdi_timer =
-{NULL, NULL, 0, 0L, ps2esdi_reset_timer};
+static struct timer_list esdi_timer = {NULL, NULL, 0, 0L, ps2esdi_reset_timer};
static int reset_status;
+static int ps2esdi_slot = -1;
int tp720esdi = 0; /* Is it Integrated ESDI of ThinkPad-720? */
struct ps2esdi_i_struct {
@@ -198,6 +194,51 @@ __initfunc(int ps2esdi_init(void))
} /* ps2esdi_init */
+#ifdef MODULE
+
+int cyl[2] = {-1,-1};
+int head[2] = {-1, -1};
+int sect[2] = {-1, -1};
+
+MODULE_PARM(tp720esdi, "i");
+MODULE_PARM(cyl, "i");
+MODULE_PARM(head, "i");
+MODULE_PARM(track, "i");
+
+int init_module(void) {
+ int drive;
+
+ for(drive = 0; drive <= 1; drive++) {
+ struct ps2_esdi_i_struct *info = &ps2esdi_info[drive];
+
+ if (cyl[drive] != -1) {
+ info->cyl = info->lzone = cyl[drive];
+ info->wpcom = 0;
+ }
+ if (head[drive] != -1) {
+ info->head = head[drive];
+ info->ctl = (head[drive] > 8 ? 8 : 0);
+ }
+ if (sect[drive] != -1) info->sect = sect[drive];
+ }
+ return ps2esdi_init();
+}
+
+void
+cleanup_module(void)
+{
+ if(ps2esdi_slot)
+ {
+ mca_mark_as_unused(ps2esdi_slot);
+ mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL);
+ }
+ release_region(io_base, 4);
+ free_dma(dma_arb_level);
+ free_irq(PS2ESDI_IRQ, NULL)
+ unregister_blkdev(MAJOR_NR, "ed");
+}
+#endif /* MODULE */
+
/* handles boot time command line parameters */
__initfunc(void tp720_setup(char *str, int *ints))
{
@@ -289,6 +330,8 @@ __initfunc(static void ps2esdi_geninit(struct gendisk *ignored))
return;
}
+ ps2esdi_slot = slot;
+ mca_mark_as_used(slot);
mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL);
/* Found the slot - read the POS register 2 to get the necessary
@@ -383,6 +426,9 @@ __initfunc(static void ps2esdi_geninit(struct gendisk *ignored))
}
for (i = 0; i < (MAX_HD << 6); i++)
ps2esdi_blocksizes[i] = 1024;
+
+ request_dma(dma_arb_level, "ed");
+ request_region(io_base, 4, "ed");
blksize_size[MAJOR_NR] = ps2esdi_blocksizes;
} /* ps2esdi_geninit */
@@ -511,7 +557,7 @@ static void reset_ctrl(void)
printk("%s: hard reset...\n", DEVICE_NAME);
outb_p(CTRL_HARD_RESET, ESDI_CONTROL);
expire = jiffies + 200;
- while (jiffies < expire);
+ while (time_before(jiffies, expire));
outb_p(1, ESDI_CONTROL);
} /* hard reset */
@@ -588,7 +634,7 @@ static int ps2esdi_out_cmd_blk(u_short * cmd_blk)
outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
/* do not write to the controller, if it is busy */
- for (i = jiffies + ESDI_STAT_TIMEOUT; (i > jiffies) && (inb(ESDI_STATUS) &
+ for (i = jiffies + ESDI_STAT_TIMEOUT; time_after(i, jiffies) && (inb(ESDI_STATUS) &
STATUS_BUSY););
#if 0
@@ -611,7 +657,7 @@ static int ps2esdi_out_cmd_blk(u_short * cmd_blk)
for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) {
status = inb(ESDI_STATUS);
for (j = jiffies + ESDI_STAT_TIMEOUT;
- (j > jiffies) && (status & STATUS_BUSY) &&
+ time_after(j, jiffies) && (status & STATUS_BUSY) &&
(status & STATUS_CMD_INF); status = inb(ESDI_STATUS));
if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) {
#if 0
diff --git a/drivers/block/sl82c105.c b/drivers/block/sl82c105.c
index 39b62fddd..6c1d12cb9 100644
--- a/drivers/block/sl82c105.c
+++ b/drivers/block/sl82c105.c
@@ -14,11 +14,6 @@
#include "ide.h"
#include "ide_modes.h"
-unsigned int chrp_ide_irq = 0;
-int chrp_ide_ports_known = 0;
-ide_ioreg_t chrp_ide_regbase[MAX_HWIFS];
-ide_ioreg_t chrp_idedma_regbase;
-
void ide_init_sl82c105(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
@@ -37,37 +32,3 @@ void ide_init_sl82c105(ide_hwif_t *hwif)
printk("IDE control/status register: %08x\n",t32);
pci_write_config_dword(dev, 0x40, 0x10ff08a1);
}
-
-/* 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);
-
- chrp_ide_ports_known = 1;
-
- if(pdev) {
- chrp_ide_regbase[0]=pdev->base_address[0] &
- PCI_BASE_ADDRESS_IO_MASK;
- chrp_ide_regbase[1]=pdev->base_address[2] &
- PCI_BASE_ADDRESS_IO_MASK;
- chrp_idedma_regbase=pdev->base_address[4] &
- PCI_BASE_ADDRESS_IO_MASK;
- chrp_ide_irq=pdev->irq;
- }
-}
-
-
-void chrp_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
-{
- ide_ioreg_t port = base;
- int i = 8;
-
- while (i--)
- *p++ = port++;
- *p++ = port;
- if (irq != NULL)
- *irq = chrp_ide_irq;
-}
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index bacb3df98..247db08d6 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -22,12 +22,15 @@
#include <asm/prom.h>
#include <asm/uaccess.h>
#include <asm/mediabay.h>
+#include <asm/feature.h>
#define MAJOR_NR FLOPPY_MAJOR
#include <linux/blk.h>
-static int floppy_blocksizes[2] = {512};
-static int floppy_sizes[2] = {2880};
+static int floppy_blocksizes[2] = {512,512};
+static int floppy_sizes[2] = {2880,2880};
+
+#define MAX_FLOPPIES 2
enum swim_state {
idle,
@@ -139,11 +142,12 @@ struct floppy_state {
int ejected;
struct wait_queue *wait;
int wanted;
- int in_media_bay;
+ struct device_node* media_bay; /* NULL when not in bay */
char dbdma_cmd_space[5 * sizeof(struct dbdma_cmd)];
};
-static struct floppy_state floppy_states[1];
+static struct floppy_state floppy_states[MAX_FLOPPIES];
+static int floppy_count = 0;
static unsigned short write_preamble[] = {
0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, /* gap field */
@@ -175,7 +179,7 @@ static void scan_timeout(unsigned long data);
static void seek_timeout(unsigned long data);
static void xfer_timeout(unsigned long data);
static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void fd_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+/*static void fd_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs);*/
static int grab_drive(struct floppy_state *fs, enum swim_state state,
int interruptible);
static void release_drive(struct floppy_state *fs);
@@ -190,6 +194,7 @@ 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);
+static int swim3_add_device(struct device_node *swims);
int swim3_init(void);
#define IOCTL_MODE_BIT 8
@@ -212,11 +217,11 @@ static void swim3_action(struct floppy_state *fs, int action)
volatile struct swim3 *sw = fs->swim3;
swim3_select(fs, action);
- udelay(1);
+ udelay(10);
sw->select |= LSTRB; eieio();
- udelay(2);
+ udelay(20);
sw->select &= ~LSTRB; eieio();
- udelay(1);
+ udelay(10);
out_8(&sw->select, RELAX);
}
@@ -226,7 +231,7 @@ static int swim3_readbit(struct floppy_state *fs, int bit)
int stat;
swim3_select(fs, bit);
- udelay(1);
+ udelay(10);
stat = in_8(&sw->status);
out_8(&sw->select, RELAX);
return (stat & DATA) == 0;
@@ -234,13 +239,19 @@ static int swim3_readbit(struct floppy_state *fs, int bit)
static void do_fd_request(void)
{
- start_request(&floppy_states[0]);
+ int i;
+ for(i=0;i<floppy_count;i++)
+ {
+ if (floppy_states[i].media_bay &&
+ check_media_bay(floppy_states[i].media_bay, MB_FD))
+ continue;
+ start_request(&floppy_states[i]);
+ }
sti();
}
static void start_request(struct floppy_state *fs)
{
- int drive;
unsigned long x;
if (fs->state == idle && fs->wanted) {
@@ -261,11 +272,6 @@ static void start_request(struct floppy_state *fs)
CURRENT->rq_status, CURRENT->errors, CURRENT->current_nr_sectors);
#endif
- drive = MINOR(CURRENT->rq_dev);
- if (drive != 0) {
- end_request(0);
- continue;
- }
if (CURRENT->sector < 0 || CURRENT->sector >= fs->total_secs) {
end_request(0);
continue;
@@ -438,7 +444,7 @@ static void act(struct floppy_state *fs)
case settling:
/* wait for SEEK_COMPLETE to become true */
swim3_select(fs, SEEK_COMPLETE);
- udelay(1);
+ udelay(10);
out_8(&sw->intr_enable, ERROR | DATA_CHANGED);
in_8(&sw->intr); /* clear DATA_CHANGED */
if (in_8(&sw->status) & DATA) {
@@ -560,7 +566,7 @@ 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);
+ printk("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",
@@ -685,9 +691,11 @@ static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
}
+/*
static void fd_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
}
+*/
static int grab_drive(struct floppy_state *fs, enum swim_state state,
int interruptible)
@@ -740,8 +748,7 @@ static int fd_eject(struct floppy_state *fs)
break;
}
current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + 1;
- schedule();
+ schedule_timeout(1);
}
fs->ejected = 1;
release_drive(fs);
@@ -756,12 +763,20 @@ static int floppy_ioctl(struct inode *inode, struct file *filp,
{
struct floppy_state *fs;
int err;
+ int devnum = MINOR(inode->i_rdev);
+ if (devnum >= floppy_count)
+ return -ENODEV;
+
if (((cmd & 0x40) && !(filp && (filp->f_mode & IOCTL_MODE_BIT))) ||
((cmd & 0x80) && !suser()))
return -EPERM;
- fs = &floppy_states[0];
+ fs = &floppy_states[devnum];
+
+ if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
+ return -ENXIO;
+
switch (cmd) {
case FDEJECT:
if (fs->ref_count != 1)
@@ -781,19 +796,21 @@ static int floppy_open(struct inode *inode, struct file *filp)
struct floppy_state *fs;
volatile struct swim3 *sw;
int n, err;
+ int devnum = MINOR(inode->i_rdev);
- if (MINOR(inode->i_rdev) != 0)
+ if (devnum >= floppy_count)
return -ENODEV;
- fs = &floppy_states[0];
+
+ fs = &floppy_states[devnum];
sw = fs->swim3;
err = 0;
if (fs->ref_count == 0) {
- if (fs->in_media_bay && !check_media_bay(MB_FD))
+ if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
return -ENXIO;
out_8(&sw->mode, 0x95);
out_8(&sw->control_bic, 0xff);
out_8(&sw->reg5, 0x28);
- udelay(1);
+ udelay(10);
out_8(&sw->intr_enable, 0);
out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE);
swim3_action(fs, MOTOR_ON);
@@ -807,8 +824,7 @@ static int floppy_open(struct inode *inode, struct file *filp)
break;
}
current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + 1;
- schedule();
+ schedule_timeout(1);
}
if (err == 0 && (swim3_readbit(fs, SEEK_COMPLETE) == 0
|| swim3_readbit(fs, DISK_IN) == 0))
@@ -858,9 +874,11 @@ static int floppy_release(struct inode *inode, struct file *filp)
{
struct floppy_state *fs;
volatile struct swim3 *sw;
+ int devnum = MINOR(inode->i_rdev);
+
+ if (devnum >= floppy_count)
+ return -ENODEV;
- if (MINOR(inode->i_rdev) != 0)
- return -ENXIO;
/*
* If filp is NULL, we're being called from blkdev_release
* or after a failed mount attempt. In the former case the
@@ -870,7 +888,7 @@ 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);
- fs = &floppy_states[0];
+ fs = &floppy_states[devnum];
sw = fs->swim3;
if (fs->ref_count > 0 && --fs->ref_count == 0) {
swim3_action(fs, MOTOR_OFF);
@@ -882,10 +900,12 @@ static int floppy_release(struct inode *inode, struct file *filp)
static int floppy_check_change(kdev_t dev)
{
struct floppy_state *fs;
+ int devnum = MINOR(dev);
- if (MAJOR(dev) != MAJOR_NR || MINOR(dev) != 0)
+ if (MAJOR(dev) != MAJOR_NR || (devnum >= floppy_count))
return 0;
- fs = &floppy_states[0];
+
+ fs = &floppy_states[devnum];
return fs->ejected;
}
@@ -894,10 +914,16 @@ static int floppy_revalidate(kdev_t dev)
struct floppy_state *fs;
volatile struct swim3 *sw;
int ret, n;
+ int devnum = MINOR(dev);
- if (MAJOR(dev) != MAJOR_NR || MINOR(dev) != 0)
+ if (MAJOR(dev) != MAJOR_NR || (devnum >= floppy_count))
return 0;
- fs = &floppy_states[0];
+
+ fs = &floppy_states[devnum];
+
+ if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
+ return -ENXIO;
+
sw = fs->swim3;
grab_drive(fs, revalidating, 0);
out_8(&sw->intr_enable, 0);
@@ -911,8 +937,7 @@ static int floppy_revalidate(kdev_t dev)
if (signal_pending(current))
break;
current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + 1;
- schedule();
+ schedule_timeout(1);
}
ret = swim3_readbit(fs, SEEK_COMPLETE) == 0
|| swim3_readbit(fs, DISK_IN) == 0;
@@ -932,10 +957,12 @@ static ssize_t floppy_read(struct file *filp, char *buf,
{
struct inode *inode = filp->f_dentry->d_inode;
struct floppy_state *fs;
+ int devnum = MINOR(inode->i_rdev);
- if (MINOR(inode->i_rdev) != 0)
+ if (devnum >= floppy_count)
return -ENODEV;
- fs = &floppy_states[0];
+
+ fs = &floppy_states[devnum];
if (fs->ejected)
return -ENXIO;
return block_read(filp, buf, count, ppos);
@@ -946,10 +973,12 @@ static ssize_t floppy_write(struct file * filp, const char * buf,
{
struct inode * inode = filp->f_dentry->d_inode;
struct floppy_state *fs;
+ int devnum = MINOR(inode->i_rdev);
- if (MINOR(inode->i_rdev) != 0)
+ if (devnum >= floppy_count)
return -ENODEV;
- fs = &floppy_states[0];
+
+ fs = &floppy_states[devnum];
if (fs->ejected)
return -ENXIO;
return block_write(filp, buf, count, ppos);
@@ -978,50 +1007,72 @@ static struct file_operations floppy_fops = {
int swim3_init(void)
{
- struct device_node *swims;
- struct floppy_state *fs = &floppy_states[0];
- 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");
+ struct device_node *swim;
+
+ swim = find_devices("floppy");
+ while (swim && (floppy_count < MAX_FLOPPIES))
+ {
+ swim3_add_device(swim);
+ swim = swim->next;
}
- if (swims == NULL)
- return 0;
+ swim = find_devices("swim3");
+ while (swim && (floppy_count < MAX_FLOPPIES))
+ {
+ swim3_add_device(swim);
+ swim = swim->next;
+ }
- if (swims->next != NULL)
- printk(KERN_ERR "Warning: only using first SWIM3 floppy controller\n");
- if (swims->n_addrs != 2 || swims->n_intrs != 2) {
- printk(KERN_ERR "swim3: expecting 2 addrs and 2 intrs! (%d, %d)\n",
- swims->n_addrs, swims->n_intrs);
+ if (floppy_count > 0)
+ {
+ if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) {
+ printk(KERN_ERR "Unable to get major %d for floppy\n",
+ MAJOR_NR);
+ return -EBUSY;
+ }
+ blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blksize_size[MAJOR_NR] = floppy_blocksizes;
+ blk_size[MAJOR_NR] = floppy_sizes;
+ }
+
+ return 0;
+}
+
+static int swim3_add_device(struct device_node *swim)
+{
+ struct device_node *mediabay;
+ struct floppy_state *fs = &floppy_states[floppy_count];
+
+ if (swim->n_addrs < 2)
+ {
+ printk(KERN_INFO "swim3: expecting 2 addrs (n_addrs:%d, n_intrs:%d)\n",
+ swim->n_addrs, swim->n_intrs);
return -EINVAL;
}
- if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) {
- printk(KERN_ERR "Unable to get major %d for floppy\n",
- MAJOR_NR);
- return -EBUSY;
+ if (swim->n_intrs < 2)
+ {
+ printk(KERN_INFO "swim3: expecting 2 intrs (n_addrs:%d, n_intrs:%d)\n",
+ swim->n_addrs, swim->n_intrs);
+ return -EINVAL;
}
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
- blksize_size[MAJOR_NR] = floppy_blocksizes;
- blk_size[MAJOR_NR] = floppy_sizes;
+ mediabay = (strcasecmp(swim->parent->type, "media-bay") == 0) ? swim->parent : NULL;
+ if (mediabay == NULL)
+ feature_set(swim, FEATURE_SWIM3_enable);
+
memset(fs, 0, sizeof(*fs));
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].line;
- fs->dma_intr = swims->intrs[1].line;
+ fs->swim3 = (volatile struct swim3 *) ioremap(swim->addrs[0].address, 0x200);
+ fs->dma = (struct dbdma_regs *) ioremap(swim->addrs[1].address, 0x200);
+ fs->swim3_intr = swim->intrs[0].line;
+ fs->dma_intr = swim->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->media_bay = mediabay;
fs->dma_cmd = (struct dbdma_cmd *) DBDMA_ALIGN(fs->dbdma_cmd_space);
memset(fs->dma_cmd, 0, 2 * sizeof(struct dbdma_cmd));
@@ -1029,19 +1080,26 @@ int swim3_init(void)
if (request_irq(fs->swim3_intr, swim3_interrupt, 0, "SWIM3", fs)) {
printk(KERN_ERR "Couldn't get irq %d for SWIM3\n", fs->swim3_intr);
+ feature_clear(swim, FEATURE_SWIM3_enable);
return -EBUSY;
}
+/*
if (request_irq(fs->dma_intr, fd_dma_interrupt, 0, "SWIM3-dma", fs)) {
printk(KERN_ERR "Couldn't get irq %d for SWIM3 DMA",
fs->dma_intr);
+ feature_clear(swim, FEATURE_SWIM3_enable);
return -EBUSY;
}
+*/
init_timer(&fs->timeout);
do_floppy = NULL;
- printk(KERN_INFO "fd0: SWIM3 floppy controller\n");
+ printk(KERN_INFO "fd%d: SWIM3 floppy controller %s\n", floppy_count,
+ mediabay ? "in media bay" : "");
+ floppy_count++;
+
return 0;
}
diff --git a/drivers/block/via82c586.c b/drivers/block/via82c586.c
new file mode 100644
index 000000000..28bf80c76
--- /dev/null
+++ b/drivers/block/via82c586.c
@@ -0,0 +1,86 @@
+/*
+ * linux/drivers/block/via82c586.c Version 0.01 Aug 16, 1998
+ *
+ * Copyright (C) 1998 Michel Aubry
+ * Copyright (C) 1998 Andre Hedrick
+ *
+ * The VIA MVP-3 is reported OK with UDMA.
+ *
+ * VIA chips also have a single FIFO, with the same 64 bytes deep buffer (16 levels
+ * of 4 bytes each).
+ * However, VIA chips can have the buffer split either 8:8 levels, 16:0 levels or
+ * 0:16 levels between both channels. One could think of using this feature, as even
+ * if no level of FIFO is given to a given channel, one can always reach ATAPI drives
+ * through it, or, if one channel is unused, configuration defaults to an even split
+ * FIFO levels.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include "ide.h"
+
+/*
+ * Set VIA Chipset Timings for (U)DMA modes enabled.
+ *
+ * VIA Apollo chipset has complete support for
+ * setting up the timing parameters.
+ */
+static void set_via_timings (ide_hwif_t *hwif)
+{
+ struct pci_dev *dev = hwif->pci_dev;
+ byte post = hwif->channel ? 0xc0 : 0x30;
+ byte flush = hwif->channel ? 0xa0 : 0x50;
+ byte via_config = 0;
+ int rc = 0, errors = 0;
+
+ printk("%s: VIA Bus-Master ", hwif->name);
+
+ if (!hwif->dma_base) {
+ printk(" ERROR, NO DMA_BASE\n");
+ return;
+ }
+
+ /* setting IDE read prefetch buffer and IDE post write buffer.
+ * (This feature allows prefetched reads and post writes).
+ */
+ if ((rc = pci_read_config_byte(dev, 0x41, &via_config))) {
+ errors++;
+ goto via_error;
+ }
+ if ((rc = pci_write_config_byte(dev, 0x41, via_config | post))) {
+ errors++;
+ goto via_error;
+ }
+
+ /* setting Channel read and End-of-sector FIFO flush.
+ * (This feature ensures that FIFO flush is enabled:
+ * - for read DMA when interrupt asserts the given channel.
+ * - at the end of each sector for the given channel.)
+ */
+ if ((rc = pci_read_config_byte(dev, 0x46, &via_config))) {
+ errors++;
+ goto via_error;
+ }
+ if ((rc = pci_write_config_byte(dev, 0x46, via_config | flush))) {
+ errors++;
+ goto via_error;
+ }
+
+via_error:
+ printk("(U)DMA Timing Config %s\n", errors ? "ERROR" : "Success");
+}
+
+void ide_init_via82c586 (ide_hwif_t *hwif)
+{
+ set_via_timings(hwif);
+}
+
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index ccbcc0a97..2ea4bf393 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -108,9 +108,7 @@ static XD_SIGNATURE xd_sigs[] __initdata = {
{ 0x0008,"[BXD06 (C) DTC 17-MAY-1985]",xd_dtc_init_controller,xd_dtc5150cx_init_drive," DTC 5150CX" }, /* Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl */
{ 0x000B,"CRD18A Not an IBM rom. (C) Copyright Data Technology Corp. 05/31/88",xd_dtc_init_controller,xd_dtc_init_drive," DTC 5150X" }, /* Todd Fries, tfries@umr.edu */
{ 0x000B,"CXD23A Not an IBM ROM (C)Copyright Data Technology Corp 12/03/88",xd_dtc_init_controller,xd_dtc_init_drive," DTC 5150X" }, /* Pat Mackinlay, pat@it.com.au */
- { 0x0008,"07/15/86 (C) Copyright 1986 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Dig. 1002AWX1" }, /* Ian Justman, citrus!ianj@csusac.ecs.csus.edu */
{ 0x0008,"07/15/86(C) Copyright 1986 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Dig. 1002-27X" }, /* Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl */
- { 0x0008,"06/24/88 (C) Copyright 1988 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Dig. 1004A27X" }, /* Dave Thaler, thalerd@engin.umich.edu */
{ 0x0008,"06/24/88(C) Copyright 1988 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Dig. WDXT-GEN2" }, /* Dan Newcombe, newcombe@aa.csc.peachnet.edu */
{ 0x0015,"SEAGATE ST11 BIOS REVISION",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Salvador Abreu, spa@fct.unl.pt */
{ 0x0010,"ST11R BIOS",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Risto Kankkunen, risto.kankkunen@cs.helsinki.fi */
@@ -533,6 +531,8 @@ static void xd_interrupt_handler(int irq, void *dev_id, struct pt_regs * regs)
/* xd_setup_dma: set up the DMA controller for a data transfer */
static u_char xd_setup_dma (u_char mode,u_char *buffer,u_int count)
{
+ unsigned long f;
+
if (nodma)
return (PIO_MODE);
if (((u_int) buffer & 0xFFFF0000) != (((u_int) buffer + count) & 0xFFFF0000)) {
@@ -541,11 +541,15 @@ static u_char xd_setup_dma (u_char mode,u_char *buffer,u_int count)
#endif /* DEBUG_OTHER */
return (PIO_MODE);
}
+
+ f=claim_dma_lock();
disable_dma(xd_dma);
clear_dma_ff(xd_dma);
set_dma_mode(xd_dma,mode);
set_dma_addr(xd_dma,(u_int) buffer);
set_dma_count(xd_dma,count);
+
+ release_dma_lock(f);
return (DMA_MODE); /* use DMA and INT */
}
@@ -583,7 +587,7 @@ static inline u_char xd_waitport (u_short port,u_char flags,u_char mask,u_long t
int success;
xdc_busy = 1;
- while ((success = ((inb(port) & mask) != flags)) && (jiffies < expiry)) {
+ while ((success = ((inb(port) & mask) != flags)) && time_before(jiffies, expiry)) {
xd_timer.expires = jiffies;
cli();
add_timer(&xd_timer);
@@ -597,13 +601,22 @@ static inline u_char xd_waitport (u_short port,u_char flags,u_char mask,u_long t
static inline u_int xd_wait_for_IRQ (void)
{
+ unsigned long flags;
xd_watchdog_int.expires = jiffies + 8 * HZ;
add_timer(&xd_watchdog_int);
+
+ flags=claim_dma_lock();
enable_dma(xd_dma);
+ release_dma_lock(flags);
+
sleep_on(&xd_wait_int);
del_timer(&xd_watchdog_int);
xdc_busy = 0;
+
+ flags=claim_dma_lock();
disable_dma(xd_dma);
+ release_dma_lock(flags);
+
if (xd_error) {
printk("xd: missed IRQ - command aborted\n");
xd_error = 0;
@@ -1154,7 +1167,7 @@ int init_module(void)
for (i = 4; i > 0; i--)
if(((xd[i] = xd[i-1]) >= 0) && !count)
count = i;
- if((xd[0] = count));
+ if((xd[0] = count))
xd_setup(NULL, xd);
xd_geninit(&(struct gendisk) { 0,0,0,0,0,0,0,0,0,0,0 });
if (!xd_drives) {