summaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-10-09 00:00:47 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-10-09 00:00:47 +0000
commitd6434e1042f3b0a6dfe1b1f615af369486f9b1fa (patch)
treee2be02f33984c48ec019c654051d27964e42c441 /drivers/block
parent609d1e803baf519487233b765eb487f9ec227a18 (diff)
Merge with 2.3.19.
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/Config.in30
-rw-r--r--drivers/block/DAC960.c3570
-rw-r--r--drivers/block/DAC960.h2244
-rw-r--r--drivers/block/MAKEDEV-IDE4599
-rw-r--r--drivers/block/MAKEDEV-IDE6799
-rw-r--r--drivers/block/Makefile142
-rw-r--r--drivers/block/README.buddha210
-rw-r--r--drivers/block/acsi.c33
-rw-r--r--drivers/block/acsi_slm.c6
-rw-r--r--drivers/block/aec6210.c15
-rw-r--r--drivers/block/alim15x3.c4
-rw-r--r--drivers/block/amiflop.c1078
-rw-r--r--drivers/block/ataflop.c128
-rw-r--r--drivers/block/cmd646.c2
-rw-r--r--drivers/block/cmos-probe.c78
-rw-r--r--drivers/block/cpqarray.c6
-rw-r--r--drivers/block/cy82c693.c13
-rw-r--r--drivers/block/floppy.c70
-rw-r--r--drivers/block/genhd.c1485
-rw-r--r--drivers/block/hd.c52
-rw-r--r--drivers/block/hpt34x.c87
-rw-r--r--drivers/block/hpt366.c490
-rw-r--r--drivers/block/icside.c17
-rw-r--r--drivers/block/ide-cd.c1162
-rw-r--r--drivers/block/ide-cd.h463
-rw-r--r--drivers/block/ide-dma.c39
-rw-r--r--drivers/block/ide-floppy.c27
-rw-r--r--drivers/block/ide-pci.c192
-rw-r--r--drivers/block/ide-pmac.c85
-rw-r--r--drivers/block/ide-probe.c63
-rw-r--r--drivers/block/ide-proc.c2
-rw-r--r--drivers/block/ide-tape.c5
-rw-r--r--drivers/block/ide.c128
-rw-r--r--drivers/block/ide.h773
-rw-r--r--drivers/block/linear.c2
-rw-r--r--drivers/block/ll_rw_blk.c105
-rw-r--r--drivers/block/loop.c66
-rw-r--r--drivers/block/macide.c99
-rw-r--r--drivers/block/md.c10
-rw-r--r--drivers/block/ns87415.c2
-rw-r--r--drivers/block/paride/paride.c3
-rw-r--r--drivers/block/paride/pcd.c28
-rw-r--r--drivers/block/paride/pd.c2
-rw-r--r--drivers/block/paride/pf.c2
-rw-r--r--drivers/block/pdc202xx.c37
-rw-r--r--drivers/block/piix.c34
-rw-r--r--drivers/block/ps2esdi.c24
-rw-r--r--drivers/block/q40ide.c109
-rw-r--r--drivers/block/raid1.c9
-rw-r--r--drivers/block/raid5.c3
-rw-r--r--drivers/block/rd.c145
-rw-r--r--drivers/block/rz1000.c10
-rw-r--r--drivers/block/sis5513.c417
-rw-r--r--drivers/block/sl82c105.c112
-rw-r--r--drivers/block/swim_iop.c674
-rw-r--r--drivers/block/trm290.c15
-rw-r--r--drivers/block/via82c586.c144
-rw-r--r--drivers/block/xd.c47
-rw-r--r--drivers/block/z2ram.c31
59 files changed, 10185 insertions, 4842 deletions
diff --git a/drivers/block/Config.in b/drivers/block/Config.in
index 6fba7d5fc..7c00c4dd2 100644
--- a/drivers/block/Config.in
+++ b/drivers/block/Config.in
@@ -11,6 +11,11 @@ fi
if [ "$CONFIG_ATARI" = "y" ]; then
tristate 'Atari floppy support' CONFIG_ATARI_FLOPPY
fi
+if [ "$CONFIG_MAC" = "y" ]; then
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ bool 'Macintosh IIfx/Quadra 900/Quadra 950 floppy support (EXPERIMENTAL)' CONFIG_BLK_DEV_SWIM_IOP
+ fi
+fi
tristate 'Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support' CONFIG_BLK_DEV_IDE
comment 'Please see Documentation/ide.txt for help/info on IDE drives'
@@ -43,7 +48,6 @@ else
bool ' Use PCI DMA by default when available' CONFIG_IDEDMA_PCI_AUTO
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
bool ' Good-Bad DMA Model-Firmware (EXPERIMENTAL)' IDEDMA_NEW_DRIVE_LISTINGS
- bool ' Generic ATA-66 support (DANGEROUS)' CONFIG_IDEDMA_ULTRA_66
define_bool IDEDMA_PCI_EXPERIMENTAL y
else
define_bool IDEDMA_PCI_EXPERIMENTAL n
@@ -52,7 +56,9 @@ else
bool ' Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD
bool ' AEC6210 chipset support' CONFIG_BLK_DEV_AEC6210
if [ "$IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then
- bool ' ALI M15x3 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_ALI15X3
+ if [ "$CONFIG_X86" = "y" ]; then
+ bool ' ALI M15x3 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_ALI15X3
+ fi
bool ' CMD646 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_CMD646
bool ' CY82C693 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_CY82C693
fi
@@ -61,10 +67,13 @@ else
"$CONFIG_BLK_DEV_HPT34X" = "y" ]; then
bool ' HPT34X DMA support (DANGEROUS)' CONFIG_BLK_DEV_HPT34X_DMA
fi
- bool ' Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX
- if [ "$IDEDMA_PCI_EXPERIMENTAL" = "y" -a \
- "$CONFIG_BLK_DEV_PIIX" = "y" ]; then
- bool ' PIIXn Tuning support (EXPERIMENTAL)' CONFIG_BLK_DEV_PIIX_TUNING
+ bool ' HPT366 chipset support' CONFIG_BLK_DEV_HPT366
+ if [ "$CONFIG_X86" = "y" ]; then
+ bool ' Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX
+ if [ "$IDEDMA_PCI_EXPERIMENTAL" = "y" -a \
+ "$CONFIG_BLK_DEV_PIIX" = "y" ]; then
+ bool ' PIIXn Tuning support (EXPERIMENTAL)' CONFIG_BLK_DEV_PIIX_TUNING
+ fi
fi
if [ "$IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then
bool ' NS87415 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_NS87415
@@ -80,9 +89,14 @@ else
bool ' Special Mode Feature (DANGEROUS)' PDC202XX_FORCE_MASTER_MODE
fi
fi
+ if [ "$CONFIG_X86" = "y" ]; then
+ bool ' SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513
+ fi
if [ "$IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then
bool ' Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290
- bool ' VIA82C586 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82C586
+ if [ "$CONFIG_X86" = "y" ]; then
+ bool ' VIA82C586 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82C586
+ fi
fi
fi
if [ "$CONFIG_PPC" = "y" -o "$CONFIG_ARM" = "y" ]; then
@@ -206,9 +220,11 @@ if [ "$CONFIG_IDE_CHIPSETS" = "y" -o \
"$CONFIG_BLK_DEV_CMD640" = "y" -o \
"$CONFIG_BLK_DEV_CY82C693" = "y" -o \
"$CONFIG_BLK_DEV_HPT34X" = "y" -o \
+ "$CONFIG_BLK_DEV_HPT366" = "y" -o \
"$CONFIG_BLK_DEV_IDE_PMAC" = "y" -o \
"$CONFIG_BLK_DEV_OPTI621" = "y" -o \
"$CONFIG_BLK_DEV_PIIX" = "y" -o \
+ "$CONFIG_BLK_DEV_SIS5513" = "y" -o \
"$CONFIG_BLK_DEV_SL82C105" = "y" ]; then
define_bool CONFIG_BLK_DEV_IDE_MODES y
else
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
new file mode 100644
index 000000000..06eed2279
--- /dev/null
+++ b/drivers/block/DAC960.c
@@ -0,0 +1,3570 @@
+/*
+
+ Linux Driver for Mylex DAC960 and DAC1100 PCI RAID Controllers
+
+ Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+
+ This program is free software; you may redistribute and/or modify it under
+ the terms of the GNU General Public License Version 2 as published by the
+ Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for complete details.
+
+ The author respectfully requests that any modifications to this software be
+ sent directly to him for evaluation and testing.
+
+*/
+
+
+#define DAC960_DriverVersion "2.2.4"
+#define DAC960_DriverDate "23 August 1999"
+
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/blk.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/hdreg.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/locks.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/proc_fs.h>
+#include <linux/reboot.h>
+#include <linux/timer.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/segment.h>
+#include <linux/spinlock.h>
+#include <asm/uaccess.h>
+#include "DAC960.h"
+
+
+/*
+ DAC960_ControllerCount is the number of DAC960 Controllers detected.
+*/
+
+static int
+ DAC960_ControllerCount = 0;
+
+
+/*
+ DAC960_ActiveControllerCount is the number of Active DAC960 Controllers
+ detected.
+*/
+
+static int
+ DAC960_ActiveControllerCount = 0;
+
+
+/*
+ DAC960_Controllers is an array of pointers to the DAC960 Controller
+ structures.
+*/
+
+static DAC960_Controller_T
+ *DAC960_Controllers[DAC960_MaxControllers] = { NULL };
+
+
+/*
+ DAC960_FileOperations is the File Operations structure for DAC960 Logical
+ Disk Devices.
+*/
+
+static FileOperations_T
+ DAC960_FileOperations =
+ { llseek: NULL,
+ read: block_read,
+ write: block_write,
+ readdir: NULL,
+ poll: NULL,
+ ioctl: DAC960_IOCTL,
+ mmap: NULL,
+ open: DAC960_Open,
+ release: DAC960_Release,
+ fsync: block_fsync,
+ fasync: NULL,
+ check_media_change: NULL,
+ revalidate: NULL };
+
+
+/*
+ DAC960_ProcDirectoryEntry is the DAC960 /proc/rd directory entry.
+*/
+
+static PROC_DirectoryEntry_T
+ DAC960_ProcDirectoryEntry;
+
+
+/*
+ DAC960_NotifierBlock is the Notifier Block structure for DAC960 Driver.
+*/
+
+static NotifierBlock_T
+ DAC960_NotifierBlock = { DAC960_Finalize, NULL, 0 };
+
+
+/*
+ DAC960_AnnounceDriver announces the Driver Version and Date, Author's Name,
+ Copyright Notice, and Electronic Mail Address.
+*/
+
+static void DAC960_AnnounceDriver(DAC960_Controller_T *Controller)
+{
+ DAC960_Announce("***** DAC960 RAID Driver Version "
+ DAC960_DriverVersion " of "
+ DAC960_DriverDate " *****\n", Controller);
+ DAC960_Announce("Copyright 1998-1999 by Leonard N. Zubkoff "
+ "<lnz@dandelion.com>\n", Controller);
+}
+
+
+/*
+ DAC960_Failure prints a standardized error message, and then returns false.
+*/
+
+static boolean DAC960_Failure(DAC960_Controller_T *Controller,
+ char *ErrorMessage)
+{
+ DAC960_Error("While configuring DAC960 PCI RAID Controller at\n",
+ Controller);
+ if (Controller->IO_Address == 0)
+ DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A "
+ "PCI Address 0x%X\n", Controller,
+ Controller->Bus, Controller->Device,
+ Controller->Function, Controller->PCI_Address);
+ else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address "
+ "0x%X PCI Address 0x%X\n", Controller,
+ Controller->Bus, Controller->Device,
+ Controller->Function, Controller->IO_Address,
+ Controller->PCI_Address);
+ DAC960_Error("%s FAILED - DETACHING\n", Controller, ErrorMessage);
+ return false;
+}
+
+
+/*
+ DAC960_ClearCommand clears critical fields of Command.
+*/
+
+static inline void DAC960_ClearCommand(DAC960_Command_T *Command)
+{
+ DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+ CommandMailbox->Words[0] = 0;
+ CommandMailbox->Words[1] = 0;
+ CommandMailbox->Words[2] = 0;
+ CommandMailbox->Words[3] = 0;
+ Command->CommandStatus = 0;
+}
+
+
+/*
+ DAC960_AllocateCommand allocates a Command structure from Controller's
+ free list.
+*/
+
+static inline DAC960_Command_T *DAC960_AllocateCommand(DAC960_Controller_T
+ *Controller)
+{
+ DAC960_Command_T *Command = Controller->FreeCommands;
+ if (Command == NULL) return NULL;
+ Controller->FreeCommands = Command->Next;
+ Command->Next = NULL;
+ return Command;
+}
+
+
+/*
+ DAC960_DeallocateCommand deallocates Command, returning it to Controller's
+ free list.
+*/
+
+static inline void DAC960_DeallocateCommand(DAC960_Command_T *Command)
+{
+ DAC960_Controller_T *Controller = Command->Controller;
+ Command->Next = Controller->FreeCommands;
+ Controller->FreeCommands = Command;
+}
+
+
+/*
+ DAC960_QueueCommand queues Command.
+*/
+
+static void DAC960_QueueCommand(DAC960_Command_T *Command)
+{
+ DAC960_Controller_T *Controller = Command->Controller;
+ void *ControllerBaseAddress = Controller->BaseAddress;
+ DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+ DAC960_CommandMailbox_T *NextCommandMailbox;
+ CommandMailbox->Common.CommandIdentifier = Command - Controller->Commands;
+ switch (Controller->ControllerType)
+ {
+ case DAC960_V5_Controller:
+ NextCommandMailbox = Controller->NextCommandMailbox;
+ DAC960_V5_WriteCommandMailbox(NextCommandMailbox, CommandMailbox);
+ if (Controller->PreviousCommandMailbox1->Words[0] == 0 ||
+ Controller->PreviousCommandMailbox2->Words[0] == 0)
+ {
+ if (Controller->DualModeMemoryMailboxInterface)
+ DAC960_V5_MemoryMailboxNewCommand(ControllerBaseAddress);
+ else DAC960_V5_HardwareMailboxNewCommand(ControllerBaseAddress);
+ }
+ Controller->PreviousCommandMailbox2 = Controller->PreviousCommandMailbox1;
+ Controller->PreviousCommandMailbox1 = NextCommandMailbox;
+ if (++NextCommandMailbox > Controller->LastCommandMailbox)
+ NextCommandMailbox = Controller->FirstCommandMailbox;
+ Controller->NextCommandMailbox = NextCommandMailbox;
+ break;
+ case DAC960_V4_Controller:
+ NextCommandMailbox = Controller->NextCommandMailbox;
+ DAC960_V4_WriteCommandMailbox(NextCommandMailbox, CommandMailbox);
+ if (Controller->PreviousCommandMailbox1->Words[0] == 0 ||
+ Controller->PreviousCommandMailbox2->Words[0] == 0)
+ {
+ if (Controller->DualModeMemoryMailboxInterface)
+ DAC960_V4_MemoryMailboxNewCommand(ControllerBaseAddress);
+ else DAC960_V4_HardwareMailboxNewCommand(ControllerBaseAddress);
+ }
+ Controller->PreviousCommandMailbox2 = Controller->PreviousCommandMailbox1;
+ Controller->PreviousCommandMailbox1 = NextCommandMailbox;
+ if (++NextCommandMailbox > Controller->LastCommandMailbox)
+ NextCommandMailbox = Controller->FirstCommandMailbox;
+ Controller->NextCommandMailbox = NextCommandMailbox;
+ break;
+ case DAC960_V3_Controller:
+ while (DAC960_V3_MailboxFullP(ControllerBaseAddress))
+ udelay(1);
+ DAC960_V3_WriteCommandMailbox(ControllerBaseAddress, CommandMailbox);
+ DAC960_V3_NewCommand(ControllerBaseAddress);
+ break;
+ }
+}
+
+
+/*
+ DAC960_ExecuteCommand executes Command and waits for completion. It
+ returns true on success and false on failure.
+*/
+
+static boolean DAC960_ExecuteCommand(DAC960_Command_T *Command)
+{
+ DAC960_Controller_T *Controller = Command->Controller;
+ Semaphore_T Semaphore = MUTEX_LOCKED;
+ unsigned long ProcessorFlags;
+ Command->Semaphore = &Semaphore;
+ DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+ DAC960_QueueCommand(Command);
+ DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+ if (!in_interrupt())
+ down(&Semaphore);
+ return Command->CommandStatus == DAC960_NormalCompletion;
+}
+
+
+/*
+ DAC960_ExecuteType3 executes a DAC960 Type 3 Command and waits for
+ completion. It returns true on success and false on failure.
+*/
+
+static boolean DAC960_ExecuteType3(DAC960_Controller_T *Controller,
+ DAC960_CommandOpcode_T CommandOpcode,
+ void *DataPointer)
+{
+ DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
+ DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+ boolean Result;
+ DAC960_ClearCommand(Command);
+ Command->CommandType = DAC960_ImmediateCommand;
+ CommandMailbox->Type3.CommandOpcode = CommandOpcode;
+ CommandMailbox->Type3.BusAddress = Virtual_to_Bus(DataPointer);
+ Result = DAC960_ExecuteCommand(Command);
+ DAC960_DeallocateCommand(Command);
+ return Result;
+}
+
+
+/*
+ DAC960_ExecuteType3D executes a DAC960 Type 3D Command and waits for
+ completion. It returns true on success and false on failure.
+*/
+
+static boolean DAC960_ExecuteType3D(DAC960_Controller_T *Controller,
+ DAC960_CommandOpcode_T CommandOpcode,
+ unsigned char Channel,
+ unsigned char TargetID,
+ void *DataPointer)
+{
+ DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
+ DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+ boolean Result;
+ DAC960_ClearCommand(Command);
+ Command->CommandType = DAC960_ImmediateCommand;
+ CommandMailbox->Type3D.CommandOpcode = CommandOpcode;
+ CommandMailbox->Type3D.Channel = Channel;
+ CommandMailbox->Type3D.TargetID = TargetID;
+ CommandMailbox->Type3D.BusAddress = Virtual_to_Bus(DataPointer);
+ Result = DAC960_ExecuteCommand(Command);
+ DAC960_DeallocateCommand(Command);
+ return Result;
+}
+
+
+/*
+ DAC960_EnableMemoryMailboxInterface enables the Memory Mailbox Interface.
+*/
+
+static boolean DAC960_EnableMemoryMailboxInterface(DAC960_Controller_T
+ *Controller)
+{
+ void *ControllerBaseAddress = Controller->BaseAddress;
+ DAC960_CommandMailbox_T *CommandMailboxesMemory;
+ DAC960_StatusMailbox_T *StatusMailboxesMemory;
+ DAC960_CommandMailbox_T CommandMailbox;
+ DAC960_CommandStatus_T CommandStatus;
+ void *SavedMemoryMailboxesAddress = NULL;
+ short NextCommandMailboxIndex = 0;
+ short NextStatusMailboxIndex = 0;
+ int TimeoutCounter = 1000000, i;
+ if (Controller->ControllerType == DAC960_V5_Controller)
+ DAC960_V5_RestoreMemoryMailboxInfo(Controller,
+ &SavedMemoryMailboxesAddress,
+ &NextCommandMailboxIndex,
+ &NextStatusMailboxIndex);
+ else DAC960_V4_RestoreMemoryMailboxInfo(Controller,
+ &SavedMemoryMailboxesAddress,
+ &NextCommandMailboxIndex,
+ &NextStatusMailboxIndex);
+ if (SavedMemoryMailboxesAddress == NULL)
+ CommandMailboxesMemory =
+ (DAC960_CommandMailbox_T *) __get_free_pages(GFP_KERNEL, 1);
+ else CommandMailboxesMemory = SavedMemoryMailboxesAddress;
+ memset(CommandMailboxesMemory, 0, PAGE_SIZE << 1);
+ Controller->FirstCommandMailbox = CommandMailboxesMemory;
+ CommandMailboxesMemory += DAC960_CommandMailboxCount - 1;
+ Controller->LastCommandMailbox = CommandMailboxesMemory;
+ Controller->NextCommandMailbox =
+ &Controller->FirstCommandMailbox[NextCommandMailboxIndex];
+ if (--NextCommandMailboxIndex < 0)
+ NextCommandMailboxIndex = DAC960_CommandMailboxCount - 1;
+ Controller->PreviousCommandMailbox1 =
+ &Controller->FirstCommandMailbox[NextCommandMailboxIndex];
+ if (--NextCommandMailboxIndex < 0)
+ NextCommandMailboxIndex = DAC960_CommandMailboxCount - 1;
+ Controller->PreviousCommandMailbox2 =
+ &Controller->FirstCommandMailbox[NextCommandMailboxIndex];
+ StatusMailboxesMemory =
+ (DAC960_StatusMailbox_T *) (CommandMailboxesMemory + 1);
+ Controller->FirstStatusMailbox = StatusMailboxesMemory;
+ StatusMailboxesMemory += DAC960_StatusMailboxCount - 1;
+ Controller->LastStatusMailbox = StatusMailboxesMemory;
+ Controller->NextStatusMailbox =
+ &Controller->FirstStatusMailbox[NextStatusMailboxIndex];
+ if (SavedMemoryMailboxesAddress != NULL) return true;
+ /* Enable the Memory Mailbox Interface. */
+ Controller->DualModeMemoryMailboxInterface = true;
+ CommandMailbox.TypeX.CommandOpcode = 0x2B;
+ CommandMailbox.TypeX.CommandIdentifier = 0;
+ CommandMailbox.TypeX.CommandOpcode2 = 0x14;
+ CommandMailbox.TypeX.CommandMailboxesBusAddress =
+ Virtual_to_Bus(Controller->FirstCommandMailbox);
+ CommandMailbox.TypeX.StatusMailboxesBusAddress =
+ Virtual_to_Bus(Controller->FirstStatusMailbox);
+ for (i = 0; i < 2; i++)
+ switch (Controller->ControllerType)
+ {
+ case DAC960_V5_Controller:
+ while (--TimeoutCounter >= 0)
+ {
+ if (DAC960_V5_HardwareMailboxEmptyP(ControllerBaseAddress))
+ break;
+ udelay(10);
+ }
+ if (TimeoutCounter < 0) return false;
+ DAC960_V5_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox);
+ DAC960_V5_HardwareMailboxNewCommand(ControllerBaseAddress);
+ while (--TimeoutCounter >= 0)
+ {
+ if (DAC960_V5_HardwareMailboxStatusAvailableP(
+ ControllerBaseAddress))
+ break;
+ udelay(10);
+ }
+ if (TimeoutCounter < 0) return false;
+ CommandStatus = DAC960_V5_ReadStatusRegister(ControllerBaseAddress);
+ DAC960_V5_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress);
+ DAC960_V5_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress);
+ if (CommandStatus == DAC960_NormalCompletion) return true;
+ Controller->DualModeMemoryMailboxInterface = false;
+ CommandMailbox.TypeX.CommandOpcode2 = 0x10;
+ break;
+ case DAC960_V4_Controller:
+ while (--TimeoutCounter >= 0)
+ {
+ if (!DAC960_V4_HardwareMailboxFullP(ControllerBaseAddress))
+ break;
+ udelay(10);
+ }
+ if (TimeoutCounter < 0) return false;
+ DAC960_V4_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox);
+ DAC960_V4_HardwareMailboxNewCommand(ControllerBaseAddress);
+ while (--TimeoutCounter >= 0)
+ {
+ if (DAC960_V4_HardwareMailboxStatusAvailableP(
+ ControllerBaseAddress))
+ break;
+ udelay(10);
+ }
+ if (TimeoutCounter < 0) return false;
+ CommandStatus = DAC960_V4_ReadStatusRegister(ControllerBaseAddress);
+ DAC960_V4_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress);
+ DAC960_V4_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress);
+ if (CommandStatus == DAC960_NormalCompletion) return true;
+ Controller->DualModeMemoryMailboxInterface = false;
+ CommandMailbox.TypeX.CommandOpcode2 = 0x10;
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+
+/*
+ DAC960_DetectControllers detects DAC960 PCI RAID Controllers by interrogating
+ the PCI Configuration Space for Controller Type.
+*/
+
+static void DAC960_DetectControllers(DAC960_ControllerType_T ControllerType)
+{
+ unsigned short VendorID = 0, DeviceID = 0;
+ unsigned int MemoryWindowSize = 0;
+ PCI_Device_T *PCI_Device = NULL;
+ switch (ControllerType)
+ {
+ case DAC960_V5_Controller:
+ VendorID = PCI_VENDOR_ID_DEC;
+ DeviceID = PCI_DEVICE_ID_DEC_21285;
+ MemoryWindowSize = DAC960_V5_RegisterWindowSize;
+ break;
+ case DAC960_V4_Controller:
+ VendorID = PCI_VENDOR_ID_MYLEX;
+ DeviceID = PCI_DEVICE_ID_MYLEX_DAC960P_V4;
+ MemoryWindowSize = DAC960_V4_RegisterWindowSize;
+ break;
+ case DAC960_V3_Controller:
+ VendorID = PCI_VENDOR_ID_MYLEX;
+ DeviceID = PCI_DEVICE_ID_MYLEX_DAC960P_V3;
+ MemoryWindowSize = DAC960_V3_RegisterWindowSize;
+ break;
+ }
+ while ((PCI_Device = pci_find_device(VendorID, DeviceID, PCI_Device)) != NULL)
+ {
+ DAC960_Controller_T *Controller = (DAC960_Controller_T *)
+ kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC);
+ DAC960_IO_Address_T IO_Address = 0;
+ DAC960_PCI_Address_T PCI_Address = 0;
+ unsigned char Bus = PCI_Device->bus->number;
+ unsigned char DeviceFunction = PCI_Device->devfn;
+ unsigned char Device = DeviceFunction >> 3;
+ unsigned char Function = DeviceFunction & 0x7;
+ unsigned int IRQ_Channel = PCI_Device->irq;
+ unsigned long BaseAddress0 = PCI_Device->base_address[0];
+ unsigned long BaseAddress1 = PCI_Device->base_address[1];
+ unsigned short SubsystemVendorID, SubsystemDeviceID;
+ int CommandIdentifier;
+ pci_read_config_word(PCI_Device, PCI_SUBSYSTEM_VENDOR_ID,
+ &SubsystemVendorID);
+ pci_read_config_word(PCI_Device, PCI_SUBSYSTEM_ID,
+ &SubsystemDeviceID);
+ switch (ControllerType)
+ {
+ case DAC960_V5_Controller:
+ if (!(SubsystemVendorID == PCI_VENDOR_ID_MYLEX &&
+ SubsystemDeviceID == PCI_DEVICE_ID_MYLEX_DAC960P_V5))
+ goto Ignore;
+ PCI_Address = BaseAddress0 & PCI_BASE_ADDRESS_MEM_MASK;
+ break;
+ case DAC960_V4_Controller:
+ PCI_Address = BaseAddress0 & PCI_BASE_ADDRESS_MEM_MASK;
+ break;
+ case DAC960_V3_Controller:
+ IO_Address = BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK;
+ PCI_Address = BaseAddress1 & PCI_BASE_ADDRESS_MEM_MASK;
+ break;
+ }
+ if (DAC960_ControllerCount == DAC960_MaxControllers)
+ {
+ DAC960_Error("More than %d DAC960 Controllers detected - "
+ "ignoring from Controller at\n",
+ NULL, DAC960_MaxControllers);
+ goto Ignore;
+ }
+ if (Controller == NULL)
+ {
+ DAC960_Error("Unable to allocate Controller structure for "
+ "Controller at\n", NULL);
+ goto Ignore;
+ }
+ memset(Controller, 0, sizeof(DAC960_Controller_T));
+ init_waitqueue_head(&Controller->CommandWaitQueue);
+ Controller->ControllerNumber = DAC960_ControllerCount;
+ DAC960_Controllers[DAC960_ControllerCount++] = Controller;
+ DAC960_AnnounceDriver(Controller);
+ Controller->ControllerType = ControllerType;
+ Controller->IO_Address = IO_Address;
+ Controller->PCI_Address = PCI_Address;
+ Controller->Bus = Bus;
+ Controller->Device = Device;
+ Controller->Function = Function;
+ sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber);
+ /*
+ Acquire shared access to the IRQ Channel.
+ */
+ if (IRQ_Channel == 0)
+ {
+ DAC960_Error("IRQ Channel %d illegal for Controller at\n",
+ Controller, IRQ_Channel);
+ goto Failure;
+ }
+ strcpy(Controller->FullModelName, "DAC960");
+ if (request_irq(IRQ_Channel, DAC960_InterruptHandler,
+ SA_SHIRQ, Controller->FullModelName, Controller) < 0)
+ {
+ DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n",
+ Controller, IRQ_Channel);
+ goto Failure;
+ }
+ Controller->IRQ_Channel = IRQ_Channel;
+ /*
+ Map the Controller Register Window.
+ */
+ if (MemoryWindowSize < PAGE_SIZE)
+ MemoryWindowSize = PAGE_SIZE;
+ Controller->MemoryMappedAddress =
+ ioremap_nocache(PCI_Address & PAGE_MASK, MemoryWindowSize);
+ Controller->BaseAddress =
+ Controller->MemoryMappedAddress + (PCI_Address & ~PAGE_MASK);
+ if (Controller->MemoryMappedAddress == NULL)
+ {
+ DAC960_Error("Unable to map Controller Register Window for "
+ "Controller at\n", Controller);
+ goto Failure;
+ }
+ switch (ControllerType)
+ {
+ case DAC960_V5_Controller:
+ DAC960_V5_DisableInterrupts(Controller->BaseAddress);
+ if (!DAC960_EnableMemoryMailboxInterface(Controller))
+ {
+ DAC960_Error("Unable to Enable Memory Mailbox Interface "
+ "for Controller at\n", Controller);
+ goto Failure;
+ }
+ DAC960_V5_EnableInterrupts(Controller->BaseAddress);
+ break;
+ case DAC960_V4_Controller:
+ DAC960_V4_DisableInterrupts(Controller->BaseAddress);
+ if (!DAC960_EnableMemoryMailboxInterface(Controller))
+ {
+ DAC960_Error("Unable to Enable Memory Mailbox Interface "
+ "for Controller at\n", Controller);
+ goto Failure;
+ }
+ DAC960_V4_EnableInterrupts(Controller->BaseAddress);
+ break;
+ case DAC960_V3_Controller:
+ request_region(Controller->IO_Address, 0x80,
+ Controller->FullModelName);
+ DAC960_V3_EnableInterrupts(Controller->BaseAddress);
+ break;
+ }
+ DAC960_ActiveControllerCount++;
+ for (CommandIdentifier = 0;
+ CommandIdentifier < DAC960_MaxChannels;
+ CommandIdentifier++)
+ {
+ Controller->Commands[CommandIdentifier].Controller = Controller;
+ Controller->Commands[CommandIdentifier].Next =
+ Controller->FreeCommands;
+ Controller->FreeCommands = &Controller->Commands[CommandIdentifier];
+ }
+ continue;
+ Failure:
+ if (IO_Address == 0)
+ DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A "
+ "PCI Address 0x%X\n", Controller,
+ Bus, Device, Function, PCI_Address);
+ else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address "
+ "0x%X PCI Address 0x%X\n", Controller,
+ Bus, Device, Function, IO_Address, PCI_Address);
+ if (Controller == NULL) break;
+ if (Controller->IRQ_Channel > 0)
+ free_irq(IRQ_Channel, Controller);
+ if (Controller->MemoryMappedAddress != NULL)
+ iounmap(Controller->MemoryMappedAddress);
+ DAC960_Controllers[Controller->ControllerNumber] = NULL;
+ Ignore:
+ kfree(Controller);
+ }
+}
+
+
+/*
+ DAC960_ReadControllerConfiguration reads the Configuration Information
+ from Controller and initializes the Controller structure.
+*/
+
+static boolean DAC960_ReadControllerConfiguration(DAC960_Controller_T
+ *Controller)
+{
+ DAC960_Enquiry2_T Enquiry2;
+ DAC960_Config2_T Config2;
+ int LogicalDriveNumber, Channel, TargetID;
+ if (!DAC960_ExecuteType3(Controller, DAC960_Enquiry,
+ &Controller->Enquiry[0]))
+ return DAC960_Failure(Controller, "ENQUIRY");
+ if (!DAC960_ExecuteType3(Controller, DAC960_Enquiry2, &Enquiry2))
+ return DAC960_Failure(Controller, "ENQUIRY2");
+ if (!DAC960_ExecuteType3(Controller, DAC960_ReadConfig2, &Config2))
+ return DAC960_Failure(Controller, "READ CONFIG2");
+ if (!DAC960_ExecuteType3(Controller, DAC960_GetLogicalDriveInformation,
+ &Controller->LogicalDriveInformation[0]))
+ return DAC960_Failure(Controller, "GET LOGICAL DRIVE INFORMATION");
+ for (Channel = 0; Channel < Enquiry2.ActualChannels; Channel++)
+ for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++)
+ if (!DAC960_ExecuteType3D(Controller, DAC960_GetDeviceState,
+ Channel, TargetID,
+ &Controller->DeviceState[0][Channel][TargetID]))
+ return DAC960_Failure(Controller, "GET DEVICE STATE");
+ /*
+ Initialize the Controller Model Name and Full Model Name fields.
+ */
+ switch (Enquiry2.HardwareID.SubModel)
+ {
+ case DAC960_P_PD_PU:
+ if (Enquiry2.SCSICapability.BusSpeed == DAC960_Ultra)
+ strcpy(Controller->ModelName, "DAC960PU");
+ else strcpy(Controller->ModelName, "DAC960PD");
+ break;
+ case DAC960_PL:
+ strcpy(Controller->ModelName, "DAC960PL");
+ break;
+ case DAC960_PG:
+ strcpy(Controller->ModelName, "DAC960PG");
+ break;
+ case DAC960_PJ:
+ strcpy(Controller->ModelName, "DAC960PJ");
+ break;
+ case DAC960_PR:
+ strcpy(Controller->ModelName, "DAC960PR");
+ break;
+ case DAC960_PT:
+ strcpy(Controller->ModelName, "DAC960PT");
+ break;
+ case DAC960_PTL0:
+ strcpy(Controller->ModelName, "DAC960PTL0");
+ break;
+ case DAC960_PRL:
+ strcpy(Controller->ModelName, "DAC960PRL");
+ break;
+ case DAC960_PTL1:
+ strcpy(Controller->ModelName, "DAC960PTL1");
+ break;
+ case DAC1164_P:
+ strcpy(Controller->ModelName, "DAC1164P");
+ break;
+ default:
+ return DAC960_Failure(Controller, "MODEL VERIFICATION");
+ }
+ strcpy(Controller->FullModelName, "Mylex ");
+ strcat(Controller->FullModelName, Controller->ModelName);
+ /*
+ Initialize the Controller Firmware Version field and verify that it
+ is a supported firmware version. The supported firmware versions are:
+
+ DAC1164P 5.06 and above
+ DAC960PTL/PRL/PJ/PG 4.06 and above
+ DAC960PU/PD/PL 3.51 and above
+ */
+ sprintf(Controller->FirmwareVersion, "%d.%02d-%c-%02d",
+ Enquiry2.FirmwareID.MajorVersion, Enquiry2.FirmwareID.MinorVersion,
+ Enquiry2.FirmwareID.FirmwareType, Enquiry2.FirmwareID.TurnID);
+ if (!((Controller->FirmwareVersion[0] == '5' &&
+ strcmp(Controller->FirmwareVersion, "5.06") >= 0) ||
+ (Controller->FirmwareVersion[0] == '4' &&
+ strcmp(Controller->FirmwareVersion, "4.06") >= 0) ||
+ (Controller->FirmwareVersion[0] == '3' &&
+ strcmp(Controller->FirmwareVersion, "3.51") >= 0)))
+ {
+ DAC960_Failure(Controller, "FIRMWARE VERSION VERIFICATION");
+ DAC960_Error("Firmware Version = '%s'\n", Controller,
+ Controller->FirmwareVersion);
+ return false;
+ }
+ /*
+ Initialize the Controller Channels, Memory Size, and SAF-TE Enclosure
+ Management Enabled fields.
+ */
+ Controller->Channels = Enquiry2.ActualChannels;
+ Controller->MemorySize = Enquiry2.MemorySize >> 20;
+ Controller->SAFTE_EnclosureManagementEnabled =
+ Enquiry2.FaultManagementType == DAC960_SAFTE;
+ /*
+ Initialize the Controller Queue Depth, Driver Queue Depth, Logical Drive
+ Count, Maximum Blocks per Command, and Maximum Scatter/Gather Segments.
+ The Driver Queue Depth must be at most one less than the Controller Queue
+ Depth to allow for an automatic drive rebuild operation.
+ */
+ Controller->ControllerQueueDepth = Controller->Enquiry[0].MaxCommands;
+ Controller->DriverQueueDepth = Controller->ControllerQueueDepth - 1;
+ Controller->LogicalDriveCount = Controller->Enquiry[0].NumberOfLogicalDrives;
+ Controller->MaxBlocksPerCommand = Enquiry2.MaxBlocksPerCommand;
+ Controller->MaxScatterGatherSegments = Enquiry2.MaxScatterGatherEntries;
+ /*
+ Initialize the Stripe Size, Segment Size, and Geometry Translation.
+ */
+ Controller->StripeSize = Config2.BlocksPerStripe * Config2.BlockFactor
+ >> (10 - DAC960_BlockSizeBits);
+ Controller->SegmentSize = Config2.BlocksPerCacheLine * Config2.BlockFactor
+ >> (10 - DAC960_BlockSizeBits);
+ switch (Config2.DriveGeometry)
+ {
+ case DAC960_Geometry_128_32:
+ Controller->GeometryTranslationHeads = 128;
+ Controller->GeometryTranslationSectors = 32;
+ break;
+ case DAC960_Geometry_255_63:
+ Controller->GeometryTranslationHeads = 255;
+ Controller->GeometryTranslationSectors = 63;
+ break;
+ default:
+ return DAC960_Failure(Controller, "CONFIG2 DRIVE GEOMETRY");
+ }
+ /*
+ Initialize the Logical Drive Initial State.
+ */
+ for (LogicalDriveNumber = 0;
+ LogicalDriveNumber < Controller->LogicalDriveCount;
+ LogicalDriveNumber++)
+ Controller->LogicalDriveInitialState[LogicalDriveNumber] =
+ Controller->LogicalDriveInformation[0]
+ [LogicalDriveNumber].LogicalDriveState;
+ Controller->LastRebuildStatus = DAC960_NoRebuildOrCheckInProgress;
+ return true;
+}
+
+
+/*
+ DAC960_ReportControllerConfiguration reports the Configuration Information of
+ Controller.
+*/
+
+static boolean DAC960_ReportControllerConfiguration(DAC960_Controller_T
+ *Controller)
+{
+ DAC960_Info("Configuring Mylex %s PCI RAID Controller\n",
+ Controller, Controller->ModelName);
+ DAC960_Info(" Firmware Version: %s, Channels: %d, Memory Size: %dMB\n",
+ Controller, Controller->FirmwareVersion,
+ Controller->Channels, Controller->MemorySize);
+ DAC960_Info(" PCI Bus: %d, Device: %d, Function: %d, I/O Address: ",
+ Controller, Controller->Bus,
+ Controller->Device, Controller->Function);
+ if (Controller->IO_Address == 0)
+ DAC960_Info("Unassigned\n", Controller);
+ else DAC960_Info("0x%X\n", Controller, Controller->IO_Address);
+ DAC960_Info(" PCI Address: 0x%X mapped at 0x%lX, IRQ Channel: %d\n",
+ Controller, Controller->PCI_Address,
+ (unsigned long) Controller->BaseAddress,
+ Controller->IRQ_Channel);
+ DAC960_Info(" Controller Queue Depth: %d, "
+ "Maximum Blocks per Command: %d\n",
+ Controller, Controller->ControllerQueueDepth,
+ Controller->MaxBlocksPerCommand);
+ DAC960_Info(" Driver Queue Depth: %d, "
+ "Maximum Scatter/Gather Segments: %d\n",
+ Controller, Controller->DriverQueueDepth,
+ Controller->MaxScatterGatherSegments);
+ DAC960_Info(" Stripe Size: %dKB, Segment Size: %dKB, "
+ "BIOS Geometry: %d/%d\n", Controller,
+ Controller->StripeSize,
+ Controller->SegmentSize,
+ Controller->GeometryTranslationHeads,
+ Controller->GeometryTranslationSectors);
+ if (Controller->SAFTE_EnclosureManagementEnabled)
+ DAC960_Info(" SAF-TE Enclosure Management Enabled\n", Controller);
+ return true;
+}
+
+
+/*
+ DAC960_ReadDeviceConfiguration reads the Device Configuration Information by
+ requesting the SCSI Inquiry and SCSI Inquiry Unit Serial Number information
+ for each device connected to Controller.
+*/
+
+static boolean DAC960_ReadDeviceConfiguration(DAC960_Controller_T *Controller)
+{
+ DAC960_DCDB_T DCDBs[DAC960_MaxChannels], *DCDB;
+ Semaphore_T Semaphores[DAC960_MaxChannels], *Semaphore;
+ unsigned long ProcessorFlags;
+ int Channel, TargetID;
+ for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++)
+ {
+ for (Channel = 0; Channel < Controller->Channels; Channel++)
+ {
+ DAC960_Command_T *Command = &Controller->Commands[Channel];
+ DAC960_SCSI_Inquiry_T *InquiryStandardData =
+ &Controller->InquiryStandardData[Channel][TargetID];
+ InquiryStandardData->PeripheralDeviceType = 0x1F;
+ Semaphore = &Semaphores[Channel];
+ *Semaphore = MUTEX_LOCKED;
+ DCDB = &DCDBs[Channel];
+ DAC960_ClearCommand(Command);
+ Command->CommandType = DAC960_ImmediateCommand;
+ Command->Semaphore = Semaphore;
+ Command->CommandMailbox.Type3.CommandOpcode = DAC960_DCDB;
+ Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB);
+ DCDB->Channel = Channel;
+ DCDB->TargetID = TargetID;
+ DCDB->Direction = DAC960_DCDB_DataTransferDeviceToSystem;
+ DCDB->EarlyStatus = false;
+ DCDB->Timeout = DAC960_DCDB_Timeout_10_seconds;
+ DCDB->NoAutomaticRequestSense = false;
+ DCDB->DisconnectPermitted = true;
+ DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T);
+ DCDB->BusAddress = Virtual_to_Bus(InquiryStandardData);
+ DCDB->CDBLength = 6;
+ DCDB->TransferLengthHigh4 = 0;
+ DCDB->SenseLength = sizeof(DCDB->SenseData);
+ DCDB->CDB[0] = 0x12; /* INQUIRY */
+ DCDB->CDB[1] = 0; /* EVPD = 0 */
+ DCDB->CDB[2] = 0; /* Page Code */
+ DCDB->CDB[3] = 0; /* Reserved */
+ DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_T);
+ DCDB->CDB[5] = 0; /* Control */
+ DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+ DAC960_QueueCommand(Command);
+ DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+ }
+ for (Channel = 0; Channel < Controller->Channels; Channel++)
+ {
+ DAC960_Command_T *Command = &Controller->Commands[Channel];
+ DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber =
+ &Controller->InquiryUnitSerialNumber[Channel][TargetID];
+ InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
+ Semaphore = &Semaphores[Channel];
+ down(Semaphore);
+ if (Command->CommandStatus != DAC960_NormalCompletion) continue;
+ Command->Semaphore = Semaphore;
+ DCDB = &DCDBs[Channel];
+ DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
+ DCDB->BusAddress = Virtual_to_Bus(InquiryUnitSerialNumber);
+ DCDB->SenseLength = sizeof(DCDB->SenseData);
+ DCDB->CDB[0] = 0x12; /* INQUIRY */
+ DCDB->CDB[1] = 1; /* EVPD = 1 */
+ DCDB->CDB[2] = 0x80; /* Page Code */
+ DCDB->CDB[3] = 0; /* Reserved */
+ DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
+ DCDB->CDB[5] = 0; /* Control */
+ DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+ DAC960_QueueCommand(Command);
+ DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+ down(Semaphore);
+ }
+ }
+ return true;
+}
+
+
+/*
+ DAC960_ReportDeviceConfiguration reports the Device Configuration Information
+ of Controller.
+*/
+
+static boolean DAC960_ReportDeviceConfiguration(DAC960_Controller_T *Controller)
+{
+ int LogicalDriveNumber, Channel, TargetID;
+ DAC960_Info(" Physical Devices:\n", Controller);
+ for (Channel = 0; Channel < Controller->Channels; Channel++)
+ for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++)
+ {
+ DAC960_SCSI_Inquiry_T *InquiryStandardData =
+ &Controller->InquiryStandardData[Channel][TargetID];
+ DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber =
+ &Controller->InquiryUnitSerialNumber[Channel][TargetID];
+ DAC960_DeviceState_T *DeviceState =
+ &Controller->DeviceState[Controller->DeviceStateIndex]
+ [Channel][TargetID];
+ DAC960_ErrorTable_T *ErrorTable =
+ &Controller->ErrorTable[Controller->ErrorTableIndex];
+ DAC960_ErrorTableEntry_T *ErrorEntry =
+ &ErrorTable->ErrorTableEntries[Channel][TargetID];
+ char Vendor[1+sizeof(InquiryStandardData->VendorIdentification)];
+ char Model[1+sizeof(InquiryStandardData->ProductIdentification)];
+ char Revision[1+sizeof(InquiryStandardData->ProductRevisionLevel)];
+ char SerialNumber[1+sizeof(InquiryUnitSerialNumber
+ ->ProductSerialNumber)];
+ int i;
+ if (InquiryStandardData->PeripheralDeviceType == 0x1F) continue;
+ for (i = 0; i < sizeof(Vendor)-1; i++)
+ {
+ unsigned char VendorCharacter =
+ InquiryStandardData->VendorIdentification[i];
+ Vendor[i] = (VendorCharacter >= ' ' && VendorCharacter <= '~'
+ ? VendorCharacter : ' ');
+ }
+ Vendor[sizeof(Vendor)-1] = '\0';
+ for (i = 0; i < sizeof(Model)-1; i++)
+ {
+ unsigned char ModelCharacter =
+ InquiryStandardData->ProductIdentification[i];
+ Model[i] = (ModelCharacter >= ' ' && ModelCharacter <= '~'
+ ? ModelCharacter : ' ');
+ }
+ Model[sizeof(Model)-1] = '\0';
+ for (i = 0; i < sizeof(Revision)-1; i++)
+ {
+ unsigned char RevisionCharacter =
+ InquiryStandardData->ProductRevisionLevel[i];
+ Revision[i] = (RevisionCharacter >= ' ' && RevisionCharacter <= '~'
+ ? RevisionCharacter : ' ');
+ }
+ Revision[sizeof(Revision)-1] = '\0';
+ DAC960_Info(" %d:%d%s Vendor: %s Model: %s Revision: %s\n",
+ Controller, Channel, TargetID, (TargetID < 10 ? " " : ""),
+ Vendor, Model, Revision);
+ if (InquiryUnitSerialNumber->PeripheralDeviceType != 0x1F)
+ {
+ int SerialNumberLength = InquiryUnitSerialNumber->PageLength;
+ if (SerialNumberLength >
+ sizeof(InquiryUnitSerialNumber->ProductSerialNumber))
+ SerialNumberLength =
+ sizeof(InquiryUnitSerialNumber->ProductSerialNumber);
+ for (i = 0; i < SerialNumberLength; i++)
+ {
+ unsigned char SerialNumberCharacter =
+ InquiryUnitSerialNumber->ProductSerialNumber[i];
+ SerialNumber[i] =
+ (SerialNumberCharacter >= ' ' && SerialNumberCharacter <= '~'
+ ? SerialNumberCharacter : ' ');
+ }
+ SerialNumber[SerialNumberLength] = '\0';
+ DAC960_Info(" Serial Number: %s\n",
+ Controller, SerialNumber);
+ }
+ if (DeviceState->Present && DeviceState->DeviceType == DAC960_DiskType)
+ {
+ if (Controller->DeviceResetCount[Channel][TargetID] > 0)
+ DAC960_Info(" Disk Status: %s, %d blocks, %d resets\n",
+ Controller,
+ (DeviceState->DeviceState == DAC960_Device_Dead
+ ? "Dead"
+ : DeviceState->DeviceState == DAC960_Device_WriteOnly
+ ? "Write-Only"
+ : DeviceState->DeviceState == DAC960_Device_Online
+ ? "Online" : "Standby"),
+ DeviceState->DiskSize,
+ Controller->DeviceResetCount[Channel][TargetID]);
+ else
+ DAC960_Info(" Disk Status: %s, %d blocks\n", Controller,
+ (DeviceState->DeviceState == DAC960_Device_Dead
+ ? "Dead"
+ : DeviceState->DeviceState == DAC960_Device_WriteOnly
+ ? "Write-Only"
+ : DeviceState->DeviceState == DAC960_Device_Online
+ ? "Online" : "Standby"),
+ DeviceState->DiskSize);
+ }
+ if (ErrorEntry->ParityErrorCount > 0 ||
+ ErrorEntry->SoftErrorCount > 0 ||
+ ErrorEntry->HardErrorCount > 0 ||
+ ErrorEntry->MiscErrorCount > 0)
+ DAC960_Info(" Errors - Parity: %d, Soft: %d, "
+ "Hard: %d, Misc: %d\n", Controller,
+ ErrorEntry->ParityErrorCount,
+ ErrorEntry->SoftErrorCount,
+ ErrorEntry->HardErrorCount,
+ ErrorEntry->MiscErrorCount);
+ }
+ DAC960_Info(" Logical Drives:\n", Controller);
+ for (LogicalDriveNumber = 0;
+ LogicalDriveNumber < Controller->LogicalDriveCount;
+ LogicalDriveNumber++)
+ {
+ DAC960_LogicalDriveInformation_T *LogicalDriveInformation =
+ &Controller->LogicalDriveInformation
+ [Controller->LogicalDriveInformationIndex][LogicalDriveNumber];
+ DAC960_Info(" /dev/rd/c%dd%d: RAID-%d, %s, %d blocks, %s\n",
+ Controller, Controller->ControllerNumber, LogicalDriveNumber,
+ LogicalDriveInformation->RAIDLevel,
+ (LogicalDriveInformation->LogicalDriveState ==
+ DAC960_LogicalDrive_Online
+ ? "Online"
+ : LogicalDriveInformation->LogicalDriveState ==
+ DAC960_LogicalDrive_Critical
+ ? "Critical" : "Offline"),
+ LogicalDriveInformation->LogicalDriveSize,
+ (LogicalDriveInformation->WriteBack
+ ? "Write Back" : "Write Thru"));
+ }
+ return true;
+}
+
+
+/*
+ DAC960_RegisterBlockDevice registers the Block Device structures
+ associated with Controller.
+*/
+
+static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
+{
+ static void (*RequestFunctions[DAC960_MaxControllers])(void) =
+ { DAC960_RequestFunction0, DAC960_RequestFunction1,
+ DAC960_RequestFunction2, DAC960_RequestFunction3,
+ DAC960_RequestFunction4, DAC960_RequestFunction5,
+ DAC960_RequestFunction6, DAC960_RequestFunction7 };
+ int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber;
+ GenericDiskInfo_T *GenericDiskInfo;
+ int MinorNumber;
+ /*
+ Register the Block Device Major Number for this DAC960 Controller.
+ */
+ if (register_blkdev(MajorNumber, "rd", &DAC960_FileOperations) < 0)
+ {
+ DAC960_Error("UNABLE TO ACQUIRE MAJOR NUMBER %d - DETACHING\n",
+ Controller, MajorNumber);
+ return false;
+ }
+ /*
+ Initialize the I/O Request Function.
+ */
+ blk_dev[MajorNumber].request_fn =
+ 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.
+ */
+ for (MinorNumber = 0; MinorNumber < DAC960_MinorCount; MinorNumber++)
+ {
+ Controller->BlockSizes[MinorNumber] = BLOCK_SIZE;
+ Controller->MaxSectorsPerRequest[MinorNumber] =
+ Controller->MaxBlocksPerCommand;
+ Controller->MaxSegmentsPerRequest[MinorNumber] =
+ Controller->MaxScatterGatherSegments;
+ }
+ Controller->GenericDiskInfo.part = Controller->DiskPartitions;
+ Controller->GenericDiskInfo.sizes = Controller->PartitionSizes;
+ blksize_size[MajorNumber] = Controller->BlockSizes;
+ max_sectors[MajorNumber] = Controller->MaxSectorsPerRequest;
+ max_segments[MajorNumber] = Controller->MaxSegmentsPerRequest;
+ /*
+ Initialize Read Ahead to 128 sectors.
+ */
+ read_ahead[MajorNumber] = 128;
+ /*
+ Complete initialization of the Generic Disk Information structure.
+ */
+ Controller->GenericDiskInfo.major = MajorNumber;
+ Controller->GenericDiskInfo.major_name = "rd";
+ Controller->GenericDiskInfo.minor_shift = DAC960_MaxPartitionsBits;
+ Controller->GenericDiskInfo.max_p = DAC960_MaxPartitions;
+ Controller->GenericDiskInfo.max_nr = DAC960_MaxLogicalDrives;
+ Controller->GenericDiskInfo.init = DAC960_InitializeGenericDiskInfo;
+ Controller->GenericDiskInfo.nr_real = Controller->LogicalDriveCount;
+ Controller->GenericDiskInfo.real_devices = Controller;
+ Controller->GenericDiskInfo.next = NULL;
+ /*
+ Install the Generic Disk Information structure at the end of the list.
+ */
+ if ((GenericDiskInfo = gendisk_head) != NULL)
+ {
+ while (GenericDiskInfo->next != NULL)
+ GenericDiskInfo = GenericDiskInfo->next;
+ GenericDiskInfo->next = &Controller->GenericDiskInfo;
+ }
+ else gendisk_head = &Controller->GenericDiskInfo;
+ /*
+ Indicate the Block Device Registration completed successfully,
+ */
+ return true;
+}
+
+
+/*
+ DAC960_UnregisterBlockDevice unregisters the Block Device structures
+ associated with Controller.
+*/
+
+static void DAC960_UnregisterBlockDevice(DAC960_Controller_T *Controller)
+{
+ int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber;
+ /*
+ Unregister the Block Device Major Number for this DAC960 Controller.
+ */
+ unregister_blkdev(MajorNumber, "rd");
+ /*
+ Remove the I/O Request Function.
+ */
+ blk_dev[MajorNumber].request_fn = NULL;
+ /*
+ Remove the Disk Partitions array, Partition Sizes array, Block Sizes
+ array, Max Sectors per Request array, and Max Segments per Request array.
+ */
+ Controller->GenericDiskInfo.part = NULL;
+ Controller->GenericDiskInfo.sizes = NULL;
+ blk_size[MajorNumber] = NULL;
+ blksize_size[MajorNumber] = NULL;
+ max_sectors[MajorNumber] = NULL;
+ max_segments[MajorNumber] = NULL;
+ /*
+ Remove the Generic Disk Information structure from the list.
+ */
+ if (gendisk_head != &Controller->GenericDiskInfo)
+ {
+ GenericDiskInfo_T *GenericDiskInfo = gendisk_head;
+ while (GenericDiskInfo != NULL &&
+ GenericDiskInfo->next != &Controller->GenericDiskInfo)
+ GenericDiskInfo = GenericDiskInfo->next;
+ if (GenericDiskInfo != NULL)
+ GenericDiskInfo->next = GenericDiskInfo->next->next;
+ }
+ else gendisk_head = Controller->GenericDiskInfo.next;
+}
+
+
+/*
+ DAC960_InitializeController initializes Controller.
+*/
+
+static void DAC960_InitializeController(DAC960_Controller_T *Controller)
+{
+ if (DAC960_ReadControllerConfiguration(Controller) &&
+ DAC960_ReportControllerConfiguration(Controller) &&
+ DAC960_ReadDeviceConfiguration(Controller) &&
+ DAC960_ReportDeviceConfiguration(Controller) &&
+ DAC960_RegisterBlockDevice(Controller))
+ {
+ /*
+ Initialize the Command structures.
+ */
+ DAC960_Command_T *Commands = Controller->Commands;
+ int CommandIdentifier;
+ Controller->FreeCommands = NULL;
+ for (CommandIdentifier = 0;
+ CommandIdentifier < Controller->DriverQueueDepth;
+ CommandIdentifier++)
+ {
+ Commands[CommandIdentifier].Controller = Controller;
+ Commands[CommandIdentifier].Next = Controller->FreeCommands;
+ Controller->FreeCommands = &Commands[CommandIdentifier];
+ }
+ /*
+ Initialize the Monitoring Timer.
+ */
+ init_timer(&Controller->MonitoringTimer);
+ Controller->MonitoringTimer.expires =
+ jiffies + DAC960_MonitoringTimerInterval;
+ Controller->MonitoringTimer.data = (unsigned long) Controller;
+ Controller->MonitoringTimer.function = DAC960_MonitoringTimerFunction;
+ add_timer(&Controller->MonitoringTimer);
+ Controller->ControllerInitialized = true;
+ }
+ else DAC960_FinalizeController(Controller);
+}
+
+
+/*
+ DAC960_FinalizeController finalizes Controller.
+*/
+
+static void DAC960_FinalizeController(DAC960_Controller_T *Controller)
+{
+ if (Controller->ControllerInitialized)
+ {
+ del_timer(&Controller->MonitoringTimer);
+ DAC960_Notice("Flushing Cache...", Controller);
+ DAC960_ExecuteType3(Controller, DAC960_Flush, NULL);
+ DAC960_Notice("done\n", Controller);
+ switch (Controller->ControllerType)
+ {
+ case DAC960_V5_Controller:
+ if (!Controller->DualModeMemoryMailboxInterface)
+ DAC960_V5_SaveMemoryMailboxInfo(Controller);
+ break;
+ case DAC960_V4_Controller:
+ if (!Controller->DualModeMemoryMailboxInterface)
+ DAC960_V4_SaveMemoryMailboxInfo(Controller);
+ break;
+ case DAC960_V3_Controller:
+ break;
+ }
+ }
+ free_irq(Controller->IRQ_Channel, Controller);
+ iounmap(Controller->MemoryMappedAddress);
+ if (Controller->IO_Address > 0)
+ release_region(Controller->IO_Address, 0x80);
+ DAC960_UnregisterBlockDevice(Controller);
+ DAC960_Controllers[Controller->ControllerNumber] = NULL;
+ kfree(Controller);
+}
+
+
+/*
+ DAC960_Initialize initializes the DAC960 Driver.
+*/
+
+void DAC960_Initialize(void)
+{
+ int ControllerNumber;
+ DAC960_DetectControllers(DAC960_V5_Controller);
+ DAC960_DetectControllers(DAC960_V4_Controller);
+ DAC960_DetectControllers(DAC960_V3_Controller);
+ if (DAC960_ActiveControllerCount == 0) return;
+ for (ControllerNumber = 0;
+ ControllerNumber < DAC960_ControllerCount;
+ ControllerNumber++)
+ if (DAC960_Controllers[ControllerNumber] != NULL)
+ DAC960_InitializeController(DAC960_Controllers[ControllerNumber]);
+ DAC960_CreateProcEntries();
+ register_reboot_notifier(&DAC960_NotifierBlock);
+}
+
+
+/*
+ DAC960_Finalize finalizes the DAC960 Driver.
+*/
+
+static int DAC960_Finalize(NotifierBlock_T *NotifierBlock,
+ unsigned long Event,
+ void *Buffer)
+{
+ int ControllerNumber;
+ if (!(Event == SYS_RESTART || Event == SYS_HALT || Event == SYS_POWER_OFF))
+ return NOTIFY_DONE;
+ if (DAC960_ActiveControllerCount == 0) return NOTIFY_OK;
+ for (ControllerNumber = 0;
+ ControllerNumber < DAC960_ControllerCount;
+ ControllerNumber++)
+ if (DAC960_Controllers[ControllerNumber] != NULL)
+ DAC960_FinalizeController(DAC960_Controllers[ControllerNumber]);
+ DAC960_DestroyProcEntries();
+ unregister_reboot_notifier(&DAC960_NotifierBlock);
+ return NOTIFY_OK;
+}
+
+
+/*
+ DAC960_ProcessRequest attempts to remove one I/O Request from Controller's
+ I/O Request Queue and queues it to the Controller. WaitForCommand is true if
+ this function should wait for a Command to become available if necessary.
+ This function returns true if an I/O Request was queued and false otherwise.
+*/
+
+static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller,
+ boolean WaitForCommand)
+{
+ IO_Request_T **RequestQueuePointer =
+ &blk_dev[DAC960_MAJOR + Controller->ControllerNumber].current_request;
+ IO_Request_T *Request;
+ DAC960_Command_T *Command;
+ char *RequestBuffer;
+ while (true)
+ {
+ Request = *RequestQueuePointer;
+ if (Request == NULL || Request->rq_status == RQ_INACTIVE) return false;
+ Command = DAC960_AllocateCommand(Controller);
+ if (Command != NULL) break;
+ if (!WaitForCommand) return false;
+ spin_unlock(&io_request_lock);
+ sleep_on(&Controller->CommandWaitQueue);
+ spin_lock_irq(&io_request_lock);
+ }
+ DAC960_ClearCommand(Command);
+ if (Request->cmd == READ)
+ Command->CommandType = DAC960_ReadCommand;
+ else Command->CommandType = DAC960_WriteCommand;
+ Command->Semaphore = Request->sem;
+ Command->LogicalDriveNumber = DAC960_LogicalDriveNumber(Request->rq_dev);
+ Command->BlockNumber =
+ Request->sector
+ + Controller->GenericDiskInfo.part[MINOR(Request->rq_dev)].start_sect;
+ Command->BlockCount = Request->nr_sectors;
+ Command->SegmentCount = Request->nr_segments;
+ Command->BufferHeader = Request->bh;
+ RequestBuffer = Request->buffer;
+ Request->rq_status = RQ_INACTIVE;
+ *RequestQueuePointer = Request->next;
+ wake_up(&wait_for_request);
+ if (Command->SegmentCount == 1)
+ {
+ DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+ if (Command->CommandType == DAC960_ReadCommand)
+ CommandMailbox->Type5.CommandOpcode = DAC960_Read;
+ else CommandMailbox->Type5.CommandOpcode = DAC960_Write;
+ CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
+ CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber;
+ CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
+ CommandMailbox->Type5.BusAddress = Virtual_to_Bus(RequestBuffer);
+ }
+ else
+ {
+ DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+ DAC960_ScatterGatherSegment_T
+ *ScatterGatherList = Command->ScatterGatherList;
+ BufferHeader_T *BufferHeader = Command->BufferHeader;
+ char *LastDataEndPointer = NULL;
+ int SegmentNumber = 0;
+ if (Command->CommandType == DAC960_ReadCommand)
+ CommandMailbox->Type5.CommandOpcode = DAC960_ReadWithOldScatterGather;
+ else
+ CommandMailbox->Type5.CommandOpcode = DAC960_WriteWithOldScatterGather;
+ CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
+ CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber;
+ CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
+ CommandMailbox->Type5.BusAddress = Virtual_to_Bus(ScatterGatherList);
+ CommandMailbox->Type5.ScatterGatherCount = Command->SegmentCount;
+ while (BufferHeader != NULL)
+ {
+ if (BufferHeader->b_data == LastDataEndPointer)
+ {
+ ScatterGatherList[SegmentNumber-1].SegmentByteCount +=
+ BufferHeader->b_size;
+ LastDataEndPointer += BufferHeader->b_size;
+ }
+ else
+ {
+ ScatterGatherList[SegmentNumber].SegmentDataPointer =
+ Virtual_to_Bus(BufferHeader->b_data);
+ ScatterGatherList[SegmentNumber].SegmentByteCount =
+ BufferHeader->b_size;
+ LastDataEndPointer = BufferHeader->b_data + BufferHeader->b_size;
+ if (SegmentNumber++ > Controller->MaxScatterGatherSegments)
+ panic("DAC960: Scatter/Gather Segment Overflow\n");
+ }
+ BufferHeader = BufferHeader->b_reqnext;
+ }
+ if (SegmentNumber != Command->SegmentCount)
+ panic("DAC960: SegmentNumber != SegmentCount\n");
+ }
+ DAC960_QueueCommand(Command);
+ return true;
+}
+
+
+/*
+ DAC960_ProcessRequests attempts to remove as many I/O Requests as possible
+ from Controller's I/O Request Queue and queue them to the Controller.
+*/
+
+static inline void DAC960_ProcessRequests(DAC960_Controller_T *Controller)
+{
+ int Counter = 0;
+ while (DAC960_ProcessRequest(Controller, Counter++ == 0)) ;
+}
+
+
+/*
+ DAC960_RequestFunction0 is the I/O Request Function for DAC960 Controller 0.
+*/
+
+static void DAC960_RequestFunction0(void)
+{
+ DAC960_Controller_T *Controller = DAC960_Controllers[0];
+ ProcessorFlags_T ProcessorFlags;
+ /*
+ Acquire exclusive access to Controller.
+ */
+ DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+ /*
+ Process I/O Requests for Controller.
+ */
+ DAC960_ProcessRequests(Controller);
+ /*
+ Release exclusive access to Controller.
+ */
+ DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+ DAC960_RequestFunction1 is the I/O Request Function for DAC960 Controller 1.
+*/
+
+static void DAC960_RequestFunction1(void)
+{
+ DAC960_Controller_T *Controller = DAC960_Controllers[1];
+ ProcessorFlags_T ProcessorFlags;
+ /*
+ Acquire exclusive access to Controller.
+ */
+ DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+ /*
+ Process I/O Requests for Controller.
+ */
+ DAC960_ProcessRequests(Controller);
+ /*
+ Release exclusive access to Controller.
+ */
+ DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+ DAC960_RequestFunction2 is the I/O Request Function for DAC960 Controller 2.
+*/
+
+static void DAC960_RequestFunction2(void)
+{
+ DAC960_Controller_T *Controller = DAC960_Controllers[2];
+ ProcessorFlags_T ProcessorFlags;
+ /*
+ Acquire exclusive access to Controller.
+ */
+ DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+ /*
+ Process I/O Requests for Controller.
+ */
+ DAC960_ProcessRequests(Controller);
+ /*
+ Release exclusive access to Controller.
+ */
+ DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+ DAC960_RequestFunction3 is the I/O Request Function for DAC960 Controller 3.
+*/
+
+static void DAC960_RequestFunction3(void)
+{
+ DAC960_Controller_T *Controller = DAC960_Controllers[3];
+ ProcessorFlags_T ProcessorFlags;
+ /*
+ Acquire exclusive access to Controller.
+ */
+ DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+ /*
+ Process I/O Requests for Controller.
+ */
+ DAC960_ProcessRequests(Controller);
+ /*
+ Release exclusive access to Controller.
+ */
+ DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+ DAC960_RequestFunction4 is the I/O Request Function for DAC960 Controller 4.
+*/
+
+static void DAC960_RequestFunction4(void)
+{
+ DAC960_Controller_T *Controller = DAC960_Controllers[4];
+ ProcessorFlags_T ProcessorFlags;
+ /*
+ Acquire exclusive access to Controller.
+ */
+ DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+ /*
+ Process I/O Requests for Controller.
+ */
+ DAC960_ProcessRequests(Controller);
+ /*
+ Release exclusive access to Controller.
+ */
+ DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+ DAC960_RequestFunction5 is the I/O Request Function for DAC960 Controller 5.
+*/
+
+static void DAC960_RequestFunction5(void)
+{
+ DAC960_Controller_T *Controller = DAC960_Controllers[5];
+ ProcessorFlags_T ProcessorFlags;
+ /*
+ Acquire exclusive access to Controller.
+ */
+ DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+ /*
+ Process I/O Requests for Controller.
+ */
+ DAC960_ProcessRequests(Controller);
+ /*
+ Release exclusive access to Controller.
+ */
+ DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+ DAC960_RequestFunction6 is the I/O Request Function for DAC960 Controller 6.
+*/
+
+static void DAC960_RequestFunction6(void)
+{
+ DAC960_Controller_T *Controller = DAC960_Controllers[6];
+ ProcessorFlags_T ProcessorFlags;
+ /*
+ Acquire exclusive access to Controller.
+ */
+ DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+ /*
+ Process I/O Requests for Controller.
+ */
+ DAC960_ProcessRequests(Controller);
+ /*
+ Release exclusive access to Controller.
+ */
+ DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+ DAC960_RequestFunction7 is the I/O Request Function for DAC960 Controller 7.
+*/
+
+static void DAC960_RequestFunction7(void)
+{
+ DAC960_Controller_T *Controller = DAC960_Controllers[7];
+ ProcessorFlags_T ProcessorFlags;
+ /*
+ Acquire exclusive access to Controller.
+ */
+ DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+ /*
+ Process I/O Requests for Controller.
+ */
+ DAC960_ProcessRequests(Controller);
+ /*
+ Release exclusive access to Controller.
+ */
+ DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+ DAC960_ReadWriteError prints an appropriate error message for Command when
+ an error occurs on a Read or Write operation.
+*/
+
+static void DAC960_ReadWriteError(DAC960_Command_T *Command)
+{
+ DAC960_Controller_T *Controller = Command->Controller;
+ char *CommandName = "UNKNOWN";
+ switch (Command->CommandType)
+ {
+ case DAC960_ReadCommand:
+ case DAC960_ReadRetryCommand:
+ CommandName = "READ";
+ break;
+ case DAC960_WriteCommand:
+ case DAC960_WriteRetryCommand:
+ CommandName = "WRITE";
+ break;
+ case DAC960_MonitoringCommand:
+ case DAC960_ImmediateCommand:
+ case DAC960_QueuedCommand:
+ break;
+ }
+ switch (Command->CommandStatus)
+ {
+ case DAC960_IrrecoverableDataError:
+ DAC960_Error("Irrecoverable Data Error on %s:\n",
+ Controller, CommandName);
+ break;
+ case DAC960_LogicalDriveNonexistentOrOffline:
+ DAC960_Error("Logical Drive Nonexistent or Offline on %s:\n",
+ Controller, CommandName);
+ break;
+ case DAC960_AccessBeyondEndOfLogicalDrive:
+ DAC960_Error("Attempt to Access Beyond End of Logical Drive "
+ "on %s:\n", Controller, CommandName);
+ break;
+ case DAC960_BadDataEncountered:
+ DAC960_Error("Bad Data Encountered on %s:\n", Controller, CommandName);
+ break;
+ default:
+ DAC960_Error("Unexpected Error Status %04X on %s:\n",
+ Controller, Command->CommandStatus, CommandName);
+ break;
+ }
+ DAC960_Error(" /dev/rd/c%dd%d: absolute blocks %d..%d\n",
+ Controller, Controller->ControllerNumber,
+ Command->LogicalDriveNumber, Command->BlockNumber,
+ Command->BlockNumber + Command->BlockCount - 1);
+ if (DAC960_PartitionNumber(Command->BufferHeader->b_rdev) > 0)
+ DAC960_Error(" /dev/rd/c%dd%dp%d: relative blocks %d..%d\n",
+ Controller, Controller->ControllerNumber,
+ Command->LogicalDriveNumber,
+ DAC960_PartitionNumber(Command->BufferHeader->b_rdev),
+ Command->BufferHeader->b_rsector,
+ Command->BufferHeader->b_rsector + Command->BlockCount - 1);
+}
+
+
+/*
+ DAC960_ProcessCompletedBuffer performs completion processing for an
+ individual Buffer.
+*/
+
+static inline void DAC960_ProcessCompletedBuffer(BufferHeader_T *BufferHeader,
+ boolean SuccessfulIO)
+{
+ BufferHeader->b_end_io(BufferHeader, SuccessfulIO);
+}
+
+
+/*
+ DAC960_ProcessCompletedCommand performs completion processing for Command.
+*/
+
+static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command)
+{
+ DAC960_Controller_T *Controller = Command->Controller;
+ DAC960_CommandType_T CommandType = Command->CommandType;
+ DAC960_CommandOpcode_T CommandOpcode =
+ Command->CommandMailbox.Common.CommandOpcode;
+ DAC960_CommandStatus_T CommandStatus = Command->CommandStatus;
+ BufferHeader_T *BufferHeader = Command->BufferHeader;
+ if (CommandType == DAC960_ReadCommand ||
+ CommandType == DAC960_WriteCommand)
+ {
+ if (CommandStatus == DAC960_NormalCompletion)
+ {
+ /*
+ Perform completion processing for all buffers in this I/O Request.
+ */
+ while (BufferHeader != NULL)
+ {
+ BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
+ BufferHeader->b_reqnext = NULL;
+ DAC960_ProcessCompletedBuffer(BufferHeader, true);
+ BufferHeader = NextBufferHeader;
+ }
+ /*
+ Wake up requestor for swap file paging requests.
+ */
+ if (Command->Semaphore != NULL)
+ {
+ up(Command->Semaphore);
+ Command->Semaphore = NULL;
+ }
+ add_blkdev_randomness(DAC960_MAJOR + Controller->ControllerNumber);
+ }
+ else if ((CommandStatus == DAC960_IrrecoverableDataError ||
+ CommandStatus == DAC960_BadDataEncountered) &&
+ BufferHeader != NULL &&
+ BufferHeader->b_reqnext != NULL)
+ {
+ DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+ if (CommandType == DAC960_ReadCommand)
+ {
+ Command->CommandType = DAC960_ReadRetryCommand;
+ CommandMailbox->Type5.CommandOpcode = DAC960_Read;
+ }
+ else
+ {
+ Command->CommandType = DAC960_WriteRetryCommand;
+ CommandMailbox->Type5.CommandOpcode = DAC960_Write;
+ }
+ Command->BlockCount = BufferHeader->b_size >> DAC960_BlockSizeBits;
+ CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
+ CommandMailbox->Type5.BusAddress =
+ Virtual_to_Bus(BufferHeader->b_data);
+ DAC960_QueueCommand(Command);
+ return;
+ }
+ else
+ {
+ if (CommandStatus != DAC960_LogicalDriveNonexistentOrOffline)
+ DAC960_ReadWriteError(Command);
+ /*
+ Perform completion processing for all buffers in this I/O Request.
+ */
+ while (BufferHeader != NULL)
+ {
+ BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
+ BufferHeader->b_reqnext = NULL;
+ DAC960_ProcessCompletedBuffer(BufferHeader, false);
+ BufferHeader = NextBufferHeader;
+ }
+ /*
+ Wake up requestor for swap file paging requests.
+ */
+ if (Command->Semaphore != NULL)
+ {
+ up(Command->Semaphore);
+ Command->Semaphore = NULL;
+ }
+ }
+ }
+ else if (CommandType == DAC960_ReadRetryCommand ||
+ CommandType == DAC960_WriteRetryCommand)
+ {
+ BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
+ BufferHeader->b_reqnext = NULL;
+ /*
+ Perform completion processing for this single buffer.
+ */
+ if (CommandStatus == DAC960_NormalCompletion)
+ DAC960_ProcessCompletedBuffer(BufferHeader, true);
+ else
+ {
+ if (CommandStatus != DAC960_LogicalDriveNonexistentOrOffline)
+ DAC960_ReadWriteError(Command);
+ DAC960_ProcessCompletedBuffer(BufferHeader, false);
+ }
+ if (NextBufferHeader != NULL)
+ {
+ DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+ Command->BlockNumber +=
+ BufferHeader->b_size >> DAC960_BlockSizeBits;
+ Command->BlockCount =
+ NextBufferHeader->b_size >> DAC960_BlockSizeBits;
+ Command->BufferHeader = NextBufferHeader;
+ CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
+ CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
+ CommandMailbox->Type5.BusAddress =
+ Virtual_to_Bus(NextBufferHeader->b_data);
+ DAC960_QueueCommand(Command);
+ return;
+ }
+ }
+ else if (CommandType == DAC960_MonitoringCommand ||
+ CommandOpcode == DAC960_Enquiry ||
+ CommandOpcode == DAC960_GetRebuildProgress)
+ {
+ if (CommandType != DAC960_MonitoringCommand)
+ {
+ if (CommandOpcode == DAC960_Enquiry)
+ memcpy(&Controller->Enquiry[Controller->EnquiryIndex ^ 1],
+ Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress),
+ sizeof(DAC960_Enquiry_T));
+ else if (CommandOpcode == DAC960_GetRebuildProgress)
+ memcpy(&Controller->RebuildProgress,
+ Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress),
+ sizeof(DAC960_RebuildProgress_T));
+ }
+ if (CommandOpcode == DAC960_Enquiry)
+ {
+ DAC960_Enquiry_T *OldEnquiry =
+ &Controller->Enquiry[Controller->EnquiryIndex];
+ DAC960_Enquiry_T *NewEnquiry =
+ &Controller->Enquiry[Controller->EnquiryIndex ^= 1];
+ unsigned int OldCriticalLogicalDriveCount =
+ OldEnquiry->CriticalLogicalDriveCount;
+ unsigned int NewCriticalLogicalDriveCount =
+ NewEnquiry->CriticalLogicalDriveCount;
+ if (NewEnquiry->StatusFlags.DeferredWriteError !=
+ OldEnquiry->StatusFlags.DeferredWriteError)
+ DAC960_Critical("Deferred Write Error Flag is now %s\n", Controller,
+ (NewEnquiry->StatusFlags.DeferredWriteError
+ ? "TRUE" : "FALSE"));
+ if ((NewCriticalLogicalDriveCount > 0 ||
+ NewCriticalLogicalDriveCount != OldCriticalLogicalDriveCount) ||
+ (NewEnquiry->OfflineLogicalDriveCount > 0 ||
+ NewEnquiry->OfflineLogicalDriveCount !=
+ OldEnquiry->OfflineLogicalDriveCount) ||
+ (NewEnquiry->DeadDriveCount > 0 ||
+ NewEnquiry->DeadDriveCount !=
+ OldEnquiry->DeadDriveCount) ||
+ (NewEnquiry->EventLogSequenceNumber !=
+ OldEnquiry->EventLogSequenceNumber) ||
+ Controller->MonitoringTimerCount == 0 ||
+ (jiffies - Controller->SecondaryMonitoringTime
+ >= DAC960_SecondaryMonitoringInterval))
+ {
+ Controller->NeedLogicalDriveInformation = true;
+ Controller->NewEventLogSequenceNumber =
+ NewEnquiry->EventLogSequenceNumber;
+ Controller->NeedErrorTableInformation = true;
+ Controller->NeedDeviceStateInformation = true;
+ Controller->DeviceStateChannel = 0;
+ Controller->DeviceStateTargetID = -1;
+ Controller->SecondaryMonitoringTime = jiffies;
+ }
+ if (NewEnquiry->RebuildFlag == DAC960_StandbyRebuildInProgress ||
+ NewEnquiry->RebuildFlag == DAC960_BackgroundRebuildInProgress ||
+ OldEnquiry->RebuildFlag == DAC960_StandbyRebuildInProgress ||
+ OldEnquiry->RebuildFlag == DAC960_BackgroundRebuildInProgress)
+ Controller->NeedRebuildProgress = true;
+ if (OldEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress)
+ switch (NewEnquiry->RebuildFlag)
+ {
+ case DAC960_NoStandbyRebuildOrCheckInProgress:
+ DAC960_Progress("Consistency Check Completed Successfully\n",
+ Controller);
+ break;
+ case DAC960_StandbyRebuildInProgress:
+ case DAC960_BackgroundRebuildInProgress:
+ break;
+ case DAC960_BackgroundCheckInProgress:
+ Controller->NeedConsistencyCheckProgress = true;
+ break;
+ case DAC960_StandbyRebuildCompletedWithError:
+ DAC960_Progress("Consistency Check Completed with Error\n",
+ Controller);
+ break;
+ case DAC960_BackgroundRebuildOrCheckFailed_DriveFailed:
+ DAC960_Progress("Consistency Check Failed - "
+ "Physical Drive Failed\n", Controller);
+ break;
+ case DAC960_BackgroundRebuildOrCheckFailed_LogicalDriveFailed:
+ DAC960_Progress("Consistency Check Failed - "
+ "Logical Drive Failed\n", Controller);
+ break;
+ case DAC960_BackgroundRebuildOrCheckFailed_OtherCauses:
+ DAC960_Progress("Consistency Check Failed - Other Causes\n",
+ Controller);
+ break;
+ case DAC960_BackgroundRebuildOrCheckSuccessfullyTerminated:
+ DAC960_Progress("Consistency Check Successfully Terminated\n",
+ Controller);
+ break;
+ }
+ else if (NewEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress)
+ Controller->NeedConsistencyCheckProgress = true;
+ }
+ else if (CommandOpcode == DAC960_PerformEventLogOperation)
+ {
+ static char
+ *DAC960_EventMessages[] =
+ { "killed because write recovery failed",
+ "killed because of SCSI bus reset failure",
+ "killed because of double check condition",
+ "killed because it was removed",
+ "killed because of gross error on SCSI chip",
+ "killed because of bad tag returned from drive",
+ "killed because of timeout on SCSI command",
+ "killed because of reset SCSI command issued from system",
+ "killed because busy or parity error count exceeded limit",
+ "killed because of 'kill drive' command from system",
+ "killed because of selection timeout",
+ "killed due to SCSI phase sequence error",
+ "killed due to unknown status" };
+ DAC960_EventLogEntry_T *EventLogEntry = &Controller->EventLogEntry;
+ if (EventLogEntry->SequenceNumber ==
+ Controller->OldEventLogSequenceNumber)
+ {
+ unsigned char SenseKey = EventLogEntry->SenseKey;
+ unsigned char AdditionalSenseCode =
+ EventLogEntry->AdditionalSenseCode;
+ unsigned char AdditionalSenseCodeQualifier =
+ EventLogEntry->AdditionalSenseCodeQualifier;
+ if (SenseKey == 9 &&
+ AdditionalSenseCode == 0x80 &&
+ AdditionalSenseCodeQualifier <
+ sizeof(DAC960_EventMessages) / sizeof(char *))
+ DAC960_Critical("Physical Drive %d:%d %s\n", Controller,
+ EventLogEntry->Channel,
+ EventLogEntry->TargetID,
+ DAC960_EventMessages[
+ AdditionalSenseCodeQualifier]);
+ else if (SenseKey == 6 && AdditionalSenseCode == 0x29)
+ {
+ if (Controller->MonitoringTimerCount > 0)
+ Controller->DeviceResetCount[EventLogEntry->Channel]
+ [EventLogEntry->TargetID]++;
+ }
+ else if (!(SenseKey == 0 ||
+ (SenseKey == 2 &&
+ AdditionalSenseCode == 0x04 &&
+ (AdditionalSenseCodeQualifier == 0x01 ||
+ AdditionalSenseCodeQualifier == 0x02))))
+ {
+ DAC960_Critical("Physical Drive %d:%d Error Log: "
+ "Sense Key = %d, ASC = %02X, ASCQ = %02X\n",
+ Controller,
+ EventLogEntry->Channel,
+ EventLogEntry->TargetID,
+ SenseKey,
+ AdditionalSenseCode,
+ AdditionalSenseCodeQualifier);
+ DAC960_Critical("Physical Drive %d:%d Error Log: "
+ "Information = %02X%02X%02X%02X "
+ "%02X%02X%02X%02X\n",
+ Controller,
+ EventLogEntry->Channel,
+ EventLogEntry->TargetID,
+ EventLogEntry->Information[0],
+ EventLogEntry->Information[1],
+ EventLogEntry->Information[2],
+ EventLogEntry->Information[3],
+ EventLogEntry->CommandSpecificInformation[0],
+ EventLogEntry->CommandSpecificInformation[1],
+ EventLogEntry->CommandSpecificInformation[2],
+ EventLogEntry->CommandSpecificInformation[3]);
+ }
+ }
+ Controller->OldEventLogSequenceNumber++;
+ }
+ else if (CommandOpcode == DAC960_GetErrorTable)
+ {
+ DAC960_ErrorTable_T *OldErrorTable =
+ &Controller->ErrorTable[Controller->ErrorTableIndex];
+ DAC960_ErrorTable_T *NewErrorTable =
+ &Controller->ErrorTable[Controller->ErrorTableIndex ^= 1];
+ int Channel, TargetID;
+ for (Channel = 0; Channel < Controller->Channels; Channel++)
+ for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++)
+ {
+ DAC960_ErrorTableEntry_T *NewErrorEntry =
+ &NewErrorTable->ErrorTableEntries[Channel][TargetID];
+ DAC960_ErrorTableEntry_T *OldErrorEntry =
+ &OldErrorTable->ErrorTableEntries[Channel][TargetID];
+ if ((NewErrorEntry->ParityErrorCount !=
+ OldErrorEntry->ParityErrorCount) ||
+ (NewErrorEntry->SoftErrorCount !=
+ OldErrorEntry->SoftErrorCount) ||
+ (NewErrorEntry->HardErrorCount !=
+ OldErrorEntry->HardErrorCount) ||
+ (NewErrorEntry->MiscErrorCount !=
+ OldErrorEntry->MiscErrorCount))
+ DAC960_Critical("Physical Drive %d:%d Errors: "
+ "Parity = %d, Soft = %d, "
+ "Hard = %d, Misc = %d\n",
+ Controller, Channel, TargetID,
+ NewErrorEntry->ParityErrorCount,
+ NewErrorEntry->SoftErrorCount,
+ NewErrorEntry->HardErrorCount,
+ NewErrorEntry->MiscErrorCount);
+ }
+ }
+ else if (CommandOpcode == DAC960_GetDeviceState)
+ {
+ DAC960_DeviceState_T *OldDeviceState =
+ &Controller->DeviceState[Controller->DeviceStateIndex]
+ [Controller->DeviceStateChannel]
+ [Controller->DeviceStateTargetID];
+ DAC960_DeviceState_T *NewDeviceState =
+ &Controller->DeviceState[Controller->DeviceStateIndex ^ 1]
+ [Controller->DeviceStateChannel]
+ [Controller->DeviceStateTargetID];
+ if (NewDeviceState->DeviceState != OldDeviceState->DeviceState)
+ DAC960_Critical("Physical Drive %d:%d is now %s\n", Controller,
+ Controller->DeviceStateChannel,
+ Controller->DeviceStateTargetID,
+ (NewDeviceState->DeviceState == DAC960_Device_Dead
+ ? "DEAD"
+ : NewDeviceState->DeviceState
+ == DAC960_Device_WriteOnly
+ ? "WRITE-ONLY"
+ : NewDeviceState->DeviceState
+ == DAC960_Device_Online
+ ? "ONLINE" : "STANDBY"));
+ if (OldDeviceState->DeviceState == DAC960_Device_Dead &&
+ NewDeviceState->DeviceState != DAC960_Device_Dead)
+ {
+ Controller->NeedDeviceInquiryInformation = true;
+ Controller->NeedDeviceSerialNumberInformation = true;
+ }
+ }
+ else if (CommandOpcode == DAC960_GetLogicalDriveInformation)
+ {
+ int LogicalDriveNumber;
+ for (LogicalDriveNumber = 0;
+ LogicalDriveNumber < Controller->LogicalDriveCount;
+ LogicalDriveNumber++)
+ {
+ DAC960_LogicalDriveInformation_T *OldLogicalDriveInformation =
+ &Controller->LogicalDriveInformation
+ [Controller->LogicalDriveInformationIndex]
+ [LogicalDriveNumber];
+ DAC960_LogicalDriveInformation_T *NewLogicalDriveInformation =
+ &Controller->LogicalDriveInformation
+ [Controller->LogicalDriveInformationIndex ^ 1]
+ [LogicalDriveNumber];
+ if (NewLogicalDriveInformation->LogicalDriveState !=
+ OldLogicalDriveInformation->LogicalDriveState)
+ DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
+ "is now %s\n", Controller,
+ LogicalDriveNumber,
+ Controller->ControllerNumber,
+ LogicalDriveNumber,
+ (NewLogicalDriveInformation->LogicalDriveState
+ == DAC960_LogicalDrive_Online
+ ? "ONLINE"
+ : NewLogicalDriveInformation->LogicalDriveState
+ == DAC960_LogicalDrive_Critical
+ ? "CRITICAL" : "OFFLINE"));
+ if (NewLogicalDriveInformation->WriteBack !=
+ OldLogicalDriveInformation->WriteBack)
+ DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
+ "is now %s\n", Controller,
+ LogicalDriveNumber,
+ Controller->ControllerNumber,
+ LogicalDriveNumber,
+ (NewLogicalDriveInformation->WriteBack
+ ? "WRITE BACK" : "WRITE THRU"));
+ }
+ Controller->LogicalDriveInformationIndex ^= 1;
+ }
+ else if (CommandOpcode == DAC960_GetRebuildProgress)
+ {
+ unsigned int LogicalDriveNumber =
+ Controller->RebuildProgress.LogicalDriveNumber;
+ unsigned int LogicalDriveSize =
+ Controller->RebuildProgress.LogicalDriveSize;
+ unsigned int BlocksCompleted =
+ LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks;
+ switch (CommandStatus)
+ {
+ case DAC960_NormalCompletion:
+ Controller->EphemeralProgressMessage = true;
+ DAC960_Progress("Rebuild in Progress: "
+ "Logical Drive %d (/dev/rd/c%dd%d) "
+ "%d%% completed\n",
+ Controller, LogicalDriveNumber,
+ Controller->ControllerNumber,
+ LogicalDriveNumber,
+ (100 * (BlocksCompleted >> 7))
+ / (LogicalDriveSize >> 7));
+ Controller->EphemeralProgressMessage = false;
+ break;
+ case DAC960_RebuildFailed_LogicalDriveFailure:
+ DAC960_Progress("Rebuild Failed due to "
+ "Logical Drive Failure\n", Controller);
+ break;
+ case DAC960_RebuildFailed_BadBlocksOnOther:
+ DAC960_Progress("Rebuild Failed due to "
+ "Bad Blocks on Other Drives\n", Controller);
+ break;
+ case DAC960_RebuildFailed_NewDriveFailed:
+ DAC960_Progress("Rebuild Failed due to "
+ "Failure of Drive Being Rebuilt\n", Controller);
+ break;
+ case DAC960_NoRebuildOrCheckInProgress:
+ if (Controller->LastRebuildStatus != DAC960_NormalCompletion)
+ break;
+ case DAC960_RebuildSuccessful:
+ DAC960_Progress("Rebuild Completed Successfully\n", Controller);
+ break;
+ }
+ Controller->LastRebuildStatus = CommandStatus;
+ }
+ else if (CommandOpcode == DAC960_RebuildStat)
+ {
+ unsigned int LogicalDriveNumber =
+ Controller->RebuildProgress.LogicalDriveNumber;
+ unsigned int LogicalDriveSize =
+ Controller->RebuildProgress.LogicalDriveSize;
+ unsigned int BlocksCompleted =
+ LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks;
+ if (CommandStatus == DAC960_NormalCompletion)
+ {
+ Controller->EphemeralProgressMessage = true;
+ DAC960_Progress("Consistency Check in Progress: "
+ "Logical Drive %d (/dev/rd/c%dd%d) "
+ "%d%% completed\n",
+ Controller, LogicalDriveNumber,
+ Controller->ControllerNumber,
+ LogicalDriveNumber,
+ (100 * (BlocksCompleted >> 7))
+ / (LogicalDriveSize >> 7));
+ Controller->EphemeralProgressMessage = false;
+ }
+ }
+ }
+ if (CommandType == DAC960_MonitoringCommand)
+ {
+ if (Controller->NewEventLogSequenceNumber
+ - Controller->OldEventLogSequenceNumber > 0)
+ {
+ Command->CommandMailbox.Type3E.CommandOpcode =
+ DAC960_PerformEventLogOperation;
+ Command->CommandMailbox.Type3E.OperationType =
+ DAC960_GetEventLogEntry;
+ Command->CommandMailbox.Type3E.OperationQualifier = 1;
+ Command->CommandMailbox.Type3E.SequenceNumber =
+ Controller->OldEventLogSequenceNumber;
+ Command->CommandMailbox.Type3E.BusAddress =
+ Virtual_to_Bus(&Controller->EventLogEntry);
+ DAC960_QueueCommand(Command);
+ return;
+ }
+ if (Controller->NeedErrorTableInformation)
+ {
+ Controller->NeedErrorTableInformation = false;
+ Command->CommandMailbox.Type3.CommandOpcode = DAC960_GetErrorTable;
+ Command->CommandMailbox.Type3.BusAddress =
+ Virtual_to_Bus(
+ &Controller->ErrorTable[Controller->ErrorTableIndex ^ 1]);
+ DAC960_QueueCommand(Command);
+ return;
+ }
+ if (Controller->NeedRebuildProgress &&
+ Controller->Enquiry[Controller->EnquiryIndex]
+ .CriticalLogicalDriveCount <
+ Controller->Enquiry[Controller->EnquiryIndex ^ 1]
+ .CriticalLogicalDriveCount)
+ {
+ Controller->NeedRebuildProgress = false;
+ Command->CommandMailbox.Type3.CommandOpcode =
+ DAC960_GetRebuildProgress;
+ Command->CommandMailbox.Type3.BusAddress =
+ Virtual_to_Bus(&Controller->RebuildProgress);
+ DAC960_QueueCommand(Command);
+ return;
+ }
+ if (Controller->NeedDeviceStateInformation)
+ {
+ if (Controller->NeedDeviceInquiryInformation)
+ {
+ DAC960_DCDB_T *DCDB = &Controller->MonitoringDCDB;
+ DAC960_SCSI_Inquiry_T *InquiryStandardData =
+ &Controller->InquiryStandardData
+ [Controller->DeviceStateChannel]
+ [Controller->DeviceStateTargetID];
+ InquiryStandardData->PeripheralDeviceType = 0x1F;
+ Command->CommandMailbox.Type3.CommandOpcode = DAC960_DCDB;
+ Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB);
+ DCDB->Channel = Controller->DeviceStateChannel;
+ DCDB->TargetID = Controller->DeviceStateTargetID;
+ DCDB->Direction = DAC960_DCDB_DataTransferDeviceToSystem;
+ DCDB->EarlyStatus = false;
+ DCDB->Timeout = DAC960_DCDB_Timeout_10_seconds;
+ DCDB->NoAutomaticRequestSense = false;
+ DCDB->DisconnectPermitted = true;
+ DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T);
+ DCDB->BusAddress = Virtual_to_Bus(InquiryStandardData);
+ DCDB->CDBLength = 6;
+ DCDB->TransferLengthHigh4 = 0;
+ DCDB->SenseLength = sizeof(DCDB->SenseData);
+ DCDB->CDB[0] = 0x12; /* INQUIRY */
+ DCDB->CDB[1] = 0; /* EVPD = 0 */
+ DCDB->CDB[2] = 0; /* Page Code */
+ DCDB->CDB[3] = 0; /* Reserved */
+ DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_T);
+ DCDB->CDB[5] = 0; /* Control */
+ DAC960_QueueCommand(Command);
+ Controller->NeedDeviceInquiryInformation = false;
+ return;
+ }
+ if (Controller->NeedDeviceSerialNumberInformation)
+ {
+ DAC960_DCDB_T *DCDB = &Controller->MonitoringDCDB;
+ DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber =
+ &Controller->InquiryUnitSerialNumber
+ [Controller->DeviceStateChannel]
+ [Controller->DeviceStateTargetID];
+ InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
+ Command->CommandMailbox.Type3.CommandOpcode = DAC960_DCDB;
+ Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB);
+ DCDB->Channel = Controller->DeviceStateChannel;
+ DCDB->TargetID = Controller->DeviceStateTargetID;
+ DCDB->Direction = DAC960_DCDB_DataTransferDeviceToSystem;
+ DCDB->EarlyStatus = false;
+ DCDB->Timeout = DAC960_DCDB_Timeout_10_seconds;
+ DCDB->NoAutomaticRequestSense = false;
+ DCDB->DisconnectPermitted = true;
+ DCDB->TransferLength =
+ sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
+ DCDB->BusAddress = Virtual_to_Bus(InquiryUnitSerialNumber);
+ DCDB->CDBLength = 6;
+ DCDB->TransferLengthHigh4 = 0;
+ DCDB->SenseLength = sizeof(DCDB->SenseData);
+ DCDB->CDB[0] = 0x12; /* INQUIRY */
+ DCDB->CDB[1] = 1; /* EVPD = 1 */
+ DCDB->CDB[2] = 0x80; /* Page Code */
+ DCDB->CDB[3] = 0; /* Reserved */
+ DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
+ DCDB->CDB[5] = 0; /* Control */
+ DAC960_QueueCommand(Command);
+ Controller->NeedDeviceSerialNumberInformation = false;
+ return;
+ }
+ if (++Controller->DeviceStateTargetID == DAC960_MaxTargets)
+ {
+ Controller->DeviceStateChannel++;
+ Controller->DeviceStateTargetID = 0;
+ }
+ while (Controller->DeviceStateChannel < Controller->Channels)
+ {
+ DAC960_DeviceState_T *OldDeviceState =
+ &Controller->DeviceState[Controller->DeviceStateIndex]
+ [Controller->DeviceStateChannel]
+ [Controller->DeviceStateTargetID];
+ if (OldDeviceState->Present &&
+ OldDeviceState->DeviceType == DAC960_DiskType)
+ {
+ Command->CommandMailbox.Type3D.CommandOpcode =
+ DAC960_GetDeviceState;
+ Command->CommandMailbox.Type3D.Channel =
+ Controller->DeviceStateChannel;
+ Command->CommandMailbox.Type3D.TargetID =
+ Controller->DeviceStateTargetID;
+ Command->CommandMailbox.Type3D.BusAddress =
+ Virtual_to_Bus(&Controller->DeviceState
+ [Controller->DeviceStateIndex ^ 1]
+ [Controller->DeviceStateChannel]
+ [Controller->DeviceStateTargetID]);
+ DAC960_QueueCommand(Command);
+ return;
+ }
+ if (++Controller->DeviceStateTargetID == DAC960_MaxTargets)
+ {
+ Controller->DeviceStateChannel++;
+ Controller->DeviceStateTargetID = 0;
+ }
+ }
+ Controller->NeedDeviceStateInformation = false;
+ Controller->DeviceStateIndex ^= 1;
+ }
+ if (Controller->NeedLogicalDriveInformation)
+ {
+ Controller->NeedLogicalDriveInformation = false;
+ Command->CommandMailbox.Type3.CommandOpcode =
+ DAC960_GetLogicalDriveInformation;
+ Command->CommandMailbox.Type3.BusAddress =
+ Virtual_to_Bus(
+ &Controller->LogicalDriveInformation
+ [Controller->LogicalDriveInformationIndex ^ 1]);
+ DAC960_QueueCommand(Command);
+ return;
+ }
+ if (Controller->NeedRebuildProgress)
+ {
+ Controller->NeedRebuildProgress = false;
+ Command->CommandMailbox.Type3.CommandOpcode =
+ DAC960_GetRebuildProgress;
+ Command->CommandMailbox.Type3.BusAddress =
+ Virtual_to_Bus(&Controller->RebuildProgress);
+ DAC960_QueueCommand(Command);
+ return;
+ }
+ if (Controller->NeedConsistencyCheckProgress)
+ {
+ Controller->NeedConsistencyCheckProgress = false;
+ Command->CommandMailbox.Type3.CommandOpcode = DAC960_RebuildStat;
+ Command->CommandMailbox.Type3.BusAddress =
+ Virtual_to_Bus(&Controller->RebuildProgress);
+ DAC960_QueueCommand(Command);
+ return;
+ }
+ Controller->MonitoringTimerCount++;
+ Controller->MonitoringTimer.expires =
+ jiffies + DAC960_MonitoringTimerInterval;
+ add_timer(&Controller->MonitoringTimer);
+ }
+ if (CommandType == DAC960_ImmediateCommand)
+ {
+ up(Command->Semaphore);
+ Command->Semaphore = NULL;
+ return;
+ }
+ if (CommandType == DAC960_QueuedCommand)
+ {
+ DAC960_KernelCommand_T *KernelCommand = Command->KernelCommand;
+ KernelCommand->CommandStatus = CommandStatus;
+ Command->KernelCommand = NULL;
+ if (CommandOpcode == DAC960_DCDB)
+ Controller->DirectCommandActive[KernelCommand->DCDB->Channel]
+ [KernelCommand->DCDB->TargetID] = false;
+ DAC960_DeallocateCommand(Command);
+ KernelCommand->CompletionFunction(KernelCommand);
+ return;
+ }
+ /*
+ Queue a Status Monitoring Command to the Controller using the just
+ completed Command if one was deferred previously due to lack of a
+ free Command when the Monitoring Timer Function was called.
+ */
+ if (Controller->MonitoringCommandDeferred)
+ {
+ Controller->MonitoringCommandDeferred = false;
+ DAC960_QueueMonitoringCommand(Command);
+ return;
+ }
+ /*
+ Deallocate the Command, and wake up any processes waiting on a free Command.
+ */
+ DAC960_DeallocateCommand(Command);
+ wake_up(&Controller->CommandWaitQueue);
+}
+
+
+/*
+ DAC960_InterruptHandler handles hardware interrupts from DAC960 Controllers.
+*/
+
+static void DAC960_InterruptHandler(int IRQ_Channel,
+ void *DeviceIdentifier,
+ Registers_T *InterruptRegisters)
+{
+ DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+ void *ControllerBaseAddress = Controller->BaseAddress;
+ DAC960_StatusMailbox_T *NextStatusMailbox;
+ ProcessorFlags_T ProcessorFlags;
+ /*
+ Acquire exclusive access to Controller.
+ */
+ DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags);
+ /*
+ Process Hardware Interrupts for Controller.
+ */
+ switch (Controller->ControllerType)
+ {
+ case DAC960_V5_Controller:
+ DAC960_V5_AcknowledgeInterrupt(ControllerBaseAddress);
+ NextStatusMailbox = Controller->NextStatusMailbox;
+ while (NextStatusMailbox->Fields.Valid)
+ {
+ DAC960_CommandIdentifier_T CommandIdentifier =
+ NextStatusMailbox->Fields.CommandIdentifier;
+ DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier];
+ Command->CommandStatus = NextStatusMailbox->Fields.CommandStatus;
+ NextStatusMailbox->Word = 0;
+ if (++NextStatusMailbox > Controller->LastStatusMailbox)
+ NextStatusMailbox = Controller->FirstStatusMailbox;
+ DAC960_ProcessCompletedCommand(Command);
+ }
+ Controller->NextStatusMailbox = NextStatusMailbox;
+ break;
+ case DAC960_V4_Controller:
+ DAC960_V4_AcknowledgeInterrupt(ControllerBaseAddress);
+ NextStatusMailbox = Controller->NextStatusMailbox;
+ while (NextStatusMailbox->Fields.Valid)
+ {
+ DAC960_CommandIdentifier_T CommandIdentifier =
+ NextStatusMailbox->Fields.CommandIdentifier;
+ DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier];
+ Command->CommandStatus = NextStatusMailbox->Fields.CommandStatus;
+ NextStatusMailbox->Word = 0;
+ if (++NextStatusMailbox > Controller->LastStatusMailbox)
+ NextStatusMailbox = Controller->FirstStatusMailbox;
+ DAC960_ProcessCompletedCommand(Command);
+ }
+ Controller->NextStatusMailbox = NextStatusMailbox;
+ break;
+ case DAC960_V3_Controller:
+ while (DAC960_V3_StatusAvailableP(ControllerBaseAddress))
+ {
+ DAC960_CommandIdentifier_T CommandIdentifier =
+ DAC960_V3_ReadStatusCommandIdentifier(ControllerBaseAddress);
+ DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier];
+ Command->CommandStatus =
+ DAC960_V3_ReadStatusRegister(ControllerBaseAddress);
+ DAC960_V3_AcknowledgeInterrupt(ControllerBaseAddress);
+ DAC960_V3_AcknowledgeStatus(ControllerBaseAddress);
+ DAC960_ProcessCompletedCommand(Command);
+ }
+ break;
+ }
+ /*
+ Attempt to remove additional I/O Requests from the Controller's
+ I/O Request Queue and queue them to the Controller.
+ */
+ while (DAC960_ProcessRequest(Controller, false)) ;
+ /*
+ Release exclusive access to Controller.
+ */
+ DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags);
+}
+
+
+/*
+ DAC960_QueueMonitoringCommand queues a Monitoring Command to Controller.
+*/
+
+static void DAC960_QueueMonitoringCommand(DAC960_Command_T *Command)
+{
+ DAC960_Controller_T *Controller = Command->Controller;
+ DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+ DAC960_ClearCommand(Command);
+ Command->CommandType = DAC960_MonitoringCommand;
+ CommandMailbox->Type3.CommandOpcode = DAC960_Enquiry;
+ CommandMailbox->Type3.BusAddress =
+ Virtual_to_Bus(&Controller->Enquiry[Controller->EnquiryIndex ^ 1]);
+ DAC960_QueueCommand(Command);
+}
+
+
+/*
+ DAC960_MonitoringTimerFunction is the timer function for monitoring
+ the status of DAC960 Controllers.
+*/
+
+static void DAC960_MonitoringTimerFunction(unsigned long TimerData)
+{
+ DAC960_Controller_T *Controller = (DAC960_Controller_T *) TimerData;
+ DAC960_Command_T *Command;
+ ProcessorFlags_T ProcessorFlags;
+ /*
+ Acquire exclusive access to Controller.
+ */
+ DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+ /*
+ Queue a Status Monitoring Command to Controller.
+ */
+ Command = DAC960_AllocateCommand(Controller);
+ if (Command != NULL)
+ DAC960_QueueMonitoringCommand(Command);
+ else Controller->MonitoringCommandDeferred = true;
+ /*
+ Release exclusive access to Controller.
+ */
+ DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+}
+
+
+/*
+ DAC960_Open is the Device Open Function for the DAC960 Driver.
+*/
+
+static int DAC960_Open(Inode_T *Inode, File_T *File)
+{
+ int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev);
+ int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev);
+ DAC960_Controller_T *Controller;
+ if (ControllerNumber == 0 && LogicalDriveNumber == 0 &&
+ (File->f_flags & O_NONBLOCK))
+ goto ModuleOnly;
+ if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1)
+ return -ENXIO;
+ Controller = DAC960_Controllers[ControllerNumber];
+ if (Controller == NULL ||
+ LogicalDriveNumber > Controller->LogicalDriveCount - 1)
+ return -ENXIO;
+ if (Controller->LogicalDriveInformation
+ [Controller->LogicalDriveInformationIndex]
+ [LogicalDriveNumber].LogicalDriveState
+ == DAC960_LogicalDrive_Offline)
+ return -ENXIO;
+ if (Controller->LogicalDriveInitialState[LogicalDriveNumber]
+ == DAC960_LogicalDrive_Offline)
+ {
+ Controller->LogicalDriveInitialState[LogicalDriveNumber] =
+ DAC960_LogicalDrive_Online;
+ DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo);
+ resetup_one_dev(&Controller->GenericDiskInfo, LogicalDriveNumber);
+ }
+ if (Controller->GenericDiskInfo.sizes[MINOR(Inode->i_rdev)] == 0)
+ return -ENXIO;
+ /*
+ Increment Controller and Logical Drive Usage Counts.
+ */
+ Controller->ControllerUsageCount++;
+ Controller->LogicalDriveUsageCount[LogicalDriveNumber]++;
+ ModuleOnly:
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+
+/*
+ DAC960_Release is the Device Release Function for the DAC960 Driver.
+*/
+
+static int DAC960_Release(Inode_T *Inode, File_T *File)
+{
+ int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev);
+ int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev);
+ DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
+ if (ControllerNumber == 0 && LogicalDriveNumber == 0 &&
+ File != NULL && (File->f_flags & O_NONBLOCK))
+ goto ModuleOnly;
+ /*
+ Force any buffered data to be written.
+ */
+ fsync_dev(Inode->i_rdev);
+ /*
+ Decrement the Logical Drive and Controller Usage Counts.
+ */
+ Controller->LogicalDriveUsageCount[LogicalDriveNumber]--;
+ Controller->ControllerUsageCount--;
+ ModuleOnly:
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+
+/*
+ DAC960_IOCTL is the Device IOCTL Function for the DAC960 Driver.
+*/
+
+static int DAC960_IOCTL(Inode_T *Inode, File_T *File,
+ unsigned int Request, unsigned long Argument)
+{
+ int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev);
+ int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev);
+ DiskGeometry_T Geometry, *UserGeometry;
+ DAC960_Controller_T *Controller;
+ int PartitionNumber;
+ if (File->f_flags & O_NONBLOCK)
+ return DAC960_UserIOCTL(Inode, File, Request, Argument);
+ if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1)
+ return -ENXIO;
+ Controller = DAC960_Controllers[ControllerNumber];
+ if (Controller == NULL ||
+ LogicalDriveNumber > Controller->LogicalDriveCount - 1)
+ return -ENXIO;
+ switch (Request)
+ {
+ case HDIO_GETGEO:
+ /* Get BIOS Disk Geometry. */
+ UserGeometry = (DiskGeometry_T *) Argument;
+ if (UserGeometry == NULL) return -EINVAL;
+ Geometry.heads = Controller->GeometryTranslationHeads;
+ Geometry.sectors = Controller->GeometryTranslationSectors;
+ Geometry.cylinders =
+ Controller->LogicalDriveInformation
+ [Controller->LogicalDriveInformationIndex]
+ [LogicalDriveNumber].LogicalDriveSize
+ / (Controller->GeometryTranslationHeads *
+ Controller->GeometryTranslationSectors);
+ Geometry.start = Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)]
+ .start_sect;
+ return copy_to_user(UserGeometry, &Geometry, sizeof(DiskGeometry_T));
+ case BLKGETSIZE:
+ /* Get Device Size. */
+ if ((long *) Argument == NULL) return -EINVAL;
+ return put_user(Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)]
+ .nr_sects,
+ (long *) Argument);
+ case BLKRAGET:
+ /* Get Read-Ahead. */
+ if ((int *) Argument == NULL) return -EINVAL;
+ return put_user(read_ahead[MAJOR(Inode->i_rdev)], (int *) Argument);
+ case BLKRASET:
+ /* Set Read-Ahead. */
+ if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+ if (Argument > 256) return -EINVAL;
+ read_ahead[MAJOR(Inode->i_rdev)] = Argument;
+ return 0;
+ case BLKFLSBUF:
+ /* Flush Buffers. */
+ if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+ fsync_dev(Inode->i_rdev);
+ invalidate_buffers(Inode->i_rdev);
+ return 0;
+ case BLKRRPART:
+ /* Re-Read Partition Table. */
+ if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+ if (Controller->LogicalDriveUsageCount[LogicalDriveNumber] > 1)
+ return -EBUSY;
+ for (PartitionNumber = 0;
+ PartitionNumber < DAC960_MaxPartitions;
+ PartitionNumber++)
+ {
+ KernelDevice_T Device = DAC960_KernelDevice(ControllerNumber,
+ LogicalDriveNumber,
+ PartitionNumber);
+ int MinorNumber = DAC960_MinorNumber(LogicalDriveNumber,
+ PartitionNumber);
+ SuperBlock_T *SuperBlock = get_super(Device);
+ if (Controller->GenericDiskInfo.part[MinorNumber].nr_sects == 0)
+ continue;
+ /*
+ Flush all changes and invalidate buffered state.
+ */
+ sync_dev(Device);
+ if (SuperBlock != NULL)
+ invalidate_inodes(SuperBlock);
+ invalidate_buffers(Device);
+ /*
+ Clear existing partition sizes.
+ */
+ if (PartitionNumber > 0)
+ {
+ Controller->GenericDiskInfo.part[MinorNumber].start_sect = 0;
+ Controller->GenericDiskInfo.part[MinorNumber].nr_sects = 0;
+ }
+ /*
+ Reset the Block Size so that the partition table can be read.
+ */
+ set_blocksize(Device, BLOCK_SIZE);
+ }
+ resetup_one_dev(&Controller->GenericDiskInfo, LogicalDriveNumber);
+ return 0;
+ }
+ return -EINVAL;
+}
+
+
+/*
+ DAC960_UserIOCTL is the User IOCTL Function for the DAC960 Driver.
+*/
+
+static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
+ unsigned int Request, unsigned long Argument)
+{
+ int ErrorCode;
+ if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+ switch (Request)
+ {
+ case DAC960_IOCTL_GET_CONTROLLER_COUNT:
+ return DAC960_ControllerCount;
+ case DAC960_IOCTL_GET_CONTROLLER_INFO:
+ {
+ DAC960_ControllerInfo_T *UserSpaceControllerInfo =
+ (DAC960_ControllerInfo_T *) Argument;
+ DAC960_ControllerInfo_T ControllerInfo;
+ DAC960_Controller_T *Controller;
+ int ControllerNumber;
+ if (UserSpaceControllerInfo == NULL) return -EINVAL;
+ ErrorCode = get_user(ControllerNumber,
+ &UserSpaceControllerInfo->ControllerNumber);
+ if (ErrorCode != 0) return ErrorCode;
+ if (ControllerNumber < 0 ||
+ ControllerNumber > DAC960_ControllerCount - 1)
+ return -ENXIO;
+ Controller = DAC960_Controllers[ControllerNumber];
+ if (Controller == NULL)
+ return -ENXIO;
+ memset(&ControllerInfo, 0, sizeof(DAC960_ControllerInfo_T));
+ ControllerInfo.ControllerNumber = ControllerNumber;
+ ControllerInfo.PCI_Bus = Controller->Bus;
+ ControllerInfo.PCI_Device = Controller->Device;
+ ControllerInfo.PCI_Function = Controller->Function;
+ ControllerInfo.IRQ_Channel = Controller->IRQ_Channel;
+ ControllerInfo.Channels = Controller->Channels;
+ ControllerInfo.PCI_Address = Controller->PCI_Address;
+ strcpy(ControllerInfo.ModelName, Controller->ModelName);
+ strcpy(ControllerInfo.FirmwareVersion, Controller->FirmwareVersion);
+ return copy_to_user(UserSpaceControllerInfo, &ControllerInfo,
+ sizeof(DAC960_ControllerInfo_T));
+ }
+ case DAC960_IOCTL_EXECUTE_COMMAND:
+ {
+ DAC960_UserCommand_T *UserSpaceUserCommand =
+ (DAC960_UserCommand_T *) Argument;
+ DAC960_UserCommand_T UserCommand;
+ DAC960_Controller_T *Controller;
+ DAC960_Command_T *Command = NULL;
+ DAC960_CommandOpcode_T CommandOpcode;
+ DAC960_CommandStatus_T CommandStatus;
+ DAC960_DCDB_T DCDB;
+ ProcessorFlags_T ProcessorFlags;
+ int ControllerNumber, DataTransferLength;
+ unsigned char *DataTransferBuffer = NULL;
+ if (UserSpaceUserCommand == NULL) return -EINVAL;
+ ErrorCode = copy_from_user(&UserCommand, UserSpaceUserCommand,
+ sizeof(DAC960_UserCommand_T));
+ if (ErrorCode != 0) goto Failure;
+ ControllerNumber = UserCommand.ControllerNumber;
+ if (ControllerNumber < 0 ||
+ ControllerNumber > DAC960_ControllerCount - 1)
+ return -ENXIO;
+ Controller = DAC960_Controllers[ControllerNumber];
+ if (Controller == NULL)
+ return -ENXIO;
+ CommandOpcode = UserCommand.CommandMailbox.Common.CommandOpcode;
+ DataTransferLength = UserCommand.DataTransferLength;
+ if (CommandOpcode & 0x80) return -EINVAL;
+ if (CommandOpcode == DAC960_DCDB)
+ {
+ ErrorCode =
+ copy_from_user(&DCDB, UserCommand.DCDB, sizeof(DAC960_DCDB_T));
+ if (ErrorCode != 0) goto Failure;
+ if (!((DataTransferLength == 0 &&
+ DCDB.Direction == DAC960_DCDB_NoDataTransfer) ||
+ (DataTransferLength > 0 &&
+ DCDB.Direction == DAC960_DCDB_DataTransferDeviceToSystem) ||
+ (DataTransferLength < 0 &&
+ DCDB.Direction == DAC960_DCDB_DataTransferSystemToDevice)))
+ return -EINVAL;
+ if (((DCDB.TransferLengthHigh4 << 16) | DCDB.TransferLength)
+ != abs(DataTransferLength))
+ return -EINVAL;
+ }
+ if (DataTransferLength > 0)
+ {
+ DataTransferBuffer = kmalloc(DataTransferLength, GFP_KERNEL);
+ if (DataTransferBuffer == NULL) return -ENOMEM;
+ memset(DataTransferBuffer, 0, DataTransferLength);
+ }
+ else if (DataTransferLength < 0)
+ {
+ DataTransferBuffer = kmalloc(-DataTransferLength, GFP_KERNEL);
+ if (DataTransferBuffer == NULL) return -ENOMEM;
+ ErrorCode = copy_from_user(DataTransferBuffer,
+ UserCommand.DataTransferBuffer,
+ -DataTransferLength);
+ if (ErrorCode != 0) goto Failure;
+ }
+ if (CommandOpcode == DAC960_DCDB)
+ {
+ while (true)
+ {
+ DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+ if (!Controller->DirectCommandActive[DCDB.Channel]
+ [DCDB.TargetID])
+ Command = DAC960_AllocateCommand(Controller);
+ if (Command != NULL)
+ Controller->DirectCommandActive[DCDB.Channel]
+ [DCDB.TargetID] = true;
+ DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+ if (Command != NULL) break;
+ sleep_on(&Controller->CommandWaitQueue);
+ }
+ DAC960_ClearCommand(Command);
+ Command->CommandType = DAC960_ImmediateCommand;
+ memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox,
+ sizeof(DAC960_CommandMailbox_T));
+ Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(&DCDB);
+ DCDB.BusAddress = Virtual_to_Bus(DataTransferBuffer);
+ }
+ else
+ {
+ while (true)
+ {
+ DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+ Command = DAC960_AllocateCommand(Controller);
+ DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+ if (Command != NULL) break;
+ sleep_on(&Controller->CommandWaitQueue);
+ }
+ DAC960_ClearCommand(Command);
+ Command->CommandType = DAC960_ImmediateCommand;
+ memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox,
+ sizeof(DAC960_CommandMailbox_T));
+ if (DataTransferBuffer != NULL)
+ Command->CommandMailbox.Type3.BusAddress =
+ Virtual_to_Bus(DataTransferBuffer);
+ }
+ DAC960_ExecuteCommand(Command);
+ CommandStatus = Command->CommandStatus;
+ DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+ DAC960_DeallocateCommand(Command);
+ DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+ if (CommandStatus == DAC960_NormalCompletion &&
+ DataTransferLength > 0)
+ {
+ ErrorCode = copy_to_user(UserCommand.DataTransferBuffer,
+ DataTransferBuffer, DataTransferLength);
+ if (ErrorCode != 0) goto Failure;
+ }
+ if (CommandOpcode == DAC960_DCDB)
+ {
+ Controller->DirectCommandActive[DCDB.Channel]
+ [DCDB.TargetID] = false;
+ ErrorCode =
+ copy_to_user(UserCommand.DCDB, &DCDB, sizeof(DAC960_DCDB_T));
+ if (ErrorCode != 0) goto Failure;
+ }
+ ErrorCode = CommandStatus;
+ Failure:
+ if (DataTransferBuffer != NULL)
+ kfree(DataTransferBuffer);
+ return ErrorCode;
+ }
+ }
+ return -EINVAL;
+}
+
+
+/*
+ DAC960_KernelIOCTL is the Kernel IOCTL Function for the DAC960 Driver.
+*/
+
+int DAC960_KernelIOCTL(unsigned int Request, void *Argument)
+{
+ switch (Request)
+ {
+ case DAC960_IOCTL_GET_CONTROLLER_COUNT:
+ return DAC960_ControllerCount;
+ case DAC960_IOCTL_GET_CONTROLLER_INFO:
+ {
+ DAC960_ControllerInfo_T *ControllerInfo =
+ (DAC960_ControllerInfo_T *) Argument;
+ DAC960_Controller_T *Controller;
+ int ControllerNumber;
+ if (ControllerInfo == NULL) return -EINVAL;
+ ControllerNumber = ControllerInfo->ControllerNumber;
+ if (ControllerNumber < 0 ||
+ ControllerNumber > DAC960_ControllerCount - 1)
+ return -ENXIO;
+ Controller = DAC960_Controllers[ControllerNumber];
+ if (Controller == NULL)
+ return -ENXIO;
+ memset(ControllerInfo, 0, sizeof(DAC960_ControllerInfo_T));
+ ControllerInfo->ControllerNumber = ControllerNumber;
+ ControllerInfo->PCI_Bus = Controller->Bus;
+ ControllerInfo->PCI_Device = Controller->Device;
+ ControllerInfo->PCI_Function = Controller->Function;
+ ControllerInfo->IRQ_Channel = Controller->IRQ_Channel;
+ ControllerInfo->Channels = Controller->Channels;
+ ControllerInfo->PCI_Address = Controller->PCI_Address;
+ strcpy(ControllerInfo->ModelName, Controller->ModelName);
+ strcpy(ControllerInfo->FirmwareVersion, Controller->FirmwareVersion);
+ return 0;
+ }
+ case DAC960_IOCTL_EXECUTE_COMMAND:
+ {
+ DAC960_KernelCommand_T *KernelCommand =
+ (DAC960_KernelCommand_T *) Argument;
+ DAC960_Controller_T *Controller;
+ DAC960_Command_T *Command = NULL;
+ DAC960_CommandOpcode_T CommandOpcode;
+ DAC960_DCDB_T *DCDB = NULL;
+ ProcessorFlags_T ProcessorFlags;
+ int ControllerNumber, DataTransferLength;
+ unsigned char *DataTransferBuffer = NULL;
+ if (KernelCommand == NULL) return -EINVAL;
+ ControllerNumber = KernelCommand->ControllerNumber;
+ if (ControllerNumber < 0 ||
+ ControllerNumber > DAC960_ControllerCount - 1)
+ return -ENXIO;
+ Controller = DAC960_Controllers[ControllerNumber];
+ if (Controller == NULL)
+ return -ENXIO;
+ CommandOpcode = KernelCommand->CommandMailbox.Common.CommandOpcode;
+ DataTransferLength = KernelCommand->DataTransferLength;
+ DataTransferBuffer = KernelCommand->DataTransferBuffer;
+ if (CommandOpcode & 0x80) return -EINVAL;
+ if (CommandOpcode == DAC960_DCDB)
+ {
+ DCDB = KernelCommand->DCDB;
+ if (!((DataTransferLength == 0 &&
+ DCDB->Direction == DAC960_DCDB_NoDataTransfer) ||
+ (DataTransferLength > 0 &&
+ DCDB->Direction == DAC960_DCDB_DataTransferDeviceToSystem) ||
+ (DataTransferLength < 0 &&
+ DCDB->Direction == DAC960_DCDB_DataTransferSystemToDevice)))
+ return -EINVAL;
+ if (((DCDB->TransferLengthHigh4 << 16) | DCDB->TransferLength)
+ != abs(DataTransferLength))
+ return -EINVAL;
+ }
+ if (DataTransferLength != 0 && DataTransferBuffer == NULL)
+ return -EINVAL;
+ if (DataTransferLength > 0)
+ memset(DataTransferBuffer, 0, DataTransferLength);
+ if (CommandOpcode == DAC960_DCDB)
+ {
+ DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+ if (!Controller->DirectCommandActive[DCDB->Channel]
+ [DCDB->TargetID])
+ Command = DAC960_AllocateCommand(Controller);
+ if (Command == NULL)
+ {
+ DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+ return -EBUSY;
+ }
+ else Controller->DirectCommandActive[DCDB->Channel]
+ [DCDB->TargetID] = true;
+ DAC960_ClearCommand(Command);
+ Command->CommandType = DAC960_QueuedCommand;
+ memcpy(&Command->CommandMailbox, &KernelCommand->CommandMailbox,
+ sizeof(DAC960_CommandMailbox_T));
+ Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB);
+ Command->KernelCommand = KernelCommand;
+ DCDB->BusAddress = Virtual_to_Bus(DataTransferBuffer);
+ DAC960_QueueCommand(Command);
+ DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+ }
+ else
+ {
+ DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+ Command = DAC960_AllocateCommand(Controller);
+ if (Command == NULL)
+ {
+ DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+ return -EBUSY;
+ }
+ DAC960_ClearCommand(Command);
+ Command->CommandType = DAC960_QueuedCommand;
+ memcpy(&Command->CommandMailbox, &KernelCommand->CommandMailbox,
+ sizeof(DAC960_CommandMailbox_T));
+ if (DataTransferBuffer != NULL)
+ Command->CommandMailbox.Type3.BusAddress =
+ Virtual_to_Bus(DataTransferBuffer);
+ Command->KernelCommand = KernelCommand;
+ DAC960_QueueCommand(Command);
+ DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+ }
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+
+/*
+ DAC960_GenericDiskInit is the Generic Disk Information Initialization
+ Function for the DAC960 Driver.
+*/
+
+static void DAC960_InitializeGenericDiskInfo(GenericDiskInfo_T *GenericDiskInfo)
+{
+ DAC960_Controller_T *Controller =
+ (DAC960_Controller_T *) GenericDiskInfo->real_devices;
+ DAC960_LogicalDriveInformation_T *LogicalDriveInformation =
+ Controller->LogicalDriveInformation
+ [Controller->LogicalDriveInformationIndex];
+ int LogicalDriveNumber;
+ for (LogicalDriveNumber = 0;
+ LogicalDriveNumber < Controller->LogicalDriveCount;
+ LogicalDriveNumber++)
+ GenericDiskInfo->part[DAC960_MinorNumber(LogicalDriveNumber, 0)].nr_sects =
+ LogicalDriveInformation[LogicalDriveNumber].LogicalDriveSize;
+}
+
+
+/*
+ DAC960_Message prints Driver Messages.
+*/
+
+static void DAC960_Message(DAC960_MessageLevel_T MessageLevel,
+ char *Format,
+ DAC960_Controller_T *Controller,
+ ...)
+{
+ static char Buffer[DAC960_LineBufferSize];
+ static boolean BeginningOfLine = true;
+ va_list Arguments;
+ int Length = 0;
+ va_start(Arguments, Controller);
+ Length = vsprintf(Buffer, Format, Arguments);
+ va_end(Arguments);
+ if (Controller == NULL)
+ printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
+ DAC960_ControllerCount, Buffer);
+ else if (MessageLevel == DAC960_AnnounceLevel ||
+ MessageLevel == DAC960_InfoLevel)
+ {
+ if (!Controller->ControllerInitialized)
+ {
+ strcpy(&Controller->InitialStatusBuffer[
+ Controller->InitialStatusLength], Buffer);
+ Controller->InitialStatusLength += Length;
+ if (MessageLevel == DAC960_AnnounceLevel)
+ {
+ static int AnnouncementLines = 0;
+ if (++AnnouncementLines <= 2)
+ printk("%sDAC960: %s", DAC960_MessageLevelMap[MessageLevel],
+ Buffer);
+ }
+ else
+ {
+ if (BeginningOfLine)
+ {
+ if (Buffer[0] != '\n' || Length > 1)
+ printk("%sDAC960#%d: %s",
+ DAC960_MessageLevelMap[MessageLevel],
+ Controller->ControllerNumber, Buffer);
+ }
+ else printk("%s", Buffer);
+ }
+ }
+ else
+ {
+ strcpy(&Controller->CurrentStatusBuffer[
+ Controller->CurrentStatusLength], Buffer);
+ Controller->CurrentStatusLength += Length;
+ }
+ }
+ else if (MessageLevel == DAC960_ProgressLevel)
+ {
+ strcpy(Controller->RebuildProgressBuffer, Buffer);
+ Controller->RebuildProgressLength = Length;
+ if (Controller->EphemeralProgressMessage)
+ {
+ if (jiffies - Controller->LastProgressReportTime
+ >= DAC960_ProgressReportingInterval)
+ {
+ printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
+ Controller->ControllerNumber, Buffer);
+ Controller->LastProgressReportTime = jiffies;
+ }
+ }
+ else printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
+ Controller->ControllerNumber, Buffer);
+ }
+ else if (MessageLevel == DAC960_UserCriticalLevel)
+ {
+ strcpy(&Controller->UserStatusBuffer[Controller->UserStatusLength],
+ Buffer);
+ Controller->UserStatusLength += Length;
+ if (Buffer[0] != '\n' || Length > 1)
+ printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
+ Controller->ControllerNumber, Buffer);
+ }
+ else
+ {
+ if (BeginningOfLine)
+ printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
+ Controller->ControllerNumber, Buffer);
+ else printk("%s", Buffer);
+ }
+ BeginningOfLine = (Buffer[Length-1] == '\n');
+}
+
+
+/*
+ DAC960_ParsePhysicalDrive parses spaces followed by a Physical Drive
+ Channel:TargetID specification from a User Command string. It updates
+ Channel and TargetID and returns true on success and returns false otherwise.
+*/
+
+static boolean DAC960_ParsePhysicalDrive(DAC960_Controller_T *Controller,
+ char *UserCommandString,
+ unsigned char *Channel,
+ unsigned char *TargetID)
+{
+ char *NewUserCommandString = UserCommandString;
+ unsigned long XChannel, XTargetID;
+ while (*UserCommandString == ' ') UserCommandString++;
+ if (UserCommandString == NewUserCommandString)
+ return false;
+ XChannel = simple_strtoul(UserCommandString, &NewUserCommandString, 10);
+ if (NewUserCommandString == UserCommandString ||
+ *NewUserCommandString != ':' ||
+ XChannel >= Controller->Channels)
+ return false;
+ UserCommandString = ++NewUserCommandString;
+ XTargetID = simple_strtoul(UserCommandString, &NewUserCommandString, 10);
+ if (NewUserCommandString == UserCommandString ||
+ *NewUserCommandString != '\0' ||
+ XTargetID >= DAC960_MaxTargets)
+ return false;
+ *Channel = XChannel;
+ *TargetID = XTargetID;
+ return true;
+}
+
+
+/*
+ DAC960_ParseLogicalDrive parses spaces followed by a Logical Drive Number
+ specification from a User Command string. It updates LogicalDriveNumber and
+ returns true on success and returns false otherwise.
+*/
+
+static boolean DAC960_ParseLogicalDrive(DAC960_Controller_T *Controller,
+ char *UserCommandString,
+ unsigned char *LogicalDriveNumber)
+{
+ char *NewUserCommandString = UserCommandString;
+ unsigned long XLogicalDriveNumber;
+ while (*UserCommandString == ' ') UserCommandString++;
+ if (UserCommandString == NewUserCommandString)
+ return false;
+ XLogicalDriveNumber =
+ simple_strtoul(UserCommandString, &NewUserCommandString, 10);
+ if (NewUserCommandString == UserCommandString ||
+ *NewUserCommandString != '\0' ||
+ XLogicalDriveNumber >= Controller->LogicalDriveCount)
+ return false;
+ *LogicalDriveNumber = XLogicalDriveNumber;
+ return true;
+}
+
+
+/*
+ DAC960_SetDeviceState sets the Device State for a Physical Drive.
+*/
+
+static void DAC960_SetDeviceState(DAC960_Controller_T *Controller,
+ DAC960_Command_T *Command,
+ unsigned char Channel,
+ unsigned char TargetID,
+ DAC960_PhysicalDeviceState_T DeviceState,
+ const char *DeviceStateString)
+{
+ DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+ CommandMailbox->Type3D.CommandOpcode = DAC960_StartDevice;
+ CommandMailbox->Type3D.Channel = Channel;
+ CommandMailbox->Type3D.TargetID = TargetID;
+ CommandMailbox->Type3D.DeviceState = DeviceState;
+ CommandMailbox->Type3D.Modifier = 0;
+ DAC960_ExecuteCommand(Command);
+ switch (Command->CommandStatus)
+ {
+ case DAC960_NormalCompletion:
+ DAC960_UserCritical("%s of Physical Drive %d:%d Succeeded\n", Controller,
+ DeviceStateString, Channel, TargetID);
+ break;
+ case DAC960_UnableToStartDevice:
+ DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
+ "Unable to Start Device\n", Controller,
+ DeviceStateString, Channel, TargetID);
+ break;
+ case DAC960_NoDeviceAtAddress:
+ DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
+ "No Device at Address\n", Controller,
+ DeviceStateString, Channel, TargetID);
+ break;
+ case DAC960_InvalidChannelOrTargetOrModifier:
+ DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
+ "Invalid Channel or Target or Modifier\n",
+ Controller, DeviceStateString, Channel, TargetID);
+ break;
+ case DAC960_ChannelBusy:
+ DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
+ "Channel Busy\n", Controller,
+ DeviceStateString, Channel, TargetID);
+ break;
+ default:
+ DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
+ "Unexpected Status %04X\n", Controller,
+ DeviceStateString, Channel, TargetID,
+ Command->CommandStatus);
+ break;
+ }
+}
+
+
+/*
+ DAC960_ExecuteUserCommand executes a User Command.
+*/
+
+static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller,
+ char *UserCommand)
+{
+ DAC960_Command_T *Command;
+ DAC960_CommandMailbox_T *CommandMailbox;
+ ProcessorFlags_T ProcessorFlags;
+ unsigned char Channel, TargetID, LogicalDriveNumber;
+ while (true)
+ {
+ DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+ Command = DAC960_AllocateCommand(Controller);
+ DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+ if (Command != NULL) break;
+ sleep_on(&Controller->CommandWaitQueue);
+ }
+ Controller->UserStatusLength = 0;
+ DAC960_ClearCommand(Command);
+ Command->CommandType = DAC960_ImmediateCommand;
+ CommandMailbox = &Command->CommandMailbox;
+ if (strcmp(UserCommand, "flush-cache") == 0)
+ {
+ CommandMailbox->Type3.CommandOpcode = DAC960_Flush;
+ DAC960_ExecuteCommand(Command);
+ DAC960_UserCritical("Cache Flush Completed\n", Controller);
+ }
+ else if (strncmp(UserCommand, "kill", 4) == 0 &&
+ DAC960_ParsePhysicalDrive(Controller, &UserCommand[4],
+ &Channel, &TargetID))
+ {
+ DAC960_DeviceState_T *DeviceState =
+ &Controller->DeviceState[Controller->DeviceStateIndex]
+ [Channel][TargetID];
+ if (DeviceState->Present &&
+ DeviceState->DeviceType == DAC960_DiskType &&
+ DeviceState->DeviceState != DAC960_Device_Dead)
+ DAC960_SetDeviceState(Controller, Command, Channel, TargetID,
+ DAC960_Device_Dead, "Kill");
+ else DAC960_UserCritical("Kill of Physical Drive %d:%d Illegal\n",
+ Controller, Channel, TargetID);
+ }
+ else if (strncmp(UserCommand, "make-online", 11) == 0 &&
+ DAC960_ParsePhysicalDrive(Controller, &UserCommand[11],
+ &Channel, &TargetID))
+ {
+ DAC960_DeviceState_T *DeviceState =
+ &Controller->DeviceState[Controller->DeviceStateIndex]
+ [Channel][TargetID];
+ if (DeviceState->Present &&
+ DeviceState->DeviceType == DAC960_DiskType &&
+ DeviceState->DeviceState == DAC960_Device_Dead)
+ DAC960_SetDeviceState(Controller, Command, Channel, TargetID,
+ DAC960_Device_Online, "Make Online");
+ else DAC960_UserCritical("Make Online of Physical Drive %d:%d Illegal\n",
+ Controller, Channel, TargetID);
+
+ }
+ else if (strncmp(UserCommand, "make-standby", 12) == 0 &&
+ DAC960_ParsePhysicalDrive(Controller, &UserCommand[12],
+ &Channel, &TargetID))
+ {
+ DAC960_DeviceState_T *DeviceState =
+ &Controller->DeviceState[Controller->DeviceStateIndex]
+ [Channel][TargetID];
+ if (DeviceState->Present &&
+ DeviceState->DeviceType == DAC960_DiskType &&
+ DeviceState->DeviceState == DAC960_Device_Dead)
+ DAC960_SetDeviceState(Controller, Command, Channel, TargetID,
+ DAC960_Device_Standby, "Make Standby");
+ else DAC960_UserCritical("Make Standby of Physical Drive %d:%d Illegal\n",
+ Controller, Channel, TargetID);
+ }
+ else if (strncmp(UserCommand, "rebuild", 7) == 0 &&
+ DAC960_ParsePhysicalDrive(Controller, &UserCommand[7],
+ &Channel, &TargetID))
+ {
+ CommandMailbox->Type3D.CommandOpcode = DAC960_RebuildAsync;
+ CommandMailbox->Type3D.Channel = Channel;
+ CommandMailbox->Type3D.TargetID = TargetID;
+ DAC960_ExecuteCommand(Command);
+ switch (Command->CommandStatus)
+ {
+ case DAC960_NormalCompletion:
+ DAC960_UserCritical("Rebuild of Physical Drive %d:%d Initiated\n",
+ Controller, Channel, TargetID);
+ break;
+ case DAC960_AttemptToRebuildOnlineDrive:
+ DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
+ "Attempt to Rebuild Online or "
+ "Unresponsive Drive\n",
+ Controller, Channel, TargetID);
+ break;
+ case DAC960_NewDiskFailedDuringRebuild:
+ DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
+ "New Disk Failed During Rebuild\n",
+ Controller, Channel, TargetID);
+ break;
+ case DAC960_InvalidDeviceAddress:
+ DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
+ "Invalid Device Address\n",
+ Controller, Channel, TargetID);
+ break;
+ case DAC960_RebuildOrCheckAlreadyInProgress:
+ DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
+ "Rebuild or Consistency Check Already "
+ "in Progress\n", Controller, Channel, TargetID);
+ break;
+ default:
+ DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
+ "Unexpected Status %04X\n", Controller,
+ Channel, TargetID, Command->CommandStatus);
+ break;
+ }
+ }
+ else if (strncmp(UserCommand, "check-consistency", 17) == 0 &&
+ DAC960_ParseLogicalDrive(Controller, &UserCommand[17],
+ &LogicalDriveNumber))
+ {
+ CommandMailbox->Type3C.CommandOpcode = DAC960_CheckConsistencyAsync;
+ CommandMailbox->Type3C.LogicalDriveNumber = LogicalDriveNumber;
+ CommandMailbox->Type3C.AutoRestore = true;
+ DAC960_ExecuteCommand(Command);
+ switch (Command->CommandStatus)
+ {
+ case DAC960_NormalCompletion:
+ DAC960_UserCritical("Consistency Check of Logical Drive %d "
+ "(/dev/rd/c%dd%d) Initiated\n",
+ Controller, LogicalDriveNumber,
+ Controller->ControllerNumber,
+ LogicalDriveNumber);
+ break;
+ case DAC960_DependentDiskIsDead:
+ DAC960_UserCritical("Consistency Check of Logical Drive %d "
+ "(/dev/rd/c%dd%d) Failed - "
+ "Dependent Physical Drive is DEAD\n",
+ Controller, LogicalDriveNumber,
+ Controller->ControllerNumber,
+ LogicalDriveNumber);
+ break;
+ case DAC960_InvalidOrNonredundantLogicalDrive:
+ DAC960_UserCritical("Consistency Check of Logical Drive %d "
+ "(/dev/rd/c%dd%d) Failed - "
+ "Invalid or Nonredundant Logical Drive\n",
+ Controller, LogicalDriveNumber,
+ Controller->ControllerNumber,
+ LogicalDriveNumber);
+ break;
+ case DAC960_RebuildOrCheckAlreadyInProgress:
+ DAC960_UserCritical("Consistency Check of Logical Drive %d "
+ "(/dev/rd/c%dd%d) Failed - Rebuild or "
+ "Consistency Check Already in Progress\n",
+ Controller, LogicalDriveNumber,
+ Controller->ControllerNumber,
+ LogicalDriveNumber);
+ break;
+ default:
+ DAC960_UserCritical("Consistency Check of Logical Drive %d "
+ "(/dev/rd/c%dd%d) Failed - "
+ "Unexpected Status %04X\n",
+ Controller, LogicalDriveNumber,
+ Controller->ControllerNumber,
+ LogicalDriveNumber, Command->CommandStatus);
+ break;
+ }
+ }
+ else if (strcmp(UserCommand, "cancel-rebuild") == 0 ||
+ strcmp(UserCommand, "cancel-consistency-check") == 0)
+ {
+ unsigned char OldRebuildRateConstant;
+ CommandMailbox->Type3R.CommandOpcode = DAC960_RebuildControl;
+ CommandMailbox->Type3R.RebuildRateConstant = 0xFF;
+ CommandMailbox->Type3R.BusAddress =
+ Virtual_to_Bus(&OldRebuildRateConstant);
+ DAC960_ExecuteCommand(Command);
+ switch (Command->CommandStatus)
+ {
+ case DAC960_NormalCompletion:
+ DAC960_UserCritical("Rebuild or Consistency Check Cancelled\n",
+ Controller);
+ break;
+ default:
+ DAC960_UserCritical("Cancellation of Rebuild or "
+ "Consistency Check Failed - "
+ "Unexpected Status %04X\n",
+ Controller, Command->CommandStatus);
+ break;
+ }
+ }
+ else DAC960_UserCritical("Illegal User Command: '%s'\n",
+ Controller, UserCommand);
+ DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+ DAC960_DeallocateCommand(Command);
+ DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+ return true;
+}
+
+
+/*
+ DAC960_ProcReadStatus implements reading /proc/rd/status.
+*/
+
+static int DAC960_ProcReadStatus(char *Page, char **Start, off_t Offset,
+ int Count, int *EOF, void *Data)
+{
+ char *StatusMessage = "OK\n";
+ int ControllerNumber, BytesAvailable;
+ for (ControllerNumber = 0;
+ ControllerNumber < DAC960_ControllerCount;
+ ControllerNumber++)
+ {
+ DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
+ DAC960_Enquiry_T *Enquiry;
+ if (Controller == NULL) continue;
+ Enquiry = &Controller->Enquiry[Controller->EnquiryIndex];
+ if (Enquiry->CriticalLogicalDriveCount > 0 ||
+ Enquiry->OfflineLogicalDriveCount > 0 ||
+ Enquiry->DeadDriveCount > 0)
+ {
+ StatusMessage = "ALERT\n";
+ break;
+ }
+ }
+ BytesAvailable = strlen(StatusMessage) - Offset;
+ if (Count >= BytesAvailable)
+ {
+ Count = BytesAvailable;
+ *EOF = true;
+ }
+ if (Count <= 0) return 0;
+ *Start = Page;
+ memcpy(Page, &StatusMessage[Offset], Count);
+ return Count;
+}
+
+
+/*
+ DAC960_ProcReadInitialStatus implements reading /proc/rd/cN/initial_status.
+*/
+
+static int DAC960_ProcReadInitialStatus(char *Page, char **Start, off_t Offset,
+ int Count, int *EOF, void *Data)
+{
+ DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data;
+ int BytesAvailable = Controller->InitialStatusLength - Offset;
+ if (Count >= BytesAvailable)
+ {
+ Count = BytesAvailable;
+ *EOF = true;
+ }
+ if (Count <= 0) return 0;
+ *Start = Page;
+ memcpy(Page, &Controller->InitialStatusBuffer[Offset], Count);
+ return Count;
+}
+
+
+/*
+ DAC960_ProcReadCurrentStatus implements reading /proc/rd/cN/current_status.
+*/
+
+static int DAC960_ProcReadCurrentStatus(char *Page, char **Start, off_t Offset,
+ int Count, int *EOF, void *Data)
+{
+ DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data;
+ int BytesAvailable;
+ if (jiffies != Controller->LastCurrentStatusTime)
+ {
+ Controller->CurrentStatusLength = 0;
+ DAC960_AnnounceDriver(Controller);
+ DAC960_ReportControllerConfiguration(Controller);
+ DAC960_ReportDeviceConfiguration(Controller);
+ Controller->CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' ';
+ Controller->CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' ';
+ if (Controller->RebuildProgressLength > 0)
+ {
+ strcpy(&Controller->CurrentStatusBuffer
+ [Controller->CurrentStatusLength],
+ Controller->RebuildProgressBuffer);
+ Controller->CurrentStatusLength += Controller->RebuildProgressLength;
+ }
+ else
+ {
+ char *StatusMessage = "No Rebuild or Consistency Check in Progress\n";
+ strcpy(&Controller->CurrentStatusBuffer
+ [Controller->CurrentStatusLength],
+ StatusMessage);
+ Controller->CurrentStatusLength += strlen(StatusMessage);
+ }
+ Controller->LastCurrentStatusTime = jiffies;
+ }
+ BytesAvailable = Controller->CurrentStatusLength - Offset;
+ if (Count >= BytesAvailable)
+ {
+ Count = BytesAvailable;
+ *EOF = true;
+ }
+ if (Count <= 0) return 0;
+ *Start = Page;
+ memcpy(Page, &Controller->CurrentStatusBuffer[Offset], Count);
+ return Count;
+}
+
+
+/*
+ DAC960_ProcReadUserCommand implements reading /proc/rd/cN/user_command.
+*/
+
+static int DAC960_ProcReadUserCommand(char *Page, char **Start, off_t Offset,
+ int Count, int *EOF, void *Data)
+{
+ DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data;
+ int BytesAvailable = Controller->UserStatusLength - Offset;
+ if (Count >= BytesAvailable)
+ {
+ Count = BytesAvailable;
+ *EOF = true;
+ }
+ if (Count <= 0) return 0;
+ *Start = Page;
+ memcpy(Page, &Controller->UserStatusBuffer[Offset], Count);
+ return Count;
+}
+
+
+/*
+ DAC960_ProcWriteUserCommand implements writing /proc/rd/cN/user_command.
+*/
+
+static int DAC960_ProcWriteUserCommand(File_T *File, const char *Buffer,
+ unsigned long Count, void *Data)
+{
+ DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data;
+ char CommandBuffer[80];
+ int Length;
+ if (Count > sizeof(CommandBuffer)-1) return -EINVAL;
+ copy_from_user(CommandBuffer, Buffer, Count);
+ CommandBuffer[Count] = '\0';
+ Length = strlen(CommandBuffer);
+ if (CommandBuffer[Length-1] == '\n')
+ CommandBuffer[--Length] = '\0';
+ return (DAC960_ExecuteUserCommand(Controller, CommandBuffer)
+ ? Count : -EBUSY);
+}
+
+
+/*
+ DAC960_CreateProcEntries creates the /proc/rd/... entries for the DAC960
+ Driver.
+*/
+
+static void DAC960_CreateProcEntries(void)
+{
+ static PROC_DirectoryEntry_T StatusProcEntry;
+ int ControllerNumber;
+ DAC960_ProcDirectoryEntry.name = "rd";
+ DAC960_ProcDirectoryEntry.namelen = strlen(DAC960_ProcDirectoryEntry.name);
+ DAC960_ProcDirectoryEntry.mode = S_IFDIR | S_IRUGO | S_IXUGO;
+ proc_register(&proc_root, &DAC960_ProcDirectoryEntry);
+ StatusProcEntry.name = "status";
+ StatusProcEntry.namelen = strlen(StatusProcEntry.name);
+ StatusProcEntry.mode = S_IFREG | S_IRUGO;
+ StatusProcEntry.read_proc = DAC960_ProcReadStatus;
+ proc_register(&DAC960_ProcDirectoryEntry, &StatusProcEntry);
+ for (ControllerNumber = 0;
+ ControllerNumber < DAC960_ControllerCount;
+ ControllerNumber++)
+ {
+ DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
+ PROC_DirectoryEntry_T *ControllerProcEntry, *InitialStatusProcEntry;
+ PROC_DirectoryEntry_T *CurrentStatusProcEntry, *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;
+ UserCommandProcEntry->write_proc = DAC960_ProcWriteUserCommand;
+ proc_register(ControllerProcEntry, UserCommandProcEntry);
+ }
+}
+
+
+/*
+ DAC960_DestroyProcEntries destroys the /proc/rd/... entries for the DAC960
+ Driver.
+*/
+
+static void DAC960_DestroyProcEntries(void)
+{
+ proc_unregister(&proc_root, DAC960_ProcDirectoryEntry.low_ino);
+}
+
+
+/*
+ Include Module support if requested.
+*/
+
+#ifdef MODULE
+
+
+int init_module(void)
+{
+ int ControllerNumber, LogicalDriveNumber;
+ DAC960_Initialize();
+ if (DAC960_ActiveControllerCount == 0) return -1;
+ for (ControllerNumber = 0;
+ ControllerNumber < DAC960_ControllerCount;
+ ControllerNumber++)
+ {
+ DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
+ if (Controller == NULL) continue;
+ DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo);
+ for (LogicalDriveNumber = 0;
+ LogicalDriveNumber < Controller->LogicalDriveCount;
+ LogicalDriveNumber++)
+ resetup_one_dev(&Controller->GenericDiskInfo, LogicalDriveNumber);
+ }
+ return 0;
+}
+
+
+void cleanup_module(void)
+{
+ DAC960_Finalize(&DAC960_NotifierBlock, SYS_RESTART, NULL);
+}
+
+
+#endif
diff --git a/drivers/block/DAC960.h b/drivers/block/DAC960.h
new file mode 100644
index 000000000..2ff757786
--- /dev/null
+++ b/drivers/block/DAC960.h
@@ -0,0 +1,2244 @@
+/*
+
+ Linux Driver for Mylex DAC960 and DAC1100 PCI RAID Controllers
+
+ Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+
+ This program is free software; you may redistribute and/or modify it under
+ the terms of the GNU General Public License Version 2 as published by the
+ Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for complete details.
+
+ The author respectfully requests that any modifications to this software be
+ sent directly to him for evaluation and testing.
+
+*/
+
+
+/*
+ Define the maximum number of DAC960 Controllers supported by this driver.
+*/
+
+#define DAC960_MaxControllers 8
+
+
+/*
+ Define the maximum number of Controller Channels supported by this driver.
+*/
+
+#define DAC960_MaxChannels 3
+
+
+/*
+ Define the maximum number of Targets per Channel supported by this driver.
+*/
+
+#define DAC960_MaxTargets 16
+
+
+/*
+ Define the maximum number of Logical Drives supported by any DAC960 model.
+*/
+
+#define DAC960_MaxLogicalDrives 32
+
+
+/*
+ Define a Boolean data type.
+*/
+
+typedef enum { false, true } __attribute__ ((packed)) boolean;
+
+
+/*
+ Define a 32 bit I/O Address data type.
+*/
+
+typedef unsigned int DAC960_IO_Address_T;
+
+
+/*
+ Define a 32 bit PCI Bus Address data type.
+*/
+
+typedef unsigned int DAC960_PCI_Address_T;
+
+
+/*
+ Define a 32 bit Bus Address data type.
+*/
+
+typedef unsigned int DAC960_BusAddress_T;
+
+
+/*
+ Define a 32 bit Byte Count data type.
+*/
+
+typedef unsigned int DAC960_ByteCount_T;
+
+
+/*
+ Define the DAC960 Command Opcodes.
+*/
+
+typedef enum
+{
+ /* I/O Commands */
+ DAC960_ReadExtended = 0x33,
+ DAC960_WriteExtended = 0x34,
+ DAC960_ReadAheadExtended = 0x35,
+ DAC960_ReadExtendedWithScatterGather = 0xB3,
+ DAC960_WriteExtendedWithScatterGather = 0xB4,
+ DAC960_Read = 0x36,
+ DAC960_ReadWithOldScatterGather = 0xB6,
+ DAC960_Write = 0x37,
+ DAC960_WriteWithOldScatterGather = 0xB7,
+ DAC960_DCDB = 0x04,
+ DAC960_DCDBWithScatterGather = 0x84,
+ DAC960_Flush = 0x0A,
+ /* Controller Status Related Commands */
+ DAC960_Enquiry = 0x53,
+ DAC960_Enquiry2 = 0x1C,
+ DAC960_GetLogicalDriveElement = 0x55,
+ DAC960_GetLogicalDriveInformation = 0x19,
+ DAC960_IOPortRead = 0x39,
+ DAC960_IOPortWrite = 0x3A,
+ DAC960_GetSDStats = 0x3E,
+ DAC960_GetPDStats = 0x3F,
+ DAC960_PerformEventLogOperation = 0x72,
+ /* Device Related Commands */
+ DAC960_StartDevice = 0x10,
+ DAC960_GetDeviceState = 0x50,
+ DAC960_StopChannel = 0x13,
+ DAC960_StartChannel = 0x12,
+ DAC960_ResetChannel = 0x1A,
+ /* Commands Associated with Data Consistency and Errors */
+ DAC960_Rebuild = 0x09,
+ DAC960_RebuildAsync = 0x16,
+ DAC960_CheckConsistency = 0x0F,
+ DAC960_CheckConsistencyAsync = 0x1E,
+ DAC960_RebuildStat = 0x0C,
+ DAC960_GetRebuildProgress = 0x27,
+ DAC960_RebuildControl = 0x1F,
+ DAC960_ReadBadBlockTable = 0x0B,
+ DAC960_ReadBadDataTable = 0x25,
+ DAC960_ClearBadDataTable = 0x26,
+ DAC960_GetErrorTable = 0x17,
+ DAC960_AddCapacityAsync = 0x2A,
+ /* Configuration Related Commands */
+ DAC960_ReadConfig2 = 0x3D,
+ DAC960_WriteConfig2 = 0x3C,
+ DAC960_ReadConfigurationOnDisk = 0x4A,
+ DAC960_WriteConfigurationOnDisk = 0x4B,
+ DAC960_ReadConfiguration = 0x4E,
+ DAC960_ReadBackupConfiguration = 0x4D,
+ DAC960_WriteConfiguration = 0x4F,
+ DAC960_AddConfiguration = 0x4C,
+ DAC960_ReadConfigurationLabel = 0x48,
+ DAC960_WriteConfigurationLabel = 0x49,
+ /* Firmware Upgrade Related Commands */
+ DAC960_LoadImage = 0x20,
+ DAC960_StoreImage = 0x21,
+ DAC960_ProgramImage = 0x22,
+ /* Diagnostic Commands */
+ DAC960_SetDiagnosticMode = 0x31,
+ DAC960_RunDiagnostic = 0x32,
+ /* Subsystem Service Commands */
+ DAC960_GetSubsystemData = 0x70,
+ DAC960_SetSubsystemParameters = 0x71
+}
+__attribute__ ((packed))
+DAC960_CommandOpcode_T;
+
+
+/*
+ Define the DAC960 Command Identifier type.
+*/
+
+typedef unsigned char DAC960_CommandIdentifier_T;
+
+
+/*
+ Define the DAC960 Command Status Codes.
+*/
+
+#define DAC960_NormalCompletion 0x0000 /* Common */
+#define DAC960_CheckConditionReceived 0x0002 /* Common */
+#define DAC960_NoDeviceAtAddress 0x0102 /* Common */
+#define DAC960_InvalidDeviceAddress 0x0105 /* Common */
+#define DAC960_InvalidParameter 0x0105 /* Common */
+#define DAC960_IrrecoverableDataError 0x0001 /* I/O */
+#define DAC960_LogicalDriveNonexistentOrOffline 0x0002 /* I/O */
+#define DAC960_AccessBeyondEndOfLogicalDrive 0x0105 /* I/O */
+#define DAC960_BadDataEncountered 0x010C /* I/O */
+#define DAC960_DeviceBusy 0x0008 /* DCDB */
+#define DAC960_DeviceNonresponsive 0x000E /* DCDB */
+#define DAC960_CommandTerminatedAbnormally 0x000F /* DCDB */
+#define DAC960_UnableToStartDevice 0x0002 /* Device */
+#define DAC960_InvalidChannelOrTargetOrModifier 0x0105 /* Device */
+#define DAC960_ChannelBusy 0x0106 /* Device */
+#define DAC960_ChannelNotStopped 0x0002 /* Device */
+#define DAC960_AttemptToRebuildOnlineDrive 0x0002 /* Consistency */
+#define DAC960_RebuildBadBlocksEncountered 0x0003 /* Consistency */
+#define DAC960_NewDiskFailedDuringRebuild 0x0004 /* Consistency */
+#define DAC960_RebuildOrCheckAlreadyInProgress 0x0106 /* Consistency */
+#define DAC960_DependentDiskIsDead 0x0002 /* Consistency */
+#define DAC960_InconsistentBlocksFound 0x0003 /* Consistency */
+#define DAC960_InvalidOrNonredundantLogicalDrive 0x0105 /* Consistency */
+#define DAC960_NoRebuildOrCheckInProgress 0x0105 /* Consistency */
+#define DAC960_RebuildInProgress_DataValid 0x0000 /* Consistency */
+#define DAC960_RebuildFailed_LogicalDriveFailure 0x0002 /* Consistency */
+#define DAC960_RebuildFailed_BadBlocksOnOther 0x0003 /* Consistency */
+#define DAC960_RebuildFailed_NewDriveFailed 0x0004 /* Consistency */
+#define DAC960_RebuildSuccessful 0x0100 /* Consistency */
+#define DAC960_AddCapacityInProgress 0x0004 /* Consistency */
+#define DAC960_AddCapacityFailedOrSuspended 0x00F4 /* Consistency */
+#define DAC960_Config2ChecksumError 0x0002 /* Configuration */
+#define DAC960_ConfigurationSuspended 0x0106 /* Configuration */
+#define DAC960_FailedToConfigureNVRAM 0x0105 /* Configuration */
+#define DAC960_ConfigurationNotSavedStateChange 0x0106 /* Configuration */
+#define DAC960_SubsystemNotInstalled 0x0001 /* Subsystem */
+#define DAC960_SubsystemFailed 0x0002 /* Subsystem */
+#define DAC960_SubsystemBusy 0x0106 /* Subsystem */
+
+typedef unsigned short DAC960_CommandStatus_T;
+
+
+/*
+ Define the Enquiry reply structure.
+*/
+
+typedef struct DAC960_Enquiry
+{
+ unsigned char NumberOfLogicalDrives; /* Byte 0 */
+ unsigned int :24; /* Bytes 1-3 */
+ unsigned int LogicalDriveSizes[32]; /* Bytes 4-131 */
+ unsigned short FlashAge; /* Bytes 132-133 */
+ struct {
+ boolean DeferredWriteError:1; /* Byte 134 Bit 0 */
+ boolean BatteryLow:1; /* Byte 134 Bit 1 */
+ unsigned char :6; /* Byte 134 Bits 2-7 */
+ } StatusFlags;
+ unsigned char :8; /* Byte 135 */
+ unsigned char MinorFirmwareVersion; /* Byte 136 */
+ unsigned char MajorFirmwareVersion; /* Byte 137 */
+ enum {
+ DAC960_NoStandbyRebuildOrCheckInProgress = 0x00,
+ DAC960_StandbyRebuildInProgress = 0x01,
+ DAC960_BackgroundRebuildInProgress = 0x02,
+ DAC960_BackgroundCheckInProgress = 0x03,
+ DAC960_StandbyRebuildCompletedWithError = 0xFF,
+ DAC960_BackgroundRebuildOrCheckFailed_DriveFailed = 0xF0,
+ DAC960_BackgroundRebuildOrCheckFailed_LogicalDriveFailed = 0xF1,
+ DAC960_BackgroundRebuildOrCheckFailed_OtherCauses = 0xF2,
+ DAC960_BackgroundRebuildOrCheckSuccessfullyTerminated = 0xF3
+ } __attribute__ ((packed)) RebuildFlag; /* Byte 138 */
+ unsigned char MaxCommands; /* Byte 139 */
+ unsigned char OfflineLogicalDriveCount; /* Byte 140 */
+ unsigned char :8; /* Byte 141 */
+ unsigned short EventLogSequenceNumber; /* Bytes 142-143 */
+ unsigned char CriticalLogicalDriveCount; /* Byte 144 */
+ unsigned int :24; /* Bytes 145-147 */
+ unsigned char DeadDriveCount; /* Byte 148 */
+ unsigned char :8; /* Byte 149 */
+ unsigned char RebuildCount; /* Byte 150 */
+ struct {
+ unsigned char :3; /* Byte 151 Bits 0-2 */
+ boolean BatteryBackupUnitPresent:1; /* Byte 151 Bit 3 */
+ unsigned char :3; /* Byte 151 Bits 4-6 */
+ unsigned char :1; /* Byte 151 Bit 7 */
+ } MiscFlags;
+ struct {
+ unsigned char TargetID;
+ unsigned char Channel;
+ } DeadDrives[21]; /* Bytes 152-194 */
+ unsigned char Reserved[62]; /* Bytes 195-255 */
+}
+__attribute__ ((packed))
+DAC960_Enquiry_T;
+
+
+/*
+ Define the Enquiry2 reply structure.
+*/
+
+typedef struct DAC960_Enquiry2
+{
+ struct {
+ enum {
+ DAC960_P_PD_PU = 0x01,
+ DAC960_PL = 0x02,
+ DAC960_PG = 0x10,
+ DAC960_PJ = 0x11,
+ DAC960_PR = 0x12,
+ DAC960_PT = 0x13,
+ DAC960_PTL0 = 0x14,
+ DAC960_PRL = 0x15,
+ DAC960_PTL1 = 0x16,
+ DAC1164_P = 0x20
+ } __attribute__ ((packed)) SubModel; /* Byte 0 */
+ unsigned char ActualChannels; /* Byte 1 */
+ enum {
+ DAC960_FiveChannelBoard = 0x01,
+ DAC960_ThreeChannelBoard = 0x02,
+ DAC960_TwoChannelBoard = 0x03,
+ DAC960_ThreeChannelASIC_DAC = 0x04
+ } __attribute__ ((packed)) Model; /* Byte 2 */
+ enum {
+ DAC960_EISA_Controller = 0x01,
+ DAC960_MicroChannel_Controller = 0x02,
+ DAC960_PCI_Controller = 0x03,
+ DAC960_SCSItoSCSI_Controller = 0x08
+ } __attribute__ ((packed)) ProductFamily; /* Byte 3 */
+ } HardwareID; /* Bytes 0-3 */
+ /* MajorVersion.MinorVersion-FirmwareType-TurnID */
+ struct {
+ unsigned char MajorVersion; /* Byte 4 */
+ unsigned char MinorVersion; /* Byte 5 */
+ unsigned char TurnID; /* Byte 6 */
+ char FirmwareType; /* Byte 7 */
+ } FirmwareID; /* Bytes 4-7 */
+ unsigned char :8; /* Byte 8 */
+ unsigned int :24; /* Bytes 9-11 */
+ unsigned char ConfiguredChannels; /* Byte 12 */
+ unsigned char ActualChannels; /* Byte 13 */
+ unsigned char MaxTargets; /* Byte 14 */
+ unsigned char MaxTags; /* Byte 15 */
+ unsigned char MaxLogicalDrives; /* Byte 16 */
+ unsigned char MaxArms; /* Byte 17 */
+ unsigned char MaxSpans; /* Byte 18 */
+ unsigned char :8; /* Byte 19 */
+ unsigned int :32; /* Bytes 20-23 */
+ unsigned int MemorySize; /* Bytes 24-27 */
+ unsigned int CacheSize; /* Bytes 28-31 */
+ unsigned int FlashMemorySize; /* Bytes 32-35 */
+ unsigned int NonVolatileMemorySize; /* Bytes 36-39 */
+ struct {
+ enum {
+ DAC960_DRAM = 0x00,
+ DAC960_EDO = 0x01,
+ DAC960_SDRAM = 0x02
+ } __attribute__ ((packed)) RamType:3; /* Byte 40 Bits 0-2 */
+ enum {
+ DAC960_None = 0x00,
+ DAC960_Parity = 0x01,
+ DAC960_ECC = 0x02
+ } __attribute__ ((packed)) ErrorCorrection:3; /* Byte 40 Bits 3-5 */
+ boolean FastPageMode:1; /* Byte 40 Bit 6 */
+ boolean LowPowerMemory:1; /* Byte 40 Bit 7 */
+ unsigned char :8; /* Bytes 41 */
+ } MemoryType;
+ unsigned short ClockSpeed; /* Bytes 42-43 */
+ unsigned short MemorySpeed; /* Bytes 44-45 */
+ unsigned short HardwareSpeed; /* Bytes 46-47 */
+ unsigned int :32; /* Bytes 48-51 */
+ unsigned int :32; /* Bytes 52-55 */
+ unsigned char :8; /* Byte 56 */
+ unsigned char :8; /* Byte 57 */
+ unsigned short :16; /* Bytes 58-59 */
+ unsigned short MaxCommands; /* Bytes 60-61 */
+ unsigned short MaxScatterGatherEntries; /* Bytes 62-63 */
+ unsigned short MaxDriveCommands; /* Bytes 64-65 */
+ unsigned short MaxIODescriptors; /* Bytes 66-67 */
+ unsigned short MaxCombinedSectors; /* Bytes 68-69 */
+ unsigned char Latency; /* Byte 70 */
+ unsigned char :8; /* Byte 71 */
+ unsigned char SCSITimeout; /* Byte 72 */
+ unsigned char :8; /* Byte 73 */
+ unsigned short MinFreeLines; /* Bytes 74-75 */
+ unsigned int :32; /* Bytes 76-79 */
+ unsigned int :32; /* Bytes 80-83 */
+ unsigned char RebuildRateConstant; /* Byte 84 */
+ unsigned char :8; /* Byte 85 */
+ unsigned char :8; /* Byte 86 */
+ unsigned char :8; /* Byte 87 */
+ unsigned int :32; /* Bytes 88-91 */
+ unsigned int :32; /* Bytes 92-95 */
+ unsigned short PhysicalDriveBlockSize; /* Bytes 96-97 */
+ unsigned short LogicalDriveBlockSize; /* Bytes 98-99 */
+ unsigned short MaxBlocksPerCommand; /* Bytes 100-101 */
+ unsigned short BlockFactor; /* Bytes 102-103 */
+ unsigned short CacheLineSize; /* Bytes 104-105 */
+ struct {
+ enum {
+ DAC960_Narrow_8bit = 0x00,
+ DAC960_Wide_16bit = 0x01,
+ DAC960_Wide_32bit = 0x02
+ } __attribute__ ((packed)) BusWidth:2; /* Byte 106 Bits 0-1 */
+ enum {
+ DAC960_Fast = 0x00,
+ DAC960_Ultra = 0x01,
+ DAC960_Ultra2 = 0x02
+ } __attribute__ ((packed)) BusSpeed:2; /* Byte 106 Bits 2-3 */
+ boolean Differential:1; /* Byte 106 Bit 4 */
+ unsigned char :3; /* Byte 106 Bits 5-7 */
+ } SCSICapability;
+ unsigned char :8; /* Byte 107 */
+ unsigned int :32; /* Bytes 108-111 */
+ unsigned short FirmwareBuildNumber; /* Bytes 112-113 */
+ enum {
+ DAC960_AEMI = 0x01,
+ DAC960_OEM1 = 0x02,
+ DAC960_OEM2 = 0x04,
+ DAC960_OEM3 = 0x08,
+ DAC960_Conner = 0x10,
+ DAC960_SAFTE = 0x20
+ } __attribute__ ((packed)) FaultManagementType; /* Byte 114 */
+ unsigned char :8; /* Byte 115 */
+ struct {
+ boolean Clustering:1; /* Byte 116 Bit 0 */
+ boolean MylexOnlineRAIDExpansion:1; /* Byte 116 Bit 1 */
+ unsigned int :30; /* Bytes 116-119 */
+ } FirmwareFeatures;
+ unsigned int :32; /* Bytes 120-123 */
+ unsigned int :32; /* Bytes 124-127 */
+}
+DAC960_Enquiry2_T;
+
+
+/*
+ Define the Logical Drive State type.
+*/
+
+typedef enum
+{
+ DAC960_LogicalDrive_Online = 0x03,
+ DAC960_LogicalDrive_Critical = 0x04,
+ DAC960_LogicalDrive_Offline = 0xFF
+}
+__attribute__ ((packed))
+DAC960_LogicalDriveState_T;
+
+
+/*
+ Define the Get Logical Drive Information reply structure.
+*/
+
+typedef struct DAC960_LogicalDriveInformation
+{
+ unsigned int LogicalDriveSize; /* Bytes 0-3 */
+ DAC960_LogicalDriveState_T LogicalDriveState; /* Byte 4 */
+ unsigned char RAIDLevel:7; /* Byte 5 Bits 0-6 */
+ boolean WriteBack:1; /* Byte 5 Bit 7 */
+ unsigned int :16; /* Bytes 6-7 */
+}
+DAC960_LogicalDriveInformation_T;
+
+
+/*
+ Define the Perform Event Log Operation Types.
+*/
+
+typedef enum
+{
+ DAC960_GetEventLogEntry = 0x00
+}
+__attribute__ ((packed))
+DAC960_PerformEventLogOpType_T;
+
+
+/*
+ Define the Get Event Log Entry reply structure.
+*/
+
+typedef struct DAC960_EventLogEntry
+{
+ unsigned char MessageType; /* Byte 0 */
+ unsigned char MessageLength; /* Byte 1 */
+ unsigned char TargetID:5; /* Byte 2 Bits 0-4 */
+ unsigned char Channel:3; /* Byte 2 Bits 5-7 */
+ unsigned char LogicalUnit:6; /* Byte 3 Bits 0-5 */
+ unsigned char :2; /* Byte 3 Bits 6-7 */
+ unsigned short SequenceNumber; /* Bytes 4-5 */
+ unsigned char ErrorCode:7; /* Byte 6 Bits 0-6 */
+ boolean Valid:1; /* Byte 6 Bit 7 */
+ unsigned char SegmentNumber; /* Byte 7 */
+ unsigned char SenseKey:4; /* Byte 8 Bits 0-3 */
+ unsigned char :1; /* Byte 8 Bit 4 */
+ boolean ILI:1; /* Byte 8 Bit 5 */
+ boolean EOM:1; /* Byte 8 Bit 6 */
+ boolean Filemark:1; /* Byte 8 Bit 7 */
+ unsigned char Information[4]; /* Bytes 9-12 */
+ unsigned char AdditionalSenseLength; /* Byte 13 */
+ unsigned char CommandSpecificInformation[4]; /* Bytes 14-17 */
+ unsigned char AdditionalSenseCode; /* Byte 18 */
+ unsigned char AdditionalSenseCodeQualifier; /* Byte 19 */
+ unsigned char Dummy[12]; /* Bytes 20-31 */
+}
+DAC960_EventLogEntry_T;
+
+
+/*
+ Define the Physical Device State type.
+*/
+
+typedef enum
+{
+ DAC960_Device_Dead = 0x00,
+ DAC960_Device_WriteOnly = 0x02,
+ DAC960_Device_Online = 0x03,
+ DAC960_Device_Standby = 0x10
+}
+__attribute__ ((packed))
+DAC960_PhysicalDeviceState_T;
+
+
+/*
+ Define the Get Device State reply structure.
+*/
+
+typedef struct DAC960_DeviceState
+{
+ boolean Present:1; /* Byte 0 Bit 0 */
+ unsigned char :7; /* Byte 0 Bits 1-7 */
+ enum {
+ DAC960_OtherType = 0x00,
+ DAC960_DiskType = 0x01,
+ DAC960_SequentialType = 0x02,
+ DAC960_CDROM_or_WORM_Type = 0x03
+ } __attribute__ ((packed)) DeviceType:2; /* Byte 1 Bits 0-1 */
+ boolean :1; /* Byte 1 Bit 2 */
+ boolean Fast20:1; /* Byte 1 Bit 3 */
+ boolean Sync:1; /* Byte 1 Bit 4 */
+ boolean Fast:1; /* Byte 1 Bit 5 */
+ boolean Wide:1; /* Byte 1 Bit 6 */
+ boolean TaggedQueuingSupported:1; /* Byte 1 Bit 7 */
+ DAC960_PhysicalDeviceState_T DeviceState; /* Byte 2 */
+ unsigned char :8; /* Byte 3 */
+ unsigned char SynchronousMultiplier; /* Byte 4 */
+ unsigned char SynchronousOffset:5; /* Byte 5 Bits 0-4 */
+ unsigned char :3; /* Byte 5 Bits 5-7 */
+ unsigned long DiskSize __attribute__ ((packed)); /* Bytes 6-9 */
+}
+DAC960_DeviceState_T;
+
+
+/*
+ Define the Get Rebuild Progress reply structure.
+*/
+
+typedef struct DAC960_RebuildProgress
+{
+ unsigned int LogicalDriveNumber; /* Bytes 0-3 */
+ unsigned int LogicalDriveSize; /* Bytes 4-7 */
+ unsigned int RemainingBlocks; /* Bytes 8-11 */
+}
+DAC960_RebuildProgress_T;
+
+
+/*
+ Define the Error Table Entry and Get Error Table reply structure.
+*/
+
+typedef struct DAC960_ErrorTableEntry
+{
+ unsigned char ParityErrorCount; /* Byte 0 */
+ unsigned char SoftErrorCount; /* Byte 1 */
+ unsigned char HardErrorCount; /* Byte 2 */
+ unsigned char MiscErrorCount; /* Byte 3 */
+}
+DAC960_ErrorTableEntry_T;
+
+
+/*
+ Define the Get Error Table reply structure.
+*/
+
+typedef struct DAC960_ErrorTable
+{
+ DAC960_ErrorTableEntry_T
+ ErrorTableEntries[DAC960_MaxChannels][DAC960_MaxTargets];
+}
+DAC960_ErrorTable_T;
+
+
+/*
+ Define the Config2 reply structure.
+*/
+
+typedef struct DAC960_Config2
+{
+ unsigned char :1; /* Byte 0 Bit 0 */
+ boolean ActiveNegationEnabled:1; /* Byte 0 Bit 1 */
+ unsigned char :5; /* Byte 0 Bits 2-6 */
+ boolean NoRescanIfResetReceivedDuringScan:1; /* Byte 0 Bit 7 */
+ boolean StorageWorksSupportEnabled:1; /* Byte 1 Bit 0 */
+ boolean HewlettPackardSupportEnabled:1; /* Byte 1 Bit 1 */
+ boolean NoDisconnectOnFirstCommand:1; /* Byte 1 Bit 2 */
+ unsigned char :2; /* Byte 1 Bits 3-4 */
+ boolean AEMI_ARM:1; /* Byte 1 Bit 5 */
+ boolean AEMI_OFM:1; /* Byte 1 Bit 6 */
+ unsigned char :1; /* Byte 1 Bit 7 */
+ enum {
+ DAC960_OEMID_Mylex = 0x00,
+ DAC960_OEMID_IBM = 0x08,
+ DAC960_OEMID_HP = 0x0A,
+ DAC960_OEMID_DEC = 0x0C,
+ DAC960_OEMID_Siemens = 0x10,
+ DAC960_OEMID_Intel = 0x12
+ } __attribute__ ((packed)) OEMID; /* Byte 2 */
+ unsigned char OEMModelNumber; /* Byte 3 */
+ unsigned char PhysicalSector; /* Byte 4 */
+ unsigned char LogicalSector; /* Byte 5 */
+ unsigned char BlockFactor; /* Byte 6 */
+ boolean ReadAheadEnabled:1; /* Byte 7 Bit 0 */
+ boolean LowBIOSDelay:1; /* Byte 7 Bit 1 */
+ unsigned char :2; /* Byte 7 Bits 2-3 */
+ boolean ReassignRestrictedToOneSector:1; /* Byte 7 Bit 4 */
+ unsigned char :1; /* Byte 7 Bit 5 */
+ boolean ForceUnitAccessDuringWriteRecovery:1; /* Byte 7 Bit 6 */
+ boolean EnableLeftSymmetricRAID5Algorithm:1; /* Byte 7 Bit 7 */
+ unsigned char DefaultRebuildRate; /* Byte 8 */
+ unsigned char :8; /* Byte 9 */
+ unsigned char BlocksPerCacheLine; /* Byte 10 */
+ unsigned char BlocksPerStripe; /* Byte 11 */
+ struct {
+ enum {
+ DAC960_Async = 0x00,
+ DAC960_Sync_8MHz = 0x01,
+ DAC960_Sync_5MHz = 0x02,
+ DAC960_Sync_10or20MHz = 0x03 /* Bits 0-1 */
+ } __attribute__ ((packed)) Speed:2;
+ boolean Force8Bit:1; /* Bit 2 */
+ boolean DisableFast20:1; /* Bit 3 */
+ unsigned char :3; /* Bits 4-6 */
+ boolean EnableTaggedQueuing:1; /* Bit 7 */
+ } __attribute__ ((packed)) ChannelParameters[6]; /* Bytes 12-17 */
+ unsigned char SCSIInitiatorID; /* Byte 18 */
+ unsigned char :8; /* Byte 19 */
+ enum {
+ DAC960_StartupMode_ControllerSpinUp = 0x00,
+ DAC960_StartupMode_PowerOnSpinUp = 0x01
+ } __attribute__ ((packed)) StartupMode; /* Byte 20 */
+ unsigned char SimultaneousDeviceSpinUpCount; /* Byte 21 */
+ unsigned char SecondsDelayBetweenSpinUps; /* Byte 22 */
+ unsigned char Reserved1[29]; /* Bytes 23-51 */
+ boolean BIOSDisabled:1; /* Byte 52 Bit 0 */
+ boolean CDROMBootEnabled:1; /* Byte 52 Bit 1 */
+ unsigned char :3; /* Byte 52 Bits 2-4 */
+ enum {
+ DAC960_Geometry_128_32 = 0x00,
+ DAC960_Geometry_255_63 = 0x01,
+ DAC960_Geometry_Reserved1 = 0x02,
+ DAC960_Geometry_Reserved2 = 0x03
+ } __attribute__ ((packed)) DriveGeometry:2; /* Byte 52 Bits 5-6 */
+ unsigned char :1; /* Byte 52 Bit 7 */
+ unsigned char Reserved2[9]; /* Bytes 53-61 */
+ unsigned short Checksum; /* Bytes 62-63 */
+}
+DAC960_Config2_T;
+
+
+/*
+ Define the DCDB request structure.
+*/
+
+typedef struct DAC960_DCDB
+{
+ unsigned char TargetID:4; /* Byte 0 Bits 0-3 */
+ unsigned char Channel:4; /* Byte 0 Bits 4-7 */
+ enum {
+ DAC960_DCDB_NoDataTransfer = 0,
+ DAC960_DCDB_DataTransferDeviceToSystem = 1,
+ DAC960_DCDB_DataTransferSystemToDevice = 2,
+ DAC960_DCDB_IllegalDataTransfer = 3
+ } __attribute__ ((packed)) Direction:2; /* Byte 1 Bits 0-1 */
+ boolean EarlyStatus:1; /* Byte 1 Bit 2 */
+ unsigned char :1; /* Byte 1 Bit 3 */
+ enum {
+ DAC960_DCDB_Timeout_24_hours = 0,
+ DAC960_DCDB_Timeout_10_seconds = 1,
+ DAC960_DCDB_Timeout_60_seconds = 2,
+ DAC960_DCDB_Timeout_10_minutes = 3
+ } __attribute__ ((packed)) Timeout:2; /* Byte 1 Bits 4-5 */
+ boolean NoAutomaticRequestSense:1; /* Byte 1 Bit 6 */
+ boolean DisconnectPermitted:1; /* Byte 1 Bit 7 */
+ unsigned short TransferLength; /* Bytes 2-3 */
+ DAC960_BusAddress_T BusAddress; /* Bytes 4-7 */
+ unsigned char CDBLength:4; /* Byte 8 Bits 0-3 */
+ unsigned char TransferLengthHigh4:4; /* Byte 8 Bits 4-7 */
+ unsigned char SenseLength; /* Byte 9 */
+ unsigned char CDB[12]; /* Bytes 10-21 */
+ unsigned char SenseData[64]; /* Bytes 22-85 */
+ unsigned char Status; /* Byte 86 */
+ unsigned char :8; /* Byte 87 */
+}
+DAC960_DCDB_T;
+
+
+/*
+ Define the SCSI INQUIRY Standard Data reply structure.
+*/
+
+typedef struct DAC960_SCSI_Inquiry
+{
+ unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */
+ unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */
+ unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */
+ boolean RMB:1; /* Byte 1 Bit 7 */
+ unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */
+ unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */
+ unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */
+ unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */
+ unsigned char :2; /* Byte 3 Bits 4-5 */
+ boolean TrmIOP:1; /* Byte 3 Bit 6 */
+ boolean AENC:1; /* Byte 3 Bit 7 */
+ unsigned char AdditionalLength; /* Byte 4 */
+ unsigned char :8; /* Byte 5 */
+ unsigned char :8; /* Byte 6 */
+ boolean SftRe:1; /* Byte 7 Bit 0 */
+ boolean CmdQue:1; /* Byte 7 Bit 1 */
+ boolean :1; /* Byte 7 Bit 2 */
+ boolean Linked:1; /* Byte 7 Bit 3 */
+ boolean Sync:1; /* Byte 7 Bit 4 */
+ boolean WBus16:1; /* Byte 7 Bit 5 */
+ boolean WBus32:1; /* Byte 7 Bit 6 */
+ boolean RelAdr:1; /* Byte 7 Bit 7 */
+ unsigned char VendorIdentification[8]; /* Bytes 8-15 */
+ unsigned char ProductIdentification[16]; /* Bytes 16-31 */
+ unsigned char ProductRevisionLevel[4]; /* Bytes 32-35 */
+}
+DAC960_SCSI_Inquiry_T;
+
+
+/*
+ Define the SCSI INQUIRY Unit Serial Number reply structure.
+*/
+
+typedef struct DAC960_SCSI_Inquiry_UnitSerialNumber
+{
+ unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */
+ unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */
+ unsigned char PageCode; /* Byte 1 */
+ unsigned char :8; /* Byte 2 */
+ unsigned char PageLength; /* Byte 3 */
+ unsigned char ProductSerialNumber[28]; /* Bytes 4 - 31 */
+}
+DAC960_SCSI_Inquiry_UnitSerialNumber_T;
+
+
+/*
+ Define the Scatter/Gather List Type 1 32 Bit Address 32 Bit Byte Count
+ structure.
+*/
+
+typedef struct DAC960_ScatterGatherSegment
+{
+ DAC960_BusAddress_T SegmentDataPointer; /* Bytes 0-3 */
+ DAC960_ByteCount_T SegmentByteCount; /* Bytes 4-7 */
+}
+DAC960_ScatterGatherSegment_T;
+
+
+/*
+ Define the 13 Byte DAC960 Command Mailbox structure. Bytes 13-15 are
+ not used. The Command Mailbox structure is padded to 16 bytes for
+ efficient access.
+*/
+
+typedef union DAC960_CommandMailbox
+{
+ unsigned int Words[4]; /* Words 0-3 */
+ unsigned char Bytes[16]; /* Bytes 0-15 */
+ struct {
+ DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */
+ DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */
+ unsigned char Dummy[14]; /* Bytes 2-15 */
+ } __attribute__ ((packed)) Common;
+ struct {
+ DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */
+ DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */
+ unsigned char Dummy1[6]; /* Bytes 2-7 */
+ DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */
+ unsigned char Dummy2[4]; /* Bytes 12-15 */
+ } __attribute__ ((packed)) Type3;
+ struct {
+ DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */
+ DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */
+ unsigned char Dummy1[5]; /* Bytes 2-6 */
+ unsigned char LogicalDriveNumber:6; /* Byte 7 Bits 0-6 */
+ boolean AutoRestore:1; /* Byte 7 Bit 7 */
+ unsigned char Dummy2[8]; /* Bytes 8-15 */
+ } __attribute__ ((packed)) Type3C;
+ struct {
+ DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */
+ DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */
+ unsigned char Channel; /* Byte 2 */
+ unsigned char TargetID; /* Byte 3 */
+ DAC960_PhysicalDeviceState_T DeviceState:5; /* Byte 4 Bits 0-4 */
+ unsigned char Modifier:3; /* Byte 4 Bits 5-7 */
+ unsigned char Dummy1[3]; /* Bytes 5-7 */
+ DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */
+ unsigned char Dummy2[4]; /* Bytes 12-15 */
+ } __attribute__ ((packed)) Type3D;
+ struct {
+ DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */
+ DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */
+ DAC960_PerformEventLogOpType_T OperationType; /* Byte 2 */
+ unsigned char OperationQualifier; /* Byte 3 */
+ unsigned short SequenceNumber; /* Bytes 4-5 */
+ unsigned char Dummy1[2]; /* Bytes 6-7 */
+ DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */
+ unsigned char Dummy2[4]; /* Bytes 12-15 */
+ } __attribute__ ((packed)) Type3E;
+ struct {
+ DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */
+ DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */
+ unsigned char Dummy1[2]; /* Bytes 2-3 */
+ unsigned char RebuildRateConstant; /* Byte 4 */
+ unsigned char Dummy2[3]; /* Bytes 5-7 */
+ DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */
+ unsigned char Dummy3[4]; /* Bytes 12-15 */
+ } __attribute__ ((packed)) Type3R;
+ struct {
+ DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */
+ DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */
+ unsigned short TransferLength; /* Bytes 2-3 */
+ unsigned int LogicalBlockAddress; /* Bytes 4-7 */
+ DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */
+ unsigned char LogicalDriveNumber; /* Byte 12 */
+ unsigned char Dummy[3]; /* Bytes 13-15 */
+ } __attribute__ ((packed)) Type4;
+ struct {
+ DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */
+ DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */
+ struct {
+ unsigned short TransferLength:11; /* Bytes 2-3 */
+ unsigned char LogicalDriveNumber:5; /* Byte 3 Bits 3-7 */
+ } __attribute__ ((packed)) LD;
+ unsigned int LogicalBlockAddress; /* Bytes 4-7 */
+ DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */
+ unsigned char ScatterGatherCount:6; /* Byte 12 Bits 0-5 */
+ enum {
+ DAC960_ScatterGather_32BitAddress_32BitByteCount = 0x0,
+ DAC960_ScatterGather_32BitAddress_16BitByteCount = 0x1,
+ DAC960_ScatterGather_32BitByteCount_32BitAddress = 0x2,
+ DAC960_ScatterGather_16BitByteCount_32BitAddress = 0x3
+ } __attribute__ ((packed)) ScatterGatherType:2; /* Byte 12 Bits 6-7 */
+ unsigned char Dummy[3]; /* Bytes 13-15 */
+ } __attribute__ ((packed)) Type5;
+ struct {
+ DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */
+ DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */
+ unsigned char CommandOpcode2; /* Byte 2 */
+ unsigned char :8; /* Byte 3 */
+ DAC960_BusAddress_T CommandMailboxesBusAddress; /* Bytes 4-7 */
+ DAC960_BusAddress_T StatusMailboxesBusAddress; /* Bytes 8-11 */
+ unsigned char Dummy[4]; /* Bytes 12-15 */
+ } __attribute__ ((packed)) TypeX;
+}
+DAC960_CommandMailbox_T;
+
+
+/*
+ Define the DAC960 Driver IOCTL requests.
+*/
+
+#define DAC960_IOCTL_GET_CONTROLLER_COUNT 0xDAC001
+#define DAC960_IOCTL_GET_CONTROLLER_INFO 0xDAC002
+#define DAC960_IOCTL_EXECUTE_COMMAND 0xDAC003
+
+
+/*
+ Define the DAC960_IOCTL_GET_CONTROLLER_INFO reply structure.
+*/
+
+typedef struct DAC960_ControllerInfo
+{
+ unsigned char ControllerNumber;
+ unsigned char PCI_Bus;
+ unsigned char PCI_Device;
+ unsigned char PCI_Function;
+ unsigned char IRQ_Channel;
+ unsigned char Channels;
+ DAC960_PCI_Address_T PCI_Address;
+ unsigned char ModelName[16];
+ unsigned char FirmwareVersion[16];
+}
+DAC960_ControllerInfo_T;
+
+
+/*
+ Define the User Mode DAC960_IOCTL_EXECUTE_COMMAND request structure.
+*/
+
+typedef struct DAC960_UserCommand
+{
+ unsigned char ControllerNumber;
+ DAC960_CommandMailbox_T CommandMailbox;
+ int DataTransferLength;
+ void *DataTransferBuffer;
+ DAC960_DCDB_T *DCDB;
+}
+DAC960_UserCommand_T;
+
+
+/*
+ Define the Kernel Mode DAC960_IOCTL_EXECUTE_COMMAND request structure.
+*/
+
+typedef struct DAC960_KernelCommand
+{
+ unsigned char ControllerNumber;
+ DAC960_CommandMailbox_T CommandMailbox;
+ int DataTransferLength;
+ void *DataTransferBuffer;
+ DAC960_DCDB_T *DCDB;
+ DAC960_CommandStatus_T CommandStatus;
+ void (*CompletionFunction)(struct DAC960_KernelCommand *);
+ void *CompletionData;
+}
+DAC960_KernelCommand_T;
+
+
+/*
+ Import the Kernel Mode IOCTL interface.
+*/
+
+extern int DAC960_KernelIOCTL(unsigned int Request, void *Argument);
+
+
+/*
+ Virtual_to_Bus maps from Kernel Virtual Addresses to PCI Bus Addresses.
+*/
+
+static inline DAC960_BusAddress_T Virtual_to_Bus(void *VirtualAddress)
+{
+ return (DAC960_BusAddress_T) virt_to_bus(VirtualAddress);
+}
+
+
+/*
+ Bus_to_Virtual maps from PCI Bus Addresses to Kernel Virtual Addresses.
+*/
+
+static inline void *Bus_to_Virtual(DAC960_BusAddress_T BusAddress)
+{
+ return (void *) bus_to_virt(BusAddress);
+}
+
+
+/*
+ DAC960_DriverVersion protects the private portion of this file.
+*/
+
+#ifdef DAC960_DriverVersion
+
+
+/*
+ Define the maximum Driver Queue Depth and Controller Queue Depth supported
+ by any DAC960 model.
+*/
+
+#define DAC960_MaxDriverQueueDepth 127
+#define DAC960_MaxControllerQueueDepth 128
+
+
+/*
+ Define the maximum number of Scatter/Gather Segments supported by any
+ DAC960 model.
+*/
+
+#define DAC960_MaxScatterGatherSegments 33
+
+
+/*
+ Define the number of Command Mailboxes and Status Mailboxes used by the
+ Memory Mailbox Interface.
+*/
+
+#define DAC960_CommandMailboxCount 256
+#define DAC960_StatusMailboxCount 1024
+
+
+/*
+ Define the DAC960 Controller Monitoring Timer Interval.
+*/
+
+#define DAC960_MonitoringTimerInterval (10 * HZ)
+
+
+/*
+ Define the DAC960 Controller Secondary Monitoring Interval.
+*/
+
+#define DAC960_SecondaryMonitoringInterval (60 * HZ)
+
+
+/*
+ Define the DAC960 Controller Progress Reporting Interval.
+*/
+
+#define DAC960_ProgressReportingInterval (60 * HZ)
+
+
+/*
+ Define the maximum number of Partitions allowed for each Logical Drive.
+*/
+
+#define DAC960_MaxPartitions 8
+#define DAC960_MaxPartitionsBits 3
+
+
+/*
+ Define macros to extract the Controller Number, Logical Drive Number, and
+ Partition Number from a Kernel Device, and to construct a Major Number, Minor
+ Number, and Kernel Device from the Controller Number, Logical Drive Number,
+ and Partition Number. There is one Major Number assigned to each Controller.
+ The associated Minor Number is divided into the Logical Drive Number and
+ Partition Number.
+*/
+
+#define DAC960_ControllerNumber(Device) \
+ (MAJOR(Device) - DAC960_MAJOR)
+
+#define DAC960_LogicalDriveNumber(Device) \
+ (MINOR(Device) >> DAC960_MaxPartitionsBits)
+
+#define DAC960_PartitionNumber(Device) \
+ (MINOR(Device) & (DAC960_MaxPartitions - 1))
+
+#define DAC960_MajorNumber(ControllerNumber) \
+ (DAC960_MAJOR + (ControllerNumber))
+
+#define DAC960_MinorNumber(LogicalDriveNumber, PartitionNumber) \
+ (((LogicalDriveNumber) << DAC960_MaxPartitionsBits) | (PartitionNumber))
+
+#define DAC960_MinorCount (DAC960_MaxLogicalDrives \
+ * DAC960_MaxPartitions)
+
+#define DAC960_KernelDevice(ControllerNumber, \
+ LogicalDriveNumber, \
+ PartitionNumber) \
+ MKDEV(DAC960_MajorNumber(ControllerNumber), \
+ DAC960_MinorNumber(LogicalDriveNumber, PartitionNumber))
+
+
+/*
+ Define the DAC960 Controller fixed Block Size and Block Size Bits.
+*/
+
+#define DAC960_BlockSize 512
+#define DAC960_BlockSizeBits 9
+
+
+/*
+ Define the Controller Line Buffer, Status Buffer, Rebuild Progress,
+ and User Message Sizes.
+*/
+
+#define DAC960_LineBufferSize 100
+#define DAC960_StatusBufferSize 16384
+#define DAC960_RebuildProgressSize 200
+#define DAC960_UserMessageSize 200
+
+
+/*
+ Define the types of DAC960 Controllers that are supported.
+*/
+
+typedef enum
+{
+ DAC960_V5_Controller = 1, /* DAC1164P */
+ DAC960_V4_Controller = 2, /* DAC960PTL/PJ/PG */
+ DAC960_V3_Controller = 3 /* DAC960PU/PD/PL */
+}
+DAC960_ControllerType_T;
+
+
+/*
+ Define the Driver Message Levels.
+*/
+
+typedef enum DAC960_MessageLevel
+{
+ DAC960_AnnounceLevel = 0,
+ DAC960_InfoLevel = 1,
+ DAC960_NoticeLevel = 2,
+ DAC960_WarningLevel = 3,
+ DAC960_ErrorLevel = 4,
+ DAC960_ProgressLevel = 5,
+ DAC960_CriticalLevel = 6,
+ DAC960_UserCriticalLevel = 7
+}
+DAC960_MessageLevel_T;
+
+static char
+ *DAC960_MessageLevelMap[] =
+ { KERN_NOTICE, KERN_NOTICE, KERN_NOTICE, KERN_WARNING,
+ KERN_ERR, KERN_CRIT, KERN_CRIT, KERN_CRIT };
+
+
+/*
+ Define Driver Message macros.
+*/
+
+#define DAC960_Announce(Format, Arguments...) \
+ DAC960_Message(DAC960_AnnounceLevel, Format, ##Arguments)
+
+#define DAC960_Info(Format, Arguments...) \
+ DAC960_Message(DAC960_InfoLevel, Format, ##Arguments)
+
+#define DAC960_Notice(Format, Arguments...) \
+ DAC960_Message(DAC960_NoticeLevel, Format, ##Arguments)
+
+#define DAC960_Warning(Format, Arguments...) \
+ DAC960_Message(DAC960_WarningLevel, Format, ##Arguments)
+
+#define DAC960_Error(Format, Arguments...) \
+ DAC960_Message(DAC960_ErrorLevel, Format, ##Arguments)
+
+#define DAC960_Progress(Format, Arguments...) \
+ DAC960_Message(DAC960_ProgressLevel, Format, ##Arguments)
+
+#define DAC960_Critical(Format, Arguments...) \
+ DAC960_Message(DAC960_CriticalLevel, Format, ##Arguments)
+
+#define DAC960_UserCritical(Format, Arguments...) \
+ DAC960_Message(DAC960_UserCriticalLevel, Format, ##Arguments)
+
+
+/*
+ Define types for some of the structures that interface with the rest
+ of the Linux Kernel and I/O Subsystem.
+*/
+
+typedef struct buffer_head BufferHeader_T;
+typedef struct file File_T;
+typedef struct file_operations FileOperations_T;
+typedef struct gendisk GenericDiskInfo_T;
+typedef struct hd_geometry DiskGeometry_T;
+typedef struct hd_struct DiskPartition_T;
+typedef struct inode Inode_T;
+typedef struct inode_operations InodeOperations_T;
+typedef kdev_t KernelDevice_T;
+typedef struct notifier_block NotifierBlock_T;
+typedef struct pci_dev PCI_Device_T;
+typedef struct proc_dir_entry PROC_DirectoryEntry_T;
+typedef unsigned long ProcessorFlags_T;
+typedef struct pt_regs Registers_T;
+typedef struct request IO_Request_T;
+typedef struct semaphore Semaphore_T;
+typedef struct super_block SuperBlock_T;
+typedef struct timer_list Timer_T;
+typedef wait_queue_head_t WaitQueue_T;
+
+
+/*
+ Define the DAC960 Controller Status Mailbox structure.
+*/
+
+typedef union DAC960_StatusMailbox
+{
+ unsigned int Word; /* Bytes 0-3 */
+ struct {
+ DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 0 */
+ unsigned char :7; /* Byte 1 Bits 0-6 */
+ boolean Valid:1; /* Byte 1 Bit 7 */
+ DAC960_CommandStatus_T CommandStatus; /* Bytes 2-3 */
+ } Fields;
+}
+DAC960_StatusMailbox_T;
+
+
+/*
+ Define the DAC960 Driver Command Types.
+*/
+
+typedef enum
+{
+ DAC960_ReadCommand = 1,
+ DAC960_WriteCommand = 2,
+ DAC960_ReadRetryCommand = 3,
+ DAC960_WriteRetryCommand = 4,
+ DAC960_MonitoringCommand = 5,
+ DAC960_ImmediateCommand = 6,
+ DAC960_QueuedCommand = 7
+}
+DAC960_CommandType_T;
+
+
+/*
+ Define the DAC960 Driver Command structure.
+*/
+
+typedef struct DAC960_Command
+{
+ DAC960_CommandType_T CommandType;
+ DAC960_CommandMailbox_T CommandMailbox;
+ DAC960_CommandStatus_T CommandStatus;
+ struct DAC960_Controller *Controller;
+ struct DAC960_Command *Next;
+ Semaphore_T *Semaphore;
+ unsigned int LogicalDriveNumber;
+ unsigned int BlockNumber;
+ unsigned int BlockCount;
+ unsigned int SegmentCount;
+ BufferHeader_T *BufferHeader;
+ DAC960_KernelCommand_T *KernelCommand;
+ DAC960_ScatterGatherSegment_T
+ ScatterGatherList[DAC960_MaxScatterGatherSegments];
+}
+DAC960_Command_T;
+
+
+/*
+ Define the DAC960 Driver Controller structure.
+*/
+
+typedef struct DAC960_Controller
+{
+ void *BaseAddress;
+ void *MemoryMappedAddress;
+ DAC960_ControllerType_T ControllerType;
+ DAC960_IO_Address_T IO_Address;
+ DAC960_PCI_Address_T PCI_Address;
+ unsigned char ControllerNumber;
+ unsigned char ControllerName[4];
+ unsigned char ModelName[12];
+ unsigned char FullModelName[18];
+ unsigned char FirmwareVersion[14];
+ unsigned char Bus;
+ unsigned char Device;
+ unsigned char Function;
+ unsigned char IRQ_Channel;
+ unsigned char Channels;
+ unsigned char MemorySize;
+ unsigned char LogicalDriveCount;
+ unsigned char GeometryTranslationHeads;
+ unsigned char GeometryTranslationSectors;
+ unsigned short ControllerQueueDepth;
+ unsigned short DriverQueueDepth;
+ unsigned short MaxBlocksPerCommand;
+ unsigned short MaxScatterGatherSegments;
+ unsigned short StripeSize;
+ unsigned short SegmentSize;
+ unsigned short NewEventLogSequenceNumber;
+ unsigned short OldEventLogSequenceNumber;
+ unsigned short InitialStatusLength;
+ unsigned short CurrentStatusLength;
+ unsigned short UserStatusLength;
+ unsigned short RebuildProgressLength;
+ unsigned int ControllerUsageCount;
+ unsigned int EnquiryIndex;
+ unsigned int LogicalDriveInformationIndex;
+ unsigned int ErrorTableIndex;
+ unsigned int DeviceStateIndex;
+ unsigned int DeviceStateChannel;
+ unsigned int DeviceStateTargetID;
+ unsigned long MonitoringTimerCount;
+ unsigned long SecondaryMonitoringTime;
+ unsigned long LastProgressReportTime;
+ unsigned long LastCurrentStatusTime;
+ boolean DualModeMemoryMailboxInterface;
+ boolean SAFTE_EnclosureManagementEnabled;
+ boolean ControllerInitialized;
+ boolean MonitoringCommandDeferred;
+ boolean NeedLogicalDriveInformation;
+ boolean NeedErrorTableInformation;
+ boolean NeedDeviceStateInformation;
+ boolean NeedDeviceInquiryInformation;
+ boolean NeedDeviceSerialNumberInformation;
+ boolean NeedRebuildProgress;
+ boolean NeedConsistencyCheckProgress;
+ boolean EphemeralProgressMessage;
+ Timer_T MonitoringTimer;
+ GenericDiskInfo_T GenericDiskInfo;
+ DAC960_Command_T *FreeCommands;
+ DAC960_CommandMailbox_T *FirstCommandMailbox;
+ DAC960_CommandMailbox_T *LastCommandMailbox;
+ DAC960_CommandMailbox_T *NextCommandMailbox;
+ DAC960_CommandMailbox_T *PreviousCommandMailbox1;
+ DAC960_CommandMailbox_T *PreviousCommandMailbox2;
+ 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];
+ DAC960_ErrorTable_T ErrorTable[2];
+ DAC960_EventLogEntry_T EventLogEntry;
+ DAC960_RebuildProgress_T RebuildProgress;
+ DAC960_CommandStatus_T LastRebuildStatus;
+ DAC960_LogicalDriveInformation_T
+ LogicalDriveInformation[2][DAC960_MaxLogicalDrives];
+ DAC960_LogicalDriveState_T LogicalDriveInitialState[DAC960_MaxLogicalDrives];
+ DAC960_DeviceState_T DeviceState[2][DAC960_MaxChannels][DAC960_MaxTargets];
+ DAC960_Command_T Commands[DAC960_MaxDriverQueueDepth];
+ DAC960_SCSI_Inquiry_T
+ InquiryStandardData[DAC960_MaxChannels][DAC960_MaxTargets];
+ DAC960_SCSI_Inquiry_UnitSerialNumber_T
+ InquiryUnitSerialNumber[DAC960_MaxChannels][DAC960_MaxTargets];
+ DiskPartition_T DiskPartitions[DAC960_MinorCount];
+ int LogicalDriveUsageCount[DAC960_MaxLogicalDrives];
+ int PartitionSizes[DAC960_MinorCount];
+ int BlockSizes[DAC960_MinorCount];
+ int MaxSectorsPerRequest[DAC960_MinorCount];
+ int MaxSegmentsPerRequest[DAC960_MinorCount];
+ int DeviceResetCount[DAC960_MaxChannels][DAC960_MaxTargets];
+ boolean DirectCommandActive[DAC960_MaxChannels][DAC960_MaxTargets];
+ char InitialStatusBuffer[DAC960_StatusBufferSize];
+ char CurrentStatusBuffer[DAC960_StatusBufferSize];
+ char UserStatusBuffer[DAC960_UserMessageSize];
+ char RebuildProgressBuffer[DAC960_RebuildProgressSize];
+}
+DAC960_Controller_T;
+
+
+/*
+ DAC960_AcquireControllerLock acquires exclusive access to Controller.
+*/
+
+static inline
+void DAC960_AcquireControllerLock(DAC960_Controller_T *Controller,
+ ProcessorFlags_T *ProcessorFlags)
+{
+ spin_lock_irqsave(&io_request_lock, *ProcessorFlags);
+}
+
+
+/*
+ DAC960_ReleaseControllerLock releases exclusive access to Controller.
+*/
+
+static inline
+void DAC960_ReleaseControllerLock(DAC960_Controller_T *Controller,
+ ProcessorFlags_T *ProcessorFlags)
+{
+ spin_unlock_irqrestore(&io_request_lock, *ProcessorFlags);
+}
+
+
+/*
+ DAC960_AcquireControllerLockRF acquires exclusive access to Controller,
+ but is only called from the request function with the io_request_lock held.
+*/
+
+static inline
+void DAC960_AcquireControllerLockRF(DAC960_Controller_T *Controller,
+ ProcessorFlags_T *ProcessorFlags)
+{
+}
+
+
+/*
+ DAC960_ReleaseControllerLockRF releases exclusive access to Controller,
+ but is only called from the request function with the io_request_lock held.
+*/
+
+static inline
+void DAC960_ReleaseControllerLockRF(DAC960_Controller_T *Controller,
+ ProcessorFlags_T *ProcessorFlags)
+{
+}
+
+
+/*
+ DAC960_AcquireControllerLockIH acquires exclusive access to Controller,
+ but is only called from the interrupt handler.
+*/
+
+static inline
+void DAC960_AcquireControllerLockIH(DAC960_Controller_T *Controller,
+ ProcessorFlags_T *ProcessorFlags)
+{
+ spin_lock_irqsave(&io_request_lock, *ProcessorFlags);
+}
+
+
+/*
+ DAC960_ReleaseControllerLockIH releases exclusive access to Controller,
+ but is only called from the interrupt handler.
+*/
+
+static inline
+void DAC960_ReleaseControllerLockIH(DAC960_Controller_T *Controller,
+ ProcessorFlags_T *ProcessorFlags)
+{
+ spin_unlock_irqrestore(&io_request_lock, *ProcessorFlags);
+}
+
+
+/*
+ Define the DAC960 V5 Controller Interface Register Offsets.
+*/
+
+#define DAC960_V5_RegisterWindowSize 0x80
+
+typedef enum
+{
+ DAC960_V5_InboundDoorBellRegisterOffset = 0x60,
+ DAC960_V5_OutboundDoorBellRegisterOffset = 0x61,
+ DAC960_V5_InterruptMaskRegisterOffset = 0x34,
+ DAC960_V5_CommandOpcodeRegisterOffset = 0x50,
+ DAC960_V5_CommandIdentifierRegisterOffset = 0x51,
+ DAC960_V5_MailboxRegister2Offset = 0x52,
+ DAC960_V5_MailboxRegister3Offset = 0x53,
+ DAC960_V5_MailboxRegister4Offset = 0x54,
+ DAC960_V5_MailboxRegister5Offset = 0x55,
+ DAC960_V5_MailboxRegister6Offset = 0x56,
+ DAC960_V5_MailboxRegister7Offset = 0x57,
+ DAC960_V5_MailboxRegister8Offset = 0x58,
+ DAC960_V5_MailboxRegister9Offset = 0x59,
+ DAC960_V5_MailboxRegister10Offset = 0x5A,
+ DAC960_V5_MailboxRegister11Offset = 0x5B,
+ DAC960_V5_MailboxRegister12Offset = 0x5C,
+ DAC960_V5_StatusCommandIdentifierRegOffset = 0x5D,
+ DAC960_V5_StatusRegisterOffset = 0x5E
+}
+DAC960_V5_RegisterOffsets_T;
+
+
+/*
+ Define the structure of the DAC960 V5 Inbound Door Bell Register.
+*/
+
+typedef union DAC960_V5_InboundDoorBellRegister
+{
+ unsigned char All;
+ struct {
+ boolean HardwareMailboxNewCommand:1; /* Bit 0 */
+ boolean AcknowledgeHardwareMailboxStatus:1; /* Bit 1 */
+ boolean GenerateInterrupt:1; /* Bit 2 */
+ boolean ControllerReset:1; /* Bit 3 */
+ boolean MemoryMailboxNewCommand:1; /* Bit 4 */
+ unsigned char :3; /* Bits 5-7 */
+ } Write;
+ struct {
+ boolean HardwareMailboxEmpty:1; /* Bit 0 */
+ unsigned char :7; /* Bits 1-7 */
+ } Read;
+}
+DAC960_V5_InboundDoorBellRegister_T;
+
+
+/*
+ Define the structure of the DAC960 V5 Outbound Door Bell Register.
+*/
+
+typedef union DAC960_V5_OutboundDoorBellRegister
+{
+ unsigned char All;
+ struct {
+ boolean AcknowledgeHardwareMailboxInterrupt:1; /* Bit 0 */
+ boolean AcknowledgeMemoryMailboxInterrupt:1; /* Bit 1 */
+ unsigned char :6; /* Bits 2-7 */
+ } Write;
+ struct {
+ boolean HardwareMailboxStatusAvailable:1; /* Bit 0 */
+ boolean MemoryMailboxStatusAvailable:1; /* Bit 1 */
+ unsigned char :6; /* Bits 2-7 */
+ } Read;
+}
+DAC960_V5_OutboundDoorBellRegister_T;
+
+
+/*
+ Define the structure of the DAC960 V5 Interrupt Mask Register.
+*/
+
+typedef union DAC960_V5_InterruptMaskRegister
+{
+ unsigned char All;
+ struct {
+ unsigned char :2; /* Bits 0-1 */
+ boolean DisableInterrupts:1; /* Bit 2 */
+ unsigned char :5; /* Bits 3-7 */
+ } Bits;
+}
+DAC960_V5_InterruptMaskRegister_T;
+
+
+/*
+ Define inline functions to provide an abstraction for reading and writing the
+ DAC960 V5 Controller Interface Registers.
+*/
+
+static inline
+void DAC960_V5_HardwareMailboxNewCommand(void *ControllerBaseAddress)
+{
+ DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+ InboundDoorBellRegister.All = 0;
+ InboundDoorBellRegister.Write.HardwareMailboxNewCommand = true;
+ writeb(InboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V5_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
+{
+ DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+ InboundDoorBellRegister.All = 0;
+ InboundDoorBellRegister.Write.AcknowledgeHardwareMailboxStatus = true;
+ writeb(InboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V5_GenerateInterrupt(void *ControllerBaseAddress)
+{
+ DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+ InboundDoorBellRegister.All = 0;
+ InboundDoorBellRegister.Write.GenerateInterrupt = true;
+ writeb(InboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V5_ControllerReset(void *ControllerBaseAddress)
+{
+ DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+ InboundDoorBellRegister.All = 0;
+ InboundDoorBellRegister.Write.ControllerReset = true;
+ writeb(InboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V5_MemoryMailboxNewCommand(void *ControllerBaseAddress)
+{
+ DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+ InboundDoorBellRegister.All = 0;
+ InboundDoorBellRegister.Write.MemoryMailboxNewCommand = true;
+ writeb(InboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+}
+
+static inline
+boolean DAC960_V5_HardwareMailboxEmptyP(void *ControllerBaseAddress)
+{
+ DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+ InboundDoorBellRegister.All =
+ readb(ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+ return InboundDoorBellRegister.Read.HardwareMailboxEmpty;
+}
+
+static inline
+void DAC960_V5_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
+{
+ DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+ OutboundDoorBellRegister.All = 0;
+ OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true;
+ writeb(OutboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V5_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
+{
+ DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+ OutboundDoorBellRegister.All = 0;
+ OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true;
+ writeb(OutboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V5_AcknowledgeInterrupt(void *ControllerBaseAddress)
+{
+ DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+ OutboundDoorBellRegister.All = 0;
+ OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true;
+ OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true;
+ writeb(OutboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+boolean DAC960_V5_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
+{
+ DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+ OutboundDoorBellRegister.All =
+ readb(ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
+ return OutboundDoorBellRegister.Read.HardwareMailboxStatusAvailable;
+}
+
+static inline
+boolean DAC960_V5_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
+{
+ DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+ OutboundDoorBellRegister.All =
+ readb(ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
+ return OutboundDoorBellRegister.Read.MemoryMailboxStatusAvailable;
+}
+
+static inline
+void DAC960_V5_EnableInterrupts(void *ControllerBaseAddress)
+{
+ DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister;
+ InterruptMaskRegister.All = 0;
+ InterruptMaskRegister.Bits.DisableInterrupts = false;
+ writeb(InterruptMaskRegister.All,
+ ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset);
+}
+
+static inline
+void DAC960_V5_DisableInterrupts(void *ControllerBaseAddress)
+{
+ DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister;
+ InterruptMaskRegister.All = 0;
+ InterruptMaskRegister.Bits.DisableInterrupts = true;
+ writeb(InterruptMaskRegister.All,
+ ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset);
+}
+
+static inline
+boolean DAC960_V5_InterruptsEnabledP(void *ControllerBaseAddress)
+{
+ DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister;
+ InterruptMaskRegister.All =
+ readb(ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset);
+ return !InterruptMaskRegister.Bits.DisableInterrupts;
+}
+
+static inline
+void DAC960_V5_WriteCommandMailbox(DAC960_CommandMailbox_T *NextCommandMailbox,
+ DAC960_CommandMailbox_T *CommandMailbox)
+{
+ NextCommandMailbox->Words[1] = CommandMailbox->Words[1];
+ NextCommandMailbox->Words[2] = CommandMailbox->Words[2];
+ NextCommandMailbox->Words[3] = CommandMailbox->Words[3];
+ NextCommandMailbox->Words[0] = CommandMailbox->Words[0];
+}
+
+static inline
+void DAC960_V5_WriteHardwareMailbox(void *ControllerBaseAddress,
+ DAC960_CommandMailbox_T *CommandMailbox)
+{
+ writel(CommandMailbox->Words[0],
+ ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset);
+ writel(CommandMailbox->Words[1],
+ ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset);
+ writel(CommandMailbox->Words[2],
+ ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset);
+ writeb(CommandMailbox->Bytes[12],
+ ControllerBaseAddress + DAC960_V5_MailboxRegister12Offset);
+}
+
+static inline DAC960_CommandIdentifier_T
+DAC960_V5_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
+{
+ return readb(ControllerBaseAddress
+ + DAC960_V5_StatusCommandIdentifierRegOffset);
+}
+
+static inline DAC960_CommandStatus_T
+DAC960_V5_ReadStatusRegister(void *ControllerBaseAddress)
+{
+ return readw(ControllerBaseAddress + DAC960_V5_StatusRegisterOffset);
+}
+
+static inline
+void DAC960_V5_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller)
+{
+ void *ControllerBaseAddress = Controller->BaseAddress;
+ writel(0x743C485E,
+ ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset);
+ writel((unsigned long) Controller->FirstCommandMailbox,
+ ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset);
+ writew(Controller->NextCommandMailbox - Controller->FirstCommandMailbox,
+ ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset);
+ writew(Controller->NextStatusMailbox - Controller->FirstStatusMailbox,
+ ControllerBaseAddress + DAC960_V5_MailboxRegister10Offset);
+}
+
+static inline
+void DAC960_V5_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller,
+ void **MemoryMailboxAddress,
+ short *NextCommandMailboxIndex,
+ short *NextStatusMailboxIndex)
+{
+ void *ControllerBaseAddress = Controller->BaseAddress;
+ if (readl(ControllerBaseAddress
+ + DAC960_V5_CommandOpcodeRegisterOffset) != 0x743C485E)
+ return;
+ *MemoryMailboxAddress =
+ (void *) readl(ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset);
+ *NextCommandMailboxIndex =
+ readw(ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset);
+ *NextStatusMailboxIndex =
+ readw(ControllerBaseAddress + DAC960_V5_MailboxRegister10Offset);
+}
+
+
+/*
+ Define the DAC960 V4 Controller Interface Register Offsets.
+*/
+
+#define DAC960_V4_RegisterWindowSize 0x2000
+
+typedef enum
+{
+ DAC960_V4_InboundDoorBellRegisterOffset = 0x0020,
+ DAC960_V4_OutboundDoorBellRegisterOffset = 0x002C,
+ DAC960_V4_InterruptMaskRegisterOffset = 0x0034,
+ DAC960_V4_CommandOpcodeRegisterOffset = 0x1000,
+ DAC960_V4_CommandIdentifierRegisterOffset = 0x1001,
+ DAC960_V4_MailboxRegister2Offset = 0x1002,
+ DAC960_V4_MailboxRegister3Offset = 0x1003,
+ DAC960_V4_MailboxRegister4Offset = 0x1004,
+ DAC960_V4_MailboxRegister5Offset = 0x1005,
+ DAC960_V4_MailboxRegister6Offset = 0x1006,
+ DAC960_V4_MailboxRegister7Offset = 0x1007,
+ DAC960_V4_MailboxRegister8Offset = 0x1008,
+ DAC960_V4_MailboxRegister9Offset = 0x1009,
+ DAC960_V4_MailboxRegister10Offset = 0x100A,
+ DAC960_V4_MailboxRegister11Offset = 0x100B,
+ DAC960_V4_MailboxRegister12Offset = 0x100C,
+ DAC960_V4_StatusCommandIdentifierRegOffset = 0x1018,
+ DAC960_V4_StatusRegisterOffset = 0x101A
+}
+DAC960_V4_RegisterOffsets_T;
+
+
+/*
+ Define the structure of the DAC960 V4 Inbound Door Bell Register.
+*/
+
+typedef union DAC960_V4_InboundDoorBellRegister
+{
+ unsigned int All;
+ struct {
+ boolean HardwareMailboxNewCommand:1; /* Bit 0 */
+ boolean AcknowledgeHardwareMailboxStatus:1; /* Bit 1 */
+ boolean GenerateInterrupt:1; /* Bit 2 */
+ boolean ControllerReset:1; /* Bit 3 */
+ boolean MemoryMailboxNewCommand:1; /* Bit 4 */
+ unsigned int :27; /* Bits 5-31 */
+ } Write;
+ struct {
+ boolean HardwareMailboxFull:1; /* Bit 0 */
+ unsigned int :31; /* Bits 1-31 */
+ } Read;
+}
+DAC960_V4_InboundDoorBellRegister_T;
+
+
+/*
+ Define the structure of the DAC960 V4 Outbound Door Bell Register.
+*/
+
+typedef union DAC960_V4_OutboundDoorBellRegister
+{
+ unsigned int All;
+ struct {
+ boolean AcknowledgeHardwareMailboxInterrupt:1; /* Bit 0 */
+ boolean AcknowledgeMemoryMailboxInterrupt:1; /* Bit 1 */
+ unsigned int :30; /* Bits 2-31 */
+ } Write;
+ struct {
+ boolean HardwareMailboxStatusAvailable:1; /* Bit 0 */
+ boolean MemoryMailboxStatusAvailable:1; /* Bit 1 */
+ unsigned int :30; /* Bits 2-31 */
+ } Read;
+}
+DAC960_V4_OutboundDoorBellRegister_T;
+
+
+/*
+ Define the structure of the DAC960 V4 Interrupt Mask Register.
+*/
+
+typedef union DAC960_V4_InterruptMaskRegister
+{
+ unsigned int All;
+ struct {
+ unsigned int MessageUnitInterruptMask1:2; /* Bits 0-1 */
+ boolean DisableInterrupts:1; /* Bit 2 */
+ unsigned int MessageUnitInterruptMask2:5; /* Bits 3-7 */
+ unsigned int Reserved0:24; /* Bits 8-31 */
+ } Bits;
+}
+DAC960_V4_InterruptMaskRegister_T;
+
+
+/*
+ Define inline functions to provide an abstraction for reading and writing the
+ DAC960 V4 Controller Interface Registers.
+*/
+
+static inline
+void DAC960_V4_HardwareMailboxNewCommand(void *ControllerBaseAddress)
+{
+ DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+ InboundDoorBellRegister.All = 0;
+ InboundDoorBellRegister.Write.HardwareMailboxNewCommand = true;
+ writel(InboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V4_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
+{
+ DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+ InboundDoorBellRegister.All = 0;
+ InboundDoorBellRegister.Write.AcknowledgeHardwareMailboxStatus = true;
+ writel(InboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V4_GenerateInterrupt(void *ControllerBaseAddress)
+{
+ DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+ InboundDoorBellRegister.All = 0;
+ InboundDoorBellRegister.Write.GenerateInterrupt = true;
+ writel(InboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V4_ControllerReset(void *ControllerBaseAddress)
+{
+ DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+ InboundDoorBellRegister.All = 0;
+ InboundDoorBellRegister.Write.ControllerReset = true;
+ writel(InboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V4_MemoryMailboxNewCommand(void *ControllerBaseAddress)
+{
+ DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+ InboundDoorBellRegister.All = 0;
+ InboundDoorBellRegister.Write.MemoryMailboxNewCommand = true;
+ writel(InboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+}
+
+static inline
+boolean DAC960_V4_HardwareMailboxFullP(void *ControllerBaseAddress)
+{
+ DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+ InboundDoorBellRegister.All =
+ readl(ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+ return InboundDoorBellRegister.Read.HardwareMailboxFull;
+}
+
+static inline
+void DAC960_V4_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
+{
+ DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+ OutboundDoorBellRegister.All = 0;
+ OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true;
+ writel(OutboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V4_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
+{
+ DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+ OutboundDoorBellRegister.All = 0;
+ OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true;
+ writel(OutboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V4_AcknowledgeInterrupt(void *ControllerBaseAddress)
+{
+ DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+ OutboundDoorBellRegister.All = 0;
+ OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true;
+ OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true;
+ writel(OutboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+boolean DAC960_V4_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
+{
+ DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+ OutboundDoorBellRegister.All =
+ readl(ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
+ return OutboundDoorBellRegister.Read.HardwareMailboxStatusAvailable;
+}
+
+static inline
+boolean DAC960_V4_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
+{
+ DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+ OutboundDoorBellRegister.All =
+ readl(ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
+ return OutboundDoorBellRegister.Read.MemoryMailboxStatusAvailable;
+}
+
+static inline
+void DAC960_V4_EnableInterrupts(void *ControllerBaseAddress)
+{
+ DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister;
+ InterruptMaskRegister.All = 0;
+ InterruptMaskRegister.Bits.MessageUnitInterruptMask1 = 0x3;
+ InterruptMaskRegister.Bits.DisableInterrupts = false;
+ InterruptMaskRegister.Bits.MessageUnitInterruptMask2 = 0x1F;
+ writel(InterruptMaskRegister.All,
+ ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset);
+}
+
+static inline
+void DAC960_V4_DisableInterrupts(void *ControllerBaseAddress)
+{
+ DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister;
+ InterruptMaskRegister.All = 0;
+ InterruptMaskRegister.Bits.MessageUnitInterruptMask1 = 0x3;
+ InterruptMaskRegister.Bits.DisableInterrupts = true;
+ InterruptMaskRegister.Bits.MessageUnitInterruptMask2 = 0x1F;
+ writel(InterruptMaskRegister.All,
+ ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset);
+}
+
+static inline
+boolean DAC960_V4_InterruptsEnabledP(void *ControllerBaseAddress)
+{
+ DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister;
+ InterruptMaskRegister.All =
+ readl(ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset);
+ return !InterruptMaskRegister.Bits.DisableInterrupts;
+}
+
+static inline
+void DAC960_V4_WriteCommandMailbox(DAC960_CommandMailbox_T *NextCommandMailbox,
+ DAC960_CommandMailbox_T *CommandMailbox)
+{
+ NextCommandMailbox->Words[1] = CommandMailbox->Words[1];
+ NextCommandMailbox->Words[2] = CommandMailbox->Words[2];
+ NextCommandMailbox->Words[3] = CommandMailbox->Words[3];
+ NextCommandMailbox->Words[0] = CommandMailbox->Words[0];
+}
+
+static inline
+void DAC960_V4_WriteHardwareMailbox(void *ControllerBaseAddress,
+ DAC960_CommandMailbox_T *CommandMailbox)
+{
+ writel(CommandMailbox->Words[0],
+ ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset);
+ writel(CommandMailbox->Words[1],
+ ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset);
+ writel(CommandMailbox->Words[2],
+ ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset);
+ writeb(CommandMailbox->Bytes[12],
+ ControllerBaseAddress + DAC960_V4_MailboxRegister12Offset);
+}
+
+static inline DAC960_CommandIdentifier_T
+DAC960_V4_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
+{
+ return readb(ControllerBaseAddress
+ + DAC960_V4_StatusCommandIdentifierRegOffset);
+}
+
+static inline DAC960_CommandStatus_T
+DAC960_V4_ReadStatusRegister(void *ControllerBaseAddress)
+{
+ return readw(ControllerBaseAddress + DAC960_V4_StatusRegisterOffset);
+}
+
+static inline
+void DAC960_V4_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller)
+{
+ void *ControllerBaseAddress = Controller->BaseAddress;
+ writel(0xAABBFFFF,
+ ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset);
+ writel((unsigned long) Controller->FirstCommandMailbox,
+ ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset);
+ writew(Controller->NextCommandMailbox - Controller->FirstCommandMailbox,
+ ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset);
+ writew(Controller->NextStatusMailbox - Controller->FirstStatusMailbox,
+ ControllerBaseAddress + DAC960_V4_MailboxRegister10Offset);
+}
+
+static inline
+void DAC960_V4_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller,
+ void **MemoryMailboxAddress,
+ short *NextCommandMailboxIndex,
+ short *NextStatusMailboxIndex)
+{
+ void *ControllerBaseAddress = Controller->BaseAddress;
+ if (readl(ControllerBaseAddress
+ + DAC960_V4_CommandOpcodeRegisterOffset) != 0xAABBFFFF)
+ return;
+ *MemoryMailboxAddress =
+ (void *) readl(ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset);
+ *NextCommandMailboxIndex =
+ readw(ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset);
+ *NextStatusMailboxIndex =
+ readw(ControllerBaseAddress + DAC960_V4_MailboxRegister10Offset);
+}
+
+
+/*
+ Define the DAC960 V3 Controller Interface Register Offsets.
+*/
+
+#define DAC960_V3_RegisterWindowSize 0x80
+
+typedef enum
+{
+ DAC960_V3_CommandOpcodeRegisterOffset = 0x00,
+ DAC960_V3_CommandIdentifierRegisterOffset = 0x01,
+ DAC960_V3_MailboxRegister2Offset = 0x02,
+ DAC960_V3_MailboxRegister3Offset = 0x03,
+ DAC960_V3_MailboxRegister4Offset = 0x04,
+ DAC960_V3_MailboxRegister5Offset = 0x05,
+ DAC960_V3_MailboxRegister6Offset = 0x06,
+ DAC960_V3_MailboxRegister7Offset = 0x07,
+ DAC960_V3_MailboxRegister8Offset = 0x08,
+ DAC960_V3_MailboxRegister9Offset = 0x09,
+ DAC960_V3_MailboxRegister10Offset = 0x0A,
+ DAC960_V3_MailboxRegister11Offset = 0x0B,
+ DAC960_V3_MailboxRegister12Offset = 0x0C,
+ DAC960_V3_StatusCommandIdentifierRegOffset = 0x0D,
+ DAC960_V3_StatusRegisterOffset = 0x0E,
+ DAC960_V3_InboundDoorBellRegisterOffset = 0x40,
+ DAC960_V3_OutboundDoorBellRegisterOffset = 0x41,
+ DAC960_V3_InterruptEnableRegisterOffset = 0x43
+}
+DAC960_V3_RegisterOffsets_T;
+
+
+/*
+ Define the structure of the DAC960 V3 Inbound Door Bell Register.
+*/
+
+typedef union DAC960_V3_InboundDoorBellRegister
+{
+ unsigned char All;
+ struct {
+ boolean NewCommand:1; /* Bit 0 */
+ boolean AcknowledgeStatus:1; /* Bit 1 */
+ boolean GenerateInterrupt:1; /* Bit 2 */
+ boolean ControllerReset:1; /* Bit 3 */
+ unsigned char :4; /* Bits 4-7 */
+ } Write;
+ struct {
+ boolean MailboxFull:1; /* Bit 0 */
+ unsigned char :7; /* Bits 1-7 */
+ } Read;
+}
+DAC960_V3_InboundDoorBellRegister_T;
+
+
+/*
+ Define the structure of the DAC960 V3 Outbound Door Bell Register.
+*/
+
+typedef union DAC960_V3_OutboundDoorBellRegister
+{
+ unsigned char All;
+ struct {
+ boolean AcknowledgeInterrupt:1; /* Bit 0 */
+ unsigned char :7; /* Bits 1-7 */
+ } Write;
+ struct {
+ boolean StatusAvailable:1; /* Bit 0 */
+ unsigned char :7; /* Bits 1-7 */
+ } Read;
+}
+DAC960_V3_OutboundDoorBellRegister_T;
+
+
+/*
+ Define the structure of the DAC960 V3 Interrupt Enable Register.
+*/
+
+typedef union DAC960_V3_InterruptEnableRegister
+{
+ unsigned char All;
+ struct {
+ boolean EnableInterrupts:1; /* Bit 0 */
+ unsigned char :7; /* Bits 1-7 */
+ } Bits;
+}
+DAC960_V3_InterruptEnableRegister_T;
+
+
+/*
+ Define inline functions to provide an abstraction for reading and writing the
+ DAC960 V3 Controller Interface Registers.
+*/
+
+static inline
+void DAC960_V3_NewCommand(void *ControllerBaseAddress)
+{
+ DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
+ InboundDoorBellRegister.All = 0;
+ InboundDoorBellRegister.Write.NewCommand = true;
+ writeb(InboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V3_AcknowledgeStatus(void *ControllerBaseAddress)
+{
+ DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
+ InboundDoorBellRegister.All = 0;
+ InboundDoorBellRegister.Write.AcknowledgeStatus = true;
+ writeb(InboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V3_GenerateInterrupt(void *ControllerBaseAddress)
+{
+ DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
+ InboundDoorBellRegister.All = 0;
+ InboundDoorBellRegister.Write.GenerateInterrupt = true;
+ writeb(InboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V3_ControllerReset(void *ControllerBaseAddress)
+{
+ DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
+ InboundDoorBellRegister.All = 0;
+ InboundDoorBellRegister.Write.ControllerReset = true;
+ writeb(InboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
+}
+
+static inline
+boolean DAC960_V3_MailboxFullP(void *ControllerBaseAddress)
+{
+ DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
+ InboundDoorBellRegister.All =
+ readb(ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
+ return InboundDoorBellRegister.Read.MailboxFull;
+}
+
+static inline
+void DAC960_V3_AcknowledgeInterrupt(void *ControllerBaseAddress)
+{
+ DAC960_V3_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+ OutboundDoorBellRegister.All = 0;
+ OutboundDoorBellRegister.Write.AcknowledgeInterrupt = true;
+ writeb(OutboundDoorBellRegister.All,
+ ControllerBaseAddress + DAC960_V3_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+boolean DAC960_V3_StatusAvailableP(void *ControllerBaseAddress)
+{
+ DAC960_V3_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+ OutboundDoorBellRegister.All =
+ readb(ControllerBaseAddress + DAC960_V3_OutboundDoorBellRegisterOffset);
+ return OutboundDoorBellRegister.Read.StatusAvailable;
+}
+
+static inline
+void DAC960_V3_EnableInterrupts(void *ControllerBaseAddress)
+{
+ DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister;
+ InterruptEnableRegister.All = 0;
+ InterruptEnableRegister.Bits.EnableInterrupts = true;
+ writeb(InterruptEnableRegister.All,
+ ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset);
+}
+
+static inline
+void DAC960_V3_DisableInterrupts(void *ControllerBaseAddress)
+{
+ DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister;
+ InterruptEnableRegister.All = 0;
+ InterruptEnableRegister.Bits.EnableInterrupts = false;
+ writeb(InterruptEnableRegister.All,
+ ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset);
+}
+
+static inline
+boolean DAC960_V3_InterruptsEnabledP(void *ControllerBaseAddress)
+{
+ DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister;
+ InterruptEnableRegister.All =
+ readb(ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset);
+ return InterruptEnableRegister.Bits.EnableInterrupts;
+}
+
+static inline
+void DAC960_V3_WriteCommandMailbox(void *ControllerBaseAddress,
+ DAC960_CommandMailbox_T *CommandMailbox)
+{
+ writel(CommandMailbox->Words[0],
+ ControllerBaseAddress + DAC960_V3_CommandOpcodeRegisterOffset);
+ writel(CommandMailbox->Words[1],
+ ControllerBaseAddress + DAC960_V3_MailboxRegister4Offset);
+ writel(CommandMailbox->Words[2],
+ ControllerBaseAddress + DAC960_V3_MailboxRegister8Offset);
+ writeb(CommandMailbox->Bytes[12],
+ ControllerBaseAddress + DAC960_V3_MailboxRegister12Offset);
+}
+
+static inline DAC960_CommandIdentifier_T
+DAC960_V3_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
+{
+ return readb(ControllerBaseAddress
+ + DAC960_V3_StatusCommandIdentifierRegOffset);
+}
+
+static inline DAC960_CommandStatus_T
+DAC960_V3_ReadStatusRegister(void *ControllerBaseAddress)
+{
+ return readw(ControllerBaseAddress + DAC960_V3_StatusRegisterOffset);
+}
+
+
+/*
+ Define compatibility macros between Linux 2.0 and Linux 2.1.
+*/
+
+#if LINUX_VERSION_CODE < 0x20100
+
+#define MODULE_PARM(Variable, Type)
+#define ioremap_nocache(Offset, Size) vremap(Offset, Size)
+#define iounmap(Address) vfree(Address)
+
+#endif
+
+
+/*
+ Define prototypes for the forward referenced DAC960 Driver Internal Functions.
+*/
+
+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_InterruptHandler(int, void *, Registers_T *);
+static void DAC960_QueueMonitoringCommand(DAC960_Command_T *);
+static void DAC960_MonitoringTimerFunction(unsigned long);
+static int DAC960_Open(Inode_T *, File_T *);
+static int DAC960_Release(Inode_T *, File_T *);
+static int DAC960_IOCTL(Inode_T *, File_T *, unsigned int, unsigned long);
+static int DAC960_UserIOCTL(Inode_T *, File_T *, unsigned int, unsigned long);
+static void DAC960_InitializeGenericDiskInfo(GenericDiskInfo_T *);
+static void DAC960_Message(DAC960_MessageLevel_T, char *,
+ DAC960_Controller_T *, ...);
+static void DAC960_CreateProcEntries(void);
+static void DAC960_DestroyProcEntries(void);
+
+
+/*
+ Export the Kernel Mode IOCTL interface.
+*/
+
+EXPORT_SYMBOL(DAC960_KernelIOCTL);
+
+
+#endif /* DAC960_DriverVersion */
diff --git a/drivers/block/MAKEDEV-IDE45 b/drivers/block/MAKEDEV-IDE45
deleted file mode 100644
index c55a9b3cf..000000000
--- a/drivers/block/MAKEDEV-IDE45
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/bin/sh
-#
-# Andre Hedrick <hedrick@astro.dyer.vanderbilt.edu>
-#
-# The song goes, "I did it the hard way..........."
-#
-
-if [ ! -f /dev/hdi ]; then \
- echo "Making IDE4 Primary Devices hdi's"; \
- mknod /dev/hdi b 56 0; \
- mknod /dev/hdi1 b 56 1; \
- mknod /dev/hdi2 b 56 2; \
- mknod /dev/hdi3 b 56 3; \
- mknod /dev/hdi4 b 56 4; \
- mknod /dev/hdi5 b 56 5; \
- mknod /dev/hdi6 b 56 6; \
- mknod /dev/hdi7 b 56 7; \
- mknod /dev/hdi8 b 56 8; \
- mknod /dev/hdi9 b 56 9; \
- mknod /dev/hdi10 b 56 10; \
- mknod /dev/hdi11 b 56 11; \
- mknod /dev/hdi12 b 56 12; \
- mknod /dev/hdi13 b 56 13; \
- mknod /dev/hdi14 b 56 14; \
- mknod /dev/hdi15 b 56 15; \
- mknod /dev/hdi16 b 56 16; \
- chown root.disk /dev/hdi*; \
- chmod 660 /dev/hdi*; \
-fi
-
-if [ ! -f /dev/hdj ]; then \
- echo "Making IDE4 Secondary Devices hdj's"; \
- mknod /dev/hdj b 56 64; \
- mknod /dev/hdj1 b 56 65; \
- mknod /dev/hdj2 b 56 66; \
- mknod /dev/hdj3 b 56 67; \
- mknod /dev/hdj4 b 56 68; \
- mknod /dev/hdj5 b 56 69; \
- mknod /dev/hdj6 b 56 70; \
- mknod /dev/hdj7 b 56 71; \
- mknod /dev/hdj8 b 56 72; \
- mknod /dev/hdj9 b 56 73; \
- mknod /dev/hdj10 b 56 74; \
- mknod /dev/hdj11 b 56 75; \
- mknod /dev/hdj12 b 56 76; \
- mknod /dev/hdj13 b 56 77; \
- mknod /dev/hdj14 b 56 78; \
- mknod /dev/hdj15 b 56 79; \
- mknod /dev/hdj16 b 56 80; \
- chown root.disk /dev/hdj*; \
- chmod 660 /dev/hdj*; \
-fi
-
-if [ ! -f /dev/hdk ]; then \
- echo "Making IDE5 Primary Devices hdk's"; \
- mknod /dev/hdk b 57 0; \
- mknod /dev/hdk1 b 57 1; \
- mknod /dev/hdk2 b 57 2; \
- mknod /dev/hdk3 b 57 3; \
- mknod /dev/hdk4 b 57 4; \
- mknod /dev/hdk5 b 57 5; \
- mknod /dev/hdk6 b 57 6; \
- mknod /dev/hdk7 b 57 7; \
- mknod /dev/hdk8 b 57 8; \
- mknod /dev/hdk9 b 57 9; \
- mknod /dev/hdk10 b 57 10; \
- mknod /dev/hdk11 b 57 11; \
- mknod /dev/hdk12 b 57 12; \
- mknod /dev/hdk13 b 57 13; \
- mknod /dev/hdk14 b 57 14; \
- mknod /dev/hdk15 b 57 15; \
- mknod /dev/hdk16 b 57 16; \
- chown root.disk /dev/hdk*; \
- chmod 660 /dev/hdk*; \
-fi
-
-if [ ! -f /dev/hdl ]; then \
- echo "Making IDE5 Secondary Devices hdl's"; \
- mknod /dev/hdl b 57 64; \
- mknod /dev/hdl1 b 57 65; \
- mknod /dev/hdl2 b 57 66; \
- mknod /dev/hdl3 b 57 67; \
- mknod /dev/hdl4 b 57 68; \
- mknod /dev/hdl5 b 57 69; \
- mknod /dev/hdl6 b 57 70; \
- mknod /dev/hdl7 b 57 71; \
- mknod /dev/hdl8 b 57 72; \
- mknod /dev/hdl9 b 57 73; \
- mknod /dev/hdl10 b 57 74; \
- mknod /dev/hdl11 b 57 75; \
- mknod /dev/hdl12 b 57 76; \
- mknod /dev/hdl13 b 57 77; \
- mknod /dev/hdl14 b 57 78; \
- mknod /dev/hdl15 b 57 79; \
- mknod /dev/hdl16 b 57 80; \
- chown root.disk /dev/hdl*; \
- chmod 660 /dev/hdl*; \
-fi
-
diff --git a/drivers/block/MAKEDEV-IDE67 b/drivers/block/MAKEDEV-IDE67
deleted file mode 100644
index 27728be28..000000000
--- a/drivers/block/MAKEDEV-IDE67
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/bin/sh
-#
-# Andre Hedrick <hedrick@astro.dyer.vanderbilt.edu>
-#
-# The song goes, "I did it the hard way..........."
-#
-
-if [ ! -f /dev/hdm ]; then \
- echo "Making IDE6 Primary Devices hdm's"; \
- mknod /dev/hdm b 88 0; \
- mknod /dev/hdm1 b 88 1; \
- mknod /dev/hdm2 b 88 2; \
- mknod /dev/hdm3 b 88 3; \
- mknod /dev/hdm4 b 88 4; \
- mknod /dev/hdm5 b 88 5; \
- mknod /dev/hdm6 b 88 6; \
- mknod /dev/hdm7 b 88 7; \
- mknod /dev/hdm8 b 88 8; \
- mknod /dev/hdm9 b 88 9; \
- mknod /dev/hdm10 b 88 10; \
- mknod /dev/hdm11 b 88 11; \
- mknod /dev/hdm12 b 88 12; \
- mknod /dev/hdm13 b 88 13; \
- mknod /dev/hdm14 b 88 14; \
- mknod /dev/hdm15 b 88 15; \
- mknod /dev/hdm16 b 88 16; \
- chown root.disk /dev/hdm*; \
- chmod 660 /dev/hdm*; \
-fi
-
-if [ ! -f /dev/hdn ]; then \
- echo "Making IDE6 Secondary Devices hdn's"; \
- mknod /dev/hdn b 88 64; \
- mknod /dev/hdn1 b 88 65; \
- mknod /dev/hdn2 b 88 66; \
- mknod /dev/hdn3 b 88 67; \
- mknod /dev/hdn4 b 88 68; \
- mknod /dev/hdn5 b 88 69; \
- mknod /dev/hdn6 b 88 70; \
- mknod /dev/hdn7 b 88 71; \
- mknod /dev/hdn8 b 88 72; \
- mknod /dev/hdn9 b 88 73; \
- mknod /dev/hdn10 b 88 74; \
- mknod /dev/hdn11 b 88 75; \
- mknod /dev/hdn12 b 88 76; \
- mknod /dev/hdn13 b 88 77; \
- mknod /dev/hdn14 b 88 78; \
- mknod /dev/hdn15 b 88 79; \
- mknod /dev/hdn16 b 88 80; \
- chown root.disk /dev/hdn*; \
- chmod 660 /dev/hdn*; \
-fi
-
-if [ ! -f /dev/hdo ]; then \
- echo "Making IDE7 Primary Devices hdo's"; \
- mknod /dev/hdo b 89 0; \
- mknod /dev/hdo1 b 89 1; \
- mknod /dev/hdo2 b 89 2; \
- mknod /dev/hdo3 b 89 3; \
- mknod /dev/hdo4 b 89 4; \
- mknod /dev/hdo5 b 89 5; \
- mknod /dev/hdo6 b 89 6; \
- mknod /dev/hdo7 b 89 7; \
- mknod /dev/hdo8 b 89 8; \
- mknod /dev/hdo9 b 89 9; \
- mknod /dev/hdo10 b 89 10; \
- mknod /dev/hdo11 b 89 11; \
- mknod /dev/hdo12 b 89 12; \
- mknod /dev/hdo13 b 89 13; \
- mknod /dev/hdo14 b 89 14; \
- mknod /dev/hdo15 b 89 15; \
- mknod /dev/hdo16 b 89 16; \
- chown root.disk /dev/hdo*; \
- chmod 660 /dev/hdo*; \
-fi
-
-if [ ! -f /dev/hdp ]; then \
- echo "Making IDE7 Secondary Devices hdp's"; \
- mknod /dev/hdp b 89 64; \
- mknod /dev/hdp1 b 89 65; \
- mknod /dev/hdp2 b 89 66; \
- mknod /dev/hdp3 b 89 67; \
- mknod /dev/hdp4 b 89 68; \
- mknod /dev/hdp5 b 89 69; \
- mknod /dev/hdp6 b 89 70; \
- mknod /dev/hdp7 b 89 71; \
- mknod /dev/hdp8 b 89 72; \
- mknod /dev/hdp9 b 89 73; \
- mknod /dev/hdp10 b 89 74; \
- mknod /dev/hdp11 b 89 75; \
- mknod /dev/hdp12 b 89 76; \
- mknod /dev/hdp13 b 89 77; \
- mknod /dev/hdp14 b 89 78; \
- mknod /dev/hdp15 b 89 79; \
- mknod /dev/hdp16 b 89 80; \
- chown root.disk /dev/hdp*; \
- chmod 660 /dev/hdp*; \
-fi
-
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index bb03a3200..abc2242dc 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -20,7 +20,7 @@ ALL_SUB_DIRS := $(SUB_DIRS) paride
L_TARGET := block.a
-L_OBJS := genhd.o
+L_OBJS := genhd.o cmos-probe.o
M_OBJS :=
MOD_LIST_NAME := BLOCK_MODULES
LX_OBJS := ll_rw_blk.o blkpg.o
@@ -54,6 +54,10 @@ else
endif
endif
+ifeq ($(CONFIG_BLK_DEV_SWIM_IOP),y)
+ L_OBJS += swim_iop.o
+endif
+
ifeq ($(CONFIG_ATARI_ACSI),y)
LX_OBJS += acsi.o
else
@@ -94,116 +98,140 @@ else
endif
endif
-ifeq ($(CONFIG_BLK_DEV_HD),y)
-L_OBJS += hd.o
+#
+# IDE-STUFF
+#
+
+ifeq ($(CONFIG_BLK_DEV_AEC6210),y)
+IDE_OBJS += aec6210.o
endif
-ifeq ($(CONFIG_BLK_DEV_RZ1000),y)
-IDE_OBJS += rz1000.o
+ifeq ($(CONFIG_BLK_DEV_ALI14XX),y)
+IDE_OBJS += ali14xx.o
endif
-ifeq ($(CONFIG_BLK_DEV_CMD640),y)
-IDE_OBJS += cmd640.o
+ifeq ($(CONFIG_BLK_DEV_ALI15X3),y)
+IDE_OBJS += alim15x3.o
endif
-ifeq ($(CONFIG_BLK_DEV_IDE_PMAC),y)
-IDE_OBJS += ide-pmac.o
+ifeq ($(CONFIG_BLK_DEV_BUDDHA),y)
+IDE_OBJS += buddha.o
endif
-ifeq ($(CONFIG_BLK_DEV_IDEPCI),y)
-IDE_OBJS += ide-pci.o
+ifeq ($(CONFIG_BLK_DEV_CMD640),y)
+IDE_OBJS += cmd640.o
endif
-ifeq ($(CONFIG_BLK_DEV_IDEDMA),y)
-IDE_OBJS += ide-dma.o
+ifeq ($(CONFIG_BLK_DEV_CMD646),y)
+IDE_OBJS += cmd646.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_CY82C693),y)
+IDE_OBJS += cy82c693.o
endif
ifeq ($(CONFIG_BLK_DEV_DTC2278),y)
IDE_OBJS += dtc2278.o
endif
-ifeq ($(CONFIG_BLK_DEV_HT6560B),y)
-IDE_OBJS += ht6560b.o
+ifeq ($(CONFIG_BLK_DEV_FALCON_IDE),y)
+IDE_OBJS += falconide.o
endif
-ifeq ($(CONFIG_BLK_DEV_QD6580),y)
-IDE_OBJS += qd6580.o
+ifeq ($(CONFIG_BLK_DEV_GAYLE),y)
+IDE_OBJS += gayle.o
endif
-ifeq ($(CONFIG_BLK_DEV_UMC8672),y)
-IDE_OBJS += umc8672.o
+ifeq ($(CONFIG_BLK_DEV_Q40IDE),y)
+IDE_OBJS += q40ide.o
endif
-ifeq ($(CONFIG_BLK_DEV_ALI14XX),y)
-IDE_OBJS += ali14xx.o
+ifeq ($(CONFIG_BLK_DEV_HD),y)
+L_OBJS += hd.o
endif
-ifeq ($(CONFIG_BLK_DEV_PDC4030),y)
-IDE_OBJS += pdc4030.o
+ifeq ($(CONFIG_BLK_DEV_HPT34X),y)
+IDE_OBJS += hpt34x.o
endif
-ifeq ($(CONFIG_BLK_DEV_TRM290),y)
-IDE_OBJS += trm290.o
+ifeq ($(CONFIG_BLK_DEV_HPT366),y)
+IDE_OBJS += hpt366.o
endif
-ifeq ($(CONFIG_BLK_DEV_OPTI621),y)
-IDE_OBJS += opti621.o
+ifeq ($(CONFIG_BLK_DEV_HT6560B),y)
+IDE_OBJS += ht6560b.o
endif
-ifeq ($(CONFIG_BLK_DEV_NS87415),y)
-IDE_OBJS += ns87415.o
+ifeq ($(CONFIG_BLK_DEV_IDE_ICSIDE),y)
+IDE_OBJS += icside.o
endif
-ifeq ($(CONFIG_BLK_DEV_VIA82C586),y)
-IDE_OBJS += via82c586.o
+ifeq ($(CONFIG_BLK_DEV_IDEDMA),y)
+IDE_OBJS += ide-dma.o
endif
-ifeq ($(CONFIG_BLK_DEV_GAYLE),y)
-IDE_OBJS += gayle.o
+ifeq ($(CONFIG_BLK_DEV_IDEPCI),y)
+IDE_OBJS += ide-pci.o
endif
-ifeq ($(CONFIG_BLK_DEV_FALCON_IDE),y)
-IDE_OBJS += falconide.o
+ifeq ($(CONFIG_BLK_DEV_IDE_PMAC),y)
+IDE_OBJS += ide-pmac.o
endif
ifeq ($(CONFIG_BLK_DEV_MAC_IDE),y)
IDE_OBJS += macide.o
endif
-ifeq ($(CONFIG_BLK_DEV_BUDDHA),y)
-IDE_OBJS += buddha.o
-endif
-
-ifeq ($(CONFIG_BLK_DEV_CMD646),y)
-IDE_OBJS += cmd646.o
+ifeq ($(CONFIG_BLK_DEV_NS87415),y)
+IDE_OBJS += ns87415.o
endif
-ifeq ($(CONFIG_BLK_DEV_SL82C105),y)
-IDE_OBJS += sl82c105.o
+ifeq ($(CONFIG_BLK_DEV_OPTI621),y)
+IDE_OBJS += opti621.o
endif
-ifeq ($(CONFIG_BLK_DEV_ALI15X3),y)
-IDE_OBJS += alim15x3.o
+ifeq ($(CONFIG_BLK_DEV_PDC202XX),y)
+IDE_OBJS += pdc202xx.o
endif
-ifeq ($(CONFIG_BLK_DEV_CY82C693),y)
-IDE_OBJS += cy82c693.o
+ifeq ($(CONFIG_BLK_DEV_PDC4030),y)
+IDE_OBJS += pdc4030.o
endif
ifeq ($(CONFIG_BLK_DEV_PIIX),y)
IDE_OBJS += piix.o
endif
-ifeq ($(CONFIG_BLK_DEV_PDC202XX),y)
-IDE_OBJS += pdc202xx.o
+ifeq ($(CONFIG_BLK_DEV_QD6580),y)
+IDE_OBJS += qd6580.o
endif
-ifeq ($(CONFIG_BLK_DEV_AEC6210),y)
-IDE_OBJS += aec6210.o
+ifeq ($(CONFIG_BLK_DEV_IDE_RAPIDE),y)
+IDE_OBJS += rapide.o
endif
-ifeq ($(CONFIG_BLK_DEV_HPT34X),y)
-IDE_OBJS += hpt34x.o
+ifeq ($(CONFIG_BLK_DEV_RZ1000),y)
+IDE_OBJS += rz1000.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_SIS5513),y)
+IDE_OBJS += sis5513.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_SL82C105),y)
+IDE_OBJS += sl82c105.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_TRM290),y)
+IDE_OBJS += trm290.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_UMC8672),y)
+IDE_OBJS += umc8672.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_VIA82C586),y)
+IDE_OBJS += via82c586.o
endif
### if CONFIG_BLK_DEV_IDE is n, IDE_OBJS will be ignored
@@ -282,6 +310,14 @@ else
endif
endif
+ifeq ($(CONFIG_BLK_DEV_DAC960),y)
+LX_OBJS += DAC960.o
+else
+ ifeq ($(CONFIG_BLK_DEV_DAC960),m)
+ MX_OBJS += DAC960.o
+ endif
+endif
+
ifeq ($(CONFIG_BLK_DEV_MD),y)
LX_OBJS += md.o
diff --git a/drivers/block/README.buddha b/drivers/block/README.buddha
new file mode 100644
index 000000000..d3b7bc73f
--- /dev/null
+++ b/drivers/block/README.buddha
@@ -0,0 +1,210 @@
+
+The Amiga Buddha and Catweasel IDE Driver (part of ide.c) was written by
+Geert Uytterhoeven based on the following specifications:
+
+------------------------------------------------------------------------
+
+Register map of the Buddha IDE controller and the
+Buddha-part of the Catweasel Zorro-II version
+
+The Autoconfiguration has been implemented just as Commodore
+described in their manuals, no tricks have been used (for
+example leaving some address lines out of the equations...).
+If you want to configure the board yourself (for example let
+a Linux kernel configure the card), look at the Commodore
+Docs. Reading the nibbles should give this information:
+
+Vendor number: 4626 ($1212)
+product number: 0 (42 for Catweasel Z-II)
+Serial number: 0
+Rom-vector: $1000
+
+The card should be a Z-II board, size 64K, not for freemem
+list, Rom-Vektor is valid, no second Autoconfig-board on the
+same card, no space preferrence, supports "Shutup_forever".
+
+Setting the base address should be done in two steps, just
+as the Amiga Kickstart does: The lower nibble of the 8-Bit
+address is written to $4a, then the whole Byte is written to
+$48, while it doesn't matter how often you're writing to $4a
+as long as $48 is not touched. After $48 has been written,
+the whole card disappears from $e8 and is mapped to the new
+addrress just written. Make shure $4a is written befor $48,
+otherwise your chance is only 1:16 to find the board :-).
+
+The local memory-map is even active when mapped to $e8:
+
+$0-$7e Autokonfig-space, see Z-II docs.
+
+$80-$7fd reserved
+
+$7fe Speed-select Register: Read & Write
+ (description see further down)
+
+$800-$8ff IDE-Select 0 (Port 0, Register set 0)
+
+$900-$9ff IDE-Select 1 (Port 0, Register set 1)
+
+$a00-$aff IDE-Select 2 (Port 1, Register set 0)
+
+$b00-$bff IDE-Select 3 (Port 1, Register set 1)
+
+$c00-$cff IDE-Select 4 (Port 2, Register set 0,
+ Catweasel only!)
+
+$d00-$dff IDE-Select 5 (Port 3, Register set 1,
+ Catweasel only!)
+
+$e00-$eff local expansion port, on Catweasel Z-II the
+ Catweasel registers are also mapped here.
+ Never touch, use multidisk.device!
+
+$f00 read only, Byte-access: Bit 7 shows the
+ level of the IRQ-line of IDE port 0.
+
+$f01-$f3f mirror of $f00
+
+$f40 read only, Byte-access: Bit 7 shows the
+ level of the IRQ-line of IDE port 1.
+
+$f41-$f7f mirror of $f40
+
+$f80 read only, Byte-access: Bit 7 shows the
+ level of the IRQ-line of IDE port 2.
+ (Catweasel only!)
+
+$f81-$fbf mirror of $f80
+
+$fc0 write-only: Writing any value to this
+ register enables IRQs to be passed from the
+ IDE ports to the Zorro bus. This mechanism
+ has been implemented to be compatible with
+ harddisks that are either defective or have
+ a buggy firmware and pull the IRQ line up
+ while starting up. If interrupts would
+ always be passed to the bus, the computer
+ might not start up. Once enabled, this flag
+ can not be disabled again. The level of the
+ flag can not be determined by software
+ (what for? Write to me if it's necessary!).
+
+$fc1-$fff mirror of $fc0
+
+$1000-$ffff Buddha-Rom with offset $1000 in the rom
+ chip. The addresses $0 to $fff of the rom
+ chip cannot be read. Rom is Byte-wide and
+ mapped to even addresses.
+
+The IDE ports issue an INT2. You can read the level of the
+IRQ-lines of the IDE-ports by reading from the three (two
+for Buddha-only) registers $f00, $f40 and $f80. This way
+more than one I/O request can be handled and you can easily
+determine what driver has to serve the INT2. Buddha and
+Catweasel expansion boards can issue an INT6. A seperate
+memory map is available for the I/O module and the sysop's
+I/O module.
+
+The IDE ports are fed by the address lines A2 to A4, just as
+the Amiga 1200 and Amiga 4000 IDE ports are. This way
+existing drivers can be easily ported to Buddha. A move.l
+polls two words out of the same address of IDE port since
+every word is mirrored once. movem is not possible, but
+it's not necessary either, because you can only speedup
+68000 systems with this technique. A 68020 system with
+fastmem is faster with move.l.
+
+If you're using the mirrored registers of the IDE-ports with
+A6=1, the Buddha doesn't care about the speed that you have
+selected in the speed register (see further down). With
+A6=1 (for example $840 for port 0, register set 0), a 780ns
+access is being made. These registers should be used for a
+command access to the harddisk/CD-Rom, since command
+accesses are Byte-wide and have to be made slower according
+to the ATA-X3T9 manual.
+
+Now for the speed-register: The register is byte-wide, and
+only the upper three bits are used (Bits 7 to 5). Bit 4
+must always be set to 1 to be compatible with later Buddha
+versions (if I'll ever update this one). I presume that
+I'll never use the lower four bits, but they have to be set
+to 1 by definition.
+ The values in this table have to be shifted 5 bits to the
+left and or'd with $1f (this sets the lower 5 bits).
+
+All the timings have in common: Select and IOR/IOW rise at
+the same time. IOR and IOW have a propagation delay of
+about 30ns to the clocks on the Zorro bus, that's why the
+values are no multiple of 71. One clock-cycle is 71ns long
+(exactly 70,5 at 14,18 Mhz on PAL systems).
+
+value 0 (Default after reset)
+
+497ns Select (7 clock cycles) , IOR/IOW after 172ns (2 clock cycles)
+(same timing as the Amiga 1200 does on it's IDE port without
+accelerator card)
+
+value 1
+
+639ns Select (9 clock cycles), IOR/IOW after 243ns (3 clock cycles)
+
+value 2
+
+781ns Select (11 clock cycles), IOR/IOW after 314ns (4 clock cycles)
+
+value 3
+
+355ns Select (5 clock cycles), IOR/IOW after 101ns (1 clock cycle)
+
+value 4
+
+355ns Select (5 clock cycles), IOR/IOW after 172ns (2 clock cycles)
+
+value 5
+
+355ns Select (5 clock cycles), IOR/IOW after 243ns (3 clock cycles)
+
+value 6
+
+1065ns Select (15 clock cycles), IOR/IOW after 314ns (4 clock cycles)
+
+value 7
+
+355ns Select, (5 clock cycles), IOR/IOW after 101ns (1 clock cycle)
+
+When accessing IDE registers with A6=1 (for example $84x),
+the timing will always be mode 0 8-bit compatible, no matter
+what you have selected in the speed register:
+
+781ns select, IOR/IOW after 4 clock cycles (=314ns) aktive.
+
+All the timings with a very short select-signal (the 355ns
+fast accesses) depend on the accelerator card used in the
+system: Sometimes two more clock cycles are inserted by the
+bus interface, making the whole access 497ns long. This
+doesn't affect the reliability of the controller nor the
+performance of the card, since this doesn't happen very
+often.
+
+All the timings are calculated and only confirmed by
+measurements that allowed me to count the clock cycles. If
+the system is clocked by an oscillator other than 28,37516
+Mhz (for example the NTSC-frequency 28,63636 Mhz), each
+clock cycle is shortened to a bit less than 70ns (not worth
+mentioning). You could think of a small performance boost
+by overclocking the system, but you would either need a
+multisync monitor, or a graphics card, and your internal
+diskdrive would go crazy, that's why you shouldn't tune your
+Amiga this way.
+
+Giving you the possibility to write software that is
+compatible with both the Buddha and the Catweasel Z-II, The
+Buddha acts just like a Catweasel Z-II with no device
+connected to the third IDE-port. The IRQ-register $f80
+always shows a "no IRQ here" on the Buddha, and accesses to
+the third IDE port are going into data's Nirwana on the
+Buddha.
+
+ Jens Schönfeld february 19th, 1997
+ updated may 27th, 1997
+ eMail: sysop@nostlgic.tng.oche.de
+
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index ea0e989f8..80aa52472 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -253,17 +253,8 @@ static int CurrentNSect;
static char *CurrentBuffer;
-#define SET_TIMER() \
- do { \
- del_timer( &acsi_timer ); \
- acsi_timer.expires = jiffies + ACSI_TIMEOUT; \
- add_timer( &acsi_timer ); \
- } while(0)
-
-#define CLEAR_TIMER() \
- do { \
- del_timer( &acsi_timer ); \
- } while(0)
+#define SET_TIMER() mod_timer(&acsi_timer, jiffies + ACSI_TIMEOUT)
+#define CLEAR_TIMER() del_timer(&acsi_timer)
static unsigned long STramMask;
#define STRAM_ADDR(a) (((a) & STramMask) == 0)
@@ -425,8 +416,8 @@ int acsi_wait_for_IRQ( unsigned timeout )
{
if (INT_LEVEL < 6) {
- unsigned long maxjif;
- for( maxjif = jiffies + timeout; time_before(jiffies, maxjif); )
+ unsigned long maxjif = jiffies + timeout;
+ while (time_before(jiffies, maxjif))
if (!(mfp.par_dt_reg & 0x20)) return( 1 );
}
else {
@@ -442,8 +433,8 @@ int acsi_wait_for_noIRQ( unsigned timeout )
{
if (INT_LEVEL < 6) {
- unsigned long maxjif;
- for( maxjif = jiffies + timeout; time_before(jiffies, maxjif); )
+ unsigned long maxjif = jiffies + timeout;
+ while (time_before(jiffies, maxjif))
if (mfp.par_dt_reg & 0x20) return( 1 );
}
else {
@@ -502,7 +493,7 @@ static int acsicmd_dma( const char *cmd, char *buffer, int blocks, int rwflag, i
#endif
rwflag = rwflag ? 0x100 : 0;
- paddr = VTOP( buffer );
+ paddr = virt_to_phys( buffer );
acsi_delay_end(COMMAND_DELAY);
DISABLE_IRQ();
@@ -610,7 +601,7 @@ static int acsi_reqsense( char *buffer, int targ, int lun)
if (!acsicmd_nodma( reqsense_cmd, 0 )) return( 0 );
if (!acsi_wait_for_IRQ( 10 )) return( 0 );
acsi_getstatus();
- dma_cache_maintenance( VTOP(buffer), 16, 0 );
+ dma_cache_maintenance( virt_to_phys(buffer), 16, 0 );
return( 1 );
}
@@ -809,7 +800,7 @@ static void read_intr( void )
return;
}
- dma_cache_maintenance( VTOP(CurrentBuffer), CurrentNSect*512, 0 );
+ dma_cache_maintenance( virt_to_phys(CurrentBuffer), CurrentNSect*512, 0 );
if (CurrentBuffer == acsi_buffer)
copy_from_acsibuffer();
@@ -1030,7 +1021,7 @@ static void redo_acsi_request( void )
* consecutive buffers and thus can be done with a single command.
*/
buffer = CURRENT->buffer;
- pbuffer = VTOP(buffer);
+ pbuffer = virt_to_phys(buffer);
nsect = CURRENT->current_nr_sectors;
CurrentNReq = 1;
@@ -1052,7 +1043,7 @@ static void redo_acsi_request( void )
unsigned long pendadr, pnewadr;
pendadr = pbuffer + nsect*512;
while( (bh = bh->b_reqnext) ) {
- pnewadr = VTOP(bh->b_data);
+ pnewadr = virt_to_phys(bh->b_data);
if (!STRAM_ADDR(pnewadr) || pendadr != pnewadr) break;
nsect += bh->b_size >> 9;
pendadr = pnewadr + bh->b_size;
@@ -1814,7 +1805,7 @@ int acsi_init( void )
unregister_blkdev( MAJOR_NR, "ad" );
return -ENOMEM;
}
- phys_acsi_buffer = VTOP( acsi_buffer );
+ phys_acsi_buffer = virt_to_phys( acsi_buffer );
STramMask = ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000 : 0xff000000;
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c
index b341c39c4..d718075e2 100644
--- a/drivers/block/acsi_slm.c
+++ b/drivers/block/acsi_slm.c
@@ -413,8 +413,8 @@ static void start_print( int device )
CMDSET_TARG_LUN( slmprint_cmd, sip->target, sip->lun );
cmd = slmprint_cmd;
- paddr = VTOP( SLMBuffer );
- dma_cache_maintenance( paddr, VTOP(BufferP)-paddr, 1 );
+ paddr = virt_to_phys( SLMBuffer );
+ dma_cache_maintenance( paddr, virt_to_phys(BufferP)-paddr, 1 );
DISABLE_IRQ();
/* Low on A1 */
@@ -466,7 +466,7 @@ static void slm_interrupt(int irc, void *data, struct pt_regs *fp)
addr = get_dma_addr();
stat = acsi_getstatus();
SLMError = (stat < 0) ? SLMSTAT_ACSITO :
- (addr < VTOP(BufferP)) ? SLMSTAT_NOTALL :
+ (addr < virt_to_phys(BufferP)) ? SLMSTAT_NOTALL :
stat;
dma_wd.dma_mode_status = 0x80;
diff --git a/drivers/block/aec6210.c b/drivers/block/aec6210.c
index 03ef37c90..c52d8450d 100644
--- a/drivers/block/aec6210.c
+++ b/drivers/block/aec6210.c
@@ -1,7 +1,7 @@
/*
- * linux/drivers/block/aec6210.c Version 0.01 Nov 17, 1998
+ * linux/drivers/block/aec6210.c Version 0.01 Nov 17, 1998
*
- * Copyright (C) 1998 Andre Hedrick (hedrick@astro.dyer.vanderbilt.edu)
+ * Copyright (C) 1998-99 Andre Hedrick
*
* pio 0 :: 40: 00 07 00 00 00 00 00 00 02 07 a6 04 00 02 00 02
* pio 1 :: 40: 0a 07 00 00 00 00 00 00 02 07 a6 05 00 02 00 02
@@ -31,7 +31,6 @@
* NO-Devices
* 40: 00 00 00 00 00 00 00 00 02 05 a6 00 00 02 00 02
* 50: ff ff ff ff 00 06 00 00 00 00 00 00 00 00 00 00
-
*/
#include <linux/types.h>
@@ -51,13 +50,11 @@
#include <asm/io.h>
#include <asm/irq.h>
-__initfunc(unsigned int pci_init_aec6210 (struct pci_dev *dev, const char *name))
+unsigned int __init pci_init_aec6210 (struct pci_dev *dev, const char *name)
{
- if (dev->rom_address) {
- pci_write_config_dword(dev, PCI_ROM_ADDRESS,
- dev->rom_address | PCI_ROM_ADDRESS_ENABLE);
- printk("%s: ROM enabled at 0x%08lx\n",
- name, dev->rom_address);
+ if (dev->resource[PCI_ROM_RESOURCE].start) {
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
+ printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start);
}
return dev->irq;
}
diff --git a/drivers/block/alim15x3.c b/drivers/block/alim15x3.c
index 4ea590fa2..b7a0a5c4f 100644
--- a/drivers/block/alim15x3.c
+++ b/drivers/block/alim15x3.c
@@ -110,7 +110,7 @@ static void ali15x3_tune_drive (ide_drive_t *drive, byte pio)
}
-__initfunc(unsigned int pci_init_ali15x3 (struct pci_dev *dev, const char *name))
+unsigned int __init pci_init_ali15x3 (struct pci_dev *dev, const char *name)
{
byte confreg0 = 0, confreg1 =0, progif = 0;
int errors = 0;
@@ -194,7 +194,7 @@ int ali15x3_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
return ide_dmaproc(func, drive); /* use standard DMA stuff */
}
-__initfunc(void ide_init_ali15x3 (ide_hwif_t *hwif))
+void __init ide_init_ali15x3 (ide_hwif_t *hwif)
{
struct pci_dev *dev;
byte ideic, inmir, iderev;
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 8e3459d3f..b27d12095 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -135,10 +135,10 @@ MODULE_PARM(fd_def_df0,"l");
static struct fd_drive_type drive_types[] = {
/* code name tr he rdsz wrsz sm pc1 pc2 sd st st*/
/* warning: times are now in milliseconds (ms) */
- { FD_DD_3, "DD 3.5", 80, 2, 14716, 13630, 1, 80,161, 3, 18, 1},
- { FD_HD_3, "HD 3.5", 80, 2, 28344, 27258, 2, 80,161, 3, 18, 1},
- { FD_DD_5, "DD 5.25", 40, 2, 14716, 13630, 1, 40, 81, 6, 30, 2},
- { FD_NODRIVE, "No Drive", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+{ FD_DD_3, "DD 3.5", 80, 2, 14716, 13630, 1, 80,161, 3, 18, 1},
+{ FD_HD_3, "HD 3.5", 80, 2, 28344, 27258, 2, 80,161, 3, 18, 1},
+{ FD_DD_5, "DD 5.25", 40, 2, 14716, 13630, 1, 40, 81, 6, 30, 2},
+{ FD_NODRIVE, "No Drive", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
static int num_dr_types = sizeof(drive_types) / sizeof(drive_types[0]);
@@ -150,8 +150,8 @@ static int floppy_blocksizes[256]={0,};
static int amiga_read(int), dos_read(int);
static void amiga_write(int), dos_write(int);
static struct fd_data_type data_types[] = {
- { "Amiga", 11 , amiga_read, amiga_write},
- { "MS-Dos", 9, dos_read, dos_write}
+ { "Amiga", 11 , amiga_read, amiga_write},
+ { "MS-Dos", 9, dos_read, dos_write}
};
/* current info on each unit */
@@ -189,8 +189,8 @@ static DECLARE_WAIT_QUEUE_HEAD(wait_fd_block);
/* MS-Dos MFM Coding tables (should go quick and easy) */
static unsigned char mfmencode[16]={
- 0x2a, 0x29, 0x24, 0x25, 0x12, 0x11, 0x14, 0x15,
- 0x4a, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55
+ 0x2a, 0x29, 0x24, 0x25, 0x12, 0x11, 0x14, 0x15,
+ 0x4a, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55
};
static unsigned char mfmdecode[128];
@@ -231,29 +231,29 @@ static int fd_device[4] = { 0,0,0,0 };
static void ms_isr(int irq, void *dummy, struct pt_regs *fp)
{
-ms_busy = -1;
-wake_up(&ms_wait);
+ ms_busy = -1;
+ wake_up(&ms_wait);
}
/* all waits are queued up
A more generic routine would do a schedule a la timer.device */
static void ms_delay(int ms)
{
- unsigned long flags;
- int ticks;
- if (ms > 0) {
- save_flags(flags);
- cli();
- while (ms_busy == 0)
- sleep_on(&ms_wait);
- ms_busy = 0;
- restore_flags(flags);
- ticks = MS_TICKS*ms-1;
- ciaa.tblo=ticks%256;
- ciaa.tbhi=ticks/256;
- ciaa.crb=0x19; /*count eclock, force load, one-shoot, start */
- sleep_on(&ms_wait);
- }
+ unsigned long flags;
+ int ticks;
+ if (ms > 0) {
+ save_flags(flags);
+ cli();
+ while (ms_busy == 0)
+ sleep_on(&ms_wait);
+ ms_busy = 0;
+ restore_flags(flags);
+ ticks = MS_TICKS*ms-1;
+ ciaa.tblo=ticks%256;
+ ciaa.tbhi=ticks/256;
+ ciaa.crb=0x19; /*count eclock, force load, one-shoot, start */
+ sleep_on(&ms_wait);
+ }
}
/* Hardware semaphore */
@@ -267,33 +267,33 @@ static inline int try_fdc(int drive)
static void get_fdc(int drive)
{
-unsigned long flags;
+ unsigned long flags;
- drive &= 3;
+ drive &= 3;
#ifdef DEBUG
- printk("get_fdc: drive %d fdc_busy %d fdc_nested %d\n",drive,fdc_busy,fdc_nested);
+ printk("get_fdc: drive %d fdc_busy %d fdc_nested %d\n",drive,fdc_busy,fdc_nested);
#endif
- save_flags(flags);
- cli();
- while (!try_fdc(drive))
- sleep_on(&fdc_wait);
- fdc_busy = drive;
- fdc_nested++;
- restore_flags(flags);
+ save_flags(flags);
+ cli();
+ while (!try_fdc(drive))
+ sleep_on(&fdc_wait);
+ fdc_busy = drive;
+ fdc_nested++;
+ restore_flags(flags);
}
static inline void rel_fdc(void)
{
#ifdef DEBUG
- if (fdc_nested == 0)
- printk("fd: unmatched rel_fdc\n");
- printk("rel_fdc: fdc_busy %d fdc_nested %d\n",fdc_busy,fdc_nested);
+ if (fdc_nested == 0)
+ printk("fd: unmatched rel_fdc\n");
+ printk("rel_fdc: fdc_busy %d fdc_nested %d\n",fdc_busy,fdc_nested);
#endif
- fdc_nested--;
- if (fdc_nested == 0) {
- fdc_busy = -1;
- wake_up(&fdc_wait);
- }
+ fdc_nested--;
+ if (fdc_nested == 0) {
+ fdc_busy = -1;
+ wake_up(&fdc_wait);
+ }
}
static void fd_select (int drive)
@@ -395,9 +395,9 @@ static int fd_motor_on(int nr)
static void fd_motor_off(unsigned long drive)
{
-long calledfromint;
+ long calledfromint;
#ifdef MODULE
-long decusecount;
+ long decusecount;
decusecount = drive & 0x40000000;
#endif
@@ -416,18 +416,18 @@ long decusecount;
#ifdef MODULE
/*
-this is the last interrupt for any drive access, happens after
-release (from floppy_off). So we have to wait until now to decrease
-the use count.
+ this is the last interrupt for any drive access, happens after
+ release (from floppy_off). So we have to wait until now to decrease
+ the use count.
*/
- if (decusecount)
- MOD_DEC_USE_COUNT;
+ if (decusecount)
+ MOD_DEC_USE_COUNT;
#endif
}
static void floppy_off (unsigned int nr)
{
-int drive;
+ int drive;
drive = nr & 3;
del_timer(motor_off_timer + drive);
@@ -588,29 +588,29 @@ static unsigned long fd_get_drive_id(int drive)
* type.
*/
if(drive == 0 && id == FD_NODRIVE)
- {
+ {
id = fd_def_df0;
printk(KERN_NOTICE "fd: drive 0 didn't identify, setting default %08lx\n", (ulong)fd_def_df0);
- }
+ }
/* return the ID value */
return (id);
}
static void fd_block_done(int irq, void *dummy, struct pt_regs *fp)
{
- if (block_flag)
- custom.dsklen = 0x4000;
-
- if (block_flag == 2) { /* writing */
- writepending = 2;
- post_write_timer.expires = jiffies + 1; /* at least 2 ms */
- post_write_timer.data = selected;
- add_timer(&post_write_timer);
- }
- else { /* reading */
- block_flag = 0;
- wake_up (&wait_fd_block);
- }
+ if (block_flag)
+ custom.dsklen = 0x4000;
+
+ if (block_flag == 2) { /* writing */
+ writepending = 2;
+ post_write_timer.expires = jiffies + 1; /* at least 2 ms */
+ post_write_timer.data = selected;
+ add_timer(&post_write_timer);
+ }
+ else { /* reading */
+ block_flag = 0;
+ wake_up (&wait_fd_block);
+ }
}
static void raw_read(int drive)
@@ -680,17 +680,17 @@ static int raw_write(int drive)
static void post_write (unsigned long drive)
{
#ifdef DEBUG
- printk("post_write for drive %ld\n",drive);
+ printk("post_write for drive %ld\n",drive);
#endif
- drive &= 3;
- custom.dsklen = 0;
- block_flag = 0;
- writepending = 0;
- writefromint = 0;
- unit[drive].dirty = 0;
- wake_up(&wait_fd_block);
- fd_deselect(drive);
- rel_fdc(); /* corresponds to get_fdc() in raw_write */
+ drive &= 3;
+ custom.dsklen = 0;
+ block_flag = 0;
+ writepending = 0;
+ writefromint = 0;
+ unit[drive].dirty = 0;
+ wake_up(&wait_fd_block);
+ fd_deselect(drive);
+ rel_fdc(); /* corresponds to get_fdc() in raw_write */
}
@@ -727,7 +727,7 @@ static inline unsigned long checksum(unsigned long *addr, int len)
}
static unsigned long decode (unsigned long *data, unsigned long *raw,
- int len)
+ int len)
{
ulong *odd, *even;
@@ -822,34 +822,34 @@ static int amiga_read(int drive)
static void encode(unsigned long data, unsigned long *dest)
{
- unsigned long data2;
+ unsigned long data2;
- data &= 0x55555555;
- data2 = data ^ 0x55555555;
- data |= ((data2 >> 1) | 0x80000000) & (data2 << 1);
+ data &= 0x55555555;
+ data2 = data ^ 0x55555555;
+ data |= ((data2 >> 1) | 0x80000000) & (data2 << 1);
- if (*(dest - 1) & 0x00000001)
- data &= 0x7FFFFFFF;
+ if (*(dest - 1) & 0x00000001)
+ data &= 0x7FFFFFFF;
- *dest = data;
+ *dest = data;
}
static void encode_block(unsigned long *dest, unsigned long *src, int len)
{
- int cnt, to_cnt = 0;
- unsigned long data;
-
- /* odd bits */
- for (cnt = 0; cnt < len / 4; cnt++) {
- data = src[cnt] >> 1;
- encode(data, dest + to_cnt++);
- }
-
- /* even bits */
- for (cnt = 0; cnt < len / 4; cnt++) {
- data = src[cnt];
- encode(data, dest + to_cnt++);
- }
+ int cnt, to_cnt = 0;
+ unsigned long data;
+
+ /* odd bits */
+ for (cnt = 0; cnt < len / 4; cnt++) {
+ data = src[cnt] >> 1;
+ encode(data, dest + to_cnt++);
+ }
+
+ /* even bits */
+ for (cnt = 0; cnt < len / 4; cnt++) {
+ data = src[cnt];
+ encode(data, dest + to_cnt++);
+ }
}
static unsigned long *putsec(int disk, unsigned long *raw, int cnt)
@@ -904,15 +904,15 @@ static void amiga_write(int disk)
struct dos_header {
-unsigned char track, /* 0-80 */
- side, /* 0-1 */
- sec, /* 0-...*/
- len_desc;/* 2 */
-unsigned short crc; /* on 68000 we got an alignment problem,
- but this compiler solves it by adding silently
- adding a pad byte so data won't fit
- and this took about 3h to discover.... */
-unsigned char gap1[22]; /* for longword-alignedness (0x4e) */
+ unsigned char track, /* 0-80 */
+ side, /* 0-1 */
+ sec, /* 0-...*/
+ len_desc;/* 2 */
+ unsigned short crc; /* on 68000 we got an alignment problem,
+ but this compiler solves it by adding silently
+ adding a pad byte so data won't fit
+ and this took about 3h to discover.... */
+ unsigned char gap1[22]; /* for longword-alignedness (0x4e) */
};
/* crc routines are borrowed from the messydos-handler */
@@ -972,299 +972,308 @@ my only works was to code this from manx to C....
static ushort dos_crc(void * data_a3, int data_d0, int data_d1, int data_d3)
{
-static unsigned char CRCTable1[] = {
- 0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x81,0x91,0xa1,0xb1,0xc1,0xd1,0xe1,0xf1,
- 0x12,0x02,0x32,0x22,0x52,0x42,0x72,0x62,0x93,0x83,0xb3,0xa3,0xd3,0xc3,0xf3,0xe3,
- 0x24,0x34,0x04,0x14,0x64,0x74,0x44,0x54,0xa5,0xb5,0x85,0x95,0xe5,0xf5,0xc5,0xd5,
- 0x36,0x26,0x16,0x06,0x76,0x66,0x56,0x46,0xb7,0xa7,0x97,0x87,0xf7,0xe7,0xd7,0xc7,
- 0x48,0x58,0x68,0x78,0x08,0x18,0x28,0x38,0xc9,0xd9,0xe9,0xf9,0x89,0x99,0xa9,0xb9,
- 0x5a,0x4a,0x7a,0x6a,0x1a,0x0a,0x3a,0x2a,0xdb,0xcb,0xfb,0xeb,0x9b,0x8b,0xbb,0xab,
- 0x6c,0x7c,0x4c,0x5c,0x2c,0x3c,0x0c,0x1c,0xed,0xfd,0xcd,0xdd,0xad,0xbd,0x8d,0x9d,
- 0x7e,0x6e,0x5e,0x4e,0x3e,0x2e,0x1e,0x0e,0xff,0xef,0xdf,0xcf,0xbf,0xaf,0x9f,0x8f,
- 0x91,0x81,0xb1,0xa1,0xd1,0xc1,0xf1,0xe1,0x10,0x00,0x30,0x20,0x50,0x40,0x70,0x60,
- 0x83,0x93,0xa3,0xb3,0xc3,0xd3,0xe3,0xf3,0x02,0x12,0x22,0x32,0x42,0x52,0x62,0x72,
- 0xb5,0xa5,0x95,0x85,0xf5,0xe5,0xd5,0xc5,0x34,0x24,0x14,0x04,0x74,0x64,0x54,0x44,
- 0xa7,0xb7,0x87,0x97,0xe7,0xf7,0xc7,0xd7,0x26,0x36,0x06,0x16,0x66,0x76,0x46,0x56,
- 0xd9,0xc9,0xf9,0xe9,0x99,0x89,0xb9,0xa9,0x58,0x48,0x78,0x68,0x18,0x08,0x38,0x28,
- 0xcb,0xdb,0xeb,0xfb,0x8b,0x9b,0xab,0xbb,0x4a,0x5a,0x6a,0x7a,0x0a,0x1a,0x2a,0x3a,
- 0xfd,0xed,0xdd,0xcd,0xbd,0xad,0x9d,0x8d,0x7c,0x6c,0x5c,0x4c,0x3c,0x2c,0x1c,0x0c,
- 0xef,0xff,0xcf,0xdf,0xaf,0xbf,0x8f,0x9f,0x6e,0x7e,0x4e,0x5e,0x2e,0x3e,0x0e,0x1e
-};
-
-static unsigned char CRCTable2[] = {
- 0x00,0x21,0x42,0x63,0x84,0xa5,0xc6,0xe7,0x08,0x29,0x4a,0x6b,0x8c,0xad,0xce,0xef,
- 0x31,0x10,0x73,0x52,0xb5,0x94,0xf7,0xd6,0x39,0x18,0x7b,0x5a,0xbd,0x9c,0xff,0xde,
- 0x62,0x43,0x20,0x01,0xe6,0xc7,0xa4,0x85,0x6a,0x4b,0x28,0x09,0xee,0xcf,0xac,0x8d,
- 0x53,0x72,0x11,0x30,0xd7,0xf6,0x95,0xb4,0x5b,0x7a,0x19,0x38,0xdf,0xfe,0x9d,0xbc,
- 0xc4,0xe5,0x86,0xa7,0x40,0x61,0x02,0x23,0xcc,0xed,0x8e,0xaf,0x48,0x69,0x0a,0x2b,
- 0xf5,0xd4,0xb7,0x96,0x71,0x50,0x33,0x12,0xfd,0xdc,0xbf,0x9e,0x79,0x58,0x3b,0x1a,
- 0xa6,0x87,0xe4,0xc5,0x22,0x03,0x60,0x41,0xae,0x8f,0xec,0xcd,0x2a,0x0b,0x68,0x49,
- 0x97,0xb6,0xd5,0xf4,0x13,0x32,0x51,0x70,0x9f,0xbe,0xdd,0xfc,0x1b,0x3a,0x59,0x78,
- 0x88,0xa9,0xca,0xeb,0x0c,0x2d,0x4e,0x6f,0x80,0xa1,0xc2,0xe3,0x04,0x25,0x46,0x67,
- 0xb9,0x98,0xfb,0xda,0x3d,0x1c,0x7f,0x5e,0xb1,0x90,0xf3,0xd2,0x35,0x14,0x77,0x56,
- 0xea,0xcb,0xa8,0x89,0x6e,0x4f,0x2c,0x0d,0xe2,0xc3,0xa0,0x81,0x66,0x47,0x24,0x05,
- 0xdb,0xfa,0x99,0xb8,0x5f,0x7e,0x1d,0x3c,0xd3,0xf2,0x91,0xb0,0x57,0x76,0x15,0x34,
- 0x4c,0x6d,0x0e,0x2f,0xc8,0xe9,0x8a,0xab,0x44,0x65,0x06,0x27,0xc0,0xe1,0x82,0xa3,
- 0x7d,0x5c,0x3f,0x1e,0xf9,0xd8,0xbb,0x9a,0x75,0x54,0x37,0x16,0xf1,0xd0,0xb3,0x92,
- 0x2e,0x0f,0x6c,0x4d,0xaa,0x8b,0xe8,0xc9,0x26,0x07,0x64,0x45,0xa2,0x83,0xe0,0xc1,
- 0x1f,0x3e,0x5d,0x7c,0x9b,0xba,0xd9,0xf8,0x17,0x36,0x55,0x74,0x93,0xb2,0xd1,0xf0
-};
+ static unsigned char CRCTable1[] = {
+ 0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x81,0x91,0xa1,0xb1,0xc1,0xd1,0xe1,0xf1,
+ 0x12,0x02,0x32,0x22,0x52,0x42,0x72,0x62,0x93,0x83,0xb3,0xa3,0xd3,0xc3,0xf3,0xe3,
+ 0x24,0x34,0x04,0x14,0x64,0x74,0x44,0x54,0xa5,0xb5,0x85,0x95,0xe5,0xf5,0xc5,0xd5,
+ 0x36,0x26,0x16,0x06,0x76,0x66,0x56,0x46,0xb7,0xa7,0x97,0x87,0xf7,0xe7,0xd7,0xc7,
+ 0x48,0x58,0x68,0x78,0x08,0x18,0x28,0x38,0xc9,0xd9,0xe9,0xf9,0x89,0x99,0xa9,0xb9,
+ 0x5a,0x4a,0x7a,0x6a,0x1a,0x0a,0x3a,0x2a,0xdb,0xcb,0xfb,0xeb,0x9b,0x8b,0xbb,0xab,
+ 0x6c,0x7c,0x4c,0x5c,0x2c,0x3c,0x0c,0x1c,0xed,0xfd,0xcd,0xdd,0xad,0xbd,0x8d,0x9d,
+ 0x7e,0x6e,0x5e,0x4e,0x3e,0x2e,0x1e,0x0e,0xff,0xef,0xdf,0xcf,0xbf,0xaf,0x9f,0x8f,
+ 0x91,0x81,0xb1,0xa1,0xd1,0xc1,0xf1,0xe1,0x10,0x00,0x30,0x20,0x50,0x40,0x70,0x60,
+ 0x83,0x93,0xa3,0xb3,0xc3,0xd3,0xe3,0xf3,0x02,0x12,0x22,0x32,0x42,0x52,0x62,0x72,
+ 0xb5,0xa5,0x95,0x85,0xf5,0xe5,0xd5,0xc5,0x34,0x24,0x14,0x04,0x74,0x64,0x54,0x44,
+ 0xa7,0xb7,0x87,0x97,0xe7,0xf7,0xc7,0xd7,0x26,0x36,0x06,0x16,0x66,0x76,0x46,0x56,
+ 0xd9,0xc9,0xf9,0xe9,0x99,0x89,0xb9,0xa9,0x58,0x48,0x78,0x68,0x18,0x08,0x38,0x28,
+ 0xcb,0xdb,0xeb,0xfb,0x8b,0x9b,0xab,0xbb,0x4a,0x5a,0x6a,0x7a,0x0a,0x1a,0x2a,0x3a,
+ 0xfd,0xed,0xdd,0xcd,0xbd,0xad,0x9d,0x8d,0x7c,0x6c,0x5c,0x4c,0x3c,0x2c,0x1c,0x0c,
+ 0xef,0xff,0xcf,0xdf,0xaf,0xbf,0x8f,0x9f,0x6e,0x7e,0x4e,0x5e,0x2e,0x3e,0x0e,0x1e
+ };
+
+ static unsigned char CRCTable2[] = {
+ 0x00,0x21,0x42,0x63,0x84,0xa5,0xc6,0xe7,0x08,0x29,0x4a,0x6b,0x8c,0xad,0xce,0xef,
+ 0x31,0x10,0x73,0x52,0xb5,0x94,0xf7,0xd6,0x39,0x18,0x7b,0x5a,0xbd,0x9c,0xff,0xde,
+ 0x62,0x43,0x20,0x01,0xe6,0xc7,0xa4,0x85,0x6a,0x4b,0x28,0x09,0xee,0xcf,0xac,0x8d,
+ 0x53,0x72,0x11,0x30,0xd7,0xf6,0x95,0xb4,0x5b,0x7a,0x19,0x38,0xdf,0xfe,0x9d,0xbc,
+ 0xc4,0xe5,0x86,0xa7,0x40,0x61,0x02,0x23,0xcc,0xed,0x8e,0xaf,0x48,0x69,0x0a,0x2b,
+ 0xf5,0xd4,0xb7,0x96,0x71,0x50,0x33,0x12,0xfd,0xdc,0xbf,0x9e,0x79,0x58,0x3b,0x1a,
+ 0xa6,0x87,0xe4,0xc5,0x22,0x03,0x60,0x41,0xae,0x8f,0xec,0xcd,0x2a,0x0b,0x68,0x49,
+ 0x97,0xb6,0xd5,0xf4,0x13,0x32,0x51,0x70,0x9f,0xbe,0xdd,0xfc,0x1b,0x3a,0x59,0x78,
+ 0x88,0xa9,0xca,0xeb,0x0c,0x2d,0x4e,0x6f,0x80,0xa1,0xc2,0xe3,0x04,0x25,0x46,0x67,
+ 0xb9,0x98,0xfb,0xda,0x3d,0x1c,0x7f,0x5e,0xb1,0x90,0xf3,0xd2,0x35,0x14,0x77,0x56,
+ 0xea,0xcb,0xa8,0x89,0x6e,0x4f,0x2c,0x0d,0xe2,0xc3,0xa0,0x81,0x66,0x47,0x24,0x05,
+ 0xdb,0xfa,0x99,0xb8,0x5f,0x7e,0x1d,0x3c,0xd3,0xf2,0x91,0xb0,0x57,0x76,0x15,0x34,
+ 0x4c,0x6d,0x0e,0x2f,0xc8,0xe9,0x8a,0xab,0x44,0x65,0x06,0x27,0xc0,0xe1,0x82,0xa3,
+ 0x7d,0x5c,0x3f,0x1e,0xf9,0xd8,0xbb,0x9a,0x75,0x54,0x37,0x16,0xf1,0xd0,0xb3,0x92,
+ 0x2e,0x0f,0x6c,0x4d,0xaa,0x8b,0xe8,0xc9,0x26,0x07,0x64,0x45,0xa2,0x83,0xe0,0xc1,
+ 0x1f,0x3e,0x5d,0x7c,0x9b,0xba,0xd9,0xf8,0x17,0x36,0x55,0x74,0x93,0xb2,0xd1,0xf0
+ };
/* look at the asm-code - what looks in C a bit strange is almost as good as handmade */
-register int i;
-register unsigned char *CRCT1, *CRCT2, *data, c, crch, crcl;
-
-CRCT1=CRCTable1;
-CRCT2=CRCTable2;
-data=data_a3;
-crcl=data_d1;
-crch=data_d0;
-for (i=data_d3; i>=0; i--) {
- c = (*data++) ^ crch;
- crch = CRCT1[c] ^ crcl;
- crcl = CRCT2[c];
-}
-return (crch<<8)|crcl;
+ register int i;
+ register unsigned char *CRCT1, *CRCT2, *data, c, crch, crcl;
+
+ CRCT1=CRCTable1;
+ CRCT2=CRCTable2;
+ data=data_a3;
+ crcl=data_d1;
+ crch=data_d0;
+ for (i=data_d3; i>=0; i--) {
+ c = (*data++) ^ crch;
+ crch = CRCT1[c] ^ crcl;
+ crcl = CRCT2[c];
+ }
+ return (crch<<8)|crcl;
}
static inline ushort dos_hdr_crc (struct dos_header *hdr)
{
-return dos_crc(&(hdr->track), 0xb2, 0x30, 3); /* precomputed magic */
+ return dos_crc(&(hdr->track), 0xb2, 0x30, 3); /* precomputed magic */
}
static inline ushort dos_data_crc(unsigned char *data)
{
-return dos_crc(data, 0xe2, 0x95 ,511); /* precomputed magic */
+ return dos_crc(data, 0xe2, 0x95 ,511); /* precomputed magic */
}
static inline unsigned char dos_decode_byte(ushort word)
{
-register ushort w2;
-register unsigned char byte;
-register unsigned char *dec = mfmdecode;
-
-w2=word;
-w2>>=8;
-w2&=127;
-byte = dec[w2];
-byte <<= 4;
-w2 = word & 127;
-byte |= dec[w2];
-return byte;
+ register ushort w2;
+ register unsigned char byte;
+ register unsigned char *dec = mfmdecode;
+
+ w2=word;
+ w2>>=8;
+ w2&=127;
+ byte = dec[w2];
+ byte <<= 4;
+ w2 = word & 127;
+ byte |= dec[w2];
+ return byte;
}
static unsigned long dos_decode(unsigned char *data, unsigned short *raw, int len)
{
-int i;
+ int i;
-for (i = 0; i < len; i++)
- *data++=dos_decode_byte(*raw++);
-return ((ulong)raw);
+ for (i = 0; i < len; i++)
+ *data++=dos_decode_byte(*raw++);
+ return ((ulong)raw);
}
#ifdef DEBUG
static void dbg(unsigned long ptr)
{
- printk("raw data @%08lx: %08lx, %08lx ,%08lx, %08lx\n",ptr,
- ((ulong *)ptr)[0],((ulong *)ptr)[1],((ulong *)ptr)[2],((ulong *)ptr)[3]);
+ printk("raw data @%08lx: %08lx, %08lx ,%08lx, %08lx\n", ptr,
+ ((ulong *)ptr)[0], ((ulong *)ptr)[1],
+ ((ulong *)ptr)[2], ((ulong *)ptr)[3]);
}
#endif
static int dos_read(int drive)
{
- unsigned long end;
- unsigned long raw;
- int scnt;
- unsigned short crc,data_crc[2];
- struct dos_header hdr;
-
- drive&=3;
- raw = (long) raw_buf;
- end = raw + unit[drive].type->read_size;
-
- for (scnt=0; scnt < unit[drive].dtype->sects * unit[drive].type->sect_mult; scnt++) {
- do { /* search for the right sync of each sec-hdr */
- if (!(raw = scan_sync (raw, end))) {
- printk(KERN_INFO "dos_read: no hdr sync on track %d, unit %d for sector %d\n",
- unit[drive].track,drive,scnt);
- return MFM_NOSYNC;
- }
+ unsigned long end;
+ unsigned long raw;
+ int scnt;
+ unsigned short crc,data_crc[2];
+ struct dos_header hdr;
+
+ drive&=3;
+ raw = (long) raw_buf;
+ end = raw + unit[drive].type->read_size;
+
+ for (scnt=0; scnt < unit[drive].dtype->sects * unit[drive].type->sect_mult; scnt++) {
+ do { /* search for the right sync of each sec-hdr */
+ if (!(raw = scan_sync (raw, end))) {
+ printk(KERN_INFO "dos_read: no hdr sync on "
+ "track %d, unit %d for sector %d\n",
+ unit[drive].track,drive,scnt);
+ return MFM_NOSYNC;
+ }
#ifdef DEBUG
- dbg(raw);
+ dbg(raw);
#endif
- } while (*((ushort *)raw)!=0x5554); /* loop usually only once done */
- raw+=2; /* skip over headermark */
- raw = dos_decode((unsigned char *)&hdr,(ushort *) raw,8);
- crc = dos_hdr_crc(&hdr);
+ } while (*((ushort *)raw)!=0x5554); /* loop usually only once done */
+ raw+=2; /* skip over headermark */
+ raw = dos_decode((unsigned char *)&hdr,(ushort *) raw,8);
+ crc = dos_hdr_crc(&hdr);
#ifdef DEBUG
- printk("(%3d,%d,%2d,%d) %x\n", hdr.track, hdr.side,
- hdr.sec, hdr.len_desc, hdr.crc);
+ printk("(%3d,%d,%2d,%d) %x\n", hdr.track, hdr.side,
+ hdr.sec, hdr.len_desc, hdr.crc);
#endif
- if (crc != hdr.crc) {
- printk(KERN_INFO "dos_read: MFM_HEADER %04x,%04x\n", hdr.crc, crc);
- return MFM_HEADER;
- }
- if (hdr.track != unit[drive].track/unit[drive].type->heads) {
- printk(KERN_INFO "dos_read: MFM_TRACK %d, %d\n", hdr.track,
- unit[drive].track/unit[drive].type->heads);
- return MFM_TRACK;
- }
-
- if (hdr.side != unit[drive].track%unit[drive].type->heads) {
- printk(KERN_INFO "dos_read: MFM_SIDE %d, %d\n", hdr.side,
- unit[drive].track%unit[drive].type->heads);
- return MFM_TRACK;
- }
-
- if (hdr.len_desc != 2) {
- printk(KERN_INFO "dos_read: unknown sector len descriptor %d\n", hdr.len_desc);
- return MFM_DATA;
- }
+ if (crc != hdr.crc) {
+ printk(KERN_INFO "dos_read: MFM_HEADER %04x,%04x\n",
+ hdr.crc, crc);
+ return MFM_HEADER;
+ }
+ if (hdr.track != unit[drive].track/unit[drive].type->heads) {
+ printk(KERN_INFO "dos_read: MFM_TRACK %d, %d\n",
+ hdr.track,
+ unit[drive].track/unit[drive].type->heads);
+ return MFM_TRACK;
+ }
+
+ if (hdr.side != unit[drive].track%unit[drive].type->heads) {
+ printk(KERN_INFO "dos_read: MFM_SIDE %d, %d\n",
+ hdr.side,
+ unit[drive].track%unit[drive].type->heads);
+ return MFM_TRACK;
+ }
+
+ if (hdr.len_desc != 2) {
+ printk(KERN_INFO "dos_read: unknown sector len "
+ "descriptor %d\n", hdr.len_desc);
+ return MFM_DATA;
+ }
#ifdef DEBUG
- printk("hdr accepted\n");
+ printk("hdr accepted\n");
#endif
- if (!(raw = scan_sync (raw, end))) {
- printk(KERN_INFO "dos_read: no data sync on track %d, unit %d for sector%d, disk sector %d\n",
- unit[drive].track, drive, scnt, hdr.sec);
- return MFM_NOSYNC;
- }
+ if (!(raw = scan_sync (raw, end))) {
+ printk(KERN_INFO "dos_read: no data sync on track "
+ "%d, unit %d for sector%d, disk sector %d\n",
+ unit[drive].track, drive, scnt, hdr.sec);
+ return MFM_NOSYNC;
+ }
#ifdef DEBUG
- dbg(raw);
+ dbg(raw);
#endif
- if (*((ushort *)raw)!=0x5545) {
- printk(KERN_INFO "dos_read: no data mark after sync (%d,%d,%d,%d) sc=%d\n",
- hdr.track,hdr.side,hdr.sec,hdr.len_desc,scnt);
- return MFM_NOSYNC;
- }
-
- raw+=2; /* skip data mark (included in checksum) */
- raw = dos_decode((unsigned char *)(unit[drive].trackbuf + (hdr.sec - 1) * 512), (ushort *) raw, 512);
- raw = dos_decode((unsigned char *)data_crc,(ushort *) raw,4);
- crc = dos_data_crc(unit[drive].trackbuf + (hdr.sec - 1) * 512);
-
- if (crc != data_crc[0]) {
- printk(KERN_INFO "dos_read: MFM_DATA (%d,%d,%d,%d) sc=%d, %x %x\n",
- hdr.track, hdr.side, hdr.sec, hdr.len_desc,
- scnt,data_crc[0], crc);
- printk(KERN_INFO "data=(%lx,%lx,%lx,%lx,...)\n",
- ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[0],
- ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[1],
- ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[2],
- ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[3]);
- return MFM_DATA;
- }
- }
- return 0;
+ if (*((ushort *)raw)!=0x5545) {
+ printk(KERN_INFO "dos_read: no data mark after "
+ "sync (%d,%d,%d,%d) sc=%d\n",
+ hdr.track,hdr.side,hdr.sec,hdr.len_desc,scnt);
+ return MFM_NOSYNC;
+ }
+
+ raw+=2; /* skip data mark (included in checksum) */
+ raw = dos_decode((unsigned char *)(unit[drive].trackbuf + (hdr.sec - 1) * 512), (ushort *) raw, 512);
+ raw = dos_decode((unsigned char *)data_crc,(ushort *) raw,4);
+ crc = dos_data_crc(unit[drive].trackbuf + (hdr.sec - 1) * 512);
+
+ if (crc != data_crc[0]) {
+ printk(KERN_INFO "dos_read: MFM_DATA (%d,%d,%d,%d) "
+ "sc=%d, %x %x\n", hdr.track, hdr.side,
+ hdr.sec, hdr.len_desc, scnt,data_crc[0], crc);
+ printk(KERN_INFO "data=(%lx,%lx,%lx,%lx,...)\n",
+ ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[0],
+ ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[1],
+ ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[2],
+ ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[3]);
+ return MFM_DATA;
+ }
+ }
+ return 0;
}
static inline ushort dos_encode_byte(unsigned char byte)
{
-register unsigned char *enc, b2, b1;
-register ushort word;
-
-enc=mfmencode;
-b1=byte;
-b2=b1>>4;
-b1&=15;
-word=enc[b2] <<8 | enc [b1];
-return (word|((word&(256|64)) ? 0: 128));
+ register unsigned char *enc, b2, b1;
+ register ushort word;
+
+ enc=mfmencode;
+ b1=byte;
+ b2=b1>>4;
+ b1&=15;
+ word=enc[b2] <<8 | enc [b1];
+ return (word|((word&(256|64)) ? 0: 128));
}
static void dos_encode_block(ushort *dest, unsigned char *src, int len)
{
-int i;
+ int i;
-for (i = 0; i < len; i++) {
- *dest=dos_encode_byte(*src++);
- *dest|=((dest[-1]&1)||(*dest&0x4000))? 0: 0x8000;
- dest++;
-}
+ for (i = 0; i < len; i++) {
+ *dest=dos_encode_byte(*src++);
+ *dest|=((dest[-1]&1)||(*dest&0x4000))? 0: 0x8000;
+ dest++;
+ }
}
static unsigned long *ms_putsec(int drive, unsigned long *raw, int cnt)
{
-static struct dos_header hdr={0,0,0,2,0,
- {78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78}};
-int i;
-static ushort crc[2]={0,0x4e4e};
+ static struct dos_header hdr={0,0,0,2,0,
+ {78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78}};
+ int i;
+ static ushort crc[2]={0,0x4e4e};
-drive&=3;
+ drive&=3;
/* id gap 1 */
/* the MFM word before is always 9254 */
-for(i=0;i<6;i++)
- *raw++=0xaaaaaaaa;
+ for(i=0;i<6;i++)
+ *raw++=0xaaaaaaaa;
/* 3 sync + 1 headermark */
-*raw++=0x44894489;
-*raw++=0x44895554;
+ *raw++=0x44894489;
+ *raw++=0x44895554;
/* fill in the variable parts of the header */
-hdr.track=unit[drive].track/unit[drive].type->heads;
-hdr.side=unit[drive].track%unit[drive].type->heads;
-hdr.sec=cnt+1;
-hdr.crc=dos_hdr_crc(&hdr);
+ hdr.track=unit[drive].track/unit[drive].type->heads;
+ hdr.side=unit[drive].track%unit[drive].type->heads;
+ hdr.sec=cnt+1;
+ hdr.crc=dos_hdr_crc(&hdr);
/* header (without "magic") and id gap 2*/
-dos_encode_block((ushort *)raw,(unsigned char *) &hdr.track,28);
-raw+=14;
+ dos_encode_block((ushort *)raw,(unsigned char *) &hdr.track,28);
+ raw+=14;
/*id gap 3 */
-for(i=0;i<6;i++)
- *raw++=0xaaaaaaaa;
+ for(i=0;i<6;i++)
+ *raw++=0xaaaaaaaa;
/* 3 syncs and 1 datamark */
-*raw++=0x44894489;
-*raw++=0x44895545;
+ *raw++=0x44894489;
+ *raw++=0x44895545;
/* data */
-dos_encode_block((ushort *)raw,(unsigned char *)unit[drive].trackbuf+cnt*512,512);
-raw+=256;
+ dos_encode_block((ushort *)raw,
+ (unsigned char *)unit[drive].trackbuf+cnt*512,512);
+ raw+=256;
/*data crc + jd's special gap (long words :-/) */
-crc[0]=dos_data_crc(unit[drive].trackbuf+cnt*512);
-dos_encode_block((ushort *) raw,(unsigned char *)crc,4);
-raw+=2;
+ crc[0]=dos_data_crc(unit[drive].trackbuf+cnt*512);
+ dos_encode_block((ushort *) raw,(unsigned char *)crc,4);
+ raw+=2;
/* data gap */
-for(i=0;i<38;i++)
- *raw++=0x92549254;
+ for(i=0;i<38;i++)
+ *raw++=0x92549254;
-return raw; /* wrote 652 MFM words */
+ return raw; /* wrote 652 MFM words */
}
static void dos_write(int disk)
{
-int cnt;
-unsigned long raw = (unsigned long) raw_buf;
-unsigned long *ptr=(unsigned long *)raw;
+ int cnt;
+ unsigned long raw = (unsigned long) raw_buf;
+ unsigned long *ptr=(unsigned long *)raw;
-disk&=3;
+ disk&=3;
/* really gap4 + indexgap , but we write it first and round it up */
-for (cnt=0;cnt<425;cnt++)
- *ptr++=0x92549254;
+ for (cnt=0;cnt<425;cnt++)
+ *ptr++=0x92549254;
/* the following is just guessed */
-if (unit[disk].type->sect_mult==2) /* check for HD-Disks */
- for(cnt=0;cnt<473;cnt++)
- *ptr++=0x92549254;
+ if (unit[disk].type->sect_mult==2) /* check for HD-Disks */
+ for(cnt=0;cnt<473;cnt++)
+ *ptr++=0x92549254;
/* now the index marks...*/
-for (cnt=0;cnt<20;cnt++)
- *ptr++=0x92549254;
-for (cnt=0;cnt<6;cnt++)
- *ptr++=0xaaaaaaaa;
-*ptr++=0x52245224;
-*ptr++=0x52245552;
-for (cnt=0;cnt<20;cnt++)
- *ptr++=0x92549254;
+ for (cnt=0;cnt<20;cnt++)
+ *ptr++=0x92549254;
+ for (cnt=0;cnt<6;cnt++)
+ *ptr++=0xaaaaaaaa;
+ *ptr++=0x52245224;
+ *ptr++=0x52245552;
+ for (cnt=0;cnt<20;cnt++)
+ *ptr++=0x92549254;
/* sectors */
-for(cnt = 0; cnt < unit[disk].dtype->sects * unit[disk].type->sect_mult; cnt++)
- ptr=ms_putsec(disk,ptr,cnt);
+ for(cnt = 0; cnt < unit[disk].dtype->sects * unit[disk].type->sect_mult; cnt++)
+ ptr=ms_putsec(disk,ptr,cnt);
-*(ushort *)ptr = 0xaaa8; /* MFM word before is always 0x9254 */
+ *(ushort *)ptr = 0xaaa8; /* MFM word before is always 0x9254 */
}
/*
@@ -1299,37 +1308,38 @@ static void flush_track_callback(unsigned long nr)
static int non_int_flush_track (unsigned long nr)
{
-unsigned long flags;
-
- nr&=3;
- writefromint = 0;
- del_timer(&post_write_timer);
- get_fdc(nr);
- if (!fd_motor_on(nr)) {
- writepending = 0;
- rel_fdc();
- return 0;
- }
- save_flags(flags);
- cli();
- if (writepending != 2) {
- restore_flags(flags);
- (*unit[nr].dtype->write_fkt)(nr);
- if (!raw_write(nr)) {
- printk (KERN_NOTICE "floppy disk write protected in write!\n");
- writepending = 0;
- return 0;
- }
- while (block_flag == 2)
- sleep_on (&wait_fd_block);
- }
- else {
- restore_flags(flags);
- ms_delay(2); /* 2 ms post_write delay */
- post_write(nr);
- }
- rel_fdc();
- return 1;
+ unsigned long flags;
+
+ nr&=3;
+ writefromint = 0;
+ del_timer(&post_write_timer);
+ get_fdc(nr);
+ if (!fd_motor_on(nr)) {
+ writepending = 0;
+ rel_fdc();
+ return 0;
+ }
+ save_flags(flags);
+ cli();
+ if (writepending != 2) {
+ restore_flags(flags);
+ (*unit[nr].dtype->write_fkt)(nr);
+ if (!raw_write(nr)) {
+ printk (KERN_NOTICE "floppy disk write protected "
+ "in write!\n");
+ writepending = 0;
+ return 0;
+ }
+ while (block_flag == 2)
+ sleep_on (&wait_fd_block);
+ }
+ else {
+ restore_flags(flags);
+ ms_delay(2); /* 2 ms post_write delay */
+ post_write(nr);
+ }
+ rel_fdc();
+ return 1;
}
static int get_track(int drive, int track)
@@ -1379,7 +1389,7 @@ static void redo_fd_request(void)
return;
}
- repeat:
+ repeat:
if (!CURRENT) {
/* Nothing left to do */
return;
@@ -1406,11 +1416,12 @@ static void redo_fd_request(void)
floppy = unit + drive;
}
- /* Here someone could investigate to be more efficient */
+ /* Here someone could investigate to be more efficient */
for (cnt = 0; cnt < CURRENT->current_nr_sectors; cnt++) {
#ifdef DEBUG
- printk("fd: sector %ld + %d requested for %s\n",CURRENT->sector,cnt,
- (CURRENT->cmd==READ)?"read":"write");
+ printk("fd: sector %ld + %d requested for %s\n",
+ CURRENT->sector,cnt,
+ (CURRENT->cmd==READ)?"read":"write");
#endif
block = CURRENT->sector + cnt;
if ((int)block > floppy->blocks) {
@@ -1422,8 +1433,8 @@ static void redo_fd_request(void)
sector = block % (floppy->dtype->sects * floppy->type->sect_mult);
data = CURRENT->buffer + 512 * cnt;
#ifdef DEBUG
- printk("access to track %d, sector %d, with buffer at 0x%08lx\n",
- track, sector, data);
+ printk("access to track %d, sector %d, with buffer at "
+ "0x%08lx\n", track, sector, data);
#endif
if ((CURRENT->cmd != READ) && (CURRENT->cmd != WRITE)) {
@@ -1437,11 +1448,11 @@ static void redo_fd_request(void)
}
switch (CURRENT->cmd) {
- case READ:
+ case READ:
memcpy(data, unit[drive].trackbuf + sector * 512, 512);
break;
- case WRITE:
+ case WRITE:
memcpy(unit[drive].trackbuf + sector * 512, data, 512);
/* keep the drive spinning while writes are scheduled */
@@ -1494,7 +1505,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
loc.cylinders = unit[drive].type->tracks;
loc.start = 0;
if (copy_to_user((void *)param, (void *)&loc,
- sizeof(struct hd_geometry)))
+ sizeof(struct hd_geometry)))
return -EFAULT;
break;
}
@@ -1545,10 +1556,10 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
getprm.sect=unit[drive].dtype->sects * unit[drive].type->sect_mult;
getprm.size=unit[drive].blocks;
if (copy_to_user((void *)param,
- (void *)&getprm,
- sizeof(struct floppy_struct)))
+ (void *)&getprm,
+ sizeof(struct floppy_struct)))
return -EFAULT;
- break;
+ break;
case BLKGETSIZE:
return put_user(unit[drive].blocks,(long *)param);
break;
@@ -1562,13 +1573,14 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
#ifdef RAW_IOCTL
case IOCTL_RAW_TRACK:
if (copy_to_user((void *)param, raw_buf,
- unit[drive].type->read_size))
+ unit[drive].type->read_size))
return -EFAULT;
else
return unit[drive].type->read_size;
#endif
default:
- printk(KERN_DEBUG "fd_ioctl: unknown cmd %d for drive %d.",cmd,drive);
+ printk(KERN_DEBUG "fd_ioctl: unknown cmd %d for drive %d.",
+ cmd, drive);
return -ENOSYS;
}
return 0;
@@ -1589,8 +1601,8 @@ static void fd_probe(int dev)
break;
if (type >= num_dr_types) {
- printk(KERN_WARNING "fd_probe: unsupported drive type %08lx found\n",
- code);
+ printk(KERN_WARNING "fd_probe: unsupported drive type "
+ "%08lx found\n", code);
unit[drive].type = &drive_types[num_dr_types-1]; /* FD_NODRIVE */
return;
}
@@ -1611,93 +1623,93 @@ static void fd_probe(int dev)
*/
static int floppy_open(struct inode *inode, struct file *filp)
{
- int drive;
- int old_dev;
- int system;
- unsigned long flags;
-
- drive = MINOR(inode->i_rdev) & 3;
- old_dev = fd_device[drive];
-
- if (fd_ref[drive])
- if (old_dev != inode->i_rdev)
- return -EBUSY;
-
- if (unit[drive].type->code == FD_NODRIVE)
- return -ENODEV;
-
- if (filp && filp->f_mode & 3) {
- check_disk_change(inode->i_rdev);
- if (filp->f_mode & 2 ) {
- int wrprot;
-
- get_fdc(drive);
- fd_select (drive);
- wrprot = !(ciaa.pra & DSKPROT);
- fd_deselect (drive);
- rel_fdc();
-
- if (wrprot)
- return -EROFS;
- }
- }
-
- save_flags(flags);
- cli();
- fd_ref[drive]++;
- fd_device[drive] = inode->i_rdev;
+ int drive;
+ int old_dev;
+ int system;
+ unsigned long flags;
+
+ drive = MINOR(inode->i_rdev) & 3;
+ old_dev = fd_device[drive];
+
+ if (fd_ref[drive])
+ if (old_dev != inode->i_rdev)
+ return -EBUSY;
+
+ if (unit[drive].type->code == FD_NODRIVE)
+ return -ENODEV;
+
+ if (filp && filp->f_mode & 3) {
+ check_disk_change(inode->i_rdev);
+ if (filp->f_mode & 2 ) {
+ int wrprot;
+
+ get_fdc(drive);
+ fd_select (drive);
+ wrprot = !(ciaa.pra & DSKPROT);
+ fd_deselect (drive);
+ rel_fdc();
+
+ if (wrprot)
+ return -EROFS;
+ }
+ }
+
+ save_flags(flags);
+ cli();
+ fd_ref[drive]++;
+ fd_device[drive] = inode->i_rdev;
#ifdef MODULE
- if (unit[drive].motor == 0)
- MOD_INC_USE_COUNT;
+ if (unit[drive].motor == 0)
+ MOD_INC_USE_COUNT;
#endif
- restore_flags(flags);
+ restore_flags(flags);
- if (old_dev && old_dev != inode->i_rdev)
- invalidate_buffers(old_dev);
+ if (old_dev && old_dev != inode->i_rdev)
+ invalidate_buffers(old_dev);
- system=(inode->i_rdev & 4)>>2;
- unit[drive].dtype=&data_types[system];
- unit[drive].blocks=unit[drive].type->heads*unit[drive].type->tracks*
+ system=(inode->i_rdev & 4)>>2;
+ unit[drive].dtype=&data_types[system];
+ unit[drive].blocks=unit[drive].type->heads*unit[drive].type->tracks*
data_types[system].sects*unit[drive].type->sect_mult;
- floppy_sizes[MINOR(inode->i_rdev)] = unit[drive].blocks >> 1;
+ floppy_sizes[MINOR(inode->i_rdev)] = unit[drive].blocks >> 1;
- printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive,
- unit[drive].type->name, data_types[system].name);
+ printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive,
+ unit[drive].type->name, data_types[system].name);
- return 0;
+ return 0;
}
static int floppy_release(struct inode * inode, struct file * filp)
{
#ifdef DEBUG
- struct super_block * sb;
+ struct super_block * sb;
#endif
- int drive = MINOR(inode->i_rdev) & 3;
+ int drive = MINOR(inode->i_rdev) & 3;
- fsync_dev(inode->i_rdev);
+ fsync_dev(inode->i_rdev);
#ifdef DEBUG
- /* This is now handled in floppy_change, but still useful for debugging */
- sb = get_super(inode->i_rdev);
- if (sb)
- invalidate_inodes(sb);
- invalidate_buffers(inode->i_rdev);
+ /* This is now handled in floppy_change, but still useful for debugging */
+ sb = get_super(inode->i_rdev);
+ if (sb)
+ invalidate_inodes(sb);
+ invalidate_buffers(inode->i_rdev);
#endif
- if (unit[drive].dirty == 1) {
- del_timer (flush_track_timer + drive);
- non_int_flush_track (drive);
- }
+ if (unit[drive].dirty == 1) {
+ del_timer (flush_track_timer + drive);
+ non_int_flush_track (drive);
+ }
- if (!fd_ref[drive]--) {
- printk(KERN_CRIT "floppy_release with fd_ref == 0");
- fd_ref[drive] = 0;
- }
+ if (!fd_ref[drive]--) {
+ printk(KERN_CRIT "floppy_release with fd_ref == 0");
+ fd_ref[drive] = 0;
+ }
#ifdef MODULE
/* the mod_use counter is handled this way */
- floppy_off (drive | 0x40000000);
+ floppy_off (drive | 0x40000000);
#endif
- return 0;
+ return 0;
}
/*
@@ -1769,23 +1781,23 @@ static int __init fd_probe_drives(void)
drives=0;
nomem=0;
for(drive=0;drive<FD_MAX_UNITS;drive++) {
- fd_probe(drive);
- if (unit[drive].type->code != FD_NODRIVE) {
- drives++;
- if ((unit[drive].trackbuf = kmalloc(FLOPPY_MAX_SECTORS * 512, GFP_KERNEL)) == NULL) {
- printk("no mem for ");
- unit[drive].type = &drive_types[num_dr_types - 1]; /* FD_NODRIVE */
- drives--;
- nomem = 1;
- }
- printk("fd%d ",drive);
- }
+ fd_probe(drive);
+ if (unit[drive].type->code != FD_NODRIVE) {
+ drives++;
+ if ((unit[drive].trackbuf = kmalloc(FLOPPY_MAX_SECTORS * 512, GFP_KERNEL)) == NULL) {
+ printk("no mem for ");
+ unit[drive].type = &drive_types[num_dr_types - 1]; /* FD_NODRIVE */
+ drives--;
+ nomem = 1;
+ }
+ printk("fd%d ",drive);
+ }
}
if ((drives > 0) || (nomem == 0)) {
- if (drives == 0)
- printk("no drives");
- printk("\n");
- return drives;
+ if (drives == 0)
+ printk("no drives");
+ printk("\n");
+ return drives;
}
printk("\n");
return -ENOMEM;
@@ -1793,85 +1805,87 @@ static int __init fd_probe_drives(void)
int __init amiga_floppy_init(void)
{
- int i;
-
- if (!AMIGAHW_PRESENT(AMI_FLOPPY))
- return -ENXIO;
- if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
- printk("fd: Unable to get major %d for floppy\n",MAJOR_NR);
- return -EBUSY;
- }
- if ((raw_buf = (char *)amiga_chip_alloc (RAW_BUF_SIZE)) == NULL) {
- printk("fd: cannot get chip mem buffer\n");
- unregister_blkdev(MAJOR_NR,"fd");
- return -ENOMEM;
- }
-
- if (request_irq(IRQ_FLOPPY, fd_block_done, 0, "floppy_dma", NULL) != 0) {
- printk("fd: cannot get irq for dma\n");
- amiga_chip_free(raw_buf);
- unregister_blkdev(MAJOR_NR,"fd");
- return -EBUSY;
- }
- if (request_irq(IRQ_AMIGA_CIAA_TB, ms_isr, 0, "floppy_timer", NULL) != 0) {
- printk("fd: cannot get irq for timer\n");
- free_irq(IRQ_FLOPPY, NULL);
- amiga_chip_free(raw_buf);
- unregister_blkdev(MAJOR_NR,"fd");
- return -EBUSY;
- }
- if (fd_probe_drives() < 1) { /* No usable drives */
- free_irq(IRQ_AMIGA_CIAA_TB, NULL);
- free_irq(IRQ_FLOPPY, NULL);
- amiga_chip_free(raw_buf);
- unregister_blkdev(MAJOR_NR,"fd");
- return -ENXIO;
- }
-
- /* initialize variables */
- motor_on_timer.next = NULL;
- motor_on_timer.prev = NULL;
- motor_on_timer.expires = 0;
- motor_on_timer.data = 0;
- motor_on_timer.function = motor_on_callback;
- for (i = 0; i < FD_MAX_UNITS; i++) {
- motor_off_timer[i].next = NULL;
- motor_off_timer[i].prev = NULL;
- motor_off_timer[i].expires = 0;
- motor_off_timer[i].data = i|0x80000000;
- motor_off_timer[i].function = fd_motor_off;
- flush_track_timer[i].next = NULL;
- flush_track_timer[i].prev = NULL;
- flush_track_timer[i].expires = 0;
- flush_track_timer[i].data = i;
- flush_track_timer[i].function = flush_track_callback;
-
- unit[i].track = -1;
- }
-
- post_write_timer.next = NULL;
- post_write_timer.prev = NULL;
- post_write_timer.expires = 0;
- post_write_timer.data = 0;
- post_write_timer.function = post_write;
+ int i;
+
+ if (!AMIGAHW_PRESENT(AMI_FLOPPY))
+ return -ENXIO;
+
+ if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
+ printk("fd: Unable to get major %d for floppy\n",MAJOR_NR);
+ return -EBUSY;
+ }
+
+ if ((raw_buf = (char *)amiga_chip_alloc (RAW_BUF_SIZE)) == NULL) {
+ printk("fd: cannot get chip mem buffer\n");
+ unregister_blkdev(MAJOR_NR,"fd");
+ return -ENOMEM;
+ }
+
+ if (!request_irq(IRQ_AMIGA_DSKBLK, fd_block_done, 0, "floppy_dma", NULL)) {
+ printk("fd: cannot get irq for dma\n");
+ amiga_chip_free(raw_buf);
+ unregister_blkdev(MAJOR_NR,"fd");
+ return -EBUSY;
+ }
+ if (!request_irq(IRQ_AMIGA_CIAA_TB, ms_isr, 0, "floppy_timer", NULL)) {
+ printk("fd: cannot get irq for timer\n");
+ free_irq(IRQ_AMIGA_DSKBLK, NULL);
+ amiga_chip_free(raw_buf);
+ unregister_blkdev(MAJOR_NR,"fd");
+ return -EBUSY;
+ }
+ if (fd_probe_drives() < 1) { /* No usable drives */
+ free_irq(IRQ_AMIGA_CIAA_TB, NULL);
+ free_irq(IRQ_AMIGA_DSKBLK, NULL);
+ amiga_chip_free(raw_buf);
+ unregister_blkdev(MAJOR_NR,"fd");
+ return -ENXIO;
+ }
+
+ /* initialize variables */
+ motor_on_timer.next = NULL;
+ motor_on_timer.prev = NULL;
+ motor_on_timer.expires = 0;
+ motor_on_timer.data = 0;
+ motor_on_timer.function = motor_on_callback;
+ for (i = 0; i < FD_MAX_UNITS; i++) {
+ motor_off_timer[i].next = NULL;
+ motor_off_timer[i].prev = NULL;
+ motor_off_timer[i].expires = 0;
+ motor_off_timer[i].data = i|0x80000000;
+ motor_off_timer[i].function = fd_motor_off;
+ flush_track_timer[i].next = NULL;
+ flush_track_timer[i].prev = NULL;
+ flush_track_timer[i].expires = 0;
+ flush_track_timer[i].data = i;
+ flush_track_timer[i].function = flush_track_callback;
+
+ unit[i].track = -1;
+ }
+
+ post_write_timer.next = NULL;
+ post_write_timer.prev = NULL;
+ post_write_timer.expires = 0;
+ post_write_timer.data = 0;
+ post_write_timer.function = post_write;
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
- blksize_size[MAJOR_NR] = floppy_blocksizes;
- blk_size[MAJOR_NR] = floppy_sizes;
+ blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blksize_size[MAJOR_NR] = floppy_blocksizes;
+ blk_size[MAJOR_NR] = floppy_sizes;
- for (i = 0; i < 128; i++)
- mfmdecode[i]=255;
- for (i = 0; i < 16; i++)
- mfmdecode[mfmencode[i]]=i;
+ for (i = 0; i < 128; i++)
+ mfmdecode[i]=255;
+ for (i = 0; i < 16; i++)
+ mfmdecode[mfmencode[i]]=i;
- /* make sure that disk DMA is enabled */
- custom.dmacon = DMAF_SETCLR | DMAF_DISK;
+ /* make sure that disk DMA is enabled */
+ custom.dmacon = DMAF_SETCLR | DMAF_DISK;
- /* init ms timer */
- ciaa.crb = 8; /* one-shot, stop */
+ /* init ms timer */
+ ciaa.crb = 8; /* one-shot, stop */
- (void)do_floppy; /* avoid warning about unused variable */
- return 0;
+ (void)do_floppy; /* avoid warning about unused variable */
+ return 0;
}
#ifdef MODULE
@@ -1879,25 +1893,25 @@ int __init amiga_floppy_init(void)
int init_module(void)
{
- if (!MACH_IS_AMIGA)
- return -ENXIO;
- return amiga_floppy_init();
+ if (!MACH_IS_AMIGA)
+ return -ENXIO;
+ return amiga_floppy_init();
}
void cleanup_module(void)
{
-int i;
-
-for( i = 0; i < FD_MAX_UNITS; i++)
- if (unit[i].type->code != FD_NODRIVE)
- kfree(unit[i].trackbuf);
-free_irq(IRQ_AMIGA_CIAA_TB, NULL);
-free_irq(IRQ_FLOPPY, NULL);
-custom.dmacon = DMAF_DISK; /* disable DMA */
-amiga_chip_free(raw_buf);
-blk_size[MAJOR_NR] = NULL;
-blksize_size[MAJOR_NR] = NULL;
-blk_dev[MAJOR_NR].request_fn = NULL;
-unregister_blkdev(MAJOR_NR, "fd");
+ int i;
+
+ for( i = 0; i < FD_MAX_UNITS; i++)
+ if (unit[i].type->code != FD_NODRIVE)
+ kfree(unit[i].trackbuf);
+ free_irq(IRQ_AMIGA_CIAA_TB, NULL);
+ free_irq(IRQ_AMIGA_DSKBLK, NULL);
+ custom.dmacon = DMAF_DISK; /* disable DMA */
+ amiga_chip_free(raw_buf);
+ blk_size[MAJOR_NR] = NULL;
+ blksize_size[MAJOR_NR] = NULL;
+ blk_dev[MAJOR_NR].request_fn = NULL;
+ unregister_blkdev(MAJOR_NR, "fd");
}
#endif
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index cf408b8c7..b8df87205 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -215,11 +215,10 @@ static struct atari_disk_type user_params[FD_MAX_UNITS];
* restored upon disk change by floppy_revalidate() if valid (as seen by
* default_params[].blocks > 0 - a bit in unit[].flags might be used for this?)
*/
-static struct atari_disk_type default_params[FD_MAX_UNITS] = {
- { NULL, 0, 0, 0, 0}, };
+static struct atari_disk_type default_params[FD_MAX_UNITS];
static int floppy_sizes[256];
-static int floppy_blocksizes[256] = { 0, };
+static int floppy_blocksizes[256];
/* current info on each unit */
static struct atari_floppy_struct {
@@ -331,26 +330,6 @@ static unsigned int changed_floppies = 0xff, fake_change = 0;
* will give up. */
-#define START_MOTOR_OFF_TIMER(delay) \
- do { \
- motor_off_timer.expires = jiffies + (delay); \
- add_timer( &motor_off_timer ); \
- MotorOffTrys = 0; \
- } while(0)
-
-#define START_CHECK_CHANGE_TIMER(delay) \
- do { \
- timer_table[FLOPPY_TIMER].expires = jiffies + (delay); \
- timer_active |= (1 << FLOPPY_TIMER); \
- } while(0)
-
-#define START_TIMEOUT() \
- mod_timer(&timeout_timer, jiffies + FLOPPY_TIMEOUT)
-
-#define STOP_TIMEOUT() \
- del_timer(&timeout_timer)
-
-
/*
* The driver is trying to determine the correct media format
* while Probing is set. fd_rwsec_done() clears it after a
@@ -420,6 +399,31 @@ static struct timer_list timeout_timer =
{ NULL, NULL, 0, 0, fd_times_out };
+static inline void
+start_motor_off_timer(void)
+{
+ mod_timer(&motor_off_timer, jiffies + FD_MOTOR_OFF_DELAY);
+ MotorOffTrys = 0;
+}
+
+static inline void
+start_check_change_timer(void)
+{
+ timer_table[FLOPPY_TIMER].expires = jiffies + CHECK_CHANGE_DELAY;
+ timer_active |= (1 << FLOPPY_TIMER);
+}
+
+static inline void
+start_timeout(void)
+{
+ mod_timer(&timeout_timer, jiffies + FLOPPY_TIMEOUT);
+}
+
+static inline void
+stop_timeout(void)
+{
+ del_timer(&timeout_timer);
+}
/* Select the side to use. */
@@ -497,19 +501,12 @@ static void fd_deselect( void )
static void fd_motor_off_timer( unsigned long dummy )
{
-/* unsigned long flags; */
unsigned char status;
- int delay;
- del_timer( &motor_off_timer );
-
if (SelectedDrive < 0)
/* no drive selected, needn't deselect anyone */
return;
-/* save_flags(flags);
- cli(); */
-
if (stdma_islocked())
goto retry;
@@ -519,21 +516,18 @@ static void fd_motor_off_timer( unsigned long dummy )
/* motor already turned off by FDC -> deselect drives */
MotorOn = 0;
fd_deselect();
-/* restore_flags(flags); */
return;
}
/* not yet off, try again */
retry:
-/* restore_flags(flags); */
/* Test again later; if tested too often, it seems there is no disk
* in the drive and the FDC will leave the motor on forever (or,
* at least until a disk is inserted). So we'll test only twice
* per second from then on...
*/
- delay = (MotorOffTrys < FD_MOTOR_OFF_MAXTRY) ?
- (++MotorOffTrys, HZ/20) : HZ/2;
- START_MOTOR_OFF_TIMER( delay );
+ mod_timer(&motor_off_timer,
+ jiffies + (MotorOffTrys++ < FD_MOTOR_OFF_MAXTRY ? HZ/20 : HZ/2));
}
@@ -571,7 +565,7 @@ static void check_change( void )
}
restore_flags(flags);
- START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY );
+ start_check_change_timer();
}
@@ -603,8 +597,7 @@ static void floppy_irq (int irq, void *dummy, struct pt_regs *fp)
unsigned char status;
void (*handler)( int );
- handler = FloppyIRQHandler;
- FloppyIRQHandler = NULL;
+ handler = xchg(&FloppyIRQHandler, NULL);
if (handler) {
nop();
@@ -805,7 +798,7 @@ static void fd_calibrate( void )
NeedSeek = 1;
MotorOn = 1;
- START_TIMEOUT();
+ start_timeout();
/* wait for IRQ */
}
@@ -813,7 +806,7 @@ static void fd_calibrate( void )
static void fd_calibrate_done( int status )
{
DPRINT(("fd_calibrate_done()\n"));
- STOP_TIMEOUT();
+ stop_timeout();
/* set the correct speed now */
if (ATARIHW_PRESENT(FDCSPEED))
@@ -853,7 +846,7 @@ static void fd_seek( void )
MotorOn = 1;
set_head_settle_flag();
- START_TIMEOUT();
+ start_timeout();
/* wait for IRQ */
}
@@ -861,7 +854,7 @@ static void fd_seek( void )
static void fd_seek_done( int status )
{
DPRINT(("fd_seek_done()\n"));
- STOP_TIMEOUT();
+ stop_timeout();
/* set the correct speed */
if (ATARIHW_PRESENT(FDCSPEED))
@@ -900,7 +893,7 @@ static void fd_rwsec( void )
DPRINT(("fd_rwsec(), Sec=%d, Access=%c\n",ReqSector, ReqCmd == WRITE ? 'w' : 'r' ));
if (ReqCmd == WRITE) {
if (ATARIHW_PRESENT(EXTD_DMA)) {
- paddr = (unsigned long)VTOP(ReqData);
+ paddr = virt_to_phys(ReqData);
}
else {
copy_buffer( ReqData, DMABuffer );
@@ -913,7 +906,8 @@ static void fd_rwsec( void )
if (read_track)
paddr = PhysTrackBuffer;
else
- paddr = ATARIHW_PRESENT(EXTD_DMA) ? VTOP(ReqData) : PhysDMABuffer;
+ paddr = ATARIHW_PRESENT(EXTD_DMA) ?
+ virt_to_phys(ReqData) : PhysDMABuffer;
rwflag = 0;
}
@@ -978,14 +972,12 @@ static void fd_rwsec( void )
* search for the first non-existent sector and need 1 sec to
* recognise that it isn't present :-(
*/
- del_timer (&readtrack_timer);
- readtrack_timer.expires =
- jiffies + HZ/5 + (old_motoron ? 0 : HZ);
- /* 1 rot. + 5 rot.s if motor was off */
MultReadInProgress = 1;
- add_timer( &readtrack_timer );
+ mod_timer(&readtrack_timer,
+ /* 1 rot. + 5 rot.s if motor was off */
+ jiffies + HZ/5 + (old_motoron ? 0 : HZ));
}
- START_TIMEOUT();
+ start_timeout();
}
@@ -996,8 +988,6 @@ static void fd_readtrack_check( unsigned long dummy )
save_flags(flags);
cli();
- del_timer( &readtrack_timer );
-
if (!MultReadInProgress) {
/* This prevents a race condition that could arise if the
* interrupt is triggered while the calling of this timer
@@ -1045,8 +1035,7 @@ static void fd_readtrack_check( unsigned long dummy )
/* not yet finished, wait another tenth rotation */
restore_flags(flags);
DPRINT(("fd_readtrack_check(): not yet finished\n"));
- readtrack_timer.expires = jiffies + HZ/5/10;
- add_timer( &readtrack_timer );
+ mod_timer(&readtrack_timer, jiffies + HZ/5/10);
}
}
@@ -1068,7 +1057,7 @@ static void fd_rwsec_done1(int status)
{
unsigned int track;
- STOP_TIMEOUT();
+ stop_timeout();
/* Correct the track if stretch != 0 */
if (SUDT->stretch) {
@@ -1150,7 +1139,7 @@ static void fd_rwsec_done1(int status)
if (!read_track) {
void *addr;
addr = ATARIHW_PRESENT( EXTD_DMA ) ? ReqData : DMABuffer;
- dma_cache_maintenance( VTOP(addr), 512, 0 );
+ dma_cache_maintenance( virt_to_phys(addr), 512, 0 );
if (!ATARIHW_PRESENT( EXTD_DMA ))
copy_buffer (addr, ReqData);
} else {
@@ -1237,7 +1226,7 @@ static void fd_writetrack( void )
dma_wd.fdc_acces_seccount = FDCCMD_WRTRA | get_head_settle_flag();
MotorOn = 1;
- START_TIMEOUT();
+ start_timeout();
/* wait for interrupt */
}
@@ -1246,7 +1235,7 @@ static void fd_writetrack_done( int status )
{
DPRINT(("fd_writetrack_done()\n"));
- STOP_TIMEOUT();
+ stop_timeout();
if (status & FDCSTAT_WPROT) {
printk(KERN_NOTICE "fd%d: is write protected\n", SelectedDrive );
@@ -1304,7 +1293,7 @@ static void finish_fdc( void )
SET_IRQ_HANDLER( finish_fdc_done );
FDC_WRITE (FDCREG_CMD, FDCCMD_SEEK);
MotorOn = 1;
- START_TIMEOUT();
+ start_timeout();
/* we must wait for the IRQ here, because the ST-DMA
is released immediately afterwards and the interrupt
may be delivered to the wrong driver. */
@@ -1317,19 +1306,18 @@ static void finish_fdc_done( int dummy )
unsigned long flags;
DPRINT(("finish_fdc_done entered\n"));
- STOP_TIMEOUT();
+ stop_timeout();
NeedSeek = 0;
if ((timer_active & (1 << FLOPPY_TIMER)) &&
- timer_table[FLOPPY_TIMER].expires < jiffies + 5)
+ time_before(timer_table[FLOPPY_TIMER].expires, jiffies + 5))
/* If the check for a disk change is done too early after this
* last seek command, the WP bit still reads wrong :-((
*/
timer_table[FLOPPY_TIMER].expires = jiffies + 5;
else
- START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY );
- del_timer( &motor_off_timer );
- START_MOTOR_OFF_TIMER( FD_MOTOR_OFF_DELAY );
+ start_check_change_timer();
+ start_motor_off_timer();
save_flags(flags);
cli();
@@ -1828,10 +1816,10 @@ static int __init fd_test_drive_present( int drive )
FDC_WRITE (FDCREG_TRACK, 0xff00);
FDC_WRITE( FDCREG_CMD, FDCCMD_RESTORE | FDCCMDADD_H | FDCSTEP_6 );
- for( ok = 0, timeout = jiffies + 2*HZ+HZ/2; time_before(jiffies, timeout); ) {
+ timeout = jiffies + 2*HZ+HZ/2;
+ while (time_before(jiffies, timeout))
if (!(mfp.par_dt_reg & 0x20))
break;
- }
status = FDC_READ( FDCREG_STATUS );
ok = (status & FDCSTAT_TR00) != 0;
@@ -1892,9 +1880,9 @@ static void __init config_types( void )
}
if (cnt > 0) {
- START_MOTOR_OFF_TIMER( FD_MOTOR_OFF_DELAY );
+ start_motor_off_timer();
if (cnt == 1) fd_select_drive( 0 );
- START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY );
+ start_check_change_timer();
}
}
@@ -2045,8 +2033,8 @@ int __init atari_floppy_init (void)
return -ENOMEM;
}
TrackBuffer = DMABuffer + 512;
- PhysDMABuffer = (unsigned long) VTOP(DMABuffer);
- PhysTrackBuffer = (unsigned long) VTOP(TrackBuffer);
+ PhysDMABuffer = virt_to_phys(DMABuffer);
+ PhysTrackBuffer = virt_to_phys(TrackBuffer);
BufferDrive = BufferSide = BufferTrack = -1;
for (i = 0; i < FD_MAX_UNITS; i++) {
diff --git a/drivers/block/cmd646.c b/drivers/block/cmd646.c
index 52e572507..05cf7c2bf 100644
--- a/drivers/block/cmd646.c
+++ b/drivers/block/cmd646.c
@@ -1,4 +1,4 @@
-/* $Id: cmd646.c,v 1.14 1999/07/03 08:56:09 davem Exp $
+/* $Id: cmd646.c,v 1.15 1999/07/23 01:48:37 davem Exp $
* cmd646.c: Enable interrupts at initialization time on Ultra/PCI machines.
* Note, this driver is not used at all on other systems because
* there the "BIOS" has done all of the following already.
diff --git a/drivers/block/cmos-probe.c b/drivers/block/cmos-probe.c
new file mode 100644
index 000000000..f0147d5e3
--- /dev/null
+++ b/drivers/block/cmos-probe.c
@@ -0,0 +1,78 @@
+/*
+ * linux/drivers/block/cmos-probe.c Version 1.00 August 16, 1999
+ *
+ * Copyright (C) 1994-1999 Linus Torvalds & authors (see below)
+ */
+
+#undef REALLY_SLOW_IO /* most systems can safely undef this */
+
+#include <linux/config.h>
+#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/malloc.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>
+
+/*
+ * We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc
+ * controller that is BIOS compatible with ST-506, and thus showing up in our
+ * BIOS table, but not register compatible, and therefore not present in CMOS.
+ *
+ * Furthermore, we will assume that our ST-506 drives <if any> are the primary
+ * drives in the system -- the ones reflected as drive 1 or 2. The first
+ * drive is stored in the high nibble of CMOS byte 0x12, the second in the low
+ * nibble. This will be either a 4 bit drive type or 0xf indicating use byte
+ * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. A non-zero value
+ * means we have an AT controller hard disk for that drive.
+ *
+ * Of course, there is no guarantee that either drive is actually on the
+ * "primary" IDE interface, but we don't bother trying to sort that out here.
+ * If a drive is not actually on the primary interface, then these parameters
+ * will be ignored. This results in the user having to supply the logical
+ * drive geometry as a boot parameter for each drive not on the primary i/f.
+ *
+ * The only "perfect" way to handle this would be to modify the setup.[cS] code
+ * to do BIOS calls Int13h/Fn08h and Int13h/Fn48h to get all of the drive info
+ * for us during initialization. I have the necessary docs -- any takers? -ml
+ */
+void probe_cmos_for_drives (ide_hwif_t *hwif)
+{
+#ifdef __i386__
+ extern struct drive_info_struct drive_info;
+ byte cmos_disks, *BIOS = (byte *) &drive_info;
+ int unit;
+
+#ifdef CONFIG_BLK_DEV_PDC4030
+ if (hwif->chipset == ide_pdc4030 && hwif->channel != 0)
+ return;
+#endif /* CONFIG_BLK_DEV_PDC4030 */
+ outb_p(0x12,0x70); /* specify CMOS address 0x12 */
+ cmos_disks = inb_p(0x71); /* read the data from 0x12 */
+ /* Extract drive geometry from CMOS+BIOS if not already setup */
+ for (unit = 0; unit < MAX_DRIVES; ++unit) {
+ ide_drive_t *drive = &hwif->drives[unit];
+ if ((cmos_disks & (0xf0 >> (unit*4))) && !drive->present && !drive->nobios) {
+ drive->cyl = drive->bios_cyl = *(unsigned short *)BIOS;
+ drive->head = drive->bios_head = *(BIOS+2);
+ drive->sect = drive->bios_sect = *(BIOS+14);
+ drive->ctl = *(BIOS+8);
+ drive->present = 1;
+ }
+ BIOS += 16;
+ }
+#endif
+}
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 7aeff3bfb..1b2be20dd 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -35,8 +35,8 @@
#include <linux/timer.h>
#include <linux/proc_fs.h>
#include <linux/hdreg.h>
+#include <linux/spinlock.h>
#include <asm/uaccess.h>
-#include <asm/spinlock.h>
#include <asm/io.h>
@@ -631,7 +631,7 @@ static int cpqarray_pci_init(ctlr_info_t *c, unchar bus, unchar device_fn)
irq = pdev->irq;
for(i=0; i<6; i++)
- addr[i] = pdev->base_address[i];
+ addr[i] = pdev->resource[i].flags;
(void) pcibios_read_config_word(bus, device_fn,
PCI_COMMAND,&command);
@@ -665,7 +665,7 @@ DBGINFO(
*/
for(i=0; i<6; i++)
if (!(addr[i] & 0x1)) {
- c->paddr = addr[i];
+ c->paddr = pdev->resource[i].start;
break;
}
c->vaddr = remap_pci_mem(c->paddr, 128);
diff --git a/drivers/block/cy82c693.c b/drivers/block/cy82c693.c
index e1e46ea8a..e204bc0e6 100644
--- a/drivers/block/cy82c693.c
+++ b/drivers/block/cy82c693.c
@@ -369,6 +369,17 @@ static void cy82c693_tune_drive (ide_drive_t *drive, byte pio)
/*
* this function is called during init and is used to setup the cy82c693 chip
*/
+/*
+ * FIXME! "pci_init_cy82c693" really should replace
+ * the "init_cy82c693_chip", it is the correct location to tinker/setup
+ * the device prior to INIT.
+ */
+
+unsigned int __init pci_init_cy82c693(struct pci_dev *dev, const char *name)
+{
+ return 0;
+}
+
static void init_cy82c693_chip (struct pci_dev *dev)
{
static int initDone = 0;
@@ -420,7 +431,7 @@ static void init_cy82c693_chip (struct pci_dev *dev)
/*
* the init function - called for each ide channel once
*/
-__initfunc(void ide_init_cy82c693(ide_hwif_t *hwif))
+void __init ide_init_cy82c693(ide_hwif_t *hwif)
{
hwif->chipset = ide_cy82c693;
if (hwif->dma_base)
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index ae2ab6b0f..d74fdc369 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -106,6 +106,12 @@
* 1998/09/20 -- David Weinehall -- Added slow-down code for buggy PS/2-drives.
*/
+/*
+ * 1999/08/13 -- Paul Slootman -- floppy stopped working on Alpha after 24
+ * days, 6 hours, 32 minutes and 32 seconds (i.e. MAXINT jiffies; ints were
+ * being used to store jiffies, which are unsigned longs).
+ */
+
#define FLOPPY_SANITY_CHECK
#undef FLOPPY_SILENT_DCL_CLEAR
@@ -330,7 +336,6 @@ static int inr; /* size of reply buffer, when called from interrupt */
#define SEL_DLY (2*HZ/100)
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
/*
* this struct defines the different floppy drive types.
*/
@@ -607,10 +612,10 @@ static void is_alive(const char *message)
#define OLOGSIZE 20
static void (*lasthandler)(void) = NULL;
-static int interruptjiffies=0;
-static int resultjiffies=0;
+static unsigned long interruptjiffies=0;
+static unsigned long resultjiffies=0;
static int resultsize=0;
-static int lastredo=0;
+static unsigned long lastredo=0;
static struct output_log {
unsigned char data;
@@ -630,7 +635,7 @@ static void reschedule_timeout(int drive, const char *message, int marg)
drive = current_drive;
del_timer(&fd_timeout);
if (drive < 0 || drive > N_DRIVE) {
- fd_timeout.expires = jiffies + 20*HZ;
+ fd_timeout.expires = jiffies + 20UL*HZ;
drive=0;
} else
fd_timeout.expires = jiffies + UDP->timeout;
@@ -713,7 +718,7 @@ static int disk_change(int drive)
#ifdef DCL_DEBUG
if (UDP->flags & FD_DEBUG){
DPRINT("checking disk change line for drive %d\n",drive);
- DPRINT("jiffies=%ld\n", jiffies);
+ DPRINT("jiffies=%lu\n", jiffies);
DPRINT("disk change line=%x\n",fd_inb(FD_DIR)&0x80);
DPRINT("flags=%lx\n",UDRS->flags);
}
@@ -1007,7 +1012,7 @@ static void main_command_interrupt(void)
}
/* waits for a delay (spinup or select) to pass */
-static int wait_for_completion(int delay, timeout_fn function)
+static int wait_for_completion(unsigned long delay, timeout_fn function)
{
if (FDCS->reset){
reset_fdc(); /* do the reset during sleep to win time
@@ -1280,7 +1285,7 @@ static int fdc_configure(void)
static void fdc_specify(void)
{
unsigned char spec1, spec2;
- int srt, hlt, hut;
+ unsigned long srt, hlt, hut;
unsigned long dtr = NOMINAL_DTR;
unsigned long scale_dtr = NOMINAL_DTR;
int hlt_max_code = 0x7f;
@@ -1370,7 +1375,7 @@ static int fdc_dtr(void)
* Pause 5 msec to avoid trouble. (Needs to be 2 jiffies)
*/
FDCS->dtr = raw_cmd->rate & 3;
- return(wait_for_completion(jiffies+2*HZ/100,
+ return(wait_for_completion(jiffies+2UL*HZ/100,
(timeout_fn) floppy_ready));
} /* fdc_dtr */
@@ -1466,7 +1471,8 @@ static int interpret_errors(void)
*/
static void setup_rw_floppy(void)
{
- int i,ready_date,r, flags,dflags;
+ int i,r, flags,dflags;
+ unsigned long ready_date;
timeout_fn function;
flags = raw_cmd->flags;
@@ -1539,7 +1545,7 @@ static void seek_interrupt(void)
#ifdef DCL_DEBUG
if (DP->flags & FD_DEBUG){
DPRINT("clearing NEWCHANGE flag because of effective seek\n");
- DPRINT("jiffies=%ld\n", jiffies);
+ DPRINT("jiffies=%lu\n", jiffies);
}
#endif
CLEARF(FD_DISK_NEWCHANGE); /* effective seek */
@@ -1829,20 +1835,20 @@ static void show_floppy(void)
printk("\n");
printk("floppy driver state\n");
printk("-------------------\n");
- printk("now=%ld last interrupt=%d last called handler=%p\n",
- jiffies, interruptjiffies, lasthandler);
+ printk("now=%lu last interrupt=%lu diff=%lu last called handler=%p\n",
+ jiffies, interruptjiffies, jiffies-interruptjiffies, lasthandler);
#ifdef FLOPPY_SANITY_CHECK
printk("timeout_message=%s\n", timeout_message);
printk("last output bytes:\n");
for (i=0; i < OLOGSIZE; i++)
- printk("%2x %2x %ld\n",
+ printk("%2x %2x %lu\n",
output_log[(i+output_log_pos) % OLOGSIZE].data,
output_log[(i+output_log_pos) % OLOGSIZE].status,
output_log[(i+output_log_pos) % OLOGSIZE].jiffies);
- printk("last result at %d\n", resultjiffies);
- printk("last redo_fd_request at %d\n", lastredo);
+ printk("last result at %lu\n", resultjiffies);
+ printk("last redo_fd_request at %lu\n", lastredo);
for (i=0; i<resultsize; i++){
printk("%2x ", reply_buffer[i]);
}
@@ -1859,8 +1865,8 @@ static void show_floppy(void)
printk("fd_timer.function=%p\n", fd_timer.function);
if (fd_timeout.prev){
printk("timer_table=%p\n",fd_timeout.function);
- printk("expires=%ld\n",fd_timeout.expires-jiffies);
- printk("now=%ld\n",jiffies);
+ printk("expires=%lu\n",fd_timeout.expires-jiffies);
+ printk("now=%lu\n",jiffies);
}
printk("cont=%p\n", cont);
printk("CURRENT=%p\n", CURRENT);
@@ -3005,12 +3011,12 @@ static int user_reset_fdc(int drive, int arg, int interruptible)
* Misc Ioctl's and support
* ========================
*/
-static inline int fd_copyout(void *param, const void *address, int size)
+static inline int fd_copyout(void *param, const void *address, unsigned long size)
{
return copy_to_user(param,address, size) ? -EFAULT : 0;
}
-static inline int fd_copyin(void *param, void *address, int size)
+static inline int fd_copyin(void *param, void *address, unsigned long size)
{
return copy_from_user(address, param, size) ? -EFAULT : 0;
}
@@ -3808,7 +3814,7 @@ static int check_floppy_change(kdev_t dev)
if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY))
return 1;
- if (UDP->checkfreq < jiffies - UDRS->last_checked){
+ if (UDP->checkfreq < (int)(jiffies - UDRS->last_checked)) {
lock_fdc(drive,0);
poll_drive(0,0);
process_fd_request();
@@ -4064,11 +4070,13 @@ static struct param_table {
{ "no_unexpected_interrupts", 0, &print_unex, 0, 0 },
{ "L40SX", 0, &print_unex, 0, 0 } };
-#define FLOPPY_SETUP
-void __init floppy_setup(char *str, int *ints)
+static int __init floppy_setup(char *str)
{
int i;
int param;
+ int ints[11];
+
+ str = get_options(str,ARRAY_SIZE(ints),ints);
if (str) {
for (i=0; i< ARRAY_SIZE(config_params); i++){
if (strcmp(str,config_params[i].name) == 0){
@@ -4084,7 +4092,7 @@ void __init floppy_setup(char *str, int *ints)
DPRINT("%s=%d\n", str, param);
*config_params[i].var = param;
}
- return;
+ return 1;
}
}
}
@@ -4098,6 +4106,7 @@ void __init floppy_setup(char *str, int *ints)
} else
DPRINT("botched floppy option\n");
DPRINT("Read linux/drivers/block/README.fd\n");
+ return 1;
}
static int have_no_fdc= -EIO;
@@ -4361,14 +4370,11 @@ static void floppy_release_irq_and_dma(void)
#ifdef MODULE
-extern char *get_options(char *str, int *ints);
-
char *floppy=NULL;
static void __init parse_floppy_cfg_string(char *cfg)
{
char *ptr;
- int ints[11];
while(*cfg) {
for(ptr = cfg;*cfg && *cfg != ' ' && *cfg != '\t'; cfg++);
@@ -4377,18 +4383,17 @@ static void __init parse_floppy_cfg_string(char *cfg)
cfg++;
}
if(*ptr)
- floppy_setup(get_options(ptr,ints),ints);
+ floppy_setup(ptr);
}
}
-static void __init mod_setup(char *pattern, void (*setup)(char *, int *))
+static void __init mod_setup(char *pattern, int (*setup)(char *))
{
unsigned long i;
char c;
int j;
int match;
char buffer[100];
- int ints[11];
int length = strlen(pattern)+1;
match=0;
@@ -4403,7 +4408,7 @@ static void __init mod_setup(char *pattern, void (*setup)(char *, int *))
if (!c || c == ' ' || c == '\t'){
if (j){
buffer[j] = '\0';
- setup(get_options(buffer,ints),ints);
+ setup(buffer);
}
j=0;
} else
@@ -4461,6 +4466,9 @@ MODULE_SUPPORTED_DEVICE("fd");
#endif
#else
+
+__setup ("floppy=", floppy_setup);
+
/* eject the boot floppy (if we need the drive for a different root floppy) */
/* This should only be called at boot time when we're sure that there's no
* resource contention. */
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 5f4b38559..aece0447d 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -4,1452 +4,31 @@
*
* Copyright (C) 1991-1998 Linus Torvalds
*
- *
- * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
- * in the early extended-partition checks and added DM partitions
- *
- * Support for DiskManager v6.0x added by Mark Lord,
- * with information provided by OnTrack. This now works for linux fdisk
- * and LILO, as well as loadlin and bootln. Note that disks other than
- * /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
- *
- * More flexible handling of extended partitions - aeb, 950831
- *
- * Check partition table on IDE disks for common CHS translations
- *
- * Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl}
+ * Moved partition checking code to fs/partitions* - Russell King
+ * (linux@arm.uk.linux.org)
*/
#include <linux/config.h>
#include <linux/fs.h>
#include <linux/genhd.h>
#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/string.h>
#include <linux/blk.h>
#include <linux/init.h>
-#include <asm/system.h>
-#include <asm/byteorder.h>
-
-/*
- * Many architectures don't like unaligned accesses, which is
- * frequently the case with the nr_sects and start_sect partition
- * table entries.
- */
-#include <asm/unaligned.h>
-
-#define SYS_IND(p) (get_unaligned(&p->sys_ind))
-#define NR_SECTS(p) ({ __typeof__(p->nr_sects) __a = \
- get_unaligned(&p->nr_sects); \
- le32_to_cpu(__a); \
- })
-
-#define START_SECT(p) ({ __typeof__(p->start_sect) __a = \
- get_unaligned(&p->start_sect); \
- le32_to_cpu(__a); \
- })
-
-struct gendisk *gendisk_head = NULL;
-
-static int current_minor = 0;
-extern int *blk_size[];
-extern void rd_load(void);
-extern void initrd_load(void);
-
+extern int parport_init(void);
extern int chr_dev_init(void);
extern int blk_dev_init(void);
+#ifdef CONFIG_BLK_DEV_DAC960
+extern void DAC960_Initialize(void);
+#endif
extern int scsi_dev_init(void);
extern int net_dev_init(void);
-extern int i2o_init(void);
-
-#ifdef CONFIG_PPC
-extern void note_bootable_part(kdev_t dev, int part);
-#endif
-
-/*
- * disk_name() is used by genhd.c and blkpg.c.
- * It formats the devicename of the indicated disk into
- * the supplied buffer (of size at least 32), and returns
- * a pointer to that same buffer (for convenience).
- */
-char *disk_name (struct gendisk *hd, int minor, char *buf)
-{
- unsigned int part;
- const char *maj = hd->major_name;
- int unit = (minor >> hd->minor_shift) + 'a';
-
- /*
- * IDE devices use multiple major numbers, but the drives
- * are named as: {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
- * This requires special handling here.
- */
- switch (hd->major) {
- case IDE7_MAJOR:
- unit += 2;
- case IDE6_MAJOR:
- unit += 2;
- case IDE5_MAJOR:
- unit += 2;
- case IDE4_MAJOR:
- unit += 2;
- case IDE3_MAJOR:
- unit += 2;
- case IDE2_MAJOR:
- unit += 2;
- case IDE1_MAJOR:
- unit += 2;
- case IDE0_MAJOR:
- maj = "hd";
- break;
- }
- part = minor & ((1 << hd->minor_shift) - 1);
- if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
- unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
- if (unit > 'z') {
- unit -= 'z' + 1;
- sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);
- if (part)
- sprintf(buf + 4, "%d", part);
- return buf;
- }
- }
- if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) {
- int ctlr = hd->major - COMPAQ_SMART2_MAJOR;
- int disk = minor >> hd->minor_shift;
- int part = minor & (( 1 << hd->minor_shift) - 1);
- if (part == 0)
- sprintf(buf, "%s/c%dd%d", maj, ctlr, disk);
- else
- sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, disk, part);
- return buf;
- }
- if (part)
- sprintf(buf, "%s%c%d", maj, unit, part);
- else
- sprintf(buf, "%s%c", maj, unit);
- return buf;
-}
-
-static void add_partition (struct gendisk *hd, int minor, int start, int size)
-{
- char buf[40];
- hd->part[minor].start_sect = start;
- hd->part[minor].nr_sects = size;
- if (hd->major >= COMPAQ_SMART2_MAJOR+0 && hd->major <= COMPAQ_SMART2_MAJOR+7)
- printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
- else
- printk(" %s", disk_name(hd, minor, buf));
-}
-
-static inline int is_extended_partition(struct partition *p)
-{
- return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||
- SYS_IND(p) == WIN98_EXTENDED_PARTITION ||
- SYS_IND(p) == LINUX_EXTENDED_PARTITION);
-}
-
-int get_hardsect_size(kdev_t dev)
-{
- if (hardsect_size[MAJOR(dev)] != NULL)
- return hardsect_size[MAJOR(dev)][MINOR(dev)];
- else
- return 512;
-}
-
-static unsigned int get_ptable_blocksize(kdev_t dev)
-{
- int ret = 1024;
-
- /*
- * See whether the low-level driver has given us a minumum blocksize.
- * If so, check to see whether it is larger than the default of 1024.
- */
- if (!blksize_size[MAJOR(dev)])
- {
- return ret;
- }
-
- /*
- * Check for certain special power of two sizes that we allow.
- * With anything larger than 1024, we must force the blocksize up to
- * the natural blocksize for the device so that we don't have to try
- * and read partial sectors. Anything smaller should be just fine.
- */
-
- switch( blksize_size[MAJOR(dev)][MINOR(dev)] )
- {
- case 2048:
- ret = 2048;
- break;
- case 4096:
- ret = 4096;
- break;
- case 8192:
- ret = 8192;
- break;
- case 1024:
- case 512:
- case 256:
- case 0:
- /*
- * These are all OK.
- */
- break;
- default:
- panic("Strange blocksize for partition table\n");
- }
-
- return ret;
-
-}
-
-#ifdef CONFIG_MSDOS_PARTITION
-/*
- * Create devices for each logical partition in an extended partition.
- * The logical partitions form a linked list, with each entry being
- * a partition table with two entries. The first entry
- * is the real data partition (with a start relative to the partition
- * table start). The second is a pointer to the next logical partition
- * (with a start relative to the entire extended partition).
- * We do not create a Linux partition for the partition tables, but
- * only for the actual data partitions.
- */
-
-#define MSDOS_LABEL_MAGIC 0xAA55
-
-static void extended_partition(struct gendisk *hd, kdev_t dev)
-{
- struct buffer_head *bh;
- struct partition *p;
- unsigned long first_sector, first_size, this_sector, this_size;
- int mask = (1 << hd->minor_shift) - 1;
- int sector_size = get_hardsect_size(dev) / 512;
- int i;
-
- first_sector = hd->part[MINOR(dev)].start_sect;
- first_size = hd->part[MINOR(dev)].nr_sects;
- this_sector = first_sector;
-
- while (1) {
- if ((current_minor & mask) == 0)
- return;
- if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
- return;
-
- if ((*(__u16 *) (bh->b_data+510)) != cpu_to_le16(MSDOS_LABEL_MAGIC))
- goto done;
-
- p = (struct partition *) (0x1BE + bh->b_data);
-
- this_size = hd->part[MINOR(dev)].nr_sects;
-
- /*
- * Usually, the first entry is the real data partition,
- * the 2nd entry is the next extended partition, or empty,
- * and the 3rd and 4th entries are unused.
- * However, DRDOS sometimes has the extended partition as
- * the first entry (when the data partition is empty),
- * and OS/2 seems to use all four entries.
- */
-
- /*
- * First process the data partition(s)
- */
- for (i=0; i<4; i++, p++) {
- if (!NR_SECTS(p) || is_extended_partition(p))
- continue;
-
- /* Check the 3rd and 4th entries -
- these sometimes contain random garbage */
- if (i >= 2
- && START_SECT(p) + NR_SECTS(p) > this_size
- && (this_sector + START_SECT(p) < first_sector ||
- this_sector + START_SECT(p) + NR_SECTS(p) >
- first_sector + first_size))
- continue;
-
- add_partition(hd, current_minor, this_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size);
- current_minor++;
- if ((current_minor & mask) == 0)
- goto done;
- }
- /*
- * Next, process the (first) extended partition, if present.
- * (So far, there seems to be no reason to make
- * extended_partition() recursive and allow a tree
- * of extended partitions.)
- * It should be a link to the next logical partition.
- * Create a minor for this just long enough to get the next
- * partition table. The minor will be reused for the next
- * data partition.
- */
- p -= 4;
- for (i=0; i<4; i++, p++)
- if(NR_SECTS(p) && is_extended_partition(p))
- break;
- if (i == 4)
- goto done; /* nothing left to do */
-
- hd->part[current_minor].nr_sects = NR_SECTS(p) * sector_size; /* JSt */
- hd->part[current_minor].start_sect = first_sector + START_SECT(p) * sector_size;
- this_sector = first_sector + START_SECT(p) * sector_size;
- dev = MKDEV(hd->major, current_minor);
-
- /* Use bforget(), as we have changed the disk geometry */
- bforget(bh);
- }
-done:
- bforget(bh);
-}
-
-#ifdef CONFIG_SOLARIS_X86_PARTITION
-static void
-solaris_x86_partition(struct gendisk *hd, kdev_t dev, long offset) {
-
- struct buffer_head *bh;
- struct solaris_x86_vtoc *v;
- struct solaris_x86_slice *s;
- int i;
-
- if(!(bh = bread(dev, 0, get_ptable_blocksize(dev))))
- return;
- v = (struct solaris_x86_vtoc *)(bh->b_data + 512);
- if(v->v_sanity != SOLARIS_X86_VTOC_SANE) {
- brelse(bh);
- return;
- }
- printk(" <solaris:");
- if(v->v_version != 1) {
- printk(" cannot handle version %ld vtoc>", v->v_version);
- brelse(bh);
- return;
- }
- for(i=0; i<SOLARIS_X86_NUMSLICE; i++) {
- s = &v->v_slice[i];
-
- if (s->s_size == 0)
- continue;
- printk(" [s%d]", i);
- /* solaris partitions are relative to current MS-DOS
- * one but add_partition starts relative to sector
- * zero of the disk. Therefore, must add the offset
- * of the current partition */
- add_partition(hd, current_minor, s->s_start+offset, s->s_size);
- current_minor++;
- }
- brelse(bh);
- printk(" >");
-}
-#endif
-
-#ifdef CONFIG_BSD_DISKLABEL
-static void check_and_add_bsd_partition(struct gendisk *hd,
- struct bsd_partition *bsd_p, kdev_t dev)
-{
- struct hd_struct *lin_p;
- /* check relative position of partitions. */
- for (lin_p = hd->part + 1 + MINOR(dev);
- lin_p - hd->part - MINOR(dev) < current_minor; lin_p++) {
- /* no relationship -> try again */
- if (lin_p->start_sect + lin_p->nr_sects <= bsd_p->p_offset
- || lin_p->start_sect >= bsd_p->p_offset + bsd_p->p_size)
- continue;
- /* equal -> no need to add */
- if (lin_p->start_sect == bsd_p->p_offset &&
- lin_p->nr_sects == bsd_p->p_size)
- return;
- /* bsd living within dos partition */
- if (lin_p->start_sect <= bsd_p->p_offset && lin_p->start_sect
- + lin_p->nr_sects >= bsd_p->p_offset + bsd_p->p_size) {
-#ifdef DEBUG_BSD_DISKLABEL
- printk("w: %d %ld+%ld,%d+%d",
- lin_p - hd->part,
- lin_p->start_sect, lin_p->nr_sects,
- bsd_p->p_offset, bsd_p->p_size);
-#endif
- break;
- }
- /* ouch: bsd and linux overlap. Don't even try for that partition */
-#ifdef DEBUG_BSD_DISKLABEL
- printk("???: %d %ld+%ld,%d+%d",
- lin_p - hd->part, lin_p->start_sect, lin_p->nr_sects,
- bsd_p->p_offset, bsd_p->p_size);
-#endif
- printk("???");
- return;
- } /* if the bsd partition is not currently known to linux, we end
- * up here
- */
- add_partition(hd, current_minor, bsd_p->p_offset, bsd_p->p_size);
- current_minor++;
-}
-/*
- * Create devices for BSD partitions listed in a disklabel, under a
- * dos-like partition. See extended_partition() for more information.
- */
-static void bsd_disklabel_partition(struct gendisk *hd, kdev_t dev,
- int max_partitions)
-{
- struct buffer_head *bh;
- struct bsd_disklabel *l;
- struct bsd_partition *p;
- int mask = (1 << hd->minor_shift) - 1;
-
- if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
- return;
- l = (struct bsd_disklabel *) (bh->b_data+512);
- if (l->d_magic != BSD_DISKMAGIC) {
- brelse(bh);
- return;
- }
-
- if (l->d_npartitions < max_partitions)
- max_partitions = l->d_npartitions;
- for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) {
- if ((current_minor & mask) >= (4 + hd->max_p))
- break;
-
- if (p->p_fstype != BSD_FS_UNUSED)
- check_and_add_bsd_partition(hd, p, dev);
- }
-
- /* Use bforget(), as we have changed the disk setup */
- bforget(bh);
-
-}
-#endif
-
-#ifdef CONFIG_UNIXWARE_DISKLABEL
-/*
- * Create devices for Unixware partitions listed in a disklabel, under a
- * dos-like partition. See extended_partition() for more information.
- */
-static void unixware_partition(struct gendisk *hd, kdev_t dev)
-{
- struct buffer_head *bh;
- struct unixware_disklabel *l;
- struct unixware_slice *p;
- int mask = (1 << hd->minor_shift) - 1;
-
- if (!(bh = bread(dev, 14, get_ptable_blocksize(dev))))
- return;
- l = (struct unixware_disklabel *) (bh->b_data+512);
- if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
- le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {
- brelse(bh);
- return;
- }
- printk(" <unixware:");
- p = &l->vtoc.v_slice[1];
- /* I omit the 0th slice as it is the same as whole disk. */
- while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
- if ((current_minor & mask) == 0)
- break;
-
- if (p->s_label != UNIXWARE_FS_UNUSED) {
- add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
- current_minor++;
- }
- p++;
- }
- /* Use bforget, as we have changed the disk setup */
- bforget(bh);
- printk(" >");
-}
-#endif
-
-static int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
-{
- int i, minor = current_minor;
- struct buffer_head *bh;
- struct partition *p;
- unsigned char *data;
- int mask = (1 << hd->minor_shift) - 1;
- int sector_size = get_hardsect_size(dev) / 512;
-#ifdef CONFIG_BSD_DISKLABEL
- /* no bsd disklabel as a default */
- kdev_t bsd_kdev = 0;
- int bsd_maxpart = BSD_MAXPARTITIONS;
-#endif
-#ifdef CONFIG_BLK_DEV_IDE
- int tested_for_xlate = 0;
-
-read_mbr:
-#endif
- if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
- printk(" unable to read partition table\n");
- return -1;
- }
- data = bh->b_data;
-#ifdef CONFIG_BLK_DEV_IDE
-check_table:
-#endif
- /* Use bforget(), because we have potentially changed the disk geometry */
- if (*(unsigned short *) (0x1fe + data) != cpu_to_le16(MSDOS_LABEL_MAGIC)) {
- bforget(bh);
- return 0;
- }
- p = (struct partition *) (0x1be + data);
-
-#ifdef CONFIG_BLK_DEV_IDE
- if (!tested_for_xlate++) { /* Do this only once per disk */
- /*
- * Look for various forms of IDE disk geometry translation
- */
- extern int ide_xlate_1024(kdev_t, int, const char *);
- unsigned int sig = le16_to_cpu(*(unsigned short *)(data + 2));
- if (SYS_IND(p) == EZD_PARTITION) {
- /*
- * The remainder of the disk must be accessed using
- * a translated geometry that reduces the number of
- * apparent cylinders to less than 1024 if possible.
- *
- * ide_xlate_1024() will take care of the necessary
- * adjustments to fool fdisk/LILO and partition check.
- */
- if (ide_xlate_1024(dev, -1, " [EZD]")) {
- data += 512;
- goto check_table;
- }
- } else if (SYS_IND(p) == DM6_PARTITION) {
-
- /*
- * Everything on the disk is offset by 63 sectors,
- * including a "new" MBR with its own partition table,
- * and the remainder of the disk must be accessed using
- * a translated geometry that reduces the number of
- * apparent cylinders to less than 1024 if possible.
- *
- * ide_xlate_1024() will take care of the necessary
- * adjustments to fool fdisk/LILO and partition check.
- */
- if (ide_xlate_1024(dev, 1, " [DM6:DDO]")) {
- bforget(bh);
- goto read_mbr; /* start over with new MBR */
- }
- } else if (sig <= 0x1ae &&
- *(unsigned short *)(data + sig) == cpu_to_le16(0x55AA) &&
- (1 & *(unsigned char *)(data + sig + 2))) {
- /* DM6 signature in MBR, courtesy of OnTrack */
- (void) ide_xlate_1024 (dev, 0, " [DM6:MBR]");
- } else if (SYS_IND(p) == DM6_AUX1PARTITION || SYS_IND(p) == DM6_AUX3PARTITION) {
- /*
- * DM6 on other than the first (boot) drive
- */
- (void) ide_xlate_1024(dev, 0, " [DM6:AUX]");
- } else {
- /*
- * Examine the partition table for common translations.
- * This is useful for drives in situations where the
- * translated geometry is unavailable from the BIOS.
- */
- for (i = 0; i < 4; i++) {
- struct partition *q = &p[i];
- if (NR_SECTS(q)
- && (q->sector & 63) == 1
- && (q->end_sector & 63) == 63) {
- unsigned int heads = q->end_head + 1;
- if (heads == 32 || heads == 64 ||
- heads == 128 || heads == 240 ||
- heads == 255) {
- (void) ide_xlate_1024(dev, heads, " [PTBL]");
- break;
- }
- }
- }
- }
- }
-#endif /* CONFIG_BLK_DEV_IDE */
-
- current_minor += 4; /* first "extra" minor (for extended partitions) */
- for (i=1 ; i<=4 ; minor++,i++,p++) {
- if (!NR_SECTS(p))
- continue;
- add_partition(hd, minor, first_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size);
- if (is_extended_partition(p)) {
- printk(" <");
- /*
- * If we are rereading the partition table, we need
- * to set the size of the partition so that we will
- * be able to bread the block containing the extended
- * partition info.
- */
- hd->sizes[minor] = hd->part[minor].nr_sects
- >> (BLOCK_SIZE_BITS - 9);
- extended_partition(hd, MKDEV(hd->major, minor));
- printk(" >");
- /* prevent someone doing mkfs or mkswap on an
- extended partition, but leave room for LILO */
- if (hd->part[minor].nr_sects > 2)
- hd->part[minor].nr_sects = 2;
- }
-#ifdef CONFIG_BSD_DISKLABEL
- /* tag first disklabel for late recognition */
- if (SYS_IND(p) == BSD_PARTITION || SYS_IND(p) == NETBSD_PARTITION) {
- printk("!");
- if (!bsd_kdev)
- bsd_kdev = MKDEV(hd->major, minor);
- } else if (SYS_IND(p) == OPENBSD_PARTITION) {
- printk("!");
- if (!bsd_kdev) {
- bsd_kdev = MKDEV(hd->major, minor);
- bsd_maxpart = OPENBSD_MAXPARTITIONS;
- }
- }
-#endif
-#ifdef CONFIG_UNIXWARE_DISKLABEL
- if (SYS_IND(p) == UNIXWARE_PARTITION)
- unixware_partition(hd, MKDEV(hd->major, minor));
-#endif
-#ifdef CONFIG_SOLARIS_X86_PARTITION
-
- /* james@bpgc.com: Solaris has a nasty indicator: 0x82
- * which also means linux swap. For that reason, all
- * of the prints are done inside the
- * solaris_x86_partition routine */
-
- if(SYS_IND(p) == SOLARIS_X86_PARTITION) {
- solaris_x86_partition(hd, MKDEV(hd->major, minor),
- first_sector+START_SECT(p));
- }
-#endif
- }
-#ifdef CONFIG_BSD_DISKLABEL
- if (bsd_kdev) {
- printk(" <");
- bsd_disklabel_partition(hd, bsd_kdev, bsd_maxpart);
- printk(" >");
- }
-#endif
- /*
- * Check for old-style Disk Manager partition table
- */
- if (*(unsigned short *) (data+0xfc) == cpu_to_le16(MSDOS_LABEL_MAGIC)) {
- p = (struct partition *) (0x1be + data);
- for (i = 4 ; i < 16 ; i++, current_minor++) {
- p--;
- if ((current_minor & mask) == 0)
- break;
- if (!(START_SECT(p) && NR_SECTS(p)))
- continue;
- add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
- }
- }
- printk("\n");
- bforget(bh);
- return 1;
-}
-
-#endif /* CONFIG_MSDOS_PARTITION */
-
-#ifdef CONFIG_OSF_PARTITION
-
-static int osf_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
-{
- int i;
- int mask = (1 << hd->minor_shift) - 1;
- struct buffer_head *bh;
- struct disklabel {
- u32 d_magic;
- u16 d_type,d_subtype;
- u8 d_typename[16];
- u8 d_packname[16];
- u32 d_secsize;
- u32 d_nsectors;
- u32 d_ntracks;
- u32 d_ncylinders;
- u32 d_secpercyl;
- u32 d_secprtunit;
- u16 d_sparespertrack;
- u16 d_sparespercyl;
- u32 d_acylinders;
- u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
- u32 d_headswitch, d_trkseek, d_flags;
- u32 d_drivedata[5];
- u32 d_spare[5];
- u32 d_magic2;
- u16 d_checksum;
- u16 d_npartitions;
- u32 d_bbsize, d_sbsize;
- struct d_partition {
- u32 p_size;
- u32 p_offset;
- u32 p_fsize;
- u8 p_fstype;
- u8 p_frag;
- u16 p_cpg;
- } d_partitions[8];
- } * label;
- struct d_partition * partition;
-#define DISKLABELMAGIC (0x82564557UL)
-
- if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
- printk("unable to read partition table\n");
- return -1;
- }
- label = (struct disklabel *) (bh->b_data+64);
- partition = label->d_partitions;
- if (label->d_magic != DISKLABELMAGIC) {
- brelse(bh);
- return 0;
- }
- if (label->d_magic2 != DISKLABELMAGIC) {
- brelse(bh);
- return 0;
- }
- for (i = 0 ; i < label->d_npartitions; i++, partition++) {
- if ((current_minor & mask) == 0)
- break;
- if (partition->p_size)
- add_partition(hd, current_minor,
- first_sector+partition->p_offset,
- partition->p_size);
- current_minor++;
- }
- printk("\n");
- brelse(bh);
- return 1;
-}
-
-#endif /* CONFIG_OSF_PARTITION */
-
-#ifdef CONFIG_SUN_PARTITION
-
-static int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
-{
- int i, csum;
- unsigned short *ush;
- struct buffer_head *bh;
- struct sun_disklabel {
- unsigned char info[128]; /* Informative text string */
- unsigned char spare[292]; /* Boot information etc. */
- unsigned short rspeed; /* Disk rotational speed */
- unsigned short pcylcount; /* Physical cylinder count */
- unsigned short sparecyl; /* extra sects per cylinder */
- unsigned char spare2[4]; /* More magic... */
- unsigned short ilfact; /* Interleave factor */
- unsigned short ncyl; /* Data cylinder count */
- unsigned short nacyl; /* Alt. cylinder count */
- unsigned short ntrks; /* Tracks per cylinder */
- unsigned short nsect; /* Sectors per track */
- unsigned char spare3[4]; /* Even more magic... */
- struct sun_partition {
- __u32 start_cylinder;
- __u32 num_sectors;
- } partitions[8];
- unsigned short magic; /* Magic number */
- unsigned short csum; /* Label xor'd checksum */
- } * label;
- struct sun_partition *p;
- unsigned long spc;
-#define SUN_LABEL_MAGIC 0xDABE
-
- if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) {
- printk("Dev %s: unable to read partition table\n",
- kdevname(dev));
- return -1;
- }
- label = (struct sun_disklabel *) bh->b_data;
- p = label->partitions;
- if (be16_to_cpu(label->magic) != SUN_LABEL_MAGIC) {
- printk("Dev %s Sun disklabel: bad magic %04x\n",
- kdevname(dev), be16_to_cpu(label->magic));
- brelse(bh);
- return 0;
- }
- /* Look at the checksum */
- ush = ((unsigned short *) (label+1)) - 1;
- for(csum = 0; ush >= ((unsigned short *) label);)
- csum ^= *ush--;
- if(csum) {
- printk("Dev %s Sun disklabel: Csum bad, label corrupted\n",
- kdevname(dev));
- brelse(bh);
- return 0;
- }
- /* All Sun disks have 8 partition entries */
- spc = be16_to_cpu(label->ntrks) * be16_to_cpu(label->nsect);
- for(i=0; i < 8; i++, p++) {
- unsigned long st_sector;
- int num_sectors;
-
- st_sector = first_sector + be32_to_cpu(p->start_cylinder) * spc;
- num_sectors = be32_to_cpu(p->num_sectors);
- if (num_sectors)
- add_partition(hd, current_minor, st_sector, num_sectors);
- current_minor++;
- }
- printk("\n");
- brelse(bh);
- return 1;
-}
-
-#endif /* CONFIG_SUN_PARTITION */
-
-#ifdef CONFIG_SGI_PARTITION
-
-static int sgi_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
-{
- int i, csum, magic;
- unsigned int *ui, start, blocks, cs;
- struct buffer_head *bh;
- struct sgi_disklabel {
- int magic_mushroom; /* Big fat spliff... */
- short root_part_num; /* Root partition number */
- short swap_part_num; /* Swap partition number */
- char boot_file[16]; /* Name of boot file for ARCS */
- unsigned char _unused0[48]; /* Device parameter useless crapola.. */
- struct sgi_volume {
- char name[8]; /* Name of volume */
- int block_num; /* Logical block number */
- int num_bytes; /* How big, in bytes */
- } volume[15];
- struct sgi_partition {
- int num_blocks; /* Size in logical blocks */
- int first_block; /* First logical block */
- int type; /* Type of this partition */
- } partitions[16];
- int csum; /* Disk label checksum */
- int _unused1; /* Padding */
- } *label;
- struct sgi_partition *p;
-#define SGI_LABEL_MAGIC 0x0be5a941
-
- if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) {
- printk("Dev %s: unable to read partition table\n", kdevname(dev));
- return -1;
- }
- label = (struct sgi_disklabel *) bh->b_data;
- p = &label->partitions[0];
- magic = label->magic_mushroom;
- if(be32_to_cpu(magic) != SGI_LABEL_MAGIC) {
- printk("Dev %s SGI disklabel: bad magic %08x\n",
- kdevname(dev), magic);
- brelse(bh);
- return 0;
- }
- ui = ((unsigned int *) (label + 1)) - 1;
- for(csum = 0; ui >= ((unsigned int *) label);) {
- cs = *ui--;
- csum += be32_to_cpu(cs);
- }
- if(csum) {
- printk("Dev %s SGI disklabel: csum bad, label corrupted\n",
- kdevname(dev));
- brelse(bh);
- return 0;
- }
- /* All SGI disk labels have 16 partitions, disks under Linux only
- * have 15 minor's. Luckily there are always a few zero length
- * partitions which we don't care about so we never overflow the
- * current_minor.
- */
- for(i = 0; i < 16; i++, p++) {
- blocks = be32_to_cpu(p->num_blocks);
- start = be32_to_cpu(p->first_block);
- if(!blocks)
- continue;
- add_partition(hd, current_minor, start, blocks);
- current_minor++;
- }
- printk("\n");
- brelse(bh);
- return 1;
-}
-
-#endif
-
-#ifdef CONFIG_AMIGA_PARTITION
-#include <linux/affs_hardblocks.h>
-
-static __inline__ u32
-checksum_block(u32 *m, int size)
-{
- u32 sum = 0;
-
- while (size--)
- sum += htonl(*m++);
- return sum;
-}
+extern void console_map_init(void);
+extern int soc_probe(void);
+extern int atmdev_init(void);
-static int
-amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
+void __init device_init(void)
{
- struct buffer_head *bh;
- struct RigidDiskBlock *rdb;
- struct PartitionBlock *pb;
- int start_sect;
- int nr_sects;
- int blk;
- int part, res;
- int old_blocksize;
- int blocksize;
-
- old_blocksize = get_ptable_blocksize(dev);
- blocksize = get_hardsect_size(dev);
-
- set_blocksize(dev,blocksize);
- res = 0;
-
- for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) {
- if(!(bh = bread(dev,blk,blocksize))) {
- printk("Dev %s: unable to read RDB block %d\n",
- kdevname(dev),blk);
- goto rdb_done;
- }
- if (*(u32 *)bh->b_data == htonl(IDNAME_RIGIDDISK)) {
- rdb = (struct RigidDiskBlock *)bh->b_data;
- if (checksum_block((u32 *)bh->b_data,htonl(rdb->rdb_SummedLongs) & 0x7F)) {
- /* Try again with 0xdc..0xdf zeroed, Windows might have
- * trashed it.
- */
- *(u32 *)(&bh->b_data[0xdc]) = 0;
- if (checksum_block((u32 *)bh->b_data,
- htonl(rdb->rdb_SummedLongs) & 0x7F)) {
- brelse(bh);
- printk("Dev %s: RDB in block %d has bad checksum\n",
- kdevname(dev),blk);
- continue;
- }
- printk("Warning: Trashed word at 0xd0 in block %d "
- "ignored in checksum calculation\n",blk);
- }
- printk(" RDSK");
- blk = htonl(rdb->rdb_PartitionList);
- brelse(bh);
- for (part = 1; blk > 0 && part <= 16; part++) {
- if (!(bh = bread(dev,blk,blocksize))) {
- printk("Dev %s: unable to read partition block %d\n",
- kdevname(dev),blk);
- goto rdb_done;
- }
- pb = (struct PartitionBlock *)bh->b_data;
- blk = htonl(pb->pb_Next);
- if (pb->pb_ID == htonl(IDNAME_PARTITION) && checksum_block(
- (u32 *)pb,htonl(pb->pb_SummedLongs) & 0x7F) == 0 ) {
-
- /* Tell Kernel about it */
-
- if (!(nr_sects = (htonl(pb->pb_Environment[10]) + 1 -
- htonl(pb->pb_Environment[9])) *
- htonl(pb->pb_Environment[3]) *
- htonl(pb->pb_Environment[5]))) {
- brelse(bh);
- continue;
- }
- start_sect = htonl(pb->pb_Environment[9]) *
- htonl(pb->pb_Environment[3]) *
- htonl(pb->pb_Environment[5]);
- add_partition(hd,current_minor,start_sect,nr_sects);
- current_minor++;
- res = 1;
- }
- brelse(bh);
- }
- printk("\n");
- }
- else
- brelse(bh);
- }
-
-rdb_done:
- set_blocksize(dev,old_blocksize);
- return res;
-}
-#endif /* CONFIG_AMIGA_PARTITION */
-
-#ifdef CONFIG_MAC_PARTITION
-#include <linux/ctype.h>
-
-/*
- * Code to understand MacOS partition tables.
- */
-
-#define MAC_PARTITION_MAGIC 0x504d
-
-/* type field value for A/UX or other Unix partitions */
-#define APPLE_AUX_TYPE "Apple_UNIX_SVR2"
-
-struct mac_partition {
- __u16 signature; /* expected to be MAC_PARTITION_MAGIC */
- __u16 res1;
- __u32 map_count; /* # blocks in partition map */
- __u32 start_block; /* absolute starting block # of partition */
- __u32 block_count; /* number of blocks in partition */
- char name[32]; /* partition name */
- char type[32]; /* string type description */
- __u32 data_start; /* rel block # of first data block */
- __u32 data_count; /* number of data blocks */
- __u32 status; /* partition status bits */
- __u32 boot_start;
- __u32 boot_size;
- __u32 boot_load;
- __u32 boot_load2;
- __u32 boot_entry;
- __u32 boot_entry2;
- __u32 boot_cksum;
- char processor[16]; /* identifies ISA of boot */
- /* there is more stuff after this that we don't need */
-};
-
-#define MAC_STATUS_BOOTABLE 8 /* partition is bootable */
-
-#define MAC_DRIVER_MAGIC 0x4552
-
-/* Driver descriptor structure, in block 0 */
-struct mac_driver_desc {
- __u16 signature; /* expected to be MAC_DRIVER_MAGIC */
- __u16 block_size;
- __u32 block_count;
- /* ... more stuff */
-};
-
-static int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec)
-{
- struct buffer_head *bh;
- int blk, blocks_in_map;
- int dev_bsize, dev_pos, pos;
- unsigned secsize;
-#ifdef CONFIG_PPC
- int first_bootable = 1;
-#endif
- struct mac_partition *part;
- struct mac_driver_desc *md;
-
- dev_bsize = get_ptable_blocksize(dev);
- dev_pos = 0;
- /* Get 0th block and look at the first partition map entry. */
- if ((bh = bread(dev, 0, dev_bsize)) == 0) {
- printk("%s: error reading partition table\n",
- kdevname(dev));
- return -1;
- }
- md = (struct mac_driver_desc *) bh->b_data;
- if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC) {
- brelse(bh);
- return 0;
- }
- secsize = be16_to_cpu(md->block_size);
- if (secsize >= dev_bsize) {
- brelse(bh);
- dev_pos = secsize;
- if ((bh = bread(dev, secsize/dev_bsize, dev_bsize)) == 0) {
- printk("%s: error reading partition table\n",
- kdevname(dev));
- return -1;
- }
- }
- part = (struct mac_partition *) (bh->b_data + secsize - dev_pos);
- if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) {
- brelse(bh);
- return 0; /* not a MacOS disk */
- }
- blocks_in_map = be32_to_cpu(part->map_count);
- for (blk = 1; blk <= blocks_in_map; ++blk) {
- pos = blk * secsize;
- if (pos >= dev_pos + dev_bsize) {
- brelse(bh);
- dev_pos = pos;
- if ((bh = bread(dev, pos/dev_bsize, dev_bsize)) == 0) {
- printk("%s: error reading partition table\n",
- kdevname(dev));
- return -1;
- }
- }
- part = (struct mac_partition *) (bh->b_data + pos - dev_pos);
- if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
- break;
- blocks_in_map = be32_to_cpu(part->map_count);
- add_partition(hd, current_minor,
- fsec + be32_to_cpu(part->start_block) * (secsize/512),
- be32_to_cpu(part->block_count) * (secsize/512));
-
-#ifdef CONFIG_PPC
- /*
- * If this is the first bootable partition, tell the
- * setup code, in case it wants to make this the root.
- */
- if ( (_machine == _MACH_Pmac) && first_bootable
- && (be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE)
- && strcasecmp(part->processor, "powerpc") == 0) {
- note_bootable_part(dev, blk);
- first_bootable = 0;
- }
-#endif /* CONFIG_PPC */
-
- ++current_minor;
- }
- brelse(bh);
- printk("\n");
- return 1;
-}
-
-#endif /* CONFIG_MAC_PARTITION */
-
-#ifdef CONFIG_ATARI_PARTITION
-#include <linux/atari_rootsec.h>
-
-/* ++guenther: this should be settable by the user ("make config")?.
- */
-#define ICD_PARTS
-
-static int atari_partition (struct gendisk *hd, kdev_t dev,
- unsigned long first_sector)
-{
- int minor = current_minor, m_lim = current_minor + hd->max_p;
- struct buffer_head *bh;
- struct rootsector *rs;
- struct partition_info *pi;
- ulong extensect;
- unsigned int psum;
- int i;
-#ifdef ICD_PARTS
- int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */
-#endif
-
- bh = bread (dev, 0, get_ptable_blocksize(dev));
- if (!bh) {
- printk (" unable to read block 0 (partition table)\n");
- return -1;
- }
-
- /* Verify this is an Atari rootsector: */
- psum=0;
- for (i=0;i<256;i++) {
- psum+=ntohs(((__u16 *) (bh->b_data))[i]);
- }
- if ((psum & 0xFFFF) != 0x1234) {
- brelse(bh);
- return 0;
- }
-
- rs = (struct rootsector *) bh->b_data;
- pi = &rs->part[0];
- printk (" AHDI");
- for (; pi < &rs->part[4] && minor < m_lim; minor++, pi++)
- {
- if (pi->flg & 1)
- /* active partition */
- {
- if (memcmp (pi->id, "XGM", 3) == 0)
- /* extension partition */
- {
- struct rootsector *xrs;
- struct buffer_head *xbh;
- ulong partsect;
-
-#ifdef ICD_PARTS
- part_fmt = 1;
-#endif
- printk(" XGM<");
- partsect = extensect = ntohl(pi->st);
- while (1)
- {
- xbh = bread (dev, partsect / 2, get_ptable_blocksize(dev));
- if (!xbh)
- {
- printk (" block %ld read failed\n", partsect);
- brelse(bh);
- return 0;
- }
- if (partsect & 1)
- xrs = (struct rootsector *) &xbh->b_data[512];
- else
- xrs = (struct rootsector *) &xbh->b_data[0];
-
- /* ++roman: sanity check: bit 0 of flg field must be set */
- if (!(xrs->part[0].flg & 1)) {
- printk( "\nFirst sub-partition in extended partition is not valid!\n" );
- break;
- }
-
- add_partition(hd, minor, partsect + ntohl(xrs->part[0].st),
- ntohl(xrs->part[0].siz));
-
- if (!(xrs->part[1].flg & 1)) {
- /* end of linked partition list */
- brelse( xbh );
- break;
- }
- if (memcmp( xrs->part[1].id, "XGM", 3 ) != 0) {
- printk( "\nID of extended partition is not XGM!\n" );
- brelse( xbh );
- break;
- }
-
- partsect = ntohl(xrs->part[1].st) + extensect;
- brelse (xbh);
- minor++;
- if (minor >= m_lim) {
- printk( "\nMaximum number of partitions reached!\n" );
- break;
- }
- }
- printk(" >");
- }
- else
- {
- /* we don't care about other id's */
- add_partition (hd, minor, ntohl(pi->st), ntohl(pi->siz));
- }
- }
- }
-#ifdef ICD_PARTS
- if ( part_fmt!=1 ) /* no extended partitions -> test ICD-format */
- {
- pi = &rs->icdpart[0];
- /* sanity check: no ICD format if first partition invalid */
- if (memcmp (pi->id, "GEM", 3) == 0 ||
- memcmp (pi->id, "BGM", 3) == 0 ||
- memcmp (pi->id, "LNX", 3) == 0 ||
- memcmp (pi->id, "SWP", 3) == 0 ||
- memcmp (pi->id, "RAW", 3) == 0 )
- {
- printk(" ICD<");
- for (; pi < &rs->icdpart[8] && minor < m_lim; minor++, pi++)
- {
- /* accept only GEM,BGM,RAW,LNX,SWP partitions */
- if (pi->flg & 1 &&
- (memcmp (pi->id, "GEM", 3) == 0 ||
- memcmp (pi->id, "BGM", 3) == 0 ||
- memcmp (pi->id, "LNX", 3) == 0 ||
- memcmp (pi->id, "SWP", 3) == 0 ||
- memcmp (pi->id, "RAW", 3) == 0) )
- {
- part_fmt = 2;
- add_partition (hd, minor, ntohl(pi->st), ntohl(pi->siz));
- }
- }
- printk(" >");
- }
- }
-#endif
- brelse (bh);
-
- printk ("\n");
-
- return 1;
-}
-#endif /* CONFIG_ATARI_PARTITION */
-
-#ifdef CONFIG_ULTRIX_PARTITION
-
-static int ultrix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
-{
- int i, minor = current_minor;
- struct buffer_head *bh;
- struct ultrix_disklabel {
- long pt_magic; /* magic no. indicating part. info exits */
- int pt_valid; /* set by driver if pt is current */
- struct pt_info {
- int pi_nblocks; /* no. of sectors */
- unsigned long pi_blkoff; /* block offset for start */
- } pt_part[8];
- } *label;
-
-#define PT_MAGIC 0x032957 /* Partition magic number */
-#define PT_VALID 1 /* Indicates if struct is valid */
-
-#define SBLOCK ((unsigned long)((16384 - sizeof(struct ultrix_disklabel)) \
- /get_ptable_blocksize(dev)))
-
- bh = bread (dev, SBLOCK, get_ptable_blocksize(dev));
- if (!bh) {
- printk (" unable to read block 0x%lx\n", SBLOCK);
- return -1;
- }
-
- label = (struct ultrix_disklabel *)(bh->b_data
- + get_ptable_blocksize(dev)
- - sizeof(struct ultrix_disklabel));
-
- if (label->pt_magic == PT_MAGIC && label->pt_valid == PT_VALID) {
- for (i=0; i<8; i++, minor++)
- if (label->pt_part[i].pi_nblocks)
- add_partition(hd, minor,
- label->pt_part[i].pi_blkoff,
- label->pt_part[i].pi_nblocks);
- brelse(bh);
- printk ("\n");
- return 1;
- } else {
- brelse(bh);
- return 0;
- }
-}
-
-#endif /* CONFIG_ULTRIX_PARTITION */
-
-#ifdef CONFIG_ULTRIX_PARTITION
-
-static int ultrix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
-{
- int i, minor = current_minor;
- struct buffer_head *bh;
- struct ultrix_disklabel {
- s32 pt_magic; /* magic no. indicating part. info exits */
- s32 pt_valid; /* set by driver if pt is current */
- struct pt_info {
- s32 pi_nblocks; /* no. of sectors */
- u32 pi_blkoff; /* block offset for start */
- } pt_part[8];
- } *label;
-
-#define PT_MAGIC 0x032957 /* Partition magic number */
-#define PT_VALID 1 /* Indicates if struct is valid */
-
-#define SBLOCK ((unsigned long)((16384 - sizeof(struct ultrix_disklabel)) \
- /get_ptable_blocksize(dev)))
-
- bh = bread (dev, SBLOCK, get_ptable_blocksize(dev));
- if (!bh) {
- printk (" unable to read block 0x%lx\n", SBLOCK);
- return -1;
- }
-
- label = (struct ultrix_disklabel *)(bh->b_data
- + get_ptable_blocksize(dev)
- - sizeof(struct ultrix_disklabel));
-
- if (label->pt_magic == PT_MAGIC && label->pt_valid == PT_VALID) {
- for (i=0; i<8; i++, minor++)
- if (label->pt_part[i].pi_nblocks)
- add_partition(hd, minor,
- label->pt_part[i].pi_blkoff,
- label->pt_part[i].pi_nblocks);
- brelse(bh);
- printk ("\n");
- return 1;
- } else {
- brelse(bh);
- return 0;
- }
-}
-
-#endif /* CONFIG_ULTRIX_PARTITION */
-
-static void check_partition(struct gendisk *hd, kdev_t dev)
-{
- static int first_time = 1;
- unsigned long first_sector;
- char buf[40];
-
- if (first_time)
- printk(KERN_INFO "Partition check:\n");
- first_time = 0;
- first_sector = hd->part[MINOR(dev)].start_sect;
-
- /*
- * This is a kludge to allow the partition check to be
- * skipped for specific drives (e.g. IDE CD-ROM drives)
- */
- if ((int)first_sector == -1) {
- hd->part[MINOR(dev)].start_sect = 0;
- return;
- }
-
- printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf));
-#ifdef CONFIG_MSDOS_PARTITION
- if (msdos_partition(hd, dev, first_sector))
- return;
-#endif
-#ifdef CONFIG_OSF_PARTITION
- if (osf_partition(hd, dev, first_sector))
- return;
-#endif
-#ifdef CONFIG_SUN_PARTITION
- if(sun_partition(hd, dev, first_sector))
- return;
-#endif
-#ifdef CONFIG_AMIGA_PARTITION
- if(amiga_partition(hd, dev, first_sector))
- return;
-#endif
-#ifdef CONFIG_ATARI_PARTITION
- if(atari_partition(hd, dev, first_sector))
- return;
-#endif
-#ifdef CONFIG_MAC_PARTITION
- if (mac_partition(hd, dev, first_sector))
- return;
-#endif
-#ifdef CONFIG_SGI_PARTITION
- if(sgi_partition(hd, dev, first_sector))
- return;
-#endif
-#ifdef CONFIG_ULTRIX_PARTITION
- if(ultrix_partition(hd, dev, first_sector))
- return;
-#endif
-#ifdef CONFIG_ULTRIX_PARTITION
- if(ultrix_partition(hd, dev, first_sector))
- return;
-#endif
- printk(" unknown partition table\n");
-}
-
-/* This function is used to re-read partition tables for removable disks.
- Much of the cleanup from the old partition tables should have already been
- done */
-
-/* This function will re-read the partition tables for a given device,
-and set things back up again. There are some important caveats,
-however. You must ensure that no one is using the device, and no one
-can start using the device while this function is being executed. */
-
-void resetup_one_dev(struct gendisk *dev, int drive)
-{
- int i;
- int first_minor = drive << dev->minor_shift;
- int end_minor = first_minor + dev->max_p;
-
- blk_size[dev->major] = NULL;
- current_minor = 1 + first_minor;
- check_partition(dev, MKDEV(dev->major, first_minor));
-
- /*
- * We need to set the sizes array before we will be able to access
- * any of the partitions on this device.
- */
- if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */
- for (i = first_minor; i < end_minor; i++)
- dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
- blk_size[dev->major] = dev->sizes;
- }
-}
-
-static inline void setup_dev(struct gendisk *dev)
-{
- int i, drive;
- int end_minor = dev->max_nr * dev->max_p;
-
- blk_size[dev->major] = NULL;
- for (i = 0; i < end_minor; i++) {
- dev->part[i].start_sect = 0;
- dev->part[i].nr_sects = 0;
- dev->sizes[i] = 0;
- }
- dev->init(dev);
- for (drive = 0; drive < dev->nr_real; drive++)
- resetup_one_dev(dev, drive);
-}
-
-void __init device_setup(void)
-{
- extern void console_map_init(void);
- extern void cpqarray_init(void);
-#ifdef CONFIG_PARPORT
- extern int parport_init(void) __init;
-#endif
-#ifdef CONFIG_MD_BOOT
- extern void md_setup_drive(void) __init;
-#endif
-#ifdef CONFIG_FC4_SOC
- extern int soc_probe(void);
-#endif
- struct gendisk *p;
-
#ifdef CONFIG_PARPORT
parport_init();
#endif
@@ -1463,6 +42,9 @@ void __init device_setup(void)
chr_dev_init();
blk_dev_init();
sti();
+#ifdef CONFIG_BLK_DEV_DAC960
+ DAC960_Initialize();
+#endif
#ifdef CONFIG_FC4_SOC
/* This has to be done before scsi_dev_init */
soc_probe();
@@ -1473,46 +55,13 @@ void __init device_setup(void)
#ifdef CONFIG_BLK_CPQ_DA
cpqarray_init();
#endif
-#ifdef CONFIG_INET
+#ifdef CONFIG_NET
net_dev_init();
#endif
+#ifdef CONFIG_ATM
+ (void) atmdev_init();
+#endif
#ifdef CONFIG_VT
console_map_init();
#endif
-
- for (p = gendisk_head ; p ; p=p->next)
- setup_dev(p);
-
-#ifdef CONFIG_BLK_DEV_RAM
-#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start && mount_initrd) initrd_load();
- else
-#endif
- rd_load();
-#endif
-#ifdef CONFIG_MD_BOOT
- md_setup_drive();
-#endif
}
-
-#ifdef CONFIG_PROC_FS
-int get_partition_list(char * page)
-{
- struct gendisk *p;
- char buf[40];
- int n, len;
-
- len = sprintf(page, "major minor #blocks name\n\n");
- for (p = gendisk_head; p; p = p->next) {
- for (n=0; n < (p->nr_real << p->minor_shift); n++) {
- if (p->part[n].nr_sects && len < PAGE_SIZE - 80) {
- len += sprintf(page+len,
- "%4d %4d %10d %s\n",
- p->major, n, p->sizes[n],
- disk_name(p, n, buf));
- }
- }
- }
- return len;
-}
-#endif
diff --git a/drivers/block/hd.c b/drivers/block/hd.c
index 164835bfc..49527026a 100644
--- a/drivers/block/hd.c
+++ b/drivers/block/hd.c
@@ -21,12 +21,12 @@
* Removed 99% of above. Use Mark's ide driver for those options.
* This is now a lightweight ST-506 driver. (Paul Gortmaker)
*
+ * Modified 1995 Russell King for ARM processor.
*/
/* Uncomment the following if you want verbose error reports. */
/* #define VERBOSE_ERRORS */
-#include <asm/irq.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h>
@@ -40,6 +40,7 @@
#include <linux/ioport.h>
#include <linux/mc146818rtc.h> /* CMOS defines */
#include <linux/init.h>
+#include <linux/blkpg.h>
#define REALLY_SLOW_IO
#include <asm/system.h>
@@ -49,6 +50,14 @@
#define MAJOR_NR HD_MAJOR
#include <linux/blk.h>
+#ifdef __arm__
+#undef HD_IRQ
+#endif
+#include <asm/irq.h>
+#ifdef __arm__
+#define HD_IRQ IRQ_HARDDISK
+#endif
+
static int revalidate_hddisk(kdev_t, int);
#define HD_DELAY 0
@@ -64,14 +73,14 @@ static int revalidate_hddisk(kdev_t, int);
static void recal_intr(void);
static void bad_rw_intr(void);
-static char recalibrate[MAX_HD] = { 0, };
-static char special_op[MAX_HD] = { 0, };
-static int access_count[MAX_HD] = {0, };
-static char busy[MAX_HD] = {0, };
+static char recalibrate[MAX_HD];
+static char special_op[MAX_HD];
+static int access_count[MAX_HD];
+static char busy[MAX_HD];
static DECLARE_WAIT_QUEUE_HEAD(busy_wait);
-static int reset = 0;
-static int hd_error = 0;
+static int reset;
+static int hd_error;
#define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0)
@@ -86,13 +95,14 @@ struct hd_i_struct {
static struct hd_i_struct hd_info[] = { HD_TYPE };
static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct)));
#else
-static struct hd_i_struct hd_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} };
-static int NR_HD = 0;
+static struct hd_i_struct hd_info[MAX_HD];
+static int NR_HD;
#endif
-static struct hd_struct hd[MAX_HD<<6]={{0,0},};
-static int hd_sizes[MAX_HD<<6] = {0, };
-static int hd_blocksizes[MAX_HD<<6] = {0, };
+static struct hd_struct hd[MAX_HD<<6];
+static int hd_sizes[MAX_HD<<6];
+static int hd_blocksizes[MAX_HD<<6];
+static int hd_hardsectsizes[MAX_HD<<6];
#if (HD_DELAY > 0)
unsigned long last_req;
@@ -611,7 +621,7 @@ static int hd_ioctl(struct inode * inode, struct file * file,
(long *) arg);
case BLKRRPART: /* Re-read partition tables */
- if (!capable(CAP_SYS_ADMIN))
+ if (!capable(CAP_SYS_ADMIN))
return -EACCES;
return revalidate_hddisk(inode->i_rdev, 1);
@@ -746,6 +756,17 @@ static void hd_geninit(struct gendisk *ignored)
}
}
#endif /* __i386__ */
+#ifdef __arm__
+ if (!NR_HD) {
+ /* We don't know anything about the drive. This means
+ * that you *MUST* specify the drive parameters to the
+ * kernel yourself.
+ */
+ printk("hd: no drives specified - use hd=cyl,head,sectors"
+ " on kernel command line\n");
+ }
+#endif
+
for (drive=0 ; drive < NR_HD ; drive++) {
hd[drive<<6].nr_sects = hd_info[drive].head *
hd_info[drive].sect * hd_info[drive].cyl;
@@ -764,9 +785,12 @@ static void hd_geninit(struct gendisk *ignored)
}
hd_gendisk.nr_real = NR_HD;
- for(drive=0; drive < (MAX_HD << 6); drive++)
+ for(drive=0; drive < (MAX_HD << 6); drive++) {
hd_blocksizes[drive] = 1024;
+ hd_hardsectsizes[drive] = 512;
+ }
blksize_size[MAJOR_NR] = hd_blocksizes;
+ hardsect_size[MAJOR_NR] = hd_hardsectsizes;
}
static struct file_operations hd_fops = {
diff --git a/drivers/block/hpt34x.c b/drivers/block/hpt34x.c
index 79df61b1f..284bf40bc 100644
--- a/drivers/block/hpt34x.c
+++ b/drivers/block/hpt34x.c
@@ -1,8 +1,7 @@
/*
- * linux/drivers/block/hpt34x.c Version 0.24 July 3, 1999
+ * linux/drivers/block/hpt34x.c Version 0.25 July 11, 1999
*
* Copyright (C) 1998-99 Andre Hedrick
- * (hedrick@astro.dyer.vanderbilt.edu)
*
* 00:12.0 Unknown mass storage controller:
* Triones Technologies, Inc.
@@ -118,9 +117,14 @@ static int config_chipset_for_dma (ide_drive_t *drive)
return ((int) ide_dma_off_quietly);
#endif /* HPT343_DISABLE_ALL_DMAING */
- if (id->dma_ultra & 0x0004) {
+ if (id->dma_ultra & 0x0010) {
+ goto backspeed;
+ } else if (id->dma_ultra & 0x0008) {
+ goto backspeed;
+ } else if (id->dma_ultra & 0x0004) {
+backspeed:
if (!((id->dma_ultra >> 8) & 4)) {
- drive->id->dma_ultra &= ~0x0F00;
+ drive->id->dma_ultra &= ~0xFF00;
drive->id->dma_ultra |= 0x0404;
drive->id->dma_mword &= ~0x0F00;
drive->id->dma_1word &= ~0x0F00;
@@ -128,7 +132,7 @@ static int config_chipset_for_dma (ide_drive_t *drive)
speed = XFER_UDMA_2;
} else if (id->dma_ultra & 0x0002) {
if (!((id->dma_ultra >> 8) & 2)) {
- drive->id->dma_ultra &= ~0x0F00;
+ drive->id->dma_ultra &= ~0xFF00;
drive->id->dma_ultra |= 0x0202;
drive->id->dma_mword &= ~0x0F00;
drive->id->dma_1word &= ~0x0F00;
@@ -136,7 +140,7 @@ static int config_chipset_for_dma (ide_drive_t *drive)
speed = XFER_UDMA_1;
} else if (id->dma_ultra & 0x0001) {
if (!((id->dma_ultra >> 8) & 1)) {
- drive->id->dma_ultra &= ~0x0F00;
+ drive->id->dma_ultra &= ~0xFF00;
drive->id->dma_ultra |= 0x0101;
drive->id->dma_mword &= ~0x0F00;
drive->id->dma_1word &= ~0x0F00;
@@ -190,7 +194,8 @@ static int config_chipset_for_dma (ide_drive_t *drive)
(void) hpt34x_tune_chipset(drive, speed);
- return ((int) ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+ 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);
@@ -335,62 +340,44 @@ int hpt34x_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
*/
#define HPT34X_PCI_INIT_REG 0x80
-__initfunc(unsigned int pci_init_hpt34x (struct pci_dev *dev, const char *name))
+unsigned int __init pci_init_hpt34x (struct pci_dev *dev, const char *name)
{
- int i;
unsigned short cmd;
- unsigned long hpt34xIoBase = dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK;
-#if 0
- unsigned char misc10 = inb(hpt34xIoBase + 0x0010);
- unsigned char misc11 = inb(hpt34xIoBase + 0x0011);
-#endif
pci_write_config_byte(dev, HPT34X_PCI_INIT_REG, 0x00);
pci_read_config_word(dev, PCI_COMMAND, &cmd);
- pci_write_config_word(dev, PCI_COMMAND, cmd & ~PCI_COMMAND_IO);
-
- dev->base_address[0] = (hpt34xIoBase + 0x20);
- dev->base_address[1] = (hpt34xIoBase + 0x34);
- dev->base_address[2] = (hpt34xIoBase + 0x28);
- dev->base_address[3] = (hpt34xIoBase + 0x3c);
-
- for(i=0; i<4; i++)
- dev->base_address[i] |= PCI_BASE_ADDRESS_SPACE_IO;
-
- /*
- * Since 20-23 can be assigned and are R/W, we correct them.
- */
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, dev->base_address[0]);
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, dev->base_address[1]);
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, dev->base_address[2]);
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_3, dev->base_address[3]);
- pci_write_config_word(dev, PCI_COMMAND, cmd);
-
-#if 0
- outb(misc10|0x78, (hpt34xIoBase + 0x0010));
- outb(misc11, (hpt34xIoBase + 0x0011));
-#endif
-
-#ifdef DEBUG
- printk("%s: 0x%02x 0x%02x\n",
- (pcicmd & PCI_COMMAND_MEMORY) ? "HPT345" : name,
- inb(hpt34xIoBase + 0x0010),
- inb(hpt34xIoBase + 0x0011));
-#endif
-
if (cmd & PCI_COMMAND_MEMORY) {
- if (dev->rom_address) {
- pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->rom_address | PCI_ROM_ADDRESS_ENABLE);
- printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n", dev->rom_address);
+ if (dev->resource[PCI_ROM_RESOURCE].start) {
+ pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
+ printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n", dev->resource[PCI_ROM_RESOURCE].start);
}
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0);
} else {
+ int i = 0;
+ unsigned long hpt34xIoBase = dev->resource[4].start;
+
+ pci_write_config_word(dev, PCI_COMMAND, cmd & ~PCI_COMMAND_IO);
+ dev->resource[0].start = (hpt34xIoBase + 0x20);
+ dev->resource[1].start = (hpt34xIoBase + 0x34);
+ dev->resource[2].start = (hpt34xIoBase + 0x28);
+ dev->resource[3].start = (hpt34xIoBase + 0x3c);
+ for(i=0; i<4; i++)
+ dev->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
+ /*
+ * Since 20-23 can be assigned and are R/W, we correct them.
+ */
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, dev->resource[0].start);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, dev->resource[1].start);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, dev->resource[2].start);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_3, dev->resource[3].start);
+
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
}
return dev->irq;
}
-__initfunc(void ide_init_hpt34x (ide_hwif_t *hwif))
+void __init ide_init_hpt34x (ide_hwif_t *hwif)
{
hwif->tuneproc = &hpt34x_tune_drive;
if (hwif->dma_base) {
@@ -398,7 +385,9 @@ __initfunc(void ide_init_hpt34x (ide_hwif_t *hwif))
pci_read_config_word(hwif->pci_dev, PCI_COMMAND, &pcicmd);
#ifdef CONFIG_BLK_DEV_HPT34X_DMA
+#if 0
hwif->autodma = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0;
+#endif
#endif /* CONFIG_BLK_DEV_HPT34X_DMA */
hwif->dmaproc = &hpt34x_dmaproc;
} else {
diff --git a/drivers/block/hpt366.c b/drivers/block/hpt366.c
new file mode 100644
index 000000000..b61f71687
--- /dev/null
+++ b/drivers/block/hpt366.c
@@ -0,0 +1,490 @@
+/*
+ * linux/drivers/block/hpt366.c Version 0.12 August 16, 1999
+ *
+ * Copyright (C) 1999 Andre Hedrick <andre@suse.com>
+ *
+ * drive_number
+ * = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+ * = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "ide_modes.h"
+
+const char *bad_ata66_4[] = {
+ "WDC AC310200R",
+ NULL
+};
+
+const char *bad_ata66_3[] = {
+ "WDC AC310200R",
+ NULL
+};
+
+const char *bad_ata33[] = {
+ "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2",
+ "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
+ "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
+ "Maxtor 90510D4",
+ "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2",
+ "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
+ "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
+ NULL
+};
+
+struct chipset_bus_clock_list_entry {
+ byte xfer_speed;
+ unsigned int chipset_settings;
+};
+
+struct chipset_bus_clock_list_entry forty_base [] = {
+
+ { XFER_UDMA_4 , 0x900fd943 },
+ { XFER_UDMA_3 , 0x900ad943 },
+ { XFER_UDMA_2 , 0x900bd943 },
+ { XFER_UDMA_1 , 0x9008d943 },
+ { XFER_UDMA_0 , 0x9008d943 },
+
+ { XFER_MW_DMA_2 , 0xa008d943 },
+ { XFER_MW_DMA_1 , 0xa010d955 },
+ { XFER_MW_DMA_0 , 0xa010d9fc },
+
+ { XFER_PIO_4 , 0xc008d963 },
+ { XFER_PIO_3 , 0xc010d974 },
+ { XFER_PIO_2 , 0xc010d997 },
+ { XFER_PIO_1 , 0xc010d9c7 },
+ { XFER_PIO_0 , 0xc018d9d9 },
+ { 0 , 0x0120d9d9 }
+};
+
+struct chipset_bus_clock_list_entry thirty_three_base [] = {
+
+ { XFER_UDMA_4 , 0x90c9a731 },
+ { XFER_UDMA_3 , 0x90cfa731 },
+ { XFER_UDMA_2 , 0x90caa731 },
+ { XFER_UDMA_1 , 0x90cba731 },
+ { XFER_UDMA_0 , 0x90c8a731 },
+
+ { XFER_MW_DMA_2 , 0xa0c8a731 },
+ { XFER_MW_DMA_1 , 0xa0c8a732 }, /* 0xa0c8a733 */
+ { XFER_MW_DMA_0 , 0xa0c8a797 },
+
+ { XFER_PIO_4 , 0xc0c8a731 },
+ { XFER_PIO_3 , 0xc0c8a742 },
+ { XFER_PIO_2 , 0xc0d0a753 },
+ { XFER_PIO_1 , 0xc0d0a7a3 }, /* 0xc0d0a793 */
+ { XFER_PIO_0 , 0xc0d0a7aa }, /* 0xc0d0a7a7 */
+ { 0 , 0x0120a7a7 }
+};
+
+struct chipset_bus_clock_list_entry twenty_five_base [] = {
+
+ { XFER_UDMA_4 , 0x90c98521 },
+ { XFER_UDMA_3 , 0x90cf8521 },
+ { XFER_UDMA_2 , 0x90cf8521 },
+ { XFER_UDMA_1 , 0x90cb8521 },
+ { XFER_UDMA_0 , 0x90cb8521 },
+
+ { XFER_MW_DMA_2 , 0xa0ca8521 },
+ { XFER_MW_DMA_1 , 0xa0ca8532 },
+ { XFER_MW_DMA_0 , 0xa0ca8575 },
+
+ { XFER_PIO_4 , 0xc0ca8521 },
+ { XFER_PIO_3 , 0xc0ca8532 },
+ { XFER_PIO_2 , 0xc0ca8542 },
+ { XFER_PIO_1 , 0xc0d08572 },
+ { XFER_PIO_0 , 0xc0d08585 },
+ { 0 , 0x01208585 }
+};
+
+#define HPT366_DEBUG_DRIVE_INFO 0
+#define HPT366_ALLOW_ATA66_4 0
+#define HPT366_ALLOW_ATA66_3 1
+#define HPT366_ALLOW_ATA33_2 1
+#define HPT366_ALLOW_ATA33_1 1
+#define HPT366_ALLOW_ATA33_0 1
+
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+static int check_in_drive_lists (ide_drive_t *drive, const char **list)
+{
+ struct hd_driveid *id = drive->id;
+
+ while (*list) {
+ if (!strcmp(*list++,id->model)) {
+#ifdef DEBUG
+ printk("%s: Broken ASIC, BackSpeeding (U)DMA for %s\n", drive->name, id->model);
+#endif /* DEBUG */
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static unsigned int 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 0x01208585;
+}
+
+static int hpt366_tune_chipset (ide_drive_t *drive, byte speed)
+{
+ int err;
+ byte busclock;
+
+#if HPT366_DEBUG_DRIVE_INFO
+ int drive_number = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+#endif /* HPT366_DEBUG_DRIVE_INFO */
+ byte regtime = (drive->select.b.unit & 0x01) ? 0x43 : 0x40;
+ unsigned int reg1 = 0;
+ unsigned int reg2 = 0;
+
+ pci_read_config_dword(HWIF(drive)->pci_dev, regtime, &reg1);
+ pci_read_config_byte(HWIF(drive)->pci_dev, regtime|0x01, &busclock);
+ switch(busclock) {
+ case 0xd9:
+ reg2 = pci_bus_clock_list(speed, forty_base);
+ break;
+ case 0x85:
+ reg2 = pci_bus_clock_list(speed, twenty_five_base);
+ break;
+ case 0xa7:
+ default:
+ reg2 = pci_bus_clock_list(speed, thirty_three_base);
+ break;
+ }
+
+ if (drive->id->dword_io & 1)
+ reg2 |= 0x80000000;
+ else
+ reg2 &= ~0x80000000;
+
+ pci_write_config_dword(HWIF(drive)->pci_dev, regtime, reg2);
+ err = ide_config_drive_speed(drive, speed);
+
+#if HPT366_DEBUG_DRIVE_INFO
+ printk("%s: %s drive%d (0x%08x 0x%08x) 0x%04x\n",
+ drive->name, ide_xfer_verbose(speed),
+ drive_number, reg1, reg2, err);
+#endif /* HPT366_DEBUG_DRIVE_INFO */
+ return(err);
+}
+
+/*
+ * This allows the configuration of ide_pci chipset registers
+ * for cards that learn about the drive's UDMA, DMA, PIO capabilities
+ * after the drive is reported by the OS. Initally for designed for
+ * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc.
+ *
+ * check_in_drive_lists(drive, bad_ata66_4)
+ * check_in_drive_lists(drive, bad_ata66_3)
+ * check_in_drive_lists(drive, bad_ata33)
+ *
+ */
+static int config_chipset_for_dma (ide_drive_t *drive)
+{
+ struct hd_driveid *id = drive->id;
+ byte speed = 0x00;
+
+ if ((id->dma_ultra & 0x0010) &&
+ (!check_in_drive_lists(drive, bad_ata66_4)) &&
+ (HPT366_ALLOW_ATA66_4) &&
+ (HWIF(drive)->udma_four)) {
+ 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;
+ }
+ speed = XFER_UDMA_4;
+ } else if ((id->dma_ultra & 0x0008) &&
+ (!check_in_drive_lists(drive, bad_ata66_3)) &&
+ (HPT366_ALLOW_ATA66_3) &&
+ (HWIF(drive)->udma_four)) {
+ 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;
+ }
+ speed = XFER_UDMA_3;
+ } else if ((id->dma_ultra & 0x0004) &&
+ (HPT366_ALLOW_ATA33_2) &&
+ (!check_in_drive_lists(drive, bad_ata33))) {
+ 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;
+ }
+ speed = XFER_UDMA_2;
+ } else if ((id->dma_ultra & 0x0002) &&
+ (HPT366_ALLOW_ATA33_1) &&
+ (!check_in_drive_lists(drive, bad_ata33))) {
+ 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;
+ }
+ speed = XFER_UDMA_1;
+ } else if ((id->dma_ultra & 0x0001) &&
+ (HPT366_ALLOW_ATA33_0) &&
+ (!check_in_drive_lists(drive, bad_ata33))) {
+ 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;
+ }
+ speed = XFER_UDMA_0;
+ } else if (id->dma_mword & 0x0004) {
+ 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;
+ }
+ speed = XFER_MW_DMA_2;
+ } else if (id->dma_mword & 0x0002) {
+ 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;
+ }
+ speed = XFER_MW_DMA_1;
+ } else if (id->dma_mword & 0x0001) {
+ 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;
+ }
+ speed = XFER_MW_DMA_0;
+ } else if (id->dma_1word & 0x0004) {
+ drive->id->dma_ultra &= ~0xFF00;
+ if (!((id->dma_1word >> 8) & 4)) {
+ drive->id->dma_1word &= ~0x0F00;
+ drive->id->dma_1word |= 0x0404;
+ drive->id->dma_mword &= ~0x0F00;
+ }
+ speed = XFER_SW_DMA_2;
+ } else if (id->dma_1word & 0x0002) {
+ drive->id->dma_ultra &= ~0xFF00;
+ if (!((id->dma_1word >> 8) & 2)) {
+ drive->id->dma_1word &= ~0x0F00;
+ drive->id->dma_1word |= 0x0202;
+ drive->id->dma_mword &= ~0x0F00;
+ }
+ speed = XFER_SW_DMA_1;
+ } else if (id->dma_1word & 0x0001) {
+ drive->id->dma_ultra &= ~0xFF00;
+ if (!((id->dma_1word >> 8) & 1)) {
+ drive->id->dma_1word &= ~0x0F00;
+ drive->id->dma_1word |= 0x0101;
+ drive->id->dma_mword &= ~0x0F00;
+ }
+ speed = XFER_SW_DMA_0;
+ } else {
+ return ((int) ide_dma_off_quietly);
+ }
+
+ (void) hpt366_tune_chipset(drive, speed);
+
+ return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on :
+ ((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 config_chipset_for_pio (ide_drive_t *drive)
+{
+ unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90};
+ unsigned short xfer_pio = drive->id->eide_pio_modes;
+
+ byte timing, speed, pio;
+
+ pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
+
+ if (xfer_pio> 4)
+ xfer_pio = 0;
+
+ if (drive->id->eide_pio_iordy > 0) {
+ for (xfer_pio = 5;
+ xfer_pio>0 &&
+ drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio];
+ xfer_pio--);
+ } else {
+ xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 :
+ (drive->id->eide_pio_modes & 2) ? 0x04 :
+ (drive->id->eide_pio_modes & 1) ? 0x03 :
+ (drive->id->tPIO & 2) ? 0x02 :
+ (drive->id->tPIO & 1) ? 0x01 : xfer_pio;
+ }
+
+ timing = (xfer_pio >= pio) ? xfer_pio : pio;
+
+ switch(timing) {
+ 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 = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
+ break;
+ }
+ (void) hpt366_tune_chipset(drive, speed);
+}
+
+static void hpt366_tune_drive (ide_drive_t *drive, byte pio)
+{
+ byte speed;
+ switch(pio) {
+ 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) hpt366_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);
+ 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);
+ 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);
+ 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:
+
+ config_chipset_for_pio(drive);
+ }
+ return HWIF(drive)->dmaproc(dma_func, drive);
+}
+
+/*
+ * hpt366_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
+ *
+ * This is specific to the HPT366 UDMA bios chipset
+ * by HighPoint|Triones Technologies, Inc.
+ */
+
+int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+ byte reg50h = 0, reg52h = 0;
+
+ switch (func) {
+ case ide_dma_check:
+ return config_drive_xfer_rate(drive);
+#if 0
+ case ide_dma_lostirq:
+ pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, &reg52h);
+ printk("%s: (ide_dma_lostirq) reg52h=0x%02x\n", drive->name, reg52h);
+ break;
+ case ide_dma_timeout:
+ (void) ide_dmaproc(ide_dma_off_quietly, drive);
+ pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, &reg52h);
+ printk("%s: (ide_dma_timeout) reg52h=0x%02x\n", drive->name, reg52h);
+ if (reg52h & 0x04) {
+ pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, &reg50h);
+ pci_write_config_byte(HWIF(drive)->pci_dev, 0x50, reg50h|0xff);
+ pci_write_config_byte(HWIF(drive)->pci_dev, 0x50, reg50h);
+ }
+ pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, &reg50h);
+ pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, &reg52h);
+ printk("%s: (ide_dma_timeout) reg50h=0x%02x reg52h=0x%02x :: again\n", drive->name, reg50h, reg52h);
+ (void) ide_dmaproc(ide_dma_on, drive);
+ if (reg52h & 0x04)
+ (void) ide_dmaproc(ide_dma_off, drive);
+ return 1;
+#endif
+ default:
+ break;
+ }
+ return ide_dmaproc(func, drive); /* use standard DMA stuff */
+}
+
+unsigned int __init pci_init_hpt366 (struct pci_dev *dev, const char *name)
+{
+ byte ata66 = 0;
+
+ pci_read_config_byte(dev, 0x5a, &ata66);
+ if (dev->resource[PCI_ROM_RESOURCE].start)
+ pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
+ printk("%s: reg5ah=0x%02x ATA-%s Cable Port%d\n", name, ata66, (ata66 & 0x02) ? "33" : "66", PCI_FUNC(dev->devfn));
+ return dev->irq;
+}
+
+void __init ide_init_hpt366 (ide_hwif_t *hwif)
+{
+ hwif->tuneproc = &hpt366_tune_drive;
+ if (hwif->dma_base) {
+ byte ata66 = 0;
+
+ hwif->dmaproc = &hpt366_dmaproc;
+ pci_read_config_byte(hwif->pci_dev, 0x5a, &ata66);
+ hwif->udma_four = (ata66 & 0x02) ? 0 : 1;
+ } else {
+ hwif->udma_four = 0;
+ hwif->autodma = 0;
+ hwif->drives[0].autotune = 1;
+ hwif->drives[1].autotune = 1;
+ }
+}
diff --git a/drivers/block/icside.c b/drivers/block/icside.c
index edffa0cf1..629ad927d 100644
--- a/drivers/block/icside.c
+++ b/drivers/block/icside.c
@@ -299,24 +299,7 @@ icside_config_drive(ide_drive_t *drive, int mode)
drive->drive_data = 250;
}
-#if 1
err = ide_config_drive_speed(drive, (byte) speed);
-#else
- /*
- * 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);
- 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);
-#endif
if (err == 0) {
drive->id->dma_mword &= 0x00ff;
diff --git a/drivers/block/ide-cd.c b/drivers/block/ide-cd.c
index 3d338c573..b3ba03562 100644
--- a/drivers/block/ide-cd.c
+++ b/drivers/block/ide-cd.c
@@ -2,7 +2,7 @@
* linux/drivers/block/ide-cd.c
* Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov>
* Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org>
- * Copyright (C) 1998, 1999 Jens Axboe
+ * Copyright (C) 1998, 1999 Jens Axboe <axboe@image.dk>
*
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
@@ -12,11 +12,13 @@
*
* Suggestions are welcome. Patches that work are more welcome though. ;-)
* For those wishing to work on this driver, please be sure you download
- * and comply with the latest ATAPI standard. This document can be
- * obtained by anonymous ftp from:
- * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
+ * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI
+ * (SFF-8020i rev 2.6) standards. These documents can be obtained by
+ * anonymous ftp from:
+ * ftp://fission.dt.wdc.com/pub/standards/SFF/specs/INF-8020.PDF
+ * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r01.pdf
*
- * Drives that deviate from the ATAPI standard will be accomodated as much
+ * Drives that deviate from these standards will be accomodated as much
* as possible via compile time or command-line options. Since I only have
* a few drives, you generally need to send me patches...
*
@@ -27,14 +29,8 @@
* This will allow us to get automagically notified when the media changes
* on ATAPI drives (something the stock ATAPI spec is lacking). Looks
* very cool. I discovered its existance the other day at work...
- * -Query the drive to find what features are available before trying to
- * use them (like trying to close the tray in drives that can't).
* -Make it so that Pioneer CD DR-A24X and friends don't get screwed up on
* boot
- * -Integrate DVD-ROM support in driver. Thanks to Merete Gotsæd-Petersen
- * of Pioneer Denmark for providing me with a drive for testing.
- * -Implement Features and Profiles.
- *
*
* ----------------------------------
* 1.00 Oct 31, 1994 -- Initial version.
@@ -243,11 +239,47 @@
* Useful when using ide-cd in conjunction with
* ide-scsi. TODO: non-modular way of doing the
* same.
- *
+ *
+ * 4.54 Aug 5, 1999 - Support for MMC2 class commands through the generic
+ * packet interface to cdrom.c.
+ * - Unified audio ioctl support, most of it.
+ * - cleaned up various deprecated verify_area().
+ * - Added ide_cdrom_packet() as the interface for
+ * the Uniform generic_packet().
+ * - bunch of other stuff, will fill in logs later.
+ * - report 1 slot for non-changers, like the other
+ * cd-rom drivers. don't report select disc for
+ * non-changers as well.
+ * - mask out audio playing, if the device can't do it.
+ *
+ * 4.55 Sep 1, 1999 - Eliminated the rest of the audio ioctls, except
+ * for CDROMREADTOC[ENTRY|HEADER]. Some of the drivers
+ * use this independently of the actual audio handling.
+ * They will disappear later when I get the time to
+ * do it cleanly.
+ * - Minimize the TOC reading - only do it when we
+ * know a media change has occured.
+ * - Moved all the CDROMREADx ioctls to the Uniform layer.
+ * - Heiko Eissfeldt <heiko@colossus.escape.de> supplied
+ * some fixes for CDI.
+ * - CD-ROM leaving door locked fix from Andries
+ * Brouwer <Andries.Brouwer@cwi.nl>
+ * - Erik Andersen <andersen@xmission.com> unified
+ * commands across the various drivers and how
+ * sense errors are handled.
+ *
+ * 4.56 Sep 12, 1999 - Removed changer support - it is now in the
+ * Uniform layer.
+ * - Added partition based multisession handling.
+ * - Mode sense and mode select moved to the
+ * Uniform layer.
+ * - Fixed a problem with WPI CDS-32X drive - it
+ * failed the capabilities
+ *
*
*************************************************************************/
-
-#define IDECD_VERSION "4.53"
+
+#define IDECD_VERSION "4.56"
#include <linux/config.h>
#include <linux/module.h>
@@ -304,12 +336,12 @@ void cdrom_analyze_sense_data (ide_drive_t *drive,
uses this command to poll the drive, and we don't want
to fill the syslog with useless errors. */
if (failed_command &&
- failed_command->c[0] == SCMD_READ_SUBCHANNEL)
+ failed_command->c[0] == GPCMD_READ_SUBCHANNEL)
return;
}
if (reqbuf->error_code == 0x70 && reqbuf->sense_key == 0x02
- && ((reqbuf->asc == 0x3a && reqbuf->ascq == 0x00) ||
- (reqbuf->asc == 0x04 && reqbuf->ascq == 0x01)))
+ && ((reqbuf->asc == 0x3a && reqbuf->ascq == 0x00) ||
+ (reqbuf->asc == 0x04 && reqbuf->ascq == 0x01)))
{
/*
* Suppress the following errors:
@@ -346,15 +378,16 @@ void cdrom_analyze_sense_data (ide_drive_t *drive,
s = buf;
} else {
int lo=0, mid, hi=ARY_LEN (sense_data_texts);
- unsigned short key = (reqbuf->asc << 8);
+ unsigned long key = (reqbuf->sense_key << 16);
+ key |= (reqbuf->asc << 8);
if ( ! (reqbuf->ascq >= 0x80 && reqbuf->ascq <= 0xdd) )
key |= reqbuf->ascq;
-
s = NULL;
while (hi > lo) {
mid = (lo + hi) / 2;
- if (sense_data_texts[mid].asc_ascq == key) {
+ if (sense_data_texts[mid].asc_ascq == key ||
+ sense_data_texts[mid].asc_ascq == (0xff0000|key)) {
s = sense_data_texts[mid].text;
break;
}
@@ -475,7 +508,7 @@ static void cdrom_queue_request_sense (ide_drive_t *drive,
len = sizeof (*reqbuf) / 4;
len *= 4;
- pc->c[0] = REQUEST_SENSE;
+ pc->c[0] = GPCMD_REQUEST_SENSE;
pc->c[4] = (unsigned char) len;
pc->buffer = (char *)reqbuf;
pc->buflen = len;
@@ -517,8 +550,9 @@ static int cdrom_decode_status (ide_drive_t *drive, int good_stat,
int *stat_ret)
{
struct request *rq = HWGROUP(drive)->rq;
- int stat, err, sense_key, cmd;
-
+ int stat, cmd, err, sense_key;
+ struct packet_command *pc = (struct packet_command *) rq->buffer;
+
/* Check for errors. */
stat = GET_STAT();
*stat_ret = stat;
@@ -526,8 +560,8 @@ static int cdrom_decode_status (ide_drive_t *drive, int good_stat,
if (OK_STAT (stat, good_stat, BAD_R_STAT))
return 0;
- /* Got an error. */
- err = IN_BYTE (IDE_ERROR_REG);
+ /* Get the IDE error register. */
+ err = GET_ERR();
sense_key = err >> 4;
if (rq == NULL)
@@ -541,8 +575,6 @@ static int cdrom_decode_status (ide_drive_t *drive, int good_stat,
from the drive (probably while trying
to recover from a former error). Just give up. */
- struct packet_command *pc = (struct packet_command *)
- rq->buffer;
pc->stat = 1;
cdrom_end_request (1, drive);
ide_error (drive, "request sense failure", stat);
@@ -551,23 +583,11 @@ static int cdrom_decode_status (ide_drive_t *drive, int good_stat,
} else if (cmd == PACKET_COMMAND) {
/* All other functions, except for READ. */
- struct packet_command *pc = (struct packet_command *)
- rq->buffer;
struct semaphore *sem = NULL;
/* Check for tray open. */
if (sense_key == NOT_READY) {
cdrom_saw_media_change (drive);
-#if 0 /* let the upper layers do the complaining */
- /* Print an error message to the syslog.
- Exception: don't print anything if this
- is a read subchannel command. This is
- because workman constantly polls the drive
- with this command, and we don't want
- to uselessly fill up the syslog. */
- if (pc->c[0] != SCMD_READ_SUBCHANNEL)
- printk ("%s: tray open or drive not ready\n", drive->name);
-#endif
} else if (sense_key == UNIT_ATTENTION) {
/* Check for media change. */
cdrom_saw_media_change (drive);
@@ -1061,7 +1081,7 @@ static void cdrom_start_read_continuation (ide_drive_t *drive)
/* Set up the command */
memset (&pc.c, 0, sizeof (pc.c));
- pc.c[0] = READ_10;
+ pc.c[0] = GPCMD_READ_10;
pc.c[7] = (nframes >> 8);
pc.c[8] = (nframes & 0xff);
put_unaligned(htonl (frame), (unsigned int *) &pc.c[2]);
@@ -1106,7 +1126,7 @@ static void cdrom_start_seek_continuation (ide_drive_t *drive)
frame = sector / SECTORS_PER_FRAME;
memset (&pc.c, 0, sizeof (pc.c));
- pc.c[0] = SEEK;
+ pc.c[0] = GPCMD_SEEK;
put_unaligned(htonl (frame), (unsigned int *) &pc.c[2]);
(void) cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c), &cdrom_seek_intr);
}
@@ -1170,8 +1190,6 @@ static int
cdrom_lockdoor (ide_drive_t *drive, int lockflag,
struct atapi_request_sense *reqbuf);
-
-
/* Interrupt routine for packet command completion. */
static void cdrom_pc_intr (ide_drive_t *drive)
{
@@ -1192,7 +1210,7 @@ static void cdrom_pc_intr (ide_drive_t *drive)
if ((stat & DRQ_STAT) == 0) {
/* Some of the trailing request sense fields are optional, and
some drives don't send them. Sigh. */
- if (pc->c[0] == REQUEST_SENSE &&
+ if (pc->c[0] == GPCMD_REQUEST_SENSE &&
pc->buflen > 0 &&
pc->buflen <= 5) {
while (pc->buflen > 0) {
@@ -1219,20 +1237,10 @@ static void cdrom_pc_intr (ide_drive_t *drive)
/* Figure out how much data to transfer. */
thislen = pc->buflen;
- if (thislen < 0) thislen = -thislen;
if (thislen > len) thislen = len;
/* The drive wants to be written to. */
if ((ireason & 3) == 0) {
- /* Check that we want to write. */
- if (pc->buflen > 0) {
- printk ("%s: cdrom_pc_intr: Drive wants "
- "to transfer data the wrong way!\n",
- drive->name);
- pc->stat = 1;
- thislen = 0;
- }
-
/* Transfer the data. */
atapi_output_bytes (drive, pc->buffer, thislen);
@@ -1246,19 +1254,11 @@ static void cdrom_pc_intr (ide_drive_t *drive)
/* Keep count of how much data we've moved. */
pc->buffer += thislen;
- pc->buflen += thislen;
+ pc->buflen -= thislen;
}
/* Same drill for reading. */
else if ((ireason & 3) == 2) {
- /* Check that we want to read. */
- if (pc->buflen < 0) {
- printk ("%s: cdrom_pc_intr: Drive wants to "
- "transfer data the wrong way!\n",
- drive->name);
- pc->stat = 1;
- thislen = 0;
- }
/* Transfer the data. */
atapi_input_bytes (drive, pc->buffer, thislen);
@@ -1305,11 +1305,8 @@ static void cdrom_do_packet_command (ide_drive_t *drive)
struct cdrom_info *info = drive->driver_data;
info->dma = 0;
-
- len = pc->buflen;
- if (len < 0) len = -len;
-
pc->stat = 0;
+ len = pc->buflen;
/* Start sending the command to the drive. */
cdrom_start_packet_command (drive, len, cdrom_do_pc_continuation);
@@ -1337,7 +1334,6 @@ int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc)
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);
@@ -1362,10 +1358,10 @@ int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc)
a disk. Retry, but wait a little to give
the drive time to complete the load. */
cdrom_sleep (HZ);
- } else
+ } else {
/* Otherwise, don't retry. */
retries = 0;
-
+ }
--retries;
}
@@ -1379,20 +1375,22 @@ int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc)
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, lock it again.
- (The door was probably unlocked via an explicit
+ 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 && drive->usage &&
- (pc->c[0] != REQUEST_SENSE &&
- pc->c[0] != ALLOW_MEDIUM_REMOVAL &&
- pc->c[0] != START_STOP)) {
+ 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;
}
}
-
/****************************************************************************
* cdrom driver request routine.
*/
@@ -1493,17 +1491,19 @@ cdrom_check_status (ide_drive_t *drive,
struct atapi_request_sense *reqbuf)
{
struct packet_command pc;
+ struct cdrom_info *info = drive->driver_data;
+ struct cdrom_device_info *cdi = &info->devinfo;
memset (&pc, 0, sizeof (pc));
pc.sense_data = reqbuf;
- pc.c[0] = TEST_UNIT_READY;
+ pc.c[0] = GPCMD_TEST_UNIT_READY;
#if ! STANDARD_ATAPI
/* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to
switch CDs instead of supporting the LOAD_UNLOAD opcode */
- pc.c[7] = CDROM_STATE_FLAGS (drive)->sanyo_slot % 3;
+ pc.c[7] = cdi->sanyo_slot % 3;
#endif /* not STANDARD_ATAPI */
return cdrom_queue_packet_command (drive, &pc);
@@ -1518,7 +1518,7 @@ cdrom_lockdoor (ide_drive_t *drive, int lockflag,
struct atapi_request_sense my_reqbuf;
int stat;
struct packet_command pc;
-
+
if (reqbuf == NULL)
reqbuf = &my_reqbuf;
@@ -1529,7 +1529,7 @@ cdrom_lockdoor (ide_drive_t *drive, int lockflag,
memset (&pc, 0, sizeof (pc));
pc.sense_data = reqbuf;
- pc.c[0] = ALLOW_MEDIUM_REMOVAL;
+ pc.c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
pc.c[4] = (lockflag != 0);
stat = cdrom_queue_packet_command (drive, &pc);
}
@@ -1564,45 +1564,18 @@ cdrom_eject (ide_drive_t *drive, int ejectflag,
{
struct packet_command pc;
- if (CDROM_CONFIG_FLAGS (drive)->no_eject==1 && ejectflag==0)
+ 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)
+ return 0;
memset (&pc, 0, sizeof (pc));
pc.sense_data = reqbuf;
- pc.c[0] = START_STOP;
- pc.c[4] = 2 + (ejectflag != 0);
- return cdrom_queue_packet_command (drive, &pc);
-}
-
-
-static int
-cdrom_pause (ide_drive_t *drive, int pauseflag,
- struct atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.c[0] = SCMD_PAUSE_RESUME;
- pc.c[8] = !pauseflag;
- return cdrom_queue_packet_command (drive, &pc);
-}
-
-
-static int
-cdrom_startstop (ide_drive_t *drive, int startflag,
- struct atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.c[0] = START_STOP;
- pc.c[1] = 1;
- pc.c[4] = startflag;
+ pc.c[0] = GPCMD_START_STOP_UNIT;
+ pc.c[4] = 0x02 + (ejectflag != 0);
return cdrom_queue_packet_command (drive, &pc);
}
@@ -1611,8 +1584,8 @@ cdrom_read_capacity (ide_drive_t *drive, unsigned *capacity,
struct atapi_request_sense *reqbuf)
{
struct {
- unsigned lba;
- unsigned blocklen;
+ __u32 lba;
+ __u32 blocklen;
} capbuf;
int stat;
@@ -1621,7 +1594,7 @@ cdrom_read_capacity (ide_drive_t *drive, unsigned *capacity,
memset (&pc, 0, sizeof (pc));
pc.sense_data = reqbuf;
- pc.c[0] = READ_CAPACITY;
+ pc.c[0] = GPCMD_READ_CDVD_CAPACITY;
pc.buffer = (char *)&capbuf;
pc.buflen = sizeof (capbuf);
@@ -1645,7 +1618,7 @@ cdrom_read_tocentry (ide_drive_t *drive, int trackno, int msf_flag,
pc.buffer = buf;
pc.buflen = buflen;
- pc.c[0] = SCMD_READ_TOC;
+ pc.c[0] = GPCMD_READ_TOC_PMA_ATIP;
pc.c[6] = trackno;
pc.c[7] = (buflen >> 8);
pc.c[8] = (buflen & 0xff);
@@ -1657,12 +1630,12 @@ cdrom_read_tocentry (ide_drive_t *drive, int trackno, int msf_flag,
/* 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)
+cdrom_read_toc (ide_drive_t *drive, struct atapi_request_sense *reqbuf)
{
int stat, ntracks, i;
struct cdrom_info *info = drive->driver_data;
struct atapi_toc *toc = info->toc;
+ int minor = drive->select.b.unit << PARTN_BITS;
struct {
struct atapi_toc_header hdr;
struct atapi_toc_entry ent;
@@ -1673,11 +1646,10 @@ cdrom_read_toc (ide_drive_t *drive,
toc = (struct atapi_toc *) kmalloc (sizeof (struct atapi_toc),
GFP_KERNEL);
info->toc = toc;
- }
-
- if (toc == NULL) {
- printk ("%s: No cdrom TOC buffer!\n", drive->name);
- return -EIO;
+ if (toc == NULL) {
+ printk ("%s: No cdrom TOC buffer!\n", drive->name);
+ return -ENOMEM;
+ }
}
/* Check to see if the existing data is still valid.
@@ -1689,9 +1661,7 @@ cdrom_read_toc (ide_drive_t *drive,
/* 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) +
- sizeof (struct atapi_toc_entry),
- reqbuf);
+ sizeof (struct atapi_toc_header), reqbuf);
if (stat) return stat;
#if ! STANDARD_ATAPI
@@ -1706,12 +1676,46 @@ cdrom_read_toc (ide_drive_t *drive,
if (ntracks > MAX_TRACKS) ntracks = MAX_TRACKS;
/* Now read the whole schmeer. */
- stat = cdrom_read_tocentry (drive, 0, 1, 0, (char *)&toc->hdr,
+ 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);
+ (ntracks + 1) *
+ sizeof (struct atapi_toc_entry), reqbuf);
+
+ if (stat && toc->hdr.first_track > 1) {
+ /* Cds with CDI tracks only don't have any TOC entries,
+ despite of this the returned values are
+ first_track == last_track = number of CDI tracks + 1,
+ so that this case is indistinguishable from the same
+ layout plus an additional audio track.
+ If we get an error for the regular case, we assume
+ a CDI without additional audio tracks. In this case
+ the readable TOC is empty (CDI tracks are not included)
+ and only holds the Leadout entry. Heiko Eißfeldt */
+ ntracks = 0;
+ stat = cdrom_read_tocentry (drive, CDROM_LEADOUT, 1,
+ 0, (char *)&toc->hdr,
+ sizeof (struct atapi_toc_header) +
+ (ntracks+1) *
+ sizeof (struct atapi_toc_entry),
+ reqbuf);
+ if (stat) {
+ return stat;
+ }
+#if ! STANDARD_ATAPI
+ if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) {
+ toc->hdr.first_track = bin2bcd(CDROM_LEADOUT);
+ toc->hdr.last_track = bin2bcd(CDROM_LEADOUT);
+ } else
+#endif /* not STANDARD_ATAPI */
+ {
+ toc->hdr.first_track = CDROM_LEADOUT;
+ toc->hdr.last_track = CDROM_LEADOUT;
+ }
+ } else if (stat) {
+ return stat;
+ }
if (stat) return stat;
+
toc->hdr.toc_length = ntohs (toc->hdr.toc_length);
#if ! STANDARD_ATAPI
@@ -1735,10 +1739,18 @@ cdrom_read_toc (ide_drive_t *drive,
}
/* Read the multisession information. */
- stat = cdrom_read_tocentry (drive, 0, 1, 1,
- (char *)&ms_tmp, sizeof (ms_tmp),
- reqbuf);
- if (stat) return stat;
+ 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);
+ if (stat) return stat;
+ } else {
+ ms_tmp.ent.addr.msf.minute = 0;
+ ms_tmp.ent.addr.msf.second = 2;
+ ms_tmp.ent.addr.msf.frame = 0;
+ ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT;
+ }
#if ! STANDARD_ATAPI
if (CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd)
@@ -1752,16 +1764,39 @@ cdrom_read_toc (ide_drive_t *drive,
toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);
/* Now try to get the total cdrom capacity. */
+#if 0
+ stat = cdrom_get_last_written(MKDEV(HWIF(drive)->major, minor,
+ (long *)&toc->capacity);
+ if (stat)
+#endif
stat = cdrom_read_capacity (drive, &toc->capacity, reqbuf);
if (stat) toc->capacity = 0x1fffff;
- HWIF(drive)->gd->sizes[drive->select.b.unit << PARTN_BITS]
- = (toc->capacity * SECTORS_PER_FRAME) >> (BLOCK_SIZE_BITS - 9);
- drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
+ /* for general /dev/cdrom like mounting, one big disc */
+ HWIF(drive)->gd->sizes[minor] = (toc->capacity * SECTORS_PER_FRAME) >>
+ (BLOCK_SIZE_BITS - 9);
/* Remember that we've read this stuff. */
CDROM_STATE_FLAGS (drive)->toc_valid = 1;
+ /* should be "if multisession", but it does no harm. */
+ if (ntracks == 1)
+ return 0;
+
+ /* setup each minor to respond to a session */
+ minor++;
+ i = toc->hdr.first_track;
+ while ((i <= ntracks) && ((minor & CD_PART_MASK) < CD_PART_MAX)) {
+ drive->part[minor & PARTN_MASK].start_sect = 0;
+ drive->part[minor & PARTN_MASK].nr_sects = (toc->ent[i].addr.lba *
+ SECTORS_PER_FRAME) << (BLOCK_SIZE_BITS - 9);
+ HWIF(drive)->gd->sizes[minor] = (toc->ent[i].addr.lba *
+ SECTORS_PER_FRAME) >> (BLOCK_SIZE_BITS - 9);
+ blksize_size[HWIF(drive)->major][minor] = CD_FRAMESIZE;
+ i++;
+ minor++;
+ }
+
return 0;
}
@@ -1778,7 +1813,7 @@ cdrom_read_subchannel (ide_drive_t *drive, int format,
pc.buffer = buf;
pc.buflen = buflen;
- pc.c[0] = SCMD_READ_SUBCHANNEL;
+ pc.c[0] = GPCMD_READ_SUBCHANNEL;
pc.c[1] = 2; /* MSF addressing */
pc.c[2] = 0x40; /* request subQ data */
pc.c[3] = format;
@@ -1787,46 +1822,6 @@ cdrom_read_subchannel (ide_drive_t *drive, int format,
return cdrom_queue_packet_command (drive, &pc);
}
-
-/* modeflag: 0 = current, 1 = changeable mask, 2 = default, 3 = saved */
-static int
-cdrom_mode_sense (ide_drive_t *drive, int pageno, int modeflag,
- char *buf, int buflen,
- struct atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.buffer = buf;
- pc.buflen = buflen;
- pc.c[0] = MODE_SENSE_10;
- pc.c[2] = pageno | (modeflag << 6);
- pc.c[7] = (buflen >> 8);
- pc.c[8] = (buflen & 0xff);
- return cdrom_queue_packet_command (drive, &pc);
-}
-
-static int
-cdrom_mode_select (ide_drive_t *drive, int pageno, char *buf, int buflen,
- struct atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.buffer = buf;
- pc.buflen = - buflen;
- pc.c[0] = MODE_SELECT_10;
- pc.c[1] = 0x10;
- pc.c[2] = pageno;
- pc.c[7] = (buflen >> 8);
- pc.c[8] = (buflen & 0xff);
- 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
@@ -1842,7 +1837,7 @@ cdrom_select_speed (ide_drive_t *drive, int speed,
else
speed *= 177; /* Nx to kbytes/s */
- pc.c[0] = SET_CD_SPEED;
+ pc.c[0] = GPCMD_SET_SPEED;
/* Read Drive speed in kbytes/second MSB */
pc.c[2] = (speed >> 8) & 0xff;
/* Read Drive speed in kbytes/second LSB */
@@ -1858,67 +1853,6 @@ cdrom_select_speed (ide_drive_t *drive, int speed,
return cdrom_queue_packet_command (drive, &pc);
}
-static int
-cdrom_play_lba_range_1 (ide_drive_t *drive, int lba_start, int lba_end,
- struct atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.c[0] = SCMD_PLAYAUDIO_MSF;
- lba_to_msf (lba_start, &pc.c[3], &pc.c[4], &pc.c[5]);
- lba_to_msf (lba_end-1, &pc.c[6], &pc.c[7], &pc.c[8]);
-
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd) {
- pc.c[3] = bin2bcd (pc.c[3]);
- pc.c[4] = bin2bcd (pc.c[4]);
- pc.c[5] = bin2bcd (pc.c[5]);
- pc.c[6] = bin2bcd (pc.c[6]);
- pc.c[7] = bin2bcd (pc.c[7]);
- pc.c[8] = bin2bcd (pc.c[8]);
- }
-#endif /* not STANDARD_ATAPI */
-
- return cdrom_queue_packet_command (drive, &pc);
-}
-
-
-/* Play audio starting at LBA LBA_START and finishing with the
- LBA before LBA_END. */
-static int
-cdrom_play_lba_range (ide_drive_t *drive, int lba_start, int lba_end,
- struct atapi_request_sense *reqbuf)
-{
- int i, stat;
- struct atapi_request_sense my_reqbuf;
-
- if (reqbuf == NULL)
- reqbuf = &my_reqbuf;
-
- /* Some drives, will, for certain audio cds,
- give an error if you ask them to play the entire cd using the
- values which are returned in the TOC. The play will succeed,
- however, if the ending address is adjusted downwards
- by a few frames. */
- for (i=0; i<75; i++) {
- stat = cdrom_play_lba_range_1 (drive, lba_start, lba_end,
- reqbuf);
-
- if (stat == 0 ||
- !(reqbuf->sense_key == ILLEGAL_REQUEST &&
- reqbuf->asc == 0x24))
- return stat;
-
- --lba_end;
- if (lba_end <= lba_start) break;
- }
-
- return stat;
-}
-
static
int cdrom_get_toc_entry (ide_drive_t *drive, int track,
@@ -1926,17 +1860,12 @@ int cdrom_get_toc_entry (ide_drive_t *drive, int track,
struct atapi_request_sense *reqbuf)
{
struct cdrom_info *info = drive->driver_data;
- int stat, ntracks;
- struct atapi_toc *toc;
-
- /* Make sure our saved TOC is valid. */
- stat = cdrom_read_toc (drive, reqbuf);
- if (stat) return stat;
-
- toc = info->toc;
+ struct atapi_toc *toc = info->toc;
+ int ntracks;
/* Check validity of requested track number. */
ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
+ if (toc->hdr.first_track == CDROM_LEADOUT) ntracks = 0;
if (track == CDROM_LEADOUT)
*ent = &toc->ent[ntracks];
else if (track < toc->hdr.first_track ||
@@ -1949,86 +1878,6 @@ int cdrom_get_toc_entry (ide_drive_t *drive, int track,
}
-static int
-cdrom_read_block (ide_drive_t *drive, int format, int lba, int nblocks,
- char *buf, int buflen,
- struct atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
- struct atapi_request_sense my_reqbuf;
-
- if (reqbuf == NULL)
- reqbuf = &my_reqbuf;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.buffer = buf;
- pc.buflen = buflen;
-
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS (drive)->nec260)
- pc.c[0] = 0xd4;
- else
-#endif /* not STANDARD_ATAPI */
- pc.c[0] = READ_CD;
-
- pc.c[1] = (format << 2);
- put_unaligned(htonl(lba), (unsigned int *) &pc.c[2]);
- pc.c[8] = (nblocks & 0xff);
- pc.c[7] = ((nblocks>>8) & 0xff);
- pc.c[6] = ((nblocks>>16) & 0xff);
- if (format <= 1)
- pc.c[9] = 0xf8; /* returns 2352 for any format */
- else
- pc.c[9] = 0x10;
-
- return cdrom_queue_packet_command (drive, &pc);
-}
-
-
-/* If SLOT<0, unload the current slot. Otherwise, try to load SLOT. */
-static int
-cdrom_load_unload (ide_drive_t *drive, int slot,
- struct atapi_request_sense *reqbuf)
-{
-#if ! STANDARD_ATAPI
- /* if the drive is a Sanyo 3 CD changer then TEST_UNIT_READY
- (used in the cdrom_check_status function) is used to
- switch CDs instead of LOAD_UNLOAD */
-
- if (CDROM_STATE_FLAGS (drive)->sanyo_slot > 0) {
-
- if ((slot == 1) || (slot == 2))
- CDROM_STATE_FLAGS (drive)->sanyo_slot = slot;
- else if (slot >= 0)
- CDROM_STATE_FLAGS (drive)->sanyo_slot = 3;
- else
- return 0;
-
- return cdrom_check_status (drive, reqbuf);
-
- }
- else
-#endif /*not STANDARD_ATAPI */
- {
-
- /* ATAPI Rev. 2.2+ standard for requesting switching of
- CDs in a multiplatter device */
-
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.c[0] = LOAD_UNLOAD;
- pc.c[4] = 2 + (slot >= 0);
- pc.c[8] = slot;
- return cdrom_queue_packet_command (drive, &pc);
-
- }
-}
-
/* This gets the mechanism status per ATAPI draft spec 2.6 */
static int
@@ -2042,13 +1891,12 @@ cdrom_read_mech_status (ide_drive_t *drive, char *buf, int buflen,
pc.buffer = buf;
pc.buflen = buflen;
- pc.c[0] = MECHANISM_STATUS;
+ pc.c[0] = GPCMD_MECHANISM_STATUS;
pc.c[8] = (buflen >> 8);
pc.c[9] = (buflen & 0xff);
return cdrom_queue_packet_command (drive, &pc);
}
-
/* Read the drive mechanism status and slot table into our internal buffer.
If the buffer does not yet exist, allocate it. */
static int
@@ -2090,231 +1938,70 @@ cdrom_read_changer_info (ide_drive_t *drive)
NULL);
}
+/* the generic packet interface to cdrom.c */
+static int ide_cdrom_packet(struct cdrom_device_info *cdi,
+ struct cdrom_generic_command *cgc)
+{
+ struct packet_command pc;
+ ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+
+ /* here we queue the commands from the uniform CD-ROM
+ layer. the packet must be complete, as we do not
+ touch it at all. */
+ memset(&pc, 0, sizeof(pc));
+ memcpy(pc.c, cgc->cmd, CDROM_PACKET_SIZE);
+ pc.buffer = cgc->buffer;
+ pc.buflen = cgc->buflen;
+ cgc->stat = cdrom_queue_packet_command(drive, &pc);
+ return cgc->stat;
+}
static
int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi,
unsigned int cmd, unsigned long arg)
-
{
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- struct cdrom_info *info = drive->driver_data;
+ struct cdrom_generic_command cgc;
+ char buffer[16];
+ int stat;
+ init_cdrom_command(&cgc, buffer, sizeof(buffer));
+ /* These will be moved into the Uniform layer shortly... */
switch (cmd) {
- case CDROMREADRAW:
- case CDROMREADMODE1:
- case CDROMREADMODE2: {
- struct cdrom_msf msf;
- int blocksize, format, stat, lba;
- struct atapi_toc *toc;
- char *buf;
-
- if (cmd == CDROMREADMODE1) {
- blocksize = CD_FRAMESIZE;
- format = 2;
- } else { /* for RAW and MODE2. */
- blocksize = CD_FRAMESIZE_RAW;
- format = 0;
- }
-
- copy_from_user_ret(&msf, (void *)arg, sizeof (msf), -EFAULT);
-
- lba = msf_to_lba(msf.cdmsf_min0,
- msf.cdmsf_sec0,
- msf.cdmsf_frame0);
-
- /* Make sure the TOC is up to date. */
- stat = cdrom_read_toc (drive, NULL);
- if (stat) return stat;
-
- toc = info->toc;
-
- if (lba < 0 || lba >= toc->capacity)
- return -EINVAL;
-
- buf = (char *) kmalloc (blocksize, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- stat = cdrom_read_block (drive, format, lba, 1, buf, blocksize,
- NULL);
-
- if (stat == 0) {
- if (cmd == CDROMREADMODE2) {
- /* For Mode2, skip the Sync, Header, and Subheader */
- copy_to_user_ret((char *)arg, buf+16, CD_FRAMESIZE_RAW0, -EFAULT);
- } else {
- copy_to_user_ret((char *)arg, buf, blocksize, -EFAULT);
- }
- }
-
- kfree (buf);
- return stat;
- }
-
- /* Read 2352 byte blocks from audio tracks. */
- case CDROMREADAUDIO: {
- int stat, lba;
- struct atapi_toc *toc;
- struct cdrom_read_audio ra;
- char *buf;
-
- /* Make sure the TOC is up to date. */
- stat = cdrom_read_toc (drive, NULL);
- if (stat) return stat;
-
- toc = info->toc;
-
- stat = verify_area (VERIFY_READ, (char *)arg, sizeof (ra));
- if (stat) return stat;
-
- copy_from_user (&ra, (void *)arg, sizeof (ra));
-
- if (ra.nframes < 0 || ra.nframes > toc->capacity)
- return -EINVAL;
- else if (ra.nframes == 0)
- return 0;
-
- stat = verify_area (VERIFY_WRITE, (char *)ra.buf,
- ra.nframes * CD_FRAMESIZE_RAW);
- if (stat) return stat;
-
- if (ra.addr_format == CDROM_MSF)
- lba = msf_to_lba (ra.addr.msf.minute,
- ra.addr.msf.second,
- ra.addr.msf.frame);
- else if (ra.addr_format == CDROM_LBA)
- lba = ra.addr.lba;
- else
- return -EINVAL;
-
- if (lba < 0 || lba >= toc->capacity)
- return -EINVAL;
-
- buf = (char *) kmalloc (CDROM_NBLOCKS_BUFFER*CD_FRAMESIZE_RAW,
- GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- while (ra.nframes > 0) {
- int this_nblocks = ra.nframes;
- if (this_nblocks > CDROM_NBLOCKS_BUFFER)
- this_nblocks = CDROM_NBLOCKS_BUFFER;
- stat = cdrom_read_block
- (drive, 1, lba, this_nblocks,
- buf, this_nblocks * CD_FRAMESIZE_RAW, NULL);
- if (stat) break;
-
- copy_to_user (ra.buf, buf,
- this_nblocks * CD_FRAMESIZE_RAW);
- ra.buf += this_nblocks * CD_FRAMESIZE_RAW;
- ra.nframes -= this_nblocks;
- lba += this_nblocks;
- }
-
- kfree (buf);
- return stat;
- }
-
case CDROMSETSPINDOWN: {
char spindown;
- char buffer[16];
- int stat;
-
- stat = verify_area (VERIFY_READ, (void *) arg,
- sizeof (char));
- if (stat) return stat;
- copy_from_user (&spindown, (void *) arg, sizeof(char));
+ if (copy_from_user(&spindown, (void *) arg, sizeof(char)))
+ return -EFAULT;
- stat = cdrom_mode_sense (drive, PAGE_CDROM, 0, buffer,
- sizeof (buffer), NULL);
- if (stat) return stat;
+ if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0)))
+ return stat;
buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f);
- return cdrom_mode_select (drive, PAGE_CDROM, buffer,
- sizeof (buffer), NULL);
+ return cdrom_mode_select(cdi, &cgc);
}
case CDROMGETSPINDOWN: {
char spindown;
- char buffer[16];
- int stat;
-
- stat = verify_area (VERIFY_WRITE, (void *) arg,
- sizeof (char));
- if (stat) return stat;
- stat = cdrom_mode_sense (drive, PAGE_CDROM, 0, buffer,
- sizeof (buffer), NULL);
- if (stat) return stat;
+ if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0)))
+ return stat;
spindown = buffer[11] & 0x0f;
- copy_to_user ((void *) arg, &spindown, sizeof (char));
+ if (copy_to_user((void *) arg, &spindown, sizeof (char)))
+ return -EFAULT;
return 0;
}
-#ifdef ALLOW_TEST_PACKETS
- case 0x1234: {
- int stat;
- struct packet_command pc;
- int len, lena;
-
- memset (&pc, 0, sizeof (pc));
-
- stat = verify_area (VERIFY_READ, (void *) arg, sizeof (pc.c));
- if (stat) return stat;
- copy_from_user (&pc.c, (void *) arg, sizeof (pc.c));
- arg += sizeof (pc.c);
-
- stat = verify_area (VERIFY_READ, (void *) arg, sizeof (len));
- if (stat) return stat;
- copy_from_user (&len, (void *) arg , sizeof (len));
- arg += sizeof (len);
-
- lena = len;
- if (lena < 0) lena = -lena;
-
- {
- char buf[lena];
- if (len > 0) {
- stat = verify_area (VERIFY_WRITE,
- (void *) arg, len);
- if (stat) return stat;
- }
- else if (len < 0) {
- stat = verify_area (VERIFY_READ,
- (void *) arg, -len);
- if (stat) return stat;
- copy_from_user (buf, (void*)arg, -len);
- }
-
- if (len != 0) {
- pc.buflen = len;
- pc.buffer = buf;
- }
-
- stat = cdrom_queue_packet_command (drive, &pc);
-
- if (len > 0)
- copy_to_user ((void *)arg, buf, len);
- }
-
- return stat;
- }
-#endif
-
default:
return -EINVAL;
}
}
-
-
static
int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
unsigned int cmd, void *arg)
@@ -2324,47 +2011,6 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
struct cdrom_info *info = drive->driver_data;
switch (cmd) {
- case CDROMSUBCHNL: {
- struct atapi_cdrom_subchnl scbuf;
- int stat;
- struct cdrom_subchnl *subchnl = (struct cdrom_subchnl *)arg;
-
- stat = cdrom_read_subchannel (drive, 1, /* current position */
- (char *)&scbuf, sizeof (scbuf),
- NULL);
- if (stat) return stat;
-
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd) {
- msf_from_bcd (&scbuf.acdsc_absaddr.msf);
- msf_from_bcd (&scbuf.acdsc_reladdr.msf);
- }
- if (CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd)
- scbuf.acdsc_trk = bcd2bin (scbuf.acdsc_trk);
-#endif /* not STANDARD_ATAPI */
-
- subchnl->cdsc_absaddr.msf.minute =
- scbuf.acdsc_absaddr.msf.minute;
- subchnl->cdsc_absaddr.msf.second =
- scbuf.acdsc_absaddr.msf.second;
- subchnl->cdsc_absaddr.msf.frame =
- scbuf.acdsc_absaddr.msf.frame;
-
- subchnl->cdsc_reladdr.msf.minute =
- scbuf.acdsc_reladdr.msf.minute;
- subchnl->cdsc_reladdr.msf.second =
- scbuf.acdsc_reladdr.msf.second;
- subchnl->cdsc_reladdr.msf.frame =
- scbuf.acdsc_reladdr.msf.frame;
-
- subchnl->cdsc_audiostatus = scbuf.acdsc_audiostatus;
- subchnl->cdsc_ctrl = scbuf.acdsc_ctrl;
- subchnl->cdsc_trk = scbuf.acdsc_trk;
- subchnl->cdsc_ind = scbuf.acdsc_ind;
-
- return 0;
- }
-
case CDROMREADTOCHDR: {
int stat;
struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;
@@ -2392,119 +2038,22 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
tocentry->cdte_ctrl = toce->control;
tocentry->cdte_adr = toce->adr;
- tocentry->cdte_format = CDROM_LBA;
- tocentry->cdte_addr.lba = toce->addr.lba;
-
- return 0;
- }
-
- case CDROMPLAYMSF: {
- struct cdrom_msf *msf = (struct cdrom_msf *) arg;
- int lba_start, lba_end;
-
- lba_start = msf_to_lba (msf->cdmsf_min0, msf->cdmsf_sec0,
- msf->cdmsf_frame0);
- lba_end = msf_to_lba (msf->cdmsf_min1, msf->cdmsf_sec1,
- msf->cdmsf_frame1) + 1;
-
- if (lba_end <= lba_start) return -EINVAL;
-
- return cdrom_play_lba_range (drive, lba_start, lba_end, NULL);
- }
-
- /* Like just about every other Linux cdrom driver, we ignore the
- index part of the request here. */
- case CDROMPLAYTRKIND: {
- int stat, lba_start, lba_end;
- struct cdrom_ti *ti = (struct cdrom_ti *)arg;
- struct atapi_toc_entry *first_toc, *last_toc;
-
- stat = cdrom_get_toc_entry (drive, ti->cdti_trk0, &first_toc,
- NULL);
- if (stat) return stat;
- stat = cdrom_get_toc_entry (drive, ti->cdti_trk1, &last_toc,
- NULL);
- if (stat) return stat;
-
- if (ti->cdti_trk1 != CDROM_LEADOUT) ++last_toc;
- lba_start = first_toc->addr.lba;
- lba_end = last_toc->addr.lba;
-
- if (lba_end <= lba_start) return -EINVAL;
-
- return cdrom_play_lba_range (drive, lba_start, lba_end, NULL);
- }
-
- case CDROMVOLCTRL: {
- struct cdrom_volctrl *volctrl = (struct cdrom_volctrl *) arg;
- char buffer[24], mask[24];
- int stat;
-
- stat = cdrom_mode_sense (drive, PAGE_AUDIO, 0, buffer,
- sizeof (buffer), NULL);
- if (stat) return stat;
- stat = cdrom_mode_sense (drive, PAGE_AUDIO, 1, mask,
- sizeof (buffer), NULL);
- if (stat) return stat;
-
- buffer[1] = buffer[2] = 0;
-
- buffer[17] = volctrl->channel0 & mask[17];
- buffer[19] = volctrl->channel1 & mask[19];
- buffer[21] = volctrl->channel2 & mask[21];
- buffer[23] = volctrl->channel3 & mask[23];
-
- return cdrom_mode_select (drive, PAGE_AUDIO, buffer,
- sizeof (buffer), NULL);
- }
-
- case CDROMVOLREAD: {
- struct cdrom_volctrl *volctrl = (struct cdrom_volctrl *) arg;
- char buffer[24];
- int stat;
-
- stat = cdrom_mode_sense (drive, PAGE_AUDIO, 0, buffer,
- sizeof (buffer), NULL);
- if (stat) return stat;
-
- volctrl->channel0 = buffer[17];
- volctrl->channel1 = buffer[19];
- volctrl->channel2 = buffer[21];
- volctrl->channel3 = buffer[23];
+ if (tocentry->cdte_format == CDROM_MSF) {
+ lba_to_msf (toce->addr.lba,
+ &tocentry->cdte_addr.msf.minute,
+ &tocentry->cdte_addr.msf.second,
+ &tocentry->cdte_addr.msf.frame);
+ } else
+ tocentry->cdte_addr.lba = toce->addr.lba;
return 0;
}
- case CDROMSTART:
- return cdrom_startstop (drive, 1, NULL);
-
- case CDROMSTOP: {
-#ifdef IHAVEADOLPHIN
- /* Certain Drives require this. Most don't
- and will produce errors upon CDROMSTOP
- pit says the Dolphin needs this. If you
- own a dolphin, just define IHAVEADOLPHIN somewhere */
- int stat;
- stat = cdrom_startstop (drive, 0, NULL);
- if (stat) return stat;
- return cdrom_eject (drive, 1, NULL);
-#endif /* end of IHAVEADOLPHIN */
- return cdrom_startstop (drive, 0, NULL);
- }
-
- case CDROMPAUSE:
- return cdrom_pause (drive, 1, NULL);
-
- case CDROMRESUME:
- return cdrom_pause (drive, 0, NULL);
-
-
default:
return -EINVAL;
}
}
-
static
int ide_cdrom_reset (struct cdrom_device_info *cdi)
{
@@ -2531,7 +2080,6 @@ int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
return cdrom_eject (drive, !position, NULL);
}
-
static
int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock)
{
@@ -2543,22 +2091,23 @@ static
int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
{
int stat, attempts = 3;
- struct {
- char pad[8];
- struct atapi_capabilities_page cap;
- } buf;
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)
return stat;
+ init_cdrom_command(&cgc, &buf, sizeof(buf));
/* Now with that done, update the speed fields */
do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
if (attempts-- <= 0)
return 0;
- stat = cdrom_mode_sense (drive, PAGE_CAPABILITIES, 0,
- (char *)&buf, sizeof (buf), NULL);
+ stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
} while (stat);
/* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
@@ -2577,93 +2126,6 @@ int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
return 0;
}
-
-static
-int ide_cdrom_select_disc (struct cdrom_device_info *cdi, int slot)
-{
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- struct cdrom_info *info = drive->driver_data;
-
- struct atapi_request_sense my_reqbuf;
- int stat;
- int nslots, curslot;
-
- if ( ! CDROM_CONFIG_FLAGS (drive)->is_changer)
- return -EDRIVE_CANT_DO_THIS;
-
-#if ! STANDARD_ATAPI
- if (CDROM_STATE_FLAGS (drive)->sanyo_slot > 0) {
- nslots = 3;
- curslot = CDROM_STATE_FLAGS (drive)->sanyo_slot;
- if (curslot == 3)
- curslot = 0;
- } else
-#endif /* not STANDARD_ATAPI */
- {
- stat = cdrom_read_changer_info (drive);
- if (stat)
- return stat;
-
- nslots = info->changer_info->hdr.nslots;
- curslot = info->changer_info->hdr.curslot;
- }
-
- if (slot == curslot)
- return curslot;
-
- if (slot == CDSL_CURRENT)
- return curslot;
-
- if (slot != CDSL_NONE && (slot < 0 || slot >= nslots))
- return -EINVAL;
-
- if (drive->usage > 1)
- return -EBUSY;
-
- if (slot == CDSL_NONE) {
- (void) cdrom_load_unload (drive, -1, NULL);
- cdrom_saw_media_change (drive);
- (void) cdrom_lockdoor (drive, 0, NULL);
- return 0;
- }
- else {
- int was_locked;
-
- if (
-#if ! STANDARD_ATAPI
- CDROM_STATE_FLAGS (drive)->sanyo_slot == 0 &&
-#endif
- info->changer_info->slots[slot].disc_present == 0) {
- return -ENOMEDIUM;
- }
-
- was_locked = CDROM_STATE_FLAGS (drive)->door_locked;
- if (was_locked)
- (void) cdrom_lockdoor (drive, 0, NULL);
-
- stat = cdrom_load_unload (drive, slot, NULL);
- cdrom_saw_media_change (drive);
- if (stat)
- return stat;
-
- stat = cdrom_check_status (drive, &my_reqbuf);
- if (stat && my_reqbuf.sense_key == NOT_READY)
- return -ENOENT;
-
- if (stat == 0 || my_reqbuf.sense_key == UNIT_ATTENTION) {
- stat = cdrom_read_toc (drive, &my_reqbuf);
- if (stat)
- return stat;
- }
-
- if (was_locked)
- (void) cdrom_lockdoor (drive, 1, NULL);
-
- return slot;
- }
-}
-
-
static
int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
{
@@ -2688,7 +2150,7 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
}
#if ! STANDARD_ATAPI
- else if (CDROM_STATE_FLAGS (drive)->sanyo_slot > 0)
+ else if (cdi->sanyo_slot > 0)
return CDS_NO_INFO;
#endif /* not STANDARD_ATAPI */
@@ -2710,15 +2172,10 @@ static
int ide_cdrom_get_last_session (struct cdrom_device_info *cdi,
struct cdrom_multisession *ms_info)
{
- int stat;
struct atapi_toc *toc;
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
struct cdrom_info *info = drive->driver_data;
- /* Make sure the TOC information is valid. */
- stat = cdrom_read_toc (drive, NULL);
- if (stat) return stat;
-
toc = info->toc;
ms_info->addr.lba = toc->last_session_lba;
ms_info->xa_flag = toc->xa_flag;
@@ -2726,7 +2183,6 @@ int ide_cdrom_get_last_session (struct cdrom_device_info *cdi,
return 0;
}
-
static
int ide_cdrom_get_mcn (struct cdrom_device_info *cdi,
struct cdrom_mcn *mcn_info)
@@ -2760,9 +2216,9 @@ int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi,
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
struct cdrom_info *info = drive->driver_data;
-
+ struct atapi_request_sense reqbuf;
int retval;
-
+
if (slot_nr == CDSL_CURRENT) {
(void) cdrom_check_status (drive, NULL);
retval = CDROM_STATE_FLAGS (drive)->media_changed;
@@ -2770,7 +2226,7 @@ int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi,
}
#if ! STANDARD_ATAPI
- else if (CDROM_STATE_FLAGS (drive)->sanyo_slot > 0) {
+ else if (cdi->sanyo_slot > 0) {
retval = 0;
}
#endif /* not STANDARD_ATAPI */
@@ -2788,7 +2244,17 @@ int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi,
retval = ci->slots[slot_nr].change;
}
-
+
+ /* if the media has changed, check if a disc is in the drive
+ and read the toc info. */
+ if (retval || !CDROM_STATE_FLAGS (drive)->toc_valid) {
+ /* if cdrom_read_toc fails, return 1 to indicate
+ that a disc change has occured. there might not
+ be a disc in the drive. */
+ if ((retval = cdrom_read_toc (drive, &reqbuf)))
+ return 1;
+ }
+
return retval;
}
@@ -2824,7 +2290,7 @@ struct cdrom_device_ops ide_cdrom_dops = {
ide_cdrom_tray_move, /* tray_move */
ide_cdrom_lock_door, /* lock_door */
ide_cdrom_select_speed, /* select_speed */
- ide_cdrom_select_disc, /* select_disc */
+ NULL, /* select_disc */
ide_cdrom_get_last_session, /* get_last_session */
ide_cdrom_get_mcn, /* get_mcn */
ide_cdrom_reset, /* reset */
@@ -2832,9 +2298,11 @@ struct cdrom_device_ops ide_cdrom_dops = {
ide_cdrom_dev_ioctl, /* dev_ioctl */
CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED
| CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN
- | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET
- | CDC_IOCTLS | CDC_DRIVE_STATUS, /* capability */
- 0 /* n_minors */
+ | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS
+ | CDC_DRIVE_STATUS | CDC_CD_R | CDC_CD_RW | CDC_DVD
+ | CDC_DVD_R| CDC_DVD_RAM | CDC_GENERIC_PACKET, /* capability */
+ 0, /* n_minors */
+ ide_cdrom_packet
};
static int ide_cdrom_register (ide_drive_t *drive, int nslots)
@@ -2843,13 +2311,32 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
struct cdrom_device_info *devinfo = &info->devinfo;
int minor = (drive->select.b.unit)<<PARTN_BITS;
- devinfo->dev = MKDEV (HWIF(drive)->major, minor);
+ devinfo->dev = MKDEV (HWIF(drive)->major, minor | CD_PART_MASK);
devinfo->ops = &ide_cdrom_dops;
devinfo->mask = 0;
*(int *)&devinfo->speed = CDROM_STATE_FLAGS (drive)->current_speed;
*(int *)&devinfo->capacity = nslots;
devinfo->handle = (void *) drive;
strcpy(devinfo->name, drive->name);
+
+ /* set capability mask to match the probe. */
+ if (!CDROM_CONFIG_FLAGS (drive)->cd_r)
+ devinfo->mask |= CDC_CD_R;
+ if (!CDROM_CONFIG_FLAGS (drive)->cd_rw)
+ devinfo->mask |= CDC_CD_RW;
+ if (!CDROM_CONFIG_FLAGS (drive)->dvd)
+ devinfo->mask |= CDC_DVD;
+ if (!CDROM_CONFIG_FLAGS (drive)->dvd_r)
+ devinfo->mask |= CDC_DVD_R;
+ if (!CDROM_CONFIG_FLAGS (drive)->dvd_ram)
+ devinfo->mask |= CDC_DVD_RAM;
+ if (!CDROM_CONFIG_FLAGS (drive)->is_changer)
+ devinfo->mask |= CDC_SELECT_DISC;
+ if (!CDROM_CONFIG_FLAGS (drive)->audio_play)
+ devinfo->mask |= CDC_PLAY_AUDIO;
+ if (!CDROM_CONFIG_FLAGS (drive)->close_tray)
+ devinfo->mask |= CDC_CLOSE_TRAY;
+
return register_cdrom (devinfo);
}
@@ -2857,8 +2344,11 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
static
int ide_cdrom_probe_capabilities (ide_drive_t *drive)
{
- int stat, nslots = 0, attempts = 3;
- struct {
+ struct cdrom_info *info = drive->driver_data;
+ struct cdrom_device_info *cdi = &info->devinfo;
+ int stat, nslots = 1, attempts = 3;
+ struct cdrom_generic_command cgc;
+ struct {
char pad[8];
struct atapi_capabilities_page cap;
} buf;
@@ -2866,11 +2356,19 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
if (CDROM_CONFIG_FLAGS (drive)->nec260)
return nslots;
+ init_cdrom_command(&cgc, &buf, sizeof(buf));
+ /* we have to cheat a little here. the packet will eventually
+ * be queued with ide_cdrom_packet(), which extracts the
+ * drive from cdi->handle. Since this device hasn't been
+ * registered with the Uniform layer yet, it can't do this.
+ * Same goes cdi->ops.
+ */
+ cdi->handle = (ide_drive_t *) drive;
+ cdi->ops = &ide_cdrom_dops;
do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
if (attempts-- <= 0)
return 0;
- stat = cdrom_mode_sense (drive, PAGE_CAPABILITIES, 0,
- (char *)&buf, sizeof (buf), NULL);
+ stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
} while (stat);
if (buf.cap.lock == 0)
@@ -2888,10 +2386,14 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
if (buf.cap.dvd_ram_write)
CDROM_CONFIG_FLAGS (drive)->dvd_r = 1;
if (buf.cap.dvd_r_write)
- CDROM_CONFIG_FLAGS (drive)->dvd_rw = 1;
+ CDROM_CONFIG_FLAGS (drive)->dvd_ram = 1;
+ if (buf.cap.audio_play)
+ CDROM_CONFIG_FLAGS (drive)->audio_play = 1;
+ if (buf.cap.mechtype == 0)
+ CDROM_CONFIG_FLAGS (drive)->close_tray = 0;
#if ! STANDARD_ATAPI
- if (CDROM_STATE_FLAGS (drive)->sanyo_slot > 0) {
+ if (cdi->sanyo_slot > 0) {
CDROM_CONFIG_FLAGS (drive)->is_changer = 1;
nslots = 3;
}
@@ -2928,10 +2430,10 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
drive->name, CDROM_CONFIG_FLAGS (drive)->max_speed,
(CDROM_CONFIG_FLAGS (drive)->dvd) ? "DVD-ROM" : "CD-ROM");
- if (CDROM_CONFIG_FLAGS (drive)->dvd_r|CDROM_CONFIG_FLAGS (drive)->dvd_rw)
+ if (CDROM_CONFIG_FLAGS (drive)->dvd_r|CDROM_CONFIG_FLAGS (drive)->dvd_ram)
printk (" DVD%s%s",
- (CDROM_CONFIG_FLAGS (drive)->dvd_r)? "-RAM" : "",
- (CDROM_CONFIG_FLAGS (drive)->dvd_rw)? "/RW" : "");
+ (CDROM_CONFIG_FLAGS (drive)->dvd_r)? "-R" : "",
+ (CDROM_CONFIG_FLAGS (drive)->dvd_ram)? "AM" : "");
if (CDROM_CONFIG_FLAGS (drive)->cd_r|CDROM_CONFIG_FLAGS (drive)->cd_rw)
printk (" CD%s%s",
@@ -2971,71 +2473,24 @@ static void ide_cdrom_add_settings(ide_drive_t *drive)
ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL);
}
-#ifdef CONFIG_IDECD_SLOTS
-static void ide_cdrom_slot_check (ide_drive_t *drive, int nslots)
-{
- tracktype tracks;
- struct cdrom_info *info = drive->driver_data;
- struct cdrom_device_info *devinfo = &info->devinfo;
- int slot_count = 0, drive_stat = 0, tmp;
-
- for (slot_count=0;slot_count<nslots;slot_count++) {
- (void) ide_cdrom_select_disc(devinfo, slot_count);
- printk(" CD Slot %d ", slot_count+1);
-
- drive_stat = ide_cdrom_drive_status(devinfo, slot_count);
- if (drive_stat<0) {
- continue;
- } else switch(drive_stat) {
- case CDS_DISC_OK:
- /* use routine in Uniform CD-ROM driver */
- cdrom_count_tracks(devinfo, &tracks);
- tmp = tracks.audio + tracks.data +
- tracks.cdi + tracks.xa;
- printk(": Disc has %d track%s: ", tmp,
- (tmp == 1)? "" : "s");
- printk("%d=data %d=audio %d=Cd-I %d=XA\n",
- tracks.data, tracks.audio,
- tracks.cdi, tracks.xa);
- break;
- case CDS_NO_DISC:
- printk("Empty slot.\n");
- break;
- case CDS_TRAY_OPEN:
- printk("CD-ROM tray open.\n");
- break;
- case CDS_DRIVE_NOT_READY:
- printk("CD-ROM drive not ready.\n");
- break;
- case CDS_NO_INFO:
- printk("No Information available.\n");
- break;
- default:
- printk("This Should not happen!\n");
- break;
- }
- }
- (void) ide_cdrom_select_disc(devinfo, 0);
-}
-#endif /* CONFIG_IDECD_SLOTS */
static
int ide_cdrom_setup (ide_drive_t *drive)
{
struct cdrom_info *info = drive->driver_data;
+ struct cdrom_device_info *cdi = &info->devinfo;
+ int minor = drive->select.b.unit << PARTN_BITS;
int nslots;
- kdev_t dev = MKDEV (HWIF (drive)->major,
- drive->select.b.unit << PARTN_BITS);
+ kdev_t dev = MKDEV(HWIF(drive)->major, minor);
set_device_ro (dev, 1);
- blksize_size[HWIF(drive)->major][drive->select.b.unit << PARTN_BITS] =
- CD_FRAMESIZE;
+ blksize_size[HWIF(drive)->major][minor] = CD_FRAMESIZE;
drive->special.all = 0;
drive->ready_stat = 0;
- CDROM_STATE_FLAGS (drive)->media_changed = 0;
+ CDROM_STATE_FLAGS (drive)->media_changed = 1;
CDROM_STATE_FLAGS (drive)->toc_valid = 0;
CDROM_STATE_FLAGS (drive)->door_locked = 0;
@@ -3057,9 +2512,11 @@ int ide_cdrom_setup (ide_drive_t *drive)
CDROM_CONFIG_FLAGS (drive)->test_write = 0;
CDROM_CONFIG_FLAGS (drive)->dvd = 0;
CDROM_CONFIG_FLAGS (drive)->dvd_r = 0;
- CDROM_CONFIG_FLAGS (drive)->dvd_rw = 0;
+ CDROM_CONFIG_FLAGS (drive)->dvd_ram = 0;
CDROM_CONFIG_FLAGS (drive)->no_eject = 1;
CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 0;
+ CDROM_CONFIG_FLAGS (drive)->audio_play = 0;
+ CDROM_CONFIG_FLAGS (drive)->close_tray = 1;
/* limit transfer size per interrupt. */
CDROM_CONFIG_FLAGS (drive)->limit_nframes = 0;
@@ -3073,7 +2530,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
#if ! STANDARD_ATAPI
/* by default Sanyo 3 CD changer support is turned off and
ATAPI Rev 2.2+ standard support for CD changers is used */
- CDROM_STATE_FLAGS (drive)->sanyo_slot = 0;
+ cdi->sanyo_slot = 0;
CDROM_CONFIG_FLAGS (drive)->nec260 = 0;
CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd = 0;
@@ -3125,7 +2582,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
(strcmp(drive->id->model, "CD-ROM CDR-C3G") == 0) ||
(strcmp(drive->id->model, "CD-ROM CDR_C36") == 0)) {
/* uses CD in slot 0 when value is set to 3 */
- CDROM_STATE_FLAGS (drive)->sanyo_slot = 3;
+ cdi->sanyo_slot = 3;
}
@@ -3146,11 +2603,6 @@ int ide_cdrom_setup (ide_drive_t *drive)
return 1;
}
ide_cdrom_add_settings(drive);
-#ifdef CONFIG_IDECD_SLOTS
- if (CDROM_CONFIG_FLAGS (drive)->is_changer) {
- ide_cdrom_slot_check(drive, nslots);
- }
-#endif /* CONFIG_IDECD_SLOTS */
return 0;
}
@@ -3193,7 +2645,6 @@ int ide_cdrom_check_media_change (ide_drive_t *drive)
(drive->select.b.unit)<<PARTN_BITS));
}
-
static
int ide_cdrom_cleanup(ide_drive_t *drive)
{
@@ -3278,11 +2729,12 @@ int ide_cdrom_init (void)
MOD_INC_USE_COUNT;
while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, NULL, failed++)) != NULL) {
/* skip drives that we were told to ignore */
- if (ignore != NULL)
+ if (ignore != NULL) {
if (strstr(ignore, drive->name)) {
printk("ide-cd: ignoring drive %s\n", drive->name);
continue;
}
+ }
info = (struct cdrom_info *) kmalloc (sizeof (struct cdrom_info), GFP_KERNEL);
if (info == NULL) {
printk ("%s: Can't allocate a cdrom structure\n", drive->name);
@@ -3309,11 +2761,3 @@ int ide_cdrom_init (void)
MOD_DEC_USE_COUNT;
return 0;
}
-
-
-/*==========================================================================*/
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/block/ide-cd.h b/drivers/block/ide-cd.h
index 553013b9d..ae1a252ed 100644
--- a/drivers/block/ide-cd.h
+++ b/drivers/block/ide-cd.h
@@ -1,9 +1,9 @@
#ifndef _IDE_CD_H
#define _IDE_CD_H
/*
- * linux/drivers/block/ide_modes.h
+ * linux/drivers/block/ide_cd.h
*
- * Copyright (C) 1996 Erik Andersen
+ * Copyright (C) 1996, 1997, 1998 Erik Andersen
* Copyright (C) 1998, 1999 Jens Axboe
*/
@@ -55,94 +55,37 @@
#define REQUEST_SENSE_COMMAND 4316
#define RESET_DRIVE_COMMAND 4317
-/*
- * For controlling drive spindown time.
- */
-#define CDROMGETSPINDOWN 0x531d
-#define CDROMSETSPINDOWN 0x531e
-
-
-/* Some ATAPI command opcodes (just like SCSI).
- (Some other cdrom-specific codes are in cdrom.h.) */
-#define TEST_UNIT_READY 0x00
-#define REQUEST_SENSE 0x03
-#define INQUIRY 0x12
-#define START_STOP 0x1b
-#define ALLOW_MEDIUM_REMOVAL 0x1e
-#define READ_CAPACITY 0x25
-#define READ_10 0x28
-#define SEEK 0x2b
-#define READ_HEADER 0x44
-#define STOP_PLAY_SCAN 0x4e
-#define MODE_SELECT_10 0x55
-#define MODE_SENSE_10 0x5a
-#define LOAD_UNLOAD 0xa6
-#define READ_12 0xa8
-#define READ_CD_MSF 0xb9
-#define SCAN 0xba
-#define SET_CD_SPEED 0xbb
-#define PLAY_CD 0xbc
-#define MECHANISM_STATUS 0xbd
-#define READ_CD 0xbe
-
-/* DVD Opcodes */
-#define DVD_GET_PERFORMANCE 0xac
-
-
-/* Page codes for mode sense/set */
-
-#define PAGE_READERR 0x01
-#define PAGE_CDROM 0x0d
-#define PAGE_AUDIO 0x0e
-#define PAGE_CAPABILITIES 0x2a
-#define PAGE_ALL 0x3f
-
-
-/* ATAPI sense keys (from table 140 of ATAPI 2.6) */
-
-#define NO_SENSE 0x00
-#define RECOVERED_ERROR 0x01
-#define NOT_READY 0x02
-#define MEDIUM_ERROR 0x03
-#define HARDWARE_ERROR 0x04
-#define ILLEGAL_REQUEST 0x05
-#define UNIT_ATTENTION 0x06
-#define DATA_PROTECT 0x07
-#define ABORTED_COMMAND 0x0b
-#define MISCOMPARE 0x0e
-
-/* We want some additional flags for CDROM drives.
- To save space in the ide_drive_t struct, use some fields which
- doesn't make sense for CDROMs -- `bios_cyl' and `bios_head'. */
/* Configuration flags. These describe the capabilities of the drive.
They generally do not change after initialization, unless we learn
more about the drive from stuff failing. */
struct ide_cd_config_flags {
- __u8 drq_interrupt : 1; /* Device sends an interrupt when ready
- for a packet command. */
- __u8 no_doorlock : 1; /* Drive cannot lock the door. */
- __u8 no_eject : 1; /* Drive cannot eject the disc. */
- __u8 nec260 : 1; /* Drive is a pre-1.2 NEC 260 drive. */
- __u8 playmsf_as_bcd : 1; /* PLAYMSF command takes BCD args. */
- __u8 tocaddr_as_bcd : 1; /* TOC addresses are in BCD. */
- __u8 toctracks_as_bcd : 1; /* TOC track numbers are in BCD. */
- __u8 subchan_as_bcd : 1; /* Subchannel info is in BCD. */
- __u8 is_changer : 1; /* Drive is a changer. */
- __u8 cd_r : 1; /* Drive can write to CD-R media . */
- __u8 cd_rw : 1; /* Drive can write to CD-R/W media . */
- __u8 dvd : 1; /* Drive is a DVD-ROM */
- __u8 dvd_r : 1; /* Drive can write DVD-RAM */
- __u8 dvd_rw : 1; /* Drive can write DVD-R/W */
- __u8 test_write : 1; /* Drive can fake writes */
- __u8 supp_disc_present: 1; /* Changer can report exact contents
- of slots. */
- __u8 limit_nframes : 1; /* Drive does not provide data in
- multiples of SECTOR_SIZE when more
- than one interrupt is needed. */
- __u8 seeking : 1; /* Seeking in progress */
- __u8 reserved : 6;
- byte max_speed; /* Max speed of the drive */
+ __u8 drq_interrupt : 1; /* Device sends an interrupt when ready
+ for a packet command. */
+ __u8 no_doorlock : 1; /* Drive cannot lock the door. */
+ __u8 no_eject : 1; /* Drive cannot eject the disc. */
+ __u8 nec260 : 1; /* Drive is a pre-1.2 NEC 260 drive. */
+ __u8 playmsf_as_bcd : 1; /* PLAYMSF command takes BCD args. */
+ __u8 tocaddr_as_bcd : 1; /* TOC addresses are in BCD. */
+ __u8 toctracks_as_bcd : 1; /* TOC track numbers are in BCD. */
+ __u8 subchan_as_bcd : 1; /* Subchannel info is in BCD. */
+ __u8 is_changer : 1; /* Drive is a changer. */
+ __u8 cd_r : 1; /* Drive can write to CD-R media . */
+ __u8 cd_rw : 1; /* Drive can write to CD-R/W media . */
+ __u8 dvd : 1; /* Drive is a DVD-ROM */
+ __u8 dvd_r : 1; /* Drive can write DVD-R */
+ __u8 dvd_ram : 1; /* Drive can write DVD-RAM */
+ __u8 test_write : 1; /* Drive can fake writes */
+ __u8 supp_disc_present : 1; /* Changer can report exact contents
+ of slots. */
+ __u8 limit_nframes : 1; /* Drive does not provide data in
+ multiples of SECTOR_SIZE when more
+ than one interrupt is needed. */
+ __u8 seeking : 1; /* Seeking in progress */
+ __u8 audio_play : 1; /* can do audio related commands */
+ __u8 close_tray : 1; /* can close the tray */
+ __u8 reserved : 4;
+ byte max_speed; /* Max speed of the drive */
};
#define CDROM_CONFIG_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->config_flags))
@@ -153,8 +96,7 @@ struct ide_cd_state_flags {
__u8 media_changed : 1; /* Driver has noticed a media change. */
__u8 toc_valid : 1; /* Saved TOC information is current. */
__u8 door_locked : 1; /* We think that the drive door is locked. */
- __u8 sanyo_slot : 2; /* Sanyo 3 CD changer support */
- __u8 reserved : 3;
+ __u8 reserved : 5;
byte current_speed; /* Current speed of the drive */
};
#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags))
@@ -276,15 +218,10 @@ struct atapi_cdrom_subchnl {
};
-typedef enum {
- mechtype_caddy = 0,
- mechtype_tray = 1,
- mechtype_popup = 2,
- mechtype_individual_changer = 4,
- mechtype_cartridge_changer = 5
-} mechtype_t;
-
+/* This should probably go into cdrom.h along with the other
+ * generic stuff now in the Mt. Fuji spec.
+ */
struct atapi_capabilities_page {
#if defined(__BIG_ENDIAN_BITFIELD)
__u8 parameters_saveable : 1;
@@ -518,9 +455,11 @@ struct atapi_mechstat_header {
#if defined(__BIG_ENDIAN_BITFIELD)
__u8 mech_state : 3;
- __u8 reserved1 : 5;
+ __u8 door_open : 1;
+ __u8 reserved1 : 4;
#elif defined(__LITTLE_ENDIAN_BITFIELD)
- __u8 reserved1 : 5;
+ __u8 reserved1 : 4;
+ __u8 door_open : 1;
__u8 mech_state : 3;
#else
#error "Please fix <asm/byteorder.h>"
@@ -604,11 +543,85 @@ struct cdrom_info {
#define ARY_LEN(a) ((sizeof(a) / sizeof(a[0])))
+/* This stuff should be in cdrom.h, since it is now generic... */
+
+/* ATAPI sense keys (from table 140 of ATAPI 2.6) */
+#define NO_SENSE 0x00
+#define RECOVERED_ERROR 0x01
+#define NOT_READY 0x02
+#define MEDIUM_ERROR 0x03
+#define HARDWARE_ERROR 0x04
+#define ILLEGAL_REQUEST 0x05
+#define UNIT_ATTENTION 0x06
+#define DATA_PROTECT 0x07
+#define ABORTED_COMMAND 0x0b
+#define MISCOMPARE 0x0e
+
+
+
+/* This stuff should be in cdrom.h, since it is now generic... */
#if VERBOSE_IDE_CD_ERRORS
-/* From Table 124 of the ATAPI 1.2 spec.
- Unchanged in Table 140 of the ATAPI 2.6 draft standard. */
+ /* The generic packet command opcodes for CD/DVD Logical Units,
+ * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
+const struct {
+ unsigned short packet_command;
+ const char * const text;
+} packet_command_texts[] = {
+ { GPCMD_TEST_UNIT_READY, "Test Unit Ready" },
+ { GPCMD_REQUEST_SENSE, "Request Sense" },
+ { GPCMD_FORMAT_UNIT, "Format Unit" },
+ { GPCMD_INQUIRY, "Inquiry" },
+ { GPCMD_START_STOP_UNIT, "Start/Stop Unit" },
+ { GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, "Prevent/Allow Medium Removal" },
+ { GPCMD_READ_FORMAT_CAPACITIES, "Read Format Capacities" },
+ { GPCMD_READ_CDVD_CAPACITY, "Read Cd/Dvd Capacity" },
+ { GPCMD_READ_10, "Read 10" },
+ { GPCMD_WRITE_10, "Write 10" },
+ { GPCMD_SEEK, "Seek" },
+ { GPCMD_WRITE_AND_VERIFY_10, "Write and Verify 10" },
+ { GPCMD_VERIFY_10, "Verify 10" },
+ { GPCMD_FLUSH_CACHE, "Flush Cache" },
+ { GPCMD_READ_SUBCHANNEL, "Read Subchannel" },
+ { GPCMD_READ_TOC_PMA_ATIP, "Read Table of Contents" },
+ { GPCMD_READ_HEADER, "Read Header" },
+ { GPCMD_PLAY_AUDIO_10, "Play Audio 10" },
+ { GPCMD_GET_CONFIGURATION, "Get Configuration" },
+ { GPCMD_PLAY_AUDIO_MSF, "Play Audio MSF" },
+ { GPCMD_PLAYAUDIO_TI, "Play Audio TrackIndex" },
+ { GPCMD_GET_EVENT_STATUS_NOTIFICATION, "Get Event Status Notification" },
+ { GPCMD_PAUSE_RESUME, "Pause/Resume" },
+ { GPCMD_STOP_PLAY_SCAN, "Stop Play/Scan" },
+ { GPCMD_READ_DISC_INFO, "Read Disc Info" },
+ { GPCMD_READ_TRACK_RZONE_INFO, "Read Track Rzone Info" },
+ { GPCMD_RESERVE_RZONE_TRACK, "Reserve Rzone Track" },
+ { GPCMD_SEND_OPC, "Send OPC" },
+ { GPCMD_MODE_SELECT_10, "Mode Select 10" },
+ { GPCMD_REPAIR_RZONE_TRACK, "Repair Rzone Track" },
+ { GPCMD_MODE_SENSE_10, "Mode Sense 10" },
+ { GPCMD_CLOSE_TRACK, "Close Track" },
+ { GPCMD_BLANK, "Blank" },
+ { GPCMD_SEND_EVENT, "Send Event" },
+ { GPCMD_SEND_KEY, "Send Key" },
+ { GPCMD_REPORT_KEY, "Report Key" },
+ { GPCMD_LOAD_UNLOAD, "Load/Unload" },
+ { GPCMD_SET_READ_AHEAD, "Set Read-ahead" },
+ { GPCMD_READ_12, "Read 12" },
+ { GPCMD_GET_PERFORMANCE, "Get Performance" },
+ { GPCMD_SEND_DVD_STRUCTURE, "Send DVD Structure" },
+ { GPCMD_READ_DVD_STRUCTURE, "Read DVD Structure" },
+ { GPCMD_SET_STREAMING, "Set Streaming" },
+ { GPCMD_READ_CD_MSF, "Read CD MSF" },
+ { GPCMD_SCAN, "Scan" },
+ { GPCMD_SET_SPEED, "Set Speed" },
+ { GPCMD_PLAY_CD, "Play CD" },
+ { GPCMD_MECHANISM_STATUS, "Mechanism Status" },
+ { GPCMD_READ_CD, "Read CD" },
+};
+
+
+/* From Table 303 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
const char * const sense_key_texts[16] = {
"No sense data",
"Recovered error",
@@ -628,162 +641,108 @@ const char * const sense_key_texts[16] = {
"(reserved)",
};
-
-/* From Table 37 of the ATAPI 2.6 draft standard. */
+/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
const struct {
- unsigned short packet_command;
- const char * const text;
-} packet_command_texts[] = {
- { TEST_UNIT_READY, "Test Unit Ready" },
- { REQUEST_SENSE, "Request Sense" },
- { INQUIRY, "Inquiry" },
- { START_STOP, "Start Stop Unit" },
- { ALLOW_MEDIUM_REMOVAL, "Prevent/Allow Medium Removal" },
- { READ_CAPACITY, "Read CD-ROM Capacity" },
- { READ_10, "Read(10)" },
- { SEEK, "Seek" },
- { SCMD_READ_TOC, "Read TOC" },
- { SCMD_READ_SUBCHANNEL, "Read Sub-Channel" },
- { READ_HEADER, "Read Header" },
- { STOP_PLAY_SCAN, "Stop Play/Scan" },
- { SCMD_PLAYAUDIO10, "Play Audio" },
- { SCMD_PLAYAUDIO_MSF, "Play Audio MSF" },
- { SCMD_PAUSE_RESUME, "Pause/Resume" },
- { MODE_SELECT_10, "Mode Select" },
- { MODE_SENSE_10, "Mode Sense" },
- { LOAD_UNLOAD, "Load/Unload CD" },
- { READ_12, "Read(12)" },
- { READ_CD_MSF, "Read CD MSF" },
- { SCAN, "Scan" },
- { SET_CD_SPEED, "Set CD Speed" },
- { PLAY_CD, "Play CD" },
- { MECHANISM_STATUS, "Mechanism Status" },
- { READ_CD, "Read CD" },
- { DVD_GET_PERFORMANCE, "Get Performance" },
-};
-
-
-/* From Table 125 of the ATAPI 1.2 spec.,
- with additions from Tables 141 and 142 of the ATAPI 2.6 draft standard. */
-
-const struct {
- unsigned short asc_ascq;
+ unsigned long asc_ascq;
const char * const text;
} sense_data_texts[] = {
- { 0x0000, "No additional sense information" },
-
- { 0x0011, "Audio play operation in progress" },
- { 0x0012, "Audio play operation paused" },
- { 0x0013, "Audio play operation successfully completed" },
- { 0x0014, "Audio play operation stopped due to error" },
- { 0x0015, "No current audio status to return" },
-
- { 0x0100, "Mechanical positioning or changer error" },
-
- { 0x0200, "No seek complete" },
-
- { 0x0400, "Logical unit not ready - cause not reportable" },
- { 0x0401,
- "Logical unit not ready - in progress (sic) of becoming ready" },
- { 0x0402, "Logical unit not ready - initializing command required" },
- { 0x0403, "Logical unit not ready - manual intervention required" },
-
- { 0x0501, "Media load - eject failed" },
-
- { 0x0600, "No reference position found" },
-
- { 0x0900, "Track following error" },
- { 0x0901, "Tracking servo failure" },
- { 0x0902, "Focus servo failure" },
- { 0x0903, "Spindle servo failure" },
-
- { 0x1100, "Unrecovered read error" },
- { 0x1106, "CIRC unrecovered error" },
-
- { 0x1500, "Random positioning error" },
- { 0x1501, "Mechanical positioning or changer error" },
- { 0x1502, "Positioning error detected by read of medium" },
-
- { 0x1700, "Recovered data with no error correction applied" },
- { 0x1701, "Recovered data with retries" },
- { 0x1702, "Recovered data with positive head offset" },
- { 0x1703, "Recovered data with negative head offset" },
- { 0x1704, "Recovered data with retries and/or CIRC applied" },
- { 0x1705, "Recovered data using previous sector ID" },
-
- { 0x1800, "Recovered data with error correction applied" },
- { 0x1801, "Recovered data with error correction and retries applied" },
- { 0x1802, "Recovered data - the data was auto-reallocated" },
- { 0x1803, "Recovered data with CIRC" },
- { 0x1804, "Recovered data with L-EC" },
- /* Following two not in 2.6. */
- { 0x1805, "Recovered data - recommend reassignment" },
- { 0x1806, "Recovered data - recommend rewrite" },
-
- { 0x1a00, "Parameter list length error" },
-
- { 0x2000, "Invalid command operation code" },
-
- { 0x2100, "Logical block address out of range" },
-
- { 0x2400, "Invalid field in command packet" },
-
- { 0x2600, "Invalid field in parameter list" },
- { 0x2601, "Parameter not supported" },
- { 0x2602, "Parameter value invalid" },
- /* Following code not in 2.6. */
- { 0x2603, "Threshold parameters not supported" },
-
- { 0x2800, "Not ready to ready transition, medium may have changed" },
-
- { 0x2900, "Power on, reset or bus device reset occurred" },
-
- { 0x2a00, "Parameters changed" },
- { 0x2a01, "Mode parameters changed" },
-
- { 0x3000, "Incompatible medium installed" },
- { 0x3001, "Cannot read medium - unknown format" },
- { 0x3002, "Cannot read medium - incompatible format" },
-
- /* Following code not in 2.6. */
- { 0x3700, "Rounded parameter" },
-
- { 0x3900, "Saving parameters not supported" },
-
- { 0x3a00, "Medium not present" },
-
- { 0x3f00, "ATAPI CD-ROM drive operating conditions have changed" },
- { 0x3f01, "Microcode has been changed" },
- /* Following two not in 2.6. */
- { 0x3f02, "Changed operating definition" },
- { 0x3f03, "Inquiry data has changed" },
-
- { 0x4000, "Diagnostic failure on component (ASCQ)" },
-
- { 0x4400, "Internal ATAPI CD-ROM drive failure" },
-
- { 0x4e00, "Overlapped commands attempted" },
-
- { 0x5300, "Media load or eject failed" },
- { 0x5302, "Medium removal prevented" },
-
- { 0x5700, "Unable to recover table of contents" },
-
- { 0x5a00, "Operator request or state change input (unspecified)" },
- { 0x5a01, "Operator medium removal request" },
-
- /* Following two not in 2.6. */
- { 0x5b00, "Threshold condition met" },
- { 0x5c00, "Status change" },
-
- { 0x6300, "End of user area encountered on this track" },
-
- { 0x6400, "Illegal mode for this track or incompatible medium" },
-
- /* Following error is misspelled in ATAPI 2.6 */
- { 0xb900, "Play operation oborted [sic]" },
-
- { 0xbf00, "Loss of streaming" },
+ { 0x000000, "No additional sense information" },
+ { 0x000011, "Play operation in progress" },
+ { 0x000012, "Play operation paused" },
+ { 0x000013, "Play operation successfully completed" },
+ { 0x000014, "Play operation stopped due to error" },
+ { 0x000015, "No current audio status to return" },
+ { 0x011700, "Recovered data with no error correction applied" },
+ { 0x011701, "Recovered data with retries" },
+ { 0x011702, "Recovered data with positive head offset" },
+ { 0x011703, "Recovered data with negative head offset" },
+ { 0x011704, "Recovered data with retries and/or CIRC applied" },
+ { 0x011705, "Recovered data using previous sector ID" },
+ { 0x011800, "Recovered data with error correction applied" },
+ { 0x011801, "Recovered data with error correction and retries applied"},
+ { 0x011802, "Recovered data - the data was auto-reallocated" },
+ { 0x011803, "Recovered data with CIRC" },
+ { 0x011804, "Recovered data with L-EC" },
+ { 0x015d00,
+ "Failure prediction threshold exceeded - Predicted logical unit failure" },
+ { 0x015d01,
+ "Failure prediction threshold exceeded - Predicted media failure" },
+ { 0x015dff, "Failure prediction threshold exceeded - False" },
+ { 0x020400, "Logical unit not ready - cause not reportable" },
+ /* Following is misspelled in ATAPI 2.6, _and_ in Mt. Fuji */
+ { 0x020401,
+ "Logical unit not ready - in progress [sic] of becoming ready" },
+ { 0x020402, "Logical unit not ready - initializing command required" },
+ { 0x020403, "Logical unit not ready - manual intervention required" },
+ { 0x020404, "In process of becoming ready - writing" },
+ { 0x020600, "No reference position found (media may be upside down)" },
+ { 0x023000, "Incompatible medium installed" },
+ { 0x023a00, "Medium not present" },
+ { 0x025300, "Media load or eject failed" },
+ { 0x025700, "Unable to recover table of contents" },
+ { 0x031100, "Unrecovered read error" },
+ { 0x031106, "CIRC unrecovered error" },
+ { 0x033101, "Format command failed" },
+ { 0x040200, "No seek complete" },
+ { 0x040300, "Write fault" },
+ { 0x040900, "Track following error" },
+ { 0x040901, "Tracking servo failure" },
+ { 0x040902, "Focus servo failure" },
+ { 0x040903, "Spindle servo failure" },
+ { 0x041500, "Random positioning error" },
+ { 0x041501, "Mechanical positioning or changer error" },
+ { 0x041502, "Positioning error detected by read of medium" },
+ { 0x043c00, "Mechanical positioning or changer error" },
+ { 0x044000, "Diagnostic failure on component (ASCQ)" },
+ { 0x044400, "Internal CD/DVD logical unit failure" },
+ { 0x04b600, "Media load mechanism failed" },
+ { 0x051a00, "Parameter list length error" },
+ { 0x052000, "Invalid command operation code" },
+ { 0x052c00, "Command sequence error" },
+ { 0x052100, "Logical block address out of range" },
+ { 0x052400, "Invalid field in command packet" },
+ { 0x052600, "Invalid field in parameter list" },
+ { 0x052601, "Parameter not supported" },
+ { 0x052602, "Parameter value invalid" },
+ { 0x052700, "Write protected media" },
+ { 0x053001, "Cannot read medium - unknown format" },
+ { 0x053002, "Cannot read medium - incompatible format" },
+ { 0x053900, "Saving parameters not supported" },
+ { 0x054e00, "Overlapped commands attempted" },
+ { 0x055302, "Medium removal prevented" },
+ { 0x055500, "System resource failure" },
+ { 0x056300, "End of user area encountered on this track" },
+ { 0x056400, "Illegal mode for this track or incompatible medium" },
+ { 0x056f00,
+ "Copy protection key exchange failure - Authentication failure" },
+ { 0x056f01, "Copy protection key exchange failure - Key not present" },
+ { 0x056f02,
+ "Copy protection key exchange failure - Key not established" },
+ { 0x05bf00, "Loss of streaming" },
+ { 0x062800, "Not ready to ready transition, medium may have changed" },
+ { 0x062900, "Power on, reset or hardware reset occurred" },
+ { 0x062a00, "Parameters changed" },
+ { 0x062a01, "Mode parameters changed" },
+ { 0x062e00, "Insufficient time for operation" },
+ { 0x063f00, "Logical unit operating conditions have changed" },
+ { 0x063f01, "Microcode has been changed" },
+ { 0x065a00, "Operator request or state change input (unspecified)" },
+ { 0x065a01, "Operator medium removal request" },
+ { 0x0bb900, "Play operation aborted" },
+
+ /* Here we use 0xff for the key (not a valid key) to signify
+ * that these can have _any_ key value associated with them... */
+ { 0xff0401, "Logical unit is in process of becoming ready" },
+ { 0xff0400, "Logical unit not ready, cause not reportable" },
+ { 0xff0402, "Logical unit not ready, initializing command required" },
+ { 0xff0403, "Logical unit not ready, manual intervention required" },
+ { 0xff0500, "Logical unit does not respond to selection" },
+ { 0xff0800, "Logical unit communication failure" },
+ { 0xff0802, "Logical unit communication parity error" },
+ { 0xff0801, "Logical unit communication time-out" },
+ { 0xff2500, "Logical unit not supported" },
+ { 0xff4c00, "Logical unit failed self-configuration" },
+ { 0xff3e00, "Logical unit has not self-configured yet" },
};
#endif
diff --git a/drivers/block/ide-dma.c b/drivers/block/ide-dma.c
index 0cda4398c..cd631c621 100644
--- a/drivers/block/ide-dma.c
+++ b/drivers/block/ide-dma.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/ide-dma.c Version 4.09 April 23, 1999
+ * linux/drivers/block/ide-dma.c Version 4.09 April 23, 1999
*
* Copyright (c) 1999 Andre Hedrick
* May be copied or modified under the terms of the GNU General Public License
@@ -357,12 +357,11 @@ static int config_drive_for_dma (ide_drive_t *drive)
/* Consult the list of known "bad" drives */
if (ide_dmaproc(ide_dma_bad_drive, drive))
return hwif->dmaproc(ide_dma_off, drive);
-#ifdef CONFIG_IDEDMA_ULTRA_66
+
/* Enable DMA on any drive that has UltraDMA (mode 3/4) enabled */
- if ((id->field_valid & 4) && (id->word93 & 0x2000))
+ if ((id->field_valid & 4) && (hwif->udma_four) && (id->word93 & 0x2000))
if ((id->dma_ultra & (id->dma_ultra >> 11) & 3))
return hwif->dmaproc(ide_dma_on, drive);
-#endif /* CONFIG_IDEDMA_ULTRA_66 */
/* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */
if (id->field_valid & 4) /* UltraDMA */
if ((id->dma_ultra & (id->dma_ultra >> 8) & 7))
@@ -443,6 +442,12 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
case ide_dma_bad_drive:
case ide_dma_good_drive:
return check_drive_lists(drive, (func == ide_dma_good_drive));
+ case ide_dma_lostirq:
+ case ide_dma_timeout:
+ /*
+ * printk("ide_dmaproc: chipset supported func only: %d\n", func);
+ */
+ return 1;
default:
printk("ide_dmaproc: unsupported func: %d\n", func);
return 1;
@@ -465,7 +470,7 @@ int ide_release_dma (ide_hwif_t *hwif)
}
/*
- * This can be called for a dynamically installed interface. Don't initfunc it
+ * This can be called for a dynamically installed interface. Don't __init it
*/
void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports)
@@ -510,7 +515,7 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p
/*
* Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space:
*/
-__initfunc(unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name))
+unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name)
{
unsigned long dma_base = 0;
struct pci_dev *dev = hwif->pci_dev;
@@ -518,7 +523,7 @@ __initfunc(unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, c
if (hwif->mate && hwif->mate->dma_base) {
dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8);
} else {
- dma_base = dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK;
+ dma_base = dev->resource[4].start;
if (!dma_base || dma_base == PCI_BASE_ADDRESS_IO_MASK) {
printk("%s: dma_base is invalid (0x%04lx)\n", name, dma_base);
dma_base = 0;
@@ -532,10 +537,6 @@ __initfunc(unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, c
switch(dev->device) {
case PCI_DEVICE_ID_CMD_643:
- /*
- * Lets attempt to use the same Ali tricks
- * to fix CMD643.....
- */
#ifdef CONFIG_BLK_DEV_ALI15X3
case PCI_DEVICE_ID_AL_M5219:
case PCI_DEVICE_ID_AL_M5229:
@@ -550,9 +551,19 @@ __initfunc(unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, c
}
break;
default:
- if (inb(dma_base+2) & 0x80) {
- printk("%s: simplex device: DMA disabled\n", name);
- dma_base = 0;
+ /*
+ * If the device claims "simplex" DMA,
+ * this means only one of the two interfaces
+ * can be trusted with DMA at any point in time.
+ * So we should enable DMA only on one of the
+ * two interfaces.
+ */
+ if ((inb(dma_base+2) & 0x80)) { /* simplex device? */
+ if ((!hwif->drives[0].present && !hwif->drives[1].present) ||
+ (hwif->mate && hwif->mate->dma_base)) {
+ printk("%s: simplex device: DMA disabled\n", name);
+ dma_base = 0;
+ }
}
}
}
diff --git a/drivers/block/ide-floppy.c b/drivers/block/ide-floppy.c
index 49ccb66ce..66b71b3a2 100644
--- a/drivers/block/ide-floppy.c
+++ b/drivers/block/ide-floppy.c
@@ -1,7 +1,7 @@
/*
- * linux/drivers/block/ide-floppy.c Version 0.8 Dec 7, 1997
+ * linux/drivers/block/ide-floppy.c Version 0.9 Jul 4, 1999
*
- * Copyright (C) 1996, 1997 Gadi Oxman <gadio@netvision.net.il>
+ * Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il>
*/
/*
@@ -26,9 +26,12 @@
* Issue START command only if TEST UNIT READY fails.
* Add work-around for IOMEGA ZIP revision 21.D.
* Remove idefloppy_get_capabilities().
+ * Ver 0.9 Jul 4 99 Fix a bug which might have caused the number of
+ * bytes requested on each interrupt to be zero.
+ * Thanks to <shanos@es.co.nz> for pointing this out.
*/
-#define IDEFLOPPY_VERSION "0.8"
+#define IDEFLOPPY_VERSION "0.9"
#include <linux/config.h>
#include <linux/module.h>
@@ -997,7 +1000,7 @@ static void idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc)
pc->retries++;
pc->actually_transferred=0; /* We haven't transferred any data yet */
pc->current_position=pc->buffer;
- bcount.all=pc->request_transfer; /* Request to transfer the entire buffer at once */
+ bcount.all = IDE_MIN(pc->request_transfer, 63 * 1024);
#ifdef CONFIG_BLK_DEV_IDEDMA
if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) {
@@ -1521,9 +1524,19 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
floppy->pc = floppy->pc_stack;
if (gcw.drq_type == 1)
set_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags);
- if (strcmp(drive->id->model, "IOMEGA ZIP 100 ATAPI") == 0 &&
- ((strcmp(drive->id->fw_rev, "21.D") == 0) ||
- (strcmp(drive->id->fw_rev, "23.D") == 0))) {
+ /*
+ * We used to check revisions here. At this point however
+ * I'm giving up. Just assume they are all broken, its easier.
+ *
+ * The actual reason for the workarounds was likely
+ * a driver bug after all rather than a firmware bug,
+ * and the workaround below used to hide it. It should
+ * be fixed as of version 1.9, but to be on the safe side
+ * we'll leave the limitation below for the 2.2.x tree.
+ */
+
+ if (strcmp(drive->id->model, "IOMEGA ZIP 100 ATAPI") == 0)
+ {
for (i = 0; i < 1 << PARTN_BITS; i++)
max_sectors[major][minor + i] = 64;
}
diff --git a/drivers/block/ide-pci.c b/drivers/block/ide-pci.c
index 019aec4fb..3ba39f600 100644
--- a/drivers/block/ide-pci.c
+++ b/drivers/block/ide-pci.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/ide-pci.c Version 1.03 May 1, 1999
+ * linux/drivers/block/ide-pci.c Version 1.04 July 27, 1999
*
* Copyright (c) 1998-1999 Andre Hedrick
*
@@ -52,6 +52,7 @@
#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})
+#define DEVID_HPT366 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366})
#define DEVID_ALI15X3 ((ide_pci_devid_t){PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229})
#define DEVID_CY82C693 ((ide_pci_devid_t){PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693})
#define DEVID_HINT ((ide_pci_devid_t){0x3388, 0x8013})
@@ -106,11 +107,14 @@ extern void ide_init_rz1000(ide_hwif_t *);
#endif
#ifdef CONFIG_BLK_DEV_VIA82C586
+extern unsigned int pci_init_via82c568(struct pci_dev *, const char *);
extern void ide_init_via82c586(ide_hwif_t *);
extern void ide_dmacapable_via82c586(ide_hwif_t *, unsigned long dmabase);
+#define PCI_VIA82C586 &pci_init_via82c568
#define INIT_VIA82C586 &ide_init_via82c586
#define DMA_VIA82C586 &ide_dmacapable_via82c586
#else
+#define PCI_VIA82C586 NULL
#define INIT_VIA82C586 NULL
#define DMA_VIA82C586 NULL
#endif
@@ -126,9 +130,12 @@ extern void ide_init_ali15x3(ide_hwif_t *);
#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 *);
+#define PCI_CY82C693 &pci_init_cy82c693
#define INIT_CY82C693 &ide_init_cy82c693
#else
+#define PCI_CY82C693 NULL
#define INIT_CY82C693 NULL
#endif
@@ -166,6 +173,26 @@ extern void ide_init_hpt34x(ide_hwif_t *);
#define INIT_HPT34X NULL
#endif
+#ifdef CONFIG_BLK_DEV_HPT366
+extern unsigned int pci_init_hpt366(struct pci_dev *, const char *);
+extern void ide_init_hpt366(ide_hwif_t *);
+#define PCI_HPT366 &pci_init_hpt366
+#define INIT_HPT366 &ide_init_hpt366
+#else
+#define PCI_HPT366 NULL
+#define INIT_HPT366 IDE_IGNORE
+#endif
+
+#ifdef CONFIG_BLK_DEV_SIS5513
+extern unsigned int pci_init_sis5513(struct pci_dev *, const char *);
+extern void ide_init_sis5513(ide_hwif_t *);
+#define PCI_SIS5513 &pci_init_sis5513
+#define INIT_SIS5513 &ide_init_sis5513
+#else
+#define PCI_SIS5513 NULL
+#define INIT_SIS5513 NULL
+#endif
+
#define INIT_SAMURAI NULL
#define INIT_CX5530 NULL
@@ -183,71 +210,76 @@ typedef struct ide_pci_device_s {
void (*dma_init)(ide_hwif_t *hwif, unsigned long dmabase);
ide_pci_enablebit_t enablebits[2];
byte bootable;
+ byte sixtysix;
unsigned int extra;
} ide_pci_device_t;
static ide_pci_device_t ide_pci_chipsets[] __initdata = {
- {DEVID_PIIXa, "PIIX", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_PIIXb, "PIIX", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_PIIX3, "PIIX3", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_PIIX4, "PIIX4", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_VP_IDE, "VP_IDE", NULL, INIT_VIA82C586, DMA_VIA82C586, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 },
- {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 },
- {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 },
- {DEVID_RZ1000, "RZ1000", NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_RZ1001, "RZ1001", NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_SAMURAI, "SAMURAI", NULL, INIT_SAMURAI, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_CMD640, "CMD640", NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_NS87410, "NS87410", NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0 },
- {DEVID_SIS5513, "SIS5513", NULL, NULL, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 0 },
- {DEVID_CMD643, "CMD643", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_CMD646, "CMD646", NULL, INIT_CMD646, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_HT6565, "HT6565", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_OPTI621, "OPTI621", NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 },
- {DEVID_OPTI621X,"OPTI621X", NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 },
- {DEVID_TRM290, "TRM290", NULL, INIT_TRM290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_NS87415, "NS87415", NULL, INIT_NS87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_AEC6210, "AEC6210", PCI_AEC6210, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 },
- {DEVID_W82C105, "W82C105", NULL, INIT_W82C105, NULL, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 },
- {DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_HPT34X, "HPT34X", PCI_HPT34X, INIT_HPT34X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 },
- {DEVID_ALI15X3, "ALI15X3", PCI_ALI15X3, INIT_ALI15X3, NULL, {{0x09,0x20,0x20}, {0x09,0x10,0x10}}, ON_BOARD, 0 },
- {DEVID_CY82C693,"CY82C693", NULL, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_CX5530, "CX5530", NULL, INIT_CX5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }};
+ {DEVID_PIIXa, "PIIX", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
+ {DEVID_PIIXb, "PIIX", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
+ {DEVID_PIIX3, "PIIX3", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
+ {DEVID_PIIX4, "PIIX4", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
+ {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
+ {DEVID_VP_IDE, "VP_IDE", PCI_VIA82C586, INIT_VIA82C586, DMA_VIA82C586, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0, 0 },
+ {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 0, 16 },
+ {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 1, 48 },
+ {DEVID_RZ1000, "RZ1000", NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
+ {DEVID_RZ1001, "RZ1001", NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
+ {DEVID_SAMURAI, "SAMURAI", NULL, INIT_SAMURAI, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
+ {DEVID_CMD640, "CMD640", NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
+ {DEVID_NS87410, "NS87410", NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0, 0 },
+ {DEVID_SIS5513, "SIS5513", PCI_SIS5513, INIT_SIS5513, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 1, 0 },
+ {DEVID_CMD643, "CMD643", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
+ {DEVID_CMD646, "CMD646", NULL, INIT_CMD646, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0, 0 },
+ {DEVID_HT6565, "HT6565", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
+ {DEVID_OPTI621, "OPTI621", NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0, 0 },
+ {DEVID_OPTI621X,"OPTI621X", NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0, 0 },
+ {DEVID_TRM290, "TRM290", NULL, INIT_TRM290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
+ {DEVID_NS87415, "NS87415", NULL, INIT_NS87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
+ {DEVID_AEC6210, "AEC6210", PCI_AEC6210, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, 0 },
+ {DEVID_W82C105, "W82C105", NULL, INIT_W82C105, NULL, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0, 0 },
+ {DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
+ {DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
+ {DEVID_HPT34X, "HPT34X", PCI_HPT34X, INIT_HPT34X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0, 16 },
+ {DEVID_HPT366, "HPT366", PCI_HPT366, INIT_HPT366, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 1, 256 },
+ {DEVID_ALI15X3, "ALI15X3", PCI_ALI15X3, INIT_ALI15X3, NULL, {{0x09,0x20,0x20}, {0x09,0x10,0x10}}, ON_BOARD, 0, 0 },
+ {DEVID_CY82C693,"CY82C693", PCI_CY82C693, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
+ {DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
+ {DEVID_CX5530, "CX5530", NULL, INIT_CX5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
+ {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }};
+
+static byte hpt363_shared_irq = 0;
/*
* This allows offboard ide-pci cards the enable a BIOS, verify interrupt
* settings of split-mirror pci-config space, place chipset into init-mode,
* and/or preserve an interrupt if the card is not native ide support.
*/
-__initfunc(static unsigned int ide_special_settings (struct pci_dev *dev, const char *name))
+static unsigned int __init ide_special_settings (struct pci_dev *dev, const char *name)
{
switch(dev->device) {
case PCI_DEVICE_ID_TTI_HPT343:
{
- int i;
unsigned short pcicmd = 0;
- unsigned long hpt34xIoBase = dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK;
pci_write_config_byte(dev, 0x80, 0x00);
- dev->base_address[0] = (hpt34xIoBase + 0x20);
- dev->base_address[1] = (hpt34xIoBase + 0x34);
- dev->base_address[2] = (hpt34xIoBase + 0x28);
- dev->base_address[3] = (hpt34xIoBase + 0x3c);
- for(i=0; i<4; i++)
- dev->base_address[i] |= PCI_BASE_ADDRESS_SPACE_IO;
-
pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
if (!(pcicmd & PCI_COMMAND_MEMORY)) {
+ int i;
+ unsigned long hpt34xIoBase = dev->resource[4].start;
+
+ dev->resource[0].start = (hpt34xIoBase + 0x20);
+ dev->resource[1].start = (hpt34xIoBase + 0x34);
+ dev->resource[2].start = (hpt34xIoBase + 0x28);
+ dev->resource[3].start = (hpt34xIoBase + 0x3c);
+ for(i=0; i<4; i++)
+ dev->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
} else {
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0);
}
}
+ case PCI_DEVICE_ID_TTI_HPT366:
case PCI_DEVICE_ID_PROMISE_20246:
case PCI_DEVICE_ID_PROMISE_20262:
case PCI_DEVICE_ID_ARTOP_ATP850UF:
@@ -262,7 +294,7 @@ __initfunc(static unsigned int ide_special_settings (struct pci_dev *dev, const
* Match a PCI IDE port against an entry in ide_hwifs[],
* based on io_base port if possible.
*/
-__initfunc(static ide_hwif_t *ide_match_hwif (unsigned long io_base, byte bootable, const char *name))
+static ide_hwif_t __init *ide_match_hwif (unsigned long io_base, byte bootable, const char *name)
{
int h;
ide_hwif_t *hwif;
@@ -324,7 +356,7 @@ __initfunc(static ide_hwif_t *ide_match_hwif (unsigned long io_base, byte bootab
return NULL;
}
-__initfunc(static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name))
+static int __init ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)
{
byte reg, progif = 0;
@@ -346,11 +378,15 @@ __initfunc(static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *n
/*
* Setup base registers for IDE command/control spaces for each interface:
*/
- for (reg = 0; reg < 4; reg++)
- if (!dev->base_address[reg]) {
+ for (reg = 0; reg < 4; reg++) {
+ struct resource *res = dev->resource + reg;
+ if (!(res->flags & PCI_BASE_ADDRESS_SPACE_IO))
+ continue;
+ if (!res->start) {
printk("%s: Missing I/O address #%d\n", name, reg);
return 1;
}
+ }
return 0;
}
@@ -364,7 +400,7 @@ __initfunc(static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *n
* we "know" about, this information is in the ide_pci_device_t struct;
* for all other chipsets, we just assume both interfaces are enabled.
*/
-__initfunc(static void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d))
+static void __init ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d)
{
unsigned int port, at_least_one_hwif_enabled = 0, autodma = 0, pciirq = 0;
unsigned short pcicmd = 0, tried_config = 0;
@@ -446,9 +482,19 @@ check_if_enabled:
ide_pci_enablebit_t *e = &(d->enablebits[port]);
if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val))
continue; /* port not enabled */
+ if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port))
+ return;
if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) {
- ctl = dev->base_address[(2*port)+1] & PCI_BASE_ADDRESS_IO_MASK;
- base = dev->base_address[2*port] & ~7;
+ ctl = dev->resource[(2*port)+1].start;
+ base = dev->resource[2*port].start;
+ if (!(ctl & PCI_BASE_ADDRESS_IO_MASK) ||
+ !(base & PCI_BASE_ADDRESS_IO_MASK)) {
+ printk("%s: IO baseregs (BIOS) are reported as MEM, report to <andre@suse.com>.\n", d->name);
+#if 0
+ /* FIXME! This really should check that it really gets the IO/MEM part right! */
+ continue;
+#endif
+ }
}
if ((ctl && !base) || (base && !ctl)) {
printk("%s: inconsistent baseregs (BIOS) for port %d, skipping\n", d->name, port);
@@ -484,13 +530,12 @@ check_if_enabled:
hwif->irq = hwif->channel ? 15 : 14;
goto bypass_umc_dma;
}
-
+ if ((!d->sixtysix) && (hwif->udma_four))
+ hwif->udma_four = 0;
#ifdef CONFIG_BLK_DEV_IDEDMA
if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513) ||
IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X))
autodma = 0;
- if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262))
- hwif->udma_four = 1;
if (autodma)
hwif->autodma = 1;
if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) ||
@@ -499,6 +544,7 @@ check_if_enabled:
#ifdef CONFIG_BLK_DEV_HPT34X
IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) ||
#endif /* CONFIG_BLK_DEV_HPT34X */
+ IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) ||
IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) ||
((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) {
unsigned long dma_base = ide_get_or_set_dma_base(hwif, (!mate && d->extra) ? d->extra : 0, d->name);
@@ -534,11 +580,49 @@ bypass_umc_dma:
printk("%s: neither IDE port enabled (BIOS)\n", d->name);
}
+static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d)
+{
+ struct pci_dev *dev2;
+ ide_pci_device_t *d2;
+ unsigned char pin1 = 0, pin2 = 0;
+
+ d2 = d;
+ if (PCI_FUNC(dev->devfn) & 1)
+ return;
+
+ for (dev2=pci_devices; dev2; dev2=dev2->next) {
+ if ((dev2->vendor == dev->vendor) &&
+ (dev2->device == dev->device) &&
+ (PCI_FUNC(dev2->devfn) & 1))
+ break;
+ }
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1);
+ if (dev2) {
+ pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2);
+ hpt363_shared_irq = (pin1 != pin2) ? 1 : 0;
+ }
+
+ if (hpt363_shared_irq) {
+ printk("%s: onboard version of chipset, pin1=%d pin2=%d\n",
+ d->name, pin1, pin2);
+ }
+
+ printk("%s: IDE controller on PCI bus %02x dev %02x\n",
+ d->name, dev->bus->number, dev->devfn);
+ ide_setup_pci_device(dev, d);
+
+ if (dev2 && !hpt363_shared_irq) {
+ printk("%s: IDE controller on PCI bus %02x dev %02x\n",
+ d2->name, dev2->bus->number, dev2->devfn);
+ ide_setup_pci_device(dev2, d2);
+ }
+}
+
/*
* ide_scan_pcibus() gets invoked at boot time from ide.c.
* It finds all PCI IDE controllers and calls ide_setup_pci_device for them.
*/
-__initfunc(void ide_scan_pcibus (void))
+void __init ide_scan_pcibus (void)
{
struct pci_dev *dev;
ide_pci_devid_t devid;
@@ -558,6 +642,8 @@ __initfunc(void ide_scan_pcibus (void))
continue; /* CY82C693 is more than only a IDE controller */
else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) && !(PCI_FUNC(dev->devfn) & 1))
continue; /* UM8886A/BF pair */
+ else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366))
+ hpt366_device_order_fixup(dev, d);
else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
if (IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL))
printk("%s: unknown IDE controller on PCI bus %02x device %02x, VID=%04x, DID=%04x\n",
diff --git a/drivers/block/ide-pmac.c b/drivers/block/ide-pmac.c
index 52c658311..90fbf9cbc 100644
--- a/drivers/block/ide-pmac.c
+++ b/drivers/block/ide-pmac.c
@@ -57,38 +57,47 @@ struct notifier_block idepmac_sleep_notifier = {
#endif /* CONFIG_PMAC_PBOOK */
/*
- * N.B. this can't be an initfunc, because the media-bay task can
+ * N.B. this can't be an __init, because the media-bay task can
* call ide_[un]register at any time.
*/
-void pmac_ide_init_hwif_ports ( hw_regs_t *hw,
- ide_ioreg_t data_port,
- ide_ioreg_t ctrl_port,
- int *irq)
+void pmac_ide_init_hwif_ports(hw_regs_t *hw,
+ ide_ioreg_t data_port, ide_ioreg_t ctrl_port,
+ int *irq)
{
- int i, r;
+ int i, ix;
if (data_port == 0)
return;
+
+ for (ix = 0; ix < MAX_HWIFS; ++ix)
+ if (data_port == pmac_ide_regbase[ix])
+ break;
+
+ if (ix >= MAX_HWIFS) {
+ /* Probably a PCI interface... */
+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i)
+ hw->io_ports[i] = data_port + i - IDE_DATA_OFFSET;
+ /* XXX is this right? */
+ hw->io_ports[IDE_CONTROL_OFFSET] = 0;
+ if (irq != 0)
+ *irq = 0;
+ return;
+ }
+
/* we check only for -EINVAL meaning that we have found a matching
bay but with the wrong device type */
-
- r = check_media_bay_by_base(data_port, MB_CD);
- if (r == -EINVAL)
+ i = check_media_bay_by_base(data_port, MB_CD);
+ if (i == -EINVAL) {
+ hw->io_ports[IDE_DATA_OFFSET] = 0;
return;
-
- for ( i = 0; i < 8 ; ++i )
+ }
+
+ for (i = 0; i < 8; ++i)
hw->io_ports[i] = data_port + i * 0x10;
hw->io_ports[8] = data_port + 0x160;
- if (irq != NULL) {
- *irq = 0;
- for (i = 0; i < MAX_HWIFS; ++i) {
- if (data_port == pmac_ide_regbase[i]) {
- *irq = pmac_ide_irq[i];
- break;
- }
- }
- }
+ if (irq != NULL)
+ *irq = pmac_ide_irq[ix];
}
void pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
@@ -100,15 +109,15 @@ void pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
pio = ide_get_best_pio_mode(drive, pio, 4, &d);
switch (pio) {
case 4:
- out_le32((unsigned *)(IDE_DATA_REG + 0x200), 0x211025);
+ out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), 0x211025);
break;
default:
- out_le32((unsigned *)(IDE_DATA_REG + 0x200), 0x2f8526);
+ out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), 0x2f8526);
break;
}
}
-__initfunc(void pmac_ide_probe(void))
+void __init pmac_ide_probe(void)
{
struct device_node *np;
int i;
@@ -145,14 +154,36 @@ __initfunc(void pmac_ide_probe(void))
*pp = removables;
for (i = 0, np = atas; i < MAX_HWIFS && np != NULL; np = np->next) {
+ struct device_node *tp;
+
+ /*
+ * If this node is not under a mac-io or dbdma node,
+ * leave it to the generic PCI driver.
+ */
+ for (tp = np->parent; tp != 0; tp = tp->parent)
+ if (tp->type && (strcmp(tp->type, "mac-io") == 0
+ || strcmp(tp->type, "dbdma") == 0))
+ break;
+ if (tp == 0)
+ continue;
+
if (np->n_addrs == 0) {
printk(KERN_WARNING "ide: no address for device %s\n",
np->full_name);
continue;
}
- base = (unsigned long) ioremap(np->addrs[0].address, 0x200);
-
+ /*
+ * If this slot is taken (e.g. by ide-pci.c) try the next one.
+ */
+ while (i < MAX_HWIFS
+ && ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0)
+ ++i;
+ if (i >= MAX_HWIFS)
+ break;
+
+ base = (unsigned long) ioremap(np->addrs[0].address, 0x200) - _IO_BASE;
+
/* XXX This is bogus. Should be fixed in the registry by checking
the kind of host interrupt controller, a bit like gatwick
fixes in irq.c
@@ -199,8 +230,8 @@ __initfunc(void pmac_ide_probe(void))
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-__initfunc(static void
-pmac_ide_setup_dma(struct device_node *np, ide_hwif_t *hwif))
+static void __init
+pmac_ide_setup_dma(struct device_node *np, ide_hwif_t *hwif)
{
hwif->dma_base = (unsigned long) ioremap(np->addrs[1].address, 0x200);
diff --git a/drivers/block/ide-probe.c b/drivers/block/ide-probe.c
index 76dc905dd..62008341e 100644
--- a/drivers/block/ide-probe.c
+++ b/drivers/block/ide-probe.c
@@ -20,7 +20,7 @@
* Version 1.04 fixed buggy treatments of known flash memory cards
*
* Version 1.05 fix for (hwif->chipset == ide_pdc4030)
- * added ide6/7
+ * added ide6/7/8/9
* allowed for secondary flash card to be detectable
* with new flag : drive->ata_flash : 1;
*/
@@ -352,56 +352,6 @@ static inline byte probe_for_drive (ide_drive_t *drive)
}
/*
- * We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc
- * controller that is BIOS compatible with ST-506, and thus showing up in our
- * BIOS table, but not register compatible, and therefore not present in CMOS.
- *
- * Furthermore, we will assume that our ST-506 drives <if any> are the primary
- * drives in the system -- the ones reflected as drive 1 or 2. The first
- * drive is stored in the high nibble of CMOS byte 0x12, the second in the low
- * nibble. This will be either a 4 bit drive type or 0xf indicating use byte
- * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. A non-zero value
- * means we have an AT controller hard disk for that drive.
- *
- * Of course, there is no guarantee that either drive is actually on the
- * "primary" IDE interface, but we don't bother trying to sort that out here.
- * If a drive is not actually on the primary interface, then these parameters
- * will be ignored. This results in the user having to supply the logical
- * drive geometry as a boot parameter for each drive not on the primary i/f.
- *
- * The only "perfect" way to handle this would be to modify the setup.[cS] code
- * to do BIOS calls Int13h/Fn08h and Int13h/Fn48h to get all of the drive info
- * for us during initialization. I have the necessary docs -- any takers? -ml
- */
-static void probe_cmos_for_drives (ide_hwif_t *hwif)
-{
-#ifdef __i386__
- extern struct drive_info_struct drive_info;
- byte cmos_disks, *BIOS = (byte *) &drive_info;
- int unit;
-
-#ifdef CONFIG_BLK_DEV_PDC4030
- if (hwif->chipset == ide_pdc4030 && hwif->channel != 0)
- return;
-#endif /* CONFIG_BLK_DEV_PDC4030 */
- outb_p(0x12,0x70); /* specify CMOS address 0x12 */
- cmos_disks = inb_p(0x71); /* read the data from 0x12 */
- /* Extract drive geometry from CMOS+BIOS if not already setup */
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
- if ((cmos_disks & (0xf0 >> (unit*4))) && !drive->present && !drive->nobios) {
- drive->cyl = drive->bios_cyl = *(unsigned short *)BIOS;
- drive->head = drive->bios_head = *(BIOS+2);
- drive->sect = drive->bios_sect = *(BIOS+14);
- drive->ctl = *(BIOS+8);
- drive->present = 1;
- }
- BIOS += 16;
- }
-#endif
-}
-
-/*
* This routine only knows how to look for drive units 0 and 1
* on an interface, so any setting of MAX_DRIVES > 2 won't work here.
*/
@@ -418,8 +368,11 @@ static void probe_hwif (ide_hwif_t *hwif)
if (hwif->noprobe)
return;
- if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA)
+ if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) {
+ extern void probe_cmos_for_drives(ide_hwif_t *hwif);
+
probe_cmos_for_drives (hwif);
+ }
/*
* Calculate the region that this interface occupies,
@@ -763,6 +716,12 @@ static int hwif_init (ide_hwif_t *hwif)
#if MAX_HWIFS > 7
case IDE7_MAJOR: rfn = &do_ide7_request; break;
#endif
+#if MAX_HWIFS > 8
+ case IDE8_MAJOR: rfn = &do_ide8_request; break;
+#endif
+#if MAX_HWIFS > 9
+ case IDE9_MAJOR: rfn = &do_ide9_request; break;
+#endif
default:
printk("%s: request_fn NOT DEFINED\n", hwif->name);
return (hwif->present = 0);
diff --git a/drivers/block/ide-proc.c b/drivers/block/ide-proc.c
index 623ac9268..8afe1568f 100644
--- a/drivers/block/ide-proc.c
+++ b/drivers/block/ide-proc.c
@@ -243,6 +243,7 @@ static int proc_ide_write_config
}
#endif /* CONFIG_BLK_DEV_IDEPCI */
} else { /* not pci */
+#ifndef CONFIG_Q40
switch (digits) {
case 2: outb(val, reg);
break;
@@ -251,6 +252,7 @@ static int proc_ide_write_config
case 8: outl(val, reg);
break;
}
+#endif /* CONFIG_Q40 */
}
}
}
diff --git a/drivers/block/ide-tape.c b/drivers/block/ide-tape.c
index ed278655e..6e8313733 100644
--- a/drivers/block/ide-tape.c
+++ b/drivers/block/ide-tape.c
@@ -3583,8 +3583,9 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
/*
* These two ide-pci host adapters appear to need this disabled.
*/
- if ((hwif->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) ||
- (hwif->pci_dev->device == PCI_DEVICE_ID_TTI_HPT343)) {
+ if (HWIF(drive)->pci_dev != NULL && (
+ (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) ||
+ (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_TTI_HPT343))) {
drive->dsc_overlap = 0;
} else
#endif /* CONFIG_BLK_DEV_IDEPCI */
diff --git a/drivers/block/ide.c b/drivers/block/ide.c
index 9a09e7ec3..74b3f71c6 100644
--- a/drivers/block/ide.c
+++ b/drivers/block/ide.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/ide.c Version 6.19 January 29, 1999
+ * linux/drivers/block/ide.c Version 6.20 July 10, 1999
*
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
*/
@@ -39,7 +39,7 @@
* October, 1994 -- Complete line-by-line overhaul for linux 1.1.x, by:
*
* Mark Lord (mlord@pobox.com) (IDE Perf.Pkg)
- * Delman Lee (delman@mipg.upenn.edu) ("Mr. atdisk2")
+ * Delman Lee (delman@ieee.org) ("Mr. atdisk2")
* Scott Snyder (snyder@fnald0.fnal.gov) (ATAPI IDE cd-rom)
*
* This was a rewrite of just about everything from hd.c, though some original
@@ -93,19 +93,28 @@
* Version 6.17 fix for newest EZ-Drive problem
* Version 6.18 default unpartitioned-disk translation now "BIOS LBA"
* Version 6.19 Re-design for a UNIFORM driver for all platforms,
- * model based on suggestions from Russell King and
- * Geert Uytterhoeven
+ * model based on suggestions from Russell King and
+ * Geert Uytterhoeven
* Promise DC4030VL now supported.
+ * add support for ide6/ide7
* delay_50ms() changed to ide_delay_50ms() and exported.
+ * Version 6.20 Added/Fixed Generic ATA-66 support and hwif detection.
+ * Added hdx=flash to allow for second flash disk
+ * detection w/o the hang loop.
+ * Added support for ide8/ide9
+ * Added idex=ata66 for the quirky chipsets that are
+ * ATA-66 compliant, but have yet to determine a method
+ * of verification of the 80c cable presence.
+ * Specifically Promise's PDC20262 chipset.
*
- * Some additional driver compile-time options are in ide.h
+ * 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.19"
-#define VERSION "Id: ide.c 6.19 1999/01/29"
+#define REVISION "Revision: 6.20"
+#define VERSION "Id: ide.c 6.20 1999/07/10"
#undef REALLY_SLOW_IO /* most systems can safely undef this */
@@ -144,7 +153,11 @@
extern byte fifoconfig; /* defined in via82c586.c used by ide_setup()*/
#endif
-static const byte ide_hwif_to_major[] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR };
+static const byte ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR,
+ IDE2_MAJOR, IDE3_MAJOR,
+ IDE4_MAJOR, IDE5_MAJOR,
+ IDE6_MAJOR, IDE7_MAJOR,
+ IDE8_MAJOR, IDE9_MAJOR };
static int idebus_parameter; /* holds the "idebus=" parameter */
static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */
@@ -421,8 +434,8 @@ void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
{
++bytecount;
-#ifdef CONFIG_ATARI
- if (MACH_IS_ATARI) {
+#if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
+ if (MACH_IS_ATARI || MACH_IS_Q40) {
/* Atari has a byte-swapped IDE interface */
insw_swapw(IDE_DATA_REG, buffer, bytecount / 2);
return;
@@ -436,8 +449,8 @@ void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount
void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
{
++bytecount;
-#ifdef CONFIG_ATARI
- if (MACH_IS_ATARI) {
+#if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
+ if (MACH_IS_ATARI || MACH_IS_Q40) {
/* Atari has a byte-swapped IDE interface */
outsw_swapw(IDE_DATA_REG, buffer, bytecount / 2);
return;
@@ -1187,7 +1200,9 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, unsigned long *hwgroup_flags
return;
}
hwif = HWIF(drive);
- if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif) /* set nIEN for previous hwif */
+ 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;
@@ -1308,6 +1323,20 @@ void do_ide7_request (void)
}
#endif /* MAX_HWIFS > 7 */
+#if MAX_HWIFS > 8
+void do_ide8_request (void)
+{
+ unlock_do_hwgroup_request (ide_hwifs[8].hwgroup);
+}
+#endif /* MAX_HWIFS > 8 */
+
+#if MAX_HWIFS > 9
+void do_ide9_request (void)
+{
+ unlock_do_hwgroup_request (ide_hwifs[9].hwgroup);
+}
+#endif /* MAX_HWIFS > 9 */
+
static void start_next_request (ide_hwgroup_t *hwgroup, int masked_irq)
{
unsigned long flags;
@@ -1347,6 +1376,7 @@ void ide_timer_expiry (unsigned long data)
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 {
@@ -1357,6 +1387,7 @@ void ide_timer_expiry (unsigned long data)
* need something here for HPT34X.......AMH
* irq timeout: status=0x58 { DriveReady SeekComplete DataRequest }
*/
+ (void) hwgroup->hwif->dmaproc(ide_dma_timeout, drive);
}
spin_unlock_irqrestore(&hwgroup->spinlock, flags);
ide_error(drive, "irq timeout", GET_STAT());
@@ -1957,7 +1988,7 @@ int ide_register_hw (hw_regs_t *hw, ide_hwif_t **hwifp)
}
for (index = 0; index < MAX_HWIFS; ++index) {
hwif = &ide_hwifs[index];
- if ((!hwif->present && !initializing) ||
+ if ((!hwif->present && !hwif->mate && !initializing) ||
(!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing))
goto found;
}
@@ -2248,7 +2279,8 @@ int ide_config_drive_speed (ide_drive_t *drive, byte speed)
* this point (lost interrupt).
*/
SELECT_DRIVE(HWIF(drive), drive);
- OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
+ 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);
@@ -2524,7 +2556,7 @@ char *ide_xfer_verbose (byte xfer_rate) {
* stridx() returns the offset of c within s,
* or -1 if c is '\0' or not found within s.
*/
-__initfunc(static int stridx (const char *s, char c))
+static int __init stridx (const char *s, char c)
{
char *i = strchr(s, c);
return (i && c) ? i - s : -1;
@@ -2542,7 +2574,7 @@ __initfunc(static int stridx (const char *s, char c))
* and base16 is allowed when prefixed with "0x".
* 4. otherwise, zero is returned.
*/
-__initfunc(static int match_parm (char *s, const char *keywords[], int vals[], int max_vals))
+static int __init match_parm (char *s, const char *keywords[], int vals[], int max_vals)
{
static const char *decimal = "0123456789";
static const char *hex = "0123456789abcdef";
@@ -2641,6 +2673,10 @@ __initfunc(static int match_parm (char *s, const char *keywords[], int vals[], i
* "idex=four" : four drives on idex and ide(x^1) share same ports
* "idex=reset" : reset interface before first use
* "idex=dma" : enable DMA by default on both drives if possible
+ * "idex=ata66" : informs the interface that it has an 80c cable
+ * for chipsets that are ATA-66 capable, but
+ * the ablity to bit test for detection is
+ * currently unknown.
*
* "splitfifo=betweenChan"
* : FIFO Configuration of VIA 82c586(<nothing>,"A"or"B").
@@ -2668,8 +2704,9 @@ __initfunc(static int match_parm (char *s, const char *keywords[], int vals[], i
* "ide0=ali14xx" : probe/support ali14xx chipsets (ALI M1439, M1443, M1445)
* "ide0=umc8672" : probe/support umc8672 chipsets
* "idex=dc4030" : probe/support Promise DC4030VL interface
+ * "ide=doubler" : probe/support IDE doublers on Amiga
*/
-__initfunc(void ide_setup (char *s))
+void __init ide_setup (char *s)
{
int i, vals[3];
ide_hwif_t *hwif;
@@ -2828,9 +2865,12 @@ __initfunc(void ide_setup (char *s))
if (s[3] >= '0' && s[3] <= max_hwif) {
/*
* Be VERY CAREFUL changing this: note hardcoded indexes below
+ * -8,-9,-10 : are reserved for future idex calls to ease the hardcoding.
*/
- const char *ide_words[] = {"noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "four",
- "qd6580", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL};
+ const char *ide_words[] = {
+ "noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66",
+ "minus8", "minus9", "minus10",
+ "four", "qd6580", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL };
hw = s[3] - '0';
hwif = &ide_hwifs[hw];
i = match_parm(&s[4], ide_words, vals, 3);
@@ -2838,19 +2878,19 @@ __initfunc(void ide_setup (char *s))
/*
* Cryptic check to ensure chipset not already set for hwif:
*/
- if (i > 0 || i <= -7) { /* is parameter a chipset name? */
+ if (i > 0 || i <= -11) { /* is parameter a chipset name? */
if (hwif->chipset != ide_unknown)
goto bad_option; /* chipset already specified */
- if (i <= -7 && i != -14 && hw != 0)
+ if (i <= -11 && i != -18 && hw != 0)
goto bad_hwif; /* chipset drivers are for "ide0=" only */
- if (i <= -7 && i != -14 && ide_hwifs[hw+1].chipset != ide_unknown)
+ if (i <= -11 && i != -18 && ide_hwifs[hw+1].chipset != ide_unknown)
goto bad_option; /* chipset for 2nd port already specified */
printk("\n");
}
switch (i) {
#ifdef CONFIG_BLK_DEV_PDC4030
- case -14: /* "dc4030" */
+ case -18: /* "dc4030" */
{
extern void init_pdc4030(void);
init_pdc4030();
@@ -2858,7 +2898,7 @@ __initfunc(void ide_setup (char *s))
}
#endif /* CONFIG_BLK_DEV_PDC4030 */
#ifdef CONFIG_BLK_DEV_ALI14XX
- case -13: /* "ali14xx" */
+ case -17: /* "ali14xx" */
{
extern void init_ali14xx (void);
init_ali14xx();
@@ -2866,7 +2906,7 @@ __initfunc(void ide_setup (char *s))
}
#endif /* CONFIG_BLK_DEV_ALI14XX */
#ifdef CONFIG_BLK_DEV_UMC8672
- case -12: /* "umc8672" */
+ case -16: /* "umc8672" */
{
extern void init_umc8672 (void);
init_umc8672();
@@ -2874,7 +2914,7 @@ __initfunc(void ide_setup (char *s))
}
#endif /* CONFIG_BLK_DEV_UMC8672 */
#ifdef CONFIG_BLK_DEV_DTC2278
- case -11: /* "dtc2278" */
+ case -15: /* "dtc2278" */
{
extern void init_dtc2278 (void);
init_dtc2278();
@@ -2882,7 +2922,7 @@ __initfunc(void ide_setup (char *s))
}
#endif /* CONFIG_BLK_DEV_DTC2278 */
#ifdef CONFIG_BLK_DEV_CMD640
- case -10: /* "cmd640_vlb" */
+ case -14: /* "cmd640_vlb" */
{
extern int cmd640_vlb; /* flag for cmd640.c */
cmd640_vlb = 1;
@@ -2890,7 +2930,7 @@ __initfunc(void ide_setup (char *s))
}
#endif /* CONFIG_BLK_DEV_CMD640 */
#ifdef CONFIG_BLK_DEV_HT6560B
- case -9: /* "ht6560b" */
+ case -13: /* "ht6560b" */
{
extern void init_ht6560b (void);
init_ht6560b();
@@ -2898,7 +2938,7 @@ __initfunc(void ide_setup (char *s))
}
#endif /* CONFIG_BLK_DEV_HT6560B */
#if CONFIG_BLK_DEV_QD6580
- case -8: /* "qd6580" */
+ case -12: /* "qd6580" */
{
extern void init_qd6580 (void);
init_qd6580();
@@ -2906,7 +2946,7 @@ __initfunc(void ide_setup (char *s))
}
#endif /* CONFIG_BLK_DEV_QD6580 */
#ifdef CONFIG_BLK_DEV_4DRIVES
- case -7: /* "four" drives on one set of ports */
+ case -11: /* "four" drives on one set of ports */
{
ide_hwif_t *mate = &ide_hwifs[hw^1];
mate->drives[0].select.all ^= 0x20;
@@ -2917,6 +2957,18 @@ __initfunc(void ide_setup (char *s))
goto do_serialize;
}
#endif /* CONFIG_BLK_DEV_4DRIVES */
+ case -10: /* minus10 */
+ case -9: /* minus9 */
+ case -8: /* minus8 */
+ goto bad_option;
+ case -7: /* ata66 */
+#ifdef CONFIG_BLK_DEV_IDEPCI
+ hwif->udma_four = 1;
+ goto done;
+#else /* !CONFIG_BLK_DEV_IDEPCI */
+ hwif->udma_four = 0;
+ goto bad_hwif;
+#endif /* CONFIG_BLK_DEV_IDEPCI */
case -6: /* dma */
hwif->autodma = 1;
goto done;
@@ -3080,7 +3132,7 @@ int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg)
/*
* probe_for_hwifs() finds/initializes "known" IDE interfaces
*/
-__initfunc(static void probe_for_hwifs (void))
+static void __init probe_for_hwifs (void)
{
#ifdef CONFIG_PCI
if (pci_present())
@@ -3154,7 +3206,7 @@ __initfunc(static void probe_for_hwifs (void))
#endif /* CONFIG_BLK_DEV_BUDDHA */
}
-__initfunc(void ide_init_builtin_drivers (void))
+void __init ide_init_builtin_drivers (void)
{
/*
* Probe for special PCI and other "known" interface chipsets
@@ -3425,6 +3477,12 @@ EXPORT_SYMBOL(do_ide6_request);
#if MAX_HWIFS > 7
EXPORT_SYMBOL(do_ide7_request);
#endif /* MAX_HWIFS > 7 */
+#if MAX_HWIFS > 8
+EXPORT_SYMBOL(do_ide8_request);
+#endif /* MAX_HWIFS > 8 */
+#if MAX_HWIFS > 9
+EXPORT_SYMBOL(do_ide9_request);
+#endif /* MAX_HWIFS > 9 */
/*
* Driver module
@@ -3469,7 +3527,7 @@ EXPORT_SYMBOL(ide_setup_ports);
/*
* This is gets invoked once during initialization, to set *everything* up
*/
-__initfunc(int ide_init (void))
+int __init ide_init (void)
{
static char banner_printed = 0;
@@ -3491,7 +3549,7 @@ __initfunc(int ide_init (void))
char *options = NULL;
MODULE_PARM(options,"s");
-__initfunc(static void parse_options (char *line))
+static void __init parse_options (char *line)
{
char *next = line;
diff --git a/drivers/block/ide.h b/drivers/block/ide.h
deleted file mode 100644
index 2ca3266ec..000000000
--- a/drivers/block/ide.h
+++ /dev/null
@@ -1,773 +0,0 @@
-#ifndef _IDE_H
-#define _IDE_H
-/*
- * linux/drivers/block/ide.h
- *
- * Copyright (C) 1994-1998 Linus Torvalds & authors
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/hdreg.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <asm/ide.h>
-
-/*
- * This is the multiple IDE interface driver, as evolved from hd.c.
- * It supports up to four IDE interfaces, on one or more IRQs (usually 14 & 15).
- * There can be up to two drives per interface, as per the ATA-2 spec.
- *
- * Primary i/f: ide0: major=3; (hda) minor=0; (hdb) minor=64
- * Secondary i/f: ide1: major=22; (hdc or hd1a) minor=0; (hdd or hd1b) minor=64
- * Tertiary i/f: ide2: major=33; (hde) minor=0; (hdf) minor=64
- * Quaternary i/f: ide3: major=34; (hdg) minor=0; (hdh) minor=64
- */
-
-/******************************************************************************
- * IDE driver configuration options (play with these as desired):
- *
- * REALLY_SLOW_IO can be defined in ide.c and ide-cd.c, if necessary
- */
-#undef REALLY_FAST_IO /* define if ide ports are perfect */
-#define INITIAL_MULT_COUNT 0 /* off=0; on=2,4,8,16,32, etc.. */
-
-#ifndef SUPPORT_SLOW_DATA_PORTS /* 1 to support slow data ports */
-#define SUPPORT_SLOW_DATA_PORTS 1 /* 0 to reduce kernel size */
-#endif
-#ifndef SUPPORT_VLB_SYNC /* 1 to support weird 32-bit chips */
-#define SUPPORT_VLB_SYNC 1 /* 0 to reduce kernel size */
-#endif
-#ifndef DISK_RECOVERY_TIME /* off=0; on=access_delay_time */
-#define DISK_RECOVERY_TIME 0 /* for hardware that needs it */
-#endif
-#ifndef OK_TO_RESET_CONTROLLER /* 1 needed for good error recovery */
-#define OK_TO_RESET_CONTROLLER 1 /* 0 for use with AH2372A/B interface */
-#endif
-#ifndef FAKE_FDISK_FOR_EZDRIVE /* 1 to help linux fdisk with EZDRIVE */
-#define FAKE_FDISK_FOR_EZDRIVE 1 /* 0 to reduce kernel size */
-#endif
-#ifndef FANCY_STATUS_DUMPS /* 1 for human-readable drive errors */
-#define FANCY_STATUS_DUMPS 1 /* 0 to reduce kernel size */
-#endif
-
-#ifdef CONFIG_BLK_DEV_CMD640
-#if 0 /* change to 1 when debugging cmd640 problems */
-void cmd640_dump_regs (void);
-#define CMD640_DUMP_REGS cmd640_dump_regs() /* for debugging cmd640 chipset */
-#endif
-#endif /* CONFIG_BLK_DEV_CMD640 */
-
-/*
- * IDE_DRIVE_CMD is used to implement many features of the hdparm utility
- */
-#define IDE_DRIVE_CMD 99 /* (magic) undef to reduce kernel size*/
-
-/*
- * "No user-serviceable parts" beyond this point :)
- *****************************************************************************/
-
-typedef unsigned char byte; /* used everywhere */
-
-/*
- * Probably not wise to fiddle with these
- */
-#define ERROR_MAX 8 /* Max read/write errors per sector */
-#define ERROR_RESET 3 /* Reset controller every 4th retry */
-#define ERROR_RECAL 1 /* Recalibrate every 2nd retry */
-
-/*
- * Ensure that various configuration flags have compatible settings
- */
-#ifdef REALLY_SLOW_IO
-#undef REALLY_FAST_IO
-#endif
-
-#define HWIF(drive) ((ide_hwif_t *)((drive)->hwif))
-#define HWGROUP(drive) ((ide_hwgroup_t *)(HWIF(drive)->hwgroup))
-
-/*
- * Definitions for accessing IDE controller registers
- */
-#define IDE_NR_PORTS (10)
-
-#define IDE_DATA_OFFSET (0)
-#define IDE_ERROR_OFFSET (1)
-#define IDE_NSECTOR_OFFSET (2)
-#define IDE_SECTOR_OFFSET (3)
-#define IDE_LCYL_OFFSET (4)
-#define IDE_HCYL_OFFSET (5)
-#define IDE_SELECT_OFFSET (6)
-#define IDE_STATUS_OFFSET (7)
-#define IDE_CONTROL_OFFSET (8)
-#define IDE_IRQ_OFFSET (9)
-
-#define IDE_FEATURE_OFFSET IDE_ERROR_OFFSET
-#define IDE_COMMAND_OFFSET IDE_STATUS_OFFSET
-
-#define IDE_DATA_REG (HWIF(drive)->io_ports[IDE_DATA_OFFSET])
-#define IDE_ERROR_REG (HWIF(drive)->io_ports[IDE_ERROR_OFFSET])
-#define IDE_NSECTOR_REG (HWIF(drive)->io_ports[IDE_NSECTOR_OFFSET])
-#define IDE_SECTOR_REG (HWIF(drive)->io_ports[IDE_SECTOR_OFFSET])
-#define IDE_LCYL_REG (HWIF(drive)->io_ports[IDE_LCYL_OFFSET])
-#define IDE_HCYL_REG (HWIF(drive)->io_ports[IDE_HCYL_OFFSET])
-#define IDE_SELECT_REG (HWIF(drive)->io_ports[IDE_SELECT_OFFSET])
-#define IDE_STATUS_REG (HWIF(drive)->io_ports[IDE_STATUS_OFFSET])
-#define IDE_CONTROL_REG (HWIF(drive)->io_ports[IDE_CONTROL_OFFSET])
-#define IDE_IRQ_REG (HWIF(drive)->io_ports[IDE_IRQ_OFFSET])
-
-#define IDE_FEATURE_REG IDE_ERROR_REG
-#define IDE_COMMAND_REG IDE_STATUS_REG
-#define IDE_ALTSTATUS_REG IDE_CONTROL_REG
-#define IDE_IREASON_REG IDE_NSECTOR_REG
-#define IDE_BCOUNTL_REG IDE_LCYL_REG
-#define IDE_BCOUNTH_REG IDE_HCYL_REG
-
-#ifdef REALLY_FAST_IO
-#define OUT_BYTE(b,p) outb((b),(p))
-#define IN_BYTE(p) (byte)inb(p)
-#else
-#define OUT_BYTE(b,p) outb_p((b),(p))
-#define IN_BYTE(p) (byte)inb_p(p)
-#endif /* REALLY_FAST_IO */
-
-#define GET_ERR() IN_BYTE(IDE_ERROR_REG)
-#define GET_STAT() IN_BYTE(IDE_STATUS_REG)
-#define OK_STAT(stat,good,bad) (((stat)&((good)|(bad)))==(good))
-#define BAD_R_STAT (BUSY_STAT | ERR_STAT)
-#define BAD_W_STAT (BAD_R_STAT | WRERR_STAT)
-#define BAD_STAT (BAD_R_STAT | DRQ_STAT)
-#define DRIVE_READY (READY_STAT | SEEK_STAT)
-#define DATA_READY (DRQ_STAT)
-
-/*
- * Some more useful definitions
- */
-#define IDE_MAJOR_NAME "ide" /* the same for all i/f; see also genhd.c */
-#define MAJOR_NAME IDE_MAJOR_NAME
-#define PARTN_BITS 6 /* number of minor dev bits for partitions */
-#define PARTN_MASK ((1<<PARTN_BITS)-1) /* a useful bit mask */
-#define MAX_DRIVES 2 /* per interface; 2 assumed by lots of code */
-#define SECTOR_WORDS (512 / 4) /* number of 32bit words per sector */
-#define IDE_LARGE_SEEK(b1,b2,t) (((b1) > (b2) + (t)) || ((b2) > (b1) + (t)))
-#define IDE_MIN(a,b) ((a)<(b) ? (a):(b))
-#define IDE_MAX(a,b) ((a)>(b) ? (a):(b))
-
-/*
- * Timeouts for various operations:
- */
-#define WAIT_DRQ (5*HZ/100) /* 50msec - spec allows up to 20ms */
-#ifdef CONFIG_APM
-#define WAIT_READY (5*HZ) /* 5sec - some laptops are very slow */
-#else
-#define WAIT_READY (3*HZ/100) /* 30msec - should be instantaneous */
-#endif /* CONFIG_APM */
-#define WAIT_PIDENTIFY (10*HZ) /* 10sec - should be less than 3ms (?)
- if all ATAPI CD is closed at boot */
-#define WAIT_WORSTCASE (30*HZ) /* 30sec - worst case when spinning up */
-#define WAIT_CMD (10*HZ) /* 10sec - maximum wait for an IRQ to happen */
-#define WAIT_MIN_SLEEP (2*HZ/100) /* 20msec - minimum sleep time */
-
-#define SELECT_DRIVE(hwif,drive) \
-{ \
- if (hwif->selectproc) \
- hwif->selectproc(drive); \
- OUT_BYTE((drive)->select.all, hwif->io_ports[IDE_SELECT_OFFSET]); \
-}
-
-/*
- * Now for the data we need to maintain per-drive: ide_drive_t
- */
-
-#define ide_scsi 0x21
-#define ide_disk 0x20
-#define ide_optical 0x7
-#define ide_cdrom 0x5
-#define ide_tape 0x1
-#define ide_floppy 0x0
-
-typedef union {
- unsigned all : 8; /* all of the bits together */
- struct {
- unsigned set_geometry : 1; /* respecify drive geometry */
- unsigned recalibrate : 1; /* seek to cyl 0 */
- unsigned set_multmode : 1; /* set multmode count */
- unsigned set_tune : 1; /* tune interface for drive */
- unsigned reserved : 4; /* unused */
- } b;
- } special_t;
-
-typedef struct ide_drive_s {
- struct request *queue; /* request queue */
- struct ide_drive_s *next; /* circular list of hwgroup drives */
- unsigned long sleep; /* sleep until this time */
- unsigned long service_start; /* time we started last request */
- unsigned long service_time; /* service time of last request */
- special_t special; /* special action flags */
- byte keep_settings; /* restore settings after drive reset */
- byte using_dma; /* disk is using dma for read/write */
- byte waiting_for_dma; /* dma currently in progress */
- byte unmask; /* flag: okay to unmask other irqs */
- byte slow; /* flag: slow data port */
- byte bswap; /* flag: byte swap data */
- byte dsc_overlap; /* flag: DSC overlap */
- byte nice1; /* flag: give potential excess bandwidth */
- unsigned present : 1; /* drive is physically present */
- unsigned noprobe : 1; /* from: hdx=noprobe */
- unsigned busy : 1; /* currently doing revalidate_disk() */
- unsigned removable : 1; /* 1 if need to do check_media_change */
- unsigned forced_geom : 1; /* 1 if hdx=c,h,s was given at boot */
- unsigned no_unmask : 1; /* disallow setting unmask bit */
- unsigned no_io_32bit : 1; /* disallow enabling 32bit I/O */
- unsigned nobios : 1; /* flag: do not probe bios for drive */
- unsigned revalidate : 1; /* request revalidation */
- unsigned atapi_overlap : 1; /* flag: ATAPI overlap (not supported) */
- unsigned nice0 : 1; /* flag: give obvious excess bandwidth */
- unsigned nice2 : 1; /* flag: give a share in our own bandwidth */
- unsigned doorlocking : 1; /* flag: for removable only: door lock/unlock works */
- unsigned autotune : 2; /* 1=autotune, 2=noautotune, 0=default */
-#if FAKE_FDISK_FOR_EZDRIVE
- unsigned remap_0_to_1 : 1; /* flag: partitioned with ezdrive */
-#endif /* FAKE_FDISK_FOR_EZDRIVE */
- byte media; /* disk, cdrom, tape, floppy, ... */
- select_t select; /* basic drive/head select reg value */
- byte ctl; /* "normal" value for IDE_CONTROL_REG */
- byte ready_stat; /* min status value for drive ready */
- byte mult_count; /* current multiple sector setting */
- byte mult_req; /* requested multiple sector setting */
- byte tune_req; /* requested drive tuning setting */
- byte io_32bit; /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */
- byte bad_wstat; /* used for ignoring WRERR_STAT */
- byte nowerr; /* used for ignoring WRERR_STAT */
- byte sect0; /* offset of first sector for DM6:DDO */
- byte usage; /* current "open()" count for drive */
- byte head; /* "real" number of heads */
- byte sect; /* "real" sectors per track */
- /*
- * HACK: enforce alignment for sake of IDE CDROM driver on
- * architectures with strict alignment rules.
- */
- byte bios_head __attribute__ ((aligned (8))); /* BIOS/fdisk/LILO number of heads */
- byte bios_sect __attribute__ ((aligned (8))); /* BIOS/fdisk/LILO sectors per track */
- unsigned short bios_cyl; /* BIOS/fdisk/LILO number of cyls */
- unsigned short cyl; /* "real" number of cyls */
- unsigned int drive_data; /* for use by tuneproc/selectproc as needed */
- void *hwif; /* actually (ide_hwif_t *) */
- struct wait_queue *wqueue; /* used to wait for drive in open() */
- struct hd_driveid *id; /* drive model identification info */
- struct hd_struct *part; /* drive partition table */
- char name[4]; /* drive name, such as "hda" */
- void *driver; /* (ide_driver_t *) */
- void *driver_data; /* extra driver data */
- struct proc_dir_entry *proc; /* /proc/ide/ directory entry */
- void *settings; /* /proc/ide/ drive settings */
- char driver_req[10]; /* requests specific driver */
- } ide_drive_t;
-
-/*
- * An ide_dmaproc_t() initiates/aborts DMA read/write operations on a drive.
- *
- * The caller is assumed to have selected the drive and programmed the drive's
- * sector address using CHS or LBA. All that remains is to prepare for DMA
- * and then issue the actual read/write DMA/PIO command to the drive.
- *
- * Returns 0 if all went well.
- * Returns 1 if DMA read/write could not be started, in which case the caller
- * should either try again later, or revert to PIO for the current request.
- */
-typedef enum { ide_dma_read, ide_dma_write, ide_dma_begin, ide_dma_end,
- ide_dma_check, ide_dma_on, ide_dma_off, ide_dma_off_quietly,
- ide_dma_test_irq
- } ide_dma_action_t;
-
-typedef int (ide_dmaproc_t)(ide_dma_action_t, ide_drive_t *);
-
-
-/*
- * An ide_tuneproc_t() is used to set the speed of an IDE interface
- * to a particular PIO mode. The "byte" parameter is used
- * to select the PIO mode by number (0,1,2,3,4,5), and a value of 255
- * indicates that the interface driver should "auto-tune" the PIO mode
- * according to the drive capabilities in drive->id;
- *
- * Not all interface types support tuning, and not all of those
- * support all possible PIO settings. They may silently ignore
- * or round values as they see fit.
- */
-typedef void (ide_tuneproc_t)(ide_drive_t *, byte);
-
-/*
- * This is used to provide support for strange interfaces
- */
-typedef void (ide_selectproc_t) (ide_drive_t *);
-
-/*
- * hwif_chipset_t is used to keep track of the specific hardware
- * chipset used by each IDE interface, if known.
- */
-typedef enum { ide_unknown, ide_generic, ide_pci,
- ide_cmd640, ide_dtc2278, ide_ali14xx,
- ide_qd6580, ide_umc8672, ide_ht6560b,
- ide_pdc4030, ide_rz1000, ide_trm290,
- ide_cmd646, ide_4drives
- } hwif_chipset_t;
-
-typedef struct ide_pci_devid_s {
- unsigned short vid;
- unsigned short did;
-} ide_pci_devid_t;
-
-#define IDE_PCI_DEVID_NULL ((ide_pci_devid_t){0,0})
-#define IDE_PCI_DEVID_EQ(a,b) (a.vid == b.vid && a.did == b.did)
-
-typedef struct hwif_s {
- struct hwif_s *next; /* for linked-list in ide_hwgroup_t */
- void *hwgroup; /* actually (ide_hwgroup_t *) */
- ide_ioreg_t io_ports[IDE_NR_PORTS]; /* task file registers */
- ide_drive_t drives[MAX_DRIVES]; /* drive info */
- struct gendisk *gd; /* gendisk structure */
- ide_tuneproc_t *tuneproc; /* routine to tune PIO mode for drives */
- ide_selectproc_t *selectproc; /* tweaks hardware to select drive */
- ide_dmaproc_t *dmaproc; /* dma read/write/abort routine */
- unsigned long *dmatable; /* dma physical region descriptor table */
- struct hwif_s *mate; /* other hwif from same PCI chip */
- unsigned long dma_base; /* base addr for dma ports */
- unsigned dma_extra; /* extra addr for dma ports */
- unsigned long config_data; /* for use by chipset-specific code */
- unsigned long select_data; /* for use by chipset-specific code */
- struct proc_dir_entry *proc; /* /proc/ide/ directory entry */
- int irq; /* our irq number */
- byte major; /* our major number */
- char name[6]; /* name of interface, eg. "ide0" */
- byte index; /* 0 for ide0; 1 for ide1; ... */
- hwif_chipset_t chipset; /* sub-module for tuning.. */
- unsigned noprobe : 1; /* don't probe for this interface */
- unsigned present : 1; /* this interface exists */
- unsigned serialized : 1; /* serialized operation with mate hwif */
- unsigned sharing_irq: 1; /* 1 = sharing irq with another hwif */
- unsigned reset : 1; /* reset after probe */
- unsigned autodma : 1; /* automatically try to enable DMA at boot */
- byte channel; /* for dual-port chips: 0=primary, 1=secondary */
- struct pci_dev *pci_dev; /* for pci chipsets */
- ide_pci_devid_t pci_devid; /* for pci chipsets: {VID,DID} */
-#if (DISK_RECOVERY_TIME > 0)
- unsigned long last_time; /* time when previous rq was done */
-#endif
- } ide_hwif_t;
-
-/*
- * internal ide interrupt handler type
- */
-typedef void (ide_handler_t)(ide_drive_t *);
-
-typedef struct hwgroup_s {
- spinlock_t spinlock; /* protects "busy" and "handler" */
- ide_handler_t *handler;/* irq handler, if active */
- int busy; /* BOOL: protects all fields below */
- ide_drive_t *drive; /* current drive */
- ide_hwif_t *hwif; /* ptr to current hwif in linked-list */
- struct request *rq; /* current request */
- struct timer_list timer; /* failsafe timer */
- struct request wrq; /* local copy of current write rq */
- unsigned long poll_timeout; /* timeout value during long polls */
- } ide_hwgroup_t;
-
-/*
- * configurable drive settings
- */
-
-#define TYPE_INT 0
-#define TYPE_INTA 1
-#define TYPE_BYTE 2
-#define TYPE_SHORT 3
-
-#define SETTING_READ (1 << 0)
-#define SETTING_WRITE (1 << 1)
-#define SETTING_RW (SETTING_READ | SETTING_WRITE)
-
-typedef int (ide_procset_t)(ide_drive_t *, int);
-typedef struct ide_settings_s {
- 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;
- int auto_remove;
- struct ide_settings_s *next;
-} ide_settings_t;
-
-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_remove_setting(ide_drive_t *drive, char *name);
-ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name);
-int ide_read_setting(ide_drive_t *t, ide_settings_t *setting);
-int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val);
-void ide_add_generic_settings(ide_drive_t *drive);
-
-/*
- * /proc/ide interface
- */
-typedef struct {
- const char *name;
- mode_t mode;
- read_proc_t *read_proc;
- write_proc_t *write_proc;
-} ide_proc_entry_t;
-
-#ifdef CONFIG_PROC_FS
-void proc_ide_create(void);
-void proc_ide_destroy(void);
-void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data);
-void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p);
-read_proc_t proc_ide_read_capacity;
-read_proc_t proc_ide_read_geometry;
-
-/*
- * Standard exit stuff:
- */
-#define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) \
-{ \
- len -= off; \
- if (len < count) { \
- *eof = 1; \
- if (len <= 0) \
- return 0; \
- } else \
- len = count; \
- *start = page + off; \
- return len; \
-}
-#else
-#define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0;
-#endif
-
-/*
- * Subdrivers support.
- */
-#define IDE_SUBDRIVER_VERSION 1
-
-typedef int (ide_cleanup_proc)(ide_drive_t *);
-typedef void (ide_do_request_proc)(ide_drive_t *, struct request *, unsigned long);
-typedef void (ide_end_request_proc)(byte, ide_hwgroup_t *);
-typedef int (ide_ioctl_proc)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long);
-typedef int (ide_open_proc)(struct inode *, struct file *, ide_drive_t *);
-typedef void (ide_release_proc)(struct inode *, struct file *, ide_drive_t *);
-typedef int (ide_check_media_change_proc)(ide_drive_t *);
-typedef void (ide_pre_reset_proc)(ide_drive_t *);
-typedef unsigned long (ide_capacity_proc)(ide_drive_t *);
-typedef void (ide_special_proc)(ide_drive_t *);
-typedef void (ide_setting_proc)(ide_drive_t *);
-
-typedef struct ide_driver_s {
- const char *name;
- const char *version;
- byte media;
- unsigned busy : 1;
- unsigned supports_dma : 1;
- unsigned supports_dsc_overlap : 1;
- ide_cleanup_proc *cleanup;
- ide_do_request_proc *do_request;
- ide_end_request_proc *end_request;
- ide_ioctl_proc *ioctl;
- ide_open_proc *open;
- ide_release_proc *release;
- ide_check_media_change_proc *media_change;
- ide_pre_reset_proc *pre_reset;
- ide_capacity_proc *capacity;
- ide_special_proc *special;
- ide_proc_entry_t *proc;
- } ide_driver_t;
-
-#define DRIVER(drive) ((ide_driver_t *)((drive)->driver))
-
-/*
- * IDE modules.
- */
-#define IDE_CHIPSET_MODULE 0 /* not supported yet */
-#define IDE_PROBE_MODULE 1
-#define IDE_DRIVER_MODULE 2
-
-typedef int (ide_module_init_proc)(void);
-
-typedef struct ide_module_s {
- int type;
- ide_module_init_proc *init;
- void *info;
- struct ide_module_s *next;
-} ide_module_t;
-
-/*
- * ide_hwifs[] is the master data structure used to keep track
- * of just about everything in ide.c. Whenever possible, routines
- * should be using pointers to a drive (ide_drive_t *) or
- * pointers to a hwif (ide_hwif_t *), rather than indexing this
- * structure directly (the allocation/layout may change!).
- *
- */
-#ifndef _IDE_C
-extern ide_hwif_t ide_hwifs[]; /* master data repository */
-extern ide_module_t *ide_modules;
-#endif
-
-/*
- * We need blk.h, but we replace its end_request by our own version.
- */
-#define IDE_DRIVER /* Toggle some magic bits in blk.h */
-#define LOCAL_END_REQUEST /* Don't generate end_request in blk.h */
-#include <linux/blk.h>
-
-void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup);
-
-/*
- * This is used for (nearly) all data transfers from/to the IDE interface
- */
-void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
-void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
-
-/*
- * This is used for (nearly) all ATAPI data transfers from/to the IDE interface
- */
-void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount);
-void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount);
-
-/*
- * This is used on exit from the driver, to designate the next irq handler
- * and also to start the safety timer.
- */
-void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout);
-
-/*
- * Error reporting, in human readable form (luxurious, but a memory hog).
- */
-byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat);
-
-/*
- * ide_error() takes action based on the error returned by the controller.
- * The calling function must return afterwards, to restart the request.
- */
-void ide_error (ide_drive_t *drive, const char *msg, byte stat);
-
-/*
- * 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);
-
-/*
- * ide_fixstring() cleans up and (optionally) byte-swaps a text string,
- * removing leading/trailing blanks and compressing internal blanks.
- * It is primarily used to tidy up the model name/number fields as
- * returned by the WIN_[P]IDENTIFY commands.
- */
-void ide_fixstring (byte *s, const int bytecount, const int byteswap);
-
-/*
- * This routine busy-waits for the drive status to be not "busy".
- * It then checks the status for all of the "good" bits and none
- * of the "bad" bits, and if all is okay it returns 0. All other
- * cases return 1 after invoking ide_error() -- caller should return.
- *
- */
-int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeout);
-
-/*
- * This routine is called from the partition-table code in genhd.c
- * to "convert" a drive to a logical geometry with fewer than 1024 cyls.
- *
- * The second parameter, "xparm", determines exactly how the translation
- * will be handled:
- * 0 = convert to CHS with fewer than 1024 cyls
- * using the same method as Ontrack DiskManager.
- * 1 = same as "0", plus offset everything by 63 sectors.
- * -1 = similar to "0", plus redirect sector 0 to sector 1.
- * >1 = convert to a CHS geometry with "xparm" heads.
- *
- * Returns 0 if the translation was not possible, if the device was not
- * an IDE disk drive, or if a geometry was "forced" on the commandline.
- * Returns 1 if the geometry translation was successful.
- */
-int ide_xlate_1024 (kdev_t, int, const char *);
-
-/*
- * Start a reset operation for an IDE interface.
- * The caller should return immediately after invoking this.
- */
-void ide_do_reset (ide_drive_t *);
-
-/*
- * This function is intended to be used prior to invoking ide_do_drive_cmd().
- */
-void ide_init_drive_cmd (struct request *rq);
-
-/*
- * "action" parameter type for ide_do_drive_cmd() below.
- */
-typedef enum
- {ide_wait, /* insert rq at end of list, and wait for it */
- ide_next, /* insert rq immediately after current request */
- ide_preempt, /* insert rq in front of current request */
- ide_end} /* insert rq at end of list, but don't wait for it */
- ide_action_t;
-
-/*
- * This function issues a special IDE device request
- * onto the request queue.
- *
- * If action is ide_wait, then the rq is queued at the end of the
- * request queue, and the function sleeps until it has been processed.
- * This is for use when invoked from an ioctl handler.
- *
- * If action is ide_preempt, then the rq is queued at the head of
- * the request queue, displacing the currently-being-processed
- * request and this function returns immediately without waiting
- * for the new rq to be completed. This is VERY DANGEROUS, and is
- * intended for careful use by the ATAPI tape/cdrom driver code.
- *
- * If action is ide_next, then the rq is queued immediately after
- * the currently-being-processed-request (if any), and the function
- * returns without waiting for the new rq to be completed. As above,
- * This is VERY DANGEROUS, and is intended for careful use by the
- * ATAPI tape/cdrom driver code.
- *
- * If action is ide_end, then the rq is queued at the end of the
- * request queue, and the function returns immediately without waiting
- * for the new rq to be completed. This is again intended for careful
- * use by the ATAPI tape/cdrom driver code.
- */
-int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action);
-
-/*
- * Clean up after success/failure of an explicit drive cmd.
- * stat/err are used only when (HWGROUP(drive)->rq->cmd == IDE_DRIVE_CMD).
- */
-void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err);
-
-/*
- * Issue ATA command and wait for completion.
- */
-int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf);
-
-/*
- * ide_system_bus_speed() returns what we think is the system VESA/PCI
- * bus speed (in MHz). This is used for calculating interface PIO timings.
- * The default is 40 for known PCI systems, 50 otherwise.
- * The "idebus=xx" parameter can be used to override this value.
- */
-int ide_system_bus_speed (void);
-
-/*
- * ide_multwrite() transfers a block of up to mcount sectors of data
- * to a drive as part of a disk multwrite operation.
- */
-void ide_multwrite (ide_drive_t *drive, unsigned int mcount);
-
-/*
- * ide_stall_queue() can be used by a drive to give excess bandwidth back
- * to the hwgroup by sleeping for timeout jiffies.
- */
-void ide_stall_queue (ide_drive_t *drive, unsigned long timeout);
-
-/*
- * ide_get_queue() returns the queue which corresponds to a given device.
- */
-struct request **ide_get_queue (kdev_t dev);
-
-/*
- * CompactFlash cards and their brethern pretend to be removable hard disks,
- * but they never have a slave unit, and they don't have doorlock mechanisms.
- * This test catches them, and is invoked elsewhere when setting appropriate config bits.
- */
-int drive_is_flashcard (ide_drive_t *drive);
-
-int ide_spin_wait_hwgroup(ide_drive_t *drive, unsigned long *flags);
-void ide_timer_expiry (unsigned long data);
-void ide_intr (int irq, void *dev_id, struct pt_regs *regs);
-void ide_geninit (struct gendisk *gd);
-void do_ide0_request (void);
-#if MAX_HWIFS > 1
-void do_ide1_request (void);
-#endif
-#if MAX_HWIFS > 2
-void do_ide2_request (void);
-#endif
-#if MAX_HWIFS > 3
-void do_ide3_request (void);
-#endif
-#if MAX_HWIFS > 4
-void do_ide4_request (void);
-#endif
-#if MAX_HWIFS > 5
-void do_ide5_request (void);
-#endif
-void ide_init_subdrivers (void);
-
-#ifndef _IDE_C
-extern struct file_operations ide_fops[];
-#endif
-
-#ifdef _IDE_C
-#ifdef CONFIG_BLK_DEV_IDE
-int ideprobe_init (void);
-#endif /* CONFIG_BLK_DEV_IDE */
-#ifdef CONFIG_BLK_DEV_IDEDISK
-int idedisk_init (void);
-#endif /* CONFIG_BLK_DEV_IDEDISK */
-#ifdef CONFIG_BLK_DEV_IDECD
-int ide_cdrom_init (void);
-#endif /* CONFIG_BLK_DEV_IDECD */
-#ifdef CONFIG_BLK_DEV_IDETAPE
-int idetape_init (void);
-#endif /* CONFIG_BLK_DEV_IDETAPE */
-#ifdef CONFIG_BLK_DEV_IDEFLOPPY
-int idefloppy_init (void);
-#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
-#ifdef CONFIG_BLK_DEV_IDESCSI
-int idescsi_init (void);
-#endif /* CONFIG_BLK_DEV_IDESCSI */
-#endif /* _IDE_C */
-
-int ide_register_module (ide_module_t *module);
-void ide_unregister_module (ide_module_t *module);
-ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *driver, int n);
-int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version);
-int ide_unregister_subdriver (ide_drive_t *drive);
-int ide_replace_subdriver(ide_drive_t *drive, const char *driver);
-
-#ifdef CONFIG_BLK_DEV_IDEPCI
-#define ON_BOARD 1
-#define NEVER_BOARD 0
-#ifdef CONFIG_BLK_DEV_OFFBOARD
-# define OFF_BOARD ON_BOARD
-#else /* CONFIG_BLK_DEV_OFFBOARD */
-# define OFF_BOARD NEVER_BOARD
-#endif /* CONFIG_BLK_DEV_OFFBOARD */
-
-unsigned long ide_find_free_region (unsigned short size) __init;
-void ide_scan_pcibus (void) __init;
-#endif
-#ifdef CONFIG_BLK_DEV_IDEDMA
-#define BAD_DMA_DRIVE 0
-#define GOOD_DMA_DRIVE 1
-int ide_build_dmatable (ide_drive_t *drive);
-void ide_dma_intr (ide_drive_t *drive);
-int check_drive_lists (ide_drive_t *drive, int good_bad);
-int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive);
-int ide_release_dma (ide_hwif_t *hwif);
-void ide_setup_dma (ide_hwif_t *hwif, unsigned long dmabase, unsigned int num_ports) __init;
-unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) __init;
-#endif
-
-#ifdef CONFIG_BLK_DEV_PDC4030
-#include "pdc4030.h"
-#define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030)
-#else
-#define IS_PDC4030_DRIVE (0) /* auto-NULLs out pdc4030 code */
-#endif /* CONFIG_BLK_DEV_PDC4030 */
-
-#endif /* _IDE_H */
diff --git a/drivers/block/linear.c b/drivers/block/linear.c
index b6f72fd6a..3993417d0 100644
--- a/drivers/block/linear.c
+++ b/drivers/block/linear.c
@@ -184,7 +184,7 @@ static struct md_personality linear_personality=
#ifndef MODULE
-__initfunc(void linear_init (void))
+void __init linear_init (void)
{
register_md_personality (LINEAR, &linear_personality);
}
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index c4824b9b2..bc7ef4803 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -26,6 +26,14 @@
#include <linux/module.h>
/*
+ * MAC Floppy IWM hooks
+ */
+
+#ifdef CONFIG_MAC_FLOPPY_IWM
+extern int mac_floppy_init(void);
+#endif
+
+/*
* The request-struct contains all necessary data
* to load a nr of sectors into memory
*/
@@ -109,6 +117,11 @@ int * max_readahead[MAX_BLKDEV] = { NULL, NULL, };
*/
int * max_sectors[MAX_BLKDEV] = { NULL, NULL, };
+/*
+ * Max number of segments per request
+ */
+int * max_segments[MAX_BLKDEV] = { NULL, NULL, };
+
static inline int get_max_sectors(kdev_t dev)
{
if (!max_sectors[MAJOR(dev)])
@@ -116,6 +129,13 @@ static inline int get_max_sectors(kdev_t dev)
return max_sectors[MAJOR(dev)][MINOR(dev)];
}
+static inline int get_max_segments(kdev_t dev)
+{
+ if (!max_segments[MAJOR(dev)])
+ return MAX_SEGMENTS;
+ return max_segments[MAJOR(dev)][MINOR(dev)];
+}
+
/*
* Is called with the request spinlock aquired.
* NOTE: the device-specific queue() functions
@@ -286,30 +306,37 @@ static inline void drive_stat_acct(int cmd, unsigned long nr_sectors,
* with the request-lists in peace. Thus it should be called with no spinlocks
* held.
*
- * By this point, req->cmd is always either READ/WRITE, never READA/WRITEA,
+ * By this point, req->cmd is always either READ/WRITE, never READA,
* which is important for drive_stat_acct() above.
*/
void add_request(struct blk_dev_struct * dev, struct request * req)
{
+ int major = MAJOR(req->rq_dev);
+ int minor = MINOR(req->rq_dev);
struct request * tmp, **current_request;
short disk_index;
unsigned long flags;
int queue_new_request = 0;
- switch (MAJOR(req->rq_dev)) {
+ switch (major) {
+ case DAC960_MAJOR+0:
+ disk_index = (minor & 0x00f8) >> 3;
+ if (disk_index < 4)
+ drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
+ break;
case SCSI_DISK0_MAJOR:
- disk_index = (MINOR(req->rq_dev) & 0x00f0) >> 4;
+ disk_index = (minor & 0x00f0) >> 4;
if (disk_index < 4)
drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
break;
case IDE0_MAJOR: /* same as HD_MAJOR */
case XT_DISK_MAJOR:
- disk_index = (MINOR(req->rq_dev) & 0x0040) >> 6;
+ disk_index = (minor & 0x0040) >> 6;
drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
break;
case IDE1_MAJOR:
- disk_index = ((MINOR(req->rq_dev) & 0x0040) >> 6) + 2;
+ disk_index = ((minor & 0x0040) >> 6) + 2;
drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
default:
break;
@@ -345,10 +372,12 @@ void add_request(struct blk_dev_struct * dev, struct request * req)
tmp->next = req;
/* for SCSI devices, call request_fn unconditionally */
- if (scsi_blk_major(MAJOR(req->rq_dev)))
+ if (scsi_blk_major(major))
+ queue_new_request = 1;
+ if (major >= COMPAQ_SMART2_MAJOR+0 &&
+ major <= COMPAQ_SMART2_MAJOR+7)
queue_new_request = 1;
- if (MAJOR(req->rq_dev) >= COMPAQ_SMART2_MAJOR+0 &&
- MAJOR(req->rq_dev) <= COMPAQ_SMART2_MAJOR+7)
+ if (major >= DAC960_MAJOR+0 && major <= DAC960_MAJOR+7)
queue_new_request = 1;
out:
if (queue_new_request)
@@ -403,7 +432,7 @@ void make_request(int major,int rw, struct buffer_head * bh)
unsigned long maxsector = (blk_size[major][MINOR(bh->b_rdev)] << 1) + 1;
if (maxsector < count || maxsector - count < sector) {
- bh->b_state &= (1 << BH_Lock);
+ bh->b_state &= (1 << BH_Lock) | (1 << BH_Mapped);
/* This may well happen - the kernel calls bread()
without checking the size of the device, e.g.,
when mounting a device. */
@@ -417,7 +446,7 @@ void make_request(int major,int rw, struct buffer_head * bh)
}
}
- rw_ahead = 0; /* normal case; gets changed below for READA/WRITEA */
+ rw_ahead = 0; /* normal case; gets changed below for READA */
switch (rw) {
case READA:
rw_ahead = 1;
@@ -428,13 +457,14 @@ void make_request(int major,int rw, struct buffer_head * bh)
kstat.pgpgin++;
max_req = NR_REQUEST; /* reads take precedence */
break;
- case WRITEA:
- rw_ahead = 1;
- rw = WRITE; /* drop into WRITE */
+ case WRITERAW:
+ rw = WRITE;
+ goto do_write; /* Skip the buffer refile */
case WRITE:
if (!test_and_clear_bit(BH_Dirty, &bh->b_state))
goto end_io; /* Hmmph! Nothing to write */
refile_buffer(bh);
+ do_write:
/*
* We don't allow the write-requests to fill up the
* queue completely: we want some room for reads,
@@ -482,6 +512,8 @@ void make_request(int major,int rw, struct buffer_head * bh)
case IDE5_MAJOR:
case IDE6_MAJOR:
case IDE7_MAJOR:
+ case IDE8_MAJOR:
+ case IDE9_MAJOR:
case ACSI_MAJOR:
case MFM_ACORN_MAJOR:
/*
@@ -508,6 +540,14 @@ void make_request(int major,int rw, struct buffer_head * bh)
case SCSI_DISK6_MAJOR:
case SCSI_DISK7_MAJOR:
case SCSI_CDROM_MAJOR:
+ case DAC960_MAJOR+0:
+ case DAC960_MAJOR+1:
+ case DAC960_MAJOR+2:
+ case DAC960_MAJOR+3:
+ case DAC960_MAJOR+4:
+ case DAC960_MAJOR+5:
+ case DAC960_MAJOR+6:
+ case DAC960_MAJOR+7:
case I2O_MAJOR:
case COMPAQ_SMART2_MAJOR+0:
case COMPAQ_SMART2_MAJOR+1:
@@ -592,13 +632,6 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
struct blk_dev_struct * dev;
int i;
- /* Make sure that the first block contains something reasonable */
- while (!*bh) {
- bh++;
- if (--nr <= 0)
- return;
- }
-
dev = NULL;
if ((major = MAJOR(bh[0]->b_dev)) < MAX_BLKDEV)
dev = blk_dev + major;
@@ -641,33 +674,29 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
#endif
}
- if ((rw == WRITE || rw == WRITEA) && is_read_only(bh[0]->b_dev)) {
+ if ((rw & WRITE) && is_read_only(bh[0]->b_dev)) {
printk(KERN_NOTICE "Can't write to read-only device %s\n",
kdevname(bh[0]->b_dev));
goto sorry;
}
for (i = 0; i < nr; i++) {
- if (bh[i]) {
- set_bit(BH_Req, &bh[i]->b_state);
+ set_bit(BH_Req, &bh[i]->b_state);
#ifdef CONFIG_BLK_DEV_MD
- if (MAJOR(bh[i]->b_dev) == MD_MAJOR) {
- md_make_request(MINOR (bh[i]->b_dev), rw, bh[i]);
- continue;
- }
-#endif
- make_request(MAJOR(bh[i]->b_rdev), rw, bh[i]);
+ if (MAJOR(bh[i]->b_dev) == MD_MAJOR) {
+ md_make_request(MINOR (bh[i]->b_dev), rw, bh[i]);
+ continue;
}
+#endif
+ make_request(MAJOR(bh[i]->b_rdev), rw, bh[i]);
}
return;
sorry:
for (i = 0; i < nr; i++) {
- if (bh[i]) {
- clear_bit(BH_Dirty, &bh[i]->b_state);
- clear_bit(BH_Uptodate, &bh[i]->b_state);
- bh[i]->b_end_io(bh[i], 0);
- }
+ clear_bit(BH_Dirty, &bh[i]->b_state);
+ clear_bit(BH_Uptodate, &bh[i]->b_state);
+ bh[i]->b_end_io(bh[i], 0);
}
return;
}
@@ -789,6 +818,9 @@ int __init blk_dev_init(void)
#ifdef CONFIG_MAC_FLOPPY
swim3_init();
#endif
+#ifdef CONFIG_BLK_DEV_SWIM_IOP
+ swimiop_init();
+#endif
#ifdef CONFIG_AMIGA_FLOPPY
amiga_floppy_init();
#endif
@@ -799,8 +831,9 @@ int __init blk_dev_init(void)
floppy_init();
#else
#if !defined(CONFIG_SGI_IP22) && !defined (__mc68000__) && \
- !defined(CONFIG_PMAC) && !defined(__sparc__) && !defined(CONFIG_APUS) \
- && !defined(CONFIG_DECSTATION) && !defined(CONFIG_BAGET_MIPS)
+ !defined(CONFIG_PPC) && !defined(__sparc__) && !defined(CONFIG_APUS) \
+ && !defined(CONFIG_DECSTATION) && !defined(CONFIG_BAGET_MIPS) \
+ && !defined(__sh__)
outb_p(0xc, 0x3f2);
#endif
#endif
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index b7987f33d..45f91b2da 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -21,6 +21,10 @@
* Make real block number available to downstream transfer functions, enables
* CBC (and relatives) mode encryption requiring unique IVs per data block.
* Reed H. Petty, rhp@draper.net
+ *
+ * Maximum number of loop devices now dynamic via max_loop module parameter.
+ * Still fixed at 8 devices when compiled into the kernel normally.
+ * Russell Kroll <rkroll@exploits.org> 19990701
*
* Still To Fix:
* - Advisory locking is ignored here.
@@ -61,10 +65,11 @@
#define TIMEOUT_VALUE (6 * HZ)
#include <linux/blk.h>
-#define MAX_LOOP 8
-static struct loop_device loop_dev[MAX_LOOP];
-static int loop_sizes[MAX_LOOP];
-static int loop_blksizes[MAX_LOOP];
+#include <linux/malloc.h>
+static int max_loop = 8;
+static struct loop_device *loop_dev;
+static int *loop_sizes;
+static int *loop_blksizes;
#define FALSE 0
#define TRUE (!FALSE)
@@ -169,7 +174,7 @@ repeat:
INIT_REQUEST;
current_request=CURRENT;
CURRENT=current_request->next;
- if (MINOR(current_request->rq_dev) >= MAX_LOOP)
+ if (MINOR(current_request->rq_dev) >= max_loop)
goto error_out;
lo = &loop_dev[MINOR(current_request->rq_dev)];
if (!lo->lo_dentry || !lo->transfer)
@@ -375,7 +380,7 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg)
a file structure */
lo->lo_backing_file = NULL;
} else if (S_ISREG(inode->i_mode)) {
- if (!inode->i_op->bmap) {
+ if (!inode->i_op->get_block) {
printk(KERN_ERR "loop: device has no block access/not implemented\n");
goto out_putf;
}
@@ -578,7 +583,7 @@ static int lo_ioctl(struct inode * inode, struct file * file,
return -ENODEV;
}
dev = MINOR(inode->i_rdev);
- if (dev >= MAX_LOOP)
+ if (dev >= max_loop)
return -ENODEV;
lo = &loop_dev[dev];
switch (cmd) {
@@ -615,7 +620,7 @@ static int lo_open(struct inode *inode, struct file *file)
return -ENODEV;
}
dev = MINOR(inode->i_rdev);
- if (dev >= MAX_LOOP) {
+ if (dev >= max_loop) {
return -ENODEV;
}
lo = &loop_dev[dev];
@@ -640,7 +645,7 @@ static int lo_release(struct inode *inode, struct file *file)
return 0;
}
dev = MINOR(inode->i_rdev);
- if (dev >= MAX_LOOP)
+ if (dev >= max_loop)
return 0;
err = fsync_dev(inode->i_rdev);
lo = &loop_dev[dev];
@@ -674,6 +679,8 @@ static struct file_operations lo_fops = {
*/
#ifdef MODULE
#define loop_init init_module
+MODULE_PARM(max_loop, "i");
+MODULE_PARM_DESC(max_loop, "Maximum number of loop devices (1-255)");
#endif
int loop_register_transfer(struct loop_func_table *funcs)
@@ -690,7 +697,7 @@ int loop_unregister_transfer(int number)
if ((unsigned)number >= MAX_LO_CRYPT)
return -EINVAL;
- for (lo = &loop_dev[0]; lo < &loop_dev[MAX_LOOP]; lo++) {
+ for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++) {
int type = lo->lo_encrypt_type;
if (type == number) {
xfer_funcs[type]->release(lo);
@@ -714,17 +721,46 @@ int __init loop_init(void)
MAJOR_NR);
return -EIO;
}
+
+ if ((max_loop < 1) || (max_loop > 255)) {
+ printk (KERN_WARNING "loop: max_loop must be between 1 and 255\n");
+ return -EINVAL;
+ }
+
#ifndef MODULE
printk(KERN_INFO "loop: registered device at major %d\n", MAJOR_NR);
+#else
+ printk(KERN_INFO "loop: enabling %d loop devices\n", max_loop);
#endif
+ loop_dev = kmalloc (max_loop * sizeof(struct loop_device), GFP_KERNEL);
+ if (!loop_dev) {
+ printk (KERN_ERR "loop: Unable to create loop_dev\n");
+ return -ENOMEM;
+ }
+
+ loop_sizes = kmalloc(max_loop * sizeof(int), GFP_KERNEL);
+ if (!loop_sizes) {
+ printk (KERN_ERR "loop: Unable to create loop_sizes\n");
+ kfree (loop_dev);
+ return -ENOMEM;
+ }
+
+ loop_blksizes = kmalloc (max_loop * sizeof(int), GFP_KERNEL);
+ if (!loop_blksizes) {
+ printk (KERN_ERR "loop: Unable to create loop_blksizes\n");
+ kfree (loop_dev);
+ kfree (loop_sizes);
+ return -ENOMEM;
+ }
+
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
- for (i=0; i < MAX_LOOP; i++) {
+ for (i=0; i < max_loop; i++) {
memset(&loop_dev[i], 0, sizeof(struct loop_device));
loop_dev[i].lo_number = i;
}
- memset(&loop_sizes, 0, sizeof(loop_sizes));
- memset(&loop_blksizes, 0, sizeof(loop_blksizes));
+ memset(loop_sizes, 0, max_loop * sizeof(int));
+ memset(loop_blksizes, 0, max_loop * sizeof(int));
blk_size[MAJOR_NR] = loop_sizes;
blksize_size[MAJOR_NR] = loop_blksizes;
@@ -736,5 +772,9 @@ void cleanup_module(void)
{
if (unregister_blkdev(MAJOR_NR, "loop") != 0)
printk(KERN_WARNING "loop: cannot unregister blkdev\n");
+
+ kfree (loop_dev);
+ kfree (loop_sizes);
+ kfree (loop_blksizes);
}
#endif
diff --git a/drivers/block/macide.c b/drivers/block/macide.c
index 2771ea702..4f6febd28 100644
--- a/drivers/block/macide.c
+++ b/drivers/block/macide.c
@@ -16,7 +16,7 @@
#include <linux/interrupt.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
-#include <linux/zorro.h>
+#include <linux/delay.h>
#include <linux/ide.h>
#include <asm/machw.h>
@@ -68,64 +68,16 @@ static int macide_offsets[IDE_NR_PORTS] = {
#define MAC_HD_ISR 0x101
- /*
- * IDE interrupt glue - seems to be wired to Nubus, Slot C?
- * (ROM code disassembly again)
- * First try: just use Nubus interrupt for Slot C. Have Nubus code call
- * a wrapper to ide_intr that checks the ISR (see above).
- * Need to #define IDE_IRQ_NUBUS though.
- * Alternative method: set a mac_ide_hook function pointer to the wrapper
- * here and have via_do_nubus call that hook if set.
- *
- * Quadra needs the hook, Powerbook can use Nubus slot C.
- * Checking the ISR on Quadra is done by mac_ack_intr (see Amiga code). mac_ide_intr
- * mac_ide_intr is obsolete except for providing the hwgroup argument.
- */
-
- /* The Mac hwif data, for passing hwgroup to ide_intr */
-static ide_hwif_t *mac_hwif = NULL;
-
- /* The function pointer used in the Nubus handler */
-void (*mac_ide_intr_hook)(int, void *, struct pt_regs *) = NULL;
-
- /*
- * Only purpose: feeds the hwgroup to the main IDE handler.
- * Obsolete as soon as Nubus code is fixed WRT pseudo slot C int.
- * (should be the case on Powerbooks)
- * Alas, second purpose: feed correct irq to IDE handler (I know,
- * that's cheating) :-(((
- * Fix needed for interrupt code: accept Nubus ints in the regular
- * request_irq code, then register Powerbook IDE as Nubus slot C,
- * Quadra as slot F (F for fictious).
- */
-void mac_ide_intr(int irq, void *dev_id, struct pt_regs *regs)
-{
- ide_intr(mac_hwif->irq, mac_hwif->hwgroup, regs);
-}
-
- /*
- * Check the interrupt status
- *
- * Note: In 2.0 kernels, there have been timing problems with the
- * Powerbook IDE interface (BUSY was asserted too long after the
- * interrupt triggered). Result: repeated errors, recalibrate etc.
- * Adding a wait loop to read_intr, write_intr and set_geom_intr
- * fixed the problem (waits in read/write_intr were present for Amiga
- * already).
- * Powerbooks were not tested with 2.1 due to lack of FPU emulation
- * (thanks Apple for using LC040). If the BUSY problem resurfaces in
- * 2.1, my best bet would be to add the wait loop right here, afterr
- * checking the interrupt register.
- */
-
-static int mac_ack_intr(ide_hwif_t *hwif)
+static int mac_ack_intr(ide_hwif_t* hwif)
{
- unsigned char ch;
+ unsigned char isr;
+ isr = readb(MAC_HD_BASE + MAC_HD_ISR);
+ if (isr & (1<<5)) {
+ writeb(isr & ~(1<<5), MAC_HD_BASE + MAC_HD_ISR);
+ return 1;
+ }
- ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]);
- if (!(ch & 0x20))
return 0;
- return 1;
}
/*
@@ -134,34 +86,31 @@ static int mac_ack_intr(ide_hwif_t *hwif)
void macide_init(void)
{
- hw_regs_t hw;
- int index = -1;
+ hw_regs_t hw;
+ int index = -1;
- if (MACH_IS_MAC) {
- switch(macintosh_config->ide_type) {
- case 0:
- break;
+ if (!MACH_IS_MAC || macintosh_config->ide_type == 0)
+ return;
+ switch (macintosh_config->ide_type) {
case MAC_IDE_QUADRA:
- ide_setup_ports(&hw, (ide_ioreg_t)MAC_HD_BASE, macide_offsets,
- 0, (ide_ioreg_t)(MAC_HD_BASE+MAC_HD_ISR),
- mac_ack_intr, IRQ_MAC_NUBUS);
- index = ide_register_hw(&hw, &mac_hwif);
- mac_ide_intr_hook = mac_ide_intr;
- break;
+ ide_setup_ports(&hw, (ide_ioreg_t)MAC_HD_BASE, macide_offsets,
+ 0, (ide_ioreg_t)(MAC_HD_BASE+MAC_HD_ISR),
+ mac_ack_intr, IRQ_NUBUS_F);
+ index = ide_register_hw(&hw, NULL);
+ break;
default:
ide_setup_ports(&hw, (ide_ioreg_t)MAC_HD_BASE, macide_offsets,
- 0, 0, NULL, IRQ_MAC_NUBUS);
- index = ide_register_hw(&hw, &mac_hwif);
+ 0, 0, NULL, IRQ_NUBUS_C);
+ index = ide_register_hw(&hw, NULL);
break;
}
if (index != -1) {
- if (macintosh_config->ide_type == MAC_IDE_QUADRA)
- printk("ide%d: Macintosh Quadra IDE interface\n", index);
- else
- printk("ide%d: Macintosh Powerbook IDE interface\n", index);
+ if (macintosh_config->ide_type == MAC_IDE_QUADRA)
+ printk("ide%d: Macintosh Quadra IDE interface\n", index);
+ else
+ printk("ide%d: Macintosh Powerbook IDE interface\n", index);
}
- }
}
diff --git a/drivers/block/md.c b/drivers/block/md.c
index bd610dc7b..69ff1813b 100644
--- a/drivers/block/md.c
+++ b/drivers/block/md.c
@@ -740,7 +740,7 @@ int md_make_request (int minor, int rw, struct buffer_head * bh)
if (buffer_locked(bh))
return 0;
set_bit(BH_Lock, &bh->b_state);
- if (rw == WRITE || rw == WRITEA) {
+ if (rw == WRITE) {
if (!buffer_dirty(bh)) {
bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state));
return 0;
@@ -1174,7 +1174,7 @@ struct {
};
/* called from init/main.c */
-__initfunc(void md_setup(char *str,int *ints))
+void __init md_setup(char *str,int *ints)
{
int i;
for(i=0;i<=ints[0];i++) {
@@ -1186,7 +1186,7 @@ __initfunc(void md_setup(char *str,int *ints))
return;
}
-__initfunc(void do_md_setup(char *str,int *ints))
+void __init do_md_setup(char *str,int *ints)
{
int minor, pers, factor, fault;
kdev_t dev;
@@ -1265,7 +1265,7 @@ void raid0_init (void);
void raid1_init (void);
void raid5_init (void);
-__initfunc(int md_init (void))
+int __init md_init (void)
{
printk ("md driver %d.%d.%d MAX_MD_DEV=%d, MAX_REAL=%d\n",
MD_MAJOR_VERSION, MD_MINOR_VERSION, MD_PATCHLEVEL_VERSION,
@@ -1306,7 +1306,7 @@ __initfunc(int md_init (void))
}
#ifdef CONFIG_MD_BOOT
-__initfunc(void md_setup_drive(void))
+void __init md_setup_drive(void)
{
if(md_setup_args.set)
do_md_setup(md_setup_args.str, md_setup_args.ints);
diff --git a/drivers/block/ns87415.c b/drivers/block/ns87415.c
index 9f4c1aa92..3ab183d31 100644
--- a/drivers/block/ns87415.c
+++ b/drivers/block/ns87415.c
@@ -102,7 +102,7 @@ static int ns87415_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
}
}
-__initfunc(void ide_init_ns87415 (ide_hwif_t *hwif))
+void __init ide_init_ns87415 (ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
unsigned int ctrl, using_inta;
diff --git a/drivers/block/paride/paride.c b/drivers/block/paride/paride.c
index 9e238803e..f05196389 100644
--- a/drivers/block/paride/paride.c
+++ b/drivers/block/paride/paride.c
@@ -24,7 +24,8 @@
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/string.h>
-#include <asm/spinlock.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
#ifdef CONFIG_PARPORT_MODULE
#define CONFIG_PARPORT
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index 6366afa6b..13b5f1b6a 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -142,9 +142,9 @@ static int pcd_drive_count;
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/cdrom.h>
+#include <linux/spinlock.h>
#include <asm/uaccess.h>
-#include <asm/spinlock.h>
#ifndef MODULE
@@ -838,21 +838,21 @@ static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
case CDROMPAUSE:
- { char cmd[12]={SCMD_PAUSE_RESUME,0,0,0,0,0,0,0,0,0,0,0};
+ { char cmd[12]={GPCMD_PAUSE_RESUME,0,0,0,0,0,0,0,0,0,0,0};
return (pcd_atapi(unit,cmd,0,NULL,"pause")) * EIO;
}
case CDROMRESUME:
- { char cmd[12]={SCMD_PAUSE_RESUME,0,0,0,0,0,0,0,1,0,0,0};
+ { char cmd[12]={GPCMD_PAUSE_RESUME,0,0,0,0,0,0,0,1,0,0,0};
return (pcd_atapi(unit,cmd,0,NULL,"resume")) * EIO;
}
case CDROMPLAYMSF:
- { char cmd[12]={SCMD_PLAYAUDIO_MSF,0,0,0,0,0,0,0,0,0,0,0};
+ { char cmd[12]={GPCMD_PLAY_AUDIO_MSF,0,0,0,0,0,0,0,0,0,0,0};
struct cdrom_msf* msf = (struct cdrom_msf*)arg;
cmd[3] = msf->cdmsf_min0;
@@ -867,7 +867,7 @@ static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
case CDROMPLAYBLK:
- { char cmd[12]={SCMD_PLAYAUDIO10,0,0,0,0,0,0,0,0,0,0,0};
+ { char cmd[12]={GPCMD_PLAY_AUDIO_10,0,0,0,0,0,0,0,0,0,0,0};
struct cdrom_blk* blk = (struct cdrom_blk*)arg;
cmd[2] = blk->from >> 24;
@@ -882,7 +882,7 @@ static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
case CDROMPLAYTRKIND:
- { char cmd[12]={SCMD_PLAYAUDIO_TI,0,0,0,0,0,0,0,0,0,0,0};
+ { char cmd[12]={GPCMD_PLAYAUDIO_TI,0,0,0,0,0,0,0,0,0,0,0};
struct cdrom_ti* ti = (struct cdrom_ti*)arg;
cmd[4] = ti->cdti_trk0;
@@ -895,7 +895,7 @@ static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
case CDROMREADTOCHDR:
- { char cmd[12]={SCMD_READ_TOC,0,0,0,0,0,0,0,12,0,0,0};
+ { char cmd[12]={GPCMD_READ_TOC_PMA_ATIP,0,0,0,0,0,0,0,12,0,0,0};
struct cdrom_tochdr* tochdr = (struct cdrom_tochdr*)arg;
char buffer[32];
int r;
@@ -910,7 +910,7 @@ static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
case CDROMREADTOCENTRY:
- { char cmd[12]={SCMD_READ_TOC,0,0,0,0,0,0,0,12,0,0,0};
+ { char cmd[12]={GPCMD_READ_TOC_PMA_ATIP,0,0,0,0,0,0,0,12,0,0,0};
struct cdrom_tocentry* tocentry = (struct cdrom_tocentry*)arg;
unsigned char buffer[32];
@@ -938,21 +938,21 @@ static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
case CDROMSTOP:
- { char cmd[12]={0x1b,1,0,0,0,0,0,0,0,0,0,0};
+ { char cmd[12]={GPCMD_START_STOP_UNIT,1,0,0,0,0,0,0,0,0,0,0};
return (pcd_atapi(unit,cmd,0,NULL,"stop")) * EIO;
}
case CDROMSTART:
- { char cmd[12]={0x1b,1,0,0,1,0,0,0,0,0,0,0};
+ { char cmd[12]={GPCMD_START_STOP_UNIT,1,0,0,1,0,0,0,0,0,0,0};
return (pcd_atapi(unit,cmd,0,NULL,"start")) * EIO;
}
case CDROMVOLCTRL:
- { char cmd[12]={0x5a,0,0,0,0,0,0,0,0,0,0,0};
+ { char cmd[12]={GPCMD_MODE_SENSE_10,0,0,0,0,0,0,0,0,0,0,0};
char buffer[32];
char mask[32];
struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg;
@@ -983,7 +983,7 @@ static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
case CDROMVOLREAD:
- { char cmd[12]={0x5a,0,0,0,0,0,0,0,0,0,0,0};
+ { char cmd[12]={GPCMD_MODE_SENSE_10,0,0,0,0,0,0,0,0,0,0,0};
char buffer[32];
struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg;
int r;
@@ -1004,7 +1004,7 @@ static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
case CDROMSUBCHNL:
- { char cmd[12]={SCMD_READ_SUBCHANNEL,2,0x40,1,0,0,0,0,16,0,0,0};
+ { char cmd[12]={GPCMD_READ_SUBCHANNEL,2,0x40,1,0,0,0,0,16,0,0,0};
struct cdrom_subchnl* subchnl = (struct cdrom_subchnl*)arg;
char buffer[32];
@@ -1035,7 +1035,7 @@ static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-{ char cmd[12]={SCMD_READ_SUBCHANNEL,0,0x40,2,0,0,0,0,24,0,0,0};
+{ char cmd[12]={GPCMD_READ_SUBCHANNEL,0,0x40,2,0,0,0,0,24,0,0,0};
char buffer[32];
int k;
int unit = DEVICE_NR(cdi->dev);
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 128f9b21d..bd2839053 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -161,8 +161,8 @@ static int pd_drive_count;
#include <linux/genhd.h>
#include <linux/hdreg.h>
#include <linux/cdrom.h> /* for the eject ioctl */
+#include <linux/spinlock.h>
-#include <asm/spinlock.h>
#include <asm/uaccess.h>
#ifndef MODULE
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index f1cdfe3c6..58a747cb7 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -160,7 +160,7 @@ static int pf_drive_count;
#include <linux/genhd.h>
#include <linux/hdreg.h>
#include <linux/cdrom.h>
-#include <asm/spinlock.h>
+#include <linux/spinlock.h>
#include <asm/uaccess.h>
diff --git a/drivers/block/pdc202xx.c b/drivers/block/pdc202xx.c
index 08f87655e..5bbd0c3e7 100644
--- a/drivers/block/pdc202xx.c
+++ b/drivers/block/pdc202xx.c
@@ -215,8 +215,8 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
byte test1, test2, speed;
byte AP, BP, CP, DP, EP;
int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
- byte udma_66 = ((id->word93 & 0x2000) && (dev->device == PCI_DEVICE_ID_PROMISE_20262)) ? 1 : 0;
- byte udma_33 = ultra ? (inb((dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK) + 0x001f) & 1) : 0;
+ byte udma_66 = ((id->word93 & 0x2000) && (hwif->udma_four)) ? 1 : 0;
+ byte udma_33 = ultra ? (inb((dev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK) + 0x001f) & 1) : 0;
pci_read_config_byte(dev, 0x50, &EP);
@@ -308,7 +308,7 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
speed = XFER_UDMA_3;
} else if ((id->dma_ultra & 0x0004) && (udma_33)) {
if (!((id->dma_ultra >> 8) & 4)) {
- drive->id->dma_ultra &= ~0x0F00;
+ drive->id->dma_ultra &= ~0xFF00;
drive->id->dma_ultra |= 0x0404;
drive->id->dma_mword &= ~0x0F00;
drive->id->dma_1word &= ~0x0F00;
@@ -319,7 +319,7 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
speed = XFER_UDMA_2;
} else if ((id->dma_ultra & 0x0002) && (udma_33)) {
if (!((id->dma_ultra >> 8) & 2)) {
- drive->id->dma_ultra &= ~0x0F00;
+ drive->id->dma_ultra &= ~0xFF00;
drive->id->dma_ultra |= 0x0202;
drive->id->dma_mword &= ~0x0F00;
drive->id->dma_1word &= ~0x0F00;
@@ -330,7 +330,7 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
speed = XFER_UDMA_1;
} else if ((id->dma_ultra & 0x0001) && (udma_33)) {
if (!((id->dma_ultra >> 8) & 1)) {
- drive->id->dma_ultra &= ~0x0F00;
+ drive->id->dma_ultra &= ~0xFF00;
drive->id->dma_ultra |= 0x0101;
drive->id->dma_mword &= ~0x0F00;
drive->id->dma_1word &= ~0x0F00;
@@ -491,16 +491,16 @@ int pdc202xx_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
return ide_dmaproc(func, drive); /* use standard DMA stuff */
}
-__initfunc(unsigned int pci_init_pdc202xx (struct pci_dev *dev, const char *name))
+unsigned int __init pci_init_pdc202xx (struct pci_dev *dev, const char *name)
{
- unsigned long high_16 = dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK;
+ unsigned long high_16 = dev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK;
byte udma_speed_flag = inb(high_16 + 0x001f);
byte primary_mode = inb(high_16 + 0x001a);
byte secondary_mode = inb(high_16 + 0x001b);
- if (dev->rom_address) {
- pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->rom_address | PCI_ROM_ADDRESS_ENABLE);
- printk("%s: ROM enabled at 0x%08lx\n", name, dev->rom_address);
+ if (dev->resource[PCI_ROM_RESOURCE].start) {
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
+ printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start);
}
if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) {
@@ -547,9 +547,24 @@ __initfunc(unsigned int pci_init_pdc202xx (struct pci_dev *dev, const char *name
return dev->irq;
}
-__initfunc(void ide_init_pdc202xx (ide_hwif_t *hwif))
+void __init ide_init_pdc202xx (ide_hwif_t *hwif)
{
if (hwif->dma_base) {
hwif->dmaproc = &pdc202xx_dmaproc;
+
+ switch(hwif->pci_dev->device) {
+ case PCI_DEVICE_ID_PROMISE_20262:
+#if 0
+ {
+ unsigned long high_16 = hwif->pci_dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK;
+ hwif->udma_four = 1;
+ }
+#endif
+ break;
+ case PCI_DEVICE_ID_PROMISE_20246:
+ default:
+ hwif->udma_four = 0;
+ break;
+ }
}
}
diff --git a/drivers/block/piix.c b/drivers/block/piix.c
index 384712603..b1fd76014 100644
--- a/drivers/block/piix.c
+++ b/drivers/block/piix.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/piix.c Version 0.24 June 28, 1999
+ * linux/drivers/block/piix.c Version 0.25 July 11, 1999
*
* Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
* Copyright (C) 1998-1999 Andre Hedrick, Author and Maintainer
@@ -149,18 +149,19 @@ static void piix_tune_drive (ide_drive_t *drive, byte pio)
#ifdef CONFIG_BLK_DEV_PIIX_TUNING
-static int piix_config_drive_for_dma(ide_drive_t *drive, int ultra)
+static int piix_config_drive_for_dma(ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
- unsigned long flags;
int sitre;
short reg4042, reg44, reg48, reg4a;
byte speed;
int u_speed;
- byte maslave = hwif->channel ? 0x42 : 0x40;
+
+ byte maslave = hwif->channel ? 0x42 : 0x40;
+ int ultra = (dev->device == PCI_DEVICE_ID_INTEL_82371AB) ? 1 : 0;
int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
int a_speed = 2 << (drive_number * 4);
int u_flag = 1 << drive_number;
@@ -171,9 +172,6 @@ static int piix_config_drive_for_dma(ide_drive_t *drive, int ultra)
pci_read_config_word(dev, 0x48, &reg48);
pci_read_config_word(dev, 0x4a, &reg4a);
- save_flags(flags);
- cli();
-
if (id->dma_ultra && (ultra)) {
if (!(reg48 & u_flag)) {
pci_write_config_word(dev, 0x48, reg48|u_flag);
@@ -184,7 +182,12 @@ static int piix_config_drive_for_dma(ide_drive_t *drive, int ultra)
}
}
- if ((id->dma_ultra & 0x0004) && (ultra)) {
+ if ((id->dma_ultra & 0x0010) && (ultra)) {
+ goto backspeed;
+ } else if ((id->dma_ultra & 0x0008) && (ultra)) {
+ goto backspeed;
+ } else if ((id->dma_ultra & 0x0004) && (ultra)) {
+backspeed:
drive->id->dma_mword &= ~0x0F00;
drive->id->dma_1word &= ~0x0F00;
if (!((id->dma_ultra >> 8) & 4)) {
@@ -256,7 +259,6 @@ static int piix_config_drive_for_dma(ide_drive_t *drive, int ultra)
speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
}
- restore_flags(flags);
piix_tune_drive(drive, piix_dma_2_pio(speed));
(void) ide_config_drive_speed(drive, speed);
@@ -269,7 +271,8 @@ static int piix_config_drive_for_dma(ide_drive_t *drive, int ultra)
printk("\n");
#endif /* PIIX_DEBUG_DRIVE_INFO */
- return ((int) ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+ 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);
@@ -277,10 +280,9 @@ static int piix_config_drive_for_dma(ide_drive_t *drive, int ultra)
static int piix_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
{
- int ultra = (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_INTEL_82371AB) ? 1 : 0;
switch (func) {
case ide_dma_check:
- return ide_dmaproc((ide_dma_action_t) piix_config_drive_for_dma(drive, ultra), drive);
+ return ide_dmaproc((ide_dma_action_t) piix_config_drive_for_dma(drive), drive);
default :
break;
}
@@ -292,12 +294,14 @@ static int piix_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
void ide_init_piix (ide_hwif_t *hwif)
{
hwif->tuneproc = &piix_tune_drive;
-#ifdef CONFIG_BLK_DEV_PIIX_TUNING
+
if (hwif->dma_base) {
+#ifdef CONFIG_BLK_DEV_PIIX_TUNING
hwif->dmaproc = &piix_dmaproc;
- } else
#endif /* CONFIG_BLK_DEV_PIIX_TUNING */
- {
+ hwif->drives[0].autotune = 0;
+ hwif->drives[1].autotune = 0;
+ } else {
hwif->drives[0].autotune = 1;
hwif->drives[1].autotune = 1;
}
diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
index e1ff03e8f..221a3297a 100644
--- a/drivers/block/ps2esdi.c
+++ b/drivers/block/ps2esdi.c
@@ -124,7 +124,7 @@ static struct timer_list esdi_timer = {NULL, NULL, 0, 0L, ps2esdi_reset_timer};
static int reset_status;
static int ps2esdi_slot = -1;
int tp720esdi = 0; /* Is it Integrated ESDI of ThinkPad-720? */
-
+int intg_esdi = 0; /* If integrated adapter */
struct ps2esdi_i_struct {
unsigned int head, sect, cyl, wpcom, lzone, ctl;
};
@@ -178,7 +178,7 @@ static struct gendisk ps2esdi_gendisk =
};
/* initialization routine called by ll_rw_blk.c */
-__initfunc(int ps2esdi_init(void))
+int __init ps2esdi_init(void)
{
/* register the device - pass the name, major number and operations
@@ -244,7 +244,7 @@ cleanup_module(void)
#endif /* MODULE */
/* handles boot time command line parameters */
-__initfunc(void tp720_setup(char *str, int *ints))
+void __init tp720_setup(char *str, int *ints)
{
/* no params, just sets the tp720esdi flag if it exists */
@@ -252,7 +252,7 @@ __initfunc(void tp720_setup(char *str, int *ints))
tp720esdi = 1;
}
-__initfunc(void ed_setup(char *str, int *ints))
+void __init ed_setup(char *str, int *ints)
{
int hdind = 0;
@@ -299,7 +299,7 @@ static int ps2esdi_getinfo(char *buf, int slot, void *d)
}
/* ps2 esdi specific initialization - called thru the gendisk chain */
-__initfunc(static void ps2esdi_geninit(struct gendisk *ignored))
+static void __init ps2esdi_geninit(struct gendisk *ignored)
{
/*
The first part contains the initialization code
@@ -387,7 +387,7 @@ __initfunc(static void ps2esdi_geninit(struct gendisk *ignored))
reset_status = 0;
reset_start = jiffies;
while (!reset_status) {
- esdi_timer.expires = 100;
+ esdi_timer.expires = HZ;
esdi_timer.data = 0;
esdi_timer.next = esdi_timer.prev = NULL;
add_timer(&esdi_timer);
@@ -401,8 +401,9 @@ __initfunc(static void ps2esdi_geninit(struct gendisk *ignored))
/* Integrated ESDI Disk and Controller has only one drive! */
- if (adapterID == INTG_ESDI_ID) /* if not "normal" PS2 ESDI adapter */
- ps2esdi_drives = 1; /* then we have only one physical disk! */
+ if (adapterID == INTG_ESDI_ID) {/* if not "normal" PS2 ESDI adapter */
+ ps2esdi_drives = 1; /* then we have only one physical disk! */ intg_esdi = 1;
+ }
@@ -437,7 +438,7 @@ __initfunc(static void ps2esdi_geninit(struct gendisk *ignored))
} /* ps2esdi_geninit */
-__initfunc(static void ps2esdi_get_device_cfg(void))
+static void __init ps2esdi_get_device_cfg(void)
{
u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH];
@@ -560,7 +561,7 @@ static void reset_ctrl(void)
/*BA */
printk("%s: hard reset...\n", DEVICE_NAME);
outb_p(CTRL_HARD_RESET, ESDI_CONTROL);
- expire = jiffies + 200;
+ expire = jiffies + 2*HZ;
while (time_before(jiffies, expire));
outb_p(1, ESDI_CONTROL);
} /* hard reset */
@@ -812,7 +813,8 @@ static void ps2esdi_geometry_int_handler(u_int int_ret_code)
ps2esdi_info[0].wpcom = 0;
ps2esdi_info[0].lzone = reply[3];
} else {
- ps2esdi_drives++;
+ if (!intg_esdi)
+ ps2esdi_drives++;
}
}
#ifdef OBSOLETE
diff --git a/drivers/block/q40ide.c b/drivers/block/q40ide.c
new file mode 100644
index 000000000..93d302a61
--- /dev/null
+++ b/drivers/block/q40ide.c
@@ -0,0 +1,109 @@
+/*
+ * linux/drivers/block/q40ide.c -- Q40 I/O port IDE Driver
+ *
+ * original file created 12 Jul 1997 by Geert Uytterhoeven
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * RZ:
+ * almost identical with pcide.c, maybe we can merge it later.
+ * Differences:
+ * max 2 HWIFS for now
+ * translate portaddresses to q40 native addresses (not yet...) instead rely on in/out[bw]
+ * address translation
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+
+#include "ide.h"
+
+ /*
+ * Bases of the IDE interfaces
+ */
+
+#define PCIDE_NUM_HWIFS 2
+
+#define PCIDE_BASE1 0x1f0
+#define PCIDE_BASE2 0x170
+#define PCIDE_BASE3 0x1e8
+#define PCIDE_BASE4 0x168
+#define PCIDE_BASE5 0x1e0
+#define PCIDE_BASE6 0x160
+
+static const q40ide_ioreg_t pcide_bases[PCIDE_NUM_HWIFS] = {
+ PCIDE_BASE1, PCIDE_BASE2, /* PCIDE_BASE3, PCIDE_BASE4 , PCIDE_BASE5,
+ PCIDE_BASE6 */
+};
+
+
+ /*
+ * Offsets from one of the above bases
+ */
+
+#undef HD_DATA
+#define HD_DATA 0x1f0
+
+#define PCIDE_REG(x) ((q40ide_ioreg_t)(HD_##x-PCIDE_BASE1))
+
+static const int pcide_offsets[IDE_NR_PORTS] = {
+ PCIDE_REG(DATA), PCIDE_REG(ERROR), PCIDE_REG(NSECTOR), PCIDE_REG(SECTOR),
+ PCIDE_REG(LCYL), PCIDE_REG(HCYL), PCIDE_REG(CURRENT), PCIDE_REG(STATUS),
+ PCIDE_REG(CMD)
+};
+
+int q40ide_default_irq(q40ide_ioreg_t base)
+{
+ switch (base) {
+ case 0x1f0: return 14;
+ case 0x170: return 15;
+ case 0x1e8: return 11;
+ default:
+ return 0;
+ }
+}
+
+void q40_ide_init_hwif_ports (q40ide_ioreg_t *p, q40ide_ioreg_t base, int *irq)
+{
+ q40ide_ioreg_t port = base;
+ int i = 8;
+
+ while (i--)
+ *p++ = port++;
+ *p++ = base + 0x206;
+ if (irq != NULL)
+ *irq = 0;
+}
+
+
+ /*
+ * Probe for PC IDE interfaces
+ */
+
+int q40ide_probe_hwif(int index, ide_hwif_t *hwif)
+{
+ static int pcide_index[PCIDE_NUM_HWIFS] = { 0, };
+ int i;
+
+ if (!MACH_IS_Q40)
+ return 0;
+
+ for (i = 0; i < PCIDE_NUM_HWIFS; i++) {
+ if (!pcide_index[i]) {
+ /*printk("ide%d: Q40 IDE interface\n", index);*/
+ pcide_index[i] = index+1;
+ }
+ if (pcide_index[i] == index+1) {
+ ide_setup_ports(hwif,(ide_ioreg_t) pcide_bases[i], pcide_offsets, 0, /*q40_ack_intr???*/ NULL);
+ hwif->irq = ide_default_irq((ide_ioreg_t)pcide_bases[i]); /*q40_ide_irq[i]; */ /* 14 */
+ return 1;
+ }
+ }
+ return 0;
+}
diff --git a/drivers/block/raid1.c b/drivers/block/raid1.c
index 7efb78400..6671f83e8 100644
--- a/drivers/block/raid1.c
+++ b/drivers/block/raid1.c
@@ -159,7 +159,7 @@ void raid1_end_request (struct buffer_head *bh, int uptodate)
}
/*
- * WRITE or WRITEA.
+ * WRITE.
*/
PRINTK(("raid1_end_request(), write branch.\n"));
@@ -215,15 +215,14 @@ raid1_make_request (struct md_dev *mddev, int rw, struct buffer_head * bh)
memset (r1_bh, 0, sizeof (struct raid1_bh));
/*
- * make_request() can abort the operation when READA or WRITEA are being
+ * make_request() can abort the operation when READA is being
* used and no empty request is available.
*
* Currently, just replace the command with READ/WRITE.
*/
if (rw == READA) rw = READ;
- if (rw == WRITEA) rw = WRITE;
- if (rw == WRITE || rw == WRITEA)
+ if (rw == WRITE)
mark_buffer_clean(bh); /* Too early ? */
/*
@@ -269,7 +268,7 @@ raid1_make_request (struct md_dev *mddev, int rw, struct buffer_head * bh)
}
/*
- * WRITE or WRITEA.
+ * WRITE.
*/
PRINTK(("raid1_make_request(n=%d), write branch.\n",n));
diff --git a/drivers/block/raid5.c b/drivers/block/raid5.c
index 3e60f92ce..83fc26fad 100644
--- a/drivers/block/raid5.c
+++ b/drivers/block/raid5.c
@@ -97,7 +97,7 @@ void __wait_on_stripe(struct stripe_head *sh)
sh->count++;
add_wait_queue(&sh->wait, &wait);
repeat:
- current->state = TASK_UNINTERRUPTIBLE;
+ set_current_state(TASK_UNINTERRUPTIBLE);
if (stripe_locked(sh)) {
schedule();
goto repeat;
@@ -1206,7 +1206,6 @@ static int raid5_make_request (struct md_dev *mddev, int rw, struct buffer_head
struct stripe_head *sh;
if (rw == READA) rw = READ;
- if (rw == WRITEA) rw = WRITE;
new_sector = raid5_compute_sector(bh->b_rsector, raid_disks, data_disks,
&dd_idx, &pd_idx, raid_conf);
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 6c2768b27..7aeb3a30f 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -74,15 +74,6 @@ extern void wait_for_keypress(void);
#include <linux/blk.h>
#include <linux/blkpg.h>
-/*
- * We use a block size of 512 bytes in comparision to BLOCK_SIZE
- * defined in include/linux/blk.h. This because of the finer
- * granularity for filling up a RAM disk.
- */
-#define RDBLK_SIZE_BITS 9
-#define RDBLK_SIZE (1<<RDBLK_SIZE_BITS)
-
-
/* The RAM disk size is now a parameter */
#define NUM_RAMDISKS 16 /* This cannot be overridden (yet) */
@@ -114,8 +105,21 @@ static int rd_kbsize[NUM_RAMDISKS]; /* Size in blocks of 1024 bytes */
* information).
*/
int rd_size = 4096; /* Size of the RAM disks */
+/*
+ * It would be very desiderable to have a soft-blocksize (that in the case
+ * of the ramdisk driver is also the hardblocksize ;) of PAGE_SIZE because
+ * doing that we'll achieve a far better MM footprint. Using a rd_blocksize of
+ * BLOCK_SIZE in the worst case we'll make PAGE_SIZE/BLOCK_SIZE buffer-pages
+ * unfreeable. With a rd_blocksize of PAGE_SIZE instead we are sure that only
+ * 1 page will be protected. Depending on the size of the ramdisk you
+ * may want to change the ramdisk blocksize to achieve a better or worse MM
+ * behaviour. The default is still BLOCK_SIZE (needed by rd_load_image that
+ * supposes the filesystem in the image uses a BLOCK_SIZE blocksize).
+ */
+int rd_blocksize = BLOCK_SIZE; /* Size of the RAM disks */
#ifndef MODULE
+
int rd_doload = 0; /* 1 = load RAM disk, 0 = don't load */
int rd_prompt = 1; /* 1 = prompt for RAM disk, 0 = don't prompt */
int rd_image_start = 0; /* starting block # of image */
@@ -123,7 +127,52 @@ int rd_image_start = 0; /* starting block # of image */
unsigned long initrd_start,initrd_end;
int mount_initrd = 1; /* zero if initrd should not be mounted */
int initrd_below_start_ok = 0;
+
+static int __init no_initrd(char *str)
+{
+ mount_initrd = 0;
+ return 1;
+}
+
+__setup("noinitrd", no_initrd);
+
#endif
+
+static int __init ramdisk_start_setup(char *str)
+{
+ rd_image_start = simple_strtol(str,NULL,0);
+ return 1;
+}
+
+static int __init load_ramdisk(char *str)
+{
+ rd_doload = simple_strtol(str,NULL,0) & 3;
+ return 1;
+}
+
+static int __init prompt_ramdisk(char *str)
+{
+ rd_prompt = simple_strtol(str,NULL,0) & 1;
+ return 1;
+}
+
+static int __init ramdisk_size(char *str)
+{
+ rd_size = simple_strtol(str,NULL,0);
+ return 1;
+}
+
+static int __init ramdisk_size2(char *str)
+{
+ return ramdisk_size(str);
+}
+
+__setup("ramdisk_start=", ramdisk_start_setup);
+__setup("load_ramdisk=", load_ramdisk);
+__setup("prompt_ramdisk=", prompt_ramdisk);
+__setup("ramdisk=", ramdisk_size);
+__setup("ramdisk_size=", ramdisk_size2);
+
#endif
/*
@@ -138,9 +187,6 @@ static void rd_request(void)
unsigned long offset, len;
repeat:
- if (!CURRENT)
- return;
-
INIT_REQUEST;
minor = MINOR(CURRENT->rq_dev);
@@ -150,8 +196,8 @@ repeat:
goto repeat;
}
- offset = CURRENT->sector << RDBLK_SIZE_BITS;
- len = CURRENT->current_nr_sectors << RDBLK_SIZE_BITS;
+ offset = CURRENT->sector << 9;
+ len = CURRENT->current_nr_sectors << 9;
if ((offset + len) > rd_length[minor]) {
end_request(0);
@@ -197,7 +243,7 @@ static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
case BLKGETSIZE: /* Return device size */
if (!arg) return -EINVAL;
- return put_user(rd_length[minor] >> RDBLK_SIZE_BITS, (long *) arg);
+ return put_user(rd_kbsize[minor] << 1, (long *) arg);
case BLKROSET:
case BLKROGET:
@@ -297,10 +343,18 @@ static struct file_operations fd_fops = {
};
/* This is the registration and initialization section of the RAM disk driver */
-__initfunc(int rd_init(void))
+int __init rd_init(void)
{
int i;
+ if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 ||
+ (rd_blocksize & (rd_blocksize-1)))
+ {
+ printk("RAMDISK: wrong blocksize %d, reverting to defaults\n",
+ rd_blocksize);
+ rd_blocksize = BLOCK_SIZE;
+ }
+
if (register_blkdev(MAJOR_NR, "ramdisk", &fd_fops)) {
printk("RAMDISK: Could not get major %d", MAJOR_NR);
return -EIO;
@@ -310,18 +364,19 @@ __initfunc(int rd_init(void))
for (i = 0; i < NUM_RAMDISKS; i++) {
/* rd_size is given in kB */
- rd_length[i] = (rd_size << BLOCK_SIZE_BITS);
- rd_hardsec[i] = RDBLK_SIZE;
- rd_blocksizes[i] = BLOCK_SIZE;
- rd_kbsize[i] = (rd_length[i] >> BLOCK_SIZE_BITS);
+ rd_length[i] = rd_size << 10;
+ rd_hardsec[i] = rd_blocksize;
+ rd_blocksizes[i] = rd_blocksize;
+ rd_kbsize[i] = rd_size;
}
hardsect_size[MAJOR_NR] = rd_hardsec; /* Size of the RAM disk blocks */
blksize_size[MAJOR_NR] = rd_blocksizes; /* Avoid set_blocksize() check */
blk_size[MAJOR_NR] = rd_kbsize; /* Size of the RAM disk in kB */
- printk("RAM disk driver initialized: %d RAM disks of %dK size\n",
- NUM_RAMDISKS, rd_size);
+ printk("RAMDISK driver initialized: "
+ "%d RAM disks of %dK size %d blocksize\n",
+ NUM_RAMDISKS, rd_size, rd_blocksize);
return 0;
}
@@ -331,7 +386,9 @@ __initfunc(int rd_init(void))
#ifdef MODULE
MODULE_PARM (rd_size, "1i");
-MODULE_PARM_DESC(rd_size, "Size of each RAM disk.");
+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)
{
@@ -370,8 +427,8 @@ void cleanup_module(void)
* romfs
* gzip
*/
-__initfunc(int
-identify_ramdisk_image(kdev_t device, struct file *fp, int start_block))
+int __init
+identify_ramdisk_image(kdev_t device, struct file *fp, int start_block)
{
const int size = 512;
struct minix_super_block *minixsb;
@@ -463,7 +520,7 @@ done:
/*
* This routine loads in the RAM disk image.
*/
-__initfunc(static void rd_load_image(kdev_t device, int offset, int unit))
+static void __init rd_load_image(kdev_t device, int offset, int unit)
{
struct inode inode, out_inode;
struct file infile, outfile;
@@ -518,9 +575,15 @@ __initfunc(static void rd_load_image(kdev_t device, int offset, int unit))
goto done;
}
- if (nblocks > (rd_length[unit] >> RDBLK_SIZE_BITS)) {
+ /*
+ * NOTE NOTE: nblocks suppose that the blocksize is BLOCK_SIZE, so
+ * rd_load_image will work only with filesystem BLOCK_SIZE wide!
+ * So make sure to use 1k blocksize while generating ext2fs
+ * ramdisk-images.
+ */
+ if (nblocks > (rd_length[unit] >> BLOCK_SIZE_BITS)) {
printk("RAMDISK: image too big! (%d/%ld blocks)\n",
- nblocks, rd_length[unit] >> RDBLK_SIZE_BITS);
+ nblocks, rd_length[unit] >> BLOCK_SIZE_BITS);
goto done;
}
@@ -585,7 +648,7 @@ done:
}
-__initfunc(static void rd_load_disk(int n))
+static void __init rd_load_disk(int n)
{
#ifdef CONFIG_BLK_DEV_INITRD
extern kdev_t real_root_dev;
@@ -614,18 +677,18 @@ __initfunc(static void rd_load_disk(int n))
}
-__initfunc(void rd_load(void))
+void __init rd_load(void)
{
rd_load_disk(0);
}
-__initfunc(void rd_load_secondary(void))
+void __init rd_load_secondary(void)
{
rd_load_disk(1);
}
#ifdef CONFIG_BLK_DEV_INITRD
-__initfunc(void initrd_load(void))
+void __init initrd_load(void)
{
rd_load_image(MKDEV(MAJOR_NR, INITRD_MINOR),rd_image_start,0);
}
@@ -684,21 +747,21 @@ static void gzip_release(void **);
#include "../../lib/inflate.c"
-__initfunc(static void *malloc(int size))
+static void __init *malloc(int size)
{
return kmalloc(size, GFP_KERNEL);
}
-__initfunc(static void free(void *where))
+static void __init free(void *where)
{
kfree(where);
}
-__initfunc(static void gzip_mark(void **ptr))
+static void __init gzip_mark(void **ptr)
{
}
-__initfunc(static void gzip_release(void **ptr))
+static void __init gzip_release(void **ptr)
{
}
@@ -707,7 +770,7 @@ __initfunc(static void gzip_release(void **ptr))
* Fill the input buffer. This is called only when the buffer is empty
* and at least one byte is really needed.
*/
-__initfunc(static int fill_inbuf(void))
+static int __init fill_inbuf(void)
{
if (exit_code) return -1;
@@ -724,7 +787,7 @@ __initfunc(static int fill_inbuf(void))
* Write the output window window[0..outcnt-1] and update crc and bytes_out.
* (Used for the decompressed data only.)
*/
-__initfunc(static void flush_window(void))
+static void __init flush_window(void)
{
ulg c = crc; /* temporary variable */
unsigned n;
@@ -741,14 +804,14 @@ __initfunc(static void flush_window(void))
outcnt = 0;
}
-__initfunc(static void error(char *x))
+static void __init error(char *x)
{
printk(KERN_ERR "%s", x);
exit_code = 1;
}
-__initfunc(static int
-crd_load(struct file * fp, struct file *outfp))
+static int __init
+crd_load(struct file * fp, struct file *outfp)
{
int result;
diff --git a/drivers/block/rz1000.c b/drivers/block/rz1000.c
index ae8749813..811e1665f 100644
--- a/drivers/block/rz1000.c
+++ b/drivers/block/rz1000.c
@@ -33,7 +33,7 @@
#ifdef CONFIG_BLK_DEV_IDEPCI
-__initfunc(void ide_init_rz1000 (ide_hwif_t *hwif)) /* called from ide-pci.c */
+void __init ide_init_rz1000 (ide_hwif_t *hwif) /* called from ide-pci.c */
{
unsigned short reg;
struct pci_dev *dev = hwif->pci_dev;
@@ -53,7 +53,7 @@ __initfunc(void ide_init_rz1000 (ide_hwif_t *hwif)) /* called from ide-pci.c */
#else
-__initfunc(static void init_rz1000 (struct pci_dev *dev, const char *name))
+static void __init init_rz1000 (struct pci_dev *dev, const char *name)
{
unsigned short reg, h;
@@ -83,13 +83,13 @@ __initfunc(static void init_rz1000 (struct pci_dev *dev, const char *name))
}
}
-__initfunc(void ide_probe_for_rz100x (void)) /* called from ide.c */
+void __init ide_probe_for_rz100x (void) /* called from ide.c */
{
struct pci_dev *dev = NULL;
- while (dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, dev))
+ while ((dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, dev))!=NULL)
init_rz1000 (dev, "RZ1000");
- while (dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, dev))
+ while ((dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, dev))!=NULL)
init_rz1000 (dev, "RZ1001");
}
diff --git a/drivers/block/sis5513.c b/drivers/block/sis5513.c
new file mode 100644
index 000000000..08bbb1c91
--- /dev/null
+++ b/drivers/block/sis5513.c
@@ -0,0 +1,417 @@
+/*
+ * linux/drivers/block/sis5513.c Version 0.06 July 11, 1999
+ *
+ * Copyright (C) 1999 Andre Hedrick
+ *
+ * drive_number
+ * = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+ * = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "ide_modes.h"
+
+static struct pci_dev *host_dev;
+
+#define SIS5513_DEBUG_DRIVE_INFO 0
+
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+/*
+ * ((id->word93 & 0x2000) && (HWIF(drive)->udma_four))
+ */
+static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
+{
+ struct hd_driveid *id = drive->id;
+ ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = hwif->pci_dev;
+
+ byte drive_pci, test1, test2, mask;
+ int err;
+
+ byte speed = 0x00;
+ byte unmask = 0xE0;
+ byte 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_620:
+ unmask = 0xF0;
+ four_two = 0x01;
+ default:
+ break;
+ }
+ }
+
+ 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 ide_dma_off;
+ }
+
+ pci_read_config_byte(dev, drive_pci, &test1);
+ pci_read_config_byte(dev, drive_pci|0x01, &test2);
+
+ if ((!ultra) && (test2 & 0x80)) {
+ pci_write_config_byte(dev, drive_pci|0x01, test2 & ~0x80);
+ pci_read_config_byte(dev, drive_pci|0x01, &test2);
+ }
+
+ if ((id->dma_ultra & 0x0010) && (ultra) && (udma_66) && (four_two)) {
+ 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;
+ }
+ 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)) {
+ 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;
+ }
+ if (!(test2 & 0xA0)) {
+ pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask);
+ pci_write_config_byte(dev, drive_pci|0x01, test2|0xA0);
+ }
+ speed = XFER_UDMA_3;
+ } else if ((id->dma_ultra & 0x0004) && (ultra)) {
+ 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;
+ }
+ mask = (four_two) ? 0xB0 : 0xA0;
+ if (!(test2 & mask)) {
+ pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask);
+ pci_write_config_byte(dev, drive_pci|0x01, test2|mask);
+ }
+ speed = XFER_UDMA_2;
+ } else if ((id->dma_ultra & 0x0002) && (ultra)) {
+ 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;
+ }
+ mask = (four_two) ? 0xD0 : 0xC0;
+ if (!(test2 & mask)) {
+ pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask);
+ pci_write_config_byte(dev, drive_pci|0x01, test2|mask);
+ }
+ speed = XFER_UDMA_1;
+ } else if ((id->dma_ultra & 0x0001) && (ultra)) {
+ 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;
+ }
+ if (!(test2 & unmask)) {
+ pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask);
+ pci_write_config_byte(dev, drive_pci|0x01, test2|unmask);
+ }
+ speed = XFER_UDMA_0;
+ } else if (id->dma_mword & 0x0004) {
+ if (!((id->dma_mword >> 8) & 4)) {
+ drive->id->dma_mword &= ~0x0F00;
+ drive->id->dma_mword |= 0x0404;
+ drive->id->dma_1word &= ~0x0F00;
+ }
+ speed = XFER_MW_DMA_2;
+ } else if (id->dma_mword & 0x0002) {
+ if (!((id->dma_mword >> 8) & 2)) {
+ drive->id->dma_mword &= ~0x0F00;
+ drive->id->dma_mword |= 0x0202;
+ drive->id->dma_1word &= ~0x0F00;
+ }
+ speed = XFER_MW_DMA_1;
+ } else if (id->dma_mword & 0x0001) {
+ if (!((id->dma_mword >> 8) & 1)) {
+ drive->id->dma_mword &= ~0x0F00;
+ drive->id->dma_mword |= 0x0101;
+ drive->id->dma_1word &= ~0x0F00;
+ }
+ speed = XFER_MW_DMA_0;
+ } else if (id->dma_1word & 0x0004) {
+ if (!((id->dma_1word >> 8) & 4)) {
+ drive->id->dma_1word &= ~0x0F00;
+ drive->id->dma_1word |= 0x0404;
+ drive->id->dma_mword &= ~0x0F00;
+ }
+ speed = XFER_SW_DMA_2;
+ } else if (id->dma_1word & 0x0002) {
+ if (!((id->dma_1word >> 8) & 2)) {
+ drive->id->dma_1word &= ~0x0F00;
+ drive->id->dma_1word |= 0x0202;
+ drive->id->dma_mword &= ~0x0F00;
+ }
+ speed = XFER_SW_DMA_1;
+ } else if (id->dma_1word & 0x0001) {
+ if (!((id->dma_1word >> 8) & 1)) {
+ drive->id->dma_1word &= ~0x0F00;
+ drive->id->dma_1word |= 0x0101;
+ drive->id->dma_mword &= ~0x0F00;
+ }
+ speed = XFER_SW_DMA_0;
+ } else {
+ return ((int) ide_dma_off_quietly);
+ }
+
+ err = ide_config_drive_speed(drive, speed);
+
+#if SIS5513_DEBUG_DRIVE_INFO
+ printk("%s: %s drive%d\n",
+ drive->name,
+ ide_xfer_verbose(speed),
+ drive_number);
+#endif /* SIS5513_DEBUG_DRIVE_INFO */
+
+ return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on :
+ ((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 config_drive_art_rwp (ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = hwif->pci_dev;
+
+ byte timing, pio, drive_pci, test1, test2;
+
+ unsigned short eide_pio_timing[6] = {600, 390, 240, 180, 120, 90};
+ unsigned short xfer_pio = drive->id->eide_pio_modes;
+ int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+
+ if (drive->media == ide_disk) {
+ struct pci_dev *dev = hwif->pci_dev;
+ byte reg4bh = 0;
+ byte rw_prefetch = (0x11 << drive_number);
+
+ pci_read_config_byte(dev, 0x4b, &reg4bh);
+ if ((reg4bh & rw_prefetch) != rw_prefetch)
+ pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch);
+ }
+
+ pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
+
+ if (xfer_pio> 4)
+ xfer_pio = 0;
+
+ if (drive->id->eide_pio_iordy > 0) {
+ for (xfer_pio = 5;
+ xfer_pio>0 &&
+ drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio];
+ xfer_pio--);
+ } else {
+ xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 :
+ (drive->id->eide_pio_modes & 2) ? 0x04 :
+ (drive->id->eide_pio_modes & 1) ? 0x03 : xfer_pio;
+ }
+
+ timing = (xfer_pio >= pio) ? xfer_pio : pio;
+
+/*
+ * Mode 0 Mode 1 Mode 2 Mode 3 Mode 4
+ * Active time 8T (240ns) 6T (180ns) 4T (120ns) 3T (90ns) 3T (90ns)
+ * 0x41 2:0 bits 000 110 100 011 011
+ * Recovery time 12T (360ns) 7T (210ns) 4T (120ns) 3T (90ns) 1T (30ns)
+ * 0x40 3:0 bits 0000 0111 0100 0011 0001
+ * Cycle time 20T (600ns) 13T (390ns) 8T (240ns) 6T (180ns) 4T (120ns)
+ */
+
+ 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;
+ }
+
+ pci_read_config_byte(dev, drive_pci, &test1);
+ pci_read_config_byte(dev, drive_pci|0x01, &test2);
+
+ /*
+ * Do a blanket clear of active and recovery timings.
+ */
+
+ test1 &= ~0x07;
+ test2 &= ~0x0F;
+
+ switch(timing) {
+ case 4: test1 |= 0x01;test2 |= 0x03;break;
+ case 3: test1 |= 0x03;test2 |= 0x03;break;
+ case 2: test1 |= 0x04;test2 |= 0x04;break;
+ case 1: test1 |= 0x07;test2 |= 0x06;break;
+ default: break;
+ }
+
+ pci_write_config_byte(dev, drive_pci, test1);
+ pci_write_config_byte(dev, drive_pci|0x01, test2);
+}
+
+static int config_drive_xfer_rate (ide_drive_t *drive)
+{
+ struct hd_driveid *id = drive->id;
+ ide_dma_action_t dma_func = ide_dma_off_quietly;
+
+ if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+ /* Consult the list of known "bad" drives */
+ if (ide_dmaproc(ide_dma_bad_drive, drive)) {
+ return HWIF(drive)->dmaproc(ide_dma_off, drive);
+ }
+
+ 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);
+ }
+ } else if ((ide_dmaproc(ide_dma_good_drive, drive)) &&
+ (id->eide_dma_time > 150)) {
+ /* Consult the list of known "good" drives */
+ dma_func = config_chipset_for_dma(drive, 0);
+ }
+ }
+ return HWIF(drive)->dmaproc(dma_func, drive);
+}
+
+/*
+ * sis5513_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
+ */
+int sis5513_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+ switch (func) {
+ case ide_dma_check:
+ config_drive_art_rwp(drive);
+ return config_drive_xfer_rate(drive);
+ default:
+ break;
+ }
+ return ide_dmaproc(func, drive); /* use standard DMA stuff */
+}
+
+unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name)
+{
+ struct pci_dev *host;
+ byte latency = 0, reg48h = 0;
+
+ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency);
+ pci_read_config_byte(dev, 0x48, &reg48h);
+
+ for (host = pci_devices; host; host=host->next) {
+ if (host->vendor == PCI_VENDOR_ID_SI &&
+ host->device == PCI_DEVICE_ID_SI_620) {
+ if (latency != 0x10)
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10);
+ host_dev = host;
+ printk("%s: Chipset Core ATA-66, SiS620\n", name);
+ printk("%s: Primary ATA-%s, Secondary ATA-%s Cable Detect\n",
+ name,
+ (reg48h & 0x10) ? "33" : "66",
+ (reg48h & 0x20) ? "33" : "66");
+ break;
+ } else if (host->vendor == PCI_VENDOR_ID_SI &&
+ host->device == PCI_DEVICE_ID_SI_530) {
+ host_dev = host;
+ printk("%s: Chipset Core ATA-66, SiS530\n", name);
+ printk("%s: Primary ATA-%s, Secondary ATA-%s Cable Detect\n",
+ name,
+ (reg48h & 0x10) ? "33" : "66",
+ (reg48h & 0x20) ? "33" : "66");
+ break;
+ } else if (host->vendor == PCI_VENDOR_ID_SI &&
+ host->device == PCI_DEVICE_ID_SI_5600) {
+ host_dev = host;
+ printk("SIS5600:%s Chipset Core ATA-33\n", name);
+ break;
+ } else if (host->vendor == PCI_VENDOR_ID_SI &&
+ host->device == PCI_DEVICE_ID_SI_5597) {
+ host_dev = host;
+ printk("SIS5597:%s Chipset Core ATA-33\n", name);
+ break;
+ }
+ }
+
+ if (host_dev) {
+ byte reg52h = 0;
+
+ pci_read_config_byte(dev, 0x52, &reg52h);
+ if (!(reg52h & 0x04))
+ pci_write_config_byte(dev, 0x52, reg52h|0x04);
+ }
+
+ return 0;
+}
+
+void __init ide_init_sis5513 (ide_hwif_t *hwif)
+{
+ byte reg48h = 0;
+ byte mask = hwif->channel ? 0x20 : 0x10;
+
+ pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);
+ hwif->irq = hwif->channel ? 15 : 14;
+
+ if (!(hwif->dma_base))
+ return;
+
+ if (host_dev) {
+ switch(host_dev->device) {
+ case PCI_DEVICE_ID_SI_530:
+ case PCI_DEVICE_ID_SI_620:
+ hwif->autodma = 1;
+ hwif->udma_four = (reg48h & mask) ? 0 : 1;
+ hwif->dmaproc = &sis5513_dmaproc;
+ return;
+ case PCI_DEVICE_ID_SI_5600:
+ case PCI_DEVICE_ID_SI_5597:
+ hwif->autodma = 1;
+ hwif->udma_four = 0;
+ hwif->dmaproc = &sis5513_dmaproc;
+ return;
+ default:
+ hwif->autodma = 0;
+ hwif->udma_four = 0;
+ return;
+ }
+ }
+}
diff --git a/drivers/block/sl82c105.c b/drivers/block/sl82c105.c
index 2f08740ea..d4e22d33b 100644
--- a/drivers/block/sl82c105.c
+++ b/drivers/block/sl82c105.c
@@ -1,3 +1,14 @@
+/*
+ * drivers/block/sl82c105.c
+ *
+ * SL82C105/Winbond 553 IDE driver
+ *
+ * Maintainer unknown.
+ *
+ * Drive tuning added from Corel Computer's kernel sources
+ * -- Russell King (15/11/98) linux@arm.linux.org.uk
+ */
+
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
@@ -15,9 +26,109 @@
#include "ide_modes.h"
+#ifdef CONFIG_ARCH_NETWINDER
+/*
+ * Convert a PIO mode and cycle time to the required on/off
+ * times for the interface. This has protection against run-away
+ * timings.
+ */
+static unsigned int get_timing_sl82c105(ide_pio_data_t *p)
+{
+ unsigned int cmd_on;
+ unsigned int cmd_off;
+
+ cmd_on = (ide_pio_timings[p->pio_mode].active_time + 29) / 30;
+ cmd_off = (p->cycle_time - 30 * cmd_on + 29) / 30;
+
+ if (cmd_on > 32)
+ cmd_on = 32;
+ if (cmd_on == 0)
+ cmd_on = 1;
+
+ if (cmd_off > 32)
+ cmd_off = 32;
+ if (cmd_off == 0)
+ cmd_off = 1;
+
+ return (cmd_on - 1) << 8 | (cmd_off - 1);
+}
+
+/*
+ * Tell the drive to enable the specified PIO mode.
+ * This should be in ide.c, maybe as a special command
+ * (see do_special).
+ */
+static int ide_set_drive_pio_mode(ide_drive_t *drive, byte pio)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+
+ if (pio > 2) {
+ /* FIXME: I don't believe that this SELECT_DRIVE is required,
+ * since ide.c only calls tuneproc from do_special, after
+ * the correct drive has been selected.
+ */
+ SELECT_DRIVE(hwif, drive);
+ if (IDE_CONTROL_REG)
+ OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
+ OUT_BYTE(0x08 | pio, IDE_NSECTOR_REG);
+ OUT_BYTE(0x03, IDE_FEATURE_REG);
+ OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG);
+
+ if (ide_wait_stat(drive, DRIVE_READY,
+ BUSY_STAT|DRQ_STAT|ERR_STAT, WAIT_CMD)) {
+ printk("%s: drive not ready for command\n",
+ drive->name);
+ return 1;
+ }
+ if (IDE_CONTROL_REG)
+ OUT_BYTE(drive->ctl, IDE_CONTROL_REG);
+ }
+
+ return 0;
+}
+
+/*
+ * We only deal with PIO mode here - DMA mode 'using_dma' is not
+ * initialised at the point that this function is called.
+ */
+static void tune_sl82c105(ide_drive_t *drive, byte pio)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = hwif->pci_dev;
+ ide_pio_data_t p;
+ unsigned int drv_ctrl = 0x909;
+
+ pio = ide_get_best_pio_mode(drive, pio, 5, &p);
+
+ if (!ide_set_drive_pio_mode(drive, pio)) {
+ drv_ctrl = get_timing_sl82c105(&p);
+
+ if (p.use_iordy)
+ drv_ctrl |= 0x40;
+ }
+
+ pci_write_config_word(dev,
+ (hwif->channel ? 0x4c : 0x44)
+ + (drive->select.b.unit ? 4 : 0),
+ drv_ctrl);
+
+ printk("%s: selected PIO mode %d (%dns)\n",
+ drive->name, p.pio_mode, p.cycle_time);
+}
+#endif
+
void ide_init_sl82c105(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
+
+#ifdef CONFIG_ARCH_NETWINDER
+ unsigned char ctrl_stat;
+
+ pci_read_config_byte(dev, 0x40, &ctrl_stat);
+ pci_write_config_byte(dev, 0x40, ctrl_stat | 0x33);
+
+ hwif->tuneproc = tune_sl82c105;
+#else
unsigned short t16;
unsigned int t32;
pci_read_config_word(dev, PCI_COMMAND, &t16);
@@ -33,4 +144,5 @@ void ide_init_sl82c105(ide_hwif_t *hwif)
printk("IDE control/status register: %08x\n",t32);
pci_write_config_dword(dev, 0x40, 0x10ff08a1);
#endif /* CONFIG_MBX */
+#endif
}
diff --git a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c
new file mode 100644
index 000000000..462ef7f26
--- /dev/null
+++ b/drivers/block/swim_iop.c
@@ -0,0 +1,674 @@
+/*
+ * Driver for the SWIM (Super Woz Integrated Machine) IOP
+ * floppy controller on the Macintosh IIfx and Quadra 900/950
+ *
+ * Written by Joshua M. Thompson (funaho@jurai.org)
+ * based on the SWIM3 driver (c) 1996 by Paul Mackerras.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * 1999-06-12 (jmt) - Initial implementation.
+ */
+
+/*
+ * -------------------
+ * Theory of Operation
+ * -------------------
+ *
+ * Since the SWIM IOP is message-driven we implement a simple request queue
+ * system. One outstanding request may be queued at any given time (this is
+ * an IOP limitation); only when that request has completed can a new request
+ * be sent.
+ */
+
+/* This has to be defined before some of the #includes below */
+
+#define MAJOR_NR FLOPPY_MAJOR
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/fd.h>
+#include <linux/blk.h>
+#include <linux/ioctl.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/mac_iop.h>
+#include <asm/swim_iop.h>
+
+#define DRIVER_VERSION "Version 0.1 (1999-06-12)"
+
+#define MAX_FLOPPIES 4
+
+#define IOCTL_MODE_BIT 8
+#define OPEN_WRITE_BIT 16
+
+enum swim_state {
+ idle,
+ available,
+ revalidating,
+ transferring,
+ ejecting
+};
+
+struct floppy_state {
+ enum swim_state state;
+ int drive_num; /* device number */
+ int secpercyl; /* disk geometry information */
+ int secpertrack;
+ int total_secs;
+ int write_prot; /* 1 if write-protected, 0 if not, -1 dunno */
+ int ref_count;
+ struct timer_list timeout;
+ int ejected;
+ struct wait_queue *wait;
+ int wanted;
+ int timeout_pending;
+};
+
+struct swim_iop_req {
+ int sent;
+ int complete;
+ __u8 command[32];
+ struct floppy_state *fs;
+ void (*done)(struct swim_iop_req *);
+};
+
+static struct swim_iop_req *current_req;
+static int floppy_count;
+
+static struct floppy_state floppy_states[MAX_FLOPPIES];
+
+static int floppy_blocksizes[2] = {512,512};
+static int floppy_sizes[2] = {2880,2880};
+
+static char *drive_names[7] = {
+ "not installed", /* DRV_NONE */
+ "unknown (1)", /* DRV_UNKNOWN */
+ "a 400K drive", /* DRV_400K */
+ "an 800K drive" /* DRV_800K */
+ "unknown (4)", /* ???? */
+ "an FDHD", /* DRV_FDHD */
+ "unknown (6)", /* ???? */
+ "an Apple HD20" /* DRV_HD20 */
+};
+
+int swimiop_init(void);
+static void swimiop_init_request(struct swim_iop_req *);
+static int swimiop_send_request(struct swim_iop_req *);
+static void swimiop_receive(struct iop_msg *, struct pt_regs *);
+static void swimiop_status_update(int, struct swim_drvstatus *);
+static int swimiop_eject(struct floppy_state *fs);
+
+static ssize_t floppy_read(struct file *filp, char *buf,
+ size_t count, loff_t *ppos);
+static ssize_t floppy_write(struct file *filp, const char *buf,
+ size_t count, loff_t *ppos);
+static int floppy_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long param);
+static int floppy_open(struct inode *inode, struct file *filp);
+static int floppy_release(struct inode *inode, struct file *filp);
+static int floppy_check_change(kdev_t dev);
+static int floppy_revalidate(kdev_t dev);
+static int grab_drive(struct floppy_state *fs, enum swim_state state,
+ int interruptible);
+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 start_request(struct floppy_state *fs);
+
+static struct file_operations floppy_fops = {
+ NULL, /* lseek */
+ floppy_read, /* read */
+ floppy_write, /* write */
+ NULL, /* readdir */
+ NULL, /* poll */
+ floppy_ioctl, /* ioctl */
+ NULL, /* mmap */
+ floppy_open, /* open */
+ NULL, /* flush */
+ floppy_release, /* release */
+ block_fsync, /* fsync */
+ NULL, /* fasync */
+ floppy_check_change, /* check_media_change */
+ floppy_revalidate, /* revalidate */
+};
+
+/*
+ * SWIM IOP initialization
+ */
+
+int swimiop_init(void)
+{
+ volatile struct swim_iop_req req;
+ struct swimcmd_status *cmd = (struct swimcmd_status *) &req.command[0];
+ struct swim_drvstatus *ds = &cmd->status;
+ struct floppy_state *fs;
+ int i;
+
+ current_req = NULL;
+ floppy_count = 0;
+
+ if (!iop_ism_present) return -ENODEV;
+
+ if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) {
+ printk(KERN_ERR "SWIM-IOP: Unable to get major %d for floppy\n",
+ MAJOR_NR);
+ return -EBUSY;
+ }
+ blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blksize_size[MAJOR_NR] = floppy_blocksizes;
+ blk_size[MAJOR_NR] = floppy_sizes;
+
+ printk("SWIM-IOP: %s by Joshua M. Thompson (funaho@jurai.org)\n",
+ DRIVER_VERSION);
+
+ if (iop_listen(SWIM_IOP, SWIM_CHAN, swimiop_receive, "SWIM") != 0) {
+ printk(KERN_ERR "SWIM-IOP: IOP channel already in use; can't initialize.\n");
+ return -EBUSY;
+ }
+
+ printk(KERN_ERR "SWIM_IOP: probing for installed drives.\n");
+
+ for (i = 0 ; i < MAX_FLOPPIES ; i++) {
+ memset(&floppy_states[i], 0, sizeof(struct floppy_state));
+ fs = &floppy_states[floppy_count];
+
+ swimiop_init_request(&req);
+ cmd->code = CMD_STATUS;
+ cmd->drive_num = i + 1;
+ if (swimiop_send_request(&req) != 0) continue;
+ while (!req.complete);
+ if (cmd->error != 0) {
+ printk(KERN_ERR "SWIM-IOP: probe on drive %d returned error %d\n", i, (uint) cmd->error);
+ continue;
+ }
+ if (ds->installed != 0x01) continue;
+ printk("SWIM-IOP: drive %d is %s (%s, %s, %s, %s)\n", i,
+ drive_names[ds->info.type],
+ ds->info.external? "ext" : "int",
+ ds->info.scsi? "scsi" : "floppy",
+ ds->info.fixed? "fixed" : "removable",
+ ds->info.secondary? "secondary" : "primary");
+ swimiop_status_update(floppy_count, ds);
+ fs->state = idle;
+
+ init_timer(&fs->timeout);
+ floppy_count++;
+ }
+ printk("SWIM-IOP: detected %d installed drives.\n", floppy_count);
+
+ do_floppy = NULL;
+
+ return 0;
+}
+
+static void swimiop_init_request(struct swim_iop_req *req)
+{
+ req->sent = 0;
+ req->complete = 0;
+ req->done = NULL;
+}
+
+static int swimiop_send_request(struct swim_iop_req *req)
+{
+ unsigned long cpu_flags;
+ int err;
+
+ /* It's doubtful an interrupt routine would try to send */
+ /* a SWIM request, but I'd rather play it safe here. */
+
+ save_flags(cpu_flags);
+ cli();
+
+ if (current_req != NULL) {
+ restore_flags(cpu_flags);
+ return -ENOMEM;
+ }
+
+ current_req = req;
+
+ /* Interrupts should be back on for iop_send_message() */
+
+ restore_flags(cpu_flags);
+
+ err = iop_send_message(SWIM_IOP, SWIM_CHAN, (void *) req,
+ sizeof(req->command), (__u8 *) &req->command[0],
+ swimiop_receive);
+
+ /* No race condition here; we own current_req at this point */
+
+ if (err) {
+ current_req = NULL;
+ } else {
+ req->sent = 1;
+ }
+ return err;
+}
+
+/*
+ * Receive a SWIM message from the IOP.
+ *
+ * This will be called in two cases:
+ *
+ * 1. A message has been successfully sent to the IOP.
+ * 2. An unsolicited message was received from the IOP.
+ */
+
+void swimiop_receive(struct iop_msg *msg, struct pt_regs *regs)
+{
+ struct swim_iop_req *req;
+ struct swimmsg_status *sm;
+ struct swim_drvstatus *ds;
+
+ req = current_req;
+
+ switch(msg->status) {
+ case IOP_MSGSTATUS_COMPLETE:
+ memcpy(&req->command[0], &msg->reply[0], sizeof(req->command));
+ req->complete = 1;
+ if (req->done) (*req->done)(req);
+ current_req = NULL;
+ break;
+ case IOP_MSGSTATUS_UNSOL:
+ sm = (struct swimmsg_status *) &msg->message[0];
+ ds = &sm->status;
+ swimiop_status_update(sm->drive_num, ds);
+ iop_complete_message(msg);
+ break;
+ }
+}
+
+static void swimiop_status_update(int drive_num, struct swim_drvstatus *ds)
+{
+ struct floppy_state *fs = &floppy_states[drive_num];
+
+ fs->write_prot = (ds->write_prot == 0x80);
+ if ((ds->disk_in_drive != 0x01) && (ds->disk_in_drive != 0x02)) {
+ fs->ejected = 1;
+ } else {
+ fs->ejected = 0;
+ }
+ switch(ds->info.type) {
+ case DRV_400K:
+ fs->secpercyl = 10;
+ fs->secpertrack = 10;
+ fs->total_secs = 800;
+ break;
+ case DRV_800K:
+ fs->secpercyl = 20;
+ fs->secpertrack = 10;
+ fs->total_secs = 1600;
+ break;
+ case DRV_FDHD:
+ fs->secpercyl = 36;
+ fs->secpertrack = 18;
+ fs->total_secs = 2880;
+ break;
+ default:
+ fs->secpercyl = 0;
+ fs->secpertrack = 0;
+ fs->total_secs = 0;
+ break;
+ }
+}
+
+static int swimiop_eject(struct floppy_state *fs)
+{
+ int err, n;
+ struct swim_iop_req req;
+ struct swimcmd_eject *cmd = (struct swimcmd_eject *) &req.command[0];
+
+ err = grab_drive(fs, ejecting, 1);
+ if (err) return err;
+
+ swimiop_init_request(&req);
+ cmd->code = CMD_EJECT;
+ cmd->drive_num = fs->drive_num;
+ err = swimiop_send_request(&req);
+ if (err) {
+ release_drive(fs);
+ return err;
+ }
+ for (n = 2*HZ; n > 0; --n) {
+ if (req.complete) break;
+ if (signal_pending(current)) {
+ err = -EINTR;
+ break;
+ }
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(1);
+ }
+ release_drive(fs);
+ return cmd->error;
+}
+
+static ssize_t floppy_read(struct file *filp, char *buf,
+ size_t count, loff_t *ppos)
+{
+ struct inode *inode = filp->f_dentry->d_inode;
+ struct floppy_state *fs;
+ int devnum = MINOR(inode->i_rdev);
+
+ if (devnum >= floppy_count)
+ return -ENODEV;
+
+ fs = &floppy_states[devnum];
+ if (fs->ejected)
+ return -ENXIO;
+ return block_read(filp, buf, count, ppos);
+}
+
+static ssize_t floppy_write(struct file * filp, const char * buf,
+ size_t count, loff_t *ppos)
+{
+ struct inode * inode = filp->f_dentry->d_inode;
+ struct floppy_state *fs;
+ int devnum = MINOR(inode->i_rdev);
+
+ if (devnum >= floppy_count)
+ return -ENODEV;
+ check_disk_change(inode->i_rdev);
+ fs = &floppy_states[devnum];
+ if (fs->ejected)
+ return -ENXIO;
+ if (fs->write_prot)
+ return -EROFS;
+ return block_write(filp, buf, count, ppos);
+}
+
+static struct floppy_struct floppy_type =
+ { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL }; /* 7 1.44MB 3.5" */
+
+static int floppy_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long param)
+{
+ struct floppy_state *fs;
+ int err;
+ int devnum = MINOR(inode->i_rdev);
+
+ if (devnum >= floppy_count)
+ return -ENODEV;
+
+ if (((cmd & 0x40) && !(filp && (filp->f_mode & IOCTL_MODE_BIT))) ||
+ ((cmd & 0x80) && !suser()))
+ return -EPERM;
+
+ fs = &floppy_states[devnum];
+
+ switch (cmd) {
+ case FDEJECT:
+ if (fs->ref_count != 1)
+ return -EBUSY;
+ err = swimiop_eject(fs);
+ return err;
+ case FDGETPRM:
+ err = copy_to_user((void *) param, (void *) &floppy_type,
+ sizeof(struct floppy_struct));
+ return err;
+ }
+ return -ENOIOCTLCMD;
+}
+
+static int floppy_open(struct inode *inode, struct file *filp)
+{
+ struct floppy_state *fs;
+ int err;
+ int devnum = MINOR(inode->i_rdev);
+
+ if (devnum >= floppy_count)
+ return -ENODEV;
+ if (filp == 0)
+ return -EIO;
+
+ fs = &floppy_states[devnum];
+ err = 0;
+ if (fs->ref_count == -1 || filp->f_flags & O_EXCL) return -EBUSY;
+
+ if (err == 0 && (filp->f_flags & O_NDELAY) == 0
+ && (filp->f_mode & 3)) {
+ check_disk_change(inode->i_rdev);
+ if (fs->ejected)
+ err = -ENXIO;
+ }
+
+ if (err == 0 && (filp->f_mode & 2)) {
+ if (fs->write_prot)
+ err = -EROFS;
+ }
+
+ if (err) return err;
+
+ if (filp->f_flags & O_EXCL)
+ fs->ref_count = -1;
+ else
+ ++fs->ref_count;
+
+ /* Allow ioctls if we have write-permissions even if read-only open */
+ if ((filp->f_mode & 2) || (permission(inode, 2) == 0))
+ filp->f_mode |= IOCTL_MODE_BIT;
+ if (filp->f_mode & 2)
+ filp->f_mode |= OPEN_WRITE_BIT;
+
+ return 0;
+}
+
+static int floppy_release(struct inode *inode, struct file *filp)
+{
+ struct floppy_state *fs;
+ int devnum = MINOR(inode->i_rdev);
+
+ if (devnum >= floppy_count)
+ return -ENODEV;
+
+ /*
+ * If filp is NULL, we're being called from blkdev_release
+ * or after a failed mount attempt. In the former case the
+ * device has already been sync'ed, and in the latter no
+ * sync is required. Otherwise, sync if filp is writable.
+ */
+ if (filp && (filp->f_mode & (2 | OPEN_WRITE_BIT)))
+ block_fsync (filp, filp->f_dentry);
+
+ fs = &floppy_states[devnum];
+ if (fs->ref_count > 0) fs->ref_count--;
+ return 0;
+}
+
+static int floppy_check_change(kdev_t dev)
+{
+ struct floppy_state *fs;
+ int devnum = MINOR(dev);
+
+ if (MAJOR(dev) != MAJOR_NR || (devnum >= floppy_count))
+ return 0;
+
+ fs = &floppy_states[devnum];
+ return fs->ejected;
+}
+
+static int floppy_revalidate(kdev_t dev)
+{
+ struct floppy_state *fs;
+ int devnum = MINOR(dev);
+
+ if (MAJOR(dev) != MAJOR_NR || (devnum >= floppy_count))
+ return 0;
+
+ fs = &floppy_states[devnum];
+
+ grab_drive(fs, revalidating, 0);
+ /* yadda, yadda */
+ release_drive(fs);
+
+ return 0;
+}
+
+static void floppy_off(unsigned int nr)
+{
+}
+
+static int grab_drive(struct floppy_state *fs, enum swim_state state,
+ int interruptible)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ if (fs->state != idle) {
+ ++fs->wanted;
+ while (fs->state != available) {
+ if (interruptible && signal_pending(current)) {
+ --fs->wanted;
+ restore_flags(flags);
+ return -EINTR;
+ }
+ interruptible_sleep_on(&fs->wait);
+ }
+ --fs->wanted;
+ }
+ fs->state = state;
+ restore_flags(flags);
+ return 0;
+}
+
+static void release_drive(struct floppy_state *fs)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ fs->state = idle;
+ start_request(fs);
+ restore_flags(flags);
+}
+
+static void set_timeout(struct floppy_state *fs, int nticks,
+ void (*proc)(unsigned long))
+{
+ unsigned long flags;
+
+ save_flags(flags); cli();
+ if (fs->timeout_pending)
+ del_timer(&fs->timeout);
+ fs->timeout.expires = jiffies + nticks;
+ fs->timeout.function = proc;
+ fs->timeout.data = (unsigned long) fs;
+ add_timer(&fs->timeout);
+ fs->timeout_pending = 1;
+ restore_flags(flags);
+}
+
+static void do_fd_request(void)
+{
+ int i;
+
+ for (i = 0 ; i < floppy_count ; i++) {
+ start_request(&floppy_states[i]);
+ }
+}
+
+static void fd_request_complete(struct swim_iop_req *req)
+{
+ struct floppy_state *fs = req->fs;
+ struct swimcmd_rw *cmd = (struct swimcmd_rw *) &req->command[0];
+
+ del_timer(&fs->timeout);
+ fs->timeout_pending = 0;
+ fs->state = idle;
+ if (cmd->error) {
+ printk(KERN_ERR "SWIM-IOP: error %d on read/write request.\n", cmd->error);
+ end_request(0);
+ } else {
+ CURRENT->sector += cmd->num_blocks;
+ CURRENT->current_nr_sectors -= cmd->num_blocks;
+ if (CURRENT->current_nr_sectors <= 0) {
+ end_request(1);
+ return;
+ }
+ }
+ start_request(fs);
+}
+
+static void fd_request_timeout(unsigned long data)
+{
+ struct floppy_state *fs = (struct floppy_state *) data;
+
+ fs->timeout_pending = 0;
+ end_request(0);
+ fs->state = idle;
+}
+
+static void start_request(struct floppy_state *fs)
+{
+ volatile struct swim_iop_req req;
+ struct swimcmd_rw *cmd = (struct swimcmd_rw *) &req.command[0];
+
+ if (fs->state == idle && fs->wanted) {
+ fs->state = available;
+ wake_up(&fs->wait);
+ return;
+ }
+ while (CURRENT && fs->state == idle) {
+ if (MAJOR(CURRENT->rq_dev) != MAJOR_NR)
+ panic(DEVICE_NAME ": request list destroyed");
+ if (CURRENT->bh && !buffer_locked(CURRENT->bh))
+ panic(DEVICE_NAME ": block not locked");
+#if 0
+ printk("do_fd_req: dev=%x cmd=%d sec=%ld nr_sec=%ld buf=%p\n",
+ kdev_t_to_nr(CURRENT->rq_dev), CURRENT->cmd,
+ CURRENT->sector, CURRENT->nr_sectors, CURRENT->buffer);
+ printk(" rq_status=%d errors=%d current_nr_sectors=%ld\n",
+ CURRENT->rq_status, CURRENT->errors, CURRENT->current_nr_sectors);
+#endif
+
+ if (CURRENT->sector < 0 || CURRENT->sector >= fs->total_secs) {
+ end_request(0);
+ continue;
+ }
+ if (CURRENT->current_nr_sectors == 0) {
+ end_request(1);
+ continue;
+ }
+ if (fs->ejected) {
+ end_request(0);
+ continue;
+ }
+
+ swimiop_init_request(&req);
+ req.fs = fs;
+ req.done = fd_request_complete;
+
+ if (CURRENT->cmd == WRITE) {
+ if (fs->write_prot) {
+ end_request(0);
+ continue;
+ }
+ cmd->code = CMD_WRITE;
+ } else {
+ cmd->code = CMD_READ;
+
+ }
+ cmd->drive_num = fs->drive_num;
+ cmd->buffer = CURRENT->buffer;
+ cmd->first_block = CURRENT->sector;
+ cmd->num_blocks = CURRENT->current_nr_sectors;
+
+ if (swimiop_send_request(&req)) {
+ end_request(0);
+ continue;
+ }
+
+ set_timeout(fs, HZ*CURRENT->current_nr_sectors,
+ fd_request_timeout);
+
+ fs->state = transferring;
+ }
+}
diff --git a/drivers/block/trm290.c b/drivers/block/trm290.c
index c4f96d492..ad6a75d0f 100644
--- a/drivers/block/trm290.c
+++ b/drivers/block/trm290.c
@@ -212,7 +212,7 @@ static int trm290_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
/*
* Invoked from ide-dma.c at boot time.
*/
-__initfunc(void ide_init_trm290 (ide_hwif_t *hwif))
+void __init ide_init_trm290 (ide_hwif_t *hwif)
{
unsigned int cfgbase = 0;
unsigned long flags;
@@ -220,7 +220,7 @@ __initfunc(void ide_init_trm290 (ide_hwif_t *hwif))
struct pci_dev *dev = hwif->pci_dev;
hwif->chipset = ide_trm290;
- cfgbase = dev->base_address[4];
+ cfgbase = dev->resource[4].start;
if ((dev->class & 5) && cfgbase)
{
hwif->config_data = cfgbase & PCI_BASE_ADDRESS_IO_MASK;
@@ -263,7 +263,16 @@ __initfunc(void ide_init_trm290 (ide_hwif_t *hwif))
old = inw(hwif->config_data) & ~1;
if (old != compat && inb(old+2) == 0xff) {
compat += (next_offset += 0x400); /* leave lower 10 bits untouched */
- hwif->io_ports[IDE_CONTROL_OFFSET] = compat + 2; /* FIXME: should do a check_region */
+#if 1
+ if (ide_check_region(compat + 2, 1))
+ printk("Aieee %s: ide_check_region failure at 0x%04x\n", hwif->name, (compat + 2));
+ /*
+ * The region check is not needed; however.........
+ * Since this is the checked in ide-probe.c,
+ * this is only an assignment.
+ */
+#endif
+ hwif->io_ports[IDE_CONTROL_OFFSET] = compat + 2;
outw(compat|1, hwif->config_data);
printk("%s: control basereg workaround: old=0x%04x, new=0x%04x\n", hwif->name, old, inw(hwif->config_data) & ~1);
}
diff --git a/drivers/block/via82c586.c b/drivers/block/via82c586.c
index 7dd6eb321..e5697014e 100644
--- a/drivers/block/via82c586.c
+++ b/drivers/block/via82c586.c
@@ -1,8 +1,8 @@
/*
- * linux/drivers/block/via82c586.c Version 0.03 Nov. 19, 1998
+ * linux/drivers/block/via82c586.c Version 0.04 July 11, 1999
*
* Copyright (C) 1998 Michel Aubry, Maintainer
- * Copyright (C) 1998 Andre Hedrick, Integrater
+ * Copyright (C) 1998 Andre Hedrick, Maintainer
*
* The VIA MVP-3 is reported OK with UDMA.
* The TX Pro III is also reported OK with UDMA.
@@ -57,6 +57,9 @@
#include <asm/io.h>
+static struct pci_dev *host_dev;
+static struct pci_dev *isa_dev;
+
#define DISPLAY_VIA_TIMINGS
#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS)
@@ -438,6 +441,137 @@ static int via_set_fifoconfig(ide_hwif_t *hwif)
return 0;
}
+unsigned int __init pci_init_via82c568 (struct pci_dev *dev, const char *name)
+{
+ struct pci_dev *host;
+ struct pci_dev *isa;
+
+ byte revision = 0;
+
+ for (host = pci_devices; host; host=host->next) {
+ if (host->vendor == PCI_VENDOR_ID_VIA &&
+ host->device == PCI_DEVICE_ID_VIA_82C585) {
+ host_dev = host;
+ printk("VT 82C585 Apollo VP1/VPX");
+ for (isa = pci_devices; isa; isa=isa->next) {
+ if (isa->vendor == PCI_VENDOR_ID_VIA &&
+ isa->device == PCI_DEVICE_ID_VIA_82C586_1) {
+ isa_dev = isa;
+ pci_read_config_byte(isa_dev, 0x0d, &revision);
+ if (revision >= 0x20)
+ printk(" Chipset Core ATA-33");
+ break;
+ }
+ }
+ printk("\n");
+ break;
+ } else if (host->vendor == PCI_VENDOR_ID_VIA &&
+ host->device == PCI_DEVICE_ID_VIA_82C595) {
+ host_dev = host;
+ printk("VT 82C595 Apollo VP2");
+ for (isa = pci_devices; isa; isa=isa->next) {
+ if (isa->vendor == PCI_VENDOR_ID_VIA &&
+ isa->device == PCI_DEVICE_ID_VIA_82C586_1) {
+ isa_dev = isa;
+ pci_read_config_byte(isa_dev, 0x0d, &revision);
+ if (revision >= 0x20)
+ printk(" Chipset Core ATA-33");
+ break;
+ }
+ }
+ printk("\n");
+ break;
+ } else if (host->vendor == PCI_VENDOR_ID_VIA &&
+ host->device == PCI_DEVICE_ID_VIA_82C597_0) {
+ host_dev = host;
+ printk("VT 82C597 Apollo VP3");
+ for (isa = pci_devices; isa; isa=isa->next) {
+ if (isa->vendor == PCI_VENDOR_ID_VIA &&
+ isa->device == PCI_DEVICE_ID_VIA_82C586_1) {
+ isa_dev = isa;
+ pci_read_config_byte(isa_dev, 0x0d, &revision);
+ if (revision >= 0x20)
+ printk(" Chipset Core ATA-33");
+ break;
+ }
+ }
+ printk("\n");
+ break;
+ } else if (host->vendor == PCI_VENDOR_ID_VIA &&
+ host->device == PCI_DEVICE_ID_VIA_82C598_0) {
+ host_dev = host;
+ printk("VT 82C598 Apollo MVP3");
+ for (isa = pci_devices; isa; isa=isa->next) {
+ if (isa->vendor == PCI_VENDOR_ID_VIA &&
+ isa->device == PCI_DEVICE_ID_VIA_82C586_1) {
+ isa_dev = isa;
+ pci_read_config_byte(isa_dev, 0x0d, &revision);
+ if (revision >= 0x20)
+ printk(" Chipset Core ATA-33");
+ break;
+ } else if (isa->vendor == PCI_VENDOR_ID_VIA &&
+ isa->device == PCI_DEVICE_ID_VIA_82C596) {
+ isa_dev = isa;
+ printk(" Chipset Core ATA-33");
+ break;
+ }
+ }
+ printk("\n");
+ break;
+ } else if (host->vendor == PCI_VENDOR_ID_VIA &&
+ host->device == PCI_DEVICE_ID_VIA_82C680) {
+ host_dev = host;
+ printk("VT 82C680 Apollo P6");
+ for (isa = pci_devices; isa; isa=isa->next) {
+ if (isa->vendor == PCI_VENDOR_ID_VIA &&
+ isa->device == PCI_DEVICE_ID_VIA_82C586_1) {
+ isa_dev = isa;
+ pci_read_config_byte(isa_dev, 0x0d, &revision);
+ if (revision >= 0x20)
+ printk(" Chipset Core ATA-33");
+ break;
+ }
+ }
+ printk("\n");
+ break;
+ } else if (host->vendor == PCI_VENDOR_ID_VIA &&
+ host->device == PCI_DEVICE_ID_VIA_82C691) {
+ host_dev = host;
+ printk("VT 82C691 Apollo Pro");
+ for (isa = pci_devices; isa; isa=isa->next) {
+ if (isa->vendor == PCI_VENDOR_ID_VIA &&
+ isa->device == PCI_DEVICE_ID_VIA_82C596) {
+ isa_dev = isa;
+ printk(" Chipset Core ATA-33");
+ break;
+ }
+ }
+ printk("\n");
+ break;
+ } else if (host->vendor == PCI_VENDOR_ID_VIA &&
+ host->device == PCI_DEVICE_ID_VIA_82C693) {
+ host_dev = host;
+ printk("VT 82C693 Apollo Pro Plus");
+ for (isa = pci_devices; isa; isa=isa->next) {
+ if (isa->vendor == PCI_VENDOR_ID_VIA &&
+ isa->device == PCI_DEVICE_ID_VIA_82C596) {
+ isa_dev = isa;
+ printk(" Chipset Core ATA-33");
+ break;
+ }
+ }
+ printk("\n");
+ break;
+ }
+ }
+ return 0;
+}
+
+void __init ide_init_via82c586 (ide_hwif_t *hwif)
+{
+ set_via_timings(hwif);
+}
+
/*
* ide_dmacapable_via82c568(ide_hwif_t *, unsigned long)
* checks if channel "channel" of if hwif is dma
@@ -464,9 +598,3 @@ void ide_dmacapable_via82c586 (ide_hwif_t *hwif, unsigned long dmabase)
ide_setup_dma(hwif, dmabase, 8);
}
}
-
-__initfunc(void ide_init_via82c586 (ide_hwif_t *hwif))
-{
- set_via_timings(hwif);
-}
-
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index 04c88fb08..44e8317f0 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -55,7 +55,7 @@
#define XD_DONT_USE_DMA 0 /* Initial value. may be overriden using
"nodma" module option */
-#define XD_INIT_DISK_DELAY 3 /* 30 ms delay during disk initialization */
+#define XD_INIT_DISK_DELAY (30*HZ/1000) /* 30 ms delay during disk initialization */
/* Above may need to be increased if a problem with the 2nd drive detection
(ST11M controller) or resetting a controler (WD) appears */
@@ -179,7 +179,7 @@ static volatile u_char xd_error;
static int nodma = XD_DONT_USE_DMA;
/* xd_init: register the block device number and set up pointer tables */
-__initfunc(int xd_init (void))
+int __init xd_init (void)
{
if (register_blkdev(MAJOR_NR,"xd",&xd_fops)) {
printk("xd: Unable to get major number %d\n",MAJOR_NR);
@@ -194,7 +194,7 @@ __initfunc(int xd_init (void))
}
/* xd_detect: scan the possible BIOS ROM locations for the signature strings */
-__initfunc(static u_char xd_detect (u_char *controller, unsigned int *address))
+static u_char __init xd_detect (u_char *controller, unsigned int *address)
{
u_char i,j,found = 0;
@@ -218,7 +218,7 @@ __initfunc(static u_char xd_detect (u_char *controller, unsigned int *address))
/* xd_geninit: grab the IRQ and DMA channel, initialise the drives */
/* and set up the "raw" device entries in the table */
-__initfunc(static void xd_geninit (struct gendisk *ignored))
+static void __init xd_geninit (struct gendisk *ignored)
{
u_char i,controller;
unsigned int address;
@@ -686,7 +686,7 @@ static u_int xd_command (u_char *command,u_char mode,u_char *indata,u_char *outd
return (csb & CSB_ERROR);
}
-__initfunc(static u_char xd_initdrives (void (*init_drive)(u_char drive)))
+static u_char __init xd_initdrives (void (*init_drive)(u_char drive))
{
u_char cmdblk[6],i,count = 0;
@@ -708,14 +708,14 @@ __initfunc(static u_char xd_initdrives (void (*init_drive)(u_char drive)))
return (count);
}
-__initfunc(static void xd_manual_geo_set (u_char drive))
+static void __init xd_manual_geo_set (u_char drive)
{
xd_info[drive].heads = (u_char)(xd_geo[3 * drive + 1]);
xd_info[drive].cylinders = (u_short)(xd_geo[3 * drive]);
xd_info[drive].sectors = (u_char)(xd_geo[3 * drive + 2]);
}
-__initfunc(static void xd_dtc_init_controller (unsigned int address))
+static void __init xd_dtc_init_controller (unsigned int address)
{
switch (address) {
case 0x00000:
@@ -732,7 +732,7 @@ __initfunc(static void xd_dtc_init_controller (unsigned int address))
}
-__initfunc(static void xd_dtc5150cx_init_drive (u_char drive))
+static void __init xd_dtc5150cx_init_drive (u_char drive)
{
/* values from controller's BIOS - BIOS chip may be removed */
static u_short geometry_table[][4] = {
@@ -779,7 +779,7 @@ __initfunc(static void xd_dtc5150cx_init_drive (u_char drive))
xd_recalibrate(drive);
}
-__initfunc(static void xd_dtc_init_drive (u_char drive))
+static void __init xd_dtc_init_drive (u_char drive)
{
u_char cmdblk[6],buf[64];
@@ -806,7 +806,7 @@ __initfunc(static void xd_dtc_init_drive (u_char drive))
printk("xd_dtc_init_drive: error reading geometry for xd%c\n", 'a'+drive);
}
-__initfunc(static void xd_wd_init_controller (unsigned int address))
+static void __init xd_wd_init_controller (unsigned int address)
{
switch (address) {
case 0x00000:
@@ -828,7 +828,7 @@ __initfunc(static void xd_wd_init_controller (unsigned int address))
sleep_on(&xdc_wait);
}
-__initfunc(static void xd_wd_init_drive (u_char drive))
+static void __init xd_wd_init_drive (u_char drive)
{
/* values from controller's BIOS - BIOS may be disabled */
static u_short geometry_table[][4] = {
@@ -912,7 +912,7 @@ __initfunc(static void xd_wd_init_drive (u_char drive))
}
-__initfunc(static void xd_seagate_init_controller (unsigned int address))
+static void __init xd_seagate_init_controller (unsigned int address)
{
switch (address) {
case 0x00000:
@@ -928,7 +928,7 @@ __initfunc(static void xd_seagate_init_controller (unsigned int address))
outb(0,XD_RESET); /* reset the controller */
}
-__initfunc(static void xd_seagate_init_drive (u_char drive))
+static void __init xd_seagate_init_drive (u_char drive)
{
u_char cmdblk[6],buf[0x200];
@@ -944,7 +944,7 @@ __initfunc(static void xd_seagate_init_drive (u_char drive))
}
/* Omti support courtesy Dirk Melchers */
-__initfunc(static void xd_omti_init_controller (unsigned int address))
+static void __init xd_omti_init_controller (unsigned int address)
{
switch (address) {
case 0x00000:
@@ -961,7 +961,7 @@ __initfunc(static void xd_omti_init_controller (unsigned int address))
outb(0,XD_RESET); /* reset the controller */
}
-__initfunc(static void xd_omti_init_drive (u_char drive))
+static void __init xd_omti_init_drive (u_char drive)
{
/* gets infos from drive */
xd_override_init_drive(drive);
@@ -971,7 +971,7 @@ __initfunc(static void xd_omti_init_drive (u_char drive))
}
/* Xebec support (AK) */
-__initfunc(static void xd_xebec_init_controller (unsigned int address))
+static void __init xd_xebec_init_controller (unsigned int address)
{
/* iobase may be set manually in range 0x300 - 0x33C
irq may be set manually to 2(9),3,4,5,6,7
@@ -1004,7 +1004,7 @@ If you need non-standard settings use the xd=... command */
sleep_on(&xdc_wait);
}
-__initfunc(static void xd_xebec_init_drive (u_char drive))
+static void __init xd_xebec_init_drive (u_char drive)
{
/* values from controller's BIOS - BIOS chip may be removed */
static u_short geometry_table[][5] = {
@@ -1047,7 +1047,7 @@ __initfunc(static void xd_xebec_init_drive (u_char drive))
/* xd_override_init_drive: this finds disk geometry in a "binary search" style, narrowing in on the "correct" number of heads
etc. by trying values until it gets the highest successful value. Idea courtesy Salvador Abreu (spa@fct.unl.pt). */
-__initfunc(static void xd_override_init_drive (u_char drive))
+static void __init xd_override_init_drive (u_char drive)
{
u_short min[] = { 0,0,0 },max[] = { 16,1024,64 },test[] = { 0,0,0 };
u_char cmdblk[6],i;
@@ -1074,7 +1074,7 @@ __initfunc(static void xd_override_init_drive (u_char drive))
}
/* xd_setup: initialise controler from command line parameters */
-__initfunc(void xd_setup (char *command,int *integers))
+void __init xd_setup (char *command,int *integers)
{
switch (integers[0]) {
case 4: if (integers[4] < 0)
@@ -1097,7 +1097,7 @@ __initfunc(void xd_setup (char *command,int *integers))
#ifndef MODULE
/* xd_manual_geo_init: initialise drive geometry from command line parameters
(used only for WD drives) */
-__initfunc(void xd_manual_geo_init (char *command,int *integers))
+void __init xd_manual_geo_init (char *command,int *integers)
{
int i;
if (integers[0]%3 != 0) {
@@ -1110,7 +1110,7 @@ __initfunc(void xd_manual_geo_init (char *command,int *integers))
#endif /* MODULE */
/* xd_setparam: set the drive characteristics */
-__initfunc(static void xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc))
+static void __init xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc)
{
u_char cmdblk[14];
@@ -1204,5 +1204,10 @@ void cleanup_module(void)
xd_dma_mem_free((unsigned long)xd_dma_buffer, xd_maxsectors * 0x200);
}
}
+#else
+
+__setup ("xd=", xd_setup);
+__setup ("xd_geo=", xd_manual_geo_init);
+
#endif /* MODULE */
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index f863a8326..f75150e4a 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -27,28 +27,22 @@
#define MAJOR_NR Z2RAM_MAJOR
-#include <linux/config.h>
#include <linux/major.h>
#include <linux/malloc.h>
#include <linux/blk.h>
#include <linux/init.h>
-
-#if defined(MODULE)
#include <linux/module.h>
-#endif
#include <asm/setup.h>
#include <asm/bitops.h>
#include <asm/amigahw.h>
-#ifdef CONFIG_APUS
#include <asm/pgtable.h>
#include <asm/io.h>
-#endif
#include <linux/zorro.h>
-extern int num_memory;
-extern struct mem_info memory[NUM_MEMINFO];
+extern int m68k_realnum_memory;
+extern struct mem_info m68k_memory[NUM_MEMINFO];
#define TRUE (1)
#define FALSE (0)
@@ -191,14 +185,14 @@ z2_open( struct inode *inode, struct file *filp )
int index = device - Z2MINOR_MEMLIST1 + 1;
unsigned long size, paddr, vaddr;
- if (index >= num_memory) {
+ if (index >= m68k_realnum_memory) {
printk( KERN_ERR DEVICE_NAME
": no such entry in z2ram_map\n" );
return -ENOMEM;
}
- paddr = memory[index].addr;
- size = memory[index].size & ~(Z2RAM_CHUNKSIZE-1);
+ paddr = m68k_memory[index].addr;
+ size = m68k_memory[index].size & ~(Z2RAM_CHUNKSIZE-1);
#ifdef __powerpc__
/* FIXME: ioremap doesn't build correct memory tables. */
@@ -212,8 +206,7 @@ z2_open( struct inode *inode, struct file *filp )
_PAGE_WRITETHRU);
#else
- vaddr = kernel_map (paddr, size, KERNELMAP_FULL_CACHING,
- NULL);
+ vaddr = (unsigned long)ioremap(paddr, size);
#endif
z2ram_map =
kmalloc((size/Z2RAM_CHUNKSIZE)*sizeof(z2ram_map[0]),
@@ -316,9 +309,7 @@ z2_open( struct inode *inode, struct file *filp )
blk_size[ MAJOR_NR ] = z2_sizes;
}
-#if defined(MODULE)
MOD_INC_USE_COUNT;
-#endif
return 0;
}
@@ -331,9 +322,11 @@ z2_release( struct inode *inode, struct file *filp )
sync_dev( inode->i_rdev );
-#if defined(MODULE)
+ /*
+ * FIXME: unmap memory
+ */
+
MOD_DEC_USE_COUNT;
-#endif
return 0;
}
@@ -356,8 +349,8 @@ static struct file_operations z2_fops =
NULL, /* revalidate */
};
-__initfunc(int
-z2_init( void ))
+int __init
+z2_init( void )
{
if ( !MACH_IS_AMIGA )