summaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
commit33263fc5f9ac8e8cb2b22d06af3ce5ac1dd815e4 (patch)
tree2d1b86a40bef0958a68cf1a2eafbeb0667a70543 /drivers/block
parent216f5f51aa02f8b113aa620ebc14a9631a217a00 (diff)
Merge with Linux 2.3.32.
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/Config.in11
-rw-r--r--drivers/block/DAC960.c69
-rw-r--r--drivers/block/DAC960.h20
-rw-r--r--drivers/block/Makefile8
-rw-r--r--drivers/block/acsi.c8
-rw-r--r--drivers/block/aec6210.c259
-rw-r--r--drivers/block/ali14xx.c6
-rw-r--r--drivers/block/alim15x3.c33
-rw-r--r--drivers/block/amiflop.c6
-rw-r--r--drivers/block/ataflop.c6
-rw-r--r--drivers/block/cmd640.c1
-rw-r--r--drivers/block/cpqarray.c32
-rw-r--r--drivers/block/floppy.c12
-rw-r--r--drivers/block/hd.c4
-rw-r--r--drivers/block/hpt366.c24
-rw-r--r--drivers/block/icside.c130
-rw-r--r--drivers/block/ide-cd.c473
-rw-r--r--drivers/block/ide-cd.h40
-rw-r--r--drivers/block/ide-disk.c132
-rw-r--r--drivers/block/ide-dma.c7
-rw-r--r--drivers/block/ide-features.c275
-rw-r--r--drivers/block/ide-floppy.c49
-rw-r--r--drivers/block/ide-geometry.c4
-rw-r--r--drivers/block/ide-pci.c197
-rw-r--r--drivers/block/ide-probe.c27
-rw-r--r--drivers/block/ide-proc.c51
-rw-r--r--drivers/block/ide-tape.c98
-rw-r--r--drivers/block/ide.c824
-rw-r--r--drivers/block/ll_rw_blk.c271
-rw-r--r--drivers/block/loop.c6
-rw-r--r--drivers/block/md.c165
-rw-r--r--drivers/block/nbd.c4
-rw-r--r--drivers/block/paride/pcd.c14
-rw-r--r--drivers/block/paride/pd.c20
-rw-r--r--drivers/block/paride/pf.c20
-rw-r--r--drivers/block/pdc202xx.c22
-rw-r--r--drivers/block/pdc4030.c57
-rw-r--r--drivers/block/piix.c49
-rw-r--r--drivers/block/ps2esdi.c30
-rw-r--r--drivers/block/rd.c52
-rw-r--r--drivers/block/sis5513.c85
-rw-r--r--drivers/block/sl82c105.c3
-rw-r--r--drivers/block/swim3.c6
-rw-r--r--drivers/block/swim_iop.c6
-rw-r--r--drivers/block/via82cxxx.c6
-rw-r--r--drivers/block/xd.c8
-rw-r--r--drivers/block/xd.h2
-rw-r--r--drivers/block/z2ram.c4
48 files changed, 2151 insertions, 1485 deletions
diff --git a/drivers/block/Config.in b/drivers/block/Config.in
index f32c86dc1..8f128700f 100644
--- a/drivers/block/Config.in
+++ b/drivers/block/Config.in
@@ -53,6 +53,9 @@ else
fi
bool ' Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD
bool ' AEC6210 chipset support' CONFIG_BLK_DEV_AEC6210
+ if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" -a "$CONFIG_BLK_DEV_AEC6210" = "y" ]; then
+ bool ' AEC6210 Tuning support (EXPERIMENTAL)' CONFIG_BLK_DEV_AEC6210_TUNING
+ fi
if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then
if [ "$CONFIG_X86" = "y" ]; then
bool ' ALI M15x3 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_ALI15X3
@@ -65,7 +68,10 @@ else
if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" -a "$CONFIG_BLK_DEV_HPT34X" = "y" ]; then
bool ' HPT34X DMA support (EXPERIMENTAL)' CONFIG_BLK_DEV_HPT34X_DMA
fi
- bool ' HPT366 chipset support' CONFIG_BLK_DEV_HPT366
+ bool ' HPT366 chipset support' CONFIG_BLK_DEV_HPT366
+ if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" -a "$CONFIG_BLK_DEV_HPT366" = "y" ]; then
+ bool ' HPT366 Fast Interrupt support (EXPERIMENTAL)' HPT366_FAST_IRQ_PREDICTION
+ fi
fi
if [ "$CONFIG_X86" = "y" ]; then
bool ' Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX
@@ -84,7 +90,7 @@ else
if [ "$CONFIG_BLK_DEV_PDC202XX" = "y" ]; then
bool ' Special UDMA Feature' CONFIG_PDC202XX_FORCE_BURST_BIT
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool ' Special Mode Feature (EXPERIMENTAL)' CONFIG_PDC202XX_FORCE_MASTER_MODE
+ bool ' Special Mode Feature (EXPERIMENTAL)' CONFIG_PDC202XX_FORCE_MASTER_MODE
fi
fi
if [ "$CONFIG_X86" = "y" ]; then
@@ -219,6 +225,7 @@ if [ "$CONFIG_PARIDE" = "y" -o "$CONFIG_PARIDE" = "m" ]; then
fi
if [ "$CONFIG_IDE_CHIPSETS" = "y" -o \
+ "$CONFIG_BLK_DEV_AEC6210" = "y" -o \
"$CONFIG_BLK_DEV_ALI15X3" = "y" -o \
"$CONFIG_BLK_DEV_CMD640" = "y" -o \
"$CONFIG_BLK_DEV_CY82C693" = "y" -o \
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index b2f24a633..6c0120458 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -1026,7 +1026,7 @@ static boolean DAC960_ReportDeviceConfiguration(DAC960_Controller_T *Controller)
static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
{
- static void (*RequestFunctions[DAC960_MaxControllers])(void) =
+ static void (*RequestFunctions[DAC960_MaxControllers])(request_queue_t *) =
{ DAC960_RequestFunction0, DAC960_RequestFunction1,
DAC960_RequestFunction2, DAC960_RequestFunction3,
DAC960_RequestFunction4, DAC960_RequestFunction5,
@@ -1046,8 +1046,8 @@ static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
/*
Initialize the I/O Request Function.
*/
- blk_dev[MajorNumber].request_fn =
- RequestFunctions[Controller->ControllerNumber];
+ blk_init_queue(BLK_DEFAULT_QUEUE(MajorNumber),
+ RequestFunctions[Controller->ControllerNumber]);
/*
Initialize the Disk Partitions array, Partition Sizes array, Block Sizes
array, Max Sectors per Request array, and Max Segments per Request array.
@@ -1113,7 +1113,7 @@ static void DAC960_UnregisterBlockDevice(DAC960_Controller_T *Controller)
/*
Remove the I/O Request Function.
*/
- blk_dev[MajorNumber].request_fn = NULL;
+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MajorNumber));
/*
Remove the Disk Partitions array, Partition Sizes array, Block Sizes
array, Max Sectors per Request array, and Max Segments per Request array.
@@ -1272,7 +1272,7 @@ static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller,
boolean WaitForCommand)
{
IO_Request_T **RequestQueuePointer =
- &blk_dev[DAC960_MAJOR + Controller->ControllerNumber].current_request;
+ &blk_dev[DAC960_MAJOR + Controller->ControllerNumber].request_queue.current_request;
IO_Request_T *Request;
DAC960_Command_T *Command;
char *RequestBuffer;
@@ -1375,7 +1375,7 @@ static inline void DAC960_ProcessRequests(DAC960_Controller_T *Controller)
DAC960_RequestFunction0 is the I/O Request Function for DAC960 Controller 0.
*/
-static void DAC960_RequestFunction0(void)
+static void DAC960_RequestFunction0(request_queue_t * q)
{
DAC960_Controller_T *Controller = DAC960_Controllers[0];
ProcessorFlags_T ProcessorFlags;
@@ -1398,7 +1398,7 @@ static void DAC960_RequestFunction0(void)
DAC960_RequestFunction1 is the I/O Request Function for DAC960 Controller 1.
*/
-static void DAC960_RequestFunction1(void)
+static void DAC960_RequestFunction1(request_queue_t * q)
{
DAC960_Controller_T *Controller = DAC960_Controllers[1];
ProcessorFlags_T ProcessorFlags;
@@ -1421,7 +1421,7 @@ static void DAC960_RequestFunction1(void)
DAC960_RequestFunction2 is the I/O Request Function for DAC960 Controller 2.
*/
-static void DAC960_RequestFunction2(void)
+static void DAC960_RequestFunction2(request_queue_t * q)
{
DAC960_Controller_T *Controller = DAC960_Controllers[2];
ProcessorFlags_T ProcessorFlags;
@@ -1444,7 +1444,7 @@ static void DAC960_RequestFunction2(void)
DAC960_RequestFunction3 is the I/O Request Function for DAC960 Controller 3.
*/
-static void DAC960_RequestFunction3(void)
+static void DAC960_RequestFunction3(request_queue_t * q)
{
DAC960_Controller_T *Controller = DAC960_Controllers[3];
ProcessorFlags_T ProcessorFlags;
@@ -1467,7 +1467,7 @@ static void DAC960_RequestFunction3(void)
DAC960_RequestFunction4 is the I/O Request Function for DAC960 Controller 4.
*/
-static void DAC960_RequestFunction4(void)
+static void DAC960_RequestFunction4(request_queue_t * q)
{
DAC960_Controller_T *Controller = DAC960_Controllers[4];
ProcessorFlags_T ProcessorFlags;
@@ -1490,7 +1490,7 @@ static void DAC960_RequestFunction4(void)
DAC960_RequestFunction5 is the I/O Request Function for DAC960 Controller 5.
*/
-static void DAC960_RequestFunction5(void)
+static void DAC960_RequestFunction5(request_queue_t * q)
{
DAC960_Controller_T *Controller = DAC960_Controllers[5];
ProcessorFlags_T ProcessorFlags;
@@ -1513,7 +1513,7 @@ static void DAC960_RequestFunction5(void)
DAC960_RequestFunction6 is the I/O Request Function for DAC960 Controller 6.
*/
-static void DAC960_RequestFunction6(void)
+static void DAC960_RequestFunction6(request_queue_t * q)
{
DAC960_Controller_T *Controller = DAC960_Controllers[6];
ProcessorFlags_T ProcessorFlags;
@@ -1536,7 +1536,7 @@ static void DAC960_RequestFunction6(void)
DAC960_RequestFunction7 is the I/O Request Function for DAC960 Controller 7.
*/
-static void DAC960_RequestFunction7(void)
+static void DAC960_RequestFunction7(request_queue_t * q)
{
DAC960_Controller_T *Controller = DAC960_Controllers[7];
ProcessorFlags_T ProcessorFlags;
@@ -3474,7 +3474,7 @@ static void DAC960_CreateProcEntries(void)
{
static PROC_DirectoryEntry_T *StatusProcEntry;
int ControllerNumber;
- DAC960_ProcDirectoryEntry = create_proc_entry("driver/rd", S_IFDIR, NULL);
+ DAC960_ProcDirectoryEntry = proc_mkdir("driver/rd", NULL);
StatusProcEntry = create_proc_read_entry("status", 0,
DAC960_ProcDirectoryEntry,
DAC960_ProcReadStatus, NULL);
@@ -3483,36 +3483,20 @@ static void DAC960_CreateProcEntries(void)
ControllerNumber++)
{
DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
- PROC_DirectoryEntry_T *ControllerProcEntry, *InitialStatusProcEntry;
- PROC_DirectoryEntry_T *CurrentStatusProcEntry, *UserCommandProcEntry;
+ PROC_DirectoryEntry_T *ControllerProcEntry;
+ PROC_DirectoryEntry_T *UserCommandProcEntry;
if (Controller == NULL) continue;
- ControllerProcEntry = &Controller->ControllerProcEntry;
- ControllerProcEntry->name = Controller->ControllerName;
- ControllerProcEntry->namelen = strlen(ControllerProcEntry->name);
- ControllerProcEntry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
- proc_register(DAC960_ProcDirectoryEntry, ControllerProcEntry);
- InitialStatusProcEntry = &Controller->InitialStatusProcEntry;
- InitialStatusProcEntry->name = "initial_status";
- InitialStatusProcEntry->namelen = strlen(InitialStatusProcEntry->name);
- InitialStatusProcEntry->mode = S_IFREG | S_IRUGO;
- InitialStatusProcEntry->data = Controller;
- InitialStatusProcEntry->read_proc = DAC960_ProcReadInitialStatus;
- proc_register(ControllerProcEntry, InitialStatusProcEntry);
- CurrentStatusProcEntry = &Controller->CurrentStatusProcEntry;
- CurrentStatusProcEntry->name = "current_status";
- CurrentStatusProcEntry->namelen = strlen(CurrentStatusProcEntry->name);
- CurrentStatusProcEntry->mode = S_IFREG | S_IRUGO;
- CurrentStatusProcEntry->data = Controller;
- CurrentStatusProcEntry->read_proc = DAC960_ProcReadCurrentStatus;
- proc_register(ControllerProcEntry, CurrentStatusProcEntry);
- UserCommandProcEntry = &Controller->UserCommandProcEntry;
- UserCommandProcEntry->name = "user_command";
- UserCommandProcEntry->namelen = strlen(UserCommandProcEntry->name);
- UserCommandProcEntry->mode = S_IFREG | S_IWUSR | S_IRUSR;
- UserCommandProcEntry->data = Controller;
- UserCommandProcEntry->read_proc = DAC960_ProcReadUserCommand;
+ ControllerProcEntry = proc_mkdir(Controller->ControllerName,
+ DAC960_ProcDirectoryEntry);
+ create_proc_read_entry("initial_status",0,ControllerProcEntry,
+ DAC960_ProcReadInitialStatus, Controller);
+ create_proc_read_entry("current_status",0,ControllerProcEntry,
+ DAC960_ProcReadCurrentStatus, Controller);
+ UserCommandProcEntry =
+ create_proc_read_entry("user_command", S_IWUSR|S_IRUSR,
+ ControllerProcEntry,
+ DAC960_ProcReadUserCommand, Controller);
UserCommandProcEntry->write_proc = DAC960_ProcWriteUserCommand;
- proc_register(ControllerProcEntry, UserCommandProcEntry);
}
}
@@ -3524,6 +3508,7 @@ static void DAC960_CreateProcEntries(void)
static void DAC960_DestroyProcEntries(void)
{
+ /* FIXME */
remove_proc_entry("driver/rd", NULL);
}
diff --git a/drivers/block/DAC960.h b/drivers/block/DAC960.h
index 2ff757786..e93448fab 100644
--- a/drivers/block/DAC960.h
+++ b/drivers/block/DAC960.h
@@ -1258,10 +1258,6 @@ typedef struct DAC960_Controller
DAC960_StatusMailbox_T *FirstStatusMailbox;
DAC960_StatusMailbox_T *LastStatusMailbox;
DAC960_StatusMailbox_T *NextStatusMailbox;
- PROC_DirectoryEntry_T ControllerProcEntry;
- PROC_DirectoryEntry_T InitialStatusProcEntry;
- PROC_DirectoryEntry_T CurrentStatusProcEntry;
- PROC_DirectoryEntry_T UserCommandProcEntry;
WaitQueue_T CommandWaitQueue;
DAC960_DCDB_T MonitoringDCDB;
DAC960_Enquiry_T Enquiry[2];
@@ -2212,14 +2208,14 @@ DAC960_V3_ReadStatusRegister(void *ControllerBaseAddress)
static void DAC960_FinalizeController(DAC960_Controller_T *);
static int DAC960_Finalize(NotifierBlock_T *, unsigned long, void *);
-static void DAC960_RequestFunction0(void);
-static void DAC960_RequestFunction1(void);
-static void DAC960_RequestFunction2(void);
-static void DAC960_RequestFunction3(void);
-static void DAC960_RequestFunction4(void);
-static void DAC960_RequestFunction5(void);
-static void DAC960_RequestFunction6(void);
-static void DAC960_RequestFunction7(void);
+static void DAC960_RequestFunction0(request_queue_t *);
+static void DAC960_RequestFunction1(request_queue_t *);
+static void DAC960_RequestFunction2(request_queue_t *);
+static void DAC960_RequestFunction3(request_queue_t *);
+static void DAC960_RequestFunction4(request_queue_t *);
+static void DAC960_RequestFunction5(request_queue_t *);
+static void DAC960_RequestFunction6(request_queue_t *);
+static void DAC960_RequestFunction7(request_queue_t *);
static void DAC960_InterruptHandler(int, void *, Registers_T *);
static void DAC960_QueueMonitoringCommand(DAC960_Command_T *);
static void DAC960_MonitoringTimerFunction(unsigned long);
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 1de4fa581..7225b7120 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -243,11 +243,11 @@ endif
###Collect
ifeq ($(CONFIG_BLK_DEV_IDE),y)
- LX_OBJS += ide.o
+ LX_OBJS += ide.o ide-features.o
L_OBJS += ide-probe.o $(IDE_OBJS)
else
ifeq ($(CONFIG_BLK_DEV_IDE),m)
- MIX_OBJS += ide.o $(IDE_OBJS)
+ MIX_OBJS += ide.o ide-features.o $(IDE_OBJS)
M_OBJS += ide-mod.o ide-probe-mod.o
endif
endif
@@ -374,8 +374,8 @@ endif
include $(TOPDIR)/Rules.make
-ide-mod.o: ide.o $(IDE_OBJS)
- $(LD) $(LD_RFLAG) -r -o $@ ide.o $(IDE_OBJS)
+ide-mod.o: ide.o ide-features.o $(IDE_OBJS)
+ $(LD) $(LD_RFLAG) -r -o $@ ide.o ide-features.o $(IDE_OBJS)
ide-probe-mod.o: ide-probe.o ide-geometry.o
$(LD) $(LD_RFLAG) -r -o $@ ide-probe.o ide-geometry.o
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index 80aa52472..d1631c973 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -360,7 +360,7 @@ static void acsi_times_out( unsigned long dummy );
static void copy_to_acsibuffer( void );
static void copy_from_acsibuffer( void );
static void do_end_requests( void );
-static void do_acsi_request( void );
+static void do_acsi_request( request_queue_t * );
static void redo_acsi_request( void );
static int acsi_ioctl( struct inode *inode, struct file *file, unsigned int
cmd, unsigned long arg );
@@ -938,7 +938,7 @@ static void do_end_requests( void )
*
***********************************************************************/
-static void do_acsi_request( void )
+static void do_acsi_request( request_queue_t * q )
{
stdma_lock( acsi_interrupt, NULL );
@@ -1808,7 +1808,7 @@ int acsi_init( void )
phys_acsi_buffer = virt_to_phys( acsi_buffer );
STramMask = ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000 : 0xff000000;
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */
acsi_gendisk.next = gendisk_head;
gendisk_head = &acsi_gendisk;
@@ -1838,7 +1838,7 @@ void cleanup_module(void)
struct gendisk ** gdp;
del_timer( &acsi_timer );
- blk_dev[MAJOR_NR].request_fn = 0;
+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
atari_stram_free( acsi_buffer );
if (unregister_blkdev( MAJOR_NR, "ad" ) != 0)
diff --git a/drivers/block/aec6210.c b/drivers/block/aec6210.c
index 75bb8657f..c3e51052f 100644
--- a/drivers/block/aec6210.c
+++ b/drivers/block/aec6210.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/aec6210.c Version 0.02 Sept. 3, 1999
+ * linux/drivers/block/aec6210.c Version 0.03 Nov. 12, 1999
*
* Copyright (C) 1998-99 Andre Hedrick (andre@suse.com)
* May be copied or modified under the terms of the GNU General Public License
@@ -34,6 +34,7 @@
* 50: ff ff ff ff 00 06 00 00 00 00 00 00 00 00 00 00
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
@@ -51,10 +52,225 @@
#include <asm/io.h>
#include <asm/irq.h>
+#include "ide_modes.h"
+
+#define ACARD_DEBUG_DRIVE_INFO 1
+
+#ifdef CONFIG_BLK_DEV_AEC6210_TUNING
+
+struct chipset_bus_clock_list_entry {
+ byte xfer_speed;
+ unsigned short chipset_settings;
+ byte ultra_settings;
+};
+
+struct chipset_bus_clock_list_entry aec6210_base [] = {
+ { XFER_UDMA_2, 0x0401, 0x02 },
+ { XFER_UDMA_1, 0x0401, 0x01 },
+ { XFER_UDMA_0, 0x0401, 0x01 },
+
+ { XFER_MW_DMA_2, 0x0401, 0x00 },
+ { XFER_MW_DMA_1, 0x0402, 0x00 },
+ { XFER_MW_DMA_0, 0x070a, 0x00 },
+
+ { XFER_PIO_4, 0x0401, 0x00 },
+ { XFER_PIO_3, 0x0403, 0x00 },
+ { XFER_PIO_2, 0x0708, 0x00 },
+ { XFER_PIO_1, 0x070a, 0x00 },
+ { XFER_PIO_0, 0x0700, 0x00 },
+ { 0, 0x0000, 0x00 }
+};
+
+extern char *ide_xfer_verbose (byte xfer_rate);
+
/*
* TO DO: active tuning and correction of cards without a bios.
*/
+static unsigned short pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
+{
+ for ( ; chipset_table->xfer_speed ; chipset_table++)
+ if (chipset_table->xfer_speed == speed) {
+ return chipset_table->chipset_settings;
+ }
+ return 0x0000;
+}
+
+static byte pci_bus_clock_list_ultra (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
+{
+ for ( ; chipset_table->xfer_speed ; chipset_table++)
+ if (chipset_table->xfer_speed == speed) {
+ return chipset_table->ultra_settings;
+ }
+ return 0x00;
+}
+
+static int aec6210_tune_chipset (ide_drive_t *drive, byte speed)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+
+ int err;
+ byte drive_pci;
+ unsigned short drive_conf = 0x0000;
+ byte ultra = 0x00, ultra_conf = 0x00;
+ byte tmp1 = 0x00, tmp2 = 0x00;
+
+ int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+
+ switch(drive_number) {
+ case 0: drive_pci = 0x40; break;
+ case 1: drive_pci = 0x42; break;
+ case 2: drive_pci = 0x44; break;
+ case 3: drive_pci = 0x46; break;
+ default: return -1;
+ }
+
+ pci_read_config_word(HWIF(drive)->pci_dev, drive_pci, &drive_conf);
+ drive_conf = pci_bus_clock_list(speed, aec6210_base);
+ pci_write_config_word(HWIF(drive)->pci_dev, drive_pci, drive_conf);
+
+ pci_read_config_byte(HWIF(drive)->pci_dev, 0x54, &ultra);
+ tmp1 = ((0x00 << (2*drive_number)) | (ultra & ~(3 << (2*drive_number))));
+ ultra_conf = pci_bus_clock_list_ultra(speed, aec6210_base);
+ tmp2 = ((ultra_conf << (2*drive_number)) | (tmp1 & ~(3 << (2*drive_number))));
+ pci_write_config_byte(HWIF(drive)->pci_dev, 0x54, tmp2);
+
+ err = ide_config_drive_speed(drive, speed);
+
+#if ACARD_DEBUG_DRIVE_INFO
+ printk("%s: %s drive%d 0x04%x 0x02%x 0x02%x 0x02%x 0x02%x\n",
+ drive->name, ide_xfer_verbose(speed), drive_number,
+ drive_conf, ultra, tmp1, ultra_conf, tmp2);
+#endif /* ACARD_DEBUG_DRIVE_INFO */
+
+ return(err);
+}
+
+static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
+{
+ struct hd_driveid *id = drive->id;
+ byte speed = -1;
+
+ if (drive->media != ide_disk)
+ return ((int) ide_dma_off_quietly);
+
+ if (((id->dma_ultra & 0x0010) ||
+ (id->dma_ultra & 0x0008) ||
+ (id->dma_ultra & 0x0004)) && (ultra)) {
+ speed = XFER_UDMA_2;
+ } else if ((id->dma_ultra & 0x0002) && (ultra)) {
+ speed = XFER_UDMA_1;
+ } else if ((id->dma_ultra & 0x0001) && (ultra)) {
+ speed = XFER_UDMA_0;
+ } else if (id->dma_mword & 0x0004) {
+ speed = XFER_MW_DMA_2;
+ } else if (id->dma_mword & 0x0002) {
+ speed = XFER_MW_DMA_1;
+ } else if (id->dma_mword & 0x0001) {
+ speed = XFER_MW_DMA_0;
+ } else if (id->dma_1word & 0x0004) {
+ speed = XFER_SW_DMA_2;
+ } else if (id->dma_1word & 0x0002) {
+ speed = XFER_SW_DMA_1;
+ } else if (id->dma_1word & 0x0001) {
+ speed = XFER_SW_DMA_0;
+ } else {
+ return ((int) ide_dma_off_quietly);
+ }
+ (void) aec6210_tune_chipset(drive, speed);
+
+ return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_off :
+ ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+ ((id->dma_mword >> 8) & 7) ? ide_dma_on :
+ ((id->dma_1word >> 8) & 7) ? ide_dma_on :
+ ide_dma_off_quietly);
+}
+
+static void aec6210_tune_drive (ide_drive_t *drive, byte pio)
+{
+ byte speed;
+
+ switch(pio) {
+ case 5:
+ speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
+ case 4:
+ speed = XFER_PIO_4; break;
+ case 3:
+ speed = XFER_PIO_3; break;
+ case 2:
+ speed = XFER_PIO_2; break;
+ case 1:
+ speed = XFER_PIO_1; break;
+ default:
+ speed = XFER_PIO_0; break;
+ }
+ (void) aec6210_tune_chipset(drive, speed);
+}
+
+static int config_drive_xfer_rate (ide_drive_t *drive)
+{
+ struct hd_driveid *id = drive->id;
+ ide_dma_action_t dma_func = ide_dma_on;
+
+ if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+ /* Consult the list of known "bad" drives */
+ if (ide_dmaproc(ide_dma_bad_drive, drive)) {
+ dma_func = ide_dma_off;
+ goto fast_ata_pio;
+ }
+ dma_func = ide_dma_off_quietly;
+ if (id->field_valid & 4) {
+ if (id->dma_ultra & 0x001F) {
+ /* Force if Capable UltraDMA */
+ dma_func = config_chipset_for_dma(drive, 1);
+ if ((id->field_valid & 2) &&
+ (dma_func != ide_dma_on))
+ goto try_dma_modes;
+ }
+ } else if (id->field_valid & 2) {
+try_dma_modes:
+ if ((id->dma_mword & 0x0007) ||
+ (id->dma_1word & 0x0007)) {
+ /* Force if Capable regular DMA modes */
+ dma_func = config_chipset_for_dma(drive, 0);
+ if (dma_func != ide_dma_on)
+ goto no_dma_set;
+ }
+ } else if (ide_dmaproc(ide_dma_good_drive, drive)) {
+ if (id->eide_dma_time > 150) {
+ goto no_dma_set;
+ }
+ /* Consult the list of known "good" drives */
+ dma_func = config_chipset_for_dma(drive, 0);
+ if (dma_func != ide_dma_on)
+ goto no_dma_set;
+ } else {
+ goto fast_ata_pio;
+ }
+ } else if ((id->capability & 8) || (id->field_valid & 2)) {
+fast_ata_pio:
+ dma_func = ide_dma_off_quietly;
+no_dma_set:
+ aec6210_tune_drive(drive, 5);
+ }
+ return HWIF(drive)->dmaproc(dma_func, drive);
+}
+
+/*
+ * aec6210_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
+ */
+int aec6210_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+ switch (func) {
+ case ide_dma_check:
+ return config_drive_xfer_rate(drive);
+ default:
+ break;
+ }
+ return ide_dmaproc(func, drive); /* use standard DMA stuff */
+}
+#endif /* CONFIG_BLK_DEV_AEC6210_TUNING */
+
unsigned int __init pci_init_aec6210 (struct pci_dev *dev, const char *name)
{
if (dev->resource[PCI_ROM_RESOURCE].start) {
@@ -63,3 +279,44 @@ unsigned int __init pci_init_aec6210 (struct pci_dev *dev, const char *name)
}
return dev->irq;
}
+
+void __init ide_init_aec6210 (ide_hwif_t *hwif)
+{
+#ifdef CONFIG_BLK_DEV_AEC6210_TUNING
+ hwif->tuneproc = &aec6210_tune_drive;
+
+ if (hwif->dma_base) {
+ hwif->dmaproc = &aec6210_dmaproc;
+ hwif->drives[0].autotune = 0;
+ hwif->drives[1].autotune = 0;
+ } else {
+ hwif->drives[0].autotune = 1;
+ hwif->drives[1].autotune = 1;
+ }
+#endif /* CONFIG_BLK_DEV_AEC6210_TUNING */
+}
+
+void __init ide_dmacapable_aec6210 (ide_hwif_t *hwif, unsigned long dmabase)
+{
+ byte dma_new = 0;
+ byte dma_old = inb(dmabase+2);
+ byte reg54h = 0;
+ byte masterdma = hwif->channel ? 0x30 : 0x03;
+ byte slavedma = hwif->channel ? 0xc0 : 0x0c;
+ unsigned long flags;
+
+ __save_flags(flags); /* local CPU only */
+ __cli(); /* local CPU only */
+
+ dma_new = dma_old;
+
+ pci_read_config_byte(hwif->pci_dev, 0x54, &reg54h);
+
+ if (reg54h & masterdma) dma_new |= 0x20;
+ if (reg54h & slavedma) dma_new |= 0x40;
+ if (dma_new != dma_old) outb(dma_new, dmabase+2);
+
+ __restore_flags(flags); /* local CPU only */
+
+ ide_setup_dma(hwif, dmabase, 8);
+}
diff --git a/drivers/block/ali14xx.c b/drivers/block/ali14xx.c
index 46a275305..e86fe61db 100644
--- a/drivers/block/ali14xx.c
+++ b/drivers/block/ali14xx.c
@@ -204,11 +204,11 @@ void init_ali14xx (void)
{
/* auto-detect IDE controller port */
if (!findPort()) {
- printk("ali14xx: not found\n");
+ printk("\nali14xx: not found");
return;
}
- printk("ali14xx: base= 0x%03x, regOn = 0x%02x\n", basePort, regOn);
+ printk("\nali14xx: base= 0x%03x, regOn = 0x%02x", basePort, regOn);
ide_hwifs[0].chipset = ide_ali14xx;
ide_hwifs[1].chipset = ide_ali14xx;
ide_hwifs[0].tuneproc = &ali14xx_tune_drive;
@@ -219,7 +219,7 @@ void init_ali14xx (void)
/* initialize controller registers */
if (!initRegisters()) {
- printk("ali14xx: Chip initialization failed\n");
+ printk("\nali14xx: Chip initialization failed");
return;
}
}
diff --git a/drivers/block/alim15x3.c b/drivers/block/alim15x3.c
index 545361052..ee398e156 100644
--- a/drivers/block/alim15x3.c
+++ b/drivers/block/alim15x3.c
@@ -35,8 +35,8 @@
#include <linux/stat.h>
#include <linux/proc_fs.h>
-static int ali_get_info(char *buffer, char **addr, off_t offset, int count, int dummy);
-extern int (*ali_display_info)(char *, char **, off_t, int, int); /* ide-proc.c */
+static int ali_get_info(char *buffer, char **addr, off_t offset, int count);
+extern int (*ali_display_info)(char *, char **, off_t, int); /* ide-proc.c */
struct pci_dev *bmide_dev;
char *fifo[4] = {
@@ -67,7 +67,7 @@ char *channel_status[8] = {
"error DRQ busy"
};
-static int ali_get_info(char *buffer, char **addr, off_t offset, int count, int dummy)
+static int ali_get_info(char *buffer, char **addr, off_t offset, int count)
{
byte reg53h, reg5xh, reg5yh, reg5xh1, reg5yh1;
unsigned int bibma;
@@ -693,6 +693,31 @@ unsigned int __init pci_init_ali15x3 (struct pci_dev *dev, const char *name)
chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0;
}
+ if (m5229_revision == 0x20) {
+ /*
+ * check M1533 revision (offset 0x08)
+ */
+ pci_read_config_byte(isa_dev, 0x08, &tmpbyte);
+ if (tmpbyte == 0x0A) {
+ unsigned long flags;
+ pci_read_config_byte(dev, 0x4e, &tmpbyte);
+ save_flags(flags);
+ cli();
+ /*
+ * set bit 6
+ */
+ pci_write_config_byte(dev, 0x4e, tmpbyte | 0x40);
+ restore_flags(flags);
+
+ /*
+ * this special version is similar to revision 0xC2
+ * but does not support UDMA66
+ * (cable_80_pin[0] = 0; cable_80_pin[1] = 0;)
+ */
+ m5229_revision = 0xC2;
+ }
+ }
+
return 0;
}
@@ -742,7 +767,7 @@ void __init ide_init_ali15x3 (ide_hwif_t *hwif)
}
hwif->tuneproc = &ali15x3_tune_drive;
- if ((hwif->dma_base) && (m5229_revision >= 0xC1)) {
+ if ((hwif->dma_base) && (m5229_revision >= 0x20)) {
/*
* M1543C or newer for DMAing
*/
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index a3ee727bd..1c36e09f2 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -1484,7 +1484,7 @@ static void redo_fd_request(void)
goto repeat;
}
-static void do_fd_request(void)
+static void do_fd_request(request_queue_t * q)
{
redo_fd_request();
}
@@ -1869,7 +1869,7 @@ int __init amiga_floppy_init(void)
post_write_timer.data = 0;
post_write_timer.function = post_write;
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
blksize_size[MAJOR_NR] = floppy_blocksizes;
blk_size[MAJOR_NR] = floppy_sizes;
@@ -1911,7 +1911,7 @@ void cleanup_module(void)
amiga_chip_free(raw_buf);
blk_size[MAJOR_NR] = NULL;
blksize_size[MAJOR_NR] = NULL;
- blk_dev[MAJOR_NR].request_fn = NULL;
+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
unregister_blkdev(MAJOR_NR, "fd");
}
#endif
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index b8df87205..b47904cdb 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -1529,7 +1529,7 @@ repeat:
}
-void do_fd_request(void)
+void do_fd_request(request_queue_t * q)
{
unsigned long flags;
@@ -2051,7 +2051,7 @@ int __init atari_floppy_init (void)
blk_size[MAJOR_NR] = floppy_sizes;
blksize_size[MAJOR_NR] = floppy_blocksizes;
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
printk(KERN_INFO "Atari floppy driver: max. %cD, %strack buffering\n",
DriveType == 0 ? 'D' : DriveType == 1 ? 'H' : 'E',
@@ -2103,7 +2103,7 @@ void cleanup_module (void)
{
unregister_blkdev(MAJOR_NR, "fd");
- blk_dev[MAJOR_NR].request_fn = 0;
+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
timer_active &= ~(1 << FLOPPY_TIMER);
timer_table[FLOPPY_TIMER].fn = 0;
atari_stram_free( DMABuffer );
diff --git a/drivers/block/cmd640.c b/drivers/block/cmd640.c
index ee6d7c9cc..3e5f56cec 100644
--- a/drivers/block/cmd640.c
+++ b/drivers/block/cmd640.c
@@ -686,6 +686,7 @@ static void cmd640_tune_drive (ide_drive_t *drive, byte mode_wanted)
d.cycle_time,
d.overridden ? " (overriding vendor mode)" : "");
display_clocks(index);
+ return;
}
#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 451463111..5d5799a89 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -22,6 +22,7 @@
* driver, you'll probably need the Compaq Array Controller Interface
* Specificiation (Document number ECG086/1198)
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
@@ -139,14 +140,14 @@ static void do_ida_request(int i);
*/
#define DO_IDA_REQUEST(x) { do_ida_request(x); }
-static void do_ida_request0(void) DO_IDA_REQUEST(0);
-static void do_ida_request1(void) DO_IDA_REQUEST(1);
-static void do_ida_request2(void) DO_IDA_REQUEST(2);
-static void do_ida_request3(void) DO_IDA_REQUEST(3);
-static void do_ida_request4(void) DO_IDA_REQUEST(4);
-static void do_ida_request5(void) DO_IDA_REQUEST(5);
-static void do_ida_request6(void) DO_IDA_REQUEST(6);
-static void do_ida_request7(void) DO_IDA_REQUEST(7);
+static void do_ida_request0(request_queue_t * q) DO_IDA_REQUEST(0);
+static void do_ida_request1(request_queue_t * q) DO_IDA_REQUEST(1);
+static void do_ida_request2(request_queue_t * q) DO_IDA_REQUEST(2);
+static void do_ida_request3(request_queue_t * q) DO_IDA_REQUEST(3);
+static void do_ida_request4(request_queue_t * q) DO_IDA_REQUEST(4);
+static void do_ida_request5(request_queue_t * q) DO_IDA_REQUEST(5);
+static void do_ida_request6(request_queue_t * q) DO_IDA_REQUEST(6);
+static void do_ida_request7(request_queue_t * q) DO_IDA_REQUEST(7);
static void start_io(ctlr_info_t *h);
@@ -222,7 +223,7 @@ struct file_operations ida_fops = {
static void __init ida_procinit(int i)
{
if (proc_array == NULL) {
- proc_array = create_proc_entry("driver/array", S_IFDIR, NULL);
+ proc_array = proc_mkdir("driver/array", NULL);
if (!proc_array) return;
}
@@ -378,7 +379,7 @@ void cleanup_module(void)
*/
void __init cpqarray_init(void)
{
- void (*request_fns[MAX_CTLR])(void) = {
+ void (*request_fns[MAX_CTLR])(request_queue_t *) = {
do_ida_request0, do_ida_request1,
do_ida_request2, do_ida_request3,
do_ida_request4, do_ida_request5,
@@ -479,7 +480,9 @@ void __init cpqarray_init(void)
ida_gendisk[i].sizes = ida_sizes + (i*256);
/* ida_gendisk[i].nr_real is handled by getgeometry */
- blk_dev[MAJOR_NR+i].request_fn = request_fns[i];
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR + i), request_fns[i]);
+ blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR + i), 0);
+
blksize_size[MAJOR_NR+i] = ida_blocksizes + (i*256);
hardsect_size[MAJOR_NR+i] = ida_hardsizes + (i*256);
read_ahead[MAJOR_NR+i] = READ_AHEAD;
@@ -893,10 +896,13 @@ static void do_ida_request(int ctlr)
cmdlist_t *c;
int seg, sect;
char *lastdataend;
+ request_queue_t * q;
struct buffer_head *bh;
struct request *creq;
- creq = blk_dev[MAJOR_NR+ctlr].current_request;
+ q = &blk_dev[MAJOR_NR+ctlr].request_queue;
+
+ creq = q->current_request;
if (creq == NULL || creq->rq_status == RQ_INACTIVE)
goto doreq_done;
@@ -973,7 +979,7 @@ DBGPX( printk("More to do on same request %p\n", creq); );
} else {
DBGPX( printk("Done with %p, queueing %p\n", creq, creq->next); );
creq->rq_status = RQ_INACTIVE;
- blk_dev[MAJOR_NR+ctlr].current_request = creq->next;
+ q->current_request = creq->next;
wake_up(&wait_for_request);
}
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index d74fdc369..9a204c0a8 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -1169,7 +1169,7 @@ static int output_byte(char byte)
/* gets the response from the fdc */
static int result(void)
{
- int i, status;
+ int i, status=0;
for(i=0; i < MAX_REPLIES; i++) {
if ((status = wait_til_ready()) < 0)
@@ -2932,7 +2932,7 @@ static void process_fd_request(void)
schedule_bh( (void *)(void *) redo_fd_request);
}
-static void do_fd_request(void)
+static void do_fd_request(request_queue_t * q)
{
if(usage_count == 0) {
printk("warning: usage count=0, CURRENT=%p exiting\n", CURRENT);
@@ -4132,7 +4132,7 @@ int __init floppy_init(void)
blk_size[MAJOR_NR] = floppy_sizes;
blksize_size[MAJOR_NR] = floppy_blocksizes;
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT);
config_types();
@@ -4161,7 +4161,7 @@ int __init floppy_init(void)
fdc = 0; /* reset fdc in case of unexpected interrupt */
if (floppy_grab_irq_and_dma()){
del_timer(&fd_timeout);
- blk_dev[MAJOR_NR].request_fn = NULL;
+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
unregister_blkdev(MAJOR_NR,"fd");
del_timer(&fd_timeout);
return -EBUSY;
@@ -4227,7 +4227,7 @@ int __init floppy_init(void)
schedule();
if (usage_count)
floppy_release_irq_and_dma();
- blk_dev[MAJOR_NR].request_fn = NULL;
+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
unregister_blkdev(MAJOR_NR,"fd");
}
return have_no_fdc;
@@ -4450,7 +4450,7 @@ void cleanup_module(void)
unregister_blkdev(MAJOR_NR, "fd");
- blk_dev[MAJOR_NR].request_fn = 0;
+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
/* eject disk, if any */
dummy = fd_eject(0);
}
diff --git a/drivers/block/hd.c b/drivers/block/hd.c
index 49527026a..8cf37c3de 100644
--- a/drivers/block/hd.c
+++ b/drivers/block/hd.c
@@ -585,7 +585,7 @@ repeat:
panic("unknown hd-command");
}
-static void do_hd_request (void)
+static void do_hd_request (request_queue_t * q)
{
disable_irq(HD_IRQ);
hd_request();
@@ -813,7 +813,7 @@ int __init hd_init(void)
printk("hd: unable to get major %d for hard disk\n",MAJOR_NR);
return -1;
}
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */
hd_gendisk.next = gendisk_head;
gendisk_head = &hd_gendisk;
diff --git a/drivers/block/hpt366.c b/drivers/block/hpt366.c
index d45b5f719..30bc3218c 100644
--- a/drivers/block/hpt366.c
+++ b/drivers/block/hpt366.c
@@ -218,7 +218,8 @@ static int config_chipset_for_dma (ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
byte speed = 0x00;
- unsigned int reg40 = 0;
+ byte reg51h = 0;
+ unsigned int reg40 = 0;
int rval;
if ((id->dma_ultra & 0x0010) &&
@@ -258,15 +259,22 @@ static int config_chipset_for_dma (ide_drive_t *drive)
return ((int) ide_dma_off_quietly);
}
- /* Disable the "fast interrupt" prediction.
+ pci_read_config_byte(HWIF(drive)->pci_dev, 0x51, &reg51h);
+
+#ifdef HPT366_FAST_IRQ_PREDICTION
+ /*
+ * Some drives prefer/allow for the method of handling interrupts.
+ */
+ if (!(reg51h & 0x80))
+ pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, reg51h|0x80);
+#else /* ! HPT366_FAST_IRQ_PREDICTION */
+ /*
+ * Disable the "fast interrupt" prediction.
* Instead, always wait for the real interrupt from the drive!
*/
- {
- byte reg51h = 0;
- pci_read_config_byte(HWIF(drive)->pci_dev, 0x51, &reg51h);
- if (reg51h & 0x80)
- pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, reg51h & ~0x80);
- }
+ if (reg51h & 0x80)
+ pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, reg51h & ~0x80);
+#endif /* HPT366_FAST_IRQ_PREDICTION */
/*
* Preserve existing PIO settings:
diff --git a/drivers/block/icside.c b/drivers/block/icside.c
index b83781457..d86a990f7 100644
--- a/drivers/block/icside.c
+++ b/drivers/block/icside.c
@@ -210,24 +210,11 @@ static iftype_t icside_identifyif (struct expansion_card *ec)
/*
* SG-DMA support.
*
- * Similar to the BM-DMA, but we use the RiscPCs IOMD
- * DMA controllers. There is only one DMA controller
- * per card, which means that only one drive can be
- * accessed at one time. NOTE! We do not inforce that
- * here, but we rely on the main IDE driver spotting
- * that both interfaces use the same IRQ, which should
- * guarantee this.
- *
- * We are limited by the drives IOR/IOW pulse time.
- * The closest that we can get to the requirements is
- * a type C cycle for both mode 1 and mode 2. However,
- * this does give a burst of 8MB/s.
- *
- * This has been tested with a couple of Conner
- * Peripherals 1080MB CFS1081A drives, one on each
- * interface, which deliver about 2MB/s each. I
- * believe that this is limited by the lack of
- * on-board drive cache.
+ * Similar to the BM-DMA, but we use the RiscPCs IOMD DMA controllers.
+ * There is only one DMA controller per card, which means that only
+ * one drive can be accessed at one time. NOTE! We do not enforce that
+ * here, but we rely on the main IDE driver spotting that both
+ * interfaces use the same IRQ, which should guarantee this.
*/
#define TABLE_SIZE 2048
@@ -286,27 +273,43 @@ icside_build_dmatable(ide_drive_t *drive, int reading)
}
static int
-icside_config_drive(ide_drive_t *drive, int mode)
+icside_config_if(ide_drive_t *drive, int xfer_mode)
{
- int speed, err;
-
- if (mode == 2) {
- speed = XFER_MW_DMA_2;
+ int func = ide_dma_off;
+
+ switch (xfer_mode) {
+ case XFER_MW_DMA_2:
+ /*
+ * The cycle time is limited to 250ns by the r/w
+ * pulse width (90ns), however we should still
+ * have a maximum burst transfer rate of 8MB/s.
+ */
drive->drive_data = 250;
- } else {
- speed = XFER_MW_DMA_1;
+ break;
+
+ case XFER_MW_DMA_1:
drive->drive_data = 250;
- }
+ break;
- err = ide_config_drive_speed(drive, (byte) speed);
+ case XFER_MW_DMA_0:
+ drive->drive_data = 480;
+ break;
- if (err == 0) {
- drive->id->dma_mword &= 0x00ff;
- drive->id->dma_mword |= 256 << mode;
- } else
+ default:
drive->drive_data = 0;
+ break;
+ }
+
+ if (drive->drive_data &&
+ ide_config_drive_speed(drive, (byte) xfer_mode) == 0)
+ func = ide_dma_on;
+ else
+ drive->drive_data = 480;
+
+ printk("%s: %s selected (peak %dMB/s)\n", drive->name,
+ ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data);
- return err;
+ return func;
}
static int
@@ -315,34 +318,51 @@ icside_dma_check(ide_drive_t *drive)
struct hd_driveid *id = drive->id;
ide_hwif_t *hwif = HWIF(drive);
int autodma = hwif->autodma;
+ int xfer_mode = XFER_PIO_2;
+ int func = ide_dma_off_quietly;
- if (id && (id->capability & 1) && autodma) {
- int dma_mode = 0;
+ if (!id || !(id->capability & 1) || !autodma)
+ goto out;
- /* Consult the list of known "bad" drives */
- if (ide_dmaproc(ide_dma_bad_drive, 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 && id->dma_ultra & 7)
- dma_mode = 2;
-
- /* Enable DMA on any drive that has mode1
- * or mode2 multiword DMA enabled
- */
- if (id->field_valid & 2 && id->dma_mword & 6)
- dma_mode = id->dma_mword & 4 ? 2 : 1;
+ /*
+ * Consult the list of known "bad" drives
+ */
+ if (ide_dmaproc(ide_dma_bad_drive, drive)) {
+ func = ide_dma_off;
+ goto out;
+ }
- /* Consult the list of known "good" drives */
- if (ide_dmaproc(ide_dma_good_drive, drive))
- dma_mode = 1;
+ /*
+ * Enable DMA on any drive that has multiword DMA
+ */
+ if (id->field_valid & 2) {
+ if (id->dma_mword & 4) {
+ xfer_mode = XFER_MW_DMA_2;
+ func = ide_dma_on;
+ } else if (id->dma_mword & 2) {
+ xfer_mode = XFER_MW_DMA_1;
+ func = ide_dma_on;
+ } else if (id->dma_mword & 1) {
+ xfer_mode = XFER_MW_DMA_0;
+ func = ide_dma_on;
+ }
+ goto out;
+ }
- if (dma_mode && icside_config_drive(drive, dma_mode) == 0)
- return hwif->dmaproc(ide_dma_on, drive);
+ /*
+ * Consult the list of known "good" drives
+ */
+ if (ide_dmaproc(ide_dma_good_drive, drive)) {
+ if (id->eide_dma_time > 150)
+ goto out;
+ xfer_mode = XFER_MW_DMA_1;
+ func = ide_dma_on;
}
- return hwif->dmaproc(ide_dma_off_quietly, drive);
+
+out:
+ func = icside_config_if(drive, xfer_mode);
+
+ return hwif->dmaproc(func, drive);
}
static int
diff --git a/drivers/block/ide-cd.c b/drivers/block/ide-cd.c
index e3cce8eb4..6b71cd7bf 100644
--- a/drivers/block/ide-cd.c
+++ b/drivers/block/ide-cd.c
@@ -130,7 +130,7 @@
* 3.15 July 2, 1996 -- Added support for Sanyo 3 CD changers
* from Ben Galliart <bgallia@luc.edu> with
* special help from Jeff Lightfoot
- * <jeffml@netcom.com>
+ * <jeffml@pobox.com>
* 3.15a July 9, 1996 -- Improved Sanyo 3 CD changer identification
* 3.16 Jul 28, 1996 -- Fix from Gadi to reduce kernel stack usage for ioctl.
* 3.17 Sep 17, 1996 -- Tweak audio reads for some drives.
@@ -276,7 +276,6 @@
#define IDECD_VERSION "4.56"
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
@@ -314,8 +313,7 @@ static void cdrom_saw_media_change (ide_drive_t *drive)
static
-void cdrom_analyze_sense_data (ide_drive_t *drive,
- struct atapi_request_sense *reqbuf,
+void cdrom_analyze_sense_data (ide_drive_t *drive, struct request_sense *reqbuf,
struct packet_command *failed_command)
{
if (reqbuf->sense_key == NOT_READY ||
@@ -432,27 +430,21 @@ void cdrom_analyze_sense_data (ide_drive_t *drive,
* In the case of NOT_READY, if SKSV is set the drive can
* give us nice ETA readings.
*/
- if (reqbuf->sense_key == NOT_READY &&
- (reqbuf->sense_key_specific[0] & 0x80)) {
- int progress = (reqbuf->sense_key_specific[1] << 8 |
- reqbuf->sense_key_specific[2]) * 100;
+ if (reqbuf->sense_key == NOT_READY && (reqbuf->sks[0] & 0x80)) {
+ int progress = (reqbuf->sks[1] << 8 | reqbuf->sks[2]) * 100;
printk(" Command is %02d%% complete\n", progress / 0xffff);
}
if (reqbuf->sense_key == ILLEGAL_REQUEST &&
- (reqbuf->sense_key_specific[0] & 0x80) != 0) {
+ (reqbuf->sks[0] & 0x80) != 0) {
printk (" Error in %s byte %d",
- (reqbuf->sense_key_specific[0] & 0x40) != 0
- ? "command packet"
- : "command data",
- (reqbuf->sense_key_specific[1] << 8) +
- reqbuf->sense_key_specific[2]);
-
- if ((reqbuf->sense_key_specific[0] & 0x40) != 0) {
- printk (" bit %d",
- reqbuf->sense_key_specific[0] & 0x07);
- }
+ (reqbuf->sks[0] & 0x40) != 0 ?
+ "command packet" : "command data",
+ (reqbuf->sks[1] << 8) + reqbuf->sks[2]);
+
+ if ((reqbuf->sks[0] & 0x40) != 0)
+ printk (" bit %d", reqbuf->sks[0] & 0x07);
printk ("\n");
}
@@ -477,39 +469,25 @@ void cdrom_analyze_sense_data (ide_drive_t *drive,
static void cdrom_queue_request_sense (ide_drive_t *drive,
struct semaphore *sem,
- struct atapi_request_sense *reqbuf,
struct packet_command *failed_command)
{
struct cdrom_info *info = drive->driver_data;
struct request *rq;
struct packet_command *pc;
- int len;
-
- /* If the request didn't explicitly specify where
- to put the sense data, use the statically allocated structure. */
- if (reqbuf == NULL)
- reqbuf = &info->sense_data;
/* Make up a new request to retrieve sense information. */
-
pc = &info->request_sense_pc;
- memset (pc, 0, sizeof (*pc));
-
- /* The request_sense structure has an odd number of (16-bit) words,
- which won't work well with 32-bit transfers. However, we don't care
- about the last two bytes, so just truncate the structure down
- to an even length. */
- len = sizeof (*reqbuf) / 4;
- len *= 4;
+ memset(pc, 0, sizeof (*pc));
pc->c[0] = GPCMD_REQUEST_SENSE;
- pc->c[4] = (unsigned char) len;
- pc->buffer = (char *)reqbuf;
- pc->buflen = len;
- pc->sense_data = (struct atapi_request_sense *)failed_command;
- /* stuff the sense request in front of our current request */
+ /* just get the first 18 bytes of the sense info, there might not
+ * be more available */
+ pc->c[4] = pc->buflen = 18;
+ pc->buffer = (char *)&info->sense_data;
+ pc->sense_data = (struct request_sense *)failed_command;
+ /* stuff the sense request in front of our current request */
rq = &info->request_sense_request;
ide_init_drive_cmd (rq);
rq->cmd = REQUEST_SENSE_COMMAND;
@@ -527,7 +505,7 @@ static void cdrom_end_request (int uptodate, ide_drive_t *drive)
struct packet_command *pc = (struct packet_command *)
rq->buffer;
cdrom_analyze_sense_data (drive,
- (struct atapi_request_sense *) (pc->buffer - pc->c[4]),
+ (struct request_sense *) (pc->buffer - pc->c[4]),
(struct packet_command *) pc->sense_data);
}
if (rq->cmd == READ && !rq->current_nr_sectors)
@@ -539,7 +517,7 @@ static void cdrom_end_request (int uptodate, ide_drive_t *drive)
/* Returns 0 if the request should be continued.
Returns 1 if the request was ended. */
-static int cdrom_decode_status (ide_drive_t *drive, int good_stat,
+static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive, int good_stat,
int *stat_ret)
{
struct request *rq = HWGROUP(drive)->rq;
@@ -570,7 +548,7 @@ static int cdrom_decode_status (ide_drive_t *drive, int good_stat,
pc->stat = 1;
cdrom_end_request (1, drive);
- ide_error (drive, "request sense failure", stat);
+ *startstop = ide_error (drive, "request sense failure", stat);
return 1;
} else if (cmd == PACKET_COMMAND) {
@@ -610,8 +588,7 @@ static int cdrom_decode_status (ide_drive_t *drive, int good_stat,
cdrom_end_request (1, drive);
if ((stat & ERR_STAT) != 0)
- cdrom_queue_request_sense (drive, sem,
- pc->sense_data, pc);
+ cdrom_queue_request_sense(drive, sem, pc);
} else {
/* Handle errors from READ requests. */
@@ -640,7 +617,7 @@ static int cdrom_decode_status (ide_drive_t *drive, int good_stat,
} else if ((err & ~ABRT_ERR) != 0) {
/* Go to the default handler
for other errors. */
- ide_error (drive, "cdrom_decode_status", stat);
+ *startstop = ide_error (drive, "cdrom_decode_status", stat);
return 1;
} else if ((++rq->errors > ERROR_MAX)) {
/* We've racked up too many retries. Abort. */
@@ -650,12 +627,12 @@ static int cdrom_decode_status (ide_drive_t *drive, int good_stat,
/* If we got a CHECK_CONDITION status,
queue a request sense command. */
if ((stat & ERR_STAT) != 0)
- cdrom_queue_request_sense (drive,
- NULL, NULL, NULL);
+ cdrom_queue_request_sense(drive, NULL, NULL);
}
}
/* Retry, or handle the next request. */
+ *startstop = ide_stopped;
return 1;
}
@@ -665,7 +642,6 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
struct packet_command *pc = (struct packet_command *) rq->buffer;
unsigned long wait = 0;
- printk("in expiry\n");
/* blank and format can take an extremly long time to
* complete, if the IMMED bit was not set.
*/
@@ -682,13 +658,15 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
called when the interrupt from the drive arrives. Otherwise, HANDLER
will be called immediately after the drive is prepared for the transfer. */
-static int cdrom_start_packet_command (ide_drive_t *drive, int xferlen,
+static ide_startstop_t cdrom_start_packet_command (ide_drive_t *drive, int xferlen,
ide_handler_t *handler)
{
+ ide_startstop_t startstop;
struct cdrom_info *info = drive->driver_data;
/* Wait for the controller to be idle. */
- if (ide_wait_stat(drive, 0, BUSY_STAT, WAIT_READY)) return 1;
+ if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY))
+ return startstop;
if (info->dma)
info->dma = !HWIF(drive)->dmaproc(ide_dma_read, drive);
@@ -709,12 +687,11 @@ static int cdrom_start_packet_command (ide_drive_t *drive, int xferlen,
if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry);
OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
+ return ide_started;
} else {
OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
- (*handler) (drive);
+ return (*handler) (drive);
}
-
- return 0;
}
/* Send a packet command to DRIVE described by CMD_BUF and CMD_LEN.
@@ -722,7 +699,7 @@ static int cdrom_start_packet_command (ide_drive_t *drive, int xferlen,
by cdrom_start_packet_command.
HANDLER is the interrupt handler to call when the command completes
or there's data ready. */
-static int cdrom_transfer_packet_command (ide_drive_t *drive,
+static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
unsigned char *cmd_buf, int cmd_len,
ide_handler_t *handler)
{
@@ -730,14 +707,16 @@ static int cdrom_transfer_packet_command (ide_drive_t *drive,
/* Here we should have been called after receiving an interrupt
from the device. DRQ should how be set. */
int stat_dum;
+ ide_startstop_t startstop;
/* Check for errors. */
- if (cdrom_decode_status (drive, DRQ_STAT, &stat_dum))
- return 1;
+ if (cdrom_decode_status (&startstop, drive, DRQ_STAT, &stat_dum))
+ return startstop;
} else {
+ ide_startstop_t startstop;
/* Otherwise, we must wait for DRQ to get set. */
- if (ide_wait_stat (drive, DRQ_STAT, BUSY_STAT, WAIT_READY))
- return 1;
+ if (ide_wait_stat (&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY))
+ return startstop;
}
/* Arm the interrupt handler. */
@@ -746,7 +725,7 @@ static int cdrom_transfer_packet_command (ide_drive_t *drive,
/* Send the command to the device. */
atapi_output_bytes (drive, cmd_buf, cmd_len);
- return 0;
+ return ide_started;
}
@@ -843,12 +822,13 @@ int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
/*
* Interrupt routine. Called when a read request has completed.
*/
-static void cdrom_read_intr (ide_drive_t *drive)
+static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
{
int stat;
int ireason, len, sectors_to_transfer, nskip;
struct cdrom_info *info = drive->driver_data;
int i, dma = info->dma, dma_error = 0;
+ ide_startstop_t startstop;
struct request *rq = HWGROUP(drive)->rq;
@@ -859,19 +839,18 @@ static void cdrom_read_intr (ide_drive_t *drive)
HWIF(drive)->dmaproc(ide_dma_off, drive);
}
- if (cdrom_decode_status (drive, 0, &stat))
- return;
+ if (cdrom_decode_status (&startstop, drive, 0, &stat))
+ return startstop;
if (dma) {
- if (dma_error) {
- ide_error (drive, "dma error", stat);
- return;
- }
- for (i = rq->nr_sectors; i > 0;) {
- i -= rq->current_nr_sectors;
- ide_end_request(1, HWGROUP(drive));
- }
- return;
+ if (!dma_error) {
+ for (i = rq->nr_sectors; i > 0;) {
+ i -= rq->current_nr_sectors;
+ ide_end_request(1, HWGROUP(drive));
+ }
+ return ide_stopped;
+ } else
+ return ide_error (drive, "dma error", stat);
}
/* Read the interrupt reason and the transfer length. */
@@ -888,11 +867,12 @@ static void cdrom_read_intr (ide_drive_t *drive)
cdrom_end_request (0, drive);
} else
cdrom_end_request (1, drive);
- return;
+ return ide_stopped;
}
/* Check that the drive is expecting to do the same thing we are. */
- if (cdrom_read_check_ireason (drive, len, ireason)) return;
+ if (cdrom_read_check_ireason (drive, len, ireason))
+ return ide_stopped;
/* Assume that the drive will always provide data in multiples
of at least SECTOR_SIZE, as it gets hairy to keep track
@@ -907,7 +887,7 @@ static void cdrom_read_intr (ide_drive_t *drive)
CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1;
}
cdrom_end_request (0, drive);
- return;
+ return ide_stopped;
}
/* The number of sectors we need to read from the drive. */
@@ -967,6 +947,7 @@ static void cdrom_read_intr (ide_drive_t *drive)
/* Done moving data!
Wait for another interrupt. */
ide_set_handler(drive, &cdrom_read_intr, WAIT_CMD, NULL);
+ return ide_started;
}
/*
@@ -1031,7 +1012,7 @@ static int cdrom_read_from_buffer (ide_drive_t *drive)
* However, for drq_interrupt devices, it is called from an interrupt
* when the drive is ready to accept the command.
*/
-static void cdrom_start_read_continuation (ide_drive_t *drive)
+static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive)
{
struct packet_command pc;
struct request *rq = HWGROUP(drive)->rq;
@@ -1058,7 +1039,7 @@ static void cdrom_start_read_continuation (ide_drive_t *drive)
printk ("%s: cdrom_start_read_continuation: buffer botch (%lu)\n",
drive->name, rq->current_nr_sectors);
cdrom_end_request (0, drive);
- return;
+ return ide_stopped;
}
sector -= nskip;
nsect += nskip;
@@ -1083,7 +1064,7 @@ static void cdrom_start_read_continuation (ide_drive_t *drive)
put_unaligned(htonl (frame), (unsigned int *) &pc.c[2]);
/* Send the command to the drive and return. */
- (void) cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c),
+ return cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c),
&cdrom_read_intr);
}
@@ -1092,14 +1073,15 @@ static void cdrom_start_read_continuation (ide_drive_t *drive)
#define IDECD_SEEK_TIMER (5 * WAIT_MIN_SLEEP) /* 100 ms */
#define IDECD_SEEK_TIMEOUT WAIT_CMD /* 10 sec */
-static void cdrom_seek_intr (ide_drive_t *drive)
+static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
{
struct cdrom_info *info = drive->driver_data;
int stat;
static int retry = 10;
+ ide_startstop_t startstop;
- if (cdrom_decode_status (drive, 0, &stat))
- return;
+ if (cdrom_decode_status (&startstop, drive, 0, &stat))
+ return startstop;
CDROM_CONFIG_FLAGS(drive)->seeking = 1;
if (retry && jiffies - info->start_seek > IDECD_SEEK_TIMER) {
@@ -1108,9 +1090,10 @@ static void cdrom_seek_intr (ide_drive_t *drive)
drive->dsc_overlap = 0;
}
}
+ return ide_stopped;
}
-static void cdrom_start_seek_continuation (ide_drive_t *drive)
+static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive)
{
struct packet_command pc;
struct request *rq = HWGROUP(drive)->rq;
@@ -1125,16 +1108,16 @@ static void cdrom_start_seek_continuation (ide_drive_t *drive)
memset (&pc.c, 0, sizeof (pc.c));
pc.c[0] = GPCMD_SEEK;
put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]);
- (void) cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c), &cdrom_seek_intr);
+ return cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c), &cdrom_seek_intr);
}
-static void cdrom_start_seek (ide_drive_t *drive, unsigned int block)
+static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block)
{
struct cdrom_info *info = drive->driver_data;
info->dma = 0;
info->start_seek = jiffies;
- cdrom_start_packet_command (drive, 0, cdrom_start_seek_continuation);
+ return cdrom_start_packet_command (drive, 0, cdrom_start_seek_continuation);
}
/* Fix up a possibly partially-processed request so that we can
@@ -1153,7 +1136,7 @@ static void restore_request (struct request *rq)
/*
* Start a read request from the CD-ROM.
*/
-static void cdrom_start_read (ide_drive_t *drive, unsigned int block)
+static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block)
{
struct cdrom_info *info = drive->driver_data;
struct request *rq = HWGROUP(drive)->rq;
@@ -1173,8 +1156,9 @@ static void cdrom_start_read (ide_drive_t *drive, unsigned int block)
/* Satisfy whatever we can of this request from our cached sector. */
if (cdrom_read_from_buffer(drive))
- return;
+ return ide_stopped;
+ /* Clear the local sector buffer. */
info->nsectors_buffered = 0;
/* use dma, if possible. */
@@ -1185,7 +1169,7 @@ static void cdrom_start_read (ide_drive_t *drive, unsigned int block)
info->dma = 0;
/* Start sending the read request to the drive. */
- cdrom_start_packet_command(drive, 32768, cdrom_start_read_continuation);
+ return cdrom_start_packet_command(drive, 32768, cdrom_start_read_continuation);
}
/****************************************************************************
@@ -1193,20 +1177,22 @@ static void cdrom_start_read (ide_drive_t *drive, unsigned int block)
*/
/* Forward declarations. */
-static int
-cdrom_lockdoor (ide_drive_t *drive, int lockflag,
- struct atapi_request_sense *reqbuf);
+static int cdrom_lockdoor(ide_drive_t *drive, int lockflag);
/* Interrupt routine for packet command completion. */
-static void cdrom_pc_intr (ide_drive_t *drive)
+static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
{
int ireason, len, stat, thislen;
struct request *rq = HWGROUP(drive)->rq;
struct packet_command *pc = (struct packet_command *)rq->buffer;
+ struct cdrom_info *info = drive->driver_data;
+ ide_startstop_t startstop;
+
+ pc->sense_data = &info->sense_data;
/* Check for errors. */
- if (cdrom_decode_status (drive, 0, &stat))
- return;
+ if (cdrom_decode_status (&startstop, drive, 0, &stat))
+ return startstop;
/* Read the interrupt reason and the transfer length. */
ireason = IN_BYTE (IDE_NSECTOR_REG);
@@ -1239,7 +1225,7 @@ static void cdrom_pc_intr (ide_drive_t *drive)
pc->stat = 1;
cdrom_end_request (1, drive);
}
- return;
+ return ide_stopped;
}
/* Figure out how much data to transfer. */
@@ -1290,21 +1276,22 @@ static void cdrom_pc_intr (ide_drive_t *drive)
/* Now we wait for another interrupt. */
ide_set_handler (drive, &cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry);
+ return ide_started;
}
-static void cdrom_do_pc_continuation (ide_drive_t *drive)
+static ide_startstop_t cdrom_do_pc_continuation (ide_drive_t *drive)
{
struct request *rq = HWGROUP(drive)->rq;
struct packet_command *pc = (struct packet_command *)rq->buffer;
/* Send the command to the drive and return. */
- cdrom_transfer_packet_command (drive, pc->c,
+ return cdrom_transfer_packet_command (drive, pc->c,
sizeof (pc->c), &cdrom_pc_intr);
}
-static void cdrom_do_packet_command (ide_drive_t *drive)
+static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive)
{
int len;
struct request *rq = HWGROUP(drive)->rq;
@@ -1316,7 +1303,7 @@ static void cdrom_do_packet_command (ide_drive_t *drive)
len = pc->buflen;
/* Start sending the command to the drive. */
- cdrom_start_packet_command (drive, len, cdrom_do_pc_continuation);
+ return cdrom_start_packet_command (drive, len, cdrom_do_pc_continuation);
}
@@ -1330,18 +1317,11 @@ void cdrom_sleep (int time)
}
static
-int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc)
+int cdrom_queue_packet_command(ide_drive_t *drive, struct packet_command *pc)
{
- struct atapi_request_sense my_reqbuf;
int retries = 10;
struct request req;
- /* If our caller has not provided a place to stick any sense data,
- use our own area. */
- if (pc->sense_data == NULL)
- pc->sense_data = &my_reqbuf;
- pc->sense_data->sense_key = 0;
-
/* Start of retry loop. */
do {
ide_init_drive_cmd (&req);
@@ -1356,7 +1336,7 @@ int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc)
/* The request failed. Retry if it was due to a unit
attention status
(usually means media was changed). */
- struct atapi_request_sense *reqbuf = pc->sense_data;
+ struct request_sense *reqbuf = pc->sense_data;
if (reqbuf->sense_key == UNIT_ATTENTION)
cdrom_saw_media_change (drive);
@@ -1377,75 +1357,73 @@ int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc)
} while (pc->stat != 0 && retries >= 0);
/* Return an error if the command failed. */
- if (pc->stat != 0)
+ if (pc->stat)
return -EIO;
- else {
- /* The command succeeded. If it was anything other than
- a request sense, eject, or door lock command,
- and we think that the door is presently unlocked, lock it
- again. (The door was probably unlocked via an explicit
- CDROMEJECT ioctl.) */
- if (CDROM_STATE_FLAGS (drive)->door_locked == 0 &&
- (pc->c[0] != GPCMD_TEST_UNIT_READY &&
- pc->c[0] != GPCMD_REQUEST_SENSE &&
- pc->c[0] != GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL &&
- pc->c[0] != GPCMD_START_STOP_UNIT &&
- pc->c[0] != GPCMD_MODE_SENSE_10 &&
- pc->c[0] != GPCMD_MODE_SELECT_10)) {
- (void) cdrom_lockdoor (drive, 1, NULL);
- }
- return 0;
+
+ /* The command succeeded. If it was anything other than
+ a request sense, eject, or door lock command,
+ and we think that the door is presently unlocked, lock it
+ again. (The door was probably unlocked via an explicit
+ CDROMEJECT ioctl.) */
+ if (CDROM_STATE_FLAGS (drive)->door_locked == 0 &&
+ (pc->c[0] != GPCMD_TEST_UNIT_READY &&
+ pc->c[0] != GPCMD_REQUEST_SENSE &&
+ pc->c[0] != GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL &&
+ pc->c[0] != GPCMD_START_STOP_UNIT &&
+ pc->c[0] != GPCMD_MODE_SENSE_10 &&
+ pc->c[0] != GPCMD_MODE_SELECT_10)) {
+ (void) cdrom_lockdoor (drive, 1);
}
+ return 0;
}
/****************************************************************************
* cdrom driver request routine.
*/
-static
-void ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long block)
+static ide_startstop_t
+ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long block)
{
+ ide_startstop_t action;
struct cdrom_info *info = drive->driver_data;
switch (rq->cmd) {
- case READ: {
- if (CDROM_CONFIG_FLAGS(drive)->seeking) {
- unsigned long elpased = jiffies - info->start_seek;
- int stat = GET_STAT();
-
- if ((stat & SEEK_STAT) != SEEK_STAT) {
- if (elpased < IDECD_SEEK_TIMEOUT) {
- ide_stall_queue(drive, IDECD_SEEK_TIMER);
- return;
+ case READ: {
+ if (CDROM_CONFIG_FLAGS(drive)->seeking) {
+ unsigned long elpased = jiffies - info->start_seek;
+ int stat = GET_STAT();
+
+ if ((stat & SEEK_STAT) != SEEK_STAT) {
+ if (elpased < IDECD_SEEK_TIMEOUT) {
+ ide_stall_queue(drive, IDECD_SEEK_TIMER);
+ return ide_stopped;
+ }
+ printk ("%s: DSC timeout\n", drive->name);
}
- printk ("%s: DSC timeout\n", drive->name);
+ CDROM_CONFIG_FLAGS(drive)->seeking = 0;
}
- CDROM_CONFIG_FLAGS(drive)->seeking = 0;
+ if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap)
+ action = cdrom_start_seek (drive, block);
+ else
+ action = cdrom_start_read (drive, block);
+ info->last_block = block;
+ return action;
}
- if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap)
- cdrom_start_seek (drive, block);
- else
- cdrom_start_read (drive, block);
- info->last_block = block;
- break;
- }
- case PACKET_COMMAND:
- case REQUEST_SENSE_COMMAND: {
- cdrom_do_packet_command(drive);
- break;
- }
+ case PACKET_COMMAND:
+ case REQUEST_SENSE_COMMAND: {
+ return cdrom_do_packet_command(drive);
+ }
- case RESET_DRIVE_COMMAND: {
- cdrom_end_request(1, drive);
- ide_do_reset(drive);
- break;
- }
+ case RESET_DRIVE_COMMAND: {
+ cdrom_end_request(1, drive);
+ return ide_do_reset(drive);
+ }
- default: {
- printk("ide-cd: bad cmd %d\n", rq -> cmd);
- cdrom_end_request(0, drive);
- break;
- }
+ default: {
+ printk("ide-cd: bad cmd %d\n", rq -> cmd);
+ cdrom_end_request(0, drive);
+ return ide_stopped;
+ }
}
}
@@ -1455,7 +1433,7 @@ void ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long bloc
* Ioctl handling.
*
* Routines which queue packet commands take as a final argument a pointer
- * to an atapi_request_sense struct. If execution of the command results
+ * to a request_sense struct. If execution of the command results
* in an error with a CHECK CONDITION status, this structure will be filled
* with the results of the subsequent request sense command. The pointer
* can also be NULL, in which case no sense information is returned.
@@ -1504,18 +1482,14 @@ int msf_to_lba (byte m, byte s, byte f)
return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
}
-
-static int
-cdrom_check_status (ide_drive_t *drive,
- struct atapi_request_sense *reqbuf)
+static int cdrom_check_status (ide_drive_t *drive)
{
struct packet_command pc;
struct cdrom_info *info = drive->driver_data;
struct cdrom_device_info *cdi = &info->devinfo;
- memset (&pc, 0, sizeof (pc));
+ memset(&pc, 0, sizeof(pc));
- pc.sense_data = reqbuf;
pc.c[0] = GPCMD_TEST_UNIT_READY;
#if ! STANDARD_ATAPI
@@ -1525,39 +1499,35 @@ cdrom_check_status (ide_drive_t *drive,
pc.c[7] = cdi->sanyo_slot % 3;
#endif /* not STANDARD_ATAPI */
- return cdrom_queue_packet_command (drive, &pc);
+ return cdrom_queue_packet_command(drive, &pc);
}
/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
static int
-cdrom_lockdoor (ide_drive_t *drive, int lockflag,
- struct atapi_request_sense *reqbuf)
+cdrom_lockdoor(ide_drive_t *drive, int lockflag)
{
- struct atapi_request_sense my_reqbuf;
- int stat;
+ struct request_sense *sense;
struct packet_command pc;
-
- if (reqbuf == NULL)
- reqbuf = &my_reqbuf;
+ int stat;
/* If the drive cannot lock the door, just pretend. */
if (CDROM_CONFIG_FLAGS (drive)->no_doorlock)
stat = 0;
else {
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
+ memset(&pc, 0, sizeof(pc));
pc.c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
pc.c[4] = (lockflag != 0);
stat = cdrom_queue_packet_command (drive, &pc);
}
+ sense = pc.sense_data;
+
/* If we got an illegal field error, the drive
probably cannot lock the door. */
if (stat != 0 &&
- reqbuf->sense_key == ILLEGAL_REQUEST &&
- (reqbuf->asc == 0x24 || reqbuf->asc == 0x20)) {
+ sense->sense_key == ILLEGAL_REQUEST &&
+ (sense->asc == 0x24 || sense->asc == 0x20)) {
printk ("%s: door locking not supported\n",
drive->name);
CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;
@@ -1565,7 +1535,7 @@ cdrom_lockdoor (ide_drive_t *drive, int lockflag,
}
/* no medium, that's alright. */
- if (stat != 0 && reqbuf->sense_key == NOT_READY && reqbuf->asc == 0x3a)
+ if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a)
stat = 0;
if (stat == 0)
@@ -1577,30 +1547,25 @@ cdrom_lockdoor (ide_drive_t *drive, int lockflag,
/* Eject the disk if EJECTFLAG is 0.
If EJECTFLAG is 1, try to reload the disk. */
-static int
-cdrom_eject (ide_drive_t *drive, int ejectflag,
- struct atapi_request_sense *reqbuf)
+static int cdrom_eject(ide_drive_t *drive, int ejectflag)
{
struct packet_command pc;
- if (CDROM_CONFIG_FLAGS (drive)->no_eject && !ejectflag)
+ if (CDROM_CONFIG_FLAGS(drive)->no_eject && !ejectflag)
return -EDRIVE_CANT_DO_THIS;
/* reload fails on some drives, if the tray is locked */
- if (CDROM_STATE_FLAGS (drive)->door_locked && ejectflag)
+ if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag)
return 0;
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
+ memset(&pc, 0, sizeof (pc));
pc.c[0] = GPCMD_START_STOP_UNIT;
pc.c[4] = 0x02 + (ejectflag != 0);
return cdrom_queue_packet_command (drive, &pc);
}
-static int
-cdrom_read_capacity (ide_drive_t *drive, unsigned *capacity,
- struct atapi_request_sense *reqbuf)
+static int cdrom_read_capacity(ide_drive_t *drive, unsigned *capacity)
{
struct {
__u32 lba;
@@ -1610,30 +1575,25 @@ cdrom_read_capacity (ide_drive_t *drive, unsigned *capacity,
int stat;
struct packet_command pc;
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
+ memset(&pc, 0, sizeof (pc));
pc.c[0] = GPCMD_READ_CDVD_CAPACITY;
pc.buffer = (char *)&capbuf;
- pc.buflen = sizeof (capbuf);
+ pc.buflen = sizeof(capbuf);
- stat = cdrom_queue_packet_command (drive, &pc);
+ stat = cdrom_queue_packet_command(drive, &pc);
if (stat == 0)
*capacity = be32_to_cpu(capbuf.lba);
return stat;
}
-
-static int
-cdrom_read_tocentry (ide_drive_t *drive, int trackno, int msf_flag,
- int format, char *buf, int buflen,
- struct atapi_request_sense *reqbuf)
+static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
+ int format, char *buf, int buflen)
{
struct packet_command pc;
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
+ memset(&pc, 0, sizeof(pc));
pc.buffer = buf;
pc.buflen = buflen;
@@ -1642,14 +1602,16 @@ cdrom_read_tocentry (ide_drive_t *drive, int trackno, int msf_flag,
pc.c[7] = (buflen >> 8);
pc.c[8] = (buflen & 0xff);
pc.c[9] = (format << 6);
- if (msf_flag) pc.c[1] = 2;
+
+ if (msf_flag)
+ pc.c[1] = 2;
+
return cdrom_queue_packet_command (drive, &pc);
}
/* Try to read the entire TOC for the disk into our internal buffer. */
-static int
-cdrom_read_toc (ide_drive_t *drive, struct atapi_request_sense *reqbuf)
+static int cdrom_read_toc (ide_drive_t *drive)
{
int stat, ntracks, i;
struct cdrom_info *info = drive->driver_data;
@@ -1674,13 +1636,13 @@ cdrom_read_toc (ide_drive_t *drive, struct atapi_request_sense *reqbuf)
/* Check to see if the existing data is still valid.
If it is, just return. */
if (CDROM_STATE_FLAGS (drive)->toc_valid)
- (void) cdrom_check_status (drive, NULL);
+ (void) cdrom_check_status(drive);
if (CDROM_STATE_FLAGS (drive)->toc_valid) return 0;
/* First read just the header, so we know how long the TOC is. */
stat = cdrom_read_tocentry (drive, 0, 1, 0, (char *)&toc->hdr,
- sizeof (struct atapi_toc_header), reqbuf);
+ sizeof (struct atapi_toc_header));
if (stat) return stat;
#if ! STANDARD_ATAPI
@@ -1698,7 +1660,7 @@ cdrom_read_toc (ide_drive_t *drive, struct atapi_request_sense *reqbuf)
stat = cdrom_read_tocentry (drive, toc->hdr.first_track, 1, 0, (char *)&toc->hdr,
sizeof (struct atapi_toc_header) +
(ntracks + 1) *
- sizeof (struct atapi_toc_entry), reqbuf);
+ sizeof (struct atapi_toc_entry));
if (stat && toc->hdr.first_track > 1) {
/* Cds with CDI tracks only don't have any TOC entries,
@@ -1715,8 +1677,7 @@ cdrom_read_toc (ide_drive_t *drive, struct atapi_request_sense *reqbuf)
0, (char *)&toc->hdr,
sizeof (struct atapi_toc_header) +
(ntracks+1) *
- sizeof (struct atapi_toc_entry),
- reqbuf);
+ sizeof (struct atapi_toc_entry));
if (stat) {
return stat;
}
@@ -1761,8 +1722,7 @@ cdrom_read_toc (ide_drive_t *drive, struct atapi_request_sense *reqbuf)
if (toc->hdr.first_track != CDROM_LEADOUT) {
/* Read the multisession information. */
stat = cdrom_read_tocentry (drive, 0, 1, 1,
- (char *)&ms_tmp, sizeof (ms_tmp),
- reqbuf);
+ (char *)&ms_tmp, sizeof (ms_tmp));
if (stat) return stat;
} else {
ms_tmp.ent.addr.msf.minute = 0;
@@ -1788,7 +1748,7 @@ cdrom_read_toc (ide_drive_t *drive, struct atapi_request_sense *reqbuf)
(long *)&toc->capacity);
if (stat)
#endif
- stat = cdrom_read_capacity (drive, &toc->capacity, reqbuf);
+ stat = cdrom_read_capacity (drive, &toc->capacity);
if (stat) toc->capacity = 0x1fffff;
/* for general /dev/cdrom like mounting, one big disc */
@@ -1821,17 +1781,14 @@ cdrom_read_toc (ide_drive_t *drive, struct atapi_request_sense *reqbuf)
}
-static int
-cdrom_read_subchannel (ide_drive_t *drive, int format,
- char *buf, int buflen,
- struct atapi_request_sense *reqbuf)
+static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf,
+ int buflen)
{
struct packet_command pc;
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
+ memset(&pc, 0, sizeof(pc));
- pc.buffer = buf;
+ pc.buffer = buf;
pc.buflen = buflen;
pc.c[0] = GPCMD_READ_SUBCHANNEL;
pc.c[1] = 2; /* MSF addressing */
@@ -1839,23 +1796,20 @@ cdrom_read_subchannel (ide_drive_t *drive, int format,
pc.c[3] = format;
pc.c[7] = (buflen >> 8);
pc.c[8] = (buflen & 0xff);
- return cdrom_queue_packet_command (drive, &pc);
+ return cdrom_queue_packet_command(drive, &pc);
}
/* ATAPI cdrom drives are free to select the speed you request or any slower
rate :-( Requesting too fast a speed will _not_ produce an error. */
-static int
-cdrom_select_speed (ide_drive_t *drive, int speed,
- struct atapi_request_sense *reqbuf)
+static int cdrom_select_speed (ide_drive_t *drive, int speed)
{
struct packet_command pc;
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
+ memset(&pc, 0, sizeof(pc));
if (speed == 0)
- speed = 0xffff; /* set to max */
+ speed = 0xffff; /* set to max */
else
- speed *= 177; /* Nx to kbytes/s */
+ speed *= 177; /* Nx to kbytes/s */
pc.c[0] = GPCMD_SET_SPEED;
/* Read Drive speed in kbytes/second MSB */
@@ -1874,10 +1828,8 @@ cdrom_select_speed (ide_drive_t *drive, int speed,
}
-static
-int cdrom_get_toc_entry (ide_drive_t *drive, int track,
- struct atapi_toc_entry **ent,
- struct atapi_request_sense *reqbuf)
+static int cdrom_get_toc_entry(ide_drive_t *drive, int track,
+ struct atapi_toc_entry **ent)
{
struct cdrom_info *info = drive->driver_data;
struct atapi_toc *toc = info->toc;
@@ -1915,7 +1867,13 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi,
memcpy(pc.c, cgc->cmd, CDROM_PACKET_SIZE);
pc.buffer = cgc->buffer;
pc.buflen = cgc->buflen;
- return cgc->stat = cdrom_queue_packet_command(drive, &pc);
+ cgc->stat = cdrom_queue_packet_command(drive, &pc);
+
+ /* There was an error, assign sense. */
+ if (cgc->stat)
+ cgc->sense = pc.sense_data;
+
+ return cgc->stat;
}
static
@@ -1979,7 +1937,7 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
struct atapi_toc *toc;
/* Make sure our saved TOC is valid. */
- stat = cdrom_read_toc (drive, NULL);
+ stat = cdrom_read_toc(drive);
if (stat) return stat;
toc = info->toc;
@@ -1994,8 +1952,7 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
struct cdrom_tocentry *tocentry = (struct cdrom_tocentry*) arg;
struct atapi_toc_entry *toce;
- stat = cdrom_get_toc_entry (drive, tocentry->cdte_track, &toce,
- NULL);
+ stat = cdrom_get_toc_entry (drive, tocentry->cdte_track, &toce);
if (stat) return stat;
tocentry->cdte_ctrl = toce->control;
@@ -2032,21 +1989,20 @@ static
int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- struct atapi_request_sense rq;
if (position) {
- int stat = cdrom_lockdoor (drive, 0, &rq);
+ int stat = cdrom_lockdoor (drive, 0);
if (stat) return stat;
}
- return cdrom_eject (drive, !position, NULL);
+ return cdrom_eject(drive, !position);
}
static
int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock)
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- return cdrom_lockdoor (drive, lock, NULL);
+ return cdrom_lockdoor (drive, lock);
}
static
@@ -2054,14 +2010,13 @@ int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
{
int stat, attempts = 3;
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- struct atapi_request_sense reqbuf;
struct cdrom_generic_command cgc;
struct {
char pad[8];
struct atapi_capabilities_page cap;
} buf;
- stat=cdrom_select_speed (drive, speed, &reqbuf);
- if (stat<0)
+
+ if ((stat = cdrom_select_speed (drive, speed)) < 0)
return stat;
init_cdrom_command(&cgc, &buf, sizeof(buf));
@@ -2092,19 +2047,19 @@ static
int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ struct cdrom_info *info = drive->driver_data;
if (slot_nr == CDSL_CURRENT) {
-
- struct atapi_request_sense sense;
- int stat = cdrom_check_status (drive, &sense);
- if (stat == 0 || sense.sense_key == UNIT_ATTENTION)
+ struct request_sense *sense = &info->sense_data;
+ int stat = cdrom_check_status(drive);
+ if (stat == 0 || sense->sense_key == UNIT_ATTENTION)
return CDS_DISC_OK;
- if (sense.sense_key == NOT_READY && sense.asc == 0x04 &&
- sense.ascq == 0x04)
+ if (sense->sense_key == NOT_READY && sense->asc == 0x04 &&
+ sense->ascq == 0x04)
return CDS_DISC_OK;
- if (sense.sense_key == NOT_READY) {
+ if (sense->sense_key == NOT_READY) {
/* ATAPI doesn't have anything that can help
us decide whether the drive is really
emtpy or the tray is just open. irk. */
@@ -2140,10 +2095,9 @@ int ide_cdrom_get_mcn (struct cdrom_device_info *cdi,
char mcnbuf[24];
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- stat = cdrom_read_subchannel (drive, 2, /* get MCN */
- mcnbuf, sizeof (mcnbuf),
- NULL);
- if (stat) return stat;
+/* get MCN */
+ if ((stat = cdrom_read_subchannel(drive, 2, mcnbuf, sizeof (mcnbuf))))
+ return stat;
memcpy (mcn_info->medium_catalog_number, mcnbuf+9,
sizeof (mcn_info->medium_catalog_number)-1);
@@ -2166,7 +2120,7 @@ int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi,
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
if (slot_nr == CDSL_CURRENT) {
- (void) cdrom_check_status (drive, NULL);
+ (void) cdrom_check_status(drive);
CDROM_STATE_FLAGS (drive)->media_changed = 0;
return CDROM_STATE_FLAGS (drive)->media_changed;
} else {
@@ -2367,8 +2321,13 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
if (drive->using_dma) {
if ((drive->id->field_valid & 4) &&
- (drive->id->dma_ultra & (drive->id->dma_ultra >> 8) & 7)) {
- printk(", UDMA"); /* UDMA BIOS-enabled! */
+ (drive->id->word93 & 0x2000) &&
+ (HWIF(drive)->udma_four) &&
+ (drive->id->dma_ultra & (drive->id->dma_ultra >> 11) & 3)) {
+ printk(", UDMA(66)"); /* UDMA BIOS-enabled! */
+ } else if ((drive->id->field_valid & 4) &&
+ (drive->id->dma_ultra & (drive->id->dma_ultra >> 8) & 7)) {
+ printk(", UDMA(33)"); /* UDMA BIOS-enabled! */
} else if (drive->id->field_valid & 4) {
printk(", (U)DMA"); /* Can be BIOS-enabled! */
} else {
diff --git a/drivers/block/ide-cd.h b/drivers/block/ide-cd.h
index b65baa5fe..8891205ed 100644
--- a/drivers/block/ide-cd.h
+++ b/drivers/block/ide-cd.h
@@ -7,6 +7,7 @@
* Copyright (C) 1998, 1999 Jens Axboe
*/
+#include <linux/cdrom.h>
#include <asm/byteorder.h>
/* Turn this on to have the driver print out the meanings of the
@@ -95,47 +96,14 @@ struct ide_cd_state_flags {
__u8 reserved : 4;
byte current_speed; /* Current speed of the drive */
};
-#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->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];
- byte asc;
- byte ascq;
- byte fru;
- byte sense_key_specific[3];
-};
+#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags))
struct packet_command {
char *buffer;
int buflen;
int stat;
- struct atapi_request_sense *sense_data;
+ struct request_sense *sense_data;
unsigned char c[12];
};
@@ -502,7 +470,7 @@ struct cdrom_info {
/* The result of the last successful request sense command
on this device. */
- struct atapi_request_sense sense_data;
+ struct request_sense sense_data;
struct request request_sense_request;
struct packet_command request_sense_pc;
diff --git a/drivers/block/ide-disk.c b/drivers/block/ide-disk.c
index 924451f5a..133d9cd85 100644
--- a/drivers/block/ide-disk.c
+++ b/drivers/block/ide-disk.c
@@ -133,7 +133,7 @@ static int lba_capacity_is_ok (struct hd_driveid *id)
/*
* read_intr() is the handler for disk read/multread interrupts
*/
-static void read_intr (ide_drive_t *drive)
+static ide_startstop_t read_intr (ide_drive_t *drive)
{
byte stat;
int i;
@@ -141,8 +141,7 @@ static void read_intr (ide_drive_t *drive)
struct request *rq;
if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {
- ide_error(drive, "read_intr", stat);
- return;
+ return ide_error(drive, "read_intr", stat);
}
msect = drive->mult_count;
@@ -154,12 +153,6 @@ read_next:
msect -= nsect;
} else
nsect = 1;
- /*
- * PIO input can take longish times, so we drop the spinlock.
- * On SMP, bad things might happen if syscall level code adds
- * a new request while we do this PIO, so we just freeze all
- * request queue handling while doing the PIO. FIXME
- */
idedisk_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);
#ifdef DEBUG
printk("%s: read: sectors(%ld-%ld), buffer=0x%08lx, remaining=%ld\n",
@@ -176,21 +169,24 @@ read_next:
if (msect)
goto read_next;
ide_set_handler (drive, &read_intr, WAIT_CMD, NULL);
+ return ide_started;
}
+ return ide_stopped;
}
/*
* write_intr() is the handler for disk write interrupts
*/
-static void write_intr (ide_drive_t *drive)
+static ide_startstop_t write_intr (ide_drive_t *drive)
{
byte stat;
int i;
ide_hwgroup_t *hwgroup = HWGROUP(drive);
struct request *rq = hwgroup->rq;
- int error = 0;
- if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
+ if (!OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
+ printk("%s: write_intr error1: nr_sectors=%ld, stat=0x%02x\n", drive->name, rq->nr_sectors, stat);
+ } else {
#ifdef DEBUG
printk("%s: write: sector %ld, buffer=0x%08lx, remaining=%ld\n",
drive->name, rq->sector, (unsigned long) rq->buffer,
@@ -207,26 +203,30 @@ static void write_intr (ide_drive_t *drive)
if (i > 0) {
idedisk_output_data (drive, rq->buffer, SECTOR_WORDS);
ide_set_handler (drive, &write_intr, WAIT_CMD, NULL);
+ return ide_started;
}
- goto out;
+ return ide_stopped;
}
- } else
- error = 1;
-out:
- if (error)
- ide_error(drive, "write_intr", stat);
+ printk("%s: write_intr error2: nr_sectors=%ld, stat=0x%02x\n", drive->name, rq->nr_sectors, stat);
+ }
+ return ide_error(drive, "write_intr", stat);
}
/*
* ide_multwrite() transfers a block of up to mcount sectors of data
* to a drive as part of a disk multiple-sector write operation.
+ *
+ * Returns 0 if successful; returns 1 if request had to be aborted due to corrupted buffer list.
*/
-void ide_multwrite (ide_drive_t *drive, unsigned int mcount)
+int ide_multwrite (ide_drive_t *drive, unsigned int mcount)
{
- struct request *rq = &HWGROUP(drive)->wrq;
+ ide_hwgroup_t *hwgroup= HWGROUP(drive);
+ struct request *rq = &hwgroup->wrq;
+
+ do {
+ unsigned long flags;
+ unsigned int nsect = rq->current_nr_sectors;
- do {
- unsigned int nsect = rq->current_nr_sectors;
if (nsect > mcount)
nsect = mcount;
mcount -= nsect;
@@ -237,42 +237,50 @@ void ide_multwrite (ide_drive_t *drive, unsigned int mcount)
drive->name, rq->sector, (unsigned long) rq->buffer,
nsect, rq->nr_sectors - nsect);
#endif
+ spin_lock_irqsave(&io_request_lock, flags); /* Is this really necessary? */
#ifdef CONFIG_BLK_DEV_PDC4030
rq->sector += nsect;
#endif
if ((rq->nr_sectors -= nsect) <= 0)
+ {
+ spin_unlock_irqrestore(&io_request_lock, flags);
break;
+ }
if ((rq->current_nr_sectors -= nsect) == 0) {
if ((rq->bh = rq->bh->b_reqnext) != NULL) {
rq->current_nr_sectors = rq->bh->b_size>>9;
rq->buffer = rq->bh->b_data;
} else {
- panic("%s: buffer list corrupted\n", drive->name);
- break;
+ spin_unlock_irqrestore(&io_request_lock, flags);
+ printk("%s: buffer list corrupted\n", drive->name);
+ ide_end_request(0, hwgroup);
+ return 1;
}
} else {
rq->buffer += nsect << 9;
}
+ spin_unlock_irqrestore(&io_request_lock, flags);
} while (mcount);
+ return 0;
}
/*
* multwrite_intr() is the handler for disk multwrite interrupts
*/
-static void multwrite_intr (ide_drive_t *drive)
+static ide_startstop_t multwrite_intr (ide_drive_t *drive)
{
byte stat;
int i;
ide_hwgroup_t *hwgroup = HWGROUP(drive);
struct request *rq = &hwgroup->wrq;
- int error = 0;
if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
if (stat & DRQ_STAT) {
if (rq->nr_sectors) {
- ide_multwrite(drive, drive->mult_count);
+ if (ide_multwrite(drive, drive->mult_count))
+ return ide_stopped;
ide_set_handler (drive, &multwrite_intr, WAIT_CMD, NULL);
- goto out;
+ return ide_started;
}
} else {
if (!rq->nr_sectors) { /* all done? */
@@ -281,20 +289,17 @@ static void multwrite_intr (ide_drive_t *drive)
i -= rq->current_nr_sectors;
ide_end_request(1, hwgroup);
}
- goto out;
+ return ide_stopped;
}
}
- } else
- error = 1;
-out:
- if (error)
- ide_error(drive, "multwrite_intr", stat);
+ }
+ return ide_error(drive, "multwrite_intr", stat);
}
/*
* set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd.
*/
-static void set_multmode_intr (ide_drive_t *drive)
+static ide_startstop_t set_multmode_intr (ide_drive_t *drive)
{
byte stat = GET_STAT();
@@ -309,28 +314,31 @@ static void set_multmode_intr (ide_drive_t *drive)
drive->special.b.recalibrate = 1;
(void) ide_dump_status(drive, "set_multmode", stat);
}
+ return ide_stopped;
}
/*
* set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd.
*/
-static void set_geometry_intr (ide_drive_t *drive)
+static ide_startstop_t set_geometry_intr (ide_drive_t *drive)
{
byte stat = GET_STAT();
if (!OK_STAT(stat,READY_STAT,BAD_STAT))
- ide_error(drive, "set_geometry_intr", stat);
+ return ide_error(drive, "set_geometry_intr", stat);
+ return ide_stopped;
}
/*
* recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
*/
-static void recal_intr (ide_drive_t *drive)
+static ide_startstop_t recal_intr (ide_drive_t *drive)
{
byte stat = GET_STAT();
if (!OK_STAT(stat,READY_STAT,BAD_STAT))
- ide_error(drive, "recal_intr", stat);
+ return ide_error(drive, "recal_intr", stat);
+ return ide_stopped;
}
/*
@@ -338,7 +346,7 @@ static void recal_intr (ide_drive_t *drive)
* using LBA if supported, or CHS otherwise, to address sectors.
* It also takes care of issuing special DRIVE_CMDs.
*/
-static void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
+static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
{
if (IDE_CONTROL_REG)
OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
@@ -375,45 +383,61 @@ static void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long bl
}
#ifdef CONFIG_BLK_DEV_PDC4030
if (IS_PDC4030_DRIVE) {
- extern void do_pdc4030_io(ide_drive_t *, struct request *);
- do_pdc4030_io (drive, rq);
- return;
+ extern ide_startstop_t do_pdc4030_io(ide_drive_t *, struct request *);
+ return do_pdc4030_io (drive, rq);
}
#endif /* CONFIG_BLK_DEV_PDC4030 */
if (rq->cmd == READ) {
#ifdef CONFIG_BLK_DEV_IDEDMA
if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_read, drive)))
- return;
+ return ide_started;
#endif /* CONFIG_BLK_DEV_IDEDMA */
ide_set_handler(drive, &read_intr, WAIT_CMD, NULL);
OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, IDE_COMMAND_REG);
- return;
+ return ide_started;
}
if (rq->cmd == WRITE) {
+ ide_startstop_t startstop;
#ifdef CONFIG_BLK_DEV_IDEDMA
if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_write, drive)))
- return;
+ return ide_started;
#endif /* CONFIG_BLK_DEV_IDEDMA */
OUT_BYTE(drive->mult_count ? WIN_MULTWRITE : WIN_WRITE, IDE_COMMAND_REG);
- if (ide_wait_stat(drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
+ if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
printk(KERN_ERR "%s: no DRQ after issuing %s\n", drive->name,
drive->mult_count ? "MULTWRITE" : "WRITE");
- return;
+ return startstop;
}
if (!drive->unmask)
__cli(); /* local CPU only */
if (drive->mult_count) {
- HWGROUP(drive)->wrq = *rq; /* scratchpad */
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
+ /*
+ * Ugh.. this part looks ugly because we MUST set up
+ * the interrupt handler before outputting the first block
+ * of data to be written. If we hit an error (corrupted buffer list)
+ * in ide_multwrite(), then we need to remove the handler/timer
+ * before returning. Fortunately, this NEVER happens (right?).
+ */
+ hwgroup->wrq = *rq; /* scratchpad */
ide_set_handler (drive, &multwrite_intr, WAIT_CMD, NULL);
- ide_multwrite(drive, drive->mult_count);
+ if (ide_multwrite(drive, drive->mult_count)) {
+ unsigned long flags;
+ spin_lock_irqsave(&io_request_lock, flags);
+ hwgroup->handler = NULL;
+ del_timer(&hwgroup->timer);
+ spin_unlock_irqrestore(&io_request_lock, flags);
+ return ide_stopped;
+ }
} else {
ide_set_handler (drive, &write_intr, WAIT_CMD, NULL);
idedisk_output_data(drive, rq->buffer, SECTOR_WORDS);
}
- return;
+ return ide_started;
}
printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd);
ide_end_request(0, HWGROUP(drive));
+ return ide_stopped;
}
static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
@@ -472,7 +496,7 @@ static unsigned long idedisk_capacity (ide_drive_t *drive)
return (drive->capacity - drive->sect0);
}
-static void idedisk_special (ide_drive_t *drive)
+static ide_startstop_t idedisk_special (ide_drive_t *drive)
{
special_t *s = &drive->special;
@@ -498,7 +522,9 @@ static void idedisk_special (ide_drive_t *drive)
int special = s->all;
s->all = 0;
printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special);
+ return ide_stopped;
}
+ return IS_PDC4030_DRIVE ? ide_stopped : ide_started;
}
static void idedisk_pre_reset (ide_drive_t *drive)
@@ -620,7 +646,7 @@ static int set_nowerr(ide_drive_t *drive, int arg)
return -EBUSY;
drive->nowerr = arg;
drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
- spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
+ spin_unlock_irqrestore(&io_request_lock, flags);
return 0;
}
diff --git a/drivers/block/ide-dma.c b/drivers/block/ide-dma.c
index 7712b6cd6..083039e62 100644
--- a/drivers/block/ide-dma.c
+++ b/drivers/block/ide-dma.c
@@ -186,7 +186,7 @@ const char *bad_dma_drives[] = {"WDC AC11000H",
/*
* dma_intr() is the handler for disk read/write DMA interrupts
*/
-void ide_dma_intr (ide_drive_t *drive)
+ide_startstop_t ide_dma_intr (ide_drive_t *drive)
{
int i;
byte stat, dma_stat;
@@ -201,12 +201,11 @@ void ide_dma_intr (ide_drive_t *drive)
i -= rq->current_nr_sectors;
ide_end_request(1, HWGROUP(drive));
}
- return;
+ return ide_stopped;
}
printk("%s: dma_intr: bad DMA status\n", drive->name);
}
- ide__sti(); /* local CPU only */
- ide_error(drive, "dma_intr", stat);
+ return ide_error(drive, "dma_intr", stat);
}
/*
diff --git a/drivers/block/ide-features.c b/drivers/block/ide-features.c
new file mode 100644
index 000000000..e97cada29
--- /dev/null
+++ b/drivers/block/ide-features.c
@@ -0,0 +1,275 @@
+/*
+ * linux/drivers/block/ide-features.c
+ *
+ * Copyright (C) 1999 Linus Torvalds & authors (see below)
+ *
+ * Andre Hedrick <andre@suse.com>
+ *
+ * Extracts if ide.c to address the evolving transfer rate code for
+ * the SETFEATURES_XFER callouts. Below are original authors of some or
+ * various parts of any given function below.
+ *
+ * Mark Lord <mlord@pobox.com>
+ * Gadi Oxman <gadio@netvision.net.il>
+ */
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/major.h>
+#include <linux/errno.h>
+#include <linux/genhd.h>
+#include <linux/blkpg.h>
+#include <linux/malloc.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+
+#include <asm/byteorder.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/bitops.h>
+
+/*
+ *
+ */
+char *ide_xfer_verbose (byte xfer_rate)
+{
+ switch(xfer_rate) {
+ case XFER_UDMA_4: return("UDMA 4");
+ case XFER_UDMA_3: return("UDMA 3");
+ case XFER_UDMA_2: return("UDMA 2");
+ case XFER_UDMA_1: return("UDMA 1");
+ case XFER_UDMA_0: return("UDMA 0");
+ case XFER_MW_DMA_2: return("MW DMA 2");
+ case XFER_MW_DMA_1: return("MW DMA 1");
+ case XFER_MW_DMA_0: return("MW DMA 0");
+ case XFER_SW_DMA_2: return("SW DMA 2");
+ case XFER_SW_DMA_1: return("SW DMA 1");
+ case XFER_SW_DMA_0: return("SW DMA 0");
+ case XFER_PIO_4: return("PIO 4");
+ case XFER_PIO_3: return("PIO 3");
+ case XFER_PIO_2: return("PIO 2");
+ case XFER_PIO_1: return("PIO 1");
+ case XFER_PIO_0: return("PIO 0");
+ case XFER_PIO_SLOW: return("PIO SLOW");
+ default: return("XFER ERROR");
+ }
+}
+
+/*
+ *
+ */
+char *ide_media_verbose (ide_drive_t *drive)
+{
+ switch (drive->media) {
+ case ide_disk: return("disk ");
+ case ide_cdrom: return("cdrom ");
+ case ide_tape: return("tape ");
+ case ide_floppy: return("floppy");
+ default: return("??????");
+ }
+}
+
+int ide_driveid_update (ide_drive_t *drive)
+{
+ /*
+ * Re-read drive->id for possible DMA mode
+ * change (copied from ide-probe.c)
+ */
+ struct hd_driveid *id;
+ unsigned long timeout, irqs, flags;
+
+ probe_irq_off(probe_irq_on());
+ irqs = probe_irq_on();
+ if (IDE_CONTROL_REG)
+ OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
+ ide_delay_50ms();
+ OUT_BYTE(WIN_IDENTIFY, IDE_COMMAND_REG);
+ timeout = jiffies + WAIT_WORSTCASE;
+ do {
+ if (0 < (signed long)(jiffies - timeout)) {
+ if (irqs)
+ (void) probe_irq_off(irqs);
+ return 0; /* drive timed-out */
+ }
+ ide_delay_50ms(); /* give drive a breather */
+ } while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT);
+ ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */
+ if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT))
+ return 0;
+ __save_flags(flags); /* local CPU only */
+ __cli(); /* local CPU only; some systems need this */
+ id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);
+ ide_input_data(drive, id, SECTOR_WORDS);
+ (void) GET_STAT(); /* clear drive IRQ */
+ ide__sti(); /* local CPU only */
+ __restore_flags(flags); /* local CPU only */
+ ide_fix_driveid(id);
+ if (id && id->cyls) {
+ drive->id->dma_ultra = id->dma_ultra;
+ drive->id->dma_mword = id->dma_mword;
+ drive->id->dma_1word = id->dma_1word;
+ /* anything more ? */
+#ifdef DEBUG
+ printk("%s: dma_ultra=%04X, dma_mword=%04X, dma_1word=%04X\n",
+ drive->name, id->dma_ultra, id->dma_mword, id->dma_1word);
+#endif
+ kfree(id);
+ }
+ return 1;
+}
+
+/*
+ * Similar to ide_wait_stat(), except it never calls ide_error internally.
+ * This is a kludge to handle the new ide_config_drive_speed() function,
+ * and should not otherwise be used anywhere. Eventually, the tuneproc's
+ * should be updated to return ide_startstop_t, in which case we can get
+ * rid of this abomination again. :) -ml
+ */
+int ide_wait_noerr (ide_drive_t *drive, byte good, byte bad, unsigned long timeout)
+{
+ byte stat;
+ int i;
+ unsigned long flags;
+
+ udelay(1); /* spec allows drive 400ns to assert "BUSY" */
+ if ((stat = GET_STAT()) & BUSY_STAT) {
+ __save_flags(flags); /* local CPU only */
+ ide__sti(); /* local CPU only */
+ timeout += jiffies;
+ while ((stat = GET_STAT()) & BUSY_STAT) {
+ if (0 < (signed long)(jiffies - timeout)) {
+ __restore_flags(flags); /* local CPU only */
+ (void)ide_dump_status(drive, "ide_wait_noerr", stat);
+ return 1;
+ }
+ }
+ __restore_flags(flags); /* local CPU only */
+ }
+ /*
+ * Allow status to settle, then read it again.
+ * A few rare drives vastly violate the 400ns spec here,
+ * so we'll wait up to 10usec for a "good" status
+ * rather than expensively fail things immediately.
+ * This fix courtesy of Matthew Faupel & Niccolo Rigacci.
+ */
+ for (i = 0; i < 10; i++) {
+ udelay(1);
+ if (OK_STAT((stat = GET_STAT()), good, bad))
+ return 0;
+ }
+ (void)ide_dump_status(drive, "ide_wait_noerr", stat);
+ return 1;
+}
+
+
+/*
+ * Verify that we are doing an approved SETFEATURES_XFER with respect
+ * to the hardware being able to support request. Since some hardware
+ * can improperly report capabilties, we check to see if the host adapter
+ * in combination with the device (usually a disk) properly detect
+ * and acknowledge each end of the ribbon.
+ */
+int ide_ata66_check (ide_drive_t *drive, int cmd, int nsect, int feature)
+{
+ if ((cmd == WIN_SETFEATURES) &&
+ (nsect > XFER_UDMA_2) &&
+ (feature == SETFEATURES_XFER)) {
+ if (!HWIF(drive)->udma_four) {
+ printk("%s: Speed warnings UDMA 3/4 is not functional.\n", HWIF(drive)->name);
+ return 1;
+ }
+ if ((drive->id->word93 & 0x2000) == 0) {
+ printk("%s: Speed warnings UDMA 3/4 is not functional.\n", drive->name);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER.
+ * 1 : Safe to update drive->id DMA registers.
+ * 0 : OOPs not allowed.
+ */
+int set_transfer (ide_drive_t *drive, int cmd, int nsect, int feature)
+{
+ struct hd_driveid *id = drive->id;
+
+ if ((cmd == WIN_SETFEATURES) &&
+ (nsect >= XFER_SW_DMA_0) &&
+ (feature == SETFEATURES_XFER) &&
+ (id->dma_ultra || id->dma_mword || id->dma_1word))
+ return 1;
+ return 0;
+}
+
+int ide_config_drive_speed (ide_drive_t *drive, byte speed)
+{
+ unsigned long flags;
+ int err;
+ byte stat;
+
+ __save_flags(flags); /* local CPU only */
+ __cli(); /* local CPU only */
+
+ /*
+ * Don't use ide_wait_cmd here - it will
+ * attempt to set_geometry and recalibrate,
+ * but for some reason these don't work at
+ * this point (lost interrupt).
+ */
+ SELECT_DRIVE(HWIF(drive), drive);
+ if (IDE_CONTROL_REG)
+ OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
+ OUT_BYTE(speed, IDE_NSECTOR_REG);
+ OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
+ OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG);
+
+ err = ide_wait_noerr(drive, DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT, WAIT_CMD);
+
+#if 0
+ if (IDE_CONTROL_REG)
+ OUT_BYTE(drive->ctl, IDE_CONTROL_REG);
+#endif
+
+ __restore_flags(flags); /* local CPU only */
+
+ stat = GET_STAT();
+ if (stat != DRIVE_READY)
+ (void) ide_dump_status(drive, "set_drive_speed_status", stat);
+
+ drive->id->dma_ultra &= ~0xFF00;
+ drive->id->dma_mword &= ~0x0F00;
+ drive->id->dma_1word &= ~0x0F00;
+
+ switch(speed) {
+ case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break;
+ case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break;
+ case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break;
+ case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break;
+ case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break;
+ case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break;
+ case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break;
+ case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break;
+ case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break;
+ case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break;
+ case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break;
+ default: break;
+ }
+ return(err);
+}
+
+EXPORT_SYMBOL(ide_driveid_update);
+EXPORT_SYMBOL(ide_wait_noerr);
+EXPORT_SYMBOL(ide_ata66_check);
+EXPORT_SYMBOL(set_transfer);
+EXPORT_SYMBOL(ide_config_drive_speed);
+
diff --git a/drivers/block/ide-floppy.c b/drivers/block/ide-floppy.c
index 4609e77d9..aade2c6ee 100644
--- a/drivers/block/ide-floppy.c
+++ b/drivers/block/ide-floppy.c
@@ -830,7 +830,7 @@ static void idefloppy_retry_pc (ide_drive_t *drive)
* idefloppy_pc_intr is the usual interrupt handler which will be called
* during a packet command.
*/
-static void idefloppy_pc_intr (ide_drive_t *drive)
+static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
idefloppy_status_reg_t status;
@@ -875,24 +875,22 @@ static void idefloppy_pc_intr (ide_drive_t *drive)
rq->errors++;
if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {
printk (KERN_ERR "ide-floppy: I/O error in request sense command\n");
- ide_do_reset (drive);
- return;
+ return ide_do_reset (drive);
}
idefloppy_retry_pc (drive); /* Retry operation */
- return;
+ return ide_stopped; /* queued, but not started */
}
pc->error = 0;
if (floppy->failed_pc == pc)
floppy->failed_pc=NULL;
pc->callback(drive); /* Command finished - Call the callback function */
- return;
+ return ide_stopped;
}
#ifdef CONFIG_BLK_DEV_IDEDMA
if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
printk (KERN_ERR "ide-floppy: The floppy wants to issue more interrupts in DMA mode\n");
(void) HWIF(drive)->dmaproc(ide_dma_off, drive);
- ide_do_reset (drive);
- return;
+ return ide_do_reset (drive);
}
#endif /* CONFIG_BLK_DEV_IDEDMA */
bcount.b.high=IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */
@@ -901,14 +899,12 @@ static void idefloppy_pc_intr (ide_drive_t *drive)
if (ireason.b.cod) {
printk (KERN_ERR "ide-floppy: CoD != 0 in idefloppy_pc_intr\n");
- ide_do_reset (drive);
- return;
+ return ide_do_reset (drive);
}
if (ireason.b.io == test_bit (PC_WRITING, &pc->flags)) { /* Hopefully, we will never get here */
printk (KERN_ERR "ide-floppy: We wanted to %s, ", ireason.b.io ? "Write":"Read");
printk (KERN_ERR "but the floppy wants us to %s !\n",ireason.b.io ? "Read":"Write");
- ide_do_reset (drive);
- return;
+ return ide_do_reset (drive);
}
if (!test_bit (PC_WRITING, &pc->flags)) { /* Reading - Check that we have enough space */
temp = pc->actually_transferred + bcount.all;
@@ -917,7 +913,7 @@ static void idefloppy_pc_intr (ide_drive_t *drive)
printk (KERN_ERR "ide-floppy: The floppy wants to send us more data than expected - discarding data\n");
idefloppy_discard_data (drive,bcount.all);
ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL);
- return;
+ return ide_started;
}
#if IDEFLOPPY_DEBUG_LOG
printk (KERN_NOTICE "ide-floppy: The floppy wants to send us more data than expected - allowing transfer\n");
@@ -939,31 +935,33 @@ static void idefloppy_pc_intr (ide_drive_t *drive)
pc->current_position+=bcount.all;
ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */
+ return ide_started;
}
-static void idefloppy_transfer_pc (ide_drive_t *drive)
+static ide_startstop_t idefloppy_transfer_pc (ide_drive_t *drive)
{
+ ide_startstop_t startstop;
idefloppy_floppy_t *floppy = drive->driver_data;
idefloppy_ireason_reg_t ireason;
- if (ide_wait_stat (drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) {
+ if (ide_wait_stat (&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) {
printk (KERN_ERR "ide-floppy: Strange, packet command initiated yet DRQ isn't asserted\n");
- return;
+ return startstop;
}
ireason.all=IN_BYTE (IDE_IREASON_REG);
if (!ireason.b.cod || ireason.b.io) {
printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n");
- ide_do_reset (drive);
- return;
+ return ide_do_reset (drive);
}
ide_set_handler (drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* Set the interrupt routine */
atapi_output_bytes (drive, floppy->pc->c, 12); /* Send the actual packet */
+ return ide_started;
}
/*
* Issue a packet command
*/
-static void idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc)
+static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc)
{
idefloppy_floppy_t *floppy = drive->driver_data;
idefloppy_bcount_reg_t bcount;
@@ -991,7 +989,7 @@ static void idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc)
}
floppy->failed_pc=NULL;
pc->callback(drive);
- return;
+ return ide_stopped;
}
#if IDEFLOPPY_DEBUG_LOG
printk (KERN_INFO "Retry number - %d\n",pc->retries);
@@ -1027,9 +1025,10 @@ static void idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc)
if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) {
ide_set_handler (drive, &idefloppy_transfer_pc, IDEFLOPPY_WAIT_CMD, NULL);
OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */
+ return ide_started;
} else {
OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG);
- idefloppy_transfer_pc (drive);
+ return idefloppy_transfer_pc (drive);
}
}
@@ -1135,7 +1134,7 @@ static void idefloppy_create_rw_cmd (idefloppy_floppy_t *floppy, idefloppy_pc_t
/*
* idefloppy_do_request is our request handling function.
*/
-static void idefloppy_do_request (ide_drive_t *drive, struct request *rq, unsigned long block)
+static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request *rq, unsigned long block)
{
idefloppy_floppy_t *floppy = drive->driver_data;
idefloppy_pc_t *pc;
@@ -1152,7 +1151,7 @@ static void idefloppy_do_request (ide_drive_t *drive, struct request *rq, unsign
else
printk (KERN_ERR "ide-floppy: %s: I/O error\n", drive->name);
idefloppy_end_request (0, HWGROUP(drive));
- return;
+ return ide_stopped;
}
switch (rq->cmd) {
case READ:
@@ -1160,7 +1159,7 @@ static void idefloppy_do_request (ide_drive_t *drive, struct request *rq, unsign
if (rq->sector % floppy->bs_factor || rq->nr_sectors % floppy->bs_factor) {
printk ("%s: unsupported r/w request size\n", drive->name);
idefloppy_end_request (0, HWGROUP(drive));
- return;
+ return ide_stopped;
}
pc = idefloppy_next_pc_storage (drive);
idefloppy_create_rw_cmd (floppy, pc, rq, block);
@@ -1171,10 +1170,10 @@ static void idefloppy_do_request (ide_drive_t *drive, struct request *rq, unsign
default:
printk (KERN_ERR "ide-floppy: unsupported command %x in request queue\n", rq->cmd);
idefloppy_end_request (0,HWGROUP (drive));
- return;
+ return ide_stopped;
}
pc->rq = rq;
- idefloppy_issue_pc (drive, pc);
+ return idefloppy_issue_pc (drive, pc);
}
/*
diff --git a/drivers/block/ide-geometry.c b/drivers/block/ide-geometry.c
index 8370d35a6..79abaca2b 100644
--- a/drivers/block/ide-geometry.c
+++ b/drivers/block/ide-geometry.c
@@ -1,6 +1,7 @@
/*
* linux/drivers/block/ide-geometry.c
*/
+#include <linux/config.h>
#include <linux/ide.h>
#include <asm/io.h>
@@ -65,9 +66,6 @@ void probe_cmos_for_drives (ide_hwif_t *hwif)
drive->head = drive->bios_head = *(BIOS+2);
drive->sect = drive->bios_sect = *(BIOS+14);
drive->ctl = *(BIOS+8);
-#if 0
- drive->present = 1;
-#endif
}
BIOS += 16;
}
diff --git a/drivers/block/ide-pci.c b/drivers/block/ide-pci.c
index 73ffa67ea..06a986641 100644
--- a/drivers/block/ide-pci.c
+++ b/drivers/block/ide-pci.c
@@ -49,6 +49,7 @@
#define DEVID_HT6565 ((ide_pci_devid_t){PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565})
#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_UM8673F ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F})
#define DEVID_UM8886A ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A})
#define DEVID_UM8886BF ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF})
#define DEVID_HPT34X ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343})
@@ -61,66 +62,17 @@
#define IDE_IGNORE ((void *)-1)
-#ifdef CONFIG_BLK_DEV_TRM290
-extern void ide_init_trm290(ide_hwif_t *);
-#define INIT_TRM290 &ide_init_trm290
-#else
-#define INIT_TRM290 IDE_IGNORE
-#endif
-
-#ifdef CONFIG_BLK_DEV_OPTI621
-extern void ide_init_opti621(ide_hwif_t *);
-#define INIT_OPTI621 &ide_init_opti621
-#else
-#define INIT_OPTI621 NULL
-#endif
-
-#ifdef CONFIG_BLK_DEV_NS87415
-extern void ide_init_ns87415(ide_hwif_t *);
-#define INIT_NS87415 &ide_init_ns87415
-#else
-#define INIT_NS87415 IDE_IGNORE
-#endif
-
-#ifdef CONFIG_BLK_DEV_CMD646
-extern void ide_init_cmd646(ide_hwif_t *);
-#define INIT_CMD646 &ide_init_cmd646
-#else
-#ifdef __sparc_v9__
-#define INIT_CMD646 IDE_IGNORE
-#else
-#define INIT_CMD646 NULL
-#endif
-#endif
-
-#ifdef CONFIG_BLK_DEV_SL82C105
-extern void ide_init_sl82c105(ide_hwif_t *);
-#define INIT_W82C105 &ide_init_sl82c105
-#else
-#define INIT_W82C105 IDE_IGNORE
-#endif
-
-#ifdef CONFIG_BLK_DEV_RZ1000
-extern void ide_init_rz1000(ide_hwif_t *);
-#define INIT_RZ1000 &ide_init_rz1000
-#else
-#define INIT_RZ1000 IDE_IGNORE
-#endif
-
-#ifdef CONFIG_BLK_DEV_VIA82CXXX
-extern unsigned int pci_init_via82cxxx(struct pci_dev *, const char *);
-extern unsigned int ata66_via82cxxx(ide_hwif_t *);
-extern void ide_init_via82cxxx(ide_hwif_t *);
-extern void ide_dmacapable_via82cxxx(ide_hwif_t *, unsigned long);
-#define PCI_VIA82CXXX &pci_init_via82cxxx
-#define ATA66_VIA82CXXX &ata66_via82cxxx
-#define INIT_VIA82CXXX &ide_init_via82cxxx
-#define DMA_VIA82CXXX &ide_dmacapable_via82cxxx
+#ifdef CONFIG_BLK_DEV_AEC6210
+extern unsigned int pci_init_aec6210(struct pci_dev *, const char *);
+extern void ide_init_aec6210(ide_hwif_t *);
+extern void ide_dmacapable_aec6210(ide_hwif_t *, unsigned long);
+#define PCI_AEC6210 &pci_init_aec6210
+#define INIT_AEC6210 &ide_init_aec6210
+#define DMA_AEC6210 &ide_dmacapable_aec6210
#else
-#define PCI_VIA82CXXX NULL
-#define ATA66_VIA82CXXX NULL
-#define INIT_VIA82CXXX NULL
-#define DMA_VIA82CXXX NULL
+#define PCI_AEC6210 NULL
+#define INIT_AEC6210 NULL
+#define DMA_AEC6210 NULL
#endif
#ifdef CONFIG_BLK_DEV_ALI15X3
@@ -139,6 +91,17 @@ extern void ide_dmacapable_ali15x3(ide_hwif_t *, unsigned long);
#define DMA_ALI15X3 NULL
#endif
+#ifdef CONFIG_BLK_DEV_CMD646
+extern void ide_init_cmd646(ide_hwif_t *);
+#define INIT_CMD646 &ide_init_cmd646
+#else
+#ifdef __sparc_v9__
+#define INIT_CMD646 IDE_IGNORE
+#else
+#define INIT_CMD646 NULL
+#endif
+#endif
+
#ifdef CONFIG_BLK_DEV_CY82C693
extern unsigned int pci_init_cy82c693(struct pci_dev *, const char *);
extern void ide_init_cy82c693(ide_hwif_t *);
@@ -149,32 +112,7 @@ extern void ide_init_cy82c693(ide_hwif_t *);
#define INIT_CY82C693 NULL
#endif
-#ifdef CONFIG_BLK_DEV_PDC202XX
-extern unsigned int pci_init_pdc202xx(struct pci_dev *, const char *);
-extern unsigned int ata66_pdc202xx(ide_hwif_t *);
-extern void ide_init_pdc202xx(ide_hwif_t *);
-#define PCI_PDC202XX &pci_init_pdc202xx
-#define ATA66_PDC202XX &ata66_pdc202xx
-#define INIT_PDC202XX &ide_init_pdc202xx
-#else
-#define PCI_PDC202XX NULL
-#define ATA66_PDC202XX NULL
-#define INIT_PDC202XX NULL
-#endif
-
-#ifdef CONFIG_BLK_DEV_PIIX
-extern void ide_init_piix(ide_hwif_t *);
-#define INIT_PIIX &ide_init_piix
-#else
-#define INIT_PIIX NULL
-#endif
-
-#ifdef CONFIG_BLK_DEV_AEC6210
-extern unsigned int pci_init_aec6210(struct pci_dev *, const char *);
-#define PCI_AEC6210 &pci_init_aec6210
-#else
-#define PCI_AEC6210 NULL
-#endif
+#define INIT_CX5530 NULL
#ifdef CONFIG_BLK_DEV_HPT34X
extern unsigned int pci_init_hpt34x(struct pci_dev *, const char *);
@@ -204,6 +142,52 @@ static byte hpt363_shared_irq = 0;
#define DMA_HPT366 NULL
#endif
+#ifdef CONFIG_BLK_DEV_NS87415
+extern void ide_init_ns87415(ide_hwif_t *);
+#define INIT_NS87415 &ide_init_ns87415
+#else
+#define INIT_NS87415 IDE_IGNORE
+#endif
+
+#ifdef CONFIG_BLK_DEV_OPTI621
+extern void ide_init_opti621(ide_hwif_t *);
+#define INIT_OPTI621 &ide_init_opti621
+#else
+#define INIT_OPTI621 NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_PDC202XX
+extern unsigned int pci_init_pdc202xx(struct pci_dev *, const char *);
+extern unsigned int ata66_pdc202xx(ide_hwif_t *);
+extern void ide_init_pdc202xx(ide_hwif_t *);
+#define PCI_PDC202XX &pci_init_pdc202xx
+#define ATA66_PDC202XX &ata66_pdc202xx
+#define INIT_PDC202XX &ide_init_pdc202xx
+#else
+#define PCI_PDC202XX NULL
+#define ATA66_PDC202XX NULL
+#define INIT_PDC202XX NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_PIIX
+extern unsigned int pci_init_piix(struct pci_dev *, const char *);
+extern void ide_init_piix(ide_hwif_t *);
+#define PCI_PIIX &pci_init_piix
+#define INIT_PIIX &ide_init_piix
+#else
+#define PCI_PIIX NULL
+#define INIT_PIIX NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_RZ1000
+extern void ide_init_rz1000(ide_hwif_t *);
+#define INIT_RZ1000 &ide_init_rz1000
+#else
+#define INIT_RZ1000 IDE_IGNORE
+#endif
+
+#define INIT_SAMURAI NULL
+
#ifdef CONFIG_BLK_DEV_SIS5513
extern unsigned int pci_init_sis5513(struct pci_dev *, const char *);
extern unsigned int ata66_sis5513(ide_hwif_t *);
@@ -217,8 +201,35 @@ extern void ide_init_sis5513(ide_hwif_t *);
#define INIT_SIS5513 NULL
#endif
-#define INIT_SAMURAI NULL
-#define INIT_CX5530 NULL
+#ifdef CONFIG_BLK_DEV_SL82C105
+extern void ide_init_sl82c105(ide_hwif_t *);
+#define INIT_W82C105 &ide_init_sl82c105
+#else
+#define INIT_W82C105 IDE_IGNORE
+#endif
+
+#ifdef CONFIG_BLK_DEV_TRM290
+extern void ide_init_trm290(ide_hwif_t *);
+#define INIT_TRM290 &ide_init_trm290
+#else
+#define INIT_TRM290 IDE_IGNORE
+#endif
+
+#ifdef CONFIG_BLK_DEV_VIA82CXXX
+extern unsigned int pci_init_via82cxxx(struct pci_dev *, const char *);
+extern unsigned int ata66_via82cxxx(ide_hwif_t *);
+extern void ide_init_via82cxxx(ide_hwif_t *);
+extern void ide_dmacapable_via82cxxx(ide_hwif_t *, unsigned long);
+#define PCI_VIA82CXXX &pci_init_via82cxxx
+#define ATA66_VIA82CXXX &ata66_via82cxxx
+#define INIT_VIA82CXXX &ide_init_via82cxxx
+#define DMA_VIA82CXXX &ide_dmacapable_via82cxxx
+#else
+#define PCI_VIA82CXXX NULL
+#define ATA66_VIA82CXXX NULL
+#define INIT_VIA82CXXX NULL
+#define DMA_VIA82CXXX NULL
+#endif
typedef struct ide_pci_enablebit_s {
byte reg; /* byte pci reg holding the enable-bit */
@@ -241,8 +252,8 @@ typedef struct ide_pci_device_s {
static ide_pci_device_t ide_pci_chipsets[] __initdata = {
{DEVID_PIIXa, "PIIX", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
{DEVID_PIIXb, "PIIX", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_PIIX3, "PIIX3", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_PIIX4, "PIIX4", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
+ {DEVID_PIIX3, "PIIX3", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
+ {DEVID_PIIX4, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
{DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
{DEVID_VP_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 },
{DEVID_PDC20246,"PDC20246", PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 },
@@ -260,12 +271,13 @@ static ide_pci_device_t ide_pci_chipsets[] __initdata = {
{DEVID_OPTI621X,"OPTI621X", NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 },
{DEVID_TRM290, "TRM290", NULL, NULL, INIT_TRM290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
{DEVID_NS87415, "NS87415", NULL, NULL, INIT_NS87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_AEC6210, "AEC6210", PCI_AEC6210, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 },
+ {DEVID_AEC6210, "AEC6210", PCI_AEC6210, NULL, INIT_AEC6210, DMA_AEC6210, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 },
{DEVID_W82C105, "W82C105", NULL, NULL, INIT_W82C105, NULL, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 },
+ {DEVID_UM8673F, "UM8673F", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
{DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
{DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
{DEVID_HPT34X, "HPT34X", PCI_HPT34X, NULL, INIT_HPT34X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 },
- {DEVID_HPT366, "HPT366", PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 256 },
+ {DEVID_HPT366, "HPT366", PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 240 },
{DEVID_ALI15X3, "ALI15X3", PCI_ALI15X3, ATA66_ALI15X3, INIT_ALI15X3, DMA_ALI15X3, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
{DEVID_CY82C693,"CY82C693", PCI_CY82C693, NULL, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
{DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
@@ -549,7 +561,8 @@ check_if_enabled:
}
}
if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886BF)) {
+ IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886BF) ||
+ IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8673F)) {
hwif->irq = hwif->channel ? 15 : 14;
goto bypass_umc_dma;
}
diff --git a/drivers/block/ide-probe.c b/drivers/block/ide-probe.c
index d430c5b1d..c4dc22408 100644
--- a/drivers/block/ide-probe.c
+++ b/drivers/block/ide-probe.c
@@ -56,7 +56,8 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
ide_input_data(drive, id, SECTOR_WORDS); /* read 512 bytes of id info */
ide__sti(); /* local CPU only */
ide_fix_driveid(id);
-
+ if (!drive->forced_lun)
+ drive->last_lun = id->word126 & 0x7;
#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
/*
* EATA SCSI controllers do a hardware ATA emulation:
@@ -402,7 +403,7 @@ static void probe_hwif (ide_hwif_t *hwif)
if (hwif->noprobe)
return;
if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) {
- extern void probe_cmos_for_drives(ide_hwif_t *hwif);
+ extern void probe_cmos_for_drives(ide_hwif_t *);
probe_cmos_for_drives (hwif);
}
@@ -575,10 +576,6 @@ static int init_irq (ide_hwif_t *hwif)
hwgroup->handler = NULL;
hwgroup->drive = NULL;
hwgroup->busy = 0;
- hwgroup->spinlock = (spinlock_t)SPIN_LOCK_UNLOCKED;
-#if (DEBUG_SPINLOCK > 0)
- printk("hwgroup(%s) spinlock is %p\n", hwif->name, &hwgroup->spinlock); /* FIXME */
-#endif
init_timer(&hwgroup->timer);
hwgroup->timer.function = &ide_timer_expiry;
hwgroup->timer.data = (unsigned long) hwgroup;
@@ -707,7 +704,8 @@ static void init_gendisk (ide_hwif_t *hwif)
static int hwif_init (ide_hwif_t *hwif)
{
- void (*rfn)(void);
+ ide_drive_t *drive;
+ void (*rfn)(request_queue_t *);
if (!hwif->present)
return 0;
@@ -789,11 +787,24 @@ static int hwif_init (ide_hwif_t *hwif)
init_gendisk(hwif);
blk_dev[hwif->major].data = hwif;
- blk_dev[hwif->major].request_fn = rfn;
blk_dev[hwif->major].queue = ide_get_queue;
read_ahead[hwif->major] = 8; /* (4kB) */
hwif->present = 1; /* success */
+ /*
+ * FIXME(eric) - This needs to be tested. I *think* that this
+ * is correct. Also, I believe that there is no longer any
+ * reason to have multiple functions (do_ide[0-7]_request)
+ * functions - the queuedata field could be used to indicate
+ * the correct hardware group - either this, or we could add
+ * a new field to request_queue_t to hold this information.
+ */
+ drive = &hwif->drives[0];
+ blk_init_queue(&drive->queue, rfn);
+
+ drive = &hwif->drives[1];
+ blk_init_queue(&drive->queue, rfn);
+
#if (DEBUG_SPINLOCK > 0)
{
static int done = 0;
diff --git a/drivers/block/ide-proc.c b/drivers/block/ide-proc.c
index b68072428..66e45001c 100644
--- a/drivers/block/ide-proc.c
+++ b/drivers/block/ide-proc.c
@@ -75,17 +75,22 @@
#ifdef CONFIG_BLK_DEV_ALI15X3
extern byte ali_proc;
-int (*ali_display_info)(char *, char **, off_t, int, int) = NULL;
+int (*ali_display_info)(char *, char **, off_t, int) = NULL;
#endif /* CONFIG_BLK_DEV_ALI15X3 */
+#ifdef CONFIG_BLK_DEV_PIIX
+extern byte piix_proc;
+int (*piix_display_info)(char *, char **, off_t, int) = NULL;
+#endif /* CONFIG_BLK_DEV_PIIX */
+
#ifdef CONFIG_BLK_DEV_SIS5513
extern byte sis_proc;
-int (*sis_display_info)(char *, char **, off_t, int, int) = NULL;
+int (*sis_display_info)(char *, char **, off_t, int) = NULL;
#endif /* CONFIG_BLK_DEV_SIS5513 */
#ifdef CONFIG_BLK_DEV_VIA82CXXX
extern byte via_proc;
-int (*via_display_info)(char *, char **, off_t, int, int) = NULL;
+int (*via_display_info)(char *, char **, off_t, int) = NULL;
#endif /* CONFIG_BLK_DEV_VIA82CXXX */
static int ide_getxdigit(char c)
@@ -372,6 +377,8 @@ static int proc_ide_read_imodel
case ide_pdc4030: name = "pdc4030"; break;
case ide_rz1000: name = "rz1000"; break;
case ide_trm290: name = "trm290"; break;
+ case ide_cmd646: name = "cmd646"; break;
+ case ide_cy82c693: name = "cy82c693"; break;
case ide_4drives: name = "4drives"; break;
default: name = "(unknown)"; break;
}
@@ -661,17 +668,12 @@ void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p)
}
}
-static int proc_ide_readlink(struct proc_dir_entry *de, char *page)
-{
- int n = (de->name[2] - 'a') / 2;
- return sprintf(page, "ide%d/%s", n, de->name);
-}
-
static void create_proc_ide_drives(ide_hwif_t *hwif)
{
int d;
struct proc_dir_entry *ent;
struct proc_dir_entry *parent = hwif->proc;
+ char name[64];
for (d = 0; d < MAX_DRIVES; d++) {
ide_drive_t *drive = &hwif->drives[d];
@@ -682,7 +684,7 @@ static void create_proc_ide_drives(ide_hwif_t *hwif)
if (drive->proc)
continue;
- drive->proc = create_proc_entry(drive->name, S_IFDIR, parent);
+ drive->proc = proc_mkdir(drive->name, parent);
if (drive->proc) {
ide_add_proc_entries(drive->proc, generic_drive_entries, drive);
if (driver) {
@@ -690,11 +692,9 @@ static void create_proc_ide_drives(ide_hwif_t *hwif)
ide_add_proc_entries(drive->proc, driver->proc, drive);
}
}
- ent = create_proc_entry(drive->name, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, proc_ide_root);
+ sprintf(name,"ide%d/%s", (drive->name[2]-'a')/2, drive->name);
+ ent = proc_symlink(drive->name, proc_ide_root, name);
if (!ent) return;
- ent->data = drive;
- ent->readlink_proc = proc_ide_readlink;
- ent->nlink = 1;
}
}
@@ -731,16 +731,15 @@ void create_proc_ide_interfaces(void)
for (h = 0; h < MAX_HWIFS; h++) {
ide_hwif_t *hwif = &ide_hwifs[h];
- int exist = (hwif->proc != NULL);
if (!hwif->present)
continue;
- if (!exist)
- hwif->proc = create_proc_entry(hwif->name, S_IFDIR, proc_ide_root);
- if (!hwif->proc)
- return;
- if (!exist)
+ if (!hwif->proc) {
+ hwif->proc = proc_mkdir(hwif->name, proc_ide_root);
+ if (!hwif->proc)
+ return;
ide_add_proc_entries(hwif->proc, hwif_entries, hwif);
+ }
create_proc_ide_drives(hwif);
}
}
@@ -752,7 +751,6 @@ static void destroy_proc_ide_interfaces(void)
for (h = 0; h < MAX_HWIFS; h++) {
ide_hwif_t *hwif = &ide_hwifs[h];
int exist = (hwif->proc != NULL);
-
#if 0
if (!hwif->present)
continue;
@@ -769,7 +767,7 @@ static void destroy_proc_ide_interfaces(void)
void proc_ide_create(void)
{
- proc_ide_root = create_proc_entry("ide", S_IFDIR, 0);
+ proc_ide_root = proc_mkdir("ide", 0);
if (!proc_ide_root) return;
create_proc_ide_interfaces();
@@ -781,6 +779,10 @@ void proc_ide_create(void)
if ((ali_display_info) && (ali_proc))
create_proc_info_entry("ali", 0, proc_ide_root, ali_display_info);
#endif /* CONFIG_BLK_DEV_ALI15X3 */
+#ifdef CONFIG_BLK_DEV_PIIX
+ if ((piix_display_info) && (piix_proc))
+ create_proc_info_entry("piix", 0, proc_ide_root, piix_display_info);
+#endif /* CONFIG_BLK_DEV_PIIX */
#ifdef CONFIG_BLK_DEV_SIS5513
if ((sis_display_info) && (sis_proc))
create_proc_info_entry("sis", 0, proc_ide_root, sis_display_info);
@@ -801,6 +803,10 @@ void proc_ide_destroy(void)
if ((ali_display_info) && (ali_proc))
remove_proc_entry("ide/ali",0);
#endif /* CONFIG_BLK_DEV_ALI15X3 */
+#ifdef CONFIG_BLK_DEV_PIIX
+ if ((piix_display_info) && (piix_proc))
+ remove_proc_entry("ide/piix",0);
+#endif /* CONFIG_BLK_DEV_PIIX */
#ifdef CONFIG_BLK_DEV_SIS5513
if ((sis_display_info) && (sis_proc))
remove_proc_entry("ide/sis", 0);
@@ -809,6 +815,7 @@ void proc_ide_destroy(void)
if ((via_display_info) && (via_proc))
remove_proc_entry("ide/via",0);
#endif /* CONFIG_BLK_DEV_VIA82CXXX */
+
remove_proc_entry("ide/drivers", 0);
destroy_proc_ide_interfaces();
remove_proc_entry("ide", 0);
diff --git a/drivers/block/ide-tape.c b/drivers/block/ide-tape.c
index 5ea3230dc..41a3b5045 100644
--- a/drivers/block/ide-tape.c
+++ b/drivers/block/ide-tape.c
@@ -526,7 +526,7 @@ typedef struct idetape_packet_command_s {
int b_count;
byte *buffer; /* Data buffer */
byte *current_position; /* Pointer into the above buffer */
- void (*callback) (ide_drive_t *); /* Called when this packet command is completed */
+ ide_startstop_t (*callback) (ide_drive_t *); /* Called when this packet command is completed */
byte pc_buffer[IDETAPE_PC_BUFFER_SIZE]; /* Temporary buffer */
unsigned int flags; /* Status/Action bit flags */
} idetape_pc_t;
@@ -1660,7 +1660,7 @@ static void idetape_analyze_error (ide_drive_t *drive,idetape_request_sense_resu
}
}
-static void idetape_request_sense_callback (ide_drive_t *drive)
+static ide_startstop_t idetape_request_sense_callback (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
@@ -1674,6 +1674,7 @@ static void idetape_request_sense_callback (ide_drive_t *drive)
printk (KERN_ERR "Error in REQUEST SENSE itself - Aborting request!\n");
idetape_end_request (0,HWGROUP (drive));
}
+ return ide_stopped;
}
/*
@@ -1705,7 +1706,7 @@ static void idetape_create_request_sense_cmd (idetape_pc_t *pc)
* last packet command. We queue a request sense packet command in
* the head of the request list.
*/
-static void idetape_retry_pc (ide_drive_t *drive)
+static ide_startstop_t idetape_retry_pc (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t *pc;
@@ -1718,6 +1719,7 @@ static void idetape_retry_pc (ide_drive_t *drive)
idetape_create_request_sense_cmd (pc);
set_bit (IDETAPE_IGNORE_DSC, &tape->flags);
idetape_queue_pc_head (drive, pc, rq);
+ return ide_stopped;
}
/*
@@ -1728,7 +1730,7 @@ static void idetape_retry_pc (ide_drive_t *drive)
* algorithm described before idetape_issue_packet_command.
*
*/
-static void idetape_pc_intr (ide_drive_t *drive)
+static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
idetape_status_reg_t status;
@@ -1784,11 +1786,9 @@ static void idetape_pc_intr (ide_drive_t *drive)
#endif /* IDETAPE_DEBUG_LOG */
if (pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
printk (KERN_ERR "ide-tape: I/O error in request sense command\n");
- ide_do_reset (drive);
- return;
+ return ide_do_reset (drive);
}
- idetape_retry_pc (drive); /* Retry operation */
- return;
+ return idetape_retry_pc (drive); /* Retry operation */
}
pc->error = 0;
if (test_bit (PC_WAIT_FOR_DSC, &pc->flags) && !status.b.dsc) { /* Media access command */
@@ -1796,20 +1796,18 @@ static void idetape_pc_intr (ide_drive_t *drive)
tape->dsc_polling_frequency = IDETAPE_DSC_MA_FAST;
tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT;
idetape_postpone_request (drive); /* Allow ide.c to handle other requests */
- return;
+ return ide_stopped;
}
if (tape->failed_pc == pc)
tape->failed_pc=NULL;
- pc->callback(drive); /* Command finished - Call the callback function */
- return;
+ return pc->callback(drive); /* Command finished - Call the callback function */
}
#ifdef CONFIG_BLK_DEV_IDEDMA
if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
printk (KERN_ERR "ide-tape: The tape wants to issue more interrupts in DMA mode\n");
printk (KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n");
(void) HWIF(drive)->dmaproc(ide_dma_off, drive);
- ide_do_reset (drive);
- return;
+ return ide_do_reset (drive);
}
#endif /* CONFIG_BLK_DEV_IDEDMA */
bcount.b.high=IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */
@@ -1818,14 +1816,12 @@ static void idetape_pc_intr (ide_drive_t *drive)
if (ireason.b.cod) {
printk (KERN_ERR "ide-tape: CoD != 0 in idetape_pc_intr\n");
- ide_do_reset (drive);
- return;
+ return ide_do_reset (drive);
}
if (ireason.b.io == test_bit (PC_WRITING, &pc->flags)) { /* Hopefully, we will never get here */
printk (KERN_ERR "ide-tape: We wanted to %s, ", ireason.b.io ? "Write":"Read");
printk (KERN_ERR "but the tape wants us to %s !\n",ireason.b.io ? "Read":"Write");
- ide_do_reset (drive);
- return;
+ return ide_do_reset (drive);
}
if (!test_bit (PC_WRITING, &pc->flags)) { /* Reading - Check that we have enough space */
temp = pc->actually_transferred + bcount.all;
@@ -1834,7 +1830,7 @@ static void idetape_pc_intr (ide_drive_t *drive)
printk (KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n");
idetape_discard_data (drive,bcount.all);
ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD,NULL);
- return;
+ return ide_started;
}
#if IDETAPE_DEBUG_LOG
printk (KERN_NOTICE "ide-tape: The tape wants to send us more data than expected - allowing transfer\n");
@@ -1856,6 +1852,7 @@ static void idetape_pc_intr (ide_drive_t *drive)
pc->current_position+=bcount.all;
ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD,NULL); /* And set the interrupt handler again */
+ return ide_started;
}
/*
@@ -1901,16 +1898,17 @@ static void idetape_pc_intr (ide_drive_t *drive)
*
*/
-static void idetape_transfer_pc(ide_drive_t *drive)
+static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t *pc = tape->pc;
idetape_ireason_reg_t ireason;
int retries = 100;
+ ide_startstop_t startstop;
- if (ide_wait_stat (drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) {
+ if (ide_wait_stat(&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) {
printk (KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n");
- return;
+ return startstop;
}
ireason.all=IN_BYTE (IDE_IREASON_REG);
while (retries-- && (!ireason.b.cod || ireason.b.io)) {
@@ -1925,14 +1923,14 @@ static void idetape_transfer_pc(ide_drive_t *drive)
}
if (!ireason.b.cod || ireason.b.io) {
printk (KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing a packet command\n");
- ide_do_reset (drive);
- return;
+ return ide_do_reset (drive);
}
ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* Set the interrupt routine */
atapi_output_bytes (drive,pc->c,12); /* Send the actual packet */
+ return ide_started;
}
-static void idetape_issue_packet_command (ide_drive_t *drive, idetape_pc_t *pc)
+static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape_pc_t *pc)
{
idetape_tape_t *tape = drive->driver_data;
idetape_bcount_reg_t bcount;
@@ -1961,8 +1959,7 @@ static void idetape_issue_packet_command (ide_drive_t *drive, idetape_pc_t *pc)
pc->error = IDETAPE_ERROR_GENERAL; /* Giving up */
}
tape->failed_pc=NULL;
- pc->callback(drive);
- return;
+ return pc->callback(drive);
}
#if IDETAPE_DEBUG_LOG
printk (KERN_INFO "Retry number - %d\n",pc->retries);
@@ -1997,13 +1994,14 @@ static void idetape_issue_packet_command (ide_drive_t *drive, idetape_pc_t *pc)
if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL);
OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG);
+ return ide_started;
} else {
OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG);
- idetape_transfer_pc(drive);
+ return idetape_transfer_pc(drive);
}
}
-static void idetape_media_access_finished (ide_drive_t *drive)
+static ide_startstop_t idetape_media_access_finished (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t *pc = tape->pc;
@@ -2013,8 +2011,7 @@ static void idetape_media_access_finished (ide_drive_t *drive)
if (status.b.dsc) {
if (status.b.check) { /* Error detected */
printk (KERN_ERR "ide-tape: %s: I/O error, ",tape->name);
- idetape_retry_pc (drive); /* Retry operation */
- return;
+ return idetape_retry_pc (drive); /* Retry operation */
}
pc->error = 0;
if (tape->failed_pc == pc)
@@ -2023,13 +2020,13 @@ static void idetape_media_access_finished (ide_drive_t *drive)
pc->error = IDETAPE_ERROR_GENERAL;
tape->failed_pc = NULL;
}
- pc->callback (drive);
+ return pc->callback (drive);
}
/*
* General packet command callback function.
*/
-static void idetape_pc_callback (ide_drive_t *drive)
+static ide_startstop_t idetape_pc_callback (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
@@ -2038,9 +2035,10 @@ static void idetape_pc_callback (ide_drive_t *drive)
#endif /* IDETAPE_DEBUG_LOG */
idetape_end_request (tape->pc->error ? 0:1, HWGROUP(drive));
+ return ide_stopped;
}
-static void idetape_rw_callback (ide_drive_t *drive)
+static ide_startstop_t idetape_rw_callback (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
struct request *rq = HWGROUP(drive)->rq;
@@ -2057,6 +2055,7 @@ static void idetape_rw_callback (ide_drive_t *drive)
idetape_end_request (1, HWGROUP (drive));
else
idetape_end_request (tape->pc->error, HWGROUP (drive));
+ return ide_stopped;
}
static void idetape_create_locate_cmd (idetape_pc_t *pc, unsigned int block, byte partition)
@@ -2175,7 +2174,7 @@ static void idetape_create_write_cmd (idetape_tape_t *tape, idetape_pc_t *pc, un
set_bit (PC_DMA_RECOMMENDED, &pc->flags);
}
-static void idetape_read_position_callback (ide_drive_t *drive)
+static ide_startstop_t idetape_read_position_callback (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
idetape_read_position_result_t *result;
@@ -2205,6 +2204,7 @@ static void idetape_read_position_callback (ide_drive_t *drive)
}
} else
idetape_end_request (0,HWGROUP (drive));
+ return ide_stopped;
}
static void idetape_create_read_position_cmd (idetape_pc_t *pc)
@@ -2218,7 +2218,7 @@ static void idetape_create_read_position_cmd (idetape_pc_t *pc)
/*
* idetape_do_request is our request handling function.
*/
-static void idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long block)
+static ide_startstop_t idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long block)
{
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t *pc;
@@ -2234,24 +2234,23 @@ static void idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned
/*
* We do not support buffer cache originated requests.
*/
- printk (KERN_NOTICE "ide-tape: %s: Unsupported command in request queue\n", drive->name);
+ printk (KERN_NOTICE "ide-tape: %s: Unsupported command in request queue (%d)\n", drive->name, rq->cmd);
ide_end_request (0,HWGROUP (drive)); /* Let the common code handle it */
- return;
+ return ide_stopped;
}
/*
* Retry a failed packet command
*/
if (tape->failed_pc != NULL && tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
- idetape_issue_packet_command (drive, tape->failed_pc);
- return;
+ return idetape_issue_packet_command (drive, tape->failed_pc);
}
#if IDETAPE_DEBUG_BUGS
if (postponed_rq != NULL)
if (rq != postponed_rq) {
printk (KERN_ERR "ide-tape: ide-tape.c bug - Two DSC requests were queued\n");
idetape_end_request (0,HWGROUP (drive));
- return;
+ return ide_stopped;
}
#endif /* IDETAPE_DEBUG_BUGS */
@@ -2271,15 +2270,16 @@ static void idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned
tape->dsc_timeout = jiffies + IDETAPE_DSC_RW_TIMEOUT;
} else if ((signed long) (jiffies - tape->dsc_timeout) > 0) {
printk (KERN_ERR "ide-tape: %s: DSC timeout\n", tape->name);
- if (rq->cmd == IDETAPE_PC_RQ2)
+ if (rq->cmd == IDETAPE_PC_RQ2) {
idetape_media_access_finished (drive);
- else
- ide_do_reset (drive);
- return;
+ return ide_stopped;
+ } else {
+ return ide_do_reset (drive);
+ }
} else if (jiffies - tape->dsc_polling_start > IDETAPE_DSC_MA_THRESHOLD)
tape->dsc_polling_frequency = IDETAPE_DSC_MA_SLOW;
idetape_postpone_request (drive);
- return;
+ return ide_stopped;
}
switch (rq->cmd) {
case IDETAPE_READ_RQ:
@@ -2294,20 +2294,20 @@ static void idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned
rq->cmd = IDETAPE_WRITE_RQ;
rq->errors = IDETAPE_ERROR_EOD;
idetape_end_request (1, HWGROUP(drive));
- return;
+ return ide_stopped;
case IDETAPE_PC_RQ1:
pc=(idetape_pc_t *) rq->buffer;
rq->cmd = IDETAPE_PC_RQ2;
break;
case IDETAPE_PC_RQ2:
idetape_media_access_finished (drive);
- return;
+ return ide_stopped;
default:
printk (KERN_ERR "ide-tape: bug in IDETAPE_RQ_CMD macro\n");
idetape_end_request (0,HWGROUP (drive));
- return;
+ return ide_stopped;
}
- idetape_issue_packet_command (drive, pc);
+ return idetape_issue_packet_command (drive, pc);
}
/*
diff --git a/drivers/block/ide.c b/drivers/block/ide.c
index 0f3e41fed..0222f8a0c 100644
--- a/drivers/block/ide.c
+++ b/drivers/block/ide.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/ide.c Version 6.20 July 10, 1999
+ * linux/drivers/block/ide.c Version 6.21 November 9, 1999
*
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
*/
@@ -106,15 +106,18 @@
* ATA-66 compliant, but have yet to determine a method
* of verification of the 80c cable presence.
* Specifically Promise's PDC20262 chipset.
+ * Version 6.21 Fixing/Fixed SMP spinlock issue with insight from an old
+ * hat that clarified original low level driver design.
*
* Some additional driver compile-time options are in ./include/linux/ide.h
*
* To do, in likely order of completion:
* - modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f
-*/
+ *
+ */
-#define REVISION "Revision: 6.20"
-#define VERSION "Id: ide.c 6.20 1999/07/10"
+#define REVISION "Revision: 6.21"
+#define VERSION "Id: ide.c 6.21 1999/11/10"
#undef REALLY_SLOW_IO /* most systems can safely undef this */
@@ -186,7 +189,7 @@ ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */
* For really screwy hardware (hey, at least it *can* be used with Linux)
* we can enforce a minimum delay time between successive operations.
*/
-static unsigned long read_timer(void)
+static unsigned long read_timer (void)
{
unsigned long t, flags;
int i;
@@ -472,7 +475,7 @@ static inline int drive_is_ready (ide_drive_t *drive)
#if 0
udelay(1); /* need to guarantee 400ns since last command was issued */
#endif
- if (GET_STAT() & BUSY_STAT)
+ if (GET_STAT() & BUSY_STAT) /* Note: this may clear a pending IRQ!! */
return 0; /* drive busy: definitely not interrupting */
return 1; /* drive ready: *might* be interrupting */
}
@@ -480,7 +483,7 @@ static inline int drive_is_ready (ide_drive_t *drive)
/*
* This is our end_request replacement function.
*/
-void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup)
+void ide_end_request (byte uptodate, ide_hwgroup_t *hwgroup)
{
struct request *rq;
unsigned long flags;
@@ -490,8 +493,8 @@ void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup)
if (!end_that_request_first(rq, uptodate, hwgroup->drive->name)) {
add_blkdev_randomness(MAJOR(rq->rq_dev));
- hwgroup->drive->queue = rq->next;
- blk_dev[MAJOR(rq->rq_dev)].current_request = NULL;
+ hwgroup->drive->queue.current_request = rq->next;
+ blk_dev[MAJOR(rq->rq_dev)].request_queue.current_request = NULL;
hwgroup->rq = NULL;
end_that_request_last(rq);
}
@@ -511,18 +514,16 @@ void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
unsigned long flags;
ide_hwgroup_t *hwgroup = HWGROUP(drive);
- spin_lock_irqsave(&hwgroup->spinlock, flags);
-#ifdef DEBUG
+ spin_lock_irqsave(&io_request_lock, flags);
if (hwgroup->handler != NULL) {
printk("%s: ide_set_handler: handler not null; old=%p, new=%p\n",
drive->name, hwgroup->handler, handler);
}
-#endif
hwgroup->handler = handler;
hwgroup->expiry = expiry;
hwgroup->timer.expires = jiffies + timeout;
- add_timer(&(hwgroup->timer));
- spin_unlock_irqrestore(&hwgroup->spinlock, flags);
+ add_timer(&hwgroup->timer);
+ spin_unlock_irqrestore(&io_request_lock, flags);
}
/*
@@ -557,7 +558,7 @@ void ide_geninit (struct gendisk *gd)
}
}
-static void do_reset1 (ide_drive_t *, int); /* needed below */
+static ide_startstop_t do_reset1 (ide_drive_t *, int); /* needed below */
/*
* atapi_reset_pollfunc() gets invoked to poll the interface for completion every 50ms
@@ -565,7 +566,7 @@ static void do_reset1 (ide_drive_t *, int); /* needed below */
* and we have not yet hit our maximum waiting time, then the timer is restarted
* for another 50ms.
*/
-static void atapi_reset_pollfunc (ide_drive_t *drive)
+static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
{
ide_hwgroup_t *hwgroup = HWGROUP(drive);
byte stat;
@@ -578,14 +579,14 @@ static void atapi_reset_pollfunc (ide_drive_t *drive)
} else {
if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) {
ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL);
- return; /* continue polling */
+ return ide_started; /* continue polling */
}
hwgroup->poll_timeout = 0; /* end of polling */
printk("%s: ATAPI reset timed-out, status=0x%02x\n", drive->name, stat);
- do_reset1 (drive, 1); /* do it the old fashioned way */
- return;
+ return do_reset1 (drive, 1); /* do it the old fashioned way */
}
hwgroup->poll_timeout = 0; /* done polling */
+ return ide_stopped;
}
/*
@@ -594,7 +595,7 @@ static void atapi_reset_pollfunc (ide_drive_t *drive)
* and we have not yet hit our maximum waiting time, then the timer is restarted
* for another 50ms.
*/
-static void reset_pollfunc (ide_drive_t *drive)
+static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
{
ide_hwgroup_t *hwgroup = HWGROUP(drive);
ide_hwif_t *hwif = HWIF(drive);
@@ -603,7 +604,7 @@ static void reset_pollfunc (ide_drive_t *drive)
if (!OK_STAT(tmp=GET_STAT(), 0, BUSY_STAT)) {
if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) {
ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL);
- return; /* continue polling */
+ return ide_started; /* continue polling */
}
printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp);
} else {
@@ -635,6 +636,7 @@ static void reset_pollfunc (ide_drive_t *drive)
}
}
hwgroup->poll_timeout = 0; /* done polling */
+ return ide_stopped;
}
static void pre_reset (ide_drive_t *drive)
@@ -664,7 +666,7 @@ static void pre_reset (ide_drive_t *drive)
* (up to 30 seconds worstcase). So, instead of busy-waiting here for it,
* we set a timer to poll at 50ms intervals.
*/
-static void do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
+static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
{
unsigned int unit;
unsigned long flags;
@@ -683,7 +685,7 @@ static void do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL);
__restore_flags (flags); /* local CPU only */
- return;
+ return ide_started;
}
/*
@@ -696,7 +698,7 @@ static void do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
#if OK_TO_RESET_CONTROLLER
if (!IDE_CONTROL_REG) {
__restore_flags(flags);
- return;
+ return ide_stopped;
}
/*
* Note that we also set nIEN while resetting the device,
@@ -724,14 +726,15 @@ static void do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
#endif /* OK_TO_RESET_CONTROLLER */
__restore_flags (flags); /* local CPU only */
+ return ide_started;
}
/*
* ide_do_reset() is the entry point to the drive/interface reset code.
*/
-void ide_do_reset (ide_drive_t *drive)
+ide_startstop_t ide_do_reset (ide_drive_t *drive)
{
- do_reset1 (drive, 0);
+ return do_reset1 (drive, 0);
}
/*
@@ -752,16 +755,13 @@ void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err)
}
}
spin_lock_irqsave(&io_request_lock, flags);
- drive->queue = rq->next;
- blk_dev[MAJOR(rq->rq_dev)].current_request = NULL;
+ drive->queue.current_request = rq->next;
+ blk_dev[MAJOR(rq->rq_dev)].request_queue.current_request = NULL;
HWGROUP(drive)->rq = NULL;
rq->rq_status = RQ_INACTIVE;
spin_unlock_irqrestore(&io_request_lock, flags);
- save_flags(flags); /* all CPUs; overkill? */
- cli(); /* all CPUs; overkill? */
if (rq->sem != NULL)
up(rq->sem); /* inform originator that rq has been serviced */
- restore_flags(flags); /* all CPUs; overkill? */
}
/*
@@ -854,19 +854,19 @@ static void try_to_flush_leftover_data (ide_drive_t *drive)
/*
* ide_error() takes action based on the error returned by the drive.
*/
-void ide_error (ide_drive_t *drive, const char *msg, byte stat)
+ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat)
{
struct request *rq;
byte err;
err = ide_dump_status(drive, msg, stat);
if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
- return;
+ return ide_stopped;
/* retry only "normal" I/O: */
if (rq->cmd == IDE_DRIVE_CMD) {
rq->errors = 1;
ide_end_drive_cmd(drive, stat, err);
- return;
+ return ide_stopped;
}
if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */
rq->errors |= ERROR_RESET;
@@ -875,7 +875,7 @@ void ide_error (ide_drive_t *drive, const char *msg, byte stat)
/* err has different meaning on cdrom and tape */
if (err == ABRT_ERR) {
if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY)
- return; /* some newer drives don't support WIN_SPECIFY */
+ return ide_stopped; /* some newer drives don't support WIN_SPECIFY */
} else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR))
; /* UDMA crc error -- just retry the operation */
else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */
@@ -897,19 +897,20 @@ void ide_error (ide_drive_t *drive, const char *msg, byte stat)
} else {
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
++rq->errors;
- ide_do_reset(drive);
- return;
- } else if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
+ return ide_do_reset(drive);
+ }
+ if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
drive->special.b.recalibrate = 1;
++rq->errors;
}
+ return ide_stopped;
}
/*
* Issue a simple drive command
* The drive must be selected beforehand.
*/
-void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
+void ide_cmd (ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
{
ide_set_handler (drive, handler, WAIT_CMD, NULL);
if (IDE_CONTROL_REG)
@@ -921,7 +922,7 @@ void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
/*
* drive_cmd_intr() is invoked on completion of a special DRIVE_CMD.
*/
-static void drive_cmd_intr (ide_drive_t *drive)
+static ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
{
struct request *rq = HWGROUP(drive)->rq;
byte *args = (byte *) rq->buffer;
@@ -938,17 +939,17 @@ static void drive_cmd_intr (ide_drive_t *drive)
udelay(100);
}
- if (OK_STAT(stat, READY_STAT, BAD_STAT))
- ide_end_drive_cmd (drive, stat, GET_ERR());
- else
- ide_error(drive, "drive_cmd", stat); /* calls ide_end_drive_cmd */
+ if (!OK_STAT(stat, READY_STAT, BAD_STAT))
+ return ide_error(drive, "drive_cmd", stat); /* calls ide_end_drive_cmd */
+ ide_end_drive_cmd (drive, stat, GET_ERR());
+ return ide_stopped;
}
/*
* do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT
* commands to a drive. It used to do much more, but has been scaled back.
*/
-static inline void do_special (ide_drive_t *drive)
+static ide_startstop_t do_special (ide_drive_t *drive)
{
special_t *s = &drive->special;
@@ -961,11 +962,12 @@ static inline void do_special (ide_drive_t *drive)
if (tuneproc != NULL)
tuneproc(drive, drive->tune_req);
} else if (drive->driver != NULL) {
- DRIVER(drive)->special(drive);
+ return DRIVER(drive)->special(drive);
} else if (s->all) {
printk("%s: bad special flag: 0x%02x\n", drive->name, s->all);
s->all = 0;
}
+ return ide_stopped;
}
/*
@@ -979,12 +981,11 @@ static inline void do_special (ide_drive_t *drive)
* setting a timer to wake up at half second intervals thereafter,
* until timeout is achieved, before timing out.
*/
-int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeout)
-{
+int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, byte good, byte bad, unsigned long timeout) {
byte stat;
int i;
unsigned long flags;
-
+
udelay(1); /* spec allows drive 400ns to assert "BUSY" */
if ((stat = GET_STAT()) & BUSY_STAT) {
__save_flags(flags); /* local CPU only */
@@ -993,7 +994,7 @@ int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeou
while ((stat = GET_STAT()) & BUSY_STAT) {
if (0 < (signed long)(jiffies - timeout)) {
__restore_flags(flags); /* local CPU only */
- ide_error(drive, "status timeout", stat);
+ *startstop = ide_error(drive, "status timeout", stat);
return 1;
}
}
@@ -1011,7 +1012,7 @@ int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeou
if (OK_STAT((stat = GET_STAT()), good, bad))
return 0;
}
- ide_error(drive, "status error", stat);
+ *startstop = ide_error(drive, "status error", stat);
return 1;
}
@@ -1019,7 +1020,7 @@ int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeou
* execute_drive_cmd() issues a special drive command,
* usually initiated by ioctl() from the external hdparm program.
*/
-static void execute_drive_cmd (ide_drive_t *drive, struct request *rq)
+static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq)
{
byte *args = rq->buffer;
if (args) {
@@ -1033,11 +1034,11 @@ static void execute_drive_cmd (ide_drive_t *drive, struct request *rq)
OUT_BYTE(args[2],IDE_FEATURE_REG);
OUT_BYTE(args[1],IDE_SECTOR_REG);
ide_cmd(drive, args[0], args[3], &drive_cmd_intr);
- return;
+ return ide_started;
}
OUT_BYTE(args[2],IDE_FEATURE_REG);
ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
- return;
+ return ide_started;
} else {
/*
* NULL is actually a valid way of waiting for
@@ -1047,21 +1048,21 @@ static void execute_drive_cmd (ide_drive_t *drive, struct request *rq)
printk("%s: DRIVE_CMD (null)\n", drive->name);
#endif
ide_end_drive_cmd(drive, GET_STAT(), GET_ERR());
- return;
+ return ide_stopped;
}
}
/*
* start_request() initiates handling of a new I/O request
*/
-static inline void start_request (ide_drive_t *drive)
+static ide_startstop_t start_request (ide_drive_t *drive)
{
+ ide_startstop_t startstop;
unsigned long block, blockend;
- struct request *rq = drive->queue;
+ struct request *rq = drive->queue.current_request;
unsigned int minor = MINOR(rq->rq_dev), unit = minor >> PARTN_BITS;
ide_hwif_t *hwif = HWIF(drive);
- ide__sti(); /* local CPU only */
#ifdef DEBUG
printk("%s: start_request: current=0x%08lx\n", hwif->name, (unsigned long) rq);
#endif
@@ -1094,29 +1095,27 @@ static inline void start_request (ide_drive_t *drive)
#endif
SELECT_DRIVE(hwif, drive);
- if (ide_wait_stat(drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) {
+ if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) {
printk("%s: drive not ready for command\n", drive->name);
- return;
+ return startstop;
}
if (!drive->special.all) {
if (rq->cmd == IDE_DRIVE_CMD) {
- execute_drive_cmd(drive, rq);
- return;
+ return execute_drive_cmd(drive, rq);
}
if (drive->driver != NULL) {
- DRIVER(drive)->do_request(drive, rq, block);
- return;
+ return (DRIVER(drive)->do_request(drive, rq, block));
}
printk("%s: media type %d not supported\n", drive->name, drive->media);
goto kill_rq;
}
- do_special(drive);
- return;
+ return do_special(drive);
kill_rq:
if (drive->driver != NULL)
DRIVER(drive)->end_request(0, HWGROUP(drive));
else
ide_end_request(0, HWGROUP(drive));
+ return ide_stopped;
}
/*
@@ -1143,13 +1142,13 @@ repeat:
best = NULL;
drive = hwgroup->drive;
do {
- if (drive->queue && (!drive->sleep || 0 <= (signed long)(jiffies - drive->sleep))) {
+ if (drive->queue.current_request && (!drive->sleep || 0 <= (signed long)(jiffies - drive->sleep))) {
if (!best
|| (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep)))
|| (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive))))
{
struct blk_dev_struct *bdev = &blk_dev[HWIF(drive)->major];
- if (bdev->current_request != &bdev->plug)
+ if( !bdev->request_queue.plugged )
best = drive;
}
}
@@ -1177,280 +1176,272 @@ repeat:
}
/*
- * Caller must have already acquired spinlock using *spinflags
+ * Issue a new request to a drive from hwgroup
+ * Caller must have already done spin_lock_irqsave(&io_request_lock, ..);
+ *
+ * A hwgroup is a serialized group of IDE interfaces. Usually there is
+ * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640)
+ * may have both interfaces in a single hwgroup to "serialize" access.
+ * Or possibly multiple ISA interfaces can share a common IRQ by being grouped
+ * together into one hwgroup for serialized access.
+ *
+ * Note also that several hwgroups can end up sharing a single IRQ,
+ * possibly along with many other devices. This is especially common in
+ * PCI-based systems with off-board IDE controller cards.
+ *
+ * The IDE driver uses the single global io_request_lock spinlock to protect
+ * access to the request queues, and to protect the hwgroup->busy flag.
+ *
+ * The first thread into the driver for a particular hwgroup sets the
+ * hwgroup->busy flag to indicate that this hwgroup is now active,
+ * and then initiates processing of the top request from the request queue.
+ *
+ * Other threads attempting entry notice the busy setting, and will simply
+ * queue their new requests and exit immediately. Note that hwgroup->busy
+ * remains set even when the driver is merely awaiting the next interrupt.
+ * Thus, the meaning is "this hwgroup is busy processing a request".
+ *
+ * When processing of a request completes, the completing thread or IRQ-handler
+ * will start the next request from the queue. If no more work remains,
+ * the driver will clear the hwgroup->busy flag and exit.
+ *
+ * The io_request_lock (spinlock) is used to protect all access to the
+ * hwgroup->busy flag, but is otherwise not needed for most processing in
+ * the driver. This makes the driver much more friendlier to shared IRQs
+ * than previous designs, while remaining 100% (?) SMP safe and capable.
*/
-static void ide_do_request (ide_hwgroup_t *hwgroup, unsigned long *hwgroup_flags, int masked_irq)
+static void ide_do_request (ide_hwgroup_t *hwgroup)
{
struct blk_dev_struct *bdev;
ide_drive_t *drive;
ide_hwif_t *hwif;
- unsigned long io_flags;
+ ide_startstop_t startstop;
+
+ ide_get_lock(&ide_lock, ide_intr, hwgroup); /* for atari only: POSSIBLY BROKEN HERE(?) */
- hwgroup->busy = 1;
- while (hwgroup->handler == NULL) {
- spin_lock_irqsave(&io_request_lock, io_flags);
+ while (!hwgroup->busy) {
+ hwgroup->busy = 1;
drive = choose_drive(hwgroup);
if (drive == NULL) {
unsigned long sleep = 0;
-
hwgroup->rq = NULL;
drive = hwgroup->drive;
do {
bdev = &blk_dev[HWIF(drive)->major];
- if (bdev->current_request != &bdev->plug) /* FIXME: this will do for now */
- bdev->current_request = NULL; /* (broken since patch-2.1.15) */
+ if( !bdev->request_queue.plugged )
+ bdev->request_queue.current_request = NULL; /* (broken since patch-2.1.15) */
if (drive->sleep && (!sleep || 0 < (signed long)(sleep - drive->sleep)))
sleep = drive->sleep;
} while ((drive = drive->next) != hwgroup->drive);
- spin_unlock_irqrestore(&io_request_lock, io_flags);
if (sleep) {
+ /*
+ * Take a short snooze, and then wake up this hwgroup again.
+ * This gives other hwgroups on the same a chance to
+ * play fairly with us, just in case there are big differences
+ * in relative throughputs.. don't want to hog the cpu too much.
+ */
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
+ hwgroup->sleeping = 1; /* so that ide_timer_expiry knows what to do */
mod_timer(&hwgroup->timer, sleep);
+ /* we purposely leave hwgroup->busy==1 while sleeping */
} else {
/* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_scheduler? */
ide_release_lock(&ide_lock); /* for atari only */
+ hwgroup->busy = 0;
}
- hwgroup->busy = 0;
- return;
+ return; /* no more work for this hwgroup (for now) */
}
hwif = HWIF(drive);
- if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif &&
- hwif->io_ports[IDE_CONTROL_OFFSET])
+ if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif && hwif->io_ports[IDE_CONTROL_OFFSET]) {
/* set nIEN for previous hwif */
OUT_BYTE(hwgroup->drive->ctl|2, hwgroup->hwif->io_ports[IDE_CONTROL_OFFSET]);
+ }
hwgroup->hwif = hwif;
hwgroup->drive = drive;
drive->sleep = 0;
drive->service_start = jiffies;
bdev = &blk_dev[hwif->major];
- if (bdev->current_request == &bdev->plug) /* FIXME: paranoia */
+ if( bdev->request_queue.plugged ) /* FIXME: paranoia */
printk("%s: Huh? nuking plugged queue\n", drive->name);
- bdev->current_request = hwgroup->rq = drive->queue;
- spin_unlock_irqrestore(&io_request_lock, io_flags);
-
-#if 0
- if (hwif->irq != masked_irq)
- disable_irq_nosync(hwif->irq);
- spin_unlock_irqrestore(&hwgroup->spinlock, *hwgroup_flags);
- start_request(drive);
- spin_lock_irqsave(&hwgroup->spinlock, *hwgroup_flags);
- if (hwif->irq != masked_irq)
- enable_irq(hwif->irq);
-#else
-
- if (masked_irq && hwif->irq != masked_irq) {
- printk("%s: (disable_irq) %smasked_irq %d\n",
- drive->name,
- masked_irq ? "" : "un_", hwif->irq);
-
-#if 0
- disable_irq(hwif->irq);
-#else
- disable_irq_nosync(hwif->irq);
-#endif
- }
- spin_unlock_irqrestore(&hwgroup->spinlock, *hwgroup_flags);
- start_request(drive);
- spin_lock_irqsave(&hwgroup->spinlock, *hwgroup_flags);
- if (masked_irq && hwif->irq != masked_irq) {
- printk("%s: (enable_irq) %smasked_irq %d\n",
- drive->name,
- masked_irq ? "" : "un_", hwif->irq);
- enable_irq(hwif->irq);
- }
-#endif
+ bdev->request_queue.current_request = hwgroup->rq = drive->queue.current_request;
+ spin_unlock(&io_request_lock);
+ if (!hwif->serialized) /* play it safe with buggy hardware */
+ ide__sti();
+ startstop = start_request(drive);
+ spin_lock_irq(&io_request_lock);
+ if (startstop == ide_stopped)
+ hwgroup->busy = 0;
}
}
/*
* ide_get_queue() returns the queue which corresponds to a given device.
*/
-struct request **ide_get_queue (kdev_t dev)
+request_queue_t *ide_get_queue (kdev_t dev)
{
ide_hwif_t *hwif = (ide_hwif_t *)blk_dev[MAJOR(dev)].data;
return &hwif->drives[DEVICE_NR(dev) & 1].queue;
}
-/*
- * do_hwgroup_request() invokes ide_do_request() after claiming hwgroup->busy.
- */
-static void do_hwgroup_request (ide_hwgroup_t *hwgroup)
+void do_ide0_request (request_queue_t *q)
{
- unsigned long flags;
-
- spin_lock_irqsave(&hwgroup->spinlock, flags);
- if (hwgroup->busy) {
- spin_unlock_irqrestore(&hwgroup->spinlock, flags);
- return;
- }
- del_timer(&hwgroup->timer);
- ide_get_lock(&ide_lock, ide_intr, hwgroup); /* for atari only */
- ide_do_request(hwgroup, &flags, 0);
- spin_unlock_irqrestore(&hwgroup->spinlock, flags);
-}
-
-/*
- * ll_rw_blk.c invokes our do_idex_request() function
- * with the io_request_spinlock already grabbed.
- * Since we need to do our own spinlock's internally,
- * on paths that don't necessarily originate through the
- * do_idex_request() path, we have to undo the spinlock on entry,
- * and restore it again on exit.
- * Fortunately, this is mostly a nop for non-SMP kernels.
- */
-static inline void unlock_do_hwgroup_request (ide_hwgroup_t *hwgroup)
-{
- spin_unlock(&io_request_lock);
- do_hwgroup_request (hwgroup);
- spin_lock_irq(&io_request_lock);
-}
-
-void do_ide0_request (void)
-{
- unlock_do_hwgroup_request (ide_hwifs[0].hwgroup);
+ ide_do_request (ide_hwifs[0].hwgroup);
}
#if MAX_HWIFS > 1
-void do_ide1_request (void)
+void do_ide1_request (request_queue_t *q)
{
- unlock_do_hwgroup_request (ide_hwifs[1].hwgroup);
+ ide_do_request (ide_hwifs[1].hwgroup);
}
#endif /* MAX_HWIFS > 1 */
#if MAX_HWIFS > 2
-void do_ide2_request (void)
+void do_ide2_request (request_queue_t *q)
{
- unlock_do_hwgroup_request (ide_hwifs[2].hwgroup);
+ ide_do_request (ide_hwifs[2].hwgroup);
}
#endif /* MAX_HWIFS > 2 */
#if MAX_HWIFS > 3
-void do_ide3_request (void)
+void do_ide3_request (request_queue_t *q)
{
- unlock_do_hwgroup_request (ide_hwifs[3].hwgroup);
+ ide_do_request (ide_hwifs[3].hwgroup);
}
#endif /* MAX_HWIFS > 3 */
#if MAX_HWIFS > 4
-void do_ide4_request (void)
+void do_ide4_request (request_queue_t *q)
{
- unlock_do_hwgroup_request (ide_hwifs[4].hwgroup);
+ ide_do_request (ide_hwifs[4].hwgroup);
}
#endif /* MAX_HWIFS > 4 */
#if MAX_HWIFS > 5
-void do_ide5_request (void)
+void do_ide5_request (request_queue_t *q)
{
- unlock_do_hwgroup_request (ide_hwifs[5].hwgroup);
+ ide_do_request (ide_hwifs[5].hwgroup);
}
#endif /* MAX_HWIFS > 5 */
#if MAX_HWIFS > 6
-void do_ide6_request (void)
+void do_ide6_request (request_queue_t *q)
{
- unlock_do_hwgroup_request (ide_hwifs[6].hwgroup);
+ ide_do_request (ide_hwifs[6].hwgroup);
}
#endif /* MAX_HWIFS > 6 */
#if MAX_HWIFS > 7
-void do_ide7_request (void)
+void do_ide7_request (request_queue_t *q)
{
- unlock_do_hwgroup_request (ide_hwifs[7].hwgroup);
+ ide_do_request (ide_hwifs[7].hwgroup);
}
#endif /* MAX_HWIFS > 7 */
#if MAX_HWIFS > 8
-void do_ide8_request (void)
+void do_ide8_request (request_queue_t *q)
{
- unlock_do_hwgroup_request (ide_hwifs[8].hwgroup);
+ ide_do_request (ide_hwifs[8].hwgroup);
}
#endif /* MAX_HWIFS > 8 */
#if MAX_HWIFS > 9
-void do_ide9_request (void)
+void do_ide9_request (request_queue_t *q)
{
- unlock_do_hwgroup_request (ide_hwifs[9].hwgroup);
+ ide_do_request (ide_hwifs[9].hwgroup);
}
#endif /* MAX_HWIFS > 9 */
-static void start_next_request (ide_hwgroup_t *hwgroup, int masked_irq)
-{
- unsigned long flags;
- ide_drive_t *drive;
-
- spin_lock_irqsave(&hwgroup->spinlock, flags);
- if (hwgroup->handler != NULL) {
- spin_unlock_irqrestore(&hwgroup->spinlock, flags);
- return;
- }
- drive = hwgroup->drive;
- set_recovery_timer(HWIF(drive));
- drive->service_time = jiffies - drive->service_start;
- ide_do_request(hwgroup, &flags, masked_irq);
- spin_unlock_irqrestore(&hwgroup->spinlock, flags);
-}
-
+/*
+ * ide_timer_expiry() is our timeout function for all drive operations.
+ * But note that it can also be invoked as a result of a "sleep" operation
+ * triggered by the mod_timer() call in ide_do_request.
+ */
void ide_timer_expiry (unsigned long data)
{
- ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data;
- ide_drive_t *drive;
- ide_handler_t *handler;
- ide_expiry_t *expiry;
- unsigned long flags;
- unsigned long wait;
+ ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data;
+ ide_handler_t *handler;
+ ide_expiry_t *expiry;
+ unsigned long flags;
+ unsigned long wait;
- spin_lock_irqsave(&hwgroup->spinlock, flags);
- drive = hwgroup->drive;
- if ((handler = hwgroup->handler) == NULL) {
- spin_unlock_irqrestore(&hwgroup->spinlock, flags);
- do_hwgroup_request(hwgroup);
- return;
- }
-
- hwgroup->busy = 1; /* should already be "1" */
+ spin_lock_irqsave(&io_request_lock, flags);
+ del_timer(&hwgroup->timer);
- if ((expiry = hwgroup->expiry) != NULL) {
- /* continue */
- if ((wait = expiry(drive)) != 0) {
- /* reset timer */
- hwgroup->timer.expires = jiffies + wait;
- add_timer(&(hwgroup->timer));
- spin_unlock_irqrestore(&hwgroup->spinlock, flags);
- return;
+ if ((handler = hwgroup->handler) == NULL) {
+ /*
+ * Either a marginal timeout occured
+ * (got the interrupt just as timer expired),
+ * or we were "sleeping" to give other devices a chance.
+ * Either way, we don't really want to complain about anything.
+ */
+ if (hwgroup->sleeping) {
+ hwgroup->sleeping = 0;
+ hwgroup->busy = 0;
}
- }
-
- hwgroup->handler = NULL;
-
- if (hwgroup->poll_timeout != 0) {
- spin_unlock_irqrestore(&hwgroup->spinlock, flags);
- handler(drive);
- } else if (drive_is_ready(drive)) {
- printk("%s: lost interrupt\n", drive->name);
- (void) hwgroup->hwif->dmaproc(ide_dma_lostirq, drive);
- spin_unlock_irqrestore(&hwgroup->spinlock, flags);
- handler(drive);
} else {
- if (drive->waiting_for_dma) {
- (void) hwgroup->hwif->dmaproc(ide_dma_end, drive);
- printk("%s: timeout waiting for DMA\n", drive->name);
- /*
- * need something here for HPT34X.......AMH
- * irq timeout: status=0x58 { DriveReady SeekComplete DataRequest }
- */
- (void) hwgroup->hwif->dmaproc(ide_dma_timeout, drive);
+ ide_drive_t *drive = hwgroup->drive;
+ hwgroup->handler = NULL;
+ if (!drive) {
+ printk("ide_timer_expiry: hwgroup->drive was NULL\n");
+ } else {
+ ide_hwif_t *hwif;
+ ide_startstop_t startstop;
+ if (!hwgroup->busy) {
+ hwgroup->busy = 1; /* paranoia */
+ printk("%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name);
+ }
+ if ((expiry = hwgroup->expiry) != NULL) {
+ /* continue */
+ if ((wait = expiry(drive)) != 0) {
+ /* reset timer */
+ hwgroup->timer.expires = jiffies + wait;
+ add_timer(&hwgroup->timer);
+ spin_unlock_irqrestore(&io_request_lock, flags);
+ return;
+ }
+ }
+ /*
+ * We need to simulate a real interrupt when invoking
+ * the handler() function, which means we need to globally
+ * mask the specific IRQ:
+ */
+ spin_unlock(&io_request_lock);
+ hwif = HWIF(drive);
+ disable_irq(hwif->irq);
+ __cli(); /* local CPU only, as if we were handling an interrupt */
+ if (hwgroup->poll_timeout != 0) {
+ startstop = handler(drive);
+ } else if (drive_is_ready(drive)) {
+ if (drive->waiting_for_dma)
+ (void) hwgroup->hwif->dmaproc(ide_dma_lostirq, drive);
+ (void)ide_ack_intr(hwif);
+ printk("%s: lost interrupt\n", drive->name);
+ startstop = handler(drive);
+ } else {
+ if (drive->waiting_for_dma) {
+ (void) hwgroup->hwif->dmaproc(ide_dma_end, drive);
+ printk("%s: timeout waiting for DMA\n", drive->name);
+ (void) hwgroup->hwif->dmaproc(ide_dma_timeout, drive);
+ }
+ startstop = ide_error(drive, "irq timeout", GET_STAT());
+ }
+ set_recovery_timer(hwif);
+ drive->service_time = jiffies - drive->service_start;
+ enable_irq(hwif->irq);
+ spin_lock_irq(&io_request_lock);
+ if (startstop == ide_stopped)
+ hwgroup->busy = 0;
}
- spin_unlock_irqrestore(&hwgroup->spinlock, flags);
- ide_error(drive, "irq timeout", GET_STAT());
}
- start_next_request(hwgroup, 0);
+ ide_do_request(hwgroup);
+ spin_unlock_irqrestore(&io_request_lock, flags);
}
/*
@@ -1500,6 +1491,7 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
}
} while ((hwif = hwif->next) != hwgroup->hwif);
}
+
/*
* entry point for all interrupts, caller does __cli() for us
*/
@@ -1510,13 +1502,13 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
ide_hwif_t *hwif;
ide_drive_t *drive;
ide_handler_t *handler;
+ ide_startstop_t startstop;
- __cli(); /* local CPU only */
- spin_lock_irqsave(&hwgroup->spinlock, flags);
+ spin_lock_irqsave(&io_request_lock, flags);
hwif = hwgroup->hwif;
if (!ide_ack_intr(hwif)) {
- spin_unlock_irqrestore(&hwgroup->spinlock, flags);
+ spin_unlock_irqrestore(&io_request_lock, flags);
return;
}
@@ -1542,29 +1534,72 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
* so we can safely try to do something about it:
*/
unexpected_intr(irq, hwgroup);
+#ifdef CONFIG_BLK_DEV_IDEPCI
+ } else {
+ /*
+ * Whack the status register, just in case we have a leftover pending IRQ.
+ *
+ * Unless we are some version of a Promise Ultra66 :: PDC20262.
+ * We will hang like a rock....
+ */
+ byte skip_status = ((hwif->pci_dev->device == PCI_DEVICE_ID_PROMISE_20262) ||
+ (hwif->pci_dev->device == PCI_DEVICE_ID_TTI_HPT366)) ? 1 : 0;
+ if (!skip_status)
+ (void) IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]);
+#endif /* CONFIG_BLK_DEV_IDEPCI */
}
- spin_unlock_irqrestore(&hwgroup->spinlock, flags);
+ spin_unlock_irqrestore(&io_request_lock, flags);
return;
}
drive = hwgroup->drive;
- if (!drive || !drive_is_ready(drive)) {
- spin_unlock_irqrestore(&hwgroup->spinlock, flags);
+ if (!drive) {
+ /*
+ * This should NEVER happen, and there isn't much we could do about it here.
+ */
+ spin_unlock_irqrestore(&io_request_lock, flags);
return;
}
+ if (!drive_is_ready(drive)) {
+ /*
+ * This happens regularly when we share a PCI IRQ with another device.
+ * Unfortunately, it can also happen with some buggy drives that trigger
+ * the IRQ before their status register is up to date. Hopefully we have
+ * enough advance overhead that the latter isn't a problem.
+ */
+ spin_unlock_irqrestore(&io_request_lock, flags);
+ return;
+ }
+ if (!hwgroup->busy) {
+ hwgroup->busy = 1; /* paranoia */
+ printk("%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name);
+ }
hwgroup->handler = NULL;
- del_timer(&(hwgroup->timer));
- spin_unlock_irqrestore(&hwgroup->spinlock, flags);
+ del_timer(&hwgroup->timer);
+ spin_unlock(&io_request_lock);
+
if (drive->unmask)
ide__sti(); /* local CPU only */
- handler(drive); /* service this interrupt, may set handler for next interrupt */
+ startstop = handler(drive); /* service this interrupt, may set handler for next interrupt */
+ spin_lock_irq(&io_request_lock);
+
/*
* Note that handler() may have set things up for another
* interrupt to occur soon, but it cannot happen until
* we exit from this routine, because it will be the
- * same irq as is currently being serviced here,
- * and Linux won't allow another (on any CPU) until we return.
+ * same irq as is currently being serviced here, and Linux
+ * won't allow another of the same (on any CPU) until we return.
*/
- start_next_request(hwgroup, hwif->irq);
+ set_recovery_timer(HWIF(drive));
+ drive->service_time = jiffies - drive->service_start;
+ if (startstop == ide_stopped) {
+ if (hwgroup->handler == NULL) { /* paranoia */
+ hwgroup->busy = 0;
+ ide_do_request(hwgroup);
+ } else {
+ printk("%s: ide_intr: huh? expected NULL handler on exit\n", drive->name);
+ }
+ }
+ spin_unlock_irqrestore(&io_request_lock, flags);
}
/*
@@ -1649,12 +1684,11 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
rq->rq_dev = MKDEV(major,(drive->select.b.unit)<<PARTN_BITS);
if (action == ide_wait)
rq->sem = &sem;
-
spin_lock_irqsave(&io_request_lock, flags);
- cur_rq = drive->queue;
+ cur_rq = drive->queue.current_request;
if (cur_rq == NULL || action == ide_preempt) {
rq->next = cur_rq;
- drive->queue = rq;
+ drive->queue.current_request = rq;
if (action == ide_preempt)
hwgroup->rq = NULL;
} else {
@@ -1665,13 +1699,14 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
rq->next = cur_rq->next;
cur_rq->next = rq;
}
+ ide_do_request(hwgroup);
spin_unlock_irqrestore(&io_request_lock, flags);
- do_hwgroup_request(hwgroup);
if (action == ide_wait) {
- down(&sem); /* wait for it to be serviced */
- rq->sem = NULL;
+ down(&sem); /* wait for it to be serviced */
+ return rq->errors ? -EIO : 0; /* return -EIO if errors */
}
- return rq->errors ? -EIO : 0; /* return -EIO if errors */
+ return 0;
+
}
/*
@@ -1682,7 +1717,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
* usage == 1 (we need an open channel to use an ioctl :-), so this
* is our limit.
*/
-int ide_revalidate_disk(kdev_t i_rdev)
+int ide_revalidate_disk (kdev_t i_rdev)
{
ide_drive_t *drive;
ide_hwgroup_t *hwgroup;
@@ -1694,14 +1729,14 @@ int ide_revalidate_disk(kdev_t i_rdev)
major = MAJOR(i_rdev);
minor = drive->select.b.unit << PARTN_BITS;
hwgroup = HWGROUP(drive);
- spin_lock_irqsave(&hwgroup->spinlock, flags);
+ spin_lock_irqsave(&io_request_lock, flags);
if (drive->busy || (drive->usage > 1)) {
- spin_unlock_irqrestore(&hwgroup->spinlock, flags);
+ spin_unlock_irqrestore(&io_request_lock, flags);
return -EBUSY;
};
drive->busy = 1;
MOD_INC_USE_COUNT;
- spin_unlock_irqrestore(&hwgroup->spinlock, flags);
+ spin_unlock_irqrestore(&io_request_lock, flags);
for (p = 0; p < (1<<PARTN_BITS); ++p) {
if (drive->part[p].nr_sects > 0) {
@@ -1767,7 +1802,7 @@ static void ide_init_module (int type)
#endif /* CONFIG_KMOD */
}
-static int ide_open(struct inode * inode, struct file * filp)
+static int ide_open (struct inode * inode, struct file * filp)
{
ide_drive_t *drive;
int rc;
@@ -1807,7 +1842,7 @@ static int ide_open(struct inode * inode, struct file * filp)
* Releasing a block device means we sync() it, so that it can safely
* be forgotten about...
*/
-static int ide_release(struct inode * inode, struct file * file)
+static int ide_release (struct inode * inode, struct file * file)
{
ide_drive_t *drive;
@@ -1821,7 +1856,7 @@ static int ide_release(struct inode * inode, struct file * file)
return 0;
}
-int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
+int ide_replace_subdriver (ide_drive_t *drive, const char *driver)
{
if (!drive->present || drive->busy || drive->usage)
goto abort;
@@ -1960,7 +1995,7 @@ void ide_unregister (unsigned int index)
kfree(blksize_size[hwif->major]);
kfree(max_sectors[hwif->major]);
kfree(max_readahead[hwif->major]);
- blk_dev[hwif->major].request_fn = NULL;
+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(hwif->major));
blk_dev[hwif->major].data = NULL;
blk_dev[hwif->major].queue = NULL;
blksize_size[hwif->major] = NULL;
@@ -1979,6 +2014,7 @@ void ide_unregister (unsigned int index)
init_hwif_data (index); /* restore hwif data to pristine status */
hwif->hwgroup = old_hwif.hwgroup;
hwif->tuneproc = old_hwif.tuneproc;
+ hwif->resetproc = old_hwif.resetproc;
hwif->dmaproc = old_hwif.dmaproc;
hwif->dma_base = old_hwif.dma_base;
hwif->dma_extra = old_hwif.dma_extra;
@@ -2089,7 +2125,7 @@ int ide_register (int arg1, int arg2, int irq)
return ide_register_hw(&hw, NULL);
}
-void ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
+void ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
{
ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
@@ -2115,7 +2151,7 @@ abort:
kfree(setting);
}
-void ide_remove_setting(ide_drive_t *drive, char *name)
+void ide_remove_setting (ide_drive_t *drive, char *name)
{
ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting;
@@ -2128,7 +2164,7 @@ void ide_remove_setting(ide_drive_t *drive, char *name)
kfree(setting);
}
-static ide_settings_t *ide_find_setting_by_ioctl(ide_drive_t *drive, int cmd)
+static ide_settings_t *ide_find_setting_by_ioctl (ide_drive_t *drive, int cmd)
{
ide_settings_t *setting = drive->settings;
@@ -2140,7 +2176,7 @@ static ide_settings_t *ide_find_setting_by_ioctl(ide_drive_t *drive, int cmd)
return setting;
}
-ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name)
+ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name)
{
ide_settings_t *setting = drive->settings;
@@ -2152,7 +2188,7 @@ ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name)
return setting;
}
-static void auto_remove_settings(ide_drive_t *drive)
+static void auto_remove_settings (ide_drive_t *drive)
{
ide_settings_t *setting;
repeat:
@@ -2166,13 +2202,13 @@ repeat:
}
}
-int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
+int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting)
{
int val = -EINVAL;
unsigned long flags;
if ((setting->rw & SETTING_READ)) {
- spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
+ spin_lock_irqsave(&io_request_lock, flags);
switch(setting->data_type) {
case TYPE_BYTE:
val = *((u8 *) setting->data);
@@ -2185,7 +2221,7 @@ int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
val = *((u32 *) setting->data);
break;
}
- spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
+ spin_unlock_irqrestore(&io_request_lock, flags);
}
return val;
}
@@ -2195,20 +2231,29 @@ int ide_spin_wait_hwgroup (ide_drive_t *drive, unsigned long *flags)
ide_hwgroup_t *hwgroup = HWGROUP(drive);
unsigned long timeout = jiffies + (3 * HZ);
- spin_lock_irqsave(&hwgroup->spinlock, *flags);
+ spin_lock_irqsave(&io_request_lock, *flags);
while (hwgroup->busy) {
- spin_unlock_irqrestore(&hwgroup->spinlock, *flags);
- __sti(); /* local CPU only; needed for jiffies */
+ unsigned long lflags;
+ spin_unlock_irqrestore(&io_request_lock, *flags);
+ __save_flags(lflags); /* local CPU only */
+ __sti(); /* local CPU only; needed for jiffies */
if (0 < (signed long)(jiffies - timeout)) {
+ __restore_flags(lflags); /* local CPU only */
printk("%s: channel busy\n", drive->name);
return -EBUSY;
}
- spin_lock_irqsave(&hwgroup->spinlock, *flags);
+ __restore_flags(lflags); /* local CPU only */
+ spin_lock_irqsave(&io_request_lock, *flags);
}
return 0;
}
-int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val)
+/*
+ * FIXME: This should be changed to enqueue a special request
+ * to the driver to change settings, and then wait on a sema for completion.
+ * The current scheme of polling is kludgey, though safe enough.
+ */
+int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val)
{
unsigned long flags;
int i;
@@ -2240,7 +2285,7 @@ int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val)
*p = val;
break;
}
- spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
+ spin_unlock_irqrestore(&io_request_lock, flags);
return 0;
}
@@ -2254,7 +2299,7 @@ static int set_io_32bit(ide_drive_t *drive, int arg)
return 0;
}
-static int set_using_dma(ide_drive_t *drive, int arg)
+static int set_using_dma (ide_drive_t *drive, int arg)
{
if (!drive->driver || !DRIVER(drive)->supports_dma)
return -EPERM;
@@ -2265,7 +2310,7 @@ static int set_using_dma(ide_drive_t *drive, int arg)
return 0;
}
-static int set_pio_mode(ide_drive_t *drive, int arg)
+static int set_pio_mode (ide_drive_t *drive, int arg)
{
struct request rq;
@@ -2280,7 +2325,7 @@ static int set_pio_mode(ide_drive_t *drive, int arg)
return 0;
}
-void ide_add_generic_settings(ide_drive_t *drive)
+void ide_add_generic_settings (ide_drive_t *drive)
{
/*
* drive setting name read/write access read ioctl write ioctl data type min max mul_factor div_factor data pointer set function
@@ -2325,136 +2370,6 @@ void ide_delay_50ms (void)
while (0 < (signed long)(timeout - jiffies));
}
-int ide_config_drive_speed (ide_drive_t *drive, byte speed)
-{
- struct hd_driveid *id = drive->id;
- unsigned long flags;
- int err;
-
- __save_flags(flags); /* local CPU only */
- __cli(); /* local CPU only */
-
- /*
- * Don't use ide_wait_cmd here - it will
- * attempt to set_geometry and recalibrate,
- * but for some reason these don't work at
- * this point (lost interrupt).
- */
- SELECT_DRIVE(HWIF(drive), drive);
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
- OUT_BYTE(speed, IDE_NSECTOR_REG);
- OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
- OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG);
-
- err = ide_wait_stat(drive, DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT, WAIT_CMD);
-
-#if 0
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl, IDE_CONTROL_REG);
-#endif
-
- __restore_flags(flags); /* local CPU only */
-
- switch(speed) {
- case XFER_UDMA_4:
- if (!((id->dma_ultra >> 8) & 16)) {
- drive->id->dma_ultra &= ~0xFF00;
- drive->id->dma_ultra |= 0x1010;
- }
- drive->id->dma_mword &= ~0x0F00;
- drive->id->dma_1word &= ~0x0F00;
- break;
- case XFER_UDMA_3:
- if (!((id->dma_ultra >> 8) & 8)) {
- drive->id->dma_ultra &= ~0xFF00;
- drive->id->dma_ultra |= 0x0808;
- }
- drive->id->dma_mword &= ~0x0F00;
- drive->id->dma_1word &= ~0x0F00;
- break;
- case XFER_UDMA_2:
- if (!((id->dma_ultra >> 8) & 4)) {
- drive->id->dma_ultra &= ~0xFF00;
- drive->id->dma_ultra |= 0x0404;
- }
- drive->id->dma_mword &= ~0x0F00;
- drive->id->dma_1word &= ~0x0F00;
- break;
- case XFER_UDMA_1:
- if (!((id->dma_ultra >> 8) & 2)) {
- drive->id->dma_ultra &= ~0xFF00;
- drive->id->dma_ultra |= 0x0202;
- }
- drive->id->dma_mword &= ~0x0F00;
- drive->id->dma_1word &= ~0x0F00;
- break;
- case XFER_UDMA_0:
- if (!((id->dma_ultra >> 8) & 1)) {
- drive->id->dma_ultra &= ~0xFF00;
- drive->id->dma_ultra |= 0x0101;
- }
- drive->id->dma_mword &= ~0x0F00;
- drive->id->dma_1word &= ~0x0F00;
- break;
- case XFER_MW_DMA_2:
- drive->id->dma_ultra &= ~0xFF00;
- if (!((id->dma_mword >> 8) & 4)) {
- drive->id->dma_mword &= ~0x0F00;
- drive->id->dma_mword |= 0x0404;
- }
- drive->id->dma_1word &= ~0x0F00;
- break;
- case XFER_MW_DMA_1:
- drive->id->dma_ultra &= ~0xFF00;
- if (!((id->dma_mword >> 8) & 2)) {
- drive->id->dma_mword &= ~0x0F00;
- drive->id->dma_mword |= 0x0202;
- }
- drive->id->dma_1word &= ~0x0F00;
- break;
- case XFER_MW_DMA_0:
- drive->id->dma_ultra &= ~0xFF00;
- if (!((id->dma_mword >> 8) & 1)) {
- drive->id->dma_mword &= ~0x0F00;
- drive->id->dma_mword |= 0x0101;
- }
- drive->id->dma_1word &= ~0x0F00;
- break;
- case XFER_SW_DMA_2:
- drive->id->dma_ultra &= ~0xFF00;
- drive->id->dma_mword &= ~0x0F00;
- if (!((id->dma_1word >> 8) & 4)) {
- drive->id->dma_1word &= ~0x0F00;
- drive->id->dma_1word |= 0x0404;
- }
- break;
- case XFER_SW_DMA_1:
- drive->id->dma_ultra &= ~0xFF00;
- drive->id->dma_mword &= ~0x0F00;
- if (!((id->dma_1word >> 8) & 2)) {
- drive->id->dma_1word &= ~0x0F00;
- drive->id->dma_1word |= 0x0202;
- }
- break;
- case XFER_SW_DMA_0:
- drive->id->dma_ultra &= ~0xFF00;
- drive->id->dma_mword &= ~0x0F00;
- if (!((id->dma_1word >> 8) & 1)) {
- drive->id->dma_1word &= ~0x0F00;
- drive->id->dma_1word |= 0x0101;
- }
- break;
- default:
- drive->id->dma_ultra &= ~0xFF00;
- drive->id->dma_mword &= ~0x0F00;
- drive->id->dma_1word &= ~0x0F00;
- break;
- }
-
- return(err);
-}
-
static int ide_ioctl (struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -2509,8 +2424,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
return -EINVAL;
if (drive->id == NULL)
return -ENOMSG;
- if (copy_to_user((char *)arg, (char *)drive->id,
- (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142))
+ if (copy_to_user((char *)arg, (char *)drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142))
return -EFAULT;
return 0;
@@ -2537,28 +2451,16 @@ static int ide_ioctl (struct inode *inode, struct file *file,
return -ENOMEM;
memcpy(argbuf, args, 4);
}
- if ((((byte *)arg)[0] == WIN_SETFEATURES) &&
- (((byte *)arg)[1] > 66) &&
- (((byte *)arg)[2] == 3)) {
- if (!HWIF(drive)->udma_four) {
- printk("%s: Speed warnings UDMA 3/4 is not functional.\n", HWIF(drive)->name);
- goto abort;
- }
- if ((drive->id->word93 & 0x2000) == 0) {
- printk("%s: Speed warnings UDMA 3/4 is not functional.\n", drive->name);
- goto abort;
- }
- }
+ if (ide_ata66_check(drive, args[0], args[1], args[2]))
+ goto abort;
+
err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf);
- if (!err &&
- (((byte *)arg)[0] == WIN_SETFEATURES) &&
- (((byte *)arg)[1] >= 16) &&
- (((byte *)arg)[2] == 3) &&
- (drive->id->dma_ultra ||
- drive->id->dma_mword ||
- drive->id->dma_1word)) {
-
- /*
+
+ if (!err && set_transfer(drive, args[0], args[1], args[2])) {
+
+#if 1
+ ide_driveid_update(drive);
+#else /*
* Re-read drive->id for possible DMA mode
* change (copied from ide-probe.c)
*/
@@ -2602,6 +2504,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
#endif
kfree(id);
}
+#endif
}
abort:
if (copy_to_user((void *)arg, argbuf, argsize))
@@ -2694,32 +2597,6 @@ void ide_fixstring (byte *s, const int bytecount, const int byteswap)
}
/*
- *
- */
-char *ide_xfer_verbose (byte xfer_rate) {
- switch(xfer_rate) {
- case XFER_UDMA_4: return("UDMA 4");
- case XFER_UDMA_3: return("UDMA 3");
- case XFER_UDMA_2: return("UDMA 2");
- case XFER_UDMA_1: return("UDMA 1");
- case XFER_UDMA_0: return("UDMA 0");
- case XFER_MW_DMA_2: return("MW DMA 2");
- case XFER_MW_DMA_1: return("MW DMA 1");
- case XFER_MW_DMA_0: return("MW DMA 0");
- case XFER_SW_DMA_2: return("SW DMA 2");
- case XFER_SW_DMA_1: return("SW DMA 1");
- case XFER_SW_DMA_0: return("SW DMA 0");
- case XFER_PIO_4: return("PIO 4");
- case XFER_PIO_3: return("PIO 3");
- case XFER_PIO_2: return("PIO 2");
- case XFER_PIO_1: return("PIO 1");
- case XFER_PIO_0: return("PIO 0");
- case XFER_PIO_SLOW: return("PIO SLOW");
- default: return("XFER ERROR");
- }
-}
-
-/*
* stridx() returns the offset of c within s,
* or -1 if c is '\0' or not found within s.
*/
@@ -2796,7 +2673,7 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m
* "hdx=nowerr" : ignore the WRERR_STAT bit on this drive
* "hdx=cdrom" : drive is present, and is a cdrom drive
* "hdx=cyl,head,sect" : disk drive is present, with specified geometry
- * "hdx=noremap" : do not remap 0->1 even though EZD was detected
+ * "hdx=noremap" : do not remap 0->1 even though EZD was detected
* "hdx=autotune" : driver will attempt to tune interface speed
* to the fastest PIO mode supported,
* if possible for this drive only.
@@ -2809,6 +2686,7 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m
*
* "hdx=swapdata" : when the drive is a disk, byte swap all data
* "hdx=bswap" : same as above..........
+ * "hdxlun=xx" : set the drive last logical unit.
* "hdx=flash" : allows for more than one ata_flash disk to be
* registered. In most cases, only one device
* will be present.
@@ -2914,6 +2792,19 @@ void __init ide_setup (char *s)
strncpy(drive->driver_req, s + 4, 9);
goto done;
}
+ /*
+ * Look for last lun option: "hdxlun="
+ */
+ if (s[3] == 'l' && s[4] == 'u' && s[5] == 'n') {
+ if (match_parm(&s[6], NULL, vals, 1) != 1)
+ goto bad_option;
+ if (vals[0] >= 0 && vals[0] <= 7) {
+ drive->last_lun = vals[0];
+ drive->forced_lun = 1;
+ } else
+ printk(" -- BAD LAST LUN! Expected value from 0 to 7");
+ goto done;
+ }
switch (match_parm(&s[3], hd_words, vals, 3)) {
case -1: /* "none" */
drive->nobios = 1; /* drop into "noprobe" */
@@ -3198,6 +3089,14 @@ done:
}
/*
+ * __setup("ide", ide_setup);
+ * #ifdef CONFIG_BLK_DEV_VIA82CXXX
+ * __setup("splitfifo", ide_setup);
+ * #endif
+ * __setup("hd", ide_setup);
+ */
+
+/*
* probe_for_hwifs() finds/initializes "known" IDE interfaces
*/
static void __init probe_for_hwifs (void)
@@ -3332,9 +3231,10 @@ static int default_cleanup (ide_drive_t *drive)
return ide_unregister_subdriver(drive);
}
-static void default_do_request(ide_drive_t *drive, struct request *rq, unsigned long block)
+static ide_startstop_t default_do_request(ide_drive_t *drive, struct request *rq, unsigned long block)
{
ide_end_request(0, HWGROUP(drive));
+ return ide_stopped;
}
static void default_end_request (byte uptodate, ide_hwgroup_t *hwgroup)
@@ -3372,12 +3272,13 @@ static unsigned long default_capacity (ide_drive_t *drive)
return 0x7fffffff; /* cdrom or tape */
}
-static void default_special (ide_drive_t *drive)
+static ide_startstop_t default_special (ide_drive_t *drive)
{
special_t *s = &drive->special;
s->all = 0;
drive->mult_req = 0;
+ return ide_stopped;
}
static void setup_driver_defaults (ide_drive_t *drive)
@@ -3577,7 +3478,6 @@ EXPORT_SYMBOL(ide_revalidate_disk);
EXPORT_SYMBOL(ide_cmd);
EXPORT_SYMBOL(ide_wait_cmd);
EXPORT_SYMBOL(ide_delay_50ms);
-EXPORT_SYMBOL(ide_config_drive_speed);
EXPORT_SYMBOL(ide_stall_queue);
#ifdef CONFIG_PROC_FS
EXPORT_SYMBOL(ide_add_proc_entries);
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 5363e04e2..a54f40e00 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -142,14 +142,49 @@ static inline int get_max_segments(kdev_t dev)
* NOTE: the device-specific queue() functions
* have to be atomic!
*/
-static inline struct request **get_queue(kdev_t dev)
+static inline request_queue_t *get_queue(kdev_t dev)
{
int major = MAJOR(dev);
struct blk_dev_struct *bdev = blk_dev + major;
if (bdev->queue)
return bdev->queue(dev);
- return &blk_dev[major].current_request;
+ return &blk_dev[major].request_queue;
+}
+
+void blk_cleanup_queue(request_queue_t * q)
+{
+ memset(q, 0, sizeof(*q));
+}
+
+void blk_queue_headactive(request_queue_t * q, int active)
+{
+ q->head_active = active;
+}
+
+void blk_queue_pluggable(request_queue_t * q, int use_plug)
+{
+ q->use_plug = use_plug;
+}
+
+void blk_init_queue(request_queue_t * q, request_fn_proc * rfn)
+{
+ q->request_fn = rfn;
+ q->current_request = NULL;
+ q->merge_fn = NULL;
+ q->merge_requests_fn = NULL;
+ q->plug_tq.sync = 0;
+ q->plug_tq.routine = &unplug_device;
+ q->plug_tq.data = q;
+ q->plugged = 0;
+ /*
+ * These booleans describe the queue properties. We set the
+ * default (and most common) values here. Other drivers can
+ * use the appropriate functions to alter the queue properties.
+ * as appropriate.
+ */
+ q->use_plug = 1;
+ q->head_active = 1;
}
/*
@@ -157,22 +192,18 @@ static inline struct request **get_queue(kdev_t dev)
*/
void unplug_device(void * data)
{
- struct blk_dev_struct * dev = (struct blk_dev_struct *) data;
- int queue_new_request=0;
+ request_queue_t * q = (request_queue_t *) data;
unsigned long flags;
spin_lock_irqsave(&io_request_lock,flags);
- if (dev->current_request == &dev->plug) {
- struct request * next = dev->plug.next;
- dev->current_request = next;
- if (next || dev->queue) {
- dev->plug.next = NULL;
- queue_new_request = 1;
+ if( q->plugged )
+ {
+ q->plugged = 0;
+ if( q->current_request != NULL )
+ {
+ (q->request_fn)(q);
}
}
- if (queue_new_request)
- (dev->request_fn)();
-
spin_unlock_irqrestore(&io_request_lock,flags);
}
@@ -184,12 +215,13 @@ void unplug_device(void * data)
* This is called with interrupts off and no requests on the queue.
* (and with the request spinlock aquired)
*/
-static inline void plug_device(struct blk_dev_struct * dev)
+static inline void plug_device(request_queue_t * q)
{
- if (dev->current_request)
+ if (q->current_request)
return;
- dev->current_request = &dev->plug;
- queue_task(&dev->plug_tq, &tq_disk);
+
+ q->plugged = 1;
+ queue_task(&q->plug_tq, &tq_disk);
}
/*
@@ -221,6 +253,7 @@ static inline struct request * get_request(int n, kdev_t dev)
prev_found = req;
req->rq_status = RQ_ACTIVE;
req->rq_dev = dev;
+ req->special = NULL;
return req;
}
@@ -335,12 +368,11 @@ static inline void drive_stat_acct(struct request *req,
* which is important for drive_stat_acct() above.
*/
-void add_request(struct blk_dev_struct * dev, struct request * req)
+static void add_request(request_queue_t * q, struct request * req)
{
int major = MAJOR(req->rq_dev);
- struct request * tmp, **current_request;
+ struct request * tmp;
unsigned long flags;
- int queue_new_request = 0;
drive_stat_acct(req, req->nr_sectors, 1);
req->next = NULL;
@@ -349,12 +381,9 @@ void add_request(struct blk_dev_struct * dev, struct request * req)
* We use the goto to reduce locking complexity
*/
spin_lock_irqsave(&io_request_lock,flags);
- current_request = get_queue(req->rq_dev);
- if (!(tmp = *current_request)) {
- *current_request = req;
- if (dev->current_request != &dev->plug)
- queue_new_request = 1;
+ if (!(tmp = q->current_request)) {
+ q->current_request = req;
goto out;
}
for ( ; tmp->next ; tmp = tmp->next) {
@@ -372,26 +401,34 @@ void add_request(struct blk_dev_struct * dev, struct request * req)
req->next = tmp->next;
tmp->next = req;
-/* for SCSI devices, call request_fn unconditionally */
- if (scsi_blk_major(major))
- queue_new_request = 1;
- if (major >= COMPAQ_SMART2_MAJOR+0 &&
- major <= COMPAQ_SMART2_MAJOR+7)
- queue_new_request = 1;
+ /*
+ * FIXME(eric) I don't understand why there is a need for this
+ * special case code. It clearly doesn't fit any more with
+ * the new queueing architecture, and it got added in 2.3.10.
+ * I am leaving this in here until I hear back from the COMPAQ
+ * people.
+ */
+ if (major >= COMPAQ_SMART2_MAJOR+0 && major <= COMPAQ_SMART2_MAJOR+7)
+ {
+ (q->request_fn)(q);
+ }
+
if (major >= DAC960_MAJOR+0 && major <= DAC960_MAJOR+7)
- queue_new_request = 1;
+ {
+ (q->request_fn)(q);
+ }
+
out:
- if (queue_new_request)
- (dev->request_fn)();
spin_unlock_irqrestore(&io_request_lock,flags);
}
/*
* Has to be called with the request spinlock aquired
*/
-static inline void attempt_merge (struct request *req,
- int max_sectors,
- int max_segments)
+static inline void attempt_merge (request_queue_t * q,
+ struct request *req,
+ int max_sectors,
+ int max_segments)
{
struct request *next = req->next;
int total_segments;
@@ -407,16 +444,37 @@ static inline void attempt_merge (struct request *req,
total_segments--;
if (total_segments > max_segments)
return;
+
+ if( q->merge_requests_fn != NULL )
+ {
+ /*
+ * If we are not allowed to merge these requests, then
+ * return. If we are allowed to merge, then the count
+ * will have been updated to the appropriate number,
+ * and we shouldn't do it here too.
+ */
+ if( !(q->merge_requests_fn)(q, req, next) )
+ {
+ return;
+ }
+ }
+ else
+ {
+ req->nr_segments = total_segments;
+ }
+
req->bhtail->b_reqnext = next->bh;
req->bhtail = next->bhtail;
req->nr_sectors += next->nr_sectors;
- req->nr_segments = total_segments;
next->rq_status = RQ_INACTIVE;
req->next = next->next;
wake_up (&wait_for_request);
}
-void make_request(int major,int rw, struct buffer_head * bh)
+static void __make_request(request_queue_t * q,
+ int major,
+ int rw,
+ struct buffer_head * bh)
{
unsigned int sector, count;
struct request * req;
@@ -519,13 +577,20 @@ void make_request(int major,int rw, struct buffer_head * bh)
* not to schedule or do something nonatomic
*/
spin_lock_irqsave(&io_request_lock,flags);
- req = *get_queue(bh->b_rdev);
+ req = q->current_request;
if (!req) {
/* MD and loop can't handle plugging without deadlocking */
if (major != MD_MAJOR && major != LOOP_MAJOR &&
- major != DDV_MAJOR && major != NBD_MAJOR)
- plug_device(blk_dev + major); /* is atomic */
+ major != DDV_MAJOR && major != NBD_MAJOR
+ && q->use_plug)
+ plug_device(q); /* is atomic */
} else switch (major) {
+ /*
+ * FIXME(eric) - this entire switch statement is going away
+ * soon, and we will instead key off of q->head_active to decide
+ * whether the top request in the queue is active on the device
+ * or not.
+ */
case IDE0_MAJOR: /* same as HD_MAJOR */
case IDE1_MAJOR:
case FLOPPY_MAJOR:
@@ -548,7 +613,7 @@ void make_request(int major,int rw, struct buffer_head * bh)
* All other drivers need to jump over the first entry, as that
* entry may be busy being processed and we thus can't change it.
*/
- if (req == blk_dev[major].current_request)
+ if (req == q->current_request)
req = req->next;
if (!req)
break;
@@ -592,25 +657,71 @@ void make_request(int major,int rw, struct buffer_head * bh)
continue;
/* Can we add it to the end of this request? */
if (req->sector + req->nr_sectors == sector) {
- if (req->bhtail->b_data + req->bhtail->b_size
- != bh->b_data) {
- if (req->nr_segments < max_segments)
- req->nr_segments++;
- else continue;
+ /*
+ * The merge_fn is a more advanced way
+ * of accomplishing the same task. Instead
+ * of applying a fixed limit of some sort
+ * we instead define a function which can
+ * determine whether or not it is safe to
+ * merge the request or not.
+ */
+ if( q->merge_fn == NULL )
+ {
+ if (req->bhtail->b_data + req->bhtail->b_size
+ != bh->b_data) {
+ if (req->nr_segments < max_segments)
+ req->nr_segments++;
+ else continue;
+ }
+ }
+ else
+ {
+ /*
+ * See if this queue has rules that
+ * may suggest that we shouldn't merge
+ * this
+ */
+ if( !(q->merge_fn)(q, req, bh) )
+ {
+ continue;
+ }
}
req->bhtail->b_reqnext = bh;
req->bhtail = bh;
req->nr_sectors += count;
drive_stat_acct(req, count, 0);
/* Can we now merge this req with the next? */
- attempt_merge(req, max_sectors, max_segments);
+ attempt_merge(q, req, max_sectors, max_segments);
/* or to the beginning? */
} else if (req->sector - count == sector) {
- if (bh->b_data + bh->b_size
- != req->bh->b_data) {
- if (req->nr_segments < max_segments)
- req->nr_segments++;
- else continue;
+ /*
+ * The merge_fn is a more advanced way
+ * of accomplishing the same task. Instead
+ * of applying a fixed limit of some sort
+ * we instead define a function which can
+ * determine whether or not it is safe to
+ * merge the request or not.
+ */
+ if( q->merge_fn == NULL )
+ {
+ if (bh->b_data + bh->b_size
+ != req->bh->b_data) {
+ if (req->nr_segments < max_segments)
+ req->nr_segments++;
+ else continue;
+ }
+ }
+ else
+ {
+ /*
+ * See if this queue has rules that
+ * may suggest that we shouldn't merge
+ * this
+ */
+ if( !(q->merge_fn)(q, req, bh) )
+ {
+ continue;
+ }
}
bh->b_reqnext = req->bh;
req->bh = bh;
@@ -645,20 +756,37 @@ void make_request(int major,int rw, struct buffer_head * bh)
req->errors = 0;
req->sector = sector;
req->nr_sectors = count;
- req->nr_segments = 1;
req->current_nr_sectors = count;
+ req->nr_segments = 1; /* Always 1 for a new request. */
req->buffer = bh->b_data;
req->sem = NULL;
req->bh = bh;
req->bhtail = bh;
req->next = NULL;
- add_request(major+blk_dev,req);
+ add_request(q, req);
return;
end_io:
bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state));
}
+void make_request(int major,int rw, struct buffer_head * bh)
+{
+ request_queue_t * q;
+ unsigned long flags;
+
+ q = get_queue(bh->b_dev);
+
+ __make_request(q, major, rw, bh);
+
+ spin_lock_irqsave(&io_request_lock,flags);
+ if( !q->plugged )
+ (q->request_fn)(q);
+ spin_unlock_irqrestore(&io_request_lock,flags);
+}
+
+
+
/* This function can be used to request a number of buffers from a block
device. Currently the only restriction is that all buffers must belong to
the same device */
@@ -667,13 +795,13 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
{
unsigned int major;
int correct_size;
- struct blk_dev_struct * dev;
+ request_queue_t * q;
+ unsigned long flags;
int i;
- dev = NULL;
- if ((major = MAJOR(bh[0]->b_dev)) < MAX_BLKDEV)
- dev = blk_dev + major;
- if (!dev || !dev->request_fn) {
+
+ major = MAJOR(bh[0]->b_dev);
+ if (!(q = get_queue(bh[0]->b_dev))) {
printk(KERN_ERR
"ll_rw_block: Trying to read nonexistent block-device %s (%ld)\n",
kdevname(bh[0]->b_dev), bh[0]->b_blocknr);
@@ -726,8 +854,15 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
continue;
}
#endif
- make_request(MAJOR(bh[i]->b_rdev), rw, bh[i]);
+ __make_request(q, MAJOR(bh[i]->b_rdev), rw, bh[i]);
+ }
+
+ spin_lock_irqsave(&io_request_lock,flags);
+ if( !q->plugged )
+ {
+ (q->request_fn)(q);
}
+ spin_unlock_irqrestore(&io_request_lock,flags);
return;
sorry:
@@ -801,15 +936,8 @@ int __init blk_dev_init(void)
struct blk_dev_struct *dev;
for (dev = blk_dev + MAX_BLKDEV; dev-- != blk_dev;) {
- dev->request_fn = NULL;
dev->queue = NULL;
- dev->current_request = NULL;
- dev->plug.rq_status = RQ_INACTIVE;
- dev->plug.cmd = -1;
- dev->plug.next = NULL;
- dev->plug_tq.sync = 0;
- dev->plug_tq.routine = &unplug_device;
- dev->plug_tq.data = dev;
+ blk_init_queue(&dev->request_queue, NULL);
}
req = all_requests + NR_REQUEST;
@@ -926,3 +1054,6 @@ int __init blk_dev_init(void)
EXPORT_SYMBOL(io_request_lock);
EXPORT_SYMBOL(end_that_request_first);
EXPORT_SYMBOL(end_that_request_last);
+EXPORT_SYMBOL(blk_init_queue);
+EXPORT_SYMBOL(blk_cleanup_queue);
+EXPORT_SYMBOL(blk_queue_headactive);
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index cace2226c..a950172ff 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -164,7 +164,7 @@ static void figure_loop_size(struct loop_device *lo)
loop_sizes[lo->lo_number] = size;
}
-static void do_lo_request(void)
+static void do_lo_request(request_queue_t * q)
{
int real_block, block, offset, len, blksize, size;
char *dest_addr;
@@ -425,7 +425,7 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg)
lo->lo_flags |= LO_FLAGS_READ_ONLY;
set_device_ro(dev, 1);
} else {
- invalidate_inode_pages (inode);
+ vmtruncate (inode, 0);
set_device_ro(dev, 0);
}
@@ -754,7 +754,7 @@ int __init loop_init(void)
return -ENOMEM;
}
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
for (i=0; i < max_loop; i++) {
memset(&loop_dev[i], 0, sizeof(struct loop_device));
loop_dev[i].lo_number = i;
diff --git a/drivers/block/md.c b/drivers/block/md.c
index 4dedb8671..b525ef2e9 100644
--- a/drivers/block/md.c
+++ b/drivers/block/md.c
@@ -761,7 +761,7 @@ int md_make_request (int minor, int rw, struct buffer_head * bh)
}
}
-static void do_md_request (void)
+static void do_md_request (request_queue_t * q)
{
printk ("Got md request, not good...");
return;
@@ -1176,98 +1176,85 @@ void mdsyncd (void *data)
#ifdef CONFIG_MD_BOOT
struct {
- int set;
- int ints[100];
- char str[100];
+ unsigned long set;
+ int pers[MAX_MD_DEV];
+ kdev_t devices[MAX_MD_DEV][MAX_REAL];
} md_setup_args __initdata = {
- 0,{0},{0}
+ 0,{0},{{0}}
};
-/* called from init/main.c */
-void __init md_setup(char *str,int *ints)
-{
- int i;
- for(i=0;i<=ints[0];i++) {
- md_setup_args.ints[i] = ints[i];
- strcpy(md_setup_args.str, str);
-/* printk ("md: ints[%d]=%d.\n", i, ints[i]);*/
- }
- md_setup_args.set=1;
- return;
-}
-
-void __init do_md_setup(char *str,int *ints)
+/*
+ * Parse the command-line parameters given our kernel, but do not
+ * actually try to invoke the MD device now; that is handled by
+ * md_setup_drive after the low-level disk drivers have initialised.
+ *
+ * 27/11/1999: Fixed to work correctly with the 2.3 kernel (which
+ * assigns the task of parsing integer arguments to the
+ * invoked program now). Added ability to initialise all
+ * the MD devices (by specifying multiple "md=" lines)
+ * instead of just one. -- KTK
+ */
+int __init md_setup(char *str)
{
- int minor, pers, factor, fault;
- kdev_t dev;
- int i=1;
-
- if(ints[0] < 4) {
- printk ("md: Too few Arguments (%d).\n", ints[0]);
- return;
- }
-
- minor=ints[i++];
-
- if (minor >= MAX_MD_DEV) {
+ int minor, level, factor, fault, i;
+ kdev_t device;
+ char *devnames, *pername;
+
+ if(get_option(&str, &minor) != 2 || /* MD Number */
+ get_option(&str, &level) != 2 || /* RAID Personality */
+ get_option(&str, &factor) != 2 || /* Chunk Size */
+ get_option(&str, &fault) != 2) {
+ printk("md: Too few arguments supplied to md=.\n");
+ return 0;
+ } else if (minor >= MAX_MD_DEV) {
printk ("md: Minor device number too high.\n");
- return;
+ return 0;
+ } else if (md_setup_args.set & (1 << minor)) {
+ printk ("md: Warning - md=%d,... has been specified twice;\n"
+ " will discard the first definition.\n", minor);
}
-
- pers = 0;
-
- switch(ints[i++]) { /* Raidlevel */
- case -1:
+ switch(level) {
#ifdef CONFIG_MD_LINEAR
- pers = LINEAR;
- printk ("md: Setting up md%d as linear device.\n",minor);
-#else
- printk ("md: Linear mode not configured."
- "Recompile the kernel with linear mode enabled!\n");
-#endif
+ case -1:
+ level = LINEAR;
+ pername = "linear";
break;
- case 0:
- pers = STRIPED;
-#ifdef CONFIG_MD_STRIPED
- printk ("md: Setting up md%d as a striped device.\n",minor);
-#else
- printk ("md: Striped mode not configured."
- "Recompile the kernel with striped mode enabled!\n");
#endif
+#ifdef CONFIG_MD_STRIPED
+ case 0:
+ level = STRIPED;
+ pername = "striped";
break;
-/* not supported yet
- case 1:
- pers = RAID1;
- printk ("md: Setting up md%d as a raid1 device.\n",minor);
- break;
- case 5:
- pers = RAID5;
- printk ("md: Setting up md%d as a raid5 device.\n",minor);
- break;
-*/
- default:
- printk ("md: Unknown or not supported raid level %d.\n", ints[--i]);
- return;
+#endif
+ default:
+ printk ("md: The kernel has not been configured for raid%d"
+ " support!\n", level);
+ return 0;
}
-
- if(pers) {
-
- factor=ints[i++]; /* Chunksize */
- fault =ints[i++]; /* Faultlevel */
-
- pers=pers | factor | (fault << FAULT_SHIFT);
-
- while( str && (dev = name_to_kdev_t(str))) {
- do_md_add (minor, dev);
- if((str = strchr (str, ',')) != NULL)
- str++;
- }
-
- do_md_run (minor, pers);
- printk ("md: Loading md%d.\n",minor);
+ devnames = str;
+ for (i = 0; str; i++) {
+ if ((device = name_to_kdev_t(str))) {
+ md_setup_args.devices[minor][i] = device;
+ } else {
+ printk ("md: Unknown device name, %s.\n", str);
+ return 0;
+ }
+ if ((str = strchr(str, ',')) != NULL)
+ str++;
}
-
+ if (!i) {
+ printk ("md: No devices specified for md%d?\n", minor);
+ return 0;
+ }
+
+ printk ("md: Will configure md%d (%s) from %s, below.\n",
+ minor, pername, devnames);
+ md_setup_args.devices[minor][i] = (kdev_t) 0;
+ md_setup_args.pers[minor] = level | factor | (fault << FAULT_SHIFT);
+ md_setup_args.set |= (1 << minor);
+ return 0;
}
+
#endif
void linear_init (void);
@@ -1287,8 +1274,7 @@ int __init md_init (void)
return (-1);
}
- blk_dev[MD_MAJOR].request_fn=DEVICE_REQUEST;
- blk_dev[MD_MAJOR].current_request=NULL;
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
read_ahead[MD_MAJOR]=INT_MAX;
memset(md_dev, 0, MAX_MD_DEV * sizeof (struct md_dev));
md_gendisk.next=gendisk_head;
@@ -1318,7 +1304,18 @@ int __init md_init (void)
#ifdef CONFIG_MD_BOOT
void __init md_setup_drive(void)
{
- if(md_setup_args.set)
- do_md_setup(md_setup_args.str, md_setup_args.ints);
+ int minor, i;
+ kdev_t dev;
+
+ for (minor = 0; minor < MAX_MD_DEV; minor++) {
+ if ((md_setup_args.set & (1 << minor)) == 0)
+ continue;
+ printk("md: Loading md%d.\n", minor);
+ for (i = 0; (dev = md_setup_args.devices[minor][i]); i++)
+ do_md_add (minor, dev);
+ do_md_run (minor, md_setup_args.pers[minor]);
+ }
}
+
+__setup("md=", md_setup);
#endif
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 7c24449ac..cda45cc01 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -290,7 +290,7 @@ void nbd_clear_que(struct nbd_device *lo)
#undef FAIL
#define FAIL( s ) { printk( KERN_ERR "NBD, minor %d: " s "\n", dev ); goto error_out; }
-static void do_nbd_request(void)
+static void do_nbd_request(request_queue_t * q)
{
struct request *req;
int dev;
@@ -488,7 +488,7 @@ int nbd_init(void)
#endif
blksize_size[MAJOR_NR] = nbd_blksizes;
blk_size[MAJOR_NR] = nbd_sizes;
- blk_dev[MAJOR_NR].request_fn = do_nbd_request;
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_nbd_request);
for (i = 0; i < MAX_NBD; i++) {
nbd_dev[i].refcnt = 0;
nbd_dev[i].file = NULL;
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index 96e0e421e..7db6626f4 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -220,7 +220,7 @@ static int pcd_packet(struct cdrom_device_info *cdi,
static int pcd_detect(void);
static void pcd_probe_capabilities(void);
static void do_pcd_read_drq(void);
-static void do_pcd_request(void);
+static void do_pcd_request(request_queue_t * q);
static void do_pcd_read(void);
static int pcd_blocksizes[PCD_UNITS];
@@ -343,7 +343,7 @@ int pcd_init (void) /* preliminary initialisation */
for (unit=0;unit<PCD_UNITS;unit++)
if (PCD.present) register_cdrom(&PCD.info);
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */
for (i=0;i<PCD_UNITS;i++) pcd_blocksizes[i] = 1024;
@@ -750,7 +750,7 @@ static int pcd_detect( void )
/* I/O request processing */
-static void do_pcd_request (void)
+static void do_pcd_request (request_queue_t * q)
{ int unit;
@@ -814,7 +814,7 @@ static void pcd_start( void )
spin_lock_irqsave(&io_request_lock,saved_flags);
pcd_busy = 0;
end_request(0);
- do_pcd_request();
+ do_pcd_request(NULL);
spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
@@ -838,7 +838,7 @@ static void do_pcd_read( void )
spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(1);
pcd_busy = 0;
- do_pcd_request();
+ do_pcd_request(NULL);
spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
@@ -862,14 +862,14 @@ static void do_pcd_read_drq( void )
pcd_busy = 0;
pcd_bufblk = -1;
end_request(0);
- do_pcd_request();
+ do_pcd_request(NULL);
spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
do_pcd_read();
spin_lock_irqsave(&io_request_lock,saved_flags);
- do_pcd_request();
+ do_pcd_request(NULL);
spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index bd2839053..cf8f1fc2f 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -265,7 +265,7 @@ void cleanup_module( void );
#endif
static void pd_geninit(struct gendisk *ignored);
static int pd_open(struct inode *inode, struct file *file);
-static void do_pd_request(void);
+static void do_pd_request(request_queue_t * q);
static int pd_ioctl(struct inode *inode,struct file *file,
unsigned int cmd, unsigned long arg);
static int pd_release (struct inode *inode, struct file *file);
@@ -404,7 +404,7 @@ int pd_init (void)
name,major);
return -1;
}
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */
pd_gendisk.major = major;
@@ -894,7 +894,7 @@ static int pd_ready( void )
return (!(RR(1,6) & STAT_BUSY)) ;
}
-static void do_pd_request (void)
+static void do_pd_request (request_queue_t * q)
{ struct buffer_head * bh;
struct request * req;
@@ -992,7 +992,7 @@ static void do_pd_read_start( void )
spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pd_busy = 0;
- do_pd_request();
+ do_pd_request(NULL);
spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
@@ -1016,7 +1016,7 @@ static void do_pd_read_drq( void )
spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pd_busy = 0;
- do_pd_request();
+ do_pd_request(NULL);
spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
@@ -1031,7 +1031,7 @@ static void do_pd_read_drq( void )
spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(1);
pd_busy = 0;
- do_pd_request();
+ do_pd_request(NULL);
spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
@@ -1058,7 +1058,7 @@ static void do_pd_write_start( void )
spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pd_busy = 0;
- do_pd_request();
+ do_pd_request(NULL);
spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
@@ -1074,7 +1074,7 @@ static void do_pd_write_start( void )
spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pd_busy = 0;
- do_pd_request();
+ do_pd_request(NULL);
spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
@@ -1103,7 +1103,7 @@ static void do_pd_write_done( void )
spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pd_busy = 0;
- do_pd_request();
+ do_pd_request(NULL);
spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
@@ -1111,7 +1111,7 @@ static void do_pd_write_done( void )
spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(1);
pd_busy = 0;
- do_pd_request();
+ do_pd_request(NULL);
spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index 4dba8c8b5..1b935dc50 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -246,7 +246,7 @@ int pf_init(void);
void cleanup_module( void );
#endif
static int pf_open(struct inode *inode, struct file *file);
-static void do_pf_request(void);
+static void do_pf_request(request_queue_t * q);
static int pf_ioctl(struct inode *inode,struct file *file,
unsigned int cmd, unsigned long arg);
@@ -365,7 +365,7 @@ int pf_init (void) /* preliminary initialisation */
major);
return -1;
}
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */
for (i=0;i<PF_UNITS;i++) pf_blocksizes[i] = 1024;
@@ -863,7 +863,7 @@ static int pf_ready( void )
return (((RR(1,6)&(STAT_BUSY|pf_mask)) == pf_mask));
}
-static void do_pf_request (void)
+static void do_pf_request (request_queue_t * q)
{ struct buffer_head * bh;
struct request * req;
@@ -958,7 +958,7 @@ static void do_pf_read_start( void )
spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pf_busy = 0;
- do_pf_request();
+ do_pf_request(NULL);
spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
@@ -984,7 +984,7 @@ static void do_pf_read_drq( void )
spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pf_busy = 0;
- do_pf_request();
+ do_pf_request(NULL);
spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
@@ -999,7 +999,7 @@ static void do_pf_read_drq( void )
spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(1);
pf_busy = 0;
- do_pf_request();
+ do_pf_request(NULL);
spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
@@ -1025,7 +1025,7 @@ static void do_pf_write_start( void )
spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pf_busy = 0;
- do_pf_request();
+ do_pf_request(NULL);
spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
@@ -1042,7 +1042,7 @@ static void do_pf_write_start( void )
spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pf_busy = 0;
- do_pf_request();
+ do_pf_request(NULL);
spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
@@ -1072,7 +1072,7 @@ static void do_pf_write_done( void )
spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pf_busy = 0;
- do_pf_request();
+ do_pf_request(NULL);
spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
@@ -1080,7 +1080,7 @@ static void do_pf_write_done( void )
spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(1);
pf_busy = 0;
- do_pf_request();
+ do_pf_request(NULL);
spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
diff --git a/drivers/block/pdc202xx.c b/drivers/block/pdc202xx.c
index 2155aa8af..f65fb46be 100644
--- a/drivers/block/pdc202xx.c
+++ b/drivers/block/pdc202xx.c
@@ -78,6 +78,7 @@
* Released under terms of General Public License
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
@@ -220,7 +221,7 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
int err;
unsigned int drive_conf;
- byte drive_pci;
+ byte drive_pci, speed_ok = 0;
byte test1, test2, speed = -1;
byte AP, BP, CP, DP, TB, TC;
unsigned short EP;
@@ -278,16 +279,20 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
switch(drive_number) {
case 0: drive_pci = 0x60;
pci_read_config_dword(dev, drive_pci, &drive_conf);
- if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4))
+ if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) {
+ speed_ok = 1;
goto chipset_is_set;
+ }
pci_read_config_byte(dev, (drive_pci), &test1);
if (!(test1 & SYNC_ERRDY_EN))
pci_write_config_byte(dev, (drive_pci), test1|SYNC_ERRDY_EN);
break;
case 1: drive_pci = 0x64;
pci_read_config_dword(dev, drive_pci, &drive_conf);
- if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4))
+ if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) {
+ speed_ok = 1;
goto chipset_is_set;
+ }
pci_read_config_byte(dev, 0x60, &test1);
pci_read_config_byte(dev, (drive_pci), &test2);
if ((test1 & SYNC_ERRDY_EN) && !(test2 & SYNC_ERRDY_EN))
@@ -295,16 +300,20 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
break;
case 2: drive_pci = 0x68;
pci_read_config_dword(dev, drive_pci, &drive_conf);
- if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4))
+ if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) {
+ speed_ok = 1;
goto chipset_is_set;
+ }
pci_read_config_byte(dev, (drive_pci), &test1);
if (!(test1 & SYNC_ERRDY_EN))
pci_write_config_byte(dev, (drive_pci), test1|SYNC_ERRDY_EN);
break;
case 3: drive_pci = 0x6c;
pci_read_config_dword(dev, drive_pci, &drive_conf);
- if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4))
+ if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) {
+ speed_ok = 1;
goto chipset_is_set;
+ }
pci_read_config_byte(dev, 0x68, &test1);
pci_read_config_byte(dev, (drive_pci), &test2);
if ((test1 & SYNC_ERRDY_EN) && !(test2 & SYNC_ERRDY_EN))
@@ -402,7 +411,8 @@ chipset_is_set:
decode_registers(REG_D, DP);
#endif /* PDC202XX_DECODE_REGISTER_INFO */
- err = ide_config_drive_speed(drive, speed);
+ if (!speed_ok)
+ err = ide_config_drive_speed(drive, speed);
#if PDC202XX_DEBUG_DRIVE_INFO
printk("%s: %s drive%d 0x%08x ",
diff --git a/drivers/block/pdc4030.c b/drivers/block/pdc4030.c
index bf5465695..0b682645c 100644
--- a/drivers/block/pdc4030.c
+++ b/drivers/block/pdc4030.c
@@ -158,6 +158,7 @@ int __init setup_pdc4030 (ide_hwif_t *hwif)
ide_hwif_t *hwif2;
struct dc_ident ident;
int i;
+ ide_startstop_t startstop;
if (!hwif) return 0;
@@ -174,7 +175,7 @@ int __init setup_pdc4030 (ide_hwif_t *hwif)
if (pdc4030_cmd(drive,PROMISE_GET_CONFIG)) {
return 0;
}
- if (ide_wait_stat(drive,DATA_READY,BAD_W_STAT,WAIT_DRQ)) {
+ if (ide_wait_stat(&startstop, drive,DATA_READY,BAD_W_STAT,WAIT_DRQ)) {
printk(KERN_INFO
"%s: Failed Promise read config!\n",hwif->name);
return 0;
@@ -301,7 +302,7 @@ void __init ide_probe_for_pdc4030(void)
/*
* promise_read_intr() is the handler for disk read/multread interrupts
*/
-static void promise_read_intr (ide_drive_t *drive)
+static ide_startstop_t promise_read_intr (ide_drive_t *drive)
{
byte stat;
int total_remaining;
@@ -309,8 +310,7 @@ static void promise_read_intr (ide_drive_t *drive)
struct request *rq;
if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {
- ide_error(drive, "promise_read_intr", stat);
- return;
+ return ide_error(drive, "promise_read_intr", stat);
}
read_again:
@@ -367,12 +367,13 @@ read_next:
printk(KERN_DEBUG "%s: promise_read: waiting for"
"interrupt\n", drive->name);
#endif
- return;
+ return ide_started;
}
printk(KERN_ERR "%s: Eeek! promise_read_intr: sectors left "
"!DRQ !BUSY\n", drive->name);
- ide_error(drive, "promise read intr", stat);
+ return ide_error(drive, "promise read intr", stat);
}
+ return ide_stopped;
}
/*
@@ -383,7 +384,7 @@ read_next:
*
* Once not busy, the end request is called.
*/
-static void promise_complete_pollfunc(ide_drive_t *drive)
+static ide_startstop_t promise_complete_pollfunc(ide_drive_t *drive)
{
ide_hwgroup_t *hwgroup = HWGROUP(drive);
struct request *rq = hwgroup->rq;
@@ -392,13 +393,12 @@ static void promise_complete_pollfunc(ide_drive_t *drive)
if (GET_STAT() & BUSY_STAT) {
if (time_before(jiffies, hwgroup->poll_timeout)) {
ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL);
- return; /* continue polling... */
+ return ide_started; /* continue polling... */
}
hwgroup->poll_timeout = 0;
printk(KERN_ERR "%s: completion timeout - still busy!\n",
drive->name);
- ide_error(drive, "busy timeout", GET_STAT());
- return;
+ return ide_error(drive, "busy timeout", GET_STAT());
}
hwgroup->poll_timeout = 0;
@@ -409,24 +409,24 @@ static void promise_complete_pollfunc(ide_drive_t *drive)
i -= rq->current_nr_sectors;
ide_end_request(1, hwgroup);
}
+ return ide_stopped;
}
/*
* promise_write_pollfunc() is the handler for disk write completion polling.
*/
-static void promise_write_pollfunc (ide_drive_t *drive)
+static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive)
{
ide_hwgroup_t *hwgroup = HWGROUP(drive);
if (IN_BYTE(IDE_NSECTOR_REG) != 0) {
if (time_before(jiffies, hwgroup->poll_timeout)) {
ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL);
- return; /* continue polling... */
+ return ide_started; /* continue polling... */
}
hwgroup->poll_timeout = 0;
printk(KERN_ERR "%s: write timed-out!\n",drive->name);
- ide_error (drive, "write timeout", GET_STAT());
- return;
+ return ide_error (drive, "write timeout", GET_STAT());
}
/*
@@ -439,7 +439,7 @@ static void promise_write_pollfunc (ide_drive_t *drive)
printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n",
drive->name, GET_STAT());
#endif
- return;
+ return ide_started;
}
/*
@@ -449,7 +449,7 @@ static void promise_write_pollfunc (ide_drive_t *drive)
* before the final 4 sectors are transfered. There is no interrupt generated
* on writes (at least on the DC4030VL-2), we just have to poll for NOT BUSY.
*/
-static void promise_write (ide_drive_t *drive)
+static ide_startstop_t promise_write (ide_drive_t *drive)
{
ide_hwgroup_t *hwgroup = HWGROUP(drive);
struct request *rq = &hwgroup->wrq;
@@ -465,21 +465,25 @@ static void promise_write (ide_drive_t *drive)
* the polling strategy as defined above.
*/
if (rq->nr_sectors > 4) {
- ide_multwrite(drive, rq->nr_sectors - 4);
+ if (ide_multwrite(drive, rq->nr_sectors - 4))
+ return ide_stopped;
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL);
+ return ide_started;
} else {
/*
* There are 4 or fewer sectors to transfer, do them all in one go
* and wait for NOT BUSY.
*/
- ide_multwrite(drive, rq->nr_sectors);
+ if (ide_multwrite(drive, rq->nr_sectors))
+ return ide_stopped;
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL);
#ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, "
"status = %02x\n", drive->name, GET_STAT());
#endif
+ return ide_started;
}
}
@@ -488,7 +492,7 @@ static void promise_write (ide_drive_t *drive)
* already set up. It issues a READ or WRITE command to the Promise
* controller, assuming LBA has been used to set up the block number.
*/
-void do_pdc4030_io (ide_drive_t *drive, struct request *rq)
+ide_startstop_t do_pdc4030_io (ide_drive_t *drive, struct request *rq)
{
unsigned long timeout;
byte stat;
@@ -510,8 +514,7 @@ void do_pdc4030_io (ide_drive_t *drive, struct request *rq)
stat=GET_STAT();
if (stat & DRQ_STAT) {
udelay(1);
- promise_read_intr(drive);
- return;
+ return promise_read_intr(drive);
}
if (IN_BYTE(IDE_SELECT_REG) & 0x01) {
#ifdef DEBUG_READ
@@ -519,29 +522,31 @@ void do_pdc4030_io (ide_drive_t *drive, struct request *rq)
"interrupt\n", drive->name);
#endif
ide_set_handler(drive, &promise_read_intr, WAIT_CMD, NULL);
- return;
+ return ide_started;
}
udelay(1);
} while (time_before(jiffies, timeout));
printk(KERN_ERR "%s: reading: No DRQ and not waiting - Odd!\n",
drive->name);
-
+ return ide_stopped;
} else if (rq->cmd == WRITE) {
+ ide_startstop_t startstop;
OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG);
- if (ide_wait_stat(drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
+ if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
printk(KERN_ERR "%s: no DRQ after issuing "
"PROMISE_WRITE\n", drive->name);
- return;
+ return startstop;
}
if (!drive->unmask)
__cli(); /* local CPU only */
HWGROUP(drive)->wrq = *rq; /* scratchpad */
- promise_write(drive);
+ return promise_write(drive);
} else {
printk("KERN_WARNING %s: bad command: %d\n",
drive->name, rq->cmd);
ide_end_request(0, HWGROUP(drive));
+ return ide_stopped;
}
}
diff --git a/drivers/block/piix.c b/drivers/block/piix.c
index a9bcb347c..f3db84963 100644
--- a/drivers/block/piix.c
+++ b/drivers/block/piix.c
@@ -68,6 +68,42 @@
#define PIIX_DEBUG_DRIVE_INFO 0
+#define DISPLAY_PIIX_TIMINGS
+
+#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS)
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static int piix_get_info(char *, char **, off_t, int);
+extern int (*piix_display_info)(char *, char **, off_t, int); /* ide-proc.c */
+extern char *ide_media_verbose(ide_drive_t *);
+static struct pci_dev *bmide_dev;
+
+static int piix_get_info (char *buffer, char **addr, off_t offset, int count)
+{
+ /* int rc; */
+ int piix_who = (bmide_dev->device == PCI_DEVICE_ID_INTEL_82371AB) ? 4 : 3;
+ char *p = buffer;
+ p += sprintf(p, "\n Intel PIIX%d Chipset.\n", piix_who);
+ p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n\n");
+ p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
+ p += sprintf(p, "\n");
+ p += sprintf(p, "\n");
+
+/*
+ * FIXME.... Add configuration junk data....blah blah......
+ */
+
+ return p-buffer; /* => must be less than 4k! */
+}
+#endif /* defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+/*
+ * Used to set Fifo configuration via kernel command line:
+ */
+
+byte piix_proc = 0;
+
extern char *ide_xfer_verbose (byte xfer_rate);
#ifdef CONFIG_BLK_DEV_PIIX_TUNING
@@ -248,6 +284,18 @@ static int piix_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
}
#endif /* CONFIG_BLK_DEV_PIIX_TUNING */
+unsigned int __init pci_init_piix (struct pci_dev *dev, const char *name)
+{
+#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS)
+ if (!piix_proc) {
+ piix_proc = 1;
+ bmide_dev = dev;
+ piix_display_info = &piix_get_info;
+ }
+#endif /* DISPLAY_PIIX_TIMINGS && CONFIG_PROC_FS */
+ return 0;
+}
+
void __init ide_init_piix (ide_hwif_t *hwif)
{
hwif->tuneproc = &piix_tune_drive;
@@ -262,5 +310,4 @@ void __init ide_init_piix (ide_hwif_t *hwif)
hwif->drives[0].autotune = 1;
hwif->drives[1].autotune = 1;
}
-
}
diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
index 221a3297a..a90f3bbd6 100644
--- a/drivers/block/ps2esdi.c
+++ b/drivers/block/ps2esdi.c
@@ -70,7 +70,7 @@ int ps2esdi_init(void);
static void ps2esdi_geninit(struct gendisk *ignored);
-static void do_ps2esdi_request(void);
+static void do_ps2esdi_request(request_queue_t * q);
static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count);
@@ -188,7 +188,7 @@ int __init ps2esdi_init(void)
return -1;
}
/* set up some global information - indicating device specific info */
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */
/* some minor housekeeping - setup the global gendisk structure */
@@ -464,7 +464,7 @@ static void __init ps2esdi_get_device_cfg(void)
}
/* strategy routine that handles most of the IO requests */
-static void do_ps2esdi_request(void)
+static void do_ps2esdi_request(request_queue_t * q)
{
u_int block, count;
/* since, this routine is called with interrupts cleared - they
@@ -487,7 +487,7 @@ static void do_ps2esdi_request(void)
printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
end_request(FAIL);
if (CURRENT)
- do_ps2esdi_request();
+ do_ps2esdi_request(q);
return;
} /* check for above 16Mb dmas */
if ((CURRENT_DEV < ps2esdi_drives) &&
@@ -521,7 +521,7 @@ static void do_ps2esdi_request(void)
printk("%s: Unknown command\n", DEVICE_NAME);
end_request(FAIL);
if (CURRENT)
- do_ps2esdi_request();
+ do_ps2esdi_request(q);
break;
} /* handle different commands */
}
@@ -531,7 +531,7 @@ static void do_ps2esdi_request(void)
CURRENT->sector, ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects);
end_request(FAIL);
if (CURRENT)
- do_ps2esdi_request();
+ do_ps2esdi_request(q);
}
} /* main strategy routine */
@@ -598,11 +598,11 @@ static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count)
if (ps2esdi_out_cmd_blk(cmd_blk)) {
printk("%s: Controller failed\n", DEVICE_NAME);
if ((++CURRENT->errors) < MAX_RETRIES)
- return do_ps2esdi_request();
+ return do_ps2esdi_request(NULL);
else {
end_request(FAIL);
if (CURRENT)
- do_ps2esdi_request();
+ do_ps2esdi_request(NULL);
}
}
/* check for failure to put out the command block */
@@ -901,11 +901,11 @@ static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
if ((++CURRENT->errors) < MAX_RETRIES)
- do_ps2esdi_request();
+ do_ps2esdi_request(NULL);
else {
end_request(FAIL);
if (CURRENT)
- do_ps2esdi_request();
+ do_ps2esdi_request(NULL);
}
break;
}
@@ -947,11 +947,11 @@ static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
if ((++CURRENT->errors) < MAX_RETRIES)
- do_ps2esdi_request();
+ do_ps2esdi_request(NULL);
else {
end_request(FAIL);
if (CURRENT)
- do_ps2esdi_request();
+ do_ps2esdi_request(NULL);
}
break;
@@ -961,7 +961,7 @@ static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
end_request(FAIL);
if (CURRENT)
- do_ps2esdi_request();
+ do_ps2esdi_request(NULL);
break;
case INT_CMD_FORMAT:
@@ -993,11 +993,11 @@ static void ps2esdi_continue_request(void)
if (CURRENT->nr_sectors -= CURRENT->current_nr_sectors) {
CURRENT->buffer += CURRENT->current_nr_sectors * SECT_SIZE;
CURRENT->sector += CURRENT->current_nr_sectors;
- do_ps2esdi_request();
+ do_ps2esdi_request(NULL);
} else {
end_request(SUCCES);
if (CURRENT)
- do_ps2esdi_request();
+ do_ps2esdi_request(NULL);
}
}
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 9fec26361..f83a76162 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -181,7 +181,7 @@ __setup("ramdisk_size=", ramdisk_size2);
* allocated size, we must get rid of it...
*
*/
-static void rd_request(void)
+static void rd_request(request_queue_t * q)
{
unsigned int minor;
unsigned long offset, len;
@@ -276,9 +276,11 @@ static ssize_t initrd_read(struct file *file, char *buf,
static int initrd_release(struct inode *inode,struct file *file)
{
+ extern void free_initrd_mem(unsigned long, unsigned long);
+
+ if (--initrd_users) return 0;
+ free_initrd_mem(initrd_start, initrd_end);
initrd_start = 0;
- /* No need to actually release the pages, because that is
- done later by free_all_bootmem. */
return 0;
}
@@ -339,8 +341,20 @@ static struct file_operations fd_fops = {
block_fsync /* fsync */
};
+/* Before freeing the module, invalidate all of the protected buffers! */
+static void __exit rd_cleanup (void)
+{
+ int i;
+
+ for (i = 0 ; i < NUM_RAMDISKS; i++)
+ invalidate_buffers(MKDEV(MAJOR_NR, i));
+
+ unregister_blkdev( MAJOR_NR, "ramdisk" );
+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+}
+
/* This is the registration and initialization section of the RAM disk driver */
-int __init rd_init(void)
+int __init rd_init (void)
{
int i;
@@ -357,7 +371,7 @@ int __init rd_init(void)
return -EIO;
}
- blk_dev[MAJOR_NR].request_fn = &rd_request;
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &rd_request);
for (i = 0; i < NUM_RAMDISKS; i++) {
/* rd_size is given in kB */
@@ -378,37 +392,17 @@ int __init rd_init(void)
return 0;
}
-/* loadable module support */
-
#ifdef MODULE
+module_init(rd_init);
+#endif
+module_exit(rd_cleanup);
+/* loadable module support */
MODULE_PARM (rd_size, "1i");
MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes.");
MODULE_PARM (rd_blocksize, "i");
MODULE_PARM_DESC(rd_blocksize, "Blocksize of each RAM disk in bytes.");
-int init_module(void)
-{
- int error = rd_init();
- if (!error)
- printk(KERN_INFO "RAMDISK: Loaded as module.\n");
- return error;
-}
-
-/* Before freeing the module, invalidate all of the protected buffers! */
-void cleanup_module(void)
-{
- int i;
-
- for (i = 0 ; i < NUM_RAMDISKS; i++)
- invalidate_buffers(MKDEV(MAJOR_NR, i));
-
- unregister_blkdev( MAJOR_NR, "ramdisk" );
- blk_dev[MAJOR_NR].request_fn = 0;
-}
-
-#endif /* MODULE */
-
/* End of non-loading portions of the RAM disk driver */
#ifdef RD_LOADER
diff --git a/drivers/block/sis5513.c b/drivers/block/sis5513.c
index 8a3abd025..bdd30a20d 100644
--- a/drivers/block/sis5513.c
+++ b/drivers/block/sis5513.c
@@ -8,6 +8,7 @@
* Tested and designed on the SiS620/5513 chipset.
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
@@ -27,13 +28,35 @@
#include "ide_modes.h"
-#define SIS5513_DEBUG_DRIVE_INFO 0
-
#define DISPLAY_SIS_TIMINGS
+#define SIS5513_DEBUG_DRIVE_INFO 0
-static struct pci_dev *host_dev;
+static struct pci_dev *host_dev = NULL;
+
+#define arraysize(x) (sizeof(x)/sizeof(*(x)))
+
+#define SIS5513_FLAG_ATA_00 0x00000000
+#define SIS5513_FLAG_ATA_16 0x00000001
+#define SIS5513_FLAG_ATA_33 0x00000002
+#define SIS5513_FLAG_ATA_66 0x00000004
+#define SIS5513_FLAG_LATENCY 0x00000010
+
+static const struct {
+ const char *name;
+ unsigned short host_id;
+ unsigned int flags;
+} SiSHostChipInfo[] = {
+ { "SiS530", PCI_DEVICE_ID_SI_530, SIS5513_FLAG_ATA_66, },
+ { "SiS540", PCI_DEVICE_ID_SI_540, SIS5513_FLAG_ATA_66, },
+ { "SiS620", PCI_DEVICE_ID_SI_620, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, },
+ { "SiS630", PCI_DEVICE_ID_SI_630, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, },
+ { "SiS5597", PCI_DEVICE_ID_SI_5597, SIS5513_FLAG_ATA_33, },
+ { "SiS5600", PCI_DEVICE_ID_SI_5600, SIS5513_FLAG_ATA_33, },
+ { "SiS5511", PCI_DEVICE_ID_SI_5511, SIS5513_FLAG_ATA_16, },
+};
#if 0
+
static struct _pio_mode_mapping {
byte data_active;
byte recovery;
@@ -83,8 +106,8 @@ static __inline__ char * find_udma_mode (byte cycle_time)
#include <linux/stat.h>
#include <linux/proc_fs.h>
-static int sis_get_info(char *, char **, off_t, int, int);
-extern int (*sis_display_info)(char *, char **, off_t, int, int); /* ide-proc.c */
+static int sis_get_info(char *, char **, off_t, int);
+extern int (*sis_display_info)(char *, char **, off_t, int); /* ide-proc.c */
struct pci_dev *bmide_dev;
static char *cable_type[] = {
@@ -117,14 +140,11 @@ static char *active_time [] = {
"6 PCICLK", "12 PCICLK"
};
-static int sis_get_info (char *buffer, char **addr, off_t offset, int count, int dummy)
+static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
{
int rc;
char *p = buffer;
byte reg,reg1;
-#if 0
- byte cyc, rec, act;
-#endif
u16 reg2, reg3;
p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
@@ -213,16 +233,16 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
byte drive_pci, test1, test2, mask;
int err;
- byte speed = 0x00;
- byte unmask = 0xE0;
- byte four_two = 0x00;
+ byte speed = 0x00, unmask = 0xE0, four_two = 0x00;
int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
byte udma_66 = ((id->word93 & 0x2000) && (hwif->udma_four)) ? 1 : 0;
if (host_dev) {
switch(host_dev->device) {
case PCI_DEVICE_ID_SI_530:
+ case PCI_DEVICE_ID_SI_540:
case PCI_DEVICE_ID_SI_620:
+ case PCI_DEVICE_ID_SI_630:
unmask = 0xF0;
four_two = 0x01;
default:
@@ -246,13 +266,15 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
pci_read_config_byte(dev, drive_pci|0x01, &test2);
}
- if ((id->dma_ultra & 0x0010) && (ultra) && (udma_66) && (four_two)) {
+ if ((id->dma_ultra & 0x0010) && (ultra) &&
+ (udma_66) && (four_two)) {
if (!(test2 & 0x90)) {
pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask);
pci_write_config_byte(dev, drive_pci|0x01, test2|0x90);
}
speed = XFER_UDMA_4;
- } else if ((id->dma_ultra & 0x0008) && (ultra) && (udma_66) && (four_two)) {
+ } else if ((id->dma_ultra & 0x0008) && (ultra) &&
+ (udma_66) && (four_two)) {
if (!(test2 & 0xA0)) {
pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask);
pci_write_config_byte(dev, drive_pci|0x01, test2|0xA0);
@@ -438,29 +460,23 @@ int sis5513_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name)
{
struct pci_dev *host;
+ int i = 0;
byte latency = 0;
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency);
- for (host = pci_devices; host; host=host->next) {
- if (host->vendor == PCI_VENDOR_ID_SI &&
- host->device == PCI_DEVICE_ID_SI_620) {
+ for (i = 0; i < arraysize (SiSHostChipInfo) && !host_dev; i++) {
+ host = pci_find_device (PCI_VENDOR_ID_SI,
+ SiSHostChipInfo[i].host_id,
+ NULL);
+ if (!host)
+ continue;
+
+ host_dev = host;
+ printk(SiSHostChipInfo[i].name);
+ if (SiSHostChipInfo[i].flags & SIS5513_FLAG_LATENCY) {
if (latency != 0x10)
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10);
- host_dev = host;
- break;
- } else if (host->vendor == PCI_VENDOR_ID_SI &&
- host->device == PCI_DEVICE_ID_SI_530) {
- host_dev = host;
- break;
- } else if (host->vendor == PCI_VENDOR_ID_SI &&
- host->device == PCI_DEVICE_ID_SI_5600) {
- host_dev = host;
- break;
- } else if (host->vendor == PCI_VENDOR_ID_SI &&
- host->device == PCI_DEVICE_ID_SI_5597) {
- host_dev = host;
- break;
}
}
@@ -468,9 +484,10 @@ unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name)
byte reg52h = 0;
pci_read_config_byte(dev, 0x52, &reg52h);
- if (!(reg52h & 0x04))
+ if (!(reg52h & 0x04)) {
/* set IDE controller to operate in Compabitility mode obly */
pci_write_config_byte(dev, 0x52, reg52h|0x04);
+ }
#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS)
sis_proc = 1;
bmide_dev = dev;
@@ -489,7 +506,9 @@ unsigned int __init ata66_sis5513 (ide_hwif_t *hwif)
if (host_dev) {
switch(host_dev->device) {
case PCI_DEVICE_ID_SI_530:
+ case PCI_DEVICE_ID_SI_540:
case PCI_DEVICE_ID_SI_620:
+ case PCI_DEVICE_ID_SI_630:
ata66 = (reg48h & mask) ? 0 : 1;
default:
break;
@@ -509,7 +528,9 @@ void __init ide_init_sis5513 (ide_hwif_t *hwif)
if (host_dev) {
switch(host_dev->device) {
case PCI_DEVICE_ID_SI_530:
+ case PCI_DEVICE_ID_SI_540:
case PCI_DEVICE_ID_SI_620:
+ case PCI_DEVICE_ID_SI_630:
case PCI_DEVICE_ID_SI_5600:
case PCI_DEVICE_ID_SI_5597:
hwif->autodma = 1;
diff --git a/drivers/block/sl82c105.c b/drivers/block/sl82c105.c
index fa47adbb7..e029fcce6 100644
--- a/drivers/block/sl82c105.c
+++ b/drivers/block/sl82c105.c
@@ -61,6 +61,7 @@ static unsigned int get_timing_sl82c105(ide_pio_data_t *p)
static int ide_set_drive_pio_mode(ide_drive_t *drive, byte pio)
{
ide_hwif_t *hwif = HWIF(drive);
+ ide_startstop_t startstop;
if (pio > 2) {
/* FIXME: I don't believe that this SELECT_DRIVE is required,
@@ -74,7 +75,7 @@ static int ide_set_drive_pio_mode(ide_drive_t *drive, byte pio)
OUT_BYTE(0x03, IDE_FEATURE_REG);
OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG);
- if (ide_wait_stat(drive, DRIVE_READY,
+ if (ide_wait_stat(&startstop, drive, DRIVE_READY,
BUSY_STAT|DRQ_STAT|ERR_STAT, WAIT_CMD)) {
printk("%s: drive not ready for command\n",
drive->name);
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index cee5493da..06cd279af 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -219,7 +219,7 @@ static unsigned short write_postamble[] = {
static void swim3_select(struct floppy_state *fs, int sel);
static void swim3_action(struct floppy_state *fs, int action);
static int swim3_readbit(struct floppy_state *fs, int bit);
-static void do_fd_request(void);
+static void do_fd_request(request_queue_t * q);
static void start_request(struct floppy_state *fs);
static void set_timeout(struct floppy_state *fs, int nticks,
void (*proc)(unsigned long));
@@ -290,7 +290,7 @@ static int swim3_readbit(struct floppy_state *fs, int bit)
return (stat & DATA) == 0;
}
-static void do_fd_request(void)
+static void do_fd_request(request_queue_t * q)
{
int i;
for(i=0;i<floppy_count;i++)
@@ -1089,7 +1089,7 @@ int swim3_init(void)
MAJOR_NR);
return -EBUSY;
}
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
blksize_size[MAJOR_NR] = floppy_blocksizes;
blk_size[MAJOR_NR] = floppy_sizes;
}
diff --git a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c
index 462ef7f26..f15f590a4 100644
--- a/drivers/block/swim_iop.c
+++ b/drivers/block/swim_iop.c
@@ -121,7 +121,7 @@ static void release_drive(struct floppy_state *fs);
static void set_timeout(struct floppy_state *fs, int nticks,
void (*proc)(unsigned long));
static void fd_request_timeout(unsigned long);
-static void do_fd_request(void);
+static void do_fd_request(request_queue_t * q);
static void start_request(struct floppy_state *fs);
static struct file_operations floppy_fops = {
@@ -163,7 +163,7 @@ int swimiop_init(void)
MAJOR_NR);
return -EBUSY;
}
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
blksize_size[MAJOR_NR] = floppy_blocksizes;
blk_size[MAJOR_NR] = floppy_sizes;
@@ -566,7 +566,7 @@ static void set_timeout(struct floppy_state *fs, int nticks,
restore_flags(flags);
}
-static void do_fd_request(void)
+static void do_fd_request(request_queue_t * q)
{
int i;
diff --git a/drivers/block/via82cxxx.c b/drivers/block/via82cxxx.c
index e6f61c03f..9d7836e98 100644
--- a/drivers/block/via82cxxx.c
+++ b/drivers/block/via82cxxx.c
@@ -119,8 +119,8 @@ static char *control3_str[] = {
"192"
};
-static int via_get_info(char *, char **, off_t, int, int);
-extern int (*via_display_info)(char *, char **, off_t, int, int); /* ide-proc.c */
+static int via_get_info(char *, char **, off_t, int);
+extern int (*via_display_info)(char *, char **, off_t, int); /* ide-proc.c */
static struct pci_dev *bmide_dev;
static char * print_apollo_drive_config (char *buf, struct pci_dev *dev)
@@ -304,7 +304,7 @@ static char * print_apollo_chipset_control3 (char *buf, struct pci_dev *dev,
return (char *)p;
}
-static int via_get_info (char *buffer, char **addr, off_t offset, int count, int dummy)
+static int via_get_info (char *buffer, char **addr, off_t offset, int count)
{
/*
* print what /proc/via displays,
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index 44e8317f0..6d2bde45a 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -185,7 +185,7 @@ int __init xd_init (void)
printk("xd: Unable to get major number %d\n",MAJOR_NR);
return -1;
}
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */
xd_gendisk.next = gendisk_head;
gendisk_head = &xd_gendisk;
@@ -207,7 +207,7 @@ static u_char __init xd_detect (u_char *controller, unsigned int *address)
for (i = 0; i < (sizeof(xd_bases) / sizeof(xd_bases[0])) && !found; i++)
for (j = 1; j < (sizeof(xd_sigs) / sizeof(xd_sigs[0])) && !found; j++)
- if (check_signature(xd_bases[i] + xd_sigs[j].offset,xd_sigs[j].string,strlen(xd_sigs[j].string))) {
+ if (isa_check_signature(xd_bases[i] + xd_sigs[j].offset,xd_sigs[j].string,strlen(xd_sigs[j].string))) {
*controller = j;
xd_type = j;
*address = xd_bases[i];
@@ -284,7 +284,7 @@ static int xd_open (struct inode *inode,struct file *file)
}
/* do_xd_request: handle an incoming request */
-static void do_xd_request (void)
+static void do_xd_request (request_queue_t * q)
{
u_int block,count,retry;
int code;
@@ -1143,7 +1143,7 @@ static void xd_done (void)
struct gendisk ** gdp;
blksize_size[MAJOR_NR] = NULL;
- blk_dev[MAJOR_NR].request_fn = NULL;
+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
blk_size[MAJOR_NR] = NULL;
hardsect_size[MAJOR_NR] = NULL;
read_ahead[MAJOR_NR] = 0;
diff --git a/drivers/block/xd.h b/drivers/block/xd.h
index b45fae4e7..c121e8e9f 100644
--- a/drivers/block/xd.h
+++ b/drivers/block/xd.h
@@ -112,7 +112,7 @@ static u_char xd_initdrives (void (*init_drive)(u_char drive));
static void xd_geninit (struct gendisk *);
static int xd_open (struct inode *inode,struct file *file);
-static void do_xd_request (void);
+static void do_xd_request (request_queue_t * q);
static int xd_ioctl (struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg);
static int xd_release (struct inode *inode,struct file *file);
static int xd_reread_partitions (kdev_t dev);
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index f75150e4a..cceb82dd5 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -68,7 +68,7 @@ static int list_count = 0;
static int current_device = -1;
static void
-do_z2_request( void )
+do_z2_request( request_queue_t * q )
{
u_long start, len, addr, size;
@@ -373,7 +373,7 @@ z2_init( void )
}
}
- blk_dev[ MAJOR_NR ].request_fn = DEVICE_REQUEST;
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
blksize_size[ MAJOR_NR ] = z2_blocksizes;
blk_size[ MAJOR_NR ] = z2_sizes;